java最新V3微信APP支付与支付宝支付

由于项目需要微信与支付宝支付,发现更新了v3版本,使用方式与之前不一样了。查看微信官方文档发现文档的说明并不是很详细,而网上的资料大部分都是要内置okhttp的,官方文档也是推荐,也许本人有强迫症吧,不想在加依赖,于是查看sdk源码,发现提供了一个AppServiceExtension 这个类,可以更加方便的使用。看完记得点个小星星谢谢大家。

下面代码可以直接复制粘贴使用,记得修改配置

微信APP支付官方文档
支付宝APP支付官方文档

首先引入sdk

<dependency>
  <groupId>com.github.wechatpay-apiv3</groupId>
  <artifactId>wechatpay-java</artifactId>
  <version>0.2.12</version>
</dependency>
<dependency>
  <groupId>com.alipay.sdk</groupId>
  <artifactId>alipay-sdk-java</artifactId>
  <version>4.39.86.ALL</version>
</dependency>

微信支付

新建 WxAppPay.java,内容如下

package com.zyq.pay.wx.app;

import cn.hutool.json.JSONUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.http.DefaultHttpClientBuilder;
import com.wechat.pay.java.core.http.HostName;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.app.AppService;
import com.wechat.pay.java.service.payments.app.AppServiceExtension;
import com.wechat.pay.java.service.payments.app.model.Amount;
import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
import com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.app.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.app.model.SceneInfo;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.zyq.enuns.ApiResponseCode;
import com.zyq.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

/** 微信app支付
 * author xiaochi
 * date 2024/6/4 13:59
 */
@Slf4j
public class WxAppPay {

    /** 单例
     * 初始化支付配置(注意:如果还有其他微信支付方式,记得抽离去继承,配置对象必须是单例)
     * @return
     */
    private static Config config = null;

    public Config getConfig(WxAppPayRequest request){
        if (config == null){
            config = new RSAAutoCertificateConfig.Builder()
                .merchantId(request.getMchId())
                .privateKeyFromPath(request.getPrivateKeyPath())
                .merchantSerialNumber(request.getMchSerialNo())
                .apiV3Key(request.getApiV3Key())
                .build();
        }
        return config;
    }

    public WxAppPayResponse pay(WxAppPayRequest request) {
        WxAppPayResponse payResponse = new WxAppPayResponse();
        try {
            log.info("微信APP支付参数:订单[{}],body:{}",request.getOutTradeNo(),JSONUtil.toJsonStr(request));
            Config config = getConfig(request);
            PrepayRequest prepayRequest = new PrepayRequest();
            Amount amount = new Amount();
            amount.setTotal(request.getTotalFee());
            prepayRequest.setAmount(amount);
            prepayRequest.setAppid(request.getAppid());
            prepayRequest.setMchid(request.getMchId());
            prepayRequest.setDescription(request.getBody());
            prepayRequest.setNotifyUrl(request.getNotifyUrl());
            prepayRequest.setOutTradeNo(request.getOutTradeNo());

            SceneInfo sceneInfo = new SceneInfo();
            sceneInfo.setPayerClientIp(request.getIp());
            prepayRequest.setSceneInfo(sceneInfo);
            AppServiceExtension.Builder appService = new AppServiceExtension.Builder();
            appService.config(config);
            appService.httpClient(new DefaultHttpClientBuilder().config(config).build());
            appService.hostName(HostName.API);
            PrepayWithRequestPaymentResponse response = appService.build().prepayWithRequestPayment(prepayRequest);
            payResponse.setMsg("微信APP预订单成功:订单["+request.getOutTradeNo()+"]");
            payResponse.setBody(JSONUtil.toJsonStr(response));
            payResponse.setAppid(response.getAppid());
            payResponse.setPrepayId(response.getPrepayId());
            payResponse.setPartnerId(response.getPartnerId());
            payResponse.setPackageVal(response.getPackageVal());
            payResponse.setSign(response.getSign());
            payResponse.setTimestamp(response.getTimestamp());
            payResponse.setNonceStr(response.getNonceStr());
            payResponse.setSuccess(Boolean.TRUE);
        }catch (HttpException he){
            payResponse.setMsg("微信APP支付统一下单失败:订单["+request.getOutTradeNo()+"]");
            payResponse.setBody(he.getMessage());
            payResponse.setSuccess(Boolean.FALSE);
            log.info("订单[{}]微信APP支付统一下单失败:{}",request.getOutTradeNo(),he);
            throw new BusinessException(ApiResponseCode.WX_PAY_PLACE_ORDER_FAIL);
        }catch (ValidationException ve){
            payResponse.setMsg("验证微信APP支付返回签名失败:订单["+request.getOutTradeNo()+"]");
            payResponse.setBody(ve.getMessage());
            payResponse.setSuccess(Boolean.FALSE);
            log.info("订单[{}]验证微信APP支付返回签名失败:{}",request.getOutTradeNo(),ve);
            throw new BusinessException(ApiResponseCode.WX_PAY_SIGN_VERIFY_FAIL);
        }catch (ServiceException se){
            payResponse.setMsg("微信APP支付统一下单成功,服务返回异常:订单["+request.getOutTradeNo()+"]");
            payResponse.setBody(se.getMessage());
            payResponse.setSuccess(Boolean.FALSE);
            log.info("订单[{}]微信APP支付统一下单成功,服务返回异常:{}",request.getOutTradeNo(),se);
            throw new BusinessException(ApiResponseCode.ERROR.getCode(),se.getErrorMessage());
        }catch (MalformedMessageException me){
            payResponse.setMsg("微信APP支付统一下单成功,content-type不为application/json解析返回体失败:订单["+request.getOutTradeNo()+"]");
            payResponse.setBody(me.getMessage());
            payResponse.setSuccess(Boolean.FALSE);
            log.info("订单[{}]微信APP支付统一下单成功,content-type不为application/json解析返回体失败:{}",request.getOutTradeNo(),me);
            throw new BusinessException(ApiResponseCode.WX_PAY_PLACE_ORDER_SERVICE_RESPONSE_TYPE_ERROR);
        }
        return payResponse;
    }

