乐优商城项目总结——12.5 微信支付(生成支付链接,回调确认,检查支付状态和内网穿透)

生成支付链接(用户点提交订单后)

用户点了提交订单后该给他显示微信支付二维码了。

生成步骤

1 controller接收的是订单编号

/**
     * 创建支付链接
     *
     * @param orderId
     * @return
     */
    @GetMapping("/url/{id}")
    public ResponseEntity<String> createPayUrl(@PathVariable("id") Long orderId) {
        return ResponseEntity.ok(orderService.createPayUrl(orderId));
    }

2 在service中处理:

这里面填的是上一篇PayHelper类里需要的三个参数
1,商品描述信息
2,商品订单编号
3,总金额

/**
     * 创建支付链接
     *
     * @param orderId
     * @return
     */
    public String createPayUrl(Long orderId) {
//        查询订单
        Order order = queryOrderById(orderId);
//        判断订单状态
        Integer status = order.getOrderStatus().getStatus();
        if (status != OrderStatusEnum.UNPAY.value()) {
            throw new LyException(ExceptionEnum.ORDER_STATUS_EXCEPTION);
        }
//        获取金额,单位是分,所以为了少给钱给一分吧
        @NotNull Long totalPay = /*order.getActualPay()*/1l;
//        商品描述
        OrderDetail detail = order.getOrderDetails().get(0);
        String desc = detail.getTitle();


        return payHelper.getPayUrl(desc, orderId, totalPay);
    }

3 这样通过PayHelper处理后,前台页面就会出现一条支付链接:
在这里插入图片描述

前端用 js 二维码生成工具处理后就会有二维码了:

在这里插入图片描述
到这里支付链接就生成了。

然后就掏钱:
在这里插入图片描述

回调确认(用户支付成功后)

上一篇讲到,支付成功后微信会给我们发送一条消息,我们需要接受并返回消息。

问题:

我们是在本机进行测试,路径是本地,但是微信发送的消息是通过网络地址通知的,我们要接受就需要把自己电脑当做一台云服务器,要有一个网络地址,这就需要内网穿透来实现了。

1,内网穿透

简单地说就是给自己电脑一个网络ip,别人通过网络可以访问我们。
这里我使用一个工具来实现。
在这里插入图片描述
地址: https://natapp.cn

为什么使用它呢,免费啊。

注册创建用户然后选择免费隧道就好,傻瓜式操作。

下载符合自己电脑的工具,下载后是这样的:
在这里插入图片描述
有一个config.ini是自己创建的,官网也有模板,我贴出来自己的:
只有一个需要填:authtoken
填写自己的号就好,申请完隧道就会看见自己的authtoken。

#将本文件放置于natapp同级目录 程序将读取 [default] 段
#在命令行参数模式如 natapp -authtoken=xxx 等相同参数将会覆盖掉此配置
#命令行参数 -config= 可以指定任意config.ini文件
[default]
authtoken=xxxxxxxxxxxx                 #对应一条隧道的authtoken
clienttoken=                    #对应客户端的clienttoken,将会忽略authtoken,若无请留空,
log=none                        #log 日志文件,可指定本地文件, none=不做记录,stdout=直接屏幕输出 ,默认为none
loglevel=INFO                  #日志等级 DEBUG, INFO, WARNING, ERROR 默认为 DEBUG
http_proxy=                     #代理设置 如 http://10.123.10.10:3128 非代理上网用户请务必留空

然后点击exe运行就好,就像这样。
注意:地址我填的是8089,是我订单微服务的地址,因为是在这里个微服务里面处理回调确认的。
在这里插入图片描述
因为是免费的,所以那个地址会变化,实验一下就好,免费的要啥自行车呢。

2,业务实现

解决了地址问题,该返回消息了。

2.1 controller:
因为微信要的回值只支持xml,所以要返回xml类型的信息。
注意:
需要引入xml的配置,在pom文件中已经引入
有了xml的配置,才能让@requestbody注解解析xml,否则他默认只支持json


@Slf4j
@RestController
@RequestMapping("notify")
public class NotifyController {

    @Autowired
    private OrderService orderService;

