成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

微信支付V3版本集成詳解【避坑指南】

開發 后端
V3版本的集成,官方文檔還是比較清晰的,但各類的配置,一個不小心就掉坑里半天爬不出來。趁著思路清晰,特此記錄一下。

最近對項目中的微信支付功能做了升級,之前使用的是V2版本。V2版本目前還可以使用,但已暫停更新。V3版本的集成,官方文檔還是比較清晰的,但各類的配置,一個不小心就掉坑里半天爬不出來。趁著思路清晰,特此記錄一下。

V2版本參數格式是xml格式,不太好維護,V3版本已改成json格式。

V2版本的簽名是拼在參數里面的,V3版本校驗都放在配置類里面了,更加方便靈活。

前置條件

官方文檔:
https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml

1、微信開放平臺 – APP支付

  • 注冊APP,獲取appId appSecret等信息

2、微信公眾平臺 – (微信公眾號 小程序) 微信內支付

  • 開通賬號,申請支付功能,綁定商戶平臺
  • 配置域名等

3、瀏覽器H5支付

  • 申請權限:微信支付商戶平臺—>產品中心—>H5支付—>申請開通
  • 配置:產品中心—>開發配置—>H5支付

4、微信商戶平臺

  •  商戶號
  • API證書密鑰及證書序列號

  • API v3密鑰

代碼集成

微信提供兩種集成方式:wechatpay-java(推薦);wechatpay-apache-httpclient,以推薦的方式為例:

<dependency>
  <groupId>com.github.wechatpay-apiv3</groupId>
  <artifactId>wechatpay-java</artifactId>
  <version>0.2.5</version>
</dependency>

配置初始化 – 加載微信支付平臺證書

使用自動更新平臺證書的配置類 RSAAutoCertificateConfig。注:每個商戶號只能創建一個 RSAAutoCertificateConfig。

代碼實現,將配置交由Spring統一管理,單例模式保證初始化一次。

@Configuration
public class WXPayConfig {

    private Config config;

    @PostConstruct
    public void init(){
        config =
                new RSAAutoCertificateConfig.Builder()
                        .merchantId(WXPayConstants.MCHID)
                        .privateKey(WXPayConstants.PRIVATE_KEY)
                        .merchantSerialNumber(WXPayConstants.MERCHANT_SERIAL_NUMBER)
                        .apiV3Key(WXPayConstants.API_V3_KEY)
                        .build();
    }

    @Bean("h5Service")
    public H5Service getH5Service(){
        // H5支付
        return new H5Service.Builder().config(config).build();
    }

    @Bean("jsService")
    public JsapiServiceExtension getJsService(){

        // 微信js支付
        return new JsapiServiceExtension.Builder()
                        .config(config)
                        .signType("RSA") // 不填則默認為RSA
                        .build();
    }

    @Bean("appService")
    public AppServiceExtension getAppService() {
        // App支付
        return new AppServiceExtension.Builder().config(config).build();
    }

    @Bean("NotificationParser")
    public NotificationParser getNotificationParser(){
        // 支付回調的解析器
        return new NotificationParser((NotificationConfig)config);
    }
}

獲取支付請求信息

APP下單

/**
 * 獲取微信支付參數(APP)
 */
public WechatPayDTO getWechatAppPayParam(BigDecimal money, String orderNumber, String notifyUrl) throws Exception {
    // 下單
    com.wechat.pay.java.service.payments.app.model.PrepayRequest request = new com.wechat.pay.java.service.payments.app.model.PrepayRequest();
    com.wechat.pay.java.service.payments.app.model.Amount amount = new com.wechat.pay.java.service.payments.app.model.Amount();
    amount.setTotal(Integer.parseInt(totalFee(money)));
    amount.setCurrency("CNY");
    request.setAmount(amount);
    request.setAppid(WXPayConstants.APPID);
    request.setMchid(WXPayConstants.MCHID);
    request.setDescription("");
    request.setNotifyUrl(notifyUrl);
    request.setOutTradeNo(orderNumber);
    com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse response = appService.prepayWithRequestPayment(request);
    return WechatPayDTO.builder()
            .appid(response.getAppid())
            .partnerid(response.getPartnerId())
            .prepayid(response.getPrepayId())
            .packageVal(response.getPackageVal())
            .timestamp(response.getTimestamp())
            .noncestr(response.getNonceStr())
            .sign(response.getSign())
            .build();
}

公眾號 小程序下單

/**
 * 獲取微信支付參數(公眾號 小程序)
 */
public WechatPayDTO getWechatJSAPIPayParam(String openid, BigDecimal money, String orderNumber, String notifyUrl) throws Exception {
    // 下單
    com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
    com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
    amount.setTotal(Integer.parseInt(totalFee(money)));
    amount.setCurrency("CNY");
    request.setAmount(amount);
    request.setAppid(WXPayConstants.PUBLIC_APPID);
    request.setMchid(WXPayConstants.MCHID);
    request.setDescription("");
    request.setNotifyUrl(notifyUrl);
    request.setOutTradeNo(orderNumber);
    Payer payer = new Payer();
    payer.setOpenid(openid);
    request.setPayer(payer);
    PrepayWithRequestPaymentResponse response = jsService.prepayWithRequestPayment(request);
    logger.info("JS支付參數:{}", response.toString());
    return WechatPayDTO.builder()
            .appid(response.getAppId())
            .packageVal(response.getPackageVal())
            .timestamp(response.getTimeStamp())
            .noncestr(response.getNonceStr())
            .signType(response.getSignType())
            .paySign(response.getPaySign())
            .build();
}