    public WxAppPayResponse notice(WxAppPayRequest.Notice notice) {
        WxAppPayResponse wxAppPayResponse = new WxAppPayResponse();
        WxAppPayResponse.Notice noticeResponse = new WxAppPayResponse.Notice();
        // 验签
        try {
            String noticeParams = JSONUtil.toJsonStr(notice);
            wxAppPayResponse.setBody(noticeParams);
            log.info("微信支付APP回调参数Notice:{}",noticeParams);
            // 构建request,传入必要参数
            RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(notice.getMchSerialNo())
                .nonce(notice.getNonce())
                .timestamp(notice.getTimestamp())
                .signature(notice.getSignature())
                .body(notice.getBody())
                .build();
            // 初始化 NotificationParser
            NotificationParser parser = new NotificationParser((NotificationConfig) config);
            // 以支付通知回调为例,验签、解密并转换成 Transaction
            Transaction result = parser.parse(requestParam, Transaction.class);
            log.info("微信支付APP回调参数解析:{}",JSONUtil.toJsonStr(result));
            if (result != null && Objects.equals(result.getTradeState(), Transaction.TradeStateEnum.SUCCESS)){
                wxAppPayResponse.setSuccess(Boolean.TRUE);
                noticeResponse.setAppid(result.getAppid());
                noticeResponse.setTransactionId(result.getTransactionId());
                noticeResponse.setOutTradeNo(result.getOutTradeNo());
                noticeResponse.setSuccessTime(result.getSuccessTime());
                noticeResponse.setPayerTotal(result.getAmount().getPayerTotal());
                wxAppPayResponse.setNotice(noticeResponse);
                return wxAppPayResponse;
            }
        } catch (MalformedMessageException me) {
            wxAppPayResponse.setSuccess(Boolean.FALSE);
            log.info("微信支付APP回调通知参数不正确、解析通知数据失败,{}",me);
        } catch (ValidationException ve) {
            // 签名验证失败,返回 401 UNAUTHORIZED 状态码
            wxAppPayResponse.setSuccess(Boolean.FALSE);
            log.info("微信支付APP回调签名验证失败,{}", ve);
        } catch (Exception e) {
            wxAppPayResponse.setSuccess(Boolean.FALSE);
            log.info("微信支付APP回调异常:{}",e);
        }
        wxAppPayResponse.setSuccess(Boolean.FALSE);
        wxAppPayResponse.setNotice(noticeResponse);
        return wxAppPayResponse;
    }

    public WxAppPayResponse query(WxAppPayRequest request, WxAppPayRequest.Query query) {
        Config config = getConfig(request);
        WxAppPayResponse payResponse = new WxAppPayResponse();
        AppServiceExtension.Builder appService = new AppServiceExtension.Builder();
        appService.config(config);
        appService.httpClient(new DefaultHttpClientBuilder().config(config).build());
        appService.hostName(HostName.API);
        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        //QueryOrderByIdRequest queryRequest = new QueryOrderByIdRequest();
        queryRequest.setMchid(query.getMchId());
        queryRequest.setOutTradeNo(query.getOutTradeNo());
        try {
            /*SUCCESS--支付成功
            REFUND--转入退款
            NOTPAY--未支付
            CLOSED--已关闭
            REVOKED--已撤销(刷卡支付)
            USERPAYING--用户支付中
            PAYERROR--支付失败(其他原因,如银行返回失败)
            ACCEPT--已接收,等待扣款*/
            Transaction result = appService.build().queryOrderByOutTradeNo(queryRequest);
            payResponse.setMsg("微信支付查单:订单["+query.getOutTradeNo()+"]");
            payResponse.setBody(JSONUtil.toJsonStr(result));
            String outTradeNo = "out_trade_no-"+query.getOutTradeNo()+",";
            /*if (!Objects.equals(result.get("return_code"),"SUCCESS")){
                throw new BusinessException(ApiResponseCode.ERROR.getCode(),outTradeNo+result.get("return_code")+result.get("return_msg"));
            }
            if (!Objects.equals(result.get("result_code"),"SUCCESS")){
                throw new BusinessException(ApiResponseCode.ERROR.getCode(),outTradeNo+result.get("err_code")+result.get("err_code_des"));
            }*/
            if (result != null){
                if (Objects.equals(result.getTradeState(), Transaction.TradeStateEnum.SUCCESS)){
                    payResponse.setTradeState("SUCCESS");
                    payResponse.setSuccess(Boolean.TRUE);
                    log.info("微信支付查单成功:订单[{}],报文:{}",result.getOutTradeNo(),payResponse.getBody());
                }else {
                    throw new BusinessException(ApiResponseCode.ERROR.getCode(),outTradeNo+result.getTradeState().toString());
                }
            }
        } catch (ServiceException se) {
            // API返回失败, 例如ORDER_NOT_EXISTS
            //System.out.printf("code=[%s], message=[%s]\n", se.getErrorCode(), se.getErrorMessage());
            //System.out.printf("reponse body=[%s]\n", se.getResponseBody());
            payResponse.setMsg("微信支付查单,服务返回异常:订单["+query.getOutTradeNo()+"]");
            payResponse.setBody(se.getMessage());
            payResponse.setSuccess(Boolean.FALSE);
            log.info("订单[{}]微信支付查单,服务返回异常:{}",query.getOutTradeNo(),se);
            throw new BusinessException(ApiResponseCode.WX_PAY_PLACE_ORDER_SERVICE_ERROR);
        }catch (HttpException he){
            payResponse.setMsg("微微信支付查单请求失败:订单["+query.getOutTradeNo()+"]");
            payResponse.setBody(he.getMessage());
            payResponse.setSuccess(Boolean.FALSE);
            log.info("订单[{}]微信支付查单请求失败:{}",query.getOutTradeNo(),he);
            throw new BusinessException(ApiResponseCode.WX_PAY_PLACE_ORDER_FAIL);
        }catch (ValidationException ve){
            payResponse.setMsg("微信支付查单,验证签名失败:订单["+query.getOutTradeNo()+"]");
            payResponse.setBody(ve.getMessage());
            payResponse.setSuccess(Boolean.FALSE);
            log.info("订单[{}]验证微信支付返回签名失败:{}",query.getOutTradeNo(),ve);
            throw new BusinessException(ApiResponseCode.WX_PAY_SIGN_VERIFY_FAIL);
        }catch (MalformedMessageException me){
            payResponse.setMsg("微信支付查单请求成功,content-type不为application/json解析返回体失败:订单["+query.getOutTradeNo()+"]");
            payResponse.setBody(me.getMessage());
            payResponse.setSuccess(Boolean.FALSE);
            log.info("订单[{}]微信支付查单请求成功,content-type不为application/json解析返回体失败:{}",query.getOutTradeNo(),me);
            throw new BusinessException(ApiResponseCode.WX_PAY_PLACE_ORDER_SERVICE_RESPONSE_TYPE_ERROR);
        }
        return payResponse;
    }
}

