微信支付WechatPay-API-v3案例

最近微信商戶給老闆推送了一個支付即服務的功能,老闆看到了就想要,好吧,那就搞吧,看流程挺簡單的

但是是微信支付V3版API文檔,裏面和之前V2還是有出入的,

相較於的之前微信支付API,主要區別是:

  • 遵循統一的Restful的設計風格

  • 使用JSON作爲數據交互的格式,不再使用XML

  • 使用基於非對稱密鑰的SHA256-RSA的數字簽名算法,不再使用MD5或HMAC-SHA256

  • 不再要求HTTPS客戶端證書

  • 使用AES-256-GCM,對回調中的關鍵信息進行加密保護

剛開始摸這個的時候一臉霧水,看了一天文檔後,嗯,基本看懂了他的流程,流程我就不多說了,可以去看文檔,寫的還是比較詳細的

https://wechatpay-api.gitbook.io/wechatpay-api-v3/

老規矩,我就直接上碼吧!

下文可能會出現的參數

String keyPath = "apiclient_key.pem";// 私鑰證書
String mchId = "";
String serialNo = "";//公鑰證書序列號
String body = ""; // 請求報文主體,沒有查詢參數。
String platformCertPath = "WXapiclient_cert.pem";//微信平臺證書 驗證簽名時需要使用

案例一 :獲取平臺證書(如果所需要的API沒有涉及到敏感數據,可以不調用這個API,但我們以這個爲案例)

    @Test
    public void v3Get() {
        // 獲取平臺證書列表
        try {
            Map<String, Object> result = WxPayApi.v3Execution(
                    RequestMethod.GET,
                    WxDomain.CHINA.toString(),
                    WxApiType.GET_CERTIFICATES.toString(),
                    mchId,
                    serialNo,
                    keyPath,
                    body
            );
            String serialNumber = MapUtil.getStr(result, "serialNumber");
            String body = MapUtil.getStr(result, "body");
            int status = MapUtil.getInt(result, "status");

            System.out.println("serialNumber:" + serialNumber);
            System.out.println("status:" + status);
            System.out.println(result);
            // 根據證書序列號查詢對應的證書來驗證簽名結果
            boolean verifySignature = WxPayKit.verifySignature(result, platformCertPath);

            System.out.println("verifySignature:" + verifySignature + "\nbody:" + body);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

案例二:證書報文解密

    @Test
    public void aesTest() throws GeneralSecurityException {
        String associatedData = "";
        String nonce = "";
        String ciphertext = "";           
        String saveCertPath = "";
        //apikey3是V3API密鑰
        AesUtil aesUtil = new AesUtil(apiKey3.getBytes(StandardCharsets.UTF_8));
        // 平臺證書密文解密
        //associatedData,nonce,ciphertext這個三個是上面獲取平臺證書的幾個參數
        String publicKey = aesUtil.decryptToString(
            associatedData.getBytes(StandardCharsets.UTF_8),
            nonce.getBytes(StandardCharsets.UTF_8),
            ciphertext
        );
        System.out.println("平臺證書公鑰明文:" + publicKey);
        // 保存證書
        //saveCertPath 保存平臺證書的路徑 例:E:/cert/WXapiclient_cert.pem
        FileWriter writer = new FileWriter(saveCertPath);
        writer.write(publicKey);
        // 獲取平臺證書序列號
        X509Certificate certificate = PayKit.getCertificate(new                         
        ByteArrayInputStream(publicKey.getBytes()));
        System.out.println(certificate.getSerialNumber().toString(16).toUpperCase());
    }

案例三:帶敏感信息請求(就是API參數中有敏感數據需要加密的,和案例一區別就是案例三加了平臺證書序列號)

    @Test
    public void test() throws Exception {
        // 帶有敏感信息接口
        try {
            //V3都是用json了,所以用json封裝參數,參數詳情
            //https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/smartguide/chapter3_1.shtml
            JSONObject json = new JSONObject()
                    .set("corpid", "")
                    .set("store_id", 123456)
                    .set("userid", "Ta")
                    .set("name", rsaEncryptOAEP("姓名"))
                    .set("mobile", rsaEncryptOAEP("手機號"))
                    .set("qr_code", "")
                    .set("avatar", "");
            String body = JSONUtil.toJsonStr(json);

            Map<String, Object> result = WxPayApi.v3Execution(
                    RequestMethod.POST,
                    WxDomain.CHINA.toString(),
                    WxApiType.SMART_GUIDE_GUIDES.toString(),
                    mchId,
                    serialNo,
                    platSerialNumber,//平臺證書序列號
                    keyPath,
                    body
            );
            System.out.println(result);
            System.out.println(JSONUtil.toJsonStr(result));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 加密敏感信息
     * @param data
     * @return
     * @throws Exception
     */
    private String rsaEncryptOAEP(String data) throws Exception {
        X509Certificate certificate =         
        PayKit.getCertificate(FileUtil.getInputStream(platformCertPath));
        String encrypt = PayKit.rsaEncryptOAEP(data, certificate);
        return encrypt;
    }

 

如果API中沒有涉及到敏感數據,可直接ctrl+c+v案例一,改一下請求地址,然後像案例三那樣用json封裝參數就行了

如果API中有涉及到敏感數據,就要先調用獲取平臺證書列表,獲取到平臺證書序列號,然後再請求

案例二主要是用於保存平臺證書,用來驗證簽名

如果接口中帶有參數,可使用String.format(WxApiType.SMART_GUIDE_GUIDES_ASSIGN.toString(), "123")

也可以通過https://myssl.com/cert_decode.html把api證書拖進去查看相關信息

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章