普通网友 2023-08-09 11:32 采纳率: 0%
浏览 28

springlcoud微信小程序支付

微信小程序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);
            }
        }
    

    如果有用,请给个采纳,谢谢

    评论

报告相同问题?

问题事件

  • 创建了问题 8月9日

悬赏问题

  • ¥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()开发节拍器