feat: 微信V3 + 支付宝手机站/UA自适应 + 业务对接(签名下单/webhook) + 通用多业务

- 微信支付 V3 Native 渠道 (wechat.go):Native下单/回调AES-GCM解密验签/查单
- 支付宝:手机网站支付 wap.pay + 按 UA 自适应(PC page.pay扫码 / 手机拉App);qr_pay_mode=2 完整扫码收银台
- 业务对接:下单接口扩展(biz_system/biz_ref/return_url)+ HMAC 签名鉴权;支付成功 webhook 主动推送业务方 + 60s 重试 + BizNotifyLog
- 通用多业务:config.biz 改 map,加业务只改配置(BIZ_<SYS>_SECRET/_CALLBACK_URL)
- seedPlans:四档真实套餐 + promo_first_month(¥1) + test_liandiao(0.01),均挂 biz_code;/products 暴露 biz_code
- 删除沙箱 pay.html;对接设计文档入 docs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019UQmqWmV67sXGLrb3U1XXn
This commit is contained in:
2026-07-03 22:44:34 +08:00
parent 6da6964451
commit fd5f56f7de
22 changed files with 861 additions and 122 deletions
+5
View File
@@ -23,6 +23,11 @@ func AmountToCents(s string) (int64, error) {
return int64(math.Round(f * 100)), nil
}
// CentsToAmount 把分(int64)转回 "0.01" 元字符串(微信接口用分,本服务统一用元字符串)。
func CentsToAmount(cents int64) string {
return strconv.FormatFloat(float64(cents)/100, 'f', 2, 64)
}
// AmountEqual 判断两个元金额字符串是否等值(按分比较,避免浮点/格式差异)。
func AmountEqual(a, b string) bool {
ca, err1 := AmountToCents(a)
+22
View File
@@ -0,0 +1,22 @@
package util
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"strings"
)
// HMACSign 用共享密钥对若干片段做 HMAC-SHA256 签名(片段以 \n 连接),返回 base64。
// 业务对接双向共用:pay 校验业务方下单请求签名 + 给回调 payload 签名。
func HMACSign(secret string, parts ...string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(strings.Join(parts, "\n")))
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}
// HMACVerify 常量时间比对签名,防时序侧信道。
func HMACVerify(secret, sig string, parts ...string) bool {
expected := HMACSign(secret, parts...)
return hmac.Equal([]byte(expected), []byte(sig))
}