当前位置:   article > 正文

最新版微信小程序支付,退款问题实现与总结(保姆级)_微信支付 binarywang

微信支付 binarywang

1.了解微信支付逻辑

说白了就是我们去调用微信官方提供的接口,但是这些接口有很多繁琐的参数,还需要计算签名等等一系列恶心的步骤,详情可以看微信官网,我们可以用微信官方提供的sdk,也可以用github上的三方sdk,本文以GitHub上大佬binaryWang的微信支付sdk演示微信支付的实现

前言

首先我们作为后端,需要像前端提供一个接口,前端通过调用这个接口唤起下单,在这个接口中,后端回去调用微信下单接口,这时候微信会给我们返一个预支付id,我们通过这个预支付的id,

这个预支付id是唤起下单的一个必填参数,咱们只需要计算出唤起支付所需要的参数,然后传给前端,前端就可以调用这个唤起支付接口,这样,输入密码的数字轮盘就出来了

注意事项:

sdk的版本可能会影响sign的计算,导致输入支付密码后,微信提示sign鉴权失败,这里的sdk大佬们都在维护的,只需要更新到最新版本即可

2.微信支付需要的参数

mchKey:新版本更新后叫做v2密钥,作用是处理签名信息解密,在微信支付商户平台申请,为32为密钥,自行设定,需要绑定商户的手机号进行短信验证和操作码验证

keyPath: classpath:wxcert/apiclient_cert.p12

#apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径.

privateKeyPath: classpath:wxcert/apiclient_key.pem

#apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径.

privateCertPath: classpath:wxcert/apiclient_cert.pem

需要在api管理这里设置证书,在指引处可以下载证书

注:密钥,是开发者自己生成,生成后配置到商户平台即可

下载证书工具;下载后,双击“WXCertUtil.exe”文件,选择安装路径后,点击申请证书

也可通过以下链接下载证书工具:

windows版本 :https://wx.gtimg.com/mch/files/WXCertUtil.exe

mac版本 :https://wx.gtimg.com/mch/files/WXCertUtil.dmg

3.实现微信支付

导入依赖,并配置wx所需参数

  1. <!--微信支付-->
  2. <dependency>
  3. <groupId>com.github.binarywang</groupId>
  4. <artifactId>weixin-java-pay</artifactId>
  5. <version>4.6.0</version>
  6. </dependency>

订单支付

  1. /**
  2. * 订单微信支付
  3. * @param paymentForm
  4. * @return
  5. */
  6. @Override
  7. public <T> T payOrder(OrderPaymentForm paymentForm,Long memberId) {
  8. //获取订单号
  9. String orderSn = paymentForm.getOrderSn();
  10. //通过该订单号查询订单对象
  11. Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderCode, orderSn));
  12. log.info("appid---"+paymentForm.getAppId());
  13. Assert.isTrue(order!=null,"该订单信息不存在");
  14. Assert.isTrue(OrderStatusEnum.UNPAID.getValue().equals(order.getState()), "订单不可支付,请检查订单状态");
  15. RLock lock = redissonClient.getLock(OrderConstants.ORDER_LOCK_PREFIX + order.getOrderCode());
  16. try {
  17. lock.lock();
  18. T result;
  19. result = (T) wxJsapiPay(paymentForm.getAppId(), order.getOrderCode(), order.getAmount(),memberId);
  20. return result;
  21. } finally {
  22. //释放锁
  23. if (lock.isLocked()) {
  24. lock.unlock();
  25. }
  26. }
  27. }

掉起订单支付

  1. /**
  2. * 微信支付调起
  3. *
  4. * @param appId 微信小程序ID
  5. * @param orderSn 订单编号
  6. * @param paymentAmount 支付金额
  7. * @return 微信支付调起参数
  8. */
  9. private WxPayUnifiedOrderV3Result.JsapiResult wxJsapiPay(String appId, String orderSn, BigDecimal paymentAmount,Long memberId) {
  10. //价格转换为分
  11. Long longValueAmount = BigDecimal2Long(paymentAmount);
  12. //获取用户OpenId
  13. String memberOpenId = memberService.getById(memberId).getOpenid();
  14. WxPayUnifiedOrderV3Request wxRequest = new WxPayUnifiedOrderV3Request()
  15. .setAppid(appId)//小程序appId
  16. .setOutTradeNo(orderSn)//设置订单号
  17. .setAmount(new WxPayUnifiedOrderV3Request
  18. .Amount()
  19. .setTotal(Math.toIntExact(longValueAmount)).
  20. setCurrency(wxPayProperties.getCurrency())
  21. )//设置金额
  22. .setPayer(
  23. new WxPayUnifiedOrderV3Request.Payer()
  24. .setOpenid(memberOpenId)
  25. )//设置付款人
  26. .setDescription("赅买-订单编号:" + orderSn)
  27. .setNotifyUrl(wxPayProperties.getPayNotifyUrl());
  28. WxPayUnifiedOrderV3Result.JsapiResult jsapiResult;
  29. try {
  30. jsapiResult = wxPayService.createOrderV3(TradeTypeEnum.JSAPI, wxRequest);
  31. } catch (WxPayException e) {
  32. log.error(e.getMessage(), e);
  33. throw new BizException(e.getMessage()+"微信统一下单异常");
  34. }
  35. log.info("----------------------"+jsapiResult);
  36. return jsapiResult;
  37. }

