電商收付通系列②播瞳,獲取微信支付平臺證書

1掸刊、介紹

微信支付平臺證書是指由微信支付負(fù)責(zé)申請的,包含微信支付平臺標(biāo)識赢乓、公鑰信息的證書忧侧。商戶可以使用平臺證書中的公鑰進(jìn)行驗簽。注意骏全,這里的證書區(qū)別于商戶API證書,商戶API證書是直接從商戶后臺下載查看的尼斧,而微信支付平臺證書是通過電商收付通的證書接口獲取的姜贡。

2、作用

這個證書有什么用棺棵?我們需要獲取到這個證書相關(guān)的序列號和公鑰楼咳,后續(xù)請求一系列接口時需要將微信支付平臺證書序列號放在請求頭里熄捍,而公鑰是為了驗證應(yīng)答或回調(diào)的簽名,以確保應(yīng)答或回調(diào)是由微信支付發(fā)送母怜。

3余耽、獲取微信支付平臺證書

注意:不同的商戶,對應(yīng)的微信支付平臺證書是不一樣的苹熏,平臺證書會周期性更換碟贾。建議商戶定時通過API下載新的證書,不要依賴人工更換證書轨域。微信支付的平臺證書序列號位于HTTP頭Wechatpay-Serial袱耽。驗證簽名前,請商戶先檢查序列號是否跟商戶當(dāng)前所持有的微信支付平臺證書的序列號一致干发。如果不一致朱巨,請重新獲取證書。否則枉长,簽名的私鑰和證書不匹配冀续,將無法成功驗證簽名。雙手奉上獲取微信支付

/**
 * @date 2020-03-18 15:06
 * @description
 */
public class Certificate {

private static final Logger logger = LoggerFactory.getLogger(Certificate.class);
/**
     * 獲取微信支付平臺證書
     * @param merchantId
     * @param timeout
     * @param serialNo
     * @param mchPrivateKeyPath
     * @param APIv3Key
     * @param savePath
     * @return
     */
public static List<X509Certificate> getCertByAPI(String merchantId, int timeout, String serialNo, String mchPrivateKeyPath,String wechatPubKeyPath,String APIv3Key,String savePath) {
    String result = "";
    //創(chuàng)建http請求
    HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com
/v3/certificates");
    httpGet.addHeader("Content-Type", "application/json");
    httpGet.addHeader("Accept", "application/json");

    String authorization = SignUtils.authorization("GET", "/v3/certificates", merchantId, serialNo, "", mchPrivateKeyPath);

    //設(shè)置認(rèn)證信息
    httpGet.setHeader("Authorization", authorization);

    //設(shè)置請求器配置:如超時限制等
    RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000).build();
    httpGet.setConfig(config);
    List<X509Certificate> x509Certs = new ArrayList<X509Certificate>();
    try {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        int statusCode = response.getStatusLine().getStatusCode();
        HttpEntity httpEntity = response.getEntity();
        result = EntityUtils.toString(httpEntity, "UTF-8");
        if(statusCode == 200){
            logger.info("下載平臺證書返回結(jié)果:"+result);
            Header[] timestampHeader = response.getHeaders("Wechatpay-Timestamp");
                Header[] nonceHeader = response.getHeaders("Wechatpay-Nonce");
                Header[] signatureHeader = response.getHeaders("Wechatpay-Signature");
                if (timestampHeader != null && timestampHeader.length > 0 &&
                        nonceHeader != null && nonceHeader.length > 0 &&
                        signatureHeader != null && signatureHeader.length > 0) {
                    // 驗證微信支付返回簽名
                    String wTimestamp = timestampHeader[0].getValue();
                    String wNonce = nonceHeader[0].getValue();
                    String wSign = signatureHeader[0].getValue();

                    logger.info("wTimestamp:{}必峰,wNonce:{}洪唐,wSign:{}", wTimestamp, wNonce, wSign);
                    // 拼裝待簽名串
                    StringBuffer ss = new StringBuffer();
                    ss.append(wTimestamp).append("\n");
                    ss.append(wNonce).append("\n");
                    ss.append(result).append("\n");
                    // 驗證簽名
                    if (SignUtils.v3VerifyRSA(ss.toString(), Base64.decodeBase64(wSign.getBytes()), wechatPubKeyPath)) {
                        List<CertificateItem> certList = new ArrayList<CertificateItem>();
                        JSONObject json = JSONObject.parseObject(result);
                        logger.info("查詢結(jié)果json字符串轉(zhuǎn)證書List:" + json.get("data"));
                        JSONArray jsonArray = (JSONArray) json.get("data");
                        for (int i = 0; i < jsonArray.size(); i++) {
                            CertificateItem certificateItem = new CertificateItem();
                            EncryptedCertificateItem encryptCertificate = new EncryptedCertificateItem();
                            JSONObject bo = JSONObject.parseObject(jsonArray.get(i).toString());
                            certificateItem.setSerial_no(bo.get("serial_no").toString());
                            certificateItem.setEffective_time(bo.get("effective_time").toString());
                            certificateItem.setExpire_time(bo.get("expire_time").toString());
                            JSONObject encryptBo = JSONObject.parseObject(bo.get("encrypt_certificate").toString());
                            encryptCertificate.setAlgorithm(encryptBo.get("algorithm").toString());
                            encryptCertificate.setNonce(encryptBo.get("nonce").toString());
                            encryptCertificate.setAssociated_data(encryptBo.get("associated_data").toString());
                            encryptCertificate.setCiphertext(encryptBo.get("ciphertext").toString());
                            certificateItem.setEncrypt_certificate(encryptCertificate);
                            certList.add(certificateItem);
                        }
                        logger.info("證書List:" + certList);

                        List<PlainCertificateItem> plainList = decrypt(certList, APIv3Key);
                        if (CollectionUtils.isNotEmpty(plainList)) {
                            logger.info("平臺證書開始保存");
                            x509Certs = saveCertificate(plainList, savePath);
                        }
                    }
                }
        }
          response.close();
          httpClient.close(); //throw
          return x509Certs;
      } catch (Exception e) {
          e.printStackTrace();
          logger.error("下載平臺證書返回結(jié)果:"+e);
      }
      return x509Certs;
  }

