From 185b90fbbd29bcf520456196d758079e60b325eb Mon Sep 17 00:00:00 2001 From: xuhy <3313886187@qq.com> Date: 星期一, 16 六月 2025 09:49:09 +0800 Subject: [PATCH] 川易充h5接口 --- ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 154 +++++++ ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/AliPaymentReq.java | 4 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderInfo.java | 2 ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/AppPayUtil.java | 253 ++++++++++++ ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/AppAliPaymentFallbackFactory.java | 53 ++ ruoyi-api/ruoyi-api-payment/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports | 4 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java | 5 ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/H5PayUtil.java | 254 ++++++++++++ ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/AppAliPayController.java | 118 +++++ ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java | 7 ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/config/AliH5Properties.java | 56 ++ ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/AppAliPaymentClient.java | 55 ++ ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java | 13 ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/util/Md5Util.java | 48 ++ ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/H5AliPaymentFallbackFactory.java | 51 ++ ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java | 12 ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/H5AliPaymentClient.java | 54 ++ ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/H5AliPayController.java | 117 +++++ 18 files changed, 1,253 insertions(+), 7 deletions(-) diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java index cd782a1..1bb738f 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java +++ b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java @@ -142,7 +142,12 @@ public void chargingOrderALICallback(String out_trade_no, String transaction_id, String attach) { log.error("充电支付成功回调通知失败:" + throwable.getMessage()); } - + + @Override + public void chargingOrderALIH5Callback(String out_trade_no, String transaction_id, String attach) { + log.error("充电支付宝H5支付成功回调通知失败:" + throwable.getMessage()); + } + @Override public void chargingOrderStartupFailureWxRefund(String out_refund_no, String refund_id, String tradeState, String success_time) { log.error("远程启动失败后退款通知失败:" + throwable.getMessage()); diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java index 5570939..d47c9ae 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java +++ b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java @@ -174,7 +174,18 @@ void chargingOrderALICallback(@RequestParam("out_trade_no") String out_trade_no, @RequestParam("transaction_id") String transaction_id, @RequestParam("attach") String attach); - + + /** + * 充电支付成功回调通知 + * @param out_trade_no + * @param transaction_id + * @param attach + */ + @PostMapping("/t-charging-order/chargingOrderALIH5Callback") + void chargingOrderALIH5Callback(@RequestParam("out_trade_no") String out_trade_no, + @RequestParam("transaction_id") String transaction_id, + @RequestParam("attach") String attach); + /** * 远程启动失败后退款回调 * @param out_refund_no diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/AppAliPaymentFallbackFactory.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/AppAliPaymentFallbackFactory.java new file mode 100644 index 0000000..daf6786 --- /dev/null +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/AppAliPaymentFallbackFactory.java @@ -0,0 +1,53 @@ +package com.ruoyi.payment.api.factory; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.payment.api.feignClient.AppAliPaymentClient; +import com.ruoyi.payment.api.model.RefundReq; +import com.ruoyi.payment.api.model.RefundResp; +import com.ruoyi.payment.api.vo.AliPaymentReq; +import com.ruoyi.payment.api.vo.AliQueryOrder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; + +import java.util.Map; + + +/** + * 充电订单服务降级处理 + * + * @author ruoyi + */ +@Component +public class AppAliPaymentFallbackFactory implements FallbackFactory<AppAliPaymentClient> +{ + private static final Logger log = LoggerFactory.getLogger(AppAliPaymentFallbackFactory.class); + + @Override + public AppAliPaymentClient create(Throwable throwable) { + log.error("支付宝App支付调用失败:{}", throwable.getMessage()); + return new AppAliPaymentClient() { + + @Override + public R<Map<String, String>> payment(AliPaymentReq req) { + return R.fail("调起支付宝App支付失败:" + throwable.getMessage()); + } + + @Override + public R<AliQueryOrder> query(String outTradeNo) { + return R.fail("查询App支付订单失败:" + throwable.getMessage()); + } + + @Override + public void close(String outTradeNo) { + R.fail("关闭App支付订单失败:" + throwable.getMessage()); + } + + @Override + public R<RefundResp> refund(RefundReq dto) { + return R.fail("App支付宝退款失败:" + throwable.getMessage()); + } + }; + } +} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/H5AliPaymentFallbackFactory.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/H5AliPaymentFallbackFactory.java new file mode 100644 index 0000000..1734664 --- /dev/null +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/H5AliPaymentFallbackFactory.java @@ -0,0 +1,51 @@ +package com.ruoyi.payment.api.factory; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.payment.api.feignClient.H5AliPaymentClient; +import com.ruoyi.payment.api.model.RefundReq; +import com.ruoyi.payment.api.model.RefundResp; +import com.ruoyi.payment.api.vo.AliPaymentReq; +import com.ruoyi.payment.api.vo.AliQueryOrder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; + + +/** + * 充电订单服务降级处理 + * + * @author ruoyi + */ +@Component +public class H5AliPaymentFallbackFactory implements FallbackFactory<H5AliPaymentClient> +{ + private static final Logger log = LoggerFactory.getLogger(H5AliPaymentFallbackFactory.class); + + @Override + public H5AliPaymentClient create(Throwable throwable) { + log.error("支付宝H5支付调用失败:{}", throwable.getMessage()); + return new H5AliPaymentClient() { + + @Override + public R<String> payment(AliPaymentReq req) { + return R.fail("调起支付宝H5支付失败:" + throwable.getMessage()); + } + + @Override + public R<AliQueryOrder> query(String outTradeNo) { + return R.fail("查询H5支付订单失败:" + throwable.getMessage()); + } + + @Override + public void close(String outTradeNo) { + R.fail("关闭H5支付订单失败:" + throwable.getMessage()); + } + + @Override + public R<RefundResp> refund(RefundReq dto) { + return R.fail("H5支付宝退款失败:" + throwable.getMessage()); + } + }; + } +} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/AppAliPaymentClient.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/AppAliPaymentClient.java new file mode 100644 index 0000000..1bcba9a --- /dev/null +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/AppAliPaymentClient.java @@ -0,0 +1,55 @@ +package com.ruoyi.payment.api.feignClient; + +import com.ruoyi.common.core.constant.ServiceNameConstants; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.payment.api.factory.AppAliPaymentFallbackFactory; +import com.ruoyi.payment.api.factory.WxPaymentFallbackFactory; +import com.ruoyi.payment.api.model.RefundReq; +import com.ruoyi.payment.api.model.RefundResp; +import com.ruoyi.payment.api.vo.AliPaymentReq; +import com.ruoyi.payment.api.vo.AliPaymentResp; +import com.ruoyi.payment.api.vo.AliQueryOrder; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.Map; + +/** + * @author zhibing.pu + * @Date 2024/8/24 14:39 + */ +@FeignClient(contextId = "AppAliPaymentClient", value = ServiceNameConstants.PAYMENT_SERVICE, fallbackFactory = AppAliPaymentFallbackFactory.class) +public interface AppAliPaymentClient { + + + /** + * 调起支付宝小程序支付 + * @param req + * @return + */ + @PostMapping("/aliApp/payment") + R<Map<String, String>> payment(@RequestBody AliPaymentReq req); + + + /** + * 查询支付订单 + * @param outTradeNo + * @return + */ + @PostMapping("/aliApp/query") + R<AliQueryOrder> query(@RequestParam("outTradeNo") String outTradeNo); + + /** + * 关闭订单 + * @param outTradeNo + */ + @PostMapping("/aliApp/close") + void close(@RequestParam("outTradeNo") String outTradeNo); + /** + * 后台退款 远程调用 + */ + @PostMapping("/aliApp/refund") + public R<RefundResp> refund(@RequestBody RefundReq dto); +} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/H5AliPaymentClient.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/H5AliPaymentClient.java new file mode 100644 index 0000000..2dbee03 --- /dev/null +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/H5AliPaymentClient.java @@ -0,0 +1,54 @@ +package com.ruoyi.payment.api.feignClient; + +import com.ruoyi.common.core.constant.ServiceNameConstants; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.payment.api.factory.AppAliPaymentFallbackFactory; +import com.ruoyi.payment.api.factory.H5AliPaymentFallbackFactory; +import com.ruoyi.payment.api.model.RefundReq; +import com.ruoyi.payment.api.model.RefundResp; +import com.ruoyi.payment.api.vo.AliPaymentReq; +import com.ruoyi.payment.api.vo.AliQueryOrder; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.Map; + +/** + * @author zhibing.pu + * @Date 2024/8/24 14:39 + */ +@FeignClient(contextId = "H5AliPaymentClient", value = ServiceNameConstants.PAYMENT_SERVICE, fallbackFactory = H5AliPaymentFallbackFactory.class) +public interface H5AliPaymentClient { + + + /** + * 调起支付宝小程序支付 + * @param req + * @return + */ + @PostMapping("/aliH5/payment") + R<String> payment(@RequestBody AliPaymentReq req); + + + /** + * 查询支付订单 + * @param outTradeNo + * @return + */ + @PostMapping("/aliH5/query") + R<AliQueryOrder> query(@RequestParam("outTradeNo") String outTradeNo); + + /** + * 关闭订单 + * @param outTradeNo + */ + @PostMapping("/aliH5/close") + void close(@RequestParam("outTradeNo") String outTradeNo); + /** + * 后台退款 远程调用 + */ + @PostMapping("/aliH5/refund") + public R<RefundResp> refund(@RequestBody RefundReq dto); +} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/AliPaymentReq.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/AliPaymentReq.java index 07c3b52..1ee1963 100644 --- a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/AliPaymentReq.java +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/AliPaymentReq.java @@ -46,6 +46,10 @@ */ private String notifyUrl; /** + * 支付回跳地址 + */ + private String returnUrl; + /** * 初始化默认数据 */ public AliPaymentReq() { diff --git a/ruoyi-api/ruoyi-api-payment/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-api/ruoyi-api-payment/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index ecbf4d6..1e04370 100644 --- a/ruoyi-api/ruoyi-api-payment/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/ruoyi-api/ruoyi-api-payment/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1,4 @@ com.ruoyi.payment.api.factory.WxPaymentFallbackFactory -com.ruoyi.payment.api.factory.AliPaymentFallbackFactory \ No newline at end of file +com.ruoyi.payment.api.factory.AliPaymentFallbackFactory +com.ruoyi.payment.api.factory.AppAliPaymentFallbackFactory +com.ruoyi.payment.api.factory.H5AliPaymentFallbackFactory \ No newline at end of file diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java index ce56a11..78cfdda 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java @@ -853,7 +853,17 @@ @RequestParam("attach") String attach) { chargingOrderService.chargingOrderCallback(2, out_trade_no, transaction_id, attach); } - + /** + * 支付宝H5支付成功后的回调 + */ + @ResponseBody + @PostMapping(value = "/chargingOrderALIH5Callback") + public void chargingOrderALIH5Callback(@RequestParam("out_trade_no") String out_trade_no, + @RequestParam("transaction_id") String transaction_id, + @RequestParam("attach") String attach) { + chargingOrderService.chargingOrderCallback(3, out_trade_no, transaction_id, attach); + } + /** * diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java index eddec93..990f5e7 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java @@ -21,6 +21,9 @@ private Long appUserCouponId; @ApiModelProperty("车辆id") private Long appUserCarId; - @ApiModelProperty("支付方式(1=微信,2=支付宝)") + @ApiModelProperty("支付方式(1=微信,2=支付宝 3=支付宝h5)") private Integer paymentType; + @ApiModelProperty("回跳地址") + private String returnUrl; + } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderInfo.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderInfo.java index 9c9175b..a9ae091 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderInfo.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderInfo.java @@ -56,6 +56,8 @@ private List<Map<String, Object>> power; @ApiModelProperty("是否可申诉(0=否,1=是)") private Integer actionable; + @ApiModelProperty("H5是否可申诉(0=否,1=是)") + private Integer isAppeal; @ApiModelProperty("充电枪id") private Integer chargingGunId; } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java index b8a3f75..8712488 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.account.api.feignClient.*; import com.ruoyi.account.api.model.*; @@ -59,6 +60,7 @@ import com.ruoyi.other.api.domain.TVip; import com.ruoyi.other.api.feignClient.*; import com.ruoyi.payment.api.feignClient.AliPaymentClient; +import com.ruoyi.payment.api.feignClient.H5AliPaymentClient; import com.ruoyi.payment.api.feignClient.WxPaymentClient; import com.ruoyi.payment.api.model.RefundReq; import com.ruoyi.payment.api.model.RefundResp; @@ -132,6 +134,8 @@ @Resource private AliPaymentClient aliPaymentClient; + @Resource + private H5AliPaymentClient h5AliPaymentClient; @Resource private AppCouponClient appCouponClient; @@ -216,6 +220,8 @@ @Resource private ITChargingOrderSummaryDataService chargingOrderSummaryDataService; + @Resource + private TOrderAppealService orderAppealService; @@ -346,6 +352,9 @@ myChargingOrderInfo.setPower(power); } myChargingOrderInfo.setActionable(myChargingOrderInfo.getEndTime() + 604800000L < System.currentTimeMillis() ? 0 : 1); + long count = orderAppealService.count(Wrappers.lambdaQuery(TOrderAppeal.class) + .eq(TOrderAppeal::getOrderId, id)); + myChargingOrderInfo.setIsAppeal(count>0?0:1); return myChargingOrderInfo; } @@ -418,6 +427,16 @@ } } } + if(3 == rechargePaymentType){ + AliQueryOrder data = h5AliPaymentClient.query(tChargingOrder.getCode()).getData(); + if(null != data){ + //支付失败,删除无效的订单 + String tradeStatus = data.getTradeStatus(); + if(null != tradeStatus && tradeStatus.equals("TRADE_CLOSED")){ + this.removeById(tChargingOrder.getId()); + } + } + } } //检查当前枪是否是正在使用中 @@ -456,6 +475,21 @@ if(trade_state.equals("WAIT_BUYER_PAY")){ //结束第三方支付,删除订单 aliPaymentClient.close(one.getCode()); + this.removeById(one.getId()); + } + } + } + if(3 == one.getRechargePaymentType()){ + AliQueryOrder data = h5AliPaymentClient.query(one.getCode()).getData(); + if(null != data){ + String trade_state = data.getTradeStatus(); + //支付失败,删除无效的订单 + if(trade_state.equals("TRADE_CLOSED")){ + this.removeById(one.getId()); + } + if(trade_state.equals("WAIT_BUYER_PAY")){ + //结束第三方支付,删除订单 + h5AliPaymentClient.close(one.getCode()); this.removeById(one.getId()); } } @@ -561,6 +595,20 @@ AliPaymentResp data = aliPaymentClient.payment(req).getData(); if(null != data){ return AjaxResult.success(data); + } + } + if(3 == addChargingOrder.getPaymentType()){ + AliPaymentReq req = new AliPaymentReq(); + req.setOutTradeNo(chargingOrder.getCode()); + req.setTotalAmount(addChargingOrder.getPaymentAmount().toString()); + req.setSubject("充电充值"); + req.setBuyerOpenId(appUser.getAliOpenid()); + req.setBody("充电充值"); + req.setNotifyUrl("/payment/aliH5/callBack"); + req.setReturnUrl(addChargingOrder.getReturnUrl()); + String data = h5AliPaymentClient.payment(req).getData(); + if(StringUtils.hasLength(data)){ + return AjaxResult.success("操作成功",data); } } throw new RuntimeException("无效的支付方式"); @@ -976,6 +1024,36 @@ chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null); } } + if(3 == rechargePaymentType){ + RefundReq dto = new RefundReq(); + dto.setOutTradeNo(chargingOrder.getCode()); + dto.setOutRequestNo(chargingOrderRefund.getCode()); + dto.setRefundAmount(rechargeAmount.toString()); + dto.setRefundReason("充电失败,取消充电订单"); + RefundResp resp = h5AliPaymentClient.refund(dto).getData(); + if(null != resp){ + chargingOrderRefundService.save(chargingOrderRefund); + //回退会员折扣次数 + if(chargingOrder.getVipDiscountAmount().compareTo(BigDecimal.ZERO) > 0){ + TAppUser appUser = appUserClient.getUserById(chargingOrder.getAppUserId()).getData(); + GetAppUserVipDetail getAppUserVipDetail = new GetAppUserVipDetail(); + getAppUserVipDetail.setAppUserId(chargingOrder.getAppUserId()); + getAppUserVipDetail.setVipId(appUser.getVipId()); + TAppUserVipDetail data = appUserVipDetailClient.getAppUserVipDetail(getAppUserVipDetail).getData(); + if(null != data){ + data.setChargeNum(data.getChargeNum() + 1); + appUserVipDetailClient.updateAppUserVipDetail(data); + } + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null); + } + } } } @@ -1043,7 +1121,24 @@ chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null); } } - + if(3 == rechargePaymentType){ + RefundReq dto = new RefundReq(); + dto.setOutTradeNo(chargingOrder.getCode()); + dto.setOutRequestNo(chargingOrderRefund.getCode()); + dto.setRefundAmount(money.toString()); + dto.setRefundReason("充电完成退款"); + RefundResp resp = h5AliPaymentClient.refund(dto).getData(); + if(null != resp){ + chargingOrderRefundService.save(chargingOrderRefund); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null); + } + } + } } @@ -2626,7 +2721,19 @@ this.chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null); } } - + if(3 == rechargePaymentType){ + RefundReq dto = new RefundReq(); + dto.setOutTradeNo(chargingOrder.getCode()); + dto.setOutRequestNo(chargingOrderRefund.getRefundCode()); + dto.setRefundAmount(refundAmount.toString()); + dto.setRefundReason("充电完成退款"); + RefundResp resp = h5AliPaymentClient.refund(dto).getData(); + if(null != resp){ + chargingOrderRefundService.save(chargingOrderRefund); + this.chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null); + } + } + } } @@ -2827,6 +2934,21 @@ } } + if(3 == tChargingOrder.getRechargePaymentType()){ + RefundReq dto = new RefundReq(); + dto.setOutTradeNo(tChargingOrder.getCode()); + dto.setOutRequestNo(tChargingOrder.getCode()); + dto.setRefundAmount(payOrderQueryDto.getRefundAmount().toString()); + dto.setRefundReason("取消订单"); + RefundResp resp = h5AliPaymentClient.refund(dto).getData(); + if(null != resp){ + chargingOrderRefund.setRefundStatus(2); + chargingOrderRefund.setRefundAmount((tChargingOrder.getRefundAmount()==null? BigDecimal.valueOf(0) :tChargingOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount())); + this.baseMapper.updateById(tChargingOrder); + chargingOrderRefundService.save(chargingOrderRefund); + + } + } } if (payOrderQueryDto.getType()==2){ TShoppingOrder tChargingOrder = shoppingOrderService.getById(payOrderQueryDto.getOrderId()); @@ -2894,6 +3016,20 @@ shoppingOrderRefundService.save(chargingOrderRefund); } } + if(3 == tChargingOrder.getPaymentType()){ + RefundReq dto = new RefundReq(); + dto.setOutTradeNo(tChargingOrder.getCode()); + dto.setOutRequestNo(tChargingOrder.getCode()); + dto.setRefundAmount(payOrderQueryDto.getRefundAmount().toString()); + dto.setRefundReason("取消订单"); + RefundResp resp = h5AliPaymentClient.refund(dto).getData(); + if(null != resp){ + tChargingOrder.setRefundStatus(2); + tChargingOrder.setRefundAmount((tChargingOrder.getRefundAmount()==null? BigDecimal.valueOf(0) :tChargingOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount())); + shoppingOrderService.updateById(tChargingOrder); + shoppingOrderRefundService.save(chargingOrderRefund); + } + } } @@ -2959,6 +3095,20 @@ vipOrderRefundService.save(chargingOrderRefund); } } + if(3 == tChargingOrder.getPaymentType()){ + RefundReq dto = new RefundReq(); + dto.setOutTradeNo(tChargingOrder.getCode()); + dto.setOutRequestNo(tChargingOrder.getCode()); + dto.setRefundAmount(payOrderQueryDto.getRefundAmount().toString()); + dto.setRefundReason("取消订单"); + RefundResp resp = h5AliPaymentClient.refund(dto).getData(); + if(null != resp){ + tChargingOrder.setRefundStatus(2); + tChargingOrder.setRefundAmount((tChargingOrder.getRefundAmount()==null? BigDecimal.valueOf(0) :tChargingOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount())); + vipOrderService.updateById(tChargingOrder); + vipOrderRefundService.save(chargingOrderRefund); + } + } } return R.ok(); } diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/config/AliH5Properties.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/config/AliH5Properties.java new file mode 100644 index 0000000..4f6b862 --- /dev/null +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/config/AliH5Properties.java @@ -0,0 +1,56 @@ +package com.ruoyi.payment.ali.config; + + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +/** + * @author zhibing.pu + * @Date 2024/8/23 16:08 + */ +@Data +@Component +@Configuration +@ConfigurationProperties(prefix = "payment.alih5") +public class AliH5Properties { + /** + * appid + */ + private String appId; + /** + * 加签方式 + */ + private String signType; + /** + * 开发者私钥,由开发者自己生成 + */ + private String privateKey; + /** + * 支付宝公钥 + */ + private String alipayPublicKey; + /** + * 应用公钥证书文件本地路径 + */ + private String appCertPath; + /** + * 支付宝公钥证书文件本地路径 + */ + private String alipayPublicCertPath; + /** + * 支付宝根证书文件本地路径 + */ + private String rootCertPath; + /** + * 回调地址 + */ + private String notifyUrl; + /** + * V2接口地址 + */ + private String v2Path = "https://openapi.alipay.com/gateway.do"; + + +} diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/AppPayUtil.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/AppPayUtil.java new file mode 100644 index 0000000..f948f39 --- /dev/null +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/AppPayUtil.java @@ -0,0 +1,253 @@ +package com.ruoyi.payment.ali.v2; + +import com.alibaba.fastjson.JSONObject; +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayClient; +import com.alipay.api.AlipayConfig; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.domain.AlipayTradeAppPayModel; +import com.alipay.api.domain.AlipayTradeCloseModel; +import com.alipay.api.request.AlipayTradeAppPayRequest; +import com.alipay.api.request.AlipayTradeCloseRequest; +import com.alipay.api.request.AlipayTradeQueryRequest; +import com.alipay.api.request.AlipayTradeRefundRequest; +import com.alipay.api.response.AlipayTradeAppPayResponse; +import com.alipay.api.response.AlipayTradeCloseResponse; +import com.alipay.api.response.AlipayTradeQueryResponse; +import com.alipay.api.response.AlipayTradeRefundResponse; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + + +/** + * 第三方支付工具类 + */ +@Component +public class AppPayUtil { + + private static Logger log = LoggerFactory.getLogger(AppletPayUtil.class); + + private String aliAppid = "2021004172608506";//支付宝appid + + private String appPrivateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCREjc1/sU4fdzCJrtNBhaxIZb17G/9CoxDRCyHqy15TecDHl3tMt+sTpzIv1mWRUUIDtNvgBUMMv9gPfDbfl/T5Lk3MyM8sQocGBTQRTzcQzNL4fLjBT6LF6F9WSe65wG8OEtaI2IwFlKDbB7No2EkVKjWcAEdYkPu50WP6aEzXGj6CkO3CLRlUm2TXPngun8krVsB8zYkxpVA86mcB5DOXW9/1+XnXQ0i4c4k1XeDx25ycXyJGftDwBdV7Y9VA0GavUAXMZV2afRjObRcfQ554mCj4L52M/y+AC02io/+G2k+cq/yM+zr/bGp1A00gqFWI7HNLHFzoR7RdjCZXSQvAgMBAAECggEAP0r0PaGPCEuZcjeVxlAevF9MTrU+Uuc0NPDcgMCFUYRUgr7P+foVLkcKDme1vWMxcAeP5fi6thzV4HaFzC3Bv1/uExBDkmonYAR9qDRdDjhfe/7zimqyU9sWgOrR87BvyF/DOGtxnktO6rnUYqGic0hgdVZeliRWQTgz2Er1IsPJMEg/mrBDvPXeoSh+cppayYL3d7W8QVP650Eraxim0CfdFdiV0Fb5OMq/X5oPr93TdRbMoE8TMid9i+XlcmKe9pMjwat/CGK8auRpYOm0W3Ml+ybf3q2O+p/TTTSZfBYlLVb7fDdPxmZeDU/9u04k75DQR3taAQnYVvAJp3LwaQKBgQDMhpkAKR7GcI9AxpKDZY59Sg0SR68qrjYJqDtexr177wXZMxqh5a2S08fk3wLk8z5TAyucSg3kuX79wEeTMFlEBHERko/9bIVsT6U+lRY4AiXfQK1phIvRBiODQ9yBRPyEWBqkdZa0PaD4cbx0BMWe1GJE9zgoGNkOmZOa6mDrlQKBgQC1lQNfcbrr0r5coL+vx/BSSoaiHFZ4ijcCxWMPdjtxnKAfxTncq0C2UxzPgtpXYmLPrpsaulYE9nmUZIblbSPQbyTmoBIVx20Izzt/jY3YOJ7UnTgDoC24aq/RV4n/I2q3flnBqmA/+wcLwMEJvnQ+oWYIJ2e5q2XXybiWtXP/swKBgDgqGif2ItJhpKUoIqHcqKV1SWOktdClqIc8YJllQDGhcNy1cPHWjbTNXY5XQ4c12P6Y10gC+g++dMYgIEemNk08XwRxWANC4tzcfkdST5iv1lCZhUV9tZt/8Q6h+xKwrBt3ylExTWJPrj2rlhHSIaa9MgM4VH6GXEzrFaKsDFOFAoGAe33zhEbZxCZYdrCQjSDiTWUH+VpiaKo/TXAmtc5IETVfJRxCBNSnNxiBQJOSoNl1sB7kt6HAfLGP8B8KKyA1ujzMkNiOVCeD/PjLUy1XKZUgWCLwhG68iW5tUmdBn7Zbjp2st2yC9yBnI1QdNN5FOo8T0DnUbk6l/cLf+gc/88cCgYEAjYJFvXDhGKlx1xI/eLPSKNUIab5i3K57A9B8CejFIHxdV4jDf9OGj/kf/WrNcFfBGqgpqNXgtpBmtplPAQmcvNJVVoI0wfXDQHuO0vZ600Rku2Bv/uldObwq/xk46rTHtQjkIzBI25IcRh5gvaoyk+Yq+zkLZosuNyXYwVSxVJs=";//支付宝开发者应用私钥 + + private String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkRI3Nf7FOH3cwia7TQYWsSGW9exv/QqMQ0Qsh6steU3nAx5d7TLfrE6cyL9ZlkVFCA7Tb4AVDDL/YD3w235f0+S5NzMjPLEKHBgU0EU83EMzS+Hy4wU+ixehfVknuucBvDhLWiNiMBZSg2wezaNhJFSo1nABHWJD7udFj+mhM1xo+gpDtwi0ZVJtk1z54Lp/JK1bAfM2JMaVQPOpnAeQzl1vf9fl510NIuHOJNV3g8ducnF8iRn7Q8AXVe2PVQNBmr1AFzGVdmn0Yzm0XH0OeeJgo+C+djP8vgAtNoqP/htpPnKv8jPs6/2xqdQNNIKhViOxzSxxc6Ee0XYwmV0kLwIDAQAB";//支付宝应用公钥 + + private String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkoPidM7vHL/74FhOWARjkMDZN0GktpVEQaYz6qpIjTuKLcQsR74CUv9LoiGD9uquYAI52TdmxzMWbuMEvrdVIT6pWyJuCvScX2U5Zwn9Bk8bE5RmTobUrU3LFudMYIGFU3qUHqnTJFQxLsSUibTtxbov1bpCQNwk3/2RdYOpJHKDjkXzNcjJrkuNcGcuzNW/3+L5CMaVm0dxqxx0dhJ4H0xvpMw2uvdxdLXN/KoYszfps4j61x0KFwkulvD1WHzR1f/ot9NU8FZe+dkNm5cXb9HbwQIbfARyB5bd0EYHSr4fJIUJx1GnjpfT6/traxEoyOcI6diJa4b2hZpR3WvxTQIDAQAB";//支付宝支付公钥 + + private String callbackPath = "https://online.daowepark.com:443/activity";//支付回调网关地址 + + /** + * 支付宝支付 + */ + public Map<String, String> alipay(String body, String subject, String passbackParams, String outTradeNo, String amount, String notifyUrl) { + //实例化客户端 + AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipay_public_key, "RSA2"); + //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay + AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); + //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。 + AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); + model.setBody(body);//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 + model.setSubject(subject);//商品的标题/交易标题/订单标题/订单关键字等。 + model.setOutTradeNo(outTradeNo);//商户网站唯一订单号 + model.setTimeoutExpress("30m"); + model.setTotalAmount(new BigDecimal(amount).setScale(2, RoundingMode.HALF_UP).toString());//付款金额 + model.setProductCode("QUICK_MSECURITY_PAY"); + model.setPassbackParams(passbackParams);//自定义参数 + request.setBizModel(model); + request.setNotifyUrl(callbackPath + notifyUrl); + try { + //这里和普通的接口调用不同,使用的是sdkExecute + AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); + Map<String, String> map = new HashMap<>(); + map.put("orderString", response.getBody()); + map.put("returnId", passbackParams); + System.out.println(map);//就是orderString 可以直接给客户端请求,无需再做处理。 + return map; + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + public boolean close(String outTradeNo){ + try { + // 初始化SDK + AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig()); + // 构造请求参数以调用接口 + AlipayTradeCloseRequest request = new AlipayTradeCloseRequest(); + AlipayTradeCloseModel model = new AlipayTradeCloseModel(); + // 设置订单支付时传入的商户订单号 + model.setOutTradeNo(outTradeNo); + request.setBizModel(model); + AlipayTradeCloseResponse response = alipayClient.execute(request); + log.info("-----关闭支付宝支付订单-----"); + log.info("请求参数:{}", outTradeNo); + log.info("返回结果:{}", response.getBody()); + if(response.isSuccess()){ + return true; + } + }catch (Exception e){ + e.printStackTrace(); + } + return false; + } + + private AlipayConfig getAlipayConfig() { + AlipayConfig alipayConfig = new AlipayConfig(); + alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do"); + alipayConfig.setAppId(aliAppid); + alipayConfig.setPrivateKey(appPrivateKey); + alipayConfig.setFormat("json"); + alipayConfig.setAlipayPublicKey(alipayPublicKey); + alipayConfig.setCharset("UTF-8"); + alipayConfig.setSignType("RSA2"); + return alipayConfig; + } + + + /** + * 支付成功后的回调处理逻辑 + * + * @param request + */ + public Map<String, String> alipayCallback(HttpServletRequest request) { + //获取支付宝POST过来反馈信息 + Map<String, String> params = new HashMap<String, String>(); + Map requestParams = request.getParameterMap(); + for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) { + String name = (String) iter.next(); + String[] values = (String[]) requestParams.get(name); + String valueStr = ""; + for (int i = 0; i < values.length; i++) { + valueStr = (i == values.length - 1) ? valueStr + values[i] + : valueStr + values[i] + "_"; + } + //乱码解决,这段代码在出现乱码时使用。 + //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); + params.put(name, valueStr); + } + //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。 + Map<String, String> map = new HashMap<>(); + System.err.println("返回码"+params); + if (params.get("trade_status").equals("TRADE_SUCCESS")){ + String out_trade_no = params.get("out_trade_no"); + String subject = params.get("subject"); + String total_amount = params.get("total_amount"); + String trade_no = params.get("trade_no"); + String passback_params = params.get("passback_params"); + map.put("out_trade_no", out_trade_no);//商家订单号 + map.put("subject", subject); + map.put("total_amount", total_amount); + map.put("trade_no", trade_no);//支付宝交易号 + map.put("passback_params", passback_params);//回传参数 + System.err.println("回调map"); + return map; + }else{ + return null; + } + } + + + /** + * 支付宝查询订单支付状态 + * + * @param out_trade_no + * @return + * @throws Exception + */ + public AlipayTradeQueryResponse queryAliOrder(String out_trade_no) { + try { + AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipay_public_key, "RSA2"); + AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); + request.setBizContent("{" + + " \"out_trade_no\":\"" + out_trade_no + "\"" + + "}"); + AlipayTradeQueryResponse response = alipayClient.execute(request); + if (response.isSuccess()) { + String tradeStatus = response.getTradeStatus();//交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款) + return response; + } else { + return response; + } + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 支付宝扫码收款 + * + * @param data + * @return + */ + public Object aliScanQRCodePay(String data) { + return null; + } + + + + /** + * 支付宝退款 + * + * @param trade_no 支付宝交易号 + * @param refund_amount 退款金额 + * @return + * @throws AlipayApiException + */ + public Map<String, String> aliRefund(String trade_no, String refund_amount) { + try { + AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipay_public_key, "RSA2"); + AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("trade_no", trade_no); + jsonObject.put("refund_amount", refund_amount); + request.setBizContent(jsonObject.toJSONString()); + AlipayTradeRefundResponse response = alipayClient.execute(request); + Map<String, String> map = new HashMap<>(); + if (response.isSuccess()) { + System.out.println("调用成功"); + String outTradeNo = response.getOutTradeNo(); + map.put("code", response.getCode());//10000 + map.put("trade_no", response.getTradeNo());//支付宝交易号 + map.put("out_trade_no", outTradeNo);//商户订单号 + map.put("refund_fee", response.getRefundFee()); + map.put("msg", response.getMsg()); + } else { + System.out.println("调用失败"); + map.put("code", response.getCode()); + map.put("msg", response.getSubMsg()); + } + return map; + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + public static Map<String, String> xmlToMap(Element tmpElement, Map<String, String> respMap) { + if (tmpElement.isTextOnly()) { + respMap.put(tmpElement.getName(), tmpElement.getText()); + return respMap; + } + + @SuppressWarnings("unchecked") + Iterator<Element> eItor = tmpElement.elementIterator(); + while (eItor.hasNext()) { + Element element = eItor.next(); + xmlToMap(element, respMap); + } + return respMap; + } +} diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/H5PayUtil.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/H5PayUtil.java new file mode 100644 index 0000000..c68bc4e --- /dev/null +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/H5PayUtil.java @@ -0,0 +1,254 @@ +package com.ruoyi.payment.ali.v2; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alipay.api.*; +import com.alipay.api.diagnosis.DiagnosisUtils; +import com.alipay.api.domain.*; +import com.alipay.api.request.*; +import com.alipay.api.response.*; +import com.ruoyi.payment.ali.config.AliH5Properties; +import com.ruoyi.payment.ali.config.AliProperties; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.http.HttpServletRequest; +import java.io.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import static com.ruoyi.payment.ali.v2.util.Md5Util.byteArrayToHexString; + + +/** + * 第三方支付工具类 + */ +@Component +public class H5PayUtil { + private static Logger log = LoggerFactory.getLogger(AppletPayUtil.class); + + @Autowired + private AliH5Properties aliH5Properties; + + private String aliAppid = "2021004172608506";//支付宝appid + private String appPrivateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCREjc1/sU4fdzCJrtNBhaxIZb17G/9CoxDRCyHqy15TecDHl3tMt+sTpzIv1mWRUUIDtNvgBUMMv9gPfDbfl/T5Lk3MyM8sQocGBTQRTzcQzNL4fLjBT6LF6F9WSe65wG8OEtaI2IwFlKDbB7No2EkVKjWcAEdYkPu50WP6aEzXGj6CkO3CLRlUm2TXPngun8krVsB8zYkxpVA86mcB5DOXW9/1+XnXQ0i4c4k1XeDx25ycXyJGftDwBdV7Y9VA0GavUAXMZV2afRjObRcfQ554mCj4L52M/y+AC02io/+G2k+cq/yM+zr/bGp1A00gqFWI7HNLHFzoR7RdjCZXSQvAgMBAAECggEAP0r0PaGPCEuZcjeVxlAevF9MTrU+Uuc0NPDcgMCFUYRUgr7P+foVLkcKDme1vWMxcAeP5fi6thzV4HaFzC3Bv1/uExBDkmonYAR9qDRdDjhfe/7zimqyU9sWgOrR87BvyF/DOGtxnktO6rnUYqGic0hgdVZeliRWQTgz2Er1IsPJMEg/mrBDvPXeoSh+cppayYL3d7W8QVP650Eraxim0CfdFdiV0Fb5OMq/X5oPr93TdRbMoE8TMid9i+XlcmKe9pMjwat/CGK8auRpYOm0W3Ml+ybf3q2O+p/TTTSZfBYlLVb7fDdPxmZeDU/9u04k75DQR3taAQnYVvAJp3LwaQKBgQDMhpkAKR7GcI9AxpKDZY59Sg0SR68qrjYJqDtexr177wXZMxqh5a2S08fk3wLk8z5TAyucSg3kuX79wEeTMFlEBHERko/9bIVsT6U+lRY4AiXfQK1phIvRBiODQ9yBRPyEWBqkdZa0PaD4cbx0BMWe1GJE9zgoGNkOmZOa6mDrlQKBgQC1lQNfcbrr0r5coL+vx/BSSoaiHFZ4ijcCxWMPdjtxnKAfxTncq0C2UxzPgtpXYmLPrpsaulYE9nmUZIblbSPQbyTmoBIVx20Izzt/jY3YOJ7UnTgDoC24aq/RV4n/I2q3flnBqmA/+wcLwMEJvnQ+oWYIJ2e5q2XXybiWtXP/swKBgDgqGif2ItJhpKUoIqHcqKV1SWOktdClqIc8YJllQDGhcNy1cPHWjbTNXY5XQ4c12P6Y10gC+g++dMYgIEemNk08XwRxWANC4tzcfkdST5iv1lCZhUV9tZt/8Q6h+xKwrBt3ylExTWJPrj2rlhHSIaa9MgM4VH6GXEzrFaKsDFOFAoGAe33zhEbZxCZYdrCQjSDiTWUH+VpiaKo/TXAmtc5IETVfJRxCBNSnNxiBQJOSoNl1sB7kt6HAfLGP8B8KKyA1ujzMkNiOVCeD/PjLUy1XKZUgWCLwhG68iW5tUmdBn7Zbjp2st2yC9yBnI1QdNN5FOo8T0DnUbk6l/cLf+gc/88cCgYEAjYJFvXDhGKlx1xI/eLPSKNUIab5i3K57A9B8CejFIHxdV4jDf9OGj/kf/WrNcFfBGqgpqNXgtpBmtplPAQmcvNJVVoI0wfXDQHuO0vZ600Rku2Bv/uldObwq/xk46rTHtQjkIzBI25IcRh5gvaoyk+Yq+zkLZosuNyXYwVSxVJs=";//支付宝开发者应用私钥 + private String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkRI3Nf7FOH3cwia7TQYWsSGW9exv/QqMQ0Qsh6steU3nAx5d7TLfrE6cyL9ZlkVFCA7Tb4AVDDL/YD3w235f0+S5NzMjPLEKHBgU0EU83EMzS+Hy4wU+ixehfVknuucBvDhLWiNiMBZSg2wezaNhJFSo1nABHWJD7udFj+mhM1xo+gpDtwi0ZVJtk1z54Lp/JK1bAfM2JMaVQPOpnAeQzl1vf9fl510NIuHOJNV3g8ducnF8iRn7Q8AXVe2PVQNBmr1AFzGVdmn0Yzm0XH0OeeJgo+C+djP8vgAtNoqP/htpPnKv8jPs6/2xqdQNNIKhViOxzSxxc6Ee0XYwmV0kLwIDAQAB";//支付宝应用公钥 + private String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkoPidM7vHL/74FhOWARjkMDZN0GktpVEQaYz6qpIjTuKLcQsR74CUv9LoiGD9uquYAI52TdmxzMWbuMEvrdVIT6pWyJuCvScX2U5Zwn9Bk8bE5RmTobUrU3LFudMYIGFU3qUHqnTJFQxLsSUibTtxbov1bpCQNwk3/2RdYOpJHKDjkXzNcjJrkuNcGcuzNW/3+L5CMaVm0dxqxx0dhJ4H0xvpMw2uvdxdLXN/KoYszfps4j61x0KFwkulvD1WHzR1f/ot9NU8FZe+dkNm5cXb9HbwQIbfARyB5bd0EYHSr4fJIUJx1GnjpfT6/traxEoyOcI6diJa4b2hZpR3WvxTQIDAQAB";//支付宝支付公钥 + private String callbackPath = "http://221.182.45.100:9000";//支付回调网关地址 + private AlipayConfig getAlipayConfig() { + AlipayConfig alipayConfig = new AlipayConfig(); + alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do"); + alipayConfig.setAppId(aliH5Properties.getAppId()); + alipayConfig.setPrivateKey(aliH5Properties.getPrivateKey()); + alipayConfig.setFormat("json"); + alipayConfig.setAlipayPublicKey(aliH5Properties.getAlipayPublicKey()); + alipayConfig.setCharset("UTF-8"); + alipayConfig.setSignType("RSA2"); + return alipayConfig; + } + /** + * 支付宝支付 + */ + public String alipay(String body, String subject, String passbackParams, String outTradeNo, String amount, String notifyUrl,String returnUrl) { + try { + //实例化客户端 + AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig()); + //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay + AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest(); + //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。 + AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); + model.setBody(body);//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 + model.setSubject(subject);//商品的标题/交易标题/订单标题/订单关键字等。 + model.setOutTradeNo(outTradeNo);//商户网站唯一订单号 + model.setTimeoutExpress("30m"); + model.setTotalAmount(new BigDecimal(amount).setScale(2, RoundingMode.HALF_UP).toString());//付款金额 + model.setProductCode("QUICK_WAP_WAY"); + model.setPassbackParams(passbackParams);//自定义参数 + request.setBizModel(model); + request.setNotifyUrl(aliH5Properties.getNotifyUrl() + notifyUrl); + request.setReturnUrl(returnUrl); + //这里和普通的接口调用不同,使用的是sdkExecute + AlipayTradeWapPayResponse response = alipayClient.pageExecute(request, "POST"); + // 如果需要返回GET请求,请使用 + // AlipayTradeWapPayResponse response = alipayClient.pageExecute(request, "GET"); + String pageRedirectionData = response.getBody(); + log.info("-----支付宝H5支付-------:{}",pageRedirectionData); + if (response.isSuccess()) { + log.info("支付宝H5支付成功"); + return pageRedirectionData; + }else { + log.info("支付宝H5支付失败"); + String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response); + return diagnosisUrl; + } + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + public boolean close(String outTradeNo){ + try { + // 初始化SDK + AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig()); + // 构造请求参数以调用接口 + AlipayTradeCloseRequest request = new AlipayTradeCloseRequest(); + AlipayTradeCloseModel model = new AlipayTradeCloseModel(); + // 设置订单支付时传入的商户订单号 + model.setOutTradeNo(outTradeNo); + request.setBizModel(model); + AlipayTradeCloseResponse response = alipayClient.execute(request); + log.info("-----关闭支付宝支付订单-----"); + log.info("请求参数:{}", outTradeNo); + log.info("返回结果:{}", response.getBody()); + if(response.isSuccess()){ + return true; + } + }catch (Exception e){ + e.printStackTrace(); + } + return false; + } + + /** + * 支付成功后的回调处理逻辑 + * + * @param request + */ + public Map<String, String> alipayCallback(HttpServletRequest request) { + //获取支付宝POST过来反馈信息 + Map<String, String> params = new HashMap<String, String>(); + Map requestParams = request.getParameterMap(); + for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) { + String name = (String) iter.next(); + String[] values = (String[]) requestParams.get(name); + String valueStr = ""; + for (int i = 0; i < values.length; i++) { + valueStr = (i == values.length - 1) ? valueStr + values[i] + : valueStr + values[i] + "_"; + } + //乱码解决,这段代码在出现乱码时使用。 + //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); + params.put(name, valueStr); + } + //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。 + //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type) + Map<String, String> map = new HashMap<>(); + System.err.println("返回码"+params); + if (params.get("trade_status").equals("TRADE_SUCCESS")){ + String out_trade_no = params.get("out_trade_no"); + String subject = params.get("subject"); + String total_amount = params.get("total_amount"); + String trade_no = params.get("trade_no"); + String passback_params = params.get("passback_params"); + map.put("out_trade_no", out_trade_no);//商家订单号 + map.put("subject", subject); + map.put("total_amount", total_amount); + map.put("trade_no", trade_no);//支付宝交易号 + map.put("passback_params", passback_params);//回传参数 + System.err.println("回调map"); + return map; + }else{ + return null; + } + } + + + /** + * 支付宝查询订单支付状态 + * + * @param out_trade_no + * @return + * @throws Exception + */ + public AlipayTradeQueryResponse queryAliOrder(String out_trade_no) { + try { + // 初始化SDK + AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig()); + AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); + AlipayTradeQueryModel model = new AlipayTradeQueryModel(); + // 设置订单支付时传入的商户订单号 + model.setOutTradeNo(out_trade_no); + request.setBizModel(model); + AlipayTradeQueryResponse response = alipayClient.execute(request); + if (response.isSuccess()) { + String tradeStatus = response.getTradeStatus();//交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款) + return response; + } else { + return response; + } + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 支付宝退款 + * + * @param trade_no 支付宝交易号 + * @param refund_amount 退款金额 + * @return + * @throws AlipayApiException + */ + public Map<String, String> aliRefund(String trade_no, String refund_amount) { + try { + // 初始化SDK + AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig()); + AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); + AlipayTradeRefundModel model = new AlipayTradeRefundModel(); + // 设置订单支付时传入的商户订单号 + model.setTradeNo(trade_no); + model.setRefundAmount(refund_amount); + model.setRefundReason("充电退款"); + request.setBizModel(model); + AlipayTradeRefundResponse response = alipayClient.execute(request); + Map<String, String> map = new HashMap<>(); + if (response.isSuccess()) { + log.info("调用成功"); + String outTradeNo = response.getOutTradeNo(); + map.put("code", response.getCode());//10000 + map.put("trade_no", response.getTradeNo());//支付宝交易号 + map.put("out_trade_no", outTradeNo);//商户订单号 + map.put("refund_fee", response.getRefundFee()); + map.put("msg", response.getMsg()); + } else { + log.error("调用失败"); + map.put("code", response.getCode()); + map.put("msg", response.getSubMsg()); + } + return map; + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + public static Map<String, String> xmlToMap(Element tmpElement, Map<String, String> respMap) { + if (tmpElement.isTextOnly()) { + respMap.put(tmpElement.getName(), tmpElement.getText()); + return respMap; + } + + @SuppressWarnings("unchecked") + Iterator<Element> eItor = tmpElement.elementIterator(); + while (eItor.hasNext()) { + Element element = eItor.next(); + xmlToMap(element, respMap); + } + return respMap; + } +} diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/util/Md5Util.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/util/Md5Util.java new file mode 100644 index 0000000..b948c99 --- /dev/null +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/util/Md5Util.java @@ -0,0 +1,48 @@ +package com.ruoyi.payment.ali.v2.util; + +import java.security.MessageDigest; + +public class Md5Util { + private static final String hexDigIts[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; + + /** + * MD5加密 + * + * @param origin 字符 + * @param charsetname 编码 + * @return + */ + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if (null == charsetname || "".equals(charsetname)) { + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + } else { + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + } catch (Exception e) { + } + return resultString; + } + + + public static String byteArrayToHexString(byte b[]) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++) { + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + public static String byteToHexString(byte b) { + int n = b; + if (n < 0) { + n += 256; + } + int d1 = n / 16; + int d2 = n % 16; + return hexDigIts[d1] + hexDigIts[d2]; + } +} diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/AppAliPayController.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/AppAliPayController.java new file mode 100644 index 0000000..7d95041 --- /dev/null +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/AppAliPayController.java @@ -0,0 +1,118 @@ +package com.ruoyi.payment.controller; + +import com.alipay.api.response.AlipayTradeQueryResponse; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.order.api.feignClient.ChargingOrderClient; +import com.ruoyi.order.api.feignClient.OrderClient; +import com.ruoyi.payment.ali.v2.AppPayUtil; +import com.ruoyi.payment.api.model.RefundReq; +import com.ruoyi.payment.api.model.RefundResp; +import com.ruoyi.payment.api.vo.AliPaymentReq; +import com.ruoyi.payment.api.vo.AliPaymentResp; +import com.ruoyi.payment.api.vo.AliQueryOrder; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import java.util.Map; + +/** + * @author zhibing.pu + * @Date 2024/8/24 14:29 + */ +@RestController +@RequestMapping("/aliApp") +public class AppAliPayController { + + @Resource + private AppPayUtil appPayUtil; + @Resource + private ChargingOrderClient chargingOrderClient; + + /** + * 调起支付宝小程序支付 + * @param req + * @return + */ + @ResponseBody + @PostMapping("/payment") + public R<Map<String, String>> payment(@RequestBody AliPaymentReq req){ + Map<String, String> alipay = appPayUtil.alipay(req.getBody(), req.getSubject(), req.getPassbackParams(), req.getOutTradeNo(), req.getTotalAmount(), req.getNotifyUrl()); + return R.ok(alipay); + } + + /** + * 查询订单 + * @param outTradeNo + * @return + */ + @ResponseBody + @PostMapping("/query") + public R<AliQueryOrder> query(@RequestParam("outTradeNo") String outTradeNo){ + AlipayTradeQueryResponse alipayTradeQueryResponse = appPayUtil.queryAliOrder(outTradeNo); + if(null != alipayTradeQueryResponse){ + AliQueryOrder aliQueryOrder = new AliQueryOrder(); + BeanUtils.copyProperties(alipayTradeQueryResponse, aliQueryOrder); + return R.ok(aliQueryOrder); + } + return R.ok(); + } + + /** + * 关闭订单 + * @param outTradeNo + */ + @ResponseBody + @PostMapping("/close") + public void close(@RequestParam("outTradeNo") String outTradeNo){ + boolean close = appPayUtil.close(outTradeNo); + if(!close){ + throw new RuntimeException("关闭支付宝订单失败"); + } + } + /** + * 后台退款 远程调用 + */ + @PostMapping("/refund") + public R<RefundResp> refund(@RequestBody RefundReq dto){ + Map<String, String> map = appPayUtil.aliRefund(dto.getOutTradeNo(), dto.getRefundAmount()); + RefundResp refundResp = new RefundResp(); + refundResp.setCode(map.get("code")); + refundResp.setMsg(map.get("msg")); + refundResp.setTradeNo(map.get("trade_no")); + refundResp.setOutTradeNo(map.get("out_trade_no")); + refundResp.setRefundFee(new Double(map.get("refund_fee"))); + return R.ok(refundResp); + } + + @ResponseBody + @PostMapping(value = "/callBack") + public void chargingOrderALICallback(HttpServletRequest request, HttpServletResponse response) { + try { +// Map<String, String> callback = appPayUtil.alipayCallback(request); +// if(null != callback){ +// String out_trade_no = callback.get("out_trade_no"); +// String attach = callback.get("subject"); +// String total_amount = callback.get("total_amount"); +// String transaction_id = callback.get("trade_no"); +// String substring = out_trade_no.substring(0, 2); +// switch (substring){ +// case "CD": +// chargingOrderClient.chargingOrderALIAppCallback(out_trade_no, transaction_id, attach); +// System.err.println("----充电支付回调"); +// break; +// } +// PrintWriter writer = response.getWriter(); +// writer.println("success"); +// writer.flush(); +// writer.close(); +// } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/H5AliPayController.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/H5AliPayController.java new file mode 100644 index 0000000..33b7ed7 --- /dev/null +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/H5AliPayController.java @@ -0,0 +1,117 @@ +package com.ruoyi.payment.controller; + +import com.alipay.api.response.AlipayTradeQueryResponse; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.order.api.feignClient.ChargingOrderClient; +import com.ruoyi.payment.ali.v2.AppPayUtil; +import com.ruoyi.payment.ali.v2.H5PayUtil; +import com.ruoyi.payment.api.model.RefundReq; +import com.ruoyi.payment.api.model.RefundResp; +import com.ruoyi.payment.api.vo.AliPaymentReq; +import com.ruoyi.payment.api.vo.AliQueryOrder; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import java.util.Map; + +/** + * @author zhibing.pu + * @Date 2024/8/24 14:29 + */ +@RestController +@RequestMapping("/aliH5") +public class H5AliPayController { + + @Resource + private H5PayUtil h5PayUtil; + @Resource + private ChargingOrderClient chargingOrderClient; + + /** + * 调起支付宝小程序支付 + * @param req + * @return + */ + @ResponseBody + @PostMapping("/payment") + public R<String> payment(@RequestBody AliPaymentReq req){ + String alipay = h5PayUtil.alipay(req.getBody(), req.getSubject(), req.getPassbackParams(), req.getOutTradeNo(), req.getTotalAmount(), req.getNotifyUrl(),req.getReturnUrl()); + return R.ok(alipay); + } + + /** + * 查询订单 + * @param outTradeNo + * @return + */ + @ResponseBody + @PostMapping("/query") + public R<AliQueryOrder> query(@RequestParam("outTradeNo") String outTradeNo){ + AlipayTradeQueryResponse alipayTradeQueryResponse = h5PayUtil.queryAliOrder(outTradeNo); + if(null != alipayTradeQueryResponse){ + AliQueryOrder aliQueryOrder = new AliQueryOrder(); + BeanUtils.copyProperties(alipayTradeQueryResponse, aliQueryOrder); + return R.ok(aliQueryOrder); + } + return R.ok(); + } + + /** + * 关闭订单 + * @param outTradeNo + */ + @ResponseBody + @PostMapping("/close") + public void close(@RequestParam("outTradeNo") String outTradeNo){ + boolean close = h5PayUtil.close(outTradeNo); + if(!close){ + throw new RuntimeException("关闭支付宝订单失败"); + } + } + /** + * 后台退款 远程调用 + */ + @PostMapping("/refund") + public R<RefundResp> refund(@RequestBody RefundReq dto){ + Map<String, String> map = h5PayUtil.aliRefund(dto.getOutTradeNo(), dto.getRefundAmount()); + RefundResp refundResp = new RefundResp(); + refundResp.setCode(map.get("code")); + refundResp.setMsg(map.get("msg")); + refundResp.setTradeNo(map.get("trade_no")); + refundResp.setOutTradeNo(map.get("out_trade_no")); + refundResp.setRefundFee(new Double(map.get("refund_fee"))); + return R.ok(refundResp); + } + + @ResponseBody + @PostMapping(value = "/callBack") + public void chargingOrderALICallback(HttpServletRequest request, HttpServletResponse response) { + try { + Map<String, String> callback = h5PayUtil.alipayCallback(request); + if(null != callback){ + String out_trade_no = callback.get("out_trade_no"); + String attach = callback.get("subject"); + String total_amount = callback.get("total_amount"); + String transaction_id = callback.get("trade_no"); + String substring = out_trade_no.substring(0, 2); + switch (substring){ + case "CD": + chargingOrderClient.chargingOrderALIH5Callback(out_trade_no, transaction_id, attach); + System.err.println("----充电支付回调"); + break; + } + PrintWriter writer = response.getWriter(); + writer.println("success"); + writer.flush(); + writer.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} -- Gitblit v1.7.1