> 我們的支付時不允許在訂單的支付接口傳訂單金額的,所以我們采用了訂單號進行支付的形式
## 支付
我們來到`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));
```
這里的事件也是和營銷活動有關的,比如分銷,這些代碼也是商業版才有的。
- 開發環境準備
- 基本開發手冊
- 項目目錄結構
- 權限管理
- 通用分頁表格
- Swagger文檔
- undertow容器
- 對xss攻擊的防御
- 分布式鎖
- 統一的系統日志
- 統一驗證
- 統一異常處理
- 文件上傳下載
- 一對多、多對多分頁
- 認證與授權
- 從授權開始看源碼
- 自己寫個授權的方法-開源版
- 商城表設計
- 商品信息
- 商品分組
- 購物車
- 訂單
- 地區管理
- 運費模板
- 接口設計
- 必讀
- 購物車的設計
- 訂單設計-確認訂單
- 訂單設計-提交訂單
- 訂單設計-支付
- 生產環境
- nginx安裝與跨域配置
- 安裝mysql
- 安裝redis
- 傳統方式部署項目
- docker
- 使用docker部署商城
- centos jdk安裝
- docker centos 安裝
- Docker Compose 安裝與卸載
- docker 鏡像的基本操作
- docker 容器的基本操作
- 通過yum安裝maven
- 常見問題