赞
踩
说白了就是我们去调用微信官方提供的接口,但是这些接口有很多繁琐的参数,还需要计算签名等等一系列恶心的步骤,详情可以看微信官网,我们可以用微信官方提供的sdk,也可以用github上的三方sdk,本文以GitHub上大佬binaryWang的微信支付sdk演示微信支付的实现
首先我们作为后端,需要像前端提供一个接口,前端通过调用这个接口唤起下单,在这个接口中,后端回去调用微信下单接口,这时候微信会给我们返一个预支付id,我们通过这个预支付的id,
这个预支付id是唤起下单的一个必填参数,咱们只需要计算出唤起支付所需要的参数,然后传给前端,前端就可以调用这个唤起支付接口,这样,输入密码的数字轮盘就出来了
sdk的版本可能会影响sign的计算,导致输入支付密码后,微信提示sign鉴权失败,这里的sdk大佬们都在维护的,只需要更新到最新版本即可
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
导入依赖,并配置wx所需参数
- <!--微信支付-->
- <dependency>
- <groupId>com.github.binarywang</groupId>
- <artifactId>weixin-java-pay</artifactId>
- <version>4.6.0</version>
- </dependency>
订单支付
- /**
- * 订单微信支付
- * @param paymentForm
- * @return
- */
- @Override
- public <T> T payOrder(OrderPaymentForm paymentForm,Long memberId) {
- //获取订单号
- String orderSn = paymentForm.getOrderSn();
- //通过该订单号查询订单对象
- Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderCode, orderSn));
- log.info("appid---"+paymentForm.getAppId());
- Assert.isTrue(order!=null,"该订单信息不存在");
- Assert.isTrue(OrderStatusEnum.UNPAID.getValue().equals(order.getState()), "订单不可支付,请检查订单状态");
- RLock lock = redissonClient.getLock(OrderConstants.ORDER_LOCK_PREFIX + order.getOrderCode());
- try {
- lock.lock();
- T result;
- result = (T) wxJsapiPay(paymentForm.getAppId(), order.getOrderCode(), order.getAmount(),memberId);
- return result;
- } finally {
- //释放锁
- if (lock.isLocked()) {
- lock.unlock();
- }
- }
- }

掉起订单支付
- /**
- * 微信支付调起
- *
- * @param appId 微信小程序ID
- * @param orderSn 订单编号
- * @param paymentAmount 支付金额
- * @return 微信支付调起参数
- */
- private WxPayUnifiedOrderV3Result.JsapiResult wxJsapiPay(String appId, String orderSn, BigDecimal paymentAmount,Long memberId) {
- //价格转换为分
- Long longValueAmount = BigDecimal2Long(paymentAmount);
-
- //获取用户OpenId
- String memberOpenId = memberService.getById(memberId).getOpenid();
-
- WxPayUnifiedOrderV3Request wxRequest = new WxPayUnifiedOrderV3Request()
- .setAppid(appId)//小程序appId
- .setOutTradeNo(orderSn)//设置订单号
- .setAmount(new WxPayUnifiedOrderV3Request
- .Amount()
- .setTotal(Math.toIntExact(longValueAmount)).
- setCurrency(wxPayProperties.getCurrency())
- )//设置金额
- .setPayer(
- new WxPayUnifiedOrderV3Request.Payer()
- .setOpenid(memberOpenId)
- )//设置付款人
- .setDescription("赅买-订单编号:" + orderSn)
- .setNotifyUrl(wxPayProperties.getPayNotifyUrl());
-
- WxPayUnifiedOrderV3Result.JsapiResult jsapiResult;
- try {
- jsapiResult = wxPayService.createOrderV3(TradeTypeEnum.JSAPI, wxRequest);
- } catch (WxPayException e) {
- log.error(e.getMessage(), e);
- throw new BizException(e.getMessage()+"微信统一下单异常");
- }
- log.info("----------------------"+jsapiResult);
- return jsapiResult;
- }