接着继续新建一个类 WxAppPayRequest.java去继承 WxAppPay.java,内容如下:

package com.zyq.pay.wx.app;

import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;

/** 微信app支付
 * author xiaochi
 * date 2024/6/4 14:04
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class WxAppPayRequest extends WxAppPay {

    private String appid;
    private String mchId;// 商户id
    private String privateKeyPath;// 商户API私钥路径(就是证书apiclient_key.pem路径)
    private String mchSerialNo;// 商户证书序列号
    private String apiV3Key;// 商户APIV3密钥
    private String notifyUrl;// 回调地址
    private String body;// 描述
    private String outTradeNo;// 订单号
    private Integer totalFee;// 金额(分)
    private String ip = "xxxx.xx.xx.xx";// ip地址,默认正式环境

    public WxAppPayResponse pay() {
        return super.pay(this);
    }

    public WxAppPayResponse query(Query query) {
        this.setMchId(query.getMchId());
        this.setMchSerialNo(query.getMchSerialNo());
        this.setPrivateKeyPath(query.getPrivateKeyPath());
        this.setApiV3Key(query.getApiV3Key());
        return super.query(this,query);
    }

    public WxAppPayResponse notice(Notice notice) {
        return super.notice(notice);
    }

    /**
     * 微信支付回调通知
     */
    @Data
    public static class Notice{
        private String mchSerialNo;// 商户证书序列号
        private String nonce;
        private String signature;
        private String timestamp;
        private String body;

        /**
         * 获取微信回调最原始的原始报文(否则验签会失败)
         * @param request
         * @return
         * @throws Exception
         */
        public static String getBody(HttpServletRequest request) throws Exception {
            BufferedReader br = request.getReader();
            String str = null;
            StringBuilder sb = new StringBuilder();
            while ((str = br.readLine())!=null) {
                sb.append(str);
            }
            return sb.toString();
        }
    }

    /**
     * 微信查单
     */
    @Data
    public static class Query{
        private String mchId;// 商户id
        private String privateKeyPath;// 商户API私钥路径
        private String mchSerialNo;// 商户证书序列号
        private String apiV3Key;// 商户APIV3密钥
        private String transactionId;// 微信流水号
        private String outTradeNo;// 订单号
    }
}

接下来就是创建访问的接口了,进行测试了 PayController.java,内容如下:

package com.zyq.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zyq.annotation.AccessLimit;
import com.zyq.annotation.ApiAuthorize;
import com.zyq.config.AliPayConfig;
import com.zyq.config.WxConfig;
import com.zyq.constant.Constant;
import com.zyq.entity.MemoryRecordOrder;
import com.zyq.enuns.ApiResponseCode;
import com.zyq.enuns.PayStateEnum;
import com.zyq.enuns.PayWayEnum;
import com.zyq.pay.ali.AliAppPayRequest;
import com.zyq.pay.ali.AliAppPayResponse;
import com.zyq.pay.wx.app.WxAppPayRequest;
import com.zyq.pay.wx.app.WxAppPayResponse;
import com.zyq.service.IAccountDistributionTreeLevelService;
import com.zyq.service.ICodeActiveService;
import com.zyq.service.IKickbackRecordService;
import com.zyq.service.IMemoryRecordOrderNoticeService;
import com.zyq.service.IMemoryRecordOrderService;
import com.zyq.service.IMemoryRecordService;
import com.zyq.util.AsyncUtil;
import com.zyq.util.LockUtil;
import com.zyq.util.NumberUtil;
import com.zyq.util.OrderUtil;
import com.zyq.util.R;
import com.zyq.vo.req.PayReqVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

/** 支付
 * author xiaochi
 * date 2024/6/4 11:09
 */
@RestController
@RequestMapping(Constant.Api.v1+"/pay")
public class PayController extends BaseController {

    @Autowired
    public IMemoryRecordOrderService memoryRecordOrderService;
    @Autowired
    public IMemoryRecordService memoryRecordService;
    @Autowired
    public IAccountDistributionTreeLevelService accountDistributionTreeLevelService;
    @Autowired
    private WxConfig wxConfig;
    @Autowired
    private AliPayConfig aliPayConfig;
    @Autowired
    private IKickbackRecordService kickbackRecordService;
    @Autowired
    private ICodeActiveService codeActiveService;
    @Autowired
    private IMemoryRecordOrderNoticeService memoryRecordOrderNoticeService;

