Skip to content

Latest commit

 

History

History
493 lines (378 loc) · 10.4 KB

File metadata and controls

493 lines (378 loc) · 10.4 KB

Boxn API 支付集成文档

概述

本文档介绍了如何在 PitchMaster.ai 项目中集成 Boxn API 的支付功能。集成包括创建订单、处理支付、管理退款以及处理 webhook 通知。

文件结构

src/
├── api/
│   └── payment.ts          # 支付 API 客户端
├── stores/
│   └── pay.ts             # 支付状态管理 (Pinia store)
├── components/
│   └── PaymentForm.vue    # 支付表单组件
└── utils/
    └── paymentWebhook.ts  # Webhook 处理工具

快速开始

1. 环境配置

在项目根目录创建或更新 .env 文件:

# Boxn API 配置
VITE_BOXN_API_BASE_URL=https://boxn-api.onrender.com
VITE_BOXN_API_TOKEN=your_api_token_here
VITE_BOXN_WEBHOOK_SECRET=your_webhook_secret_here

2. 设置认证令牌

在应用启动时设置 Boxn API 认证令牌:

// 在 main.ts 或用户登录后
localStorage.setItem('boxn_token', 'your_api_token');

3. 使用支付 Store

import { usePaymentStore } from '@/stores/pay';

const paymentStore = usePaymentStore();

// 创建订单
const order = await paymentStore.createOrder({
  product_id: 'premium_subscription',
  quantity: 1,
  currency: 'CNY'
});

// 检查订单状态
const status = await paymentStore.getOrderStatus(order.order_id);

// 加载支付历史
await paymentStore.loadPaymentHistory();

API 接口

创建订单

POST /api/payments/orders

请求参数:

interface CreateOrderRequest {
  product_id: string;        // 产品ID
  quantity?: number;         // 数量 (默认: 1)
  currency?: string;         // 货币 (默认: CNY)
  metadata?: Record<string, unknown>; // 元数据
}

响应:

interface CreateOrderResponse {
  order_id: string;          // 订单ID
  payment_url: string;       // 支付链接
  amount: number;            // 金额
  currency: string;          // 货币
  status: string;            // 状态
  created_at: string;        // 创建时间
  expires_at: string;        // 过期时间
}

查询订单状态

GET /api/payments/orders/{order_id}

响应:

interface OrderStatusResponse {
  order_id: string;          // 订单ID
  status: string;            // 状态
  amount: number;            // 金额
  currency: string;          // 货币
  payment_method?: string;   // 支付方式
  paid_at?: string;          // 支付时间
  created_at: string;        // 创建时间
  metadata?: Record<string, unknown>; // 元数据
}

支付历史

GET /api/payments/history?page=1&limit=10

响应:

interface PaymentHistoryResponse {
  orders: OrderStatusResponse[]; // 订单列表
  total: number;                 // 总数
  page: number;                  // 当前页
  limit: number;                 // 每页数量
}

申请退款

POST /api/payments/refunds

请求参数:

interface RefundRequest {
  order_id: string;          // 订单ID
  amount?: number;           // 退款金额 (默认全额)
  reason?: string;           // 退款原因
}

组件使用

PaymentForm 组件

<template>
  <PaymentForm />
</template>

<script setup>
import PaymentForm from '@/components/PaymentForm.vue';
</script>

该组件提供以下功能:

  • 创建支付订单
  • 显示当前订单状态
  • 查看支付历史
  • 申请退款
  • 实时状态更新

Webhook 处理

设置 Webhook 端点

在你的后端服务中设置 webhook 端点:

// 示例:Express.js 后端
app.post('/webhooks/payment', async (req, res) => {
  const signature = req.headers['x-boxn-signature'];
  const payload = JSON.stringify(req.body);
  
  const isValid = await webhookUtils.processWebhookFromRequest(
    payload,
    signature,
    process.env.BOXN_WEBHOOK_SECRET
  );
  
  if (isValid) {
    res.status(200).json({ success: true });
  } else {
    res.status(400).json({ error: 'Invalid signature' });
  }
});

Webhook 事件类型

  • payment.completed - 支付完成
  • payment.failed - 支付失败
  • payment.refunded - 退款完成
  • payment.cancelled - 支付取消

自定义 Webhook 处理

import { PaymentWebhookHandler } from '@/utils/paymentWebhook';

class CustomWebhookHandler extends PaymentWebhookHandler {
  async handlePaymentCompleted(event) {
    // 调用父类方法
    await super.handlePaymentCompleted(event);
    
    // 自定义业务逻辑
    await this.sendConfirmationEmail(event);
    await this.updateUserSubscription(event);
    await this.triggerAnalytics(event);
  }
  
  private async sendConfirmationEmail(event) {
    // 发送确认邮件
  }
  
  private async updateUserSubscription(event) {
    // 更新用户订阅状态
  }
  
  private async triggerAnalytics(event) {
    // 触发分析事件
  }
}

状态管理

Store 状态

const paymentStore = usePaymentStore();

// 状态
paymentStore.currentOrder      // 当前订单
paymentStore.orderHistory      // 订单历史
paymentStore.paymentMethods    // 支付方式
paymentStore.isLoading         // 加载状态
paymentStore.error            // 错误信息
paymentStore.pagination       // 分页信息

