Files
pay/config/config.go
T
wangjia 6da6964451 初始提交:岩美 pay 收款服务(支付宝当面付 + 多商户多渠道架构)
- Go/Gin/GORM + 纯 Go SQLite(无 cgo)
- Channel 多渠道接口:支付宝当面付(precreate)/电脑网站支付(page.pay) 已实现,微信占位
- 多商户 merchants 表,回调验签+金额核对+幂等+查单兜底
- 收款页/结果页/二维码端点;docs/ 设计文档与部署 Runbook
- 密钥走环境变量/Bitwarden,不入库

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 07:21:48 +08:00

82 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package config
import (
"log"
"strings"
"github.com/spf13/viper"
)
type Config struct {
Server ServerConfig
Database DatabaseConfig
AlipaySandbox AlipaySandboxConfig `mapstructure:"alipay_sandbox"`
QuerySync QuerySyncConfig `mapstructure:"query_sync"`
}
type ServerConfig struct {
Port string `mapstructure:"port"`
Mode string `mapstructure:"mode"` // debug | release
BaseURL string `mapstructure:"base_url"` // 拼 notify_url / return_url 的公网根地址;沙箱回调需公网可达(内网穿透)
}
type DatabaseConfig struct {
Driver string `mapstructure:"driver"` // sqlite | mysql
DSN string `mapstructure:"dsn"` // sqlite 为文件路径;mysql 为完整 DSN
}
// AlipaySandboxConfig 启动时据此 upsert 一个支付宝(沙箱)商户,方便开箱联调。
// 生产/多商户请改为通过管理接口或 seed 写入 merchants 表。
type AlipaySandboxConfig struct {
Enabled bool `mapstructure:"enabled"`
Production bool `mapstructure:"production"` // false=沙箱网关;true=正式网关(真钱)
MerchantCode string `mapstructure:"merchant_code"` // 业务标识,如 yanmei
MerchantName string `mapstructure:"merchant_name"`
AppID string `mapstructure:"app_id"`
AppPrivateKey string `mapstructure:"app_private_key"` // 应用私钥(PKCS1/PKCS8 皆可,无 PEM 头亦可)
AlipayPublicKey string `mapstructure:"alipay_public_key"` // 支付宝公钥(公钥模式)
}
// QuerySyncConfig 兜底主动查单:定时把待支付订单拿去 alipay.trade.query 核对,防回调丢失。
type QuerySyncConfig struct {
Enabled bool `mapstructure:"enabled"`
IntervalSec int `mapstructure:"interval_sec"` // 轮询间隔(秒)
MaxAgeMin int `mapstructure:"max_age_min"` // 只查创建时间在该分钟数内的待支付单
}
var C Config
func Load() {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AddConfigPath("./config")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
// 敏感项支持环境变量覆盖(部署时不写进 config.yaml
_ = viper.BindEnv("alipay_sandbox.app_private_key", "ALIPAY_APP_PRIVATE_KEY")
_ = viper.BindEnv("alipay_sandbox.alipay_public_key", "ALIPAY_PUBLIC_KEY")
_ = viper.BindEnv("database.dsn", "DATABASE_DSN")
viper.SetDefault("server.port", "8080")
viper.SetDefault("server.mode", "debug")
viper.SetDefault("server.base_url", "http://localhost:8080")
viper.SetDefault("database.driver", "sqlite")
viper.SetDefault("database.dsn", "pay.db")
viper.SetDefault("alipay_sandbox.enabled", false)
viper.SetDefault("alipay_sandbox.merchant_code", "yanmei")
viper.SetDefault("alipay_sandbox.merchant_name", "演么测试商户")
viper.SetDefault("query_sync.enabled", true)
viper.SetDefault("query_sync.interval_sec", 30)
viper.SetDefault("query_sync.max_age_min", 30)
if err := viper.ReadInConfig(); err != nil {
log.Println("[config] 未找到 config.yaml,使用默认值 + 环境变量")
}
if err := viper.Unmarshal(&C); err != nil {
log.Fatalf("[config] 解析配置失败: %v", err)
}
}