    // --------------------------------------- 微信支付 -------------------------------------------
    /** 微信支付
     * @param reqVo 订单vo
     */
    @ApiAuthorize
    @AccessLimit(count = Constant.AccessLimit.count,timeOut = Constant.AccessLimit.timeOut)
    @PostMapping("/wx/app")
    public R<WxAppPayResponse> wxPay(@RequestBody @Valid PayReqVo reqVo, HttpServletRequest request){
        // 验证邀请码
        if (StrUtil.isNotBlank(reqVo.getCode()) && !codeActiveService.checkCodeActive(reqVo.getCode())){
            return R.error(ApiResponseCode.CODE_NOT_ACTIVE);
        }
        MemoryRecordOrder memoryRecordOrder = memoryRecordOrderService.getById(reqVo.getId());
        if (ObjectUtils.isEmpty(memoryRecordOrder)){
            return R.error(ApiResponseCode.PARAMS_ERROR);
        }
        if (Objects.equals(memoryRecordOrder.getState(),PayStateEnum.PAY.getCode())){
            return R.error(ApiResponseCode.ORDER_ALREADY_PAY);
        }
        memoryRecordOrder.setCode(reqVo.getCode());
        memoryRecordOrder.setPayWay(reqVo.getPayWay());
        if (!memoryRecordOrderService.updateById(memoryRecordOrder)){
            return R.error();
        }
        // 发起预支付成功,拼接返回参数
        WxAppPayRequest wxAppPayRequest = new WxAppPayRequest();
        wxAppPayRequest.setBody("描述信息");
        wxAppPayRequest.setTotalFee(memoryRecordOrder.getTotalPrice().intValue());
        wxAppPayRequest.setOutTradeNo(memoryRecordOrder.getOutTradeNo());
        wxAppPayRequest.setAppid(wxConfig.getAppid());
        wxAppPayRequest.setMchId(wxConfig.getMchId());
        wxAppPayRequest.setPrivateKeyPath(wxConfig.getPrivateKeyPath());
        wxAppPayRequest.setMchSerialNo(wxConfig.getMchSerialNo());
        wxAppPayRequest.setApiV3Key(wxConfig.getKey());
        wxAppPayRequest.setNotifyUrl(wxConfig.getPayCallbackUrl());
        return R.ok(wxAppPayRequest.pay());
    }

    /**
     * 微信支付回调
     * @param request
     * @return
     */
    @PostMapping("/wx/app/callback")
    public Map<String,String> wxCallback(HttpServletRequest request){
        Map<String,String> resp = new HashMap<>();
        try {
            WxAppPayRequest.Notice notice = new WxAppPayRequest.Notice();
            notice.setMchSerialNo(request.getHeader("Wechatpay-Serial"));
            notice.setNonce(request.getHeader("Wechatpay-Nonce"));
            notice.setTimestamp(request.getHeader("Wechatpay-Timestamp"));
            notice.setSignature(request.getHeader("Wechatpay-Signature"));
            notice.setBody(WxAppPayRequest.Notice.getBody(request));
            WxAppPayRequest wxAppPayRequest = new WxAppPayRequest();
            WxAppPayResponse wxAppPayResponse = wxAppPayRequest.notice(notice);
            WxAppPayResponse.Notice noticeResponse = wxAppPayResponse.getNotice();
            AsyncUtil.run(() -> {
                boolean rs = memoryRecordOrderNoticeService.saveNotifyBody(noticeResponse.getOutTradeNo(), noticeResponse.getTransactionId(), wxAppPayResponse.getBody());
                logger.info("订单[{}]交易号[{}]微信APP支付通知报文入库[{}]",noticeResponse.getOutTradeNo(),noticeResponse.getTransactionId(),rs?"成功":"失败");
            });
            if (wxAppPayResponse.isSuccess()){
                LockUtil.run(() -> {
                    // 业务逻辑
                    MemoryRecordOrder memoryRecordOrder = memoryRecordOrderService.findByOutTradeNo(noticeResponse.getOutTradeNo());
                    Map<String,String> param = new HashMap<>();
                    param.put("out_trade_no",noticeResponse.getOutTradeNo());
                    param.put("total_fee",String.valueOf(noticeResponse.getPayerTotal()));
                    param.put("appid",noticeResponse.getAppid());
                    param.put("pay_time",noticeResponse.getSuccessTime());
                    param.put("notify_time", DateUtil.now());
                    if (this.check(memoryRecordOrder,param,PayWayEnum.WX)){
                        // 更新业务
                        this.updatePayStateByOrderNo(noticeResponse.getOutTradeNo(),param, PayWayEnum.WX);
                        //分销与佣金计算入库
                        this.handleSave(memoryRecordOrder);
                    }
                });
                resp.put("code","SUCCESS");
                resp.put("message","成功");
                return resp;
            }
            resp.put("code","FAIL");
            resp.put("message","失败");
            return resp;
        }catch (Exception e){
            logger.info("微信APP支付回调异常:{}",e);
        }
        resp.put("code","FAIL");
        resp.put("message","失败");
        return resp;
    }

