在实际 Web 开发中,支付宝和微信支付的异步回调接口 是支付系统的重要一环。
当用户完成支付后,第三方支付平台(如支付宝、微信)会向商户的回调地址发送支付结果通知。
商户系统收到回调数据后,需要验证签名、更新订单状态,并返回响应。
本篇我们将用 Go(Gin 框架)实现一个模拟的支付宝/微信支付回调接口,方便本地测试与学习。
一、功能目标
-
- 提供
/alipay/callback
和/wechat/callback
两个回调接口。
- 提供
-
- 接收 POST 请求中的支付结果参数(模拟)。
-
- 校验签名(简单模拟,不接入真实加密算法)。
-
- 根据支付状态更新订单状态(内存模拟)。
-
- 返回支付平台期望的响应格式。
二、项目结构
go
project/
│── main.go
└── orders.go (订单状态管理模拟)
三、代码实现
go
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"sync"
)
var (
orderStore = make(map[string]string) // orderID -> status
mu sync.Mutex
)
// 模拟订单更新
func updateOrderStatus(orderID, status string) {
mu.Lock()
defer mu.Unlock()
orderStore[orderID] = status
fmt.Printf("订单 %s 状态更新为 %s\n", orderID, status)
}
// 模拟签名验证(实际需用支付宝/微信 SDK)
func verifySignature(params map[string]string, sign string) bool {
// 实际业务中应根据支付宝/微信签名算法进行验证
return sign == "valid-sign"
}
// 支付宝回调
func alipayCallback(c *gin.Context) {
orderID := c.PostForm("out_trade_no")
status := c.PostForm("trade_status")
sign := c.PostForm("sign")
if !verifySignature(map[string]string{
"out_trade_no": orderID,
"trade_status": status,
}, sign) {
c.String(http.StatusBadRequest, "invalid sign")
return
}
if status == "TRADE_SUCCESS" {
updateOrderStatus(orderID, "已支付")
}
// 支付宝期望返回 "success"
c.String(http.StatusOK, "success")
}
// 微信回调(JSON 格式)
func wechatCallback(c *gin.Context) {
var data struct {
OrderID string `json:"out_trade_no"`
Status string `json:"trade_state"`
Sign string `json:"sign"`
}
if err := c.ShouldBindJSON(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if !verifySignature(map[string]string{
"out_trade_no": data.OrderID,
"trade_state": data.Status,
}, data.Sign) {
c.JSON(http.StatusBadRequest, gin.H{"message": "invalid sign"})
return
}
if data.Status == "SUCCESS" {
updateOrderStatus(data.OrderID, "已支付")
}
// 微信期望返回 XML 格式
c.String(http.StatusOK, `<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>`)
}
func main() {
r := gin.Default()
r.POST("/alipay/callback", alipayCallback)
r.POST("/wechat/callback", wechatCallback)
// 查询订单状态(方便测试)
r.GET("/order/:id", func(c *gin.Context) {
id := c.Param("id")
mu.Lock()
status, exists := orderStore[id]
mu.Unlock()
if !exists {
c.JSON(http.StatusNotFound, gin.H{"error": "订单不存在"})
return
}
c.JSON(http.StatusOK, gin.H{"order_id": id, "status": status})
})
r.Run(":8080")
}
四、测试方法
1. 模拟支付宝回调
bash
curl -X POST http://localhost:8080/alipay/callback \
-d "out_trade_no=12345&trade_status=TRADE_SUCCESS&sign=valid-sign"
返回:
success
查询订单:
bash
curl http://localhost:8080/order/12345
返回:
json
{"order_id":"12345","status":"已支付"}
2. 模拟微信回调
json
curl -X POST http://localhost:8080/wechat/callback \
-H "Content-Type: application/json" \
-d '{"out_trade_no":"67890","trade_state":"SUCCESS","sign":"valid-sign"}'
返回:
xml
<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>
查询订单:
bash
curl http://localhost:8080/order/67890
五、注意事项
-
- 签名验证
-
- • 示例中只是模拟验证,真实生产环境必须使用支付宝/微信提供的 SDK 和密钥。
-
- 回调幂等性
-
- • 支付平台可能会多次发送相同回调,处理逻辑必须保证幂等(不要重复更新订单状态)。
-
- 安全
-
- • 回调接口应只允许支付平台访问,可考虑验证来源 IP、HTTPS 等安全措施。
六、总结
本篇示例展示了支付宝与微信异步回调接口的核心流程 :
接收参数 → 验证签名 → 更新订单状态 → 返回响应。
在真实生产环境中,需要结合官方文档与 SDK,实现完整的签名算法与安全策略。