微信小程序jsapi v3支付流程和如何实现代码 需要的配置参数有哪些
1条回答 默认 最新
- 林间6 2023-08-09 14:56关注
参数:
wx-pay: v3: #微信关联的小程序的appid appId: xxxxx #微信支付商户号 mchId: xxxxxx #微信支付证书序列号 serialnumber: xxxxxx #微信支付apiv3的密钥 apiKey3: xxxxx #微信支付证书 certKeyPath: /cert/xxxxx.pem #微信支付回调商户线上地址api notifyUrl: https://xxxxx/pay/callback #微信支付关闭订单api closeOrderUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}/close #微信支付小程序预下单api jsApiUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi #微信支付订单查询api queryOrder: https://api.mch.weixin.qq.com/v3/pay/transactions/id/
初始化服务
@Service @Transactional public class SysPayServiceImpl implements SysPayService { private static final Logger log = LoggerFactory.getLogger(SysPayServiceImpl.class); @Autowired private WxPayConfig wxPayConfig; //微信专业httpClient private static CloseableHttpClient httpClient; //生成签名用 private static Sign sign; //证书管理器 private static CertificatesManager certificatesManager; @Autowired private SysOrderDao sysOrderDao; //初始化微信支付的参数 @PostConstruct public void init() throws Exception { //获取商户私钥 PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(getFileInputStream(wxPayConfig.getCertKeyPath())); // 获取证书管理器实例 certificatesManager = CertificatesManager.getInstance(); sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, merchantPrivateKey.getEncoded(), null); // 向证书管理器增加需要自动更新平台证书的商户信息 certificatesManager.putMerchant(wxPayConfig.getMchId(), new WechatPay2Credentials(wxPayConfig.getMchId(), new PrivateKeySigner(wxPayConfig.getSerialnumber(), merchantPrivateKey)), wxPayConfig.getApiKey3().getBytes(StandardCharsets.UTF_8)); // 从证书管理器中获取verifier Verifier verifier = certificatesManager.getVerifier(wxPayConfig.getMchId()); //用于构造HttpClient WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create() .withMerchant(wxPayConfig.getMchId(), wxPayConfig.getSerialnumber(), merchantPrivateKey) .withValidator(new WechatPay2Validator(verifier)); httpClient = builder.build(); } /** * 使用getResourceAsStream直接从resources根路径下获取文件流 * @param path */ private InputStream getFileInputStream(String path) { InputStream in = this.getClass().getResourceAsStream(path); return in; } }
预生成订单
//预订单生成返回给小程序请求参数 @Override public AjaxResult prePay(WxPayDto dto) { log.info("微信小程序支付JSAPI预下单开始------"); AjaxResult ajaxResult = AjaxResult.success(); JSONObject obj = new JSONObject(); //应用ID obj.put("appid", wxPayConfig.getAppId()); //直连商户号 obj.put("mchid", wxPayConfig.getMchId()); //商品描述 obj.put("description", dto.getDescription()); //商户订单号 obj.put("out_trade_no", dto.getOrderCode()); //通知地址 obj.put("notify_url", wxPayConfig.getNotifyUrl()); //附加数据 查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段。 Map<String, String> attach = new HashMap<>(); attach.put("orderCode", dto.getOrderCode()); obj.put("attach", JSON.toJSONString(attach)); //订单金额 JSONObject amount = new JSONObject(); amount.put("total", dto.getPrice()); obj.put("amount", amount); //支付者 JSONObject payer = new JSONObject(); payer.put("openid", dto.getOpenId()); obj.put("payer", payer); log.info("微信小程序支付JSAPI预下单请求参数:{}" + obj.toJSONString()); HttpPost httpPost = new HttpPost(wxPayConfig.getJsApiUrl()); httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-type", "application/json; charset=utf-8"); httpPost.setEntity(new StringEntity(obj.toJSONString(), "UTF-8")); String bodyAsString ; try { if(httpClient == null){ log.info("微信小程序支付JSAPI预下单请求失败"); return AjaxResult.error("预下单失败,请重试,无法连接微信支付服务器!" ); } //执行请求 CloseableHttpResponse response = httpClient.execute(httpPost); bodyAsString = EntityUtils.toString(response.getEntity()); } catch (IOException e) { log.info("微信小程序支付JSAPI预下单请求失败{}", e.getMessage()); return AjaxResult.error("预下单失败,请重试!" + e.getMessage()); } String prePayId = JSONObject.parseObject(bodyAsString).getString("prepay_id"); if (prePayId == null){ String message = JSONObject.parseObject(bodyAsString).getString("message"); log.info("微信小程序支付JSAPI预下单请求失败{}", message); return AjaxResult.error("预下单失败,请重试!" + message); } //准备小程序端的请求参数 ajaxResult.put("appId", wxPayConfig.getAppId()); String timeStamp = String.valueOf(System.currentTimeMillis() / 1000); ajaxResult.put("timeStamp", timeStamp); String nonceStr = IdUtil.fastSimpleUUID(); ajaxResult.put("nonceStr", nonceStr); String packageStr = "prepay_id=" + prePayId; ajaxResult.put("package", packageStr); ajaxResult.put("signType", "RSA"); String signString = wxPayConfig.getAppId() + "\n" + timeStamp + "\n" + nonceStr + "\n" + packageStr + "\n"; ajaxResult.put("paySign", Base64.encode(sign.sign(signString.getBytes()))); return ajaxResult; }
回调
//微信支付回调通知 @Override public void callback(HttpServletRequest servletRequest, HttpServletResponse response) { log.info("----------->微信支付回调开始"); Map<String, String> map = new HashMap<>(12); String timeStamp = servletRequest.getHeader("Wechatpay-Timestamp"); String nonce = servletRequest.getHeader("Wechatpay-Nonce"); String signature = servletRequest.getHeader("Wechatpay-Signature"); String certSn = servletRequest.getHeader("Wechatpay-Serial"); try (BufferedReader reader = new BufferedReader(new InputStreamReader(servletRequest.getInputStream()))) { StringBuilder stringBuilder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } String obj = stringBuilder.toString(); log.info("微信支付回调请求参数:{},{},{},{},{}", obj, timeStamp, nonce, signature, certSn); Verifier verifier = certificatesManager.getVerifier(wxPayConfig.getMchId()); String sn = verifier.getValidCertificate().getSerialNumber().toString(16).toUpperCase(Locale.ROOT); NotificationRequest request = new NotificationRequest.Builder().withSerialNumber(sn) .withNonce(nonce) .withTimestamp(timeStamp) .withSignature(signature) .withBody(obj) .build(); NotificationHandler handler = new NotificationHandler(verifier, wxPayConfig.getApiKey3().getBytes(StandardCharsets.UTF_8)); // 验签和解析请求体 Notification notification = handler.parse(request); JSONObject res = JSON.parseObject(notification.getDecryptData()); log.info("微信支付回调响应参数:{}", res.toJSONString()); //做一些操作 if (res != null) { //如果支付成功 String tradeState = res.getString("trade_state"); if("SUCCESS".equals(tradeState)){ //拿到商户订单号 String outTradeNo = res.getString("out_trade_no"); JSONObject amountJson = res.getJSONObject("amount"); Integer payerTotal = amountJson.getInteger("payer_total"); SysOrder sysOrder = sysOrderDao.queryByOrderCode(outTradeNo); if(sysOrder != null){ if(sysOrder.getPayStatus() == 1){ //如果支付状态为1 说明订单已经支付成功了,直接响应微信服务器返回成功 response.setStatus(200); map.put("code", "SUCCESS"); map.put("message", "SUCCESS"); response.setHeader("Content-type", ContentType.JSON.toString()); response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); response.flushBuffer(); } //验证用户支付的金额和订单金额是否一致 if(payerTotal.equals(sysOrder.getOrderPrice())){ //修改订单状态 String successTime = res.getString("success_time"); sysOrder.setPayStatus(1); sysOrderDao.update(sysOrder); //响应微信服务器 response.setStatus(200); map.put("code", "SUCCESS"); map.put("message", "SUCCESS"); response.setHeader("Content-type", ContentType.JSON.toString()); response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); response.flushBuffer(); } } } } response.setStatus(500); map.put("code", "ERROR"); map.put("message", "签名错误"); response.setHeader("Content-type", ContentType.JSON.toString()); response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); response.flushBuffer(); } catch (Exception e) { log.error("微信支付回调失败", e); } }
如果有用,请给个采纳,谢谢
解决 无用评论 打赏 举报
悬赏问题
- ¥15 python点云生成mesh精度不够怎么办
- ¥15 QT C++ 鼠标键盘通信
- ¥15 改进Yolov8时添加的注意力模块在task.py里检测不到
- ¥50 高维数据处理方法求指导
- ¥100 数字取证课程 关于FAT文件系统的操作
- ¥15 如何使用js实现打印时每页设置统一的标题
- ¥15 安装TIA PortalV15.1报错
- ¥15 能把水桶搬到饮水机的机械设计
- ¥15 Android Studio中如何把H5逻辑放在Assets 文件夹中以实现将h5代码打包为apk
- ¥15 使用小程序wx.createWebAudioContext()开发节拍器