    // --------------------------------------- 支付宝支付 -------------------------------------------
    /** 支付宝支付
     */
    @ApiAuthorize
    @AccessLimit(count = Constant.AccessLimit.count,timeOut = Constant.AccessLimit.timeOut)
    @PostMapping("/ali")
    public R<AliAppPayResponse> aliPay(@RequestBody @Valid PayReqVo reqVo){
        // 验证邀请码
        if (StrUtil.isNotBlank(reqVo.getCode()) && !codeActiveService.checkCodeActive(reqVo.getCode())){
            return R.error(ApiResponseCode.CODE_NOT_ACTIVE);
        }
        MemoryRecordOrder memoryRecordOrder = memoryRecordOrderService.getById(reqVo.getId());
        if (ObjectUtils.isEmpty(memoryRecordOrder)){
            return R.error(ApiResponseCode.PARAMS_ERROR);
        }
        if (Objects.equals(memoryRecordOrder.getState(),PayStateEnum.PAY.getCode())){
            return R.error(ApiResponseCode.ORDER_ALREADY_PAY);
        }
        memoryRecordOrder.setCode(reqVo.getCode());
        memoryRecordOrder.setPayWay(reqVo.getPayWay());
        if (!memoryRecordOrderService.updateById(memoryRecordOrder)){
            return R.error();
        }
        AliAppPayRequest aliPayAppRequest = new AliAppPayRequest();
        aliPayAppRequest.setNotifyUrl(aliPayConfig.getPayCallbackUrl());
        aliPayAppRequest.setAppid(aliPayConfig.getAppid());
        aliPayAppRequest.setPrivateKey(aliPayConfig.getPrivateKey());
        aliPayAppRequest.setPublicKey(aliPayConfig.getPublicKey());
        aliPayAppRequest.setOutTradeNo(memoryRecordOrder.getOutTradeNo());
        aliPayAppRequest.setTotalAmount(OrderUtil.coverRmb(memoryRecordOrder.getTotalPrice()).toString());
        aliPayAppRequest.setSubject("描述信息");
        return R.ok(aliPayAppRequest.pay());
    }

    /**
     * 支付宝支付回调
     * @param request
     * @return
     */
    @PostMapping("/ali/callback")
    public String aliCallback(HttpServletRequest request){
        try {
            Map<String, String> params = this.toMap(request);
            if (params.isEmpty()){
                return "failure";
            }
            // 保存通知报文
            AsyncUtil.run(() -> {
                String outTradeNo = params.get("out_trade_no");
                String tradeNo = params.get("trade_no");
                boolean rs = memoryRecordOrderNoticeService.saveNotifyBody(outTradeNo, tradeNo, JSONUtil.toJsonStr(params));
                logger.info("订单[{}]交易号[{}]支付宝APP支付通知报文入库[{}]",outTradeNo,tradeNo,rs?"成功":"失败");
            });
            AliAppPayRequest aliPayAppRequest = new AliAppPayRequest();
            AliAppPayRequest.Notice notice = new AliAppPayRequest.Notice();
            notice.setPublicKey(aliPayConfig.getPublicKey());
            notice.setOutTradeNo(params.get("out_trade_no"));
            notice.setTransactionId(params.get("trade_no"));
            notice.setBody(params);
            String result = aliPayAppRequest.notice(notice,(param) -> {
                //String notifyTime = param.get("notify_time");// 通知时间
                String outTradeNo = param.get("out_trade_no");
                LockUtil.run(() -> {
                    try {
                        MemoryRecordOrder memoryRecordOrder = memoryRecordOrderService.findByOutTradeNo(outTradeNo);
                        if (this.check(memoryRecordOrder,param,PayWayEnum.ALI)){
                            // 1.更新业务
                            this.updatePayStateByOrderNo(outTradeNo,params, PayWayEnum.ALI);
                            // 2.分销与佣金计算入库
                            this.handleSave(memoryRecordOrder);
                        }
                    }catch (Exception e){
                        logger.info("支付宝支付回调:订单[{}]业务执行异常:{}",outTradeNo,e);
                    }
                });
            },(param) -> {
                logger.info("订单[{}]支付回调失败:{}",param.get("out_trade_no"),JSONUtil.toJsonStr(param));
            });
            logger.info("支付宝APP回调结果:{}",result);
            return result;
        }catch (Exception e){
            logger.info("支付宝APP支付回调异常:{}",e);
            return "failure";
        }
    }

    /**
     * 微信/支付宝 支付查询
     * @param orderId
     * @return
     */
    @PostMapping("/query/{orderId}")
    public R<AliAppPayResponse> query(@PathVariable String orderId){
        MemoryRecordOrder memoryRecordOrder = memoryRecordOrderService.getById(orderId);
        if (ObjectUtils.isEmpty(memoryRecordOrder)){
            return R.error(ApiResponseCode.ORDER_NOT_EXISTS);
        }
        //1微信2支付宝
        if (Objects.equals(PayWayEnum.WX.getCode(),memoryRecordOrder.getPayWay())){
            WxAppPayRequest wxAppPayRequest = new WxAppPayRequest();
            // 微信查单
            WxAppPayRequest.Query wxQuery = new WxAppPayRequest.Query();
            wxQuery.setMchId(wxConfig.getMchId());
            wxQuery.setMchSerialNo(wxConfig.getMchSerialNo());
            wxQuery.setPrivateKeyPath(wxConfig.getPrivateKeyPath());
            wxQuery.setApiV3Key(wxConfig.getKey());
            wxQuery.setTransactionId(memoryRecordOrder.getTransactionId());
            wxQuery.setOutTradeNo(memoryRecordOrder.getOutTradeNo());
            if (wxAppPayRequest.query(wxQuery).isSuccess()){
                return R.ok();
            }
            return R.error();
        }
        AliAppPayRequest aliPayAppRequest = new AliAppPayRequest();
        AliAppPayRequest.Query aliQuery = new AliAppPayRequest.Query();
        aliQuery.setAppid(aliPayConfig.getAppid());
        aliQuery.setPrivateKey(aliPayConfig.getPrivateKey());
        aliQuery.setOutTradeNo(memoryRecordOrder.getOutTradeNo());
        aliQuery.setTransactionId(memoryRecordOrder.getTransactionId());
        aliQuery.setGateway(aliPayConfig.getGateway());
        if (aliPayAppRequest.query(aliQuery).isSuccess()){
            return R.ok();
        }
        return R.error();
    }
    // ----------------------------------- 业务处理----------------------------

