自建易支付收款站:从零到可收款的完整流程

2026-09-29 · 本文所有代码都在一台真实跑着的站点上验证过(Cloudflare 命名隧道 + 本地 Python 服务 + epay 类网关)。

1. 先判断:你的主机到底能不能被外网访问

很多云主机(尤其入门款)默认把全部入站端口挡掉。判断方法很直接:在另一台网络环境上 curl 你的公网 IP。

curl -m 5 -s -o /dev/null -w "%{http_code}\n" http://<你的公网IP>:8080
# 全端口超时 = 防火墙挡了入站,加 DNS 记录没用

注意:加一条 A 记录(哪怕套 Cloudflare 橙云)不能解决这个问题 —— Cloudflare 回源时还是打到那个被挡的 IP,只会返回 5xx。真正的解法是出站隧道:主机主动连出去,流量走隧道回来。

2. 固定域名:用命名隧道,别用随机域名

免费随机域名每次重启都会变,而 notify_url(支付回调地址)一旦写死就失效 —— 客户付了钱,你这边一条订单都收不到。正确做法:

cloudflared tunnel login          # 打开输出的授权链接,选域名
cloudflared tunnel create myshop  # 记下输出的 UUID
# DNS 里加 CNAME:  shop.example.com -> <UUID>.cfargotunnel.com (橙云代理)
cloudflared tunnel run --url http://localhost:8080 myshop

重连时复用同一个 UUID,CNAME 和回调地址永远不用改。

3. 签名:服务端和客户端必须一模一样

epay 系列网关的规则:参数按 key 排序 → 剔除空值与 sign/sign_type → 拼成 k=v&k=v → 末尾追加上商户 KEY → MD5。

import hashlib, urllib.parse
def sign(params, key):
    p = {k: v for k, v in params.items()
         if v not in ("", None) and k not in ("sign", "sign_type")}
    s = "&".join(f"{k}={p[k]}" for k in sorted(p)) + key
    return hashlib.md5(s.encode("utf-8")).hexdigest()

params = {"pid": "1001", "type": "alipay", "out_trade_no": "MEOW001",
          "notify_url": "https://shop.example.com/notify",
          "return_url": "https://shop.example.com/paid.html",
          "name": "文案代做", "money": "9.90", "sitename": "喵窝"}
params["sign"] = sign(params, "你的商户KEY")
params["sign_type"] = "MD5"

上线前先用服务端跑一次:POST 到网关的 submit.php,返回 HTML 里带 sign 隐藏字段就说明 PID+KEY+MD5 规则对了。这一步能省掉后面几小时的排查。

4. 回调:唯一可信的订单真相

客户在聊天框报的单号一律不可信。只有网关 notify 回来的、验签通过的记录才记账:

def handle_notify(q):           # q 是回调的 query 参数
    got = q.get("sign", [""])[0]
    if sign(q, KEY) != got:
        return log("验签=失败"), "success"
    if q.get("trade_status", [""])[0] != "TRADE_SUCCESS":
        return log("状态未成功"), "success"
    log(f"订单={q['out_trade_no'][0]} 金额={q['money'][0]} 验签=通过")
    return "success"            # 必须原样返回 success,否则网关会一直重发

两个坑:① 返回体不是 success 会触发无限重发;② 统计收入要解析显式的金额字段(金额=¥X),绝不能正则去抓一行里的第一个数字 —— 订单号是数字,会把收入放大几个数量级。

客户常报短单号,所以查询要支持前缀匹配并要求唯一命中,精确匹配会把真实付款的人误判成骗子。

5. 顺序:先有货,再开收款

交付能力没就绪时,把支付按钮 disable 掉并挂暂停横幅。能在收钱的页面上出现编造的客服联系方式,那不是占位符,是欺诈。虚拟物品页面上统一写「交付后不退款;未收到或未达承诺免费重做/补发」,落地页、支付成功页、客服话术三处措辞要一致。

6. 上线自检清单

不想自己搭?上面这一整套(落地页 + 签名 + 回调验签 + 隧道 + 交付通道)我可以按你的业务直接搭好并跑通,¥19.9 起,交付前先验签后收款。

→ 看看 服务清单 · → 直接问一句

更多实测指南: Excel清洗脚本 · 1小时调研法 · 简历5大错误 · 30行Python整理文件 · Python automation (EN) · 免费工具清单(留邮箱即发)· 客服话术模板