微信商户支付apiV3平台证书相关

在微信支付商户配置中获取所需商户证书支付证书文件

Method 1 : 通过商户证书获取平台证书放入header直接请求转账接口

进入上面图片中证书所在目录,执行以下命令查看证书序列号

openssl x509 -in apiclient_cert.pem -inform der -noout -text

返回

serial=123456
public static void main(String[] args) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException, IOException {
        String url = "https://api.mch.weixin.qq.com/v3/certificates";
        String schema = "WECHATPAY2-SHA256-RSA2048 ";

        HttpGet httpGet = new HttpGet(url);
        String token = getToken("GET", HttpUrl.parse(url),"");
        httpGet.addHeader("Accept", "application/json");
        httpGet.setHeader("Authorization",schema + token);
        CloseableHttpClient client = HttpClients.createDefault();
        CloseableHttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();

        String result = null;
        if (entity != null) {
            result = EntityUtils.toString(entity, "UTF8");
            System.out.println(">>>>>>>>>>>>>>>" + result);
        }
        response.close();
    }

    private static String getToken(String method, HttpUrl url, String body) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, FileNotFoundException {
        String nonceStr = "随机32位字符串";
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("utf-8"));

        return "mchid=\"" + "开通支付的商户号" + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + serial + "\","
                + "signature=\"" + signature + "\"";
    }

    private static String sign(byte[] message) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, FileNotFoundException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        File file = new File("apiclient_key.pem");
        InputStream inputStream = new FileInputStream(file);

        sign.initSign(PemUtils.loadPrivateKey(inputStream));
        sign.update(message);

        return Base64.getEncoder().encodeToString(sign.sign());
    }

    private static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }

        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

解密响应的json

/**
     * 解密响应体.
     *
     * @param apiV3Key       API V3 KEY  API v3密钥 商户平台设置的32位字符串
     * @param associatedData  response.body.data[i].encrypt_certificate.associated_data
     * @param nonce          response.body.data[i].encrypt_certificate.nonce
     * @param ciphertext     response.body.data[i].encrypt_certificate.ciphertext
     * @return the string
     * @throws GeneralSecurityException the general security exception
     */
    public static String decryptResponseBody(String apiV3Key, String associatedData, String nonce, String ciphertext) {
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

            SecretKeySpec key = new SecretKeySpec(apiV3Key.getBytes(StandardCharsets.UTF_8), "AES");
            GCMParameterSpec spec = new GCMParameterSpec(128, nonce.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));

            byte[] bytes;
            try {
                bytes = cipher.doFinal(Base64Utils.decodeFromString(ciphertext));
            } catch (GeneralSecurityException e) {
                throw new IllegalArgumentException(e);
            }
            return new String(bytes, StandardCharsets.UTF_8);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(e);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw new IllegalArgumentException(e);
        }
    }

Method2 :通过sdk自动初始化平台证书发起请求

	public WxPayService getWxPayServiceV2(WechatMerchantEntity wechatMerchant) {
        //先确定平台端的商户配置
        WechatMerchantEntity serviceMerchant = wechatMerchantDAO.getByMerchantNoAndAppid(wechatMerchant.getMerchantNo(),wechatMerchant.getAppId());
        List<CompanyAttributeEntity> companyAttributes = companyAttributeDAO.selectByMerchatId(serviceMerchant.getId());
        if (CollUtil.isEmpty(companyAttributes)) {
            throw new BusinessException(ResultEnum.WX_PAY_CONFIG_NOT_EXIST);
        }
        Map<String, CompanyAttributeEntity> companyAttributeMap = companyAttributes.stream()
                .collect(Collectors.toMap(CompanyAttributeEntity::getConfigKey, companyAttribute -> companyAttribute));
        WxPayService wxPayService = new WxPayServiceImpl();
        WxPayConfig wxPayConfig = new WxPayConfig();
        //平台appid
        wxPayConfig.setAppId(serviceMerchant.getAppId());
        //服务商商户号
        wxPayConfig.setMchId(serviceMerchant.getMerchantNo());

        //服务商的秘钥
        wxPayConfig.setMchKey(StringUtils.trimToNull(companyAttributeMap.get(MCH_KEY).getValueText()));

        //apiV3 秘钥值
        wxPayConfig.setApiV3Key(StringUtils.trimToNull(companyAttributeMap.get(MCH_KEY).getValueText()));
        //apiV3 证书序列号值
        wxPayConfig.setCertSerialNo(StringUtils.trimToNull(companyAttributeMap.get(SERIAL_NO).getValueText()));
        //服务商证书
        if (companyAttributeMap.get("apiclient_cert.p12") != null &&
                companyAttributeMap.get(CERTIFICATE).getValueBlob() != null) {
            try {
                byte[] key = new byte[8096];
                int read = new ByteArrayInputStream(companyAttributeMap.get("apiclient_cert.p12").getValueBlob()).read(key);
                wxPayConfig.setKeyContent(key);
                log.info("----->apiclient_cert.p12证书文件长度:[{}]<----", read);

                String path = "apiclient_key.pem";
                File file = new File(path);
                InputStream inputStream = new FileInputStream(file);

                //apiclient_key.pem证书文件内容的字节数组.
                wxPayConfig.setPrivateKeyContent(streamToByte(inputStream));
                log.info("----->apiclient_key证书文件长度:[{}]<----", wxPayConfig.getPrivateKeyContent().length);

				String path2 = "apiclient_cert.pem";
                File file2 = new File(path2);
                InputStream inputStream2 = new FileInputStream(file2);
                //apiclient_cert.pem证书文件内容的字节数组.
                wxPayConfig.setPrivateCertContent(streamToByte(inputStream2));
            } catch (IOException e) {
                log.error(" io exception", e);
            }
        }
        wxPayService.setConfig(wxPayConfig);
        return wxPayService;
    }
        
	public static byte[] streamToByte(InputStream is) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] bytes = new byte[1024];
        int i = -1;
        try {
            //将输入流中的数据读到bytes中,i表示bytes的长度,当读完时i=-1退出循环
            while ((i = is.read(bytes)) != -1) {
                //将指定的字节数组从偏移量off开始,写入i个字节到输出流
                bos.write(bytes, 0, i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bos.toByteArray();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值