订单处理指南

本文档介绍如何管理 Vibany 平台的支付订单,包括订单查询、状态更新和退款处理。

订单系统概述

Vibany 的订单系统用于管理用户积分充值。支持支付宝、微信支付(易支付)和 Stripe 支付方式。

订单状态

状态说明触发条件
PENDING待支付订单创建后
SUCCESS支付成功收到支付回调且验证通过
FAILED支付失败支付超时或用户取消
REFUND已退款管理员手动退款

订单数据结构

// lib/db/schema.ts
orders {
  id: string;                    // 订单 ID
  userId: string;                // 用户 ID
  buyerId: string;               // 购买者 ID
  type: string;                  // "credit" 或 "debit"
  amount: number;                // 积分数量
  status: OrderStatus;           // 订单状态
  paymentMethod: string;         // 支付方式
  outTradeNo: string;            // 商户订单号
  tradeNo: string;               // 支付平台订单号
  qrCodeUrl: string;             // 支付二维码 URL
  paidAt: Date;                  // 支付时间
  refundedAt: Date;              // 退款时间
  extra: object;                 // 扩展信息
  createdAt: Date;               // 创建时间
}

查看订单

通过 Admin 后台

  1. 访问 /admin/orders
  2. 查看所有订单列表
  3. 支持筛选(按状态、支付方式、时间)
  4. 支持搜索(按订单号、用户邮箱)

通过数据库查询

-- 查看最近订单
SELECT * FROM orders 
ORDER BY created_at DESC 
LIMIT 20;

-- 查看特定用户订单
SELECT * FROM orders 
WHERE user_id = 'user_xxx'
ORDER BY created_at DESC;

-- 查看待支付订单
SELECT * FROM orders 
WHERE status = 'PENDING'
AND created_at > NOW() - INTERVAL '24 hours';

-- 查看支付成功订单统计
SELECT 
  DATE(created_at) as date,
  COUNT(*) as order_count,
  SUM(amount) as total_points
FROM orders
WHERE status = 'SUCCESS'
GROUP BY DATE(created_at)
ORDER BY date DESC;

支付回调处理

易支付回调

回调地址

POST https://yourdomain.com/api/public/epay/notify

处理流程

  1. 接收回调数据
  2. 验证 RSA 签名
  3. 检查订单状态
  4. 更新订单为 SUCCESS
  5. 充值用户积分
  6. 处理邀请奖励(如果有)

Stripe Webhook

回调地址

POST https://yourdomain.com/api/public/stripe/notify

监听事件

  • checkout.session.completed
  • checkout.session.async_payment_succeeded

本地测试

stripe listen --forward-to localhost:3000/api/public/stripe/notify

手动处理订单

标记订单为已支付

当支付回调未能正常处理时,可能需要手动标记订单:

-- 更新订单状态
UPDATE orders 
SET 
  status = 'SUCCESS',
  paid_at = NOW(),
  trade_no = 'manual_fix_xxx'
WHERE id = 'order_xxx';

-- 充值积分(需要同时执行)
UPDATE wallets
SET permanent_points = permanent_points + (SELECT amount FROM orders WHERE id = 'order_xxx')
WHERE user_id = (SELECT user_id FROM orders WHERE id = 'order_xxx');

退款处理

通过 Admin 后台

  1. 找到订单
  2. 点击 "退款"
  3. 确认退款金额
  4. 系统会自动扣除用户积分并标记订单为 REFUND

通过 API

// 处理退款
await processRefund({
  orderId: 'order_xxx',
  reason: '用户要求退款',
  adminId: 'admin_xxx'
});

数据库操作

-- 标记订单为已退款
UPDATE orders 
SET 
  status = 'REFUND',
  refunded_at = NOW()
WHERE id = 'order_xxx';

-- 扣除用户积分
UPDATE wallets
SET permanent_points = permanent_points - (SELECT amount FROM orders WHERE id = 'order_xxx')
WHERE user_id = (SELECT user_id FROM orders WHERE id = 'order_xxx');

订单统计

收入统计

-- 每日收入统计
SELECT 
  DATE(created_at) as date,
  COUNT(*) as order_count,
  SUM(amount) as total_points,
  payment_method,
  COUNT(CASE WHEN status = 'SUCCESS' THEN 1 END) as success_count
FROM orders
WHERE status = 'SUCCESS'
GROUP BY DATE(created_at), payment_method
ORDER BY date DESC;

-- 月度汇总
SELECT 
  DATE_TRUNC('month', created_at) as month,
  COUNT(*) as total_orders,
  SUM(CASE WHEN status = 'SUCCESS' THEN amount ELSE 0 END) as revenue_points
FROM orders
GROUP BY DATE_TRUNC('month', created_at)
ORDER BY month DESC;

支付方式分析

SELECT 
  payment_method,
  COUNT(*) as order_count,
  SUM(amount) as total_amount,
  AVG(amount) as avg_amount
FROM orders
WHERE status = 'SUCCESS'
GROUP BY payment_method;

常见问题

订单状态不同步

症状:用户已支付但订单仍显示 PENDING

排查步骤

  1. 检查支付平台是否发送了回调
  2. 查看服务器日志中的回调处理记录
  3. 验证回调签名是否正确
  4. 检查数据库连接是否正常

解决方案

  1. 手动查询支付平台确认支付状态
  2. 手动更新订单状态
  3. 检查并修复回调配置

重复支付

原因:用户多次点击支付按钮

处理

// 检查订单是否已处理
if (order.status === 'SUCCESS') {
  return { message: 'Order already processed' };
}

支付回调失败

检查清单

  • 回调 URL 可访问
  • HTTPS 证书有效
  • 服务器防火墙允许外部访问
  • 请求体未被修改(Nginx 配置)

Stripe Webhook 验证失败

解决方案

  1. 确认 STRIPE_WEBHOOK_SECRET 正确
  2. 检查请求体是否原样传递
  3. 使用 stripe listen 本地测试

对账流程

每日对账

  1. 导出平台数据

    • 从易支付后台导出当日交易
    • 从 Stripe Dashboard 导出交易
  2. 对比系统数据

    SELECT 
      out_trade_no,
      amount,
      status,
      created_at
    FROM orders
    WHERE DATE(created_at) = CURRENT_DATE - 1
    ORDER BY created_at;
    
  3. 处理差异

    • 平台有但系统无:手动补单
    • 系统有但平台无:检查是否为测试数据

最佳实践

  1. 幂等性:确保同一笔支付不会被重复处理
  2. 日志记录:所有支付操作都要有详细日志
  3. 监控告警:设置订单异常监控
  4. 定期对账:每日/每周进行对账
  5. 备份数据:定期备份订单数据

相关文档

© copyright Justin 2025. All rights reserved.