您的当前位置:首页正文

微信支付V3回调与退款回调(weixin-java-pay)

2024-11-10 来源:个人技术集锦
MAVEN包

GitEE/GitHub 搜索WxJAVA 这个就是这个包的项目可在这里询问问题

    <dependency>
        <groupId>com.github.binarywang</groupId>
        <artifactId>weixin-java-pay</artifactId>
        <version>4.5.3.B</version>
    </dependency>
Controller层

微信签名文档:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml
注:不使用HttpServletRequest request 是因为我用这个获取 签名验证出现了错误,所以改用成注解来获取签名

/**
 * V3支付接口回调
 * @param appid 微信用户的openId 注:这是我自己需要的逻辑参数,你不需要可以不用。
 * @param orderPayNo  支付订单号,自己定义的微信支付订单号
 * @param payNotifyForm 微信支付回调过来的参数 注:不可以因为看文档而定义一个对象会出问题,只能用String来接受
 * @param timestamp 微信签名
 * @param nonce 微信签名
 * @param serial 微信签名
 * @param signature 微信签名
 * @param response 返回 回调结果
 * @return
 */
@PostMapping("/payNotify/{appid}/{orderPayNo}")
@ApiOperation("支付回调")
public String payNotify(@PathVariable("appid") String appid
        , @PathVariable("orderPayNo") String orderPayNo
        , @RequestBody String payNotifyForm
        , @RequestHeader("Wechatpay-Timestamp") String timestamp
        , @RequestHeader("Wechatpay-Nonce") String nonce
        , @RequestHeader("Wechatpay-Serial") String serial
        , @RequestHeader("Wechatpay-Signature") String signature
        , HttpServletResponse response){
    return payService.payNotifyV3(appid,orderPayNo, payNotifyForm, timestamp, nonce, serial, signature, response);
}

/**
 * 
 * @param appid 微信用户的openId 注:这是我自己需要的逻辑参数,你不需要可以不用。
 * @param outRefundNo 退款订单号,自己定义的微信支付订单号
 * @param payNotifyForm  微信支付回调过来的参数 注:不可以因为看文档而定义一个对象会出问题,只能用String来接受
 * @param timestamp 
 * @param nonce
 * @param serial
 * @param signature
 * @param response
 * @return
 */
@PostMapping("/refundNotify/{appid}/{outRefundNo}")
@ApiOperation("退款回调")
public String parseRefundNotifyResult(@PathVariable("appid") String appid
        , @PathVariable("outRefundNo") String outRefundNo
        , @RequestBody String payNotifyForm
        , @RequestHeader("Wechatpay-Timestamp") String timestamp
        , @RequestHeader("Wechatpay-Nonce") String nonce
        , @RequestHeader("Wechatpay-Serial") String serial
        , @RequestHeader("Wechatpay-Signature") String signature
        , HttpServletResponse response) {
    return payService.refundNotifyV3(appid,outRefundNo,payNotifyForm,timestamp, nonce, serial, signature,response);
}
证书在项目中的存放位置与 yml的配置

WxPayProperties 获取证书,密钥等路径的工具类
@Component
@Data 
@ConfigurationProperties(prefix = "he.wx.pay")
public class WxPayProperties {

/**
 * 微信支付商户号
 */
private String mchId;

/**
 * 微信支付商户密钥
 */
private String mchKey;

/**
 * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
 */
private String keyPath;

/**
 * API 开发密钥
 */
private String APIv2;

/**
 * PI 开发密钥
 */
private String APIv3;

/**
 * 微信支付 证书key
 */
private String privateKeyPath;

/**
 * 微信支付 证书Cert
 */
private String privateCertPath;

/**
 * 回调Url
 */
private String notifyUrl;
}
ServiceImpl层
 @Autowired
 private WxPayProperties properties;  // 获取证书,密钥等参数的工具类
 
/** 获取 WxPayService接口
 * getWxPayService
 * @param appid
 * @return
 */
private WxPayService getWxPayService(String appid){
    WxPayConfig payConfig = new WxPayConfig();
    payConfig.setAppId(appid);
    payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
    payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
    payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
    payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getAPIv3()));
    payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath()));
    payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));
    
    // 可以指定是否使用沙箱环境
    payConfig.setUseSandboxEnv(false);

    WxPayService wxPayService = new WxPayServiceImpl();
    wxPayService.setConfig(payConfig);
    return wxPayService;
}
/**
 * new SignatureHeader() 签名对象
 * @param timestamp
 * @param nonce
 * @param serial
 * @param signature
 * @return
 */
