Go语言实战案例:接入支付宝/微信模拟支付回调接口

在实际 Web 开发中,支付宝和微信支付的异步回调接口 是支付系统的重要一环。

当用户完成支付后,第三方支付平台(如支付宝、微信)会向商户的回调地址发送支付结果通知。

商户系统收到回调数据后,需要验证签名、更新订单状态,并返回响应。

本篇我们将用 Go(Gin 框架)实现一个模拟的支付宝/微信支付回调接口,方便本地测试与学习。


一、功能目标

    1. 提供 /alipay/callback/wechat/callback 两个回调接口。
    1. 接收 POST 请求中的支付结果参数(模拟)。
    1. 校验签名(简单模拟,不接入真实加密算法)。
    1. 根据支付状态更新订单状态(内存模拟)。
    1. 返回支付平台期望的响应格式。

二、项目结构

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

五、注意事项

    1. 签名验证
    • • 示例中只是模拟验证,真实生产环境必须使用支付宝/微信提供的 SDK 和密钥。
    1. 回调幂等性
    • • 支付平台可能会多次发送相同回调,处理逻辑必须保证幂等(不要重复更新订单状态)。
    1. 安全
    • • 回调接口应只允许支付平台访问,可考虑验证来源 IP、HTTPS 等安全措施。

六、总结

本篇示例展示了支付宝与微信异步回调接口的核心流程

接收参数 → 验证签名 → 更新订单状态 → 返回响应。

在真实生产环境中,需要结合官方文档与 SDK,实现完整的签名算法与安全策略。


相关推荐
tntxia9 小时前
Geo Scene域名修改引起的一些问题
后端
用户298698530149 小时前
Java 实现 Word 文档加密与权限解除
java·后端
vanuan10 小时前
给你的A2A-Agent加把锁-认证鉴权实战指南
后端
Yeats_Liao10 小时前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿10 小时前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试
武子康10 小时前
调查研究-201 Rust 里的 dev build 和 release build:为什么同一份代码性能差这么多?
后端·架构·rust
石小石Orz10 小时前
AI具身交互:实现一个会说话的3D虚拟伴侣
前端·人工智能·后端
Ai拆代码的曹操10 小时前
容器 CPU Throttling 有多坑?K8s CFS 限制让 P99 慢了 16 倍
后端
夕阳与风馨10 小时前
大文件(20GB+)SFTP 下载模块设计与实现
后端·架构