feat: 集成Google OAuth认证和完善Stripe支付系统
- 新增Google OAuth 2.0认证模块 - 实现Google Strategy和AuthController - 添加Google平台适配器和用户统一管理 - 支持OAuth回调和token交换机制 - 完善Stripe支付集成 - 新增Stripe支付适配器和控制器 - 实现webhook事件处理和支付确认 - 支持多币种和国际化支付 - 扩展平台类型支持 - 在PlatformType中新增GOOGLE和STRIPE - 更新适配器工厂注册机制 - 完善跨平台用户身份管理 - 增强依赖和配置 - 添加@nestjs/passport和passport-google-oauth20 - 更新支付方法枚举和货币支持 - 完善订单号生成和回调URL构建
This commit is contained in:
342
STRIPE_INTEGRATION_GUIDE.md
Normal file
342
STRIPE_INTEGRATION_GUIDE.md
Normal file
@@ -0,0 +1,342 @@
|
||||
# Stripe国际支付集成指南
|
||||
|
||||
## 概述
|
||||
|
||||
本项目已成功集成Stripe国际信用卡支付功能,支持多种国际货币(USD、EUR、GBP、JPY等)的在线支付。Stripe适配器已完整实现并集成到现有的统一支付架构中。
|
||||
|
||||
## 功能特性
|
||||
|
||||
### ✅ 已实现功能
|
||||
|
||||
1. **支付订单管理**
|
||||
- 创建Stripe PaymentIntent
|
||||
- 查询支付状态
|
||||
- 支持多种国际货币
|
||||
|
||||
2. **Webhook处理**
|
||||
- 安全的签名验证
|
||||
- 异步支付结果通知
|
||||
- 订单状态同步
|
||||
|
||||
3. **退款管理**
|
||||
- 申请退款
|
||||
- 查询退款状态
|
||||
- 部分退款支持
|
||||
|
||||
4. **安全特性**
|
||||
- Webhook签名验证
|
||||
- 环境变量配置管理
|
||||
- 错误处理和日志记录
|
||||
|
||||
5. **API接口**
|
||||
- RESTful API设计
|
||||
- Swagger文档自动生成
|
||||
- 完整的DTO验证
|
||||
|
||||
## 环境配置
|
||||
|
||||
### 必需的环境变量
|
||||
|
||||
在`.env`文件中添加以下Stripe配置:
|
||||
|
||||
```bash
|
||||
# Stripe配置
|
||||
STRIPE_SECRET_KEY=sk_test_your_secret_key_here
|
||||
STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key_here
|
||||
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here
|
||||
|
||||
# 服务器配置(用于回调URL)
|
||||
SERVER_URL=https://your-domain.com
|
||||
```
|
||||
|
||||
### 获取Stripe密钥
|
||||
|
||||
1. **注册Stripe账号**
|
||||
- 访问 [stripe.com](https://stripe.com)
|
||||
- 创建账号并完成验证
|
||||
|
||||
2. **获取API密钥**
|
||||
- 登录Stripe Dashboard
|
||||
- 进入"开发者" -> "API密钥"
|
||||
- 复制可发布密钥和密钥
|
||||
|
||||
3. **设置Webhook**
|
||||
- 进入"开发者" -> "Webhook"
|
||||
- 添加端点:`https://your-domain.com/api/v1/payment/stripe/webhook`
|
||||
- 选择事件:`payment_intent.succeeded`
|
||||
- 复制签名密钥
|
||||
|
||||
## API使用指南
|
||||
|
||||
### 1. 创建支付订单
|
||||
|
||||
```bash
|
||||
POST /api/v1/payment/stripe/create-order
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"userId": "user_123",
|
||||
"businessType": "credit_purchase",
|
||||
"businessId": "credits_500",
|
||||
"amount": 4800,
|
||||
"currency": "USD",
|
||||
"description": "购买500积分包",
|
||||
"customerEmail": "user@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"orderId": "order_123",
|
||||
"paymentIntentId": "pi_test_123",
|
||||
"clientSecret": "pi_test_123_secret_abc",
|
||||
"publishableKey": "pk_test_123",
|
||||
"amount": 4800,
|
||||
"currency": "USD",
|
||||
"status": "pending",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 查询订单状态
|
||||
|
||||
```bash
|
||||
GET /api/v1/payment/stripe/order/{orderId}
|
||||
```
|
||||
|
||||
### 3. 申请退款
|
||||
|
||||
```bash
|
||||
POST /api/v1/payment/stripe/refund
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"orderId": "order_123",
|
||||
"refundAmount": 2400,
|
||||
"reason": "用户申请退款"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 查询退款状态
|
||||
|
||||
```bash
|
||||
GET /api/v1/payment/stripe/refund/{refundId}
|
||||
```
|
||||
|
||||
### 5. 获取支持的货币
|
||||
|
||||
```bash
|
||||
GET /api/v1/payment/stripe/supported-currencies
|
||||
```
|
||||
|
||||
## 前端集成示例
|
||||
|
||||
### React + Stripe Elements
|
||||
|
||||
```javascript
|
||||
import { loadStripe } from '@stripe/stripe-js';
|
||||
import {
|
||||
Elements,
|
||||
CardElement,
|
||||
useStripe,
|
||||
useElements
|
||||
} from '@stripe/react-stripe-js';
|
||||
|
||||
const stripePromise = loadStripe('pk_test_your_publishable_key');
|
||||
|
||||
function PaymentForm({ clientSecret }) {
|
||||
const stripe = useStripe();
|
||||
const elements = useElements();
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!stripe || !elements) return;
|
||||
|
||||
const cardElement = elements.getElement(CardElement);
|
||||
|
||||
const { error, paymentIntent } = await stripe.confirmCardPayment(
|
||||
clientSecret,
|
||||
{
|
||||
payment_method: {
|
||||
card: cardElement,
|
||||
billing_details: {
|
||||
email: 'user@example.com',
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (error) {
|
||||
console.error('支付失败:', error);
|
||||
} else {
|
||||
console.log('支付成功:', paymentIntent);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<CardElement />
|
||||
<button type="submit" disabled={!stripe}>
|
||||
支付
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [clientSecret, setClientSecret] = useState('');
|
||||
|
||||
// 创建支付订单获取clientSecret
|
||||
useEffect(() => {
|
||||
fetch('/api/v1/payment/stripe/create-order', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
userId: 'user_123',
|
||||
businessType: 'credit_purchase',
|
||||
businessId: 'credits_500',
|
||||
amount: 4800,
|
||||
currency: 'USD'
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => setClientSecret(data.clientSecret));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Elements stripe={stripePromise}>
|
||||
<PaymentForm clientSecret={clientSecret} />
|
||||
</Elements>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 支持的货币
|
||||
|
||||
| 货币代码 | 货币名称 | 符号 | 最小单位 |
|
||||
|---------|---------|------|---------|
|
||||
| USD | 美元 | $ | 2位小数 |
|
||||
| EUR | 欧元 | € | 2位小数 |
|
||||
| GBP | 英镑 | £ | 2位小数 |
|
||||
| JPY | 日元 | ¥ | 0位小数 |
|
||||
| AUD | 澳元 | A$ | 2位小数 |
|
||||
| CAD | 加元 | C$ | 2位小数 |
|
||||
| SGD | 新加坡元 | S$ | 2位小数 |
|
||||
| HKD | 港币 | HK$ | 2位小数 |
|
||||
|
||||
## 测试
|
||||
|
||||
### 运行单元测试
|
||||
|
||||
```bash
|
||||
# 运行Stripe适配器测试
|
||||
npm test stripe-payment.adapter.spec.ts
|
||||
|
||||
# 运行所有支付相关测试
|
||||
npm test payment
|
||||
```
|
||||
|
||||
### 测试用卡号
|
||||
|
||||
Stripe提供以下测试卡号:
|
||||
|
||||
- **成功支付**: 4242 4242 4242 4242
|
||||
- **需要验证**: 4000 0025 0000 3155
|
||||
- **被拒绝**: 4000 0000 0000 0002
|
||||
- **余额不足**: 4000 0000 0000 9995
|
||||
|
||||
使用任意未来日期作为过期时间,任意3位数字作为CVC。
|
||||
|
||||
## 监控和日志
|
||||
|
||||
### 日志级别
|
||||
|
||||
- **INFO**: 正常的支付流程日志
|
||||
- **WARN**: 配置问题和可恢复错误
|
||||
- **ERROR**: 支付失败和系统错误
|
||||
|
||||
### 关键监控指标
|
||||
|
||||
1. **支付成功率**
|
||||
2. **响应时间**
|
||||
3. **错误率**
|
||||
4. **退款处理时间**
|
||||
|
||||
## 安全注意事项
|
||||
|
||||
1. **密钥管理**
|
||||
- 绝不在客户端暴露密钥
|
||||
- 使用环境变量存储敏感信息
|
||||
- 定期轮换API密钥
|
||||
|
||||
2. **Webhook安全**
|
||||
- 始终验证Webhook签名
|
||||
- 使用HTTPS端点
|
||||
- 实现幂等性处理
|
||||
|
||||
3. **金额处理**
|
||||
- 服务端验证所有金额
|
||||
- 使用整数避免浮点精度问题
|
||||
- 实现金额限制和验证
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **支付失败**
|
||||
- 检查Stripe密钥配置
|
||||
- 验证货币代码格式
|
||||
- 确认金额范围有效
|
||||
|
||||
2. **Webhook失败**
|
||||
- 验证端点URL可访问
|
||||
- 检查签名密钥配置
|
||||
- 确认事件类型选择
|
||||
|
||||
3. **退款问题**
|
||||
- 确认订单支付成功
|
||||
- 检查退款金额限制
|
||||
- 验证Charge ID存在
|
||||
|
||||
### 调试步骤
|
||||
|
||||
1. 查看应用日志
|
||||
2. 检查Stripe Dashboard事件
|
||||
3. 验证Webhook配置
|
||||
4. 测试API端点连通性
|
||||
|
||||
## 部署注意事项
|
||||
|
||||
### 生产环境
|
||||
|
||||
1. 使用生产环境Stripe密钥
|
||||
2. 配置HTTPS回调地址
|
||||
3. 设置适当的日志级别
|
||||
4. 配置监控和告警
|
||||
|
||||
### 性能优化
|
||||
|
||||
1. 使用数据库连接池
|
||||
2. 实现适当的缓存策略
|
||||
3. 配置合理的超时时间
|
||||
4. 监控内存和CPU使用
|
||||
|
||||
## 更新日志
|
||||
|
||||
- **v1.0.0**: 初始Stripe集成实现
|
||||
- 支付订单创建
|
||||
- Webhook处理
|
||||
- 退款功能
|
||||
- 多货币支持
|
||||
- 完整测试覆盖
|
||||
|
||||
---
|
||||
|
||||
## 技术支持
|
||||
|
||||
如有问题,请参考:
|
||||
1. [Stripe官方文档](https://stripe.com/docs)
|
||||
2. [项目API文档](/docs)
|
||||
3. 查看应用日志和错误信息
|
||||
Reference in New Issue
Block a user