private SignatureHeader getSignatureHeader(String timestamp, String nonce, String serial, String signature){
    SignatureHeader signatureHeader = new SignatureHeader();
    signatureHeader.setTimeStamp(timestamp);
    signatureHeader.setNonce(nonce);
    signatureHeader.setSerial(serial);
    signatureHeader.setSignature(signature);
    return signatureHeader;
}

   @Override
public String payNotifyV3(String appid,String orderPayNo, String payNotifyForm, String timestamp, String nonce, String serial, String signature, HttpServletResponse response){

    WxPayService wxPayService = this.getWxPayService(appid);
    SignatureHeader signatureHeader = this.getSignatureHeader(timestamp, nonce, serial, signature);

    try{
       // 使用maven包中的方法进行解析与验证
        WxPayNotifyV3Result notifyV3Result =
                wxPayService.parseOrderNotifyV3Result(payNotifyForm, signatureHeader);
        // 保存支付回调记录 用于在数据库中观看传过来的参数这么处理
        wxPayXmlService.saveWxPayXml(WxPayXmlTypeEnum.PAY.getKey(),orderPayNo,notifyV3Result.toString(),WxPayXmlRequestResponseEnum.EMPLOY.getKey());
        // 我对订单的处理逻辑 根据项目逻辑来
        this.payNotifyDisposal(notifyV3Result, orderPayNo);
    }catch (WxPayException e){
        // 保存支付回调的报错信息 方便用于排错
        wxPayXmlService.saveWxPayXml(WxPayXmlTypeEnum.PAY.getKey(),orderPayNo,e.getCustomErrorMsg(),WxPayXmlRequestResponseEnum.RESPONSE.getKey());
        response.setStatus(500);

        e.printStackTrace();
        return "{"+
                '"'+ "code"+'"'+":"+'"'+"FAIL"+'"'+" "+
                '"'+ "message"+'"'+":"+'"'+"失败"+'"'+
                "}";
    }catch (Exception e){
        response.setStatus(500);
        e.printStackTrace();
        return "{"+
                '"'+ "code"+'"'+":"+'"'+"FAIL"+'"'+" "+
                '"'+ "message"+'"'+":"+'"'+"失败"+'"'+
                "}";
    }

    //设置状态码
    response.setStatus(200);
    return "{"+
            '"'+ "code"+'"'+":"+'"'+"SUCCESS"+'"'+" "+
            '"'+ "message"+'"'+":"+'"'+"成功"+'"'+
            "}";
}

  @Override
public String refundNotifyV3(String appid,String outRefundNo, String resultNotify, String timestamp, String nonce, String serial, String signature, HttpServletResponse response) {

    WxPayService wxPayService = this.getWxPayService(appid);
    SignatureHeader signatureHeader = this.getSignatureHeader(timestamp, nonce, serial, signature);

    try {
        // 使用maven包中的方法进行解析与验证
        WxPayRefundNotifyV3Result wxPayRefundNotifyV3Result =
                wxPayService.parseRefundNotifyV3Result(resultNotify, signatureHeader);

        // 微信退款回调参数保存
        wxPayXmlService.saveWxPayXml(WxPayXmlTypeEnum.REFUND.getKey(),outRefundNo,wxPayRefundNotifyV3Result.toString(),WxPayXmlRequestResponseEnum.EMPLOY.getKey());

        this.payRefundNotifyDisposal(wxPayRefundNotifyV3Result, outRefundNo);
    }catch (WxPayException e){
        // 微信退款回调参数报错信息 保存
        wxPayXmlService.saveWxPayXml(WxPayXmlTypeEnum.REFUND.getKey(),outRefundNo,e.getCustomErrorMsg(),WxPayXmlRequestResponseEnum.EMPLOY.getKey());
        e.printStackTrace();

        //设置状态码 返回给微信
        response.setStatus(500);
        return "{"+
                '"'+ "code"+'"'+":"+'"'+"SUCCESS"+'"'+" "+
                '"'+ "message"+'"'+":"+'"'+"成功"+'"'+
                "}";
    }catch (Exception e){
        e.printStackTrace();
        //设置状态码 返回给微信
        response.setStatus(500);
        return "{"+
                '"'+ "code"+'"'+":"+'"'+"SUCCESS"+'"'+" "+
                '"'+ "message"+'"'+":"+'"'+"成功"+'"'+
                "}";
    }

    //设置状态码 返回给微信
    response.setStatus(200);
    return "{"+
            '"'+ "code"+'"'+":"+'"'+"SUCCESS"+'"'+" "+
            '"'+ "message"+'"'+":"+'"'+"成功"+'"'+
            "}";

}          
显示全文