维护说明:本文档已并入本站直接维护(单仓重构后原 backend/docs/*.md、前端 docs/*.md 不再随仓库发布)。 实现细节以 pay-unify 源码 为准,页面与源码的对应关系见相关资源

统一支付接口说明

⚠️ 认证已迁移为 OAuth2:/api/v2/* 用 Bearer token(POST /oauth/token 换取), /api/v1/* 用管理员 JWT。本文中的 GoAuth/X-Sign 示例均为旧写法,已替换。

功能概述

已将支付宝和微信的关闭订单、申请退款接口合并为统一接口,通过订单的支付方式自动路由到对应的处理逻辑。

优势

统一API设计 - 一个接口支持所有支付方式
自动识别 - 根据订单支付方式自动调用对应服务
向后兼容 - 保留原有专用接口
易于扩展 - 新增支付方式只需添加case分支
减少维护 - 统一的业务逻辑和错误处理

新增统一接口

1. 关闭订单(统一接口)

接口路径:

POST /api/v1/payment/close/{outTradeNo} POST /api/v2/payment/close/{outTradeNo}

功能说明:

  • 自动识别订单的支付方式(支付宝/微信)
  • 调用对应的关闭订单接口
  • 更新订单状态为已关闭

请求参数:

  • Path参数:outTradeNo - 商户订单号

请求头:

Authorization: Bearer <access_token>

响应示例:

1{
2  "code": 0,
3  "message": "success",
4  "data": {
5    "message": "订单关闭成功",
6    "orderNo": "202501091234567890",
7    "payWay": "alipay"
8  }
9}

2. 申请退款(统一接口)

接口路径:

POST /api/v1/payment/refund POST /api/v2/payment/refund

功能说明:

  • 自动识别订单的支付方式(支付宝/微信)
  • 调用对应的退款接口
  • 支持自定义退款金额
  • 自动处理金额单位转换(微信分/支付宝元)

请求参数:

1{
2  "outTradeNo": "202501091234567890",  // 商户订单号(必填)
3  "refundAmount": 0.01,                 // 退款金额-元(必填)
4  "refundReason": "用户申请退款"         // 退款原因(可选)
5}

请求头:

Authorization: Bearer <access_token>

响应示例:

1{
2  "code": 0,
3  "message": "success",
4  "data": {
5    "message": "退款申请成功",
6    "orderNo": "202501091234567890",
7    "payWay": "alipay",
8    "tradeNo": "2025123122001234567890",
9    "refundAmount": 0.01,
10    "refundRequestNo": "R1234567890123456789",
11    "result": null
12  }
13}

旧专用接口(已下线)

早期版本提供的支付宝 / 微信专用接口(payment/alipay/*payment/wechat/*已在当前实现中注释下线,路由不再注册。请统一使用上面的 payment/closepayment/refund 接口。

源码位置:backend/internal/handler/payment_handler.go(专用路由已被注释)。


实现原理

关闭订单流程

1. 验证应用身份 ↓ 2. 查询订单信息 ↓ 3. 检查订单状态 ↓ 4. 根据 payWay 字段判断 ├─ alipay → 调用 AlipayService.TradeClose() └─ wechat → 调用 WechatPayService.CloseOrder() ↓ 5. 更新订单状态为已关闭

退款流程

1. 验证应用身份 ↓ 2. 查询订单信息 ↓ 3. 检查订单状态和退款金额 ↓ 4. 生成唯一退款请求号 ↓ 5. 根据 payWay 字段判断 ├─ alipay → 调用 AlipayService.TradeRefund() │ 参数:金额单位为元 └─ wechat → 调用 WechatPayService.Refund() 参数:金额单位为分(自动转换) ↓ 6. 更新订单状态为已退款

核心代码

关闭订单

1// 根据支付方式调用不同的关闭接口
2switch order.PayWay {
3case "alipay":
4    err = h.alipayService.TradeClose(outTradeNo)
5case "wechat":
6    result := h.WechatPayService.CloseOrder(outTradeNo)
7default:
8    return error("不支持的支付方式")
9}

申请退款

1// 根据支付方式调用不同的退款接口
2switch order.PayWay {
3case "alipay":
4    // 支付宝:金额单位为元
5    tradeNo, err = h.alipayService.TradeRefund(AlipayRefundParams{
6        RefundAmount: req.RefundAmount,  // 元
7    })
8case "wechat":
9    // 微信:金额单位为分,需要转换
10    refundFee := int(req.RefundAmount * 100)  // 元转分
11    result, err = h.WechatPayService.Refund(WechatRefundParams{
12        RefundFee: refundFee,  // 分
13    })
14}

使用示例

统一关闭订单

1# 先换 Bearer token
2TOKEN=$(curl -s -X POST http://localhost:8097/oauth/token \
3  -H 'Content-Type: application/json' \
4  -d '{"grant_type":"client_credentials","client_id":"your-client-id","client_secret":"your-secret"}' \
5  | jq -r .access_token)
6
7# 关闭支付宝订单
8curl -X POST 'http://localhost:8097/api/v2/payment/close/202501091234567890' \
9  -H "Authorization: Bearer $TOKEN"
10
11# 关闭微信订单(相同接口)
12curl -X POST 'http://localhost:8097/api/v2/payment/close/202501099876543210' \
13  -H "Authorization: Bearer $TOKEN"

统一申请退款

1# 支付宝退款
2curl -X POST 'http://localhost:8097/api/v2/payment/refund' \
3  -H 'Content-Type: application/json' \
4  -H "Authorization: Bearer $TOKEN" \
5  -d '{
6    "outTradeNo": "202501091234567890",
7    "refundAmount": 0.01,
8    "refundReason": "用户申请退款"
9  }'
10
11# 微信退款(相同接口,相同参数格式)
12curl -X POST 'http://localhost:8097/api/v2/payment/refund' \
13  -H 'Content-Type: application/json' \
14  -H "Authorization: Bearer $TOKEN" \
15  -d '{
16    "outTradeNo": "202501099876543210",
17    "refundAmount": 1.00,
18    "refundReason": "商品质量问题"
19  }'

接口对比

功能 旧专用接口(已下线) 统一接口 说明
关闭支付宝订单 payment/alipay/close/:id payment/close/:id 统一接口
关闭微信订单 payment/wechat/close/:id payment/close/:id 统一接口
支付宝退款 payment/alipay/refund payment/refund 统一接口
微信退款 payment/wechat/refund payment/refund 统一接口

扩展支持新支付方式

如需添加新的支付方式(如PayPal),只需:

1. 在关闭订单接口添加case:

1case "paypal":
2    err = h.PaypalService.CloseOrder(outTradeNo)

2. 在退款接口添加case:

1case "paypal":
2    result, err = h.PaypalService.Refund(PaypalRefundParams{
3        OutTradeNo:   req.OutTradeNo,
4        RefundAmount: req.RefundAmount,  // 根据PayPal要求的单位
5        RefundReason: req.RefundReason,
6    })

注意事项

1. 金额单位处理

  • 统一接口输入:金额单位为元(float64)
  • 支付宝:金额单位为元,直接使用
  • 微信:金额单位为分,需要转换(元 × 100)

2. 向后兼容

  • 旧的专用接口仍然可用
  • 建议新项目使用统一接口
  • 逐步迁移旧项目到统一接口

3. 错误处理

  • 统一的错误响应格式
  • 详细的错误日志记录
  • 返回支付方式信息便于调试

4. 权限验证

  • 所有接口均需 OAuth2 Bearer 认证(POST /oauth/token 换取,见认证体系
  • 自动验证订单归属权
  • 只能操作本应用的订单

API文档

访问 Swagger 文档查看完整 API 定义:

  • 开发环境:http://localhost:8097/swagger/index.html
  • 搜索关键词:payment/closepayment/refund

相关文件

均在 backend/ 下:

  • internal/handler/payment_handler.go - 统一接口实现
  • internal/pkg/service/payment/alipay_service.go - 支付宝服务
  • internal/pkg/service/payment/wepay_service.go - 微信服务

更新日期: 2025-12-31
版本: v1.0
状态: 已完成并部署