    /**
     * 分销与佣金入库
     * @param memoryRecordOrder
     */
    private void handleSave(MemoryRecordOrder memoryRecordOrder){
        if (StrUtil.isNotBlank(memoryRecordOrder.getCode())){
            // 订单有邀请码,才添加分销记录与计算佣金
            if (accountDistributionTreeLevelService.createTreeByCode(memoryRecordOrder.getAccountId(), memoryRecordOrder.getCode())){
                logger.info("订单[{}],分销保存成功",memoryRecordOrder.getOutTradeNo());
                // 佣金
                if (kickbackRecordService.calcKickback(memoryRecordOrder)){
                    logger.info("订单[{}],accountId[{}],分佣保存成功",memoryRecordOrder.getOutTradeNo(),memoryRecordOrder.getAccountId());
                }else {
                    logger.info("订单[{}],accountId[{}],分佣保存失败",memoryRecordOrder.getOutTradeNo(),memoryRecordOrder.getAccountId());
                }
            }else {
                logger.info("订单[{}],分销保存失败",memoryRecordOrder.getOutTradeNo());
            }
        }
    }

    /**
     * 根据订单号更新支付状态(同步锁)
     * @param outTradeNo 订单号
     * @param params  回调参数
     * @param payWay 支付方式
     * @return
     */
    private void updatePayStateByOrderNo(String outTradeNo,Map<String,String> params,PayWayEnum payWay){
        QueryWrapper<MemoryRecordOrder> query = Wrappers.query();
        query.lambda().eq(MemoryRecordOrder::getOutTradeNo,outTradeNo)
                .eq(MemoryRecordOrder::getState,PayStateEnum.UNPAY.getCode());
        query.last("LIMIT 1");
        MemoryRecordOrder memoryRecordOrder = memoryRecordOrderService.getOne(query);
        if (ObjectUtils.isEmpty(memoryRecordOrder)){
            return;
        }
        memoryRecordOrder.setState(PayStateEnum.PAY.getCode());
        memoryRecordOrder.setPayWay(payWay.getCode());
        if (Objects.equals(payWay,PayWayEnum.WX)){//微信
            memoryRecordOrder.setTransactionId(params.get("transaction_id"));
            memoryRecordOrder.setPayTime(DateUtil.parse(params.get("pay_time")));//交易时间
            memoryRecordOrder.setNotifyTime(DateUtil.parse(params.get("notify_time")));
            memoryRecordOrder.setPayPrice(Long.valueOf(params.get("total_fee")));
        }
        if (Objects.equals(payWay,PayWayEnum.ALI)){// 支付宝
            memoryRecordOrder.setTransactionId(params.get("trade_no"));
            memoryRecordOrder.setPayTime(DateUtil.parse(params.get("gmt_payment")));//交易时间
            memoryRecordOrder.setNotifyTime(DateUtil.parse(params.get("notify_time")));
            memoryRecordOrder.setPayPrice(OrderUtil.rmbToCover(NumberUtil.toBigDecimal(params.get("total_amount"))));
        }
        String res = "失败";
        if (memoryRecordOrderService.updateById(memoryRecordOrder)){
            res = "成功";
        }
        logger.info("订单状态更新[{}],[{}]-{}",memoryRecordOrder.getOutTradeNo(),PayWayEnum.getValueByKey(payWay.getCode()),res);
    }

    /**
     * 验证回调参数
     * @return
     */
    private boolean check(MemoryRecordOrder memoryRecordOrder,Map<String, String> params,PayWayEnum payWayEnum){
        String outTradeNo = params.get("out_trade_no");
        //MemoryRecordOrder memoryRecordOrder = memoryRecordOrderService.findByOutTradeNo(outTradeNo);
        if (ObjectUtils.isEmpty(memoryRecordOrder)){
            logger.info("订单[{}]不存在",outTradeNo);
            return false;
        }
        if (Objects.equals(memoryRecordOrder.getState(),PayStateEnum.PAY.getCode())){
            logger.info("订单[{}]已支付",outTradeNo);
            return false;
        }
        if (Objects.equals(PayWayEnum.WX,payWayEnum)){
            // 金额验证
            if (!Objects.equals(String.valueOf(memoryRecordOrder.getTotalPrice()),params.get("total_fee"))){
                logger.info("订单[{}]金额[{}-{}]不一致",outTradeNo,memoryRecordOrder.getTotalPrice(),params.get("total_fee"));
                return false;
            }
            // 验证app_id是否为该商户本身
            if (!Objects.equals(wxConfig.getAppid(),params.get("appid"))){
                logger.info("订单[{}]微信支付回调appid[{}-{}]不一致",outTradeNo,aliPayConfig.getAppid(),params.get("appid"));
                return false;
            }
            return true;
        }
        if (Objects.equals(PayWayEnum.ALI,payWayEnum)){
            // 金额验证
            if (!Objects.equals(OrderUtil.coverRmb(memoryRecordOrder.getTotalPrice()).toString(),params.get("total_amount"))){
                logger.info("订单[{}]金额[{}-{}]不一致",outTradeNo,memoryRecordOrder.getTotalPrice(),params.get("total_amount"));
                return false;
            }
            // 验证app_id是否为该商户本身
            if (!Objects.equals(aliPayConfig.getAppid(),params.get("app_id"))){
                logger.info("订单[{}]支付宝支付回调appid[{}-{}]不一致",outTradeNo,aliPayConfig.getAppid(),params.get("app_id"));
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * 解析支付宝支付回调参数
     * @param request
     * @return
     */
    public Map<String, String> toMap(HttpServletRequest request) {
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> 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);
        }
        return params;
    }
}

访问接口已经可以进行支付了。
用到的类 WxAppPayResponse.java,内容如下:

package com.zyq.pay.wx.app;

import lombok.Data;

/**
 * author xiaochi
 * date 2024/6/4 13:50
 */
@Data
public class WxAppPayResponse {

    private String appid;

    private String partnerId;

    private String prepayId;

    private String packageVal;

    private String nonceStr;

    private String timestamp;

    private String sign;

