Files
qianyubtcandClaude Fable 5 f87ec65541 BinancePayTool v0.1.0:币安支付个人收款网关(Go 核心 + 四语言 SDK)
- Go 服务端:唯一金额/备注码/回填订单编号三路匹配、托管收银页、HMAC 回调七级重试、SQLite 单二进制
- SDK:Go / Java / PHP / Python,共享签名测试向量(docs/test_vectors.json)
- 跨语言 e2e(真实二进制 × Python SDK × mock 币安)、GitHub Actions CI、Dockerfile
- 协议文档 docs/protocol.md、调研与实测结论 docs/research.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 14:09:32 +08:00

66 lines
1.5 KiB
Go

package main
import (
"context"
"crypto/rand"
"encoding/base64"
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
const version = "0.1.0"
func main() {
cfgPath := flag.String("config", "./config.env", "配置文件路径(KEY=VALUE 格式,环境变量优先)")
showVer := flag.Bool("version", false, "打印版本")
genKey := flag.Bool("gen-key", false, "生成一个随机 API_AUTH_KEY")
flag.Parse()
if *showVer {
fmt.Println("BinancePayTool", version)
return
}
if *genKey {
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil {
log.Fatal(err)
}
fmt.Println(base64.RawURLEncoding.EncodeToString(b))
return
}
cfg, err := loadConfig(*cfgPath)
if err != nil {
log.Fatalf("[fatal] %v", err)
}
app, err := newApp(cfg)
if err != nil {
log.Fatalf("[fatal] 初始化失败: %v", err)
}
defer app.st.Close()
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
go app.matcher.run(ctx)
go app.notifier.run(ctx)
srv := &http.Server{Addr: cfg.Listen, Handler: app.mux}
go func() {
<-ctx.Done()
shutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
srv.Shutdown(shutCtx)
}()
log.Printf("[info] BinancePayTool %s 监听 %s,收款 UID %s,轮询间隔 %ds", version, cfg.Listen, cfg.BinanceUID, cfg.PollInterval)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("[fatal] %v", err)
}
log.Printf("[info] 已退出")
}