返回值
实现效果
在用户输入密码成功后,这块微信就支付成功了,这时候我们需要暴露给微信一个开发的回调接口,微信这边会传入一些加密参数,我们拿到参数后调用api将这些参数解密,最后可以对订单进行一些信息的校验以及状态的更新等操作
具体方式与支付差不多,但这块调用微信退款后,前端只需掉我们的接口,会自动完成退款,我们需要按照微信官方的返回规范,退款成功sucsess,更新订单信息
注:如果微信这块没有接收到返回成功的信息,还会按照一定策略(频繁度从高到底)不断调用我们提供的回调接口,具体调用方式请看微信小程序官方退款接口文档
退款--入参(订单编号,退款金额,退款原因)
- /**
- * 退款
- */
- public <T> T refundOrder(RefundForm refundForm){
- Assert.isTrue(refundForm.getReason()!=null,"退款备注不能为空");
- //判断该订单是否未付款,或已取消
- //获取商户订单号
- String orderCode = refundForm.getOrderCode();
- //转金额
- Long orderRundAmount = BigDecimal2Long(refundForm.getRefundAmount());
- //获取订单信息
- Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderCode, orderCode));
- //获取微信退款单号
- String wxPayCode = order.getWxPayCode();
-
- //订单金额
- Long orderAmount = BigDecimal2Long(order.getAmount());
- Assert.isTrue(order !=null,"查询不到该订单信息,无法退款");
- Assert.isTrue(order.getState()==OrderStatusEnum.PAID.getValue() || order.getState()==OrderStatusEnum.REBATES.getValue(),"该订单尚未完成支付或已取消,无法退款");
- Assert.isTrue(orderRundAmount.intValue()>0,"退款金额必须大于0");
- Assert.isTrue(orderRundAmount<=orderAmount,"退款金额必须小于等于订单金额");
- OrderRefundForm.Amount amount = OrderRefundForm.Amount.builder().refund(refundForm.getRefundAmount())//退款金额
- .total(order.getAmount()).build(); //订单金额
-
- OrderRefundForm orderRefundForm = OrderRefundForm.builder().amount(amount)
- .out_refund_no(generateTradeNo(SecurityUtils.getUserId())) //退款单号
- .reason(refundForm.getReason()==null?"":refundForm.getReason())
- .transaction_id(wxPayCode)
- .build();
- T result = (T) wxJsapiRefund(orderRefundForm);
- return result;
- }

掉起退款
- /**
- * 订单退款掉起
- * @param orderRefundForm 退款请求对象 memberId
- * @return
- */
- private WxPayRefundV3Result wxJsapiRefund(OrderRefundForm orderRefundForm) {
- //退款金额
- Long longValueRefundAmount = BigDecimal2Long(orderRefundForm.getAmount().getRefund());
- //订单总金额
- Long longValueOrderAmount = BigDecimal2Long(orderRefundForm.getAmount().getTotal());
- //通过订单号查询商品id
- Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getWxPayCode, orderRefundForm.getTransaction_id()));
- appOrderMapper.updateOrderRefundReason(orderRefundForm.getReason(),order.getId()); // 更新退款原因
- //如果是自动退款
-
- WxPayRefundV3Request wxPayRefundV3Request = new WxPayRefundV3Request().
- setTransactionId(orderRefundForm.getTransaction_id()).
- setAmount(new WxPayRefundV3Request.Amount().
- setTotal(Math.toIntExact(longValueOrderAmount))
- .setRefund(Math.toIntExact(longValueRefundAmount))
- .setCurrency(wxPayProperties.getCurrency())).
- setOutRefundNo(orderRefundForm.getOut_refund_no()).
- setNotifyUrl(wxPayProperties.getRefundNotifyUrl()).
- setReason(orderRefundForm.getReason()==null?"":orderRefundForm.getReason());
- WxPayRefundV3Result refundV3Result;
- try {
- refundV3Result = wxPayService.refundV3(wxPayRefundV3Request);
- log.info("掉起退款接口成功");
- } catch (WxPayException e) {
- throw new BizException("退款失败"+e);
- }
- return refundV3Result;
- }

退款也是一样的,需要暴露回调接口,退款成功后,微信会退款给商户,并且我们在回调接口处理订单状态等信息
实现效果:
微信支付的下单和调起需要前后端的配合与联调,我们需要根据业务需求灵活的处理更新订单的信息,再支付完成之后,在回调接口中校验支付金额与订单金额是否相同等信息,校验通过后才更新订单为已付款状态,,现在我们就实现类微信支付与退款功能了,本文没有写到回调接口的书写,如有需要可留言
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。