xuhy
昨天 185b90fbbd29bcf520456196d758079e60b325eb
川易充h5接口
10个文件已添加
8个文件已修改
1248 ■■■■■ 已修改文件
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/AppAliPaymentFallbackFactory.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/H5AliPaymentFallbackFactory.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/AppAliPaymentClient.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/H5AliPaymentClient.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/AliPaymentReq.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-payment/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderInfo.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/config/AliH5Properties.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/AppPayUtil.java 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/H5PayUtil.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/ali/v2/util/Md5Util.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/AppAliPayController.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/H5AliPayController.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java
@@ -143,6 +143,11 @@
                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
@@ -175,6 +175,17 @@
                                  @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.AppAliPaymentFallbackFactory
com.ruoyi.payment.api.factory.H5AliPaymentFallbackFactory
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
@@ -853,6 +853,16 @@
                                         @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);
                }
            }
        }
    }
@@ -1033,6 +1111,23 @@
                dto.setRefundAmount(money.toString());
                dto.setRefundReason("充电完成退款");
                RefundResp resp = aliPaymentClient.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);
                }
            }
            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 {
@@ -2626,6 +2721,18 @@
                        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();
        }
    }
}