keyfil/教程/电商/20250515-电商订单对接指南.md

200 lines
6.8 KiB
Markdown
Raw Normal View History

<!-- Space: qifu -->
<!-- Parent: 后端技术&知识&规范 -->
<!-- Parent: 技术方案 -->
<!-- Parent: 基建 -->
<!-- Parent: 03-接入指南 -->
<!-- Parent: 0301-电商接入指南 -->
<!-- Title: 20250515-电商订单对接指南 -->
<!-- Macro: :anchor\((.*)\):
Template: ac:anchor
Anchor: ${1} -->
<!-- Macro: \!\[.*\]\((.+)\)\<\!\-\- width=(.*) \-\-\>
Template: ac:image
Url: ${1}
Width: ${2} -->
<!-- Macro: \<\!\-\- :toc: \-\-\>
Template: ac:toc
Printable: 'false'
MinLevel: 2
MaxLevel: 4 -->
<!-- Include: 杂项/声明文件.md -->
<!-- :toc: -->
# 电商订单对接指南
- eBay 接入指南可以查看http://confluence.qifu.com/pages/viewpage.action?pageId=38511846
- TikTok 接入指南可以查看http://confluence.qifu.com/pages/viewpage.action?pageId=38512736
- Amazon 接入指南可以查看http://confluence.qifu.com/pages/viewpage.action?pageId=38512738
- Lazada 接入指南可以查看http://confluence.qifu.com/pages/viewpage.action?pageId=38512740
## 使用南北流量网关对接电商平台
### 接口交互流程
#### 电商用户授权流程
![](https://picture.texous.cn/blog/20250310161855028.png)
#### 接口交互流程
![](https://picture.texous.cn/blog/20250310164117594.png)
### 添加依赖
```xml
<dependencys>
<!-- RPC接口 -->
<dependency>
<groupId>com.yuanmeng.qifu</groupId>
<artifactId>qifu-saas-eg-client</artifactId>
<version>1.0.13</version>
</dependency>
<!-- SPI接收订单同步信息 -->
<dependency>
<groupId>com.yuanmeng.qifu</groupId>
<artifactId>qifu-saas-eg-spi</artifactId>
<version>1.0.13</version>
</dependency>
</dependencys>
```
### 注册SPI服务注册之后才会有 webhook 请求)
#### spi包中包含的自动注册
- qifu-saas-eg-spi 已经整合了自动注册功能。
- 默认以 spring.application.name 作为服务名在程序启动时发起注册
- 可以做特殊配置:
- ```yaml
qifu:
eg:
spi:
enable: true
enable-spi-register: true
spi-infos:
- type: 1
server-code: ${spring.application.name}
server-name: ${spring.application.name}
server-description: '测试服务'
```
- type1=订单同步SPI
- server-code唯一标识卖家授权的时候使用
- server-name服务名称SPI feign调用服务名
#### 手动注册
- 使用 `RemoteSpiService.addSpi` 来进行注册
- 可以关闭自动注册
- ```yaml
qifu:
eg:
spi:
enable-spi-register: false
```
### 卖家授权(必须)
#### 第一步:关联卖家授权应用(必须)
- `RemoteOrderService.linkApp(channel, sellerId, region, orderAppId, spiServerCodes)`
- channel`(required)`: 渠道,参考 `OrderChannelEnum` code字段
- sellerId`(required)`卖家id卖家唯一标识业务自定义
- region`(required)`:所属区域,请看 `RemoteOrderService.linkApp()` 接口文档注释
- orderAppId`(optional)`:关联的授权应用,没传由系统负载获取
- spiServerCodes`(optional)`spi回调应用编码多个用, 分割,没有时不会做 webhook
- **示例:**
- ```shell
curl -X POST --location "http://localhost:8933/order/app/link?channel=4&sellerId=keyfil001&region=Vietnam" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE3MzEzODIxNzksInRlbmFudElkIjo3LCJuaWNrbmFtZSI6IuWImOaZk-WNjiIsImV4cCI6MTczMTQyNTM3OSwiaWF0IjoxNzMxMzgyMTc5LCJ1c2VySWQiOjEzODM3MjksImp0aSI6ImYyMzQ1NDgxNWQ0NTRkNzk4MGQ2ZjQwMGQ2NWFlMzBkIn0.QjFcqlGACbR9VZXEyQhmuP-JTJTT7ILmP8FeNdGJcJI"
```
#### 获取授权链接(必须)
- `RemoteOrderService.authAuthorizeUrl(Integer channel, String sellerId)`
- **示例:**
- ```shell
curl -X GET --location "http://localhost:8933/order/oauth/authorize?channel=4&sellerId=keyfil001" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE3MzEzODIxNzksInRlbmFudElkIjo3LCJuaWNrbmFtZSI6IuWImOaZk-WNjiIsImV4cCI6MTczMTQyNTM3OSwiaWF0IjoxNzMxMzgyMTc5LCJ1c2VySWQiOjEzODM3MjksImp0aSI6ImYyMzQ1NDgxNWQ0NTRkNzk4MGQ2ZjQwMGQ2NWFlMzBkIn0.QjFcqlGACbR9VZXEyQhmuP-JTJTT7ILmP8FeNdGJcJI"
```
#### 获取accessToken回调链接为业务链接时必须
-
`RemoteOrderService.authAccessToken(Integer channel, String appName, String code, String spapiOauthCode, String shopId, String mainAccountId, String state)`
- **示例:**
- ```shell
curl -X GET --location "http://localhost:8933/open/order/oauth/callback/4?code=0_132783_8fmfr7mGBVhjyFt7aycC8R784464&state=1922598474703364098"
```
#### 授权状态(必须)(快过期时提醒用户重新授权)
- **在授权后需要查询授权状态,授权状态快过期时需要提醒用户重新授权**
- `RemoteOrderService.oauthStatus(Integer channel, String sellerId)`
- **示例:**
- ```shell
curl -X GET --location "http://localhost:8933/order/oauth/status?channel=4&sellerId=keyfil001"
```
#### 手动同步(可选)
- 手动触发订单同步操作
- `RemoteOrderService.syncOrder(OrderSyncReq req)`
- **示例:**
- ```shell
curl -X POST --location "http://localhost:8933/order/sync" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE3MzEzODIxNzksInRlbmFudElkIjo3LCJuaWNrbmFtZSI6IuWImOaZk-WNjiIsImV4cCI6MTczMTQyNTM3OSwiaWF0IjoxNzMxMzgyMTc5LCJ1c2VySWQiOjEzODM3MjksImp0aSI6ImYyMzQ1NDgxNWQ0NTRkNzk4MGQ2ZjQwMGQ2NWFlMzBkIn0.QjFcqlGACbR9VZXEyQhmuP-JTJTT7ILmP8FeNdGJcJI" \
-d '{
"channel": 4,
"sellerId": "keyfil001",
"startTimeMillis": 1742529814000
}'
```
#### 自动同步
- 每一个小时会进行一次订单同步。cron`0 0 0/1 * * ?`
### 编写SPI处理逻辑
#### 开放接口
- SPI通过自动注册接口 `/sync/order/change` 来实现 webhook 请求接收
- 需要程序开放 `/sync/order/change` 接口供 `qifu-saas-eg` 回调使用
#### 编写回调信息处理逻辑
- 实现 `OrderSyncHandler`
- **示例:**
- ```java
@Slf4j
@Component
public class OrderSyncHandlerImpl implements OrderSyncHandler {
@Override
public Boolean handle(SpiOrderReq req) {
log.info("channel: {}", req.getChannel());
log.info("sellerId: {}", req.getSellerId());
log.info("orders: {}", req.getSpiOrders());
for (SpiOrderReq.SpiOrder spiOrder : req.getSpiOrders()) {
if (spiOrder.getOldOrder() == null) {
// TODO 新订单处理逻辑
log.info("new order handler: order info: {}", spiOrder.getNewOrder());
} else {
// TODO 更新订单逻辑
log.info("update order handler: old order info: {}", spiOrder.getOldOrder());
log.info("update order handler: new order info: {}", spiOrder.getNewOrder());
}
}
return Boolean.TRUE;
}
}
```