4、結(jié)果

1自点、接口返回的內(nèi)容是json串

{
  "data": [{
    "serial_no": "5157F09EFDC096DE15EBE81A47057A7232F1B8E1",
      "effective_time ": "2018-06-08T10:34:56+08:00",
      "expire_time ": "2018-12-08T10:34:56+08:00",
      "encrypt_certificate": {
      "algorithm": "AEAD_AES_256_GCM",
      "nonce": "61f9c719728a",
      "associated_data": "certificate",
      "ciphertext": "sRvt… "
      }
  }]
}

2桐罕、通過接口下載的微信支付平臺證書

上一篇:電商收付通系列①,對請求進(jìn)行簽名桂敛,拼接Authorization

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末功炮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子术唬,更是在濱河造成了極大的恐慌薪伏,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粗仓,死亡現(xiàn)場離奇詭異嫁怀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)借浊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評論 3 400
  • 文/潘曉璐 我一進(jìn)店門塘淑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚂斤,你說我怎么就攤上這事存捺。” “怎么了?”我有些...
    開封第一講書人閱讀 170,031評論 0 366
  • 文/不壞的土叔 我叫張陵捌治,是天一觀的道長岗钩。 經(jīng)常有香客問我,道長肖油,這世上最難降的妖魔是什么兼吓? 我笑而不...
    開封第一講書人閱讀 60,334評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮森枪,結(jié)果婚禮上视搏,老公的妹妹穿的比我還像新娘。我一直安慰自己疲恢,他們只是感情好凶朗,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著显拳,像睡著了一般棚愤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上杂数,一...
    開封第一講書人閱讀 52,895評論 1 314
  • 那天宛畦,我揣著相機(jī)與錄音,去河邊找鬼揍移。 笑死次和,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的那伐。 我是一名探鬼主播踏施,決...
    沈念sama閱讀 41,300評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼罕邀!你這毒婦竟也來了畅形?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,264評論 0 277
  • 序言:老撾萬榮一對情侶失蹤诉探,失蹤者是張志新(化名)和其女友劉穎日熬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肾胯,經(jīng)...
    沈念sama閱讀 46,784評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡竖席,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了敬肚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毕荐。...
    茶點(diǎn)故事閱讀 40,989評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖艳馒,靈堂內(nèi)的尸體忽然破棺而出憎亚,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,649評論 5 351
  • 正文 年R本政府宣布虽填,位于F島的核電站,受9級特大地震影響曹动,放射性物質(zhì)發(fā)生泄漏斋日。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評論 3 336
  • 文/蒙蒙 一墓陈、第九天 我趴在偏房一處隱蔽的房頂上張望恶守。 院中可真熱鬧,春花似錦贡必、人聲如沸兔港。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衫樊。三九已至,卻和暖如春利花,著一層夾襖步出監(jiān)牢的瞬間科侈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評論 1 275
  • 我被黑心中介騙來泰國打工炒事, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留臀栈,地道東北人。 一個月前我還...
    沈念sama閱讀 49,452評論 3 379
  • 正文 我出身青樓挠乳,卻偏偏與公主長得像权薯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子睡扬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評論 2 361

推薦閱讀更多精彩內(nèi)容