    private String tradeState;// 用于查询订单状态

    //---------返回提示-------------
    private String msg;// 提示信息
    private String body;//主体
    private boolean success = false;//是否成功

    private Notice notice;// 支付回调
    /**
     * 通知返回参数
     */
    @Data
    public static class Notice{
        private String appid;//订单号
        private String transactionId;//订单号
        private String outTradeNo;//订单号
        private String successTime;// 支付完成时间
        private Integer payerTotal;// 支付金额
    }
}

支付宝支付

新建AliAppPay.java

package com.zyq.pay.ali;

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.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.zyq.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/** 支付宝支付
 * author xiaochi
 * date 2024/6/5 10:29
 */
@Slf4j
public class AliAppPay {
    private static AlipayClient alipayClient;

    /**
     * 发起支付
     * @param request
     * @return
     */
    public AliAppPayResponse pay(AliAppPayRequest request) {
        AlipayClient alipayClient = getAlipayClient(request);
        // 构造请求参数以调用接口
        AlipayTradeAppPayRequest appPayRequest = new AlipayTradeAppPayRequest();
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        // 设置订单绝对超时时间
        //model.setTimeExpire("2016-12-31 10:05:00");
        model.setOutTradeNo(request.getOutTradeNo());
        model.setTotalAmount(request.getTotalAmount());// 单位元
        model.setSubject(request.getSubject());

        appPayRequest.setBizModel(model);
        appPayRequest.setNotifyUrl(request.getNotifyUrl());
        AliAppPayResponse payResponse = new AliAppPayResponse();
        AlipayTradeAppPayResponse response;
        try {
            log.info("支付宝APP支付参数:订单[{}],body:{}",request.getOutTradeNo(),JSONUtil.toJsonStr(request));
            response = alipayClient.sdkExecute(appPayRequest);
            log.info("支付宝支付报文:订单[{}],报文:{}",request.getOutTradeNo(),response.getBody());
            payResponse.setBody(response.getBody());
            if (response.isSuccess()) {
                payResponse.setSuccess(Boolean.TRUE);
                payResponse.setMsg("支付宝APP支付调用成功:订单["+request.getOutTradeNo()+"]");
            }else {
                payResponse.setSuccess(Boolean.FALSE);
                payResponse.setMsg("支付宝APP支付调用失败:订单["+request.getOutTradeNo()+"]");
            }
            //System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        } catch (AlipayApiException e) {
            payResponse.setSuccess(Boolean.FALSE);
            log.info("支付宝APP支付失败:订单[{}],{}",request.getOutTradeNo(),e);
            throw new BusinessException(Integer.parseInt(e.getErrCode()),"订单[" + request.getOutTradeNo() + "]," +e.getMessage());
        }
        return payResponse;
    }

    /**
     * 验证签名
     * @param request
     * @param body
     * @return
     */
    public boolean verifySign(AliAppPayRequest request, Map<String, String> body) {
        // 调用SDK验证签名
        boolean signVerified = false;
        try {
            log.info("订单[{}]流水号[{}]支付宝验签body参数:{}",request.getOutTradeNo(),request.getTransactionId(), JSONUtil.toJsonStr(body));
            signVerified = AlipaySignature.rsaCheckV1(body, request.getPublicKey(), request.getCharset(), request.getSignType());
        } catch (AlipayApiException e) {
            log.info("订单[{}]流水号[{}]支付宝验签失败:{}",request.getOutTradeNo(),request.getTransactionId(),e);
        }
        log.info("订单[{}]流水号[{}]支付宝验签signVerified={}",request.getOutTradeNo(),request.getTransactionId(), signVerified);
        return signVerified;
    }

    /**
     * 查询支付
     * @param request
     * @return
     */
    public AliAppPayResponse query(AliAppPayRequest request) {
        AlipayClient alipayClient = getAlipayClient(request);
        // 构造请求参数以调用接口
        AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        // 设置订单支付时传入的商户订单号
        model.setOutTradeNo(request.getOutTradeNo());
        // 设置查询选项
        List<String> queryOptions = new ArrayList<String>();
        queryOptions.add("trade_settle_info");
        model.setQueryOptions(queryOptions);
        // 设置支付宝交易号
        model.setTradeNo(request.getTransactionId());
        queryRequest.setBizModel(model);

        AliAppPayResponse payResponse = new AliAppPayResponse();
        AlipayTradeQueryResponse response;
        try {
            response = alipayClient.execute(queryRequest);
            log.info("支付宝查询报文:订单[{}],流水号[{}],{}",request.getOutTradeNo(),request.getTransactionId(),response.getBody());
            payResponse.setBody(response.getBody());
            // TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)
            if (response.isSuccess() && (Objects.equals(response.getTradeStatus(),"TRADE_SUCCESS")||Objects.equals(response.getTradeStatus(),"TRADE_FINISHED"))) {
                payResponse.setSuccess(Boolean.TRUE);
                payResponse.setMsg("支付宝查询成功:订单["+request.getOutTradeNo()+"],流水号["+request.getTransactionId()+"]");
            }else {
                payResponse.setSuccess(Boolean.FALSE);
                payResponse.setMsg("支付宝查询失败:订单["+request.getOutTradeNo()+"],流水号["+request.getTransactionId()+"]");
            }
        } catch (AlipayApiException e) {
            log.info("支付宝查询失败:订单号[{}],流水号[{}],{}",request.getOutTradeNo(),request.getTransactionId(),e);
            throw new BusinessException(Integer.parseInt(e.getErrCode()),"订单[" + request.getOutTradeNo() + "]," +e.getMessage());
        }
        return payResponse;
    }