H5下單

/**
  * 獲取微信H5支付連接
	*/
public String getWechatH5PayUrl(BigDecimal money, String orderNumber, String notifyUrl) {
      // 下單
      PrepayRequest request = new PrepayRequest();
      Amount amount = new Amount();
      amount.setTotal(Integer.parseInt(totalFee(money)));
      amount.setCurrency("CNY");
      request.setAmount(amount);
      SceneInfo sceneInfo = new SceneInfo();
      sceneInfo.setPayerClientIp("");
      request.setSceneInfo(sceneInfo);
      request.setAppid(WXPayConstants.PUBLIC_APPID);
      request.setMchid(WXPayConstants.MCHID);
      request.setDescription("");
      request.setNotifyUrl(notifyUrl);
      request.setOutTradeNo(orderNumber);
      // 調用接口
      PrepayResponse response = h5Service.prepay(request);
      return response.getH5Url();
}

支付回調

獲取 HTTP 請求頭中的以下值,構建 RequestParam 。

  • Wechatpay-Signature
  • Wechatpay-Nonce
  • Wechatpay-Timestamp
  • Wechatpay-Serial
  • Wechatpay-Signature-Type

獲取 HTTP 請求體 body。切記不要用 JSON 對象序列化后的字符串,避免驗簽的 body 和原文不一致。

根據解密后的通知數據數據結構,構造解密對象類 DecryptObject 。支付結果通知解密對象類為 Transaction,退款結果通知解密對象類為 RefundNotification

初始化 RSAAutoCertificateConfig(已在前文統一初始化)。

初始化 NotificationParser(已在前文統一初始化)。

使用請求參數 requestParam 和 DecryptObject.class ,調用 parser.parse 驗簽并解密報文。

RequestParam requestParam = new RequestParam.Builder()
      .serialNumber(request.getHeader("Wechatpay-Serial"))
      .nonce(request.getHeader("Wechatpay-Nonce"))
      .signature(request.getHeader("Wechatpay-Signature"))
      .timestamp(request.getHeader("Wechatpay-Timestamp"))
      .signType(request.getHeader("Wechatpay-Signature-Type"))
      .body(body)
      .build();

Transaction transaction = notificationParser.parse(requestParam, Transaction.class);
if (Objects.equals(transaction.getTradeState(), Transaction.TradeStateEnum.SUCCESS)){
  //處理業務邏輯
  //通知微信支付成功
  wechatPayUtil.paySuccessful(response);
}
責任編輯:姜華 來源: 今日頭條
相關推薦

2020-10-27 10:40:18

JavaAPI V3支付

2016-03-04 10:29:51

微信支付源碼

2024-04-03 12:30:00

C++開發

2024-04-24 13:45:00

2025-03-13 06:50:50

2021-02-26 00:46:11

CIO數據決策數字化轉型

2023-05-24 10:06:42

多云實踐避坑

2021-05-08 12:30:03

Pythonexe代碼

2022-03-04 18:11:16

信服云

2021-05-07 21:53:44

Python 程序pyinstaller

2021-02-22 17:00:31

Service Mes微服務開發

2011-12-02 09:59:29

API

2010-07-30 13:17:33

NFS V3

2021-04-28 09:26:25

公有云DTS工具

2016-04-21 11:12:25

云鎖cloud云計算

2020-12-16 10:00:59

Serverless數字化云原生

2018-01-20 20:46:33

2020-06-12 11:03:22

Python開發工具

2018-03-26 11:14:13

程序猿bug代碼

2019-02-12 15:07:42

屏幕參數PC
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 蜜桃精品视频在线 | 毛片a级 | 7777精品伊人久久精品影视 | 国产综合久久久久久鬼色 | 久久伊人影院 | 精品日韩 | 久久精品女人天堂av | 国产精品久久国产精品久久 | 激情一区二区三区 | 欧美成年黄网站色视频 | 日韩在线一区二区 | 日本三级在线 | 精品久久国产 | 中文字幕在线视频免费视频 | 日本在线免费观看 | 国产精品99久久久久久宅男 | 国产福利资源 | 久久久久国产精品一区二区 | 最新国产精品 | 天堂久久久久久久 | 三级视频在线观看 | 成人不卡一区二区 | 久久精品亚洲国产 | 国产欧美精品一区二区三区 | av网站免费| 国产精品久久久久一区二区三区 | 一区二区三区四区在线视频 | 亚洲午夜精品视频 | 国产精品久久久久久久免费观看 | 亚洲午夜视频 | 成人免费共享视频 | www.youjizz.com日韩| 久久三级av | 亚洲精品一区二三区不卡 | 在线观看国产视频 | 欧美一区二区久久 | 在线观看视频91 | 午夜手机在线 | www亚洲成人 | 久久久成人精品 | 成人精品久久日伦片大全免费 |