// 计算属性
paymentStore.hasActiveOrder    // 是否有活跃订单
paymentStore.totalSpent        // 总消费金额
paymentStore.completedOrders   // 已完成订单
paymentStore.pendingOrders     // 待处理订单

Store 方法

// 创建订单
await paymentStore.createOrder(orderData);

// 查询订单状态
await paymentStore.getOrderStatus(orderId);

// 加载支付历史
await paymentStore.loadPaymentHistory(page, limit);

// 申请退款
await paymentStore.requestRefund(refundData);

// 加载支付方式
await paymentStore.loadPaymentMethods();

// 清除当前订单
paymentStore.clearCurrentOrder();

// 清除错误
paymentStore.clearError();

// 重置状态
paymentStore.reset();

错误处理

常见错误

  1. 认证失败

    // 检查 token 是否有效
    const token = localStorage.getItem('boxn_token');
    if (!token) {
      // 重定向到登录页面
    }
  2. 网络错误

    try {
      await paymentStore.createOrder(orderData);
    } catch (error) {
      if (error.response?.status === 500) {
        // 服务器错误
      } else if (error.code === 'NETWORK_ERROR') {
        // 网络错误
      }
    }
  3. 订单状态错误

    // 定期检查订单状态
    const checkOrderStatus = async (orderId: string) => {
      try {
        await paymentStore.getOrderStatus(orderId);
      } catch (error) {
        console.error('Failed to check order status:', error);
      }
    };

安全最佳实践

1. 令牌管理

  • 不要在客户端代码中硬编码 API 令牌
  • 使用环境变量存储敏感信息
  • 定期轮换 API 令牌

2. Webhook 安全

  • 始终验证 webhook 签名
  • 使用 HTTPS 端点
  • 实现幂等性处理

3. 错误处理

  • 不要在前端暴露敏感错误信息
  • 实现适当的重试机制
  • 记录错误日志用于调试

4. 数据验证

// 验证订单数据
const validateOrderData = (data: CreateOrderRequest) => {
  if (!data.product_id) {
    throw new Error('Product ID is required');
  }
  
  if (data.quantity && data.quantity < 1) {
    throw new Error('Quantity must be at least 1');
  }
  
  const validCurrencies = ['CNY', 'USD', 'EUR'];
  if (data.currency && !validCurrencies.includes(data.currency)) {
    throw new Error('Invalid currency');
  }
};

测试

单元测试

import { describe, it, expect, vi } from 'vitest';
import { usePaymentStore } from '@/stores/pay';

describe('Payment Store', () => {
  it('should create order successfully', async () => {
    const store = usePaymentStore();
    
    const mockResponse = {
      order_id: 'test_order_123',
      payment_url: 'https://payment.example.com',
      amount: 100,
      currency: 'CNY',
      status: 'pending',
      created_at: '2024-01-01T00:00:00Z',
      expires_at: '2024-01-01T01:00:00Z'
    };
    
    vi.spyOn(paymentApi, 'createOrder').mockResolvedValue(mockResponse);
    
    const result = await store.createOrder({
      product_id: 'test_product',
      quantity: 1,
      currency: 'CNY'
    });
    
    expect(result).toEqual(mockResponse);
    expect(store.currentOrder).toEqual(mockResponse);
  });
});

集成测试

// 测试完整的支付流程
describe('Payment Flow', () => {
  it('should complete payment flow', async () => {
    // 1. 创建订单
    const order = await paymentStore.createOrder({
      product_id: 'premium_subscription',
      quantity: 1,
      currency: 'CNY'
    });
    
    expect(order.status).toBe('pending');
    
    // 2. 模拟支付完成
    await paymentStore.getOrderStatus(order.order_id);
    
    // 3. 验证状态更新
    expect(paymentStore.currentOrder?.status).toBe('completed');
  });
});

部署注意事项

1. 环境变量

确保在生产环境中正确设置所有必要的环境变量:

# 生产环境
VITE_BOXN_API_BASE_URL=https://boxn-api.onrender.com
VITE_BOXN_API_TOKEN=prod_token_here
VITE_BOXN_WEBHOOK_SECRET=prod_webhook_secret_here

2. CORS 配置

确保 Boxn API 允许你的域名访问:

// 在 Boxn API 控制台中配置允许的域名
const allowedOrigins = [
  'https://yourdomain.com',
  'https://www.yourdomain.com'
];

3. 监控和日志

  • 设置错误监控 (如 Sentry)
  • 记录支付相关日志
  • 监控 webhook 处理状态

故障排除

常见问题

  1. API 调用失败

    • 检查网络连接
    • 验证 API 令牌
    • 确认 API 端点正确
  2. Webhook 不工作

    • 检查 webhook URL 是否正确
    • 验证签名密钥
    • 查看服务器日志
  3. 订单状态不同步

    • 实现定期状态检查
    • 使用 webhook 实时更新
    • 添加手动刷新功能

调试工具

// 启用调试模式
const DEBUG_PAYMENT = true;

if (DEBUG_PAYMENT) {
  console.log('Payment API Request:', requestData);
  console.log('Payment API Response:', responseData);
}

更新日志

v1.0.0 (2024-01-01)

  • 初始版本
  • 支持基本支付功能
  • 集成 Boxn API
  • 实现 webhook 处理

支持

如有问题,请参考: