- 配置PayPal沙箱环境的Client ID和密钥 - 新增updatePaymentStatus方法用于更新订单支付状态 - 新增updateOrderStatus方法用于更新订单状态 - 实现支付状态更新时同步更新订单状态逻辑 - 添加详细的日志记录和异常处理机制 - 集成MyBatis Plus查询更新订单数据
171 lines
4.5 KiB
Markdown
171 lines
4.5 KiB
Markdown
# PayPal Webhook处理指南
|
||
|
||
## 概述
|
||
|
||
PayPal Webhook是PayPal向你的服务器发送事件通知的机制。当支付状态发生变化时,PayPal会主动推送事件到你的Webhook URL。
|
||
|
||
## Webhook URL配置
|
||
|
||
在你的PayPal开发者控制台中配置Webhook URL:
|
||
- **开发环境**: `https://你的域名/api/paypal/webhook`
|
||
- **生产环境**: `https://你的生产域名/api/paypal/webhook`
|
||
|
||
## 支持的事件类型
|
||
|
||
系统已实现以下事件类型的处理:
|
||
|
||
### 1. PAYMENT.CAPTURE.COMPLETED
|
||
**触发时机**: 当PayPal成功捕获资金时触发
|
||
|
||
**处理逻辑**:
|
||
- 提取capture信息(金额、货币、状态等)
|
||
- 通过`supplementary_data.related_ids.order_id`或`custom_id`获取ERP订单号
|
||
- 更新ERP订单状态为"已支付"(PAID)
|
||
|
||
### 2. PAYMENT.CAPTURE.DENIED
|
||
**触发时机**: 当支付捕获被拒绝时触发
|
||
|
||
**处理逻辑**:
|
||
- 记录支付失败信息
|
||
- 更新ERP订单状态为"支付失败"
|
||
|
||
### 3. PAYMENT.CAPTURE.REFUNDED
|
||
**触发时机**: 当支付被退款时触发
|
||
|
||
**处理逻辑**:
|
||
- 记录退款信息
|
||
- 更新ERP订单状态为"已退款"
|
||
|
||
### 4. CHECKOUT.ORDER.APPROVED
|
||
**触发时机**: 当订单被顾客批准时触发
|
||
|
||
**处理逻辑**:
|
||
- 记录订单批准信息
|
||
- 可以触发自动捕获逻辑(如果需要)
|
||
|
||
### 5. CHECKOUT.ORDER.COMPLETED
|
||
**触发时机**: 当订单完成时触发
|
||
|
||
**处理逻辑**:
|
||
- 记录订单完成信息
|
||
- 根据业务需求处理订单完成逻辑
|
||
|
||
### 6. CHECKOUT.ORDER.CANCELLED
|
||
**触发时机**: 当订单被取消时触发
|
||
|
||
**处理逻辑**:
|
||
- 记录订单取消信息
|
||
- 更新ERP订单状态为"已取消"
|
||
|
||
## 签名验证
|
||
|
||
### 开发环境(沙箱)
|
||
- 签名验证可以暂时跳过(已实现自动跳过)
|
||
- 但建议在测试时也启用验证,确保代码正确
|
||
|
||
### 生产环境
|
||
- **必须启用签名验证**
|
||
- 需要在配置文件中设置`webhook-id`
|
||
- 系统会自动验证每个Webhook请求的签名
|
||
|
||
## 配置Webhook ID
|
||
|
||
### 1. 获取Webhook ID
|
||
|
||
1. 登录PayPal开发者控制台:https://developer.paypal.com/dashboard/
|
||
2. 进入你的应用设置
|
||
3. 找到Webhook配置部分
|
||
4. 创建或查看Webhook,获取Webhook ID
|
||
|
||
### 2. 配置到系统
|
||
|
||
在`application-dev.yml`或`application-prod.yml`中添加:
|
||
|
||
```yaml
|
||
paypal:
|
||
webhook-id: YOUR_WEBHOOK_ID
|
||
```
|
||
|
||
## 订单号关联
|
||
|
||
PayPal Webhook事件中需要关联ERP订单号,系统会按以下顺序尝试获取:
|
||
|
||
1. **从`supplementary_data.related_ids.order_id`获取**
|
||
- 这是PayPal自动填充的,包含原始订单ID
|
||
- 然后通过查询PayPal订单详情获取`reference_id`(即ERP订单号)
|
||
|
||
2. **从`custom_id`获取**
|
||
- 如果创建PayPal订单时设置了`custom_id`,可以直接获取
|
||
|
||
3. **通过`order_id`查询订单详情**
|
||
- 如果上述方法都无法获取,会通过PayPal API查询订单详情
|
||
- 从订单的`purchase_units[0].reference_id`获取ERP订单号
|
||
|
||
## 测试Webhook
|
||
|
||
### 使用PayPal Webhook模拟器
|
||
|
||
1. 登录PayPal开发者控制台
|
||
2. 进入Webhook配置页面
|
||
3. 使用"Send test webhook"功能
|
||
4. 选择要测试的事件类型
|
||
5. 系统会收到测试事件并处理
|
||
|
||
### 本地测试
|
||
|
||
如果需要在本地测试,可以使用以下工具:
|
||
|
||
1. **ngrok**(推荐):
|
||
```bash
|
||
ngrok http 8082
|
||
```
|
||
然后将ngrok提供的URL配置到PayPal Webhook URL
|
||
|
||
2. **PayPal Webhook模拟器**:
|
||
使用Postman等工具模拟Webhook请求
|
||
|
||
## 日志查看
|
||
|
||
Webhook处理的所有步骤都会记录日志,包括:
|
||
- 接收到的Webhook事件
|
||
- 签名验证结果
|
||
- 事件处理过程
|
||
- 订单状态更新结果
|
||
|
||
查看日志位置:
|
||
- 应用日志文件
|
||
- 控制台输出
|
||
|
||
## 常见问题
|
||
|
||
### 1. Webhook未收到事件
|
||
- 检查Webhook URL是否正确配置
|
||
- 确认服务器可以访问(防火墙、网络等)
|
||
- 检查PayPal控制台中的Webhook状态
|
||
|
||
### 2. 签名验证失败
|
||
- 确认Webhook ID配置正确
|
||
- 检查请求头是否完整
|
||
- 确认使用的是正确的环境(沙箱/生产)
|
||
|
||
### 3. 无法关联ERP订单
|
||
- 确认创建PayPal订单时设置了`reference_id`
|
||
- 检查订单号格式是否正确
|
||
- 查看日志中的详细信息
|
||
|
||
## 安全建议
|
||
|
||
1. **生产环境必须启用签名验证**
|
||
2. **使用HTTPS**(PayPal要求)
|
||
3. **记录所有Webhook事件**(用于审计和调试)
|
||
4. **实现幂等性处理**(防止重复处理同一事件)
|
||
5. **设置超时和重试机制**
|
||
|
||
## 代码位置
|
||
|
||
- **Webhook控制器**: `PayPalController.webhook()`
|
||
- **Webhook服务**: `PayPalWebhookService` 和 `PayPalWebhookServiceImpl`
|
||
- **事件DTO**: `PayPalWebhookEventDTO`
|
||
- **配置**: `PayPalProperties.webhookId`
|
||
|