    /**
     * 退款
     * @param request
     * @return
     */
    public AliAppPayResponse tradeRefund(AliAppPayRequest request){
        AliAppPayResponse payResponse = new AliAppPayResponse();
        AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(request.getOutTradeNo());
        model.setRefundAmount(request.getTotalAmount());
        model.setRefundReason("正常退款");
        model.setOutRequestNo(request.getOutRequestNo());
        refundRequest.setBizModel(model);
        AlipayTradeRefundResponse response;
        try {
            response = getAlipayClient(request).execute(refundRequest);
            log.info("支付宝支付报文:订单[{}],报文:{}",request.getOutTradeNo(),response.getBody());
        } catch (AlipayApiException e) {
            payResponse.setSuccess(Boolean.FALSE);
            payResponse.setBody(e.getErrMsg());
            payResponse.setMsg("支付宝退款失败:订单["+request.getOutTradeNo()+"],"+e.getErrCode());
            log.info("支付宝退款失败:订单[{}],{}", request.getOutTradeNo(),e.getErrMsg());
            throw new BusinessException(Integer.parseInt(e.getErrCode()),"out_trade_no-"+request.getOutTradeNo()+","+ e.getErrMsg());
        }
        if ("10000".equals(response.getCode())) {
            payResponse.setBody(response.getBody());
            payResponse.setMsg("支付宝退款调用成功:订单["+request.getOutTradeNo()+"]");
            payResponse.setSuccess(Boolean.TRUE);
            log.info("支付宝退款调用成功:订单[{}],报文:{}" ,request.getOutTradeNo(),response.getBody());
        } else {
            payResponse.setBody(response.getBody());
            payResponse.setMsg("支付宝退款调用失败:订单["+request.getOutTradeNo()+"]");
            payResponse.setSuccess(Boolean.FALSE);
            log.error("支付宝退款调用失败:订单[{}],报文:{}",request.getOutTradeNo(),response.getBody());
        }
        return payResponse;
    }

    /**
     * 获取支付客户端
     * @param request
     * @return
     */
    protected AlipayClient getAlipayClient(AliAppPayRequest request){
        /*if (alipayClient != null){
            return alipayClient;
        }*/
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl(request.getGateway());
        alipayConfig.setAppId(request.getAppid());
        alipayConfig.setPrivateKey(request.getPrivateKey());
        alipayConfig.setAlipayPublicKey(request.getPublicKey());
        alipayConfig.setFormat(request.getFormat());
        alipayConfig.setCharset(StandardCharsets.UTF_8.toString());
        alipayConfig.setSignType(request.getSignType());
        // 初始化SDK
//        AlipayClient alipayClient = null;
        try {
            alipayClient = new DefaultAlipayClient(alipayConfig);
        } catch (AlipayApiException e) {
            log.info("支付宝支付初始化失败:{}",e);
        }
        return alipayClient;
    }
}

接着新建AliAppPayRequest.java 继承 AliAppPay.java,内容如下:

package com.zyq.pay.ali;

import lombok.Data;
import lombok.EqualsAndHashCode;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.function.Consumer;

/** 支付宝app支付
 * author xiaochi
 * date 2024/6/4 14:04
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class AliAppPayRequest extends AliAppPay {

    private String gateway = "https://openapi.alipay.com/gateway.do";// 网关地址
    private String appid;// 应用id
    private String privateKey;// 私钥
    private String publicKey;// 公钥
    private String notifyUrl;// 回调地址
    private String outTradeNo;// 订单号
    private String totalAmount;// 金额(元)
    private String subject;// 订单标题
    private String format = "JSON";// 仅支持JSON
    private String signType = "RSA2";// 签名类型
    private String charset = StandardCharsets.UTF_8.toString();// 请求使用的编码格式

    // ------------------------------------ 查询参数 ---------------------------
    private String transactionId;// 支付宝流水号
    // ------------------------------------ 退款参数 ---------------------------
    private String outRequestNo;//退款单号

    public AliAppPayResponse pay() {
        return super.pay(this);
    }

    public String notice(Notice notice,Consumer<Map<String, String>> paySuccessback, Consumer<Map<String, String>> payFailback) {
        this.setPublicKey(notice.getPublicKey());
        this.setOutTradeNo(notice.getOutTradeNo());
        this.setTransactionId(notice.getTransactionId());
        if (super.verifySign(this,notice.getBody()) && (notice.getBody().get("app_id").equals(notice.getAppid()))){
            String tradeStatus = notice.getBody().get("trade_status");
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)){
                if (paySuccessback != null){
                    paySuccessback.accept(notice.getBody());
                }
            }else {
                if (payFailback != null){
                    payFailback.accept(notice.getBody());
                }
            }
            return "success";
        }else {
            return "failure";
        }
    }

    public AliAppPayResponse query(Query query) {
        this.setTransactionId(query.getTransactionId());
        this.setOutTradeNo(query.getOutTradeNo());
        this.setAppid(query.getAppid());
        this.setPrivateKey(query.getPrivateKey());
        this.setGateway(query.getGateway());
        return super.query(this);
    }

    /**
     * 支付宝支付通知
     */
    @Data
    public static class Notice{
        private String appid;// appid
        private String publicKey;// 公钥
        private String outTradeNo;// 订单号
        private String transactionId;// 支付宝流水号
        private Map<String, String> body;// 回调报文
    }

    /**
     * 支付宝查单
     */
    @Data
    public static class Query{
        private String appid;// appid
        private String privateKey;// 私钥
        private String outTradeNo;// 订单号
        private String transactionId;// 支付宝流水号
        private String gateway = "https://openapi.alipay.com/gateway.do";// 网关地址
    }
}

接下来继续访问上边的测试接口PayController.java,已经可以进行支付了,用到的类AliAppPayResponse.java

package com.zyq.pay.ali;

import lombok.Data;

/** 支付宝app支付vo
 * author xiaochi
 * date 2024/6/4 13:50
 */
@Data
public class AliAppPayResponse {

    private String msg;// 提示信息
    private String body;//主体
    private boolean success = false;//是否成功
}

到此完成。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容