前言:
而今朋友们对“微信支付jsapi的v3签名rsa”可能比较讲究,姐妹们都想要了解一些“微信支付jsapi的v3签名rsa”的相关知识。那么小编也在网摘上网罗了一些对于“微信支付jsapi的v3签名rsa””的相关资讯,希望大家能喜欢,姐妹们快快来学习一下吧!首先要申请微信的应用,在微信开放平台中建立移动应用,并在“接口信息”里面开通“微信支付”。
随后,把api证书、apiv3密钥申请好并把回调地址设置好
接下来直接上代码!
这里是用maven引用微信支付的依赖
<!-- 微信支付 --> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apache-httpclient</artifactId> <version>0.4.4</version> </dependency>
这里是获取预支付交易会话标识的代码部分
private CloseableHttpClient httpClient; private AutoUpdateCertificatesVerifier verifier; @Autowired private WxPayConfigServiceImpl wxPayConfigService; public void setup(String mchId, String appV3Key, String serialNo, String keyPath, String keyAlias) { try { KeyPair keyPair = WXKeyPairFactory.createPKCS12(keyPath, keyAlias, mchId); PrivateKey merchantPrivateKey = keyPair.getPrivate(); //使用自动更新的签名验证器,不需要传入证书 verifier = new AutoUpdateCertificatesVerifier( new WechatPay2Credentials(mchId, new PrivateKeySigner(serialNo, merchantPrivateKey)), appV3Key.getBytes(StandardCharsets.UTF_8)); httpClient = WechatPayHttpClientBuilder.create() .withMerchant(mchId, serialNo, merchantPrivateKey) .withValidator(new WechatPay2Validator(verifier)) .build(); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } /** * 微信APP支付 * * @param desc 订单描述 * @param outTradeNo 订单号 * @param total 金额(单位为分) * @return Client * @throws Exception */ @Override public String createOrder(String desc, String outTradeNo, int total) throws Exception { // 用于判断商户平台或商家服务 String appId = "";// 应用ID String mchId = "";// 商户号 String serialNo = "";// 商户证书序列号 String appV3Key = "";// API V3密钥 String keyPath = "";// 商家平台证书路径 String keyAlias = "Tenpay Certificate";// 证书的别名,这里是固定值 String notifyUrl = "";// 回调地址 setup(mchId, appV3Key, serialNo, keyPath, keyAlias); try { HttpPost httpPost = new HttpPost(";); httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-type", "application/json; charset=utf-8"); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectMapper objectMapper = new ObjectMapper(); ObjectNode rootNode = objectMapper.createObjectNode(); rootNode.put("mchid", mchId) .put("appid", appId) .put("notify_url", notifyUrl) .put("description", desc) .put("out_trade_no", outTradeNo); rootNode.putObject("amount") .put("total", total); objectMapper.writeValue(bos, rootNode); httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8")); CloseableHttpResponse response = httpClient.execute(httpPost); String bodyAsString = EntityUtils.toString(response.getEntity()); JSONObject jsonObject = JSON.parseObject(bodyAsString); return (String) jsonObject.get("prepay_id"); } catch (IOException e) { e.printStackTrace(); } return null; }
生成签名部分
/** * APP支付 V3 SHA256withRSA 签名. * * @param AppId 应用id * @param timestamp 当前时间戳 因为要配置到TOKEN 中所以 签名中的要跟TOKEN 保持一致 * @param nonceStr 随机字符串 要和TOKEN中的保持一致 * @param prepayId 预支付交易会话ID * @param mchId 商户号 * @param keyPath 支付证书 * @param keyAlias 证书的别名 * @return the string */ @SneakyThrows public static String generateAPPSignRSA(String AppId, long timestamp, String nonceStr, String prepayId,String mchId, String keyPath, String keyAlias) { KeyPair keyPair = WXKeyPairFactory.createPKCS12(keyPath, keyAlias, mchId); String signatureStr = Stream.of(AppId, String.valueOf(timestamp), nonceStr, prepayId) .collect(Collectors.joining("\n", "", "\n")); Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(keyPair.getPrivate()); sign.update(signatureStr.getBytes(StandardCharsets.UTF_8)); return Base64Utils.encodeToString(sign.sign()); }
回调验证部分代码
// 微信支付回调 @PostMapping("/notify") public Map<String, String> wechatCallback(HttpServletRequest request, HttpServletResponse response) { Map<String, String> map = new HashMap<>(2); try { //微信返回的请求体 String body = WXPayUtil.getRequestBody(request); //如果验证签名序列号通过 if (wxAppPayService.verifiedSign(request, body)) { //微信支付通知实体类 WxPayNotify payNotify = JSONObject.parseObject(body, WxPayNotify.class); //如果支付成功 if ("TRANSACTION.SUCCESS".equals(payNotify.getEventType())) { //通知资源数据 WxResourceVo resource = payNotify.getResource(); //解密后资源数据 String apiV3Key = wxPayConfigService.selectWechatMerchantApiV3Key(); String notifyResourceStr = WXPayUtil.decryptResponseBody(resource.getAssociatedData(), resource.getNonce(), resource.getCiphertext(), apiV3Key); //通知资源数据对象 WxNotifyResourceVo notifyResourceVo = JSONObject.parseObject(notifyResourceStr, WxNotifyResourceVo.class); String outTradeNo = notifyResourceVo.getOutTradeNo(); String transactionId = notifyResourceVo.getTransactionId(); //逻辑实现 //do something int res = 1; if (res == 1){ //通知微信正常接收到消息,否则微信会轮询该接口 map.put("code", "SUCCESS"); map.put("message", "成功"); }else{ map.put("code", "FAIL"); map.put("message", "失败"); response.setStatus(416); } } else { map.put("code", "FAIL"); map.put("message", "失败"); response.setStatus(416); } //通知微信正常接收到消息,否则微信会轮询该接口 return map; } } catch (Exception e) { e.printStackTrace(); } map.put("code", "FAIL"); map.put("message", "失败"); response.setStatus(416); return map; }
验证部分代码
/** * 验签 * @param request request请求 * @param body 微信返回请求体 * @return true,false */ @Override public boolean verifiedSign(HttpServletRequest request,String body){ boolean result = false; try{ String appId = "";// 应用ID String mchId = "";// 商户号 String serialNo = "";// 商户证书序列号 String appV3Key = "";// API V3密钥 String keyPath = "";// 商家平台证书路径 String keyAlias = "Tenpay Certificate";// 证书的别名,这里是固定值 //微信返回的证书序列号 String resSerialNo = request.getHeader("Wechatpay-Serial"); //微信返回的随机字符串 String nonceStr = request.getHeader("Wechatpay-Nonce"); //微信返回的时间戳 String timestamp = request.getHeader("Wechatpay-Timestamp"); //微信返回的签名 String wechatSign = request.getHeader("Wechatpay-Signature"); KeyPair keyPair = WXKeyPairFactory.createPKCS12(keyPath, keyAlias, mchId); PrivateKey merchantPrivateKey = keyPair.getPrivate(); //组装签名字符串 String signStr = Stream.of(timestamp, nonceStr, body) .collect(Collectors.joining("\n", "", "\n")); //使用自动更新的签名验证器,不需要传入证书 verifier = new AutoUpdateCertificatesVerifier( new WechatPay2Credentials(mchId, new PrivateKeySigner(serialNo, merchantPrivateKey)), appV3Key.getBytes(StandardCharsets.UTF_8)); result = verifier.verify(resSerialNo, signStr.getBytes(StandardCharsets.UTF_8), wechatSign); }catch (Exception e){ e.printStackTrace(); System.out.println("e:" + e); } return result; }
封装的函数
/** * 获取请求报文 * @param request * @return * @throws IOException */ public static String getRequestBody(HttpServletRequest request) throws IOException { ServletInputStream stream = null; BufferedReader reader = null; StringBuffer sb = new StringBuffer(); try { stream = request.getInputStream(); // 获取响应 reader = new BufferedReader(new InputStreamReader(stream)); String line; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { throw new IOException("读取返回支付接口数据流出现异常!"); } finally { reader.close(); } return sb.toString(); }
解码部分代码
/** * 解密 * @param associatedData 附加数据包 * @param nonce 加密使用的随机串 * @param ciphertext Base64编码后的密文 * @param apiV3Key 支付apiV3秘钥 * @return */ public static String decryptResponseBody(String associatedData, String nonce, String ciphertext, String apiV3Key) { try { Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); SecretKeySpec key = new SecretKeySpec(apiV3Key.getBytes("UTF-8"), "AES"); GCMParameterSpec spec = new GCMParameterSpec(128, nonce.getBytes("UTF-8")); cipher.init(Cipher.DECRYPT_MODE, key, spec); cipher.updateAAD(associatedData.getBytes("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 (Exception e) { e.printStackTrace(); } return null; }
版权声明:
本站文章均来自互联网搜集,如有侵犯您的权益,请联系我们删除,谢谢。
标签: #微信支付jsapi的v3签名rsa