返回值

实现效果

在用户输入密码成功后,这块微信就支付成功了,这时候我们需要暴露给微信一个开发的回调接口,微信这边会传入一些加密参数,我们拿到参数后调用api将这些参数解密,最后可以对订单进行一些信息的校验以及状态的更新等操作

4.实现微信退款

具体方式与支付差不多,但这块调用微信退款后,前端只需掉我们的接口,会自动完成退款,我们需要按照微信官方的返回规范,退款成功sucsess,更新订单信息

注:如果微信这块没有接收到返回成功的信息,还会按照一定策略(频繁度从高到底)不断调用我们提供的回调接口,具体调用方式请看微信小程序官方退款接口文档

退款--入参(订单编号,退款金额,退款原因)

  1. /**
  2. * 退款
  3. */
  4. public <T> T refundOrder(RefundForm refundForm){
  5. Assert.isTrue(refundForm.getReason()!=null,"退款备注不能为空");
  6. //判断该订单是否未付款,或已取消
  7. //获取商户订单号
  8. String orderCode = refundForm.getOrderCode();
  9. //转金额
  10. Long orderRundAmount = BigDecimal2Long(refundForm.getRefundAmount());
  11. //获取订单信息
  12. Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderCode, orderCode));
  13. //获取微信退款单号
  14. String wxPayCode = order.getWxPayCode();
  15. //订单金额
  16. Long orderAmount = BigDecimal2Long(order.getAmount());
  17. Assert.isTrue(order !=null,"查询不到该订单信息,无法退款");
  18. Assert.isTrue(order.getState()==OrderStatusEnum.PAID.getValue() || order.getState()==OrderStatusEnum.REBATES.getValue(),"该订单尚未完成支付或已取消,无法退款");
  19. Assert.isTrue(orderRundAmount.intValue()>0,"退款金额必须大于0");
  20. Assert.isTrue(orderRundAmount<=orderAmount,"退款金额必须小于等于订单金额");
  21. OrderRefundForm.Amount amount = OrderRefundForm.Amount.builder().refund(refundForm.getRefundAmount())//退款金额
  22. .total(order.getAmount()).build(); //订单金额
  23. OrderRefundForm orderRefundForm = OrderRefundForm.builder().amount(amount)
  24. .out_refund_no(generateTradeNo(SecurityUtils.getUserId())) //退款单号
  25. .reason(refundForm.getReason()==null?"":refundForm.getReason())
  26. .transaction_id(wxPayCode)
  27. .build();
  28. T result = (T) wxJsapiRefund(orderRefundForm);
  29. return result;
  30. }

掉起退款

  1. /**
  2. * 订单退款掉起
  3. * @param orderRefundForm 退款请求对象 memberId
  4. * @return
  5. */
  6. private WxPayRefundV3Result wxJsapiRefund(OrderRefundForm orderRefundForm) {
  7. //退款金额
  8. Long longValueRefundAmount = BigDecimal2Long(orderRefundForm.getAmount().getRefund());
  9. //订单总金额
  10. Long longValueOrderAmount = BigDecimal2Long(orderRefundForm.getAmount().getTotal());
  11. //通过订单号查询商品id
  12. Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getWxPayCode, orderRefundForm.getTransaction_id()));
  13. appOrderMapper.updateOrderRefundReason(orderRefundForm.getReason(),order.getId()); // 更新退款原因
  14. //如果是自动退款
  15. WxPayRefundV3Request wxPayRefundV3Request = new WxPayRefundV3Request().
  16. setTransactionId(orderRefundForm.getTransaction_id()).
  17. setAmount(new WxPayRefundV3Request.Amount().
  18. setTotal(Math.toIntExact(longValueOrderAmount))
  19. .setRefund(Math.toIntExact(longValueRefundAmount))
  20. .setCurrency(wxPayProperties.getCurrency())).
  21. setOutRefundNo(orderRefundForm.getOut_refund_no()).
  22. setNotifyUrl(wxPayProperties.getRefundNotifyUrl()).
  23. setReason(orderRefundForm.getReason()==null?"":orderRefundForm.getReason());
  24. WxPayRefundV3Result refundV3Result;
  25. try {
  26. refundV3Result = wxPayService.refundV3(wxPayRefundV3Request);
  27. log.info("掉起退款接口成功");
  28. } catch (WxPayException e) {
  29. throw new BizException("退款失败"+e);
  30. }
  31. return refundV3Result;
  32. }

退款也是一样的,需要暴露回调接口,退款成功后,微信会退款给商户,并且我们在回调接口处理订单状态等信息

实现效果:

总结:

微信支付的下单和调起需要前后端的配合与联调,我们需要根据业务需求灵活的处理更新订单的信息,再支付完成之后,在回调接口中校验支付金额与订单金额是否相同等信息,校验通过后才更新订单为已付款状态,,现在我们就实现类微信支付与退款功能了,本文没有写到回调接口的书写,如有需要可留言

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/874108
推荐阅读
  

闽ICP备14008679号