> 我们的支付时不允许在订单的支付接口传订单金额的，所以我们采用了订单号进行支付的形式

## 支付

我们来到`PayController` ，这里就是统一支付的接口，当然这里的统一支付采用的是模拟支付。

我们直接看一下核心代码：

```java
PayInfoDto payInfo = payService.pay(userId, payParam);
```

再看看里面的代码：

```java
        // 修改订单信息
        for (String orderNumber : orderNumbers) {
            OrderSettlement orderSettlement = new OrderSettlement();
            orderSettlement.setPayNo(payNo);
            orderSettlement.setPayType(payParam.getPayType());
            orderSettlement.setUserId(userId);
            orderSettlement.setOrderNumber(orderNumber);
            orderSettlementMapper.updateByOrderNumberAndUserId(orderSettlement);

            Order order = orderMapper.getOrderByOrderNumber(orderNumber);
            prodName.append(order.getProdName()).append(StrUtil.COMMA);
        }
```

这里对传过来的支付参数`orderNumbers`进行了拆分，为每个订单的结算信息都进行了更新，所以这里便支持了分单支付和并单支付的流程。



订单金额：

```java
// 除了ordernumber不一样，其他都一样
List<OrderSettlement> settlements = orderSettlementMapper.getSettlementsByPayNo(payNo);
// 应支付的总金额
double payAmount = 0.0;
for (OrderSettlement orderSettlement : settlements) {
    payAmount = Arith.add(payAmount, orderSettlement.getPayAmount());
}
```

这里面应支付的金额是通过数据库中获取的订单金额，是不接受任何前端传入的订单金额的。



## 支付回调



我们回到`controller`

```java
orderRequest.setNotifyUrl(apiConfig.getDomainName() + "/notice/pay/order");
```

这里面规定的，订单回调的地址，这也就是为什么需要`api.properties` 传入`api.domainName`的原因



根据订单配置`/notice/pay/order`，我们去到订单回调的`controller`既`PayNoticeController`

- 验签

因为订单的已经决定的订单已经支付成功，所以订单的回调是需要做一些验证的。不然谁都可以调用订单回调的地址，实在是十分危险。

其实`wxjava`这个工具包已经对返回的参数进行了校验

```java
WxPayOrderNotifyResult parseOrderNotifyResult = wxMiniPayService.parseOrderNotifyResult(xmlData);
```

在上面这个方法之下，就有那么一句话

```java
result.checkResult(this, this.getConfig().getSignType(), false);
```



- 更新支付状态

我们看看这里的业务核心方法：

```java
// 根据内部订单号更新order settlement
payService.paySuccess(payNo, bizPayNo);
```



```java
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> paySuccess(String payNo, String bizPayNo) {
        List<OrderSettlement> orderSettlements = orderSettlementMapper.selectList(new LambdaQueryWrapper<OrderSettlement>().eq(OrderSettlement::getPayNo, payNo));

        OrderSettlement settlement = orderSettlements.get(0);

        // 订单已支付
        if (settlement.getPayStatus() == 1) {
            log.info("订单已支付，settlement.id：{}",settlement.getSettlementId());
            return null;
        }
        // 修改订单结算信息
        if (orderSettlementMapper.updateToPay(payNo, settlement.getVersion()) < 1) {
            throw new YamiShopBindException("结算信息已更改");
        }


        List<String> orderNumbers = orderSettlements.stream().map(OrderSettlement::getOrderNumber).collect(Collectors.toList());

        // 将订单改为已支付状态
        orderMapper.updateByToPaySuccess(orderNumbers, PayType.WECHATPAY.value());

        List<Order> orders = orderNumbers.stream().map(orderNumber -> {
            Order order = orderMapper.getOrderByOrderNumber(orderNumber);
            order.setOrderItems(orderItemMapper.listByOrderNumber(orderNumber));
            return order;
        }).collect(Collectors.toList());
        eventPublisher.publishEvent(new PaySuccessOrderEvent(orders));
        return orderNumbers;
    }
```

这里无非就是找到原来的订单，将订单变成已支付的状态。



而这里同样有事件支付成功的事件

```java
eventPublisher.publishEvent(new PaySuccessOrderEvent(orders));
```

这里的事件也是和营销活动有关的，比如分销，这些代码也是商业版才有的。