    /**
     * produce:设置返回的一定是xml格式
     * 微信支付成功回调
     *
     * @param msg
     * @return
     */
    @PostMapping(value = "pay", produces = "application/xml")
    public ResponseEntity<String> payNotify(@RequestBody Map<String, String> msg) {
        //处理回调结果
        orderService.handleNotify(msg);
        log.info("[订单回调],接收微信支付回调,结果:{}", msg);
        // 没有异常,则返回成功
        String result = "<xml>\n" +
                "  <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                "  <return_msg><![CDATA[OK]]></return_msg>\n" +
                "</xml>";
        return ResponseEntity.ok(result);

    }
}

pom:

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>2.9.6</version>
        </dependency>

service:
校验的方法上一篇 payHelper有写,这里是直接调用。

 /**
     * 微信支付成功回调
     *
     * @param msg
     */
    public void handleNotify(Map<String, String> msg) {
//        校验数据
        payHelper.checkResultCode(msg);
//        校验签名
        payHelper.checkSignature(msg);
//        校验金额
        String totalFeeStr = msg.get("total_fee");
        String outTradeNo = msg.get("out_trade_no");  //订单编号
        if (StringUtils.isEmpty(totalFeeStr) || StringUtils.isEmpty(outTradeNo)) {
            throw new LyException(ExceptionEnum.WX_PAY_NOTIFY_PARAM_ERROR);
        }
//        获取结果中的金额
        Long totalFee = Long.valueOf(totalFeeStr);
//        获取订单金额
        Long orderId2 = Long.valueOf(outTradeNo);
        Order order2 = orderMapper.selectByPrimaryKey(orderId2);
        if (totalFee !=/*order2.getActualPay()*/ 1l) {
            throw new LyException(ExceptionEnum.WX_PAY_NOTIFY_PARAM_ERROR);
        }
//        修改订单状态
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setStatus(OrderStatusEnum.PAYED.value());
        orderStatus.setOrderId(orderId2);
        orderStatus.setCreateTime(new Date());
        int count = statusMapper.updateByPrimaryKeySelective(orderStatus);
        if (count != 1) {
            throw new LyException(ExceptionEnum.UPDATE_ORDER_STATUS_FAILED);
        }
        log.info("[订单回调],订单支付成功,订单编号:{}", orderId2);

    }

到这里也给微信发送了回复,我们前台要校验支付状态给用户反馈了。

查询支付状态(给用户的反馈)

前台要隔一段时间检查支付状态,给用户一个反馈,不能付完钱还是那个界面。

1 前端一直循环发送查询需求,然后这里接收订单编号进行查询
controller:

  /**
     * 查询订单支付状态
     *
     * @param orderId
     * @return
     */
    @GetMapping("state/{id}")
    public ResponseEntity<Integer> queryOrderState(@PathVariable("id") Long orderId) {
        return ResponseEntity.ok(orderService.queryOrderState(orderId).getValue());
    }

2 业务层处理
service:
如果没查到,去微信里主动查一下(虽然它会主动发送状态,但万一没发自己查查也好)

 public PayStateEnum queryOrderState(Long orderId) {
//        查询订单状态
        OrderStatus orderStatus = statusMapper.selectByPrimaryKey(orderId);
        Integer status = orderStatus.getStatus();
//        判断是否已支付
        if (status != OrderStatusEnum.UNPAY.value()) {
            return PayStateEnum.SUCCESS;
        }
//        如果未支付,则去微信查询
        return payHelper.queryPayState(orderId);
    }

在PayHelper里面写逻辑:
上来就是一顿校验。

 /**
     * 主动查询订单状态
     *
     * @param orderId
     */
    public PayStateEnum queryPayState(Long orderId) {
        try {
//        组织请求参数
            HashMap<String, String> data = new HashMap<>();
//        订单号
            data.put("out_trade_no", orderId.toString());
//        查询状态
            Map<String, String> result = wxPay.orderQuery(data);
            /**
             * 然后就是一顿校验
             */
            checkResultCode(result);
            checkSignature(result);
//            还有一大堆校验,将orderservice的校验金额和它的修改搬到这里来,通过
//            result.get("trade_state");获取微信该订单的状态,然后修改数据库里的订单状态
//            一顿操作猛如虎,懒得弄
        } catch (Exception e) {
            return PayStateEnum.NOT_PAY;
        }
        return PayStateEnum.NOT_PAY;
    }

到这里,查询状态也结束了,完整的流程也结束了。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值