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()); 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 ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/AppAliPaymentFallbackFactory.java
New file @@ -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()); } }; } } ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/H5AliPaymentFallbackFactory.java
New file @@ -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()); } }; } } ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/AppAliPaymentClient.java
New file @@ -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); } ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/H5AliPaymentClient.java
New file @@ -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); } 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() { 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 com.ruoyi.payment.api.factory.AliPaymentFallbackFactory com.ruoyi.payment.api.factory.AppAliPaymentFallbackFactory com.ruoyi.payment.api.factory.H5AliPaymentFallbackFactory 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); } /** * 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; } 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; } 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(); } ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/config/AliH5Properties.java
New file @@ -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"; } ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/AppPayUtil.java
New file @@ -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; } } ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/H5PayUtil.java
New file @@ -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; } } ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/util/Md5Util.java
New file @@ -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]; } } ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/AppAliPayController.java
New file @@ -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(); } } } ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/H5AliPayController.java
New file @@ -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(); } } }