From 9264873e2ce21c818e4c8db2f7a0e45ffdb20b2b Mon Sep 17 00:00:00 2001 From: zizi Date: Wed, 20 May 2026 15:41:36 +0800 Subject: [PATCH] fix: load direct payment options Register Alipay and WxPay option keys and sync option updates into runtime payment settings. --- model/option.go | 9 +++ model/option_payment_test.go | 141 +++++++++++++++++++++++++++++++++++ setting/payment_alipay.go | 46 ++++++++++++ setting/payment_wxpay.go | 74 ++++++++++++++++++ 4 files changed, 270 insertions(+) create mode 100644 model/option_payment_test.go diff --git a/model/option.go b/model/option.go index a534c11c..458fce00 100644 --- a/model/option.go +++ b/model/option.go @@ -92,6 +92,12 @@ func InitOptionMap() { common.OptionMap["StripePriceId"] = setting.StripePriceId common.OptionMap["StripeUnitPrice"] = strconv.FormatFloat(setting.StripeUnitPrice, 'f', -1, 64) common.OptionMap["StripePromotionCodesEnabled"] = strconv.FormatBool(setting.StripePromotionCodesEnabled) + for k, v := range setting.AlipayOptionValues() { + common.OptionMap[k] = v + } + for k, v := range setting.WxpayOptionValues() { + common.OptionMap[k] = v + } common.OptionMap["CreemApiKey"] = setting.CreemApiKey common.OptionMap["CreemProducts"] = setting.CreemProducts common.OptionMap["CreemTestMode"] = strconv.FormatBool(setting.CreemTestMode) @@ -240,6 +246,9 @@ func updateOptionMap(key string, value string) (err error) { if handleConfigUpdate(key, value) { return nil // 已由配置系统处理 } + if setting.UpdateAlipayOption(key, value) || setting.UpdateWxpayOption(key, value) { + return nil + } // 处理传统配置项... if strings.HasSuffix(key, "Permission") { diff --git a/model/option_payment_test.go b/model/option_payment_test.go new file mode 100644 index 00000000..8b2183fb --- /dev/null +++ b/model/option_payment_test.go @@ -0,0 +1,141 @@ +package model + +import ( + "testing" + + "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/setting" + "github.com/stretchr/testify/require" +) + +func TestPaymentOptionsUpdateRuntimeSettings(t *testing.T) { + originalAlipay := setting.Alipay + originalWxpay := setting.Wxpay + common.OptionMapRWMutex.RLock() + originalOptionMap := common.OptionMap + common.OptionMapRWMutex.RUnlock() + t.Cleanup(func() { + setting.Alipay = originalAlipay + setting.Wxpay = originalWxpay + common.OptionMapRWMutex.Lock() + common.OptionMap = originalOptionMap + common.OptionMapRWMutex.Unlock() + }) + + common.OptionMapRWMutex.Lock() + common.OptionMap = map[string]string{} + common.OptionMapRWMutex.Unlock() + + require.NoError(t, updateOptionMap(setting.AlipayEnabledOption, "true")) + require.NoError(t, updateOptionMap(setting.AlipayAppIDOption, "alipay-app")) + require.NoError(t, updateOptionMap(setting.AlipayPrivateKeyOption, "alipay-private")) + require.NoError(t, updateOptionMap(setting.AlipayPublicKeyOption, "alipay-public")) + require.NoError(t, updateOptionMap(setting.AlipayGatewayUrlOption, "https://alipay-gateway.test")) + require.NoError(t, updateOptionMap(setting.AlipayNotifyURLOption, "https://example.test/alipay/notify")) + require.NoError(t, updateOptionMap(setting.AlipayReturnURLOption, "https://example.test/alipay/return")) + + require.True(t, setting.Alipay.Enabled) + require.Equal(t, "alipay-app", setting.Alipay.AppID) + require.Equal(t, "alipay-private", setting.Alipay.PrivateKey) + require.Equal(t, "alipay-public", setting.Alipay.PublicKey) + require.Equal(t, "https://alipay-gateway.test", setting.Alipay.GatewayUrl) + require.Equal(t, "https://example.test/alipay/notify", setting.Alipay.NotifyURL) + require.Equal(t, "https://example.test/alipay/return", setting.Alipay.ReturnURL) + + require.NoError(t, updateOptionMap(setting.WxpayEnabledOption, "true")) + require.NoError(t, updateOptionMap(setting.WxpayAppIDOption, "wxpay-app")) + require.NoError(t, updateOptionMap(setting.WxpayMchIDOption, "wxpay-mch")) + require.NoError(t, updateOptionMap(setting.WxpayPrivateKeyOption, "wxpay-private")) + require.NoError(t, updateOptionMap(setting.WxpayMerchantSerialNoOption, "merchant-serial")) + require.NoError(t, updateOptionMap(setting.WxpayAPIv3KeyOption, "12345678901234567890123456789012")) + require.NoError(t, updateOptionMap(setting.WxpayPlatformPublicKeyOption, "wxpay-platform-public")) + require.NoError(t, updateOptionMap(setting.WxpayPlatformCertificateOption, "wxpay-platform-cert")) + require.NoError(t, updateOptionMap(setting.WxpayPlatformSerialNoOption, "platform-serial")) + require.NoError(t, updateOptionMap(setting.WxpayGatewayURLOption, "https://wxpay-gateway.test")) + require.NoError(t, updateOptionMap(setting.WxpayNotifyURLOption, "https://example.test/wxpay/notify")) + require.NoError(t, updateOptionMap(setting.WxpayReturnURLOption, "https://example.test/wxpay/return")) + require.NoError(t, updateOptionMap(setting.WxpayH5AppNameOption, "new-api")) + require.NoError(t, updateOptionMap(setting.WxpayH5AppURLOption, "https://example.test")) + + require.True(t, setting.Wxpay.Enabled) + require.Equal(t, "wxpay-app", setting.Wxpay.AppID) + require.Equal(t, "wxpay-mch", setting.Wxpay.MchID) + require.Equal(t, "wxpay-private", setting.Wxpay.PrivateKey) + require.Equal(t, "merchant-serial", setting.Wxpay.MerchantSerialNo) + require.Equal(t, "12345678901234567890123456789012", setting.Wxpay.APIv3Key) + require.Equal(t, "wxpay-platform-public", setting.Wxpay.PlatformPublicKey) + require.Equal(t, "wxpay-platform-cert", setting.Wxpay.PlatformCertificate) + require.Equal(t, "platform-serial", setting.Wxpay.PlatformSerialNo) + require.Equal(t, "https://wxpay-gateway.test", setting.Wxpay.GatewayURL) + require.Equal(t, "https://example.test/wxpay/notify", setting.Wxpay.NotifyURL) + require.Equal(t, "https://example.test/wxpay/return", setting.Wxpay.ReturnURL) + require.Equal(t, "new-api", setting.Wxpay.H5AppName) + require.Equal(t, "https://example.test", setting.Wxpay.H5AppURL) +} + +func TestInitOptionMapIncludesDirectPaymentOptions(t *testing.T) { + originalAlipay := setting.Alipay + originalWxpay := setting.Wxpay + common.OptionMapRWMutex.RLock() + originalOptionMap := common.OptionMap + common.OptionMapRWMutex.RUnlock() + t.Cleanup(func() { + setting.Alipay = originalAlipay + setting.Wxpay = originalWxpay + common.OptionMapRWMutex.Lock() + common.OptionMap = originalOptionMap + common.OptionMapRWMutex.Unlock() + }) + + setting.Alipay = setting.AlipaySetting{ + Enabled: true, + AppID: "init-alipay-app", + PrivateKey: "init-alipay-private", + PublicKey: "init-alipay-public", + GatewayUrl: "https://init-alipay-gateway.test", + NotifyURL: "https://example.test/init-alipay/notify", + ReturnURL: "https://example.test/init-alipay/return", + } + setting.Wxpay = setting.WxpaySetting{ + Enabled: true, + AppID: "init-wxpay-app", + MchID: "init-wxpay-mch", + PrivateKey: "init-wxpay-private", + MerchantSerialNo: "init-merchant-serial", + APIv3Key: "12345678901234567890123456789012", + PlatformPublicKey: "init-platform-public", + PlatformCertificate: "init-platform-cert", + PlatformSerialNo: "init-platform-serial", + GatewayURL: "https://init-wxpay-gateway.test", + NotifyURL: "https://example.test/init-wxpay/notify", + ReturnURL: "https://example.test/init-wxpay/return", + H5AppName: "init-new-api", + H5AppURL: "https://init.example.test", + } + + InitOptionMap() + + common.OptionMapRWMutex.RLock() + defer common.OptionMapRWMutex.RUnlock() + require.Equal(t, "true", common.OptionMap[setting.AlipayEnabledOption]) + require.Equal(t, "init-alipay-app", common.OptionMap[setting.AlipayAppIDOption]) + require.Equal(t, "init-alipay-private", common.OptionMap[setting.AlipayPrivateKeyOption]) + require.Equal(t, "init-alipay-public", common.OptionMap[setting.AlipayPublicKeyOption]) + require.Equal(t, "https://init-alipay-gateway.test", common.OptionMap[setting.AlipayGatewayUrlOption]) + require.Equal(t, "https://example.test/init-alipay/notify", common.OptionMap[setting.AlipayNotifyURLOption]) + require.Equal(t, "https://example.test/init-alipay/return", common.OptionMap[setting.AlipayReturnURLOption]) + require.Equal(t, "true", common.OptionMap[setting.WxpayEnabledOption]) + require.Equal(t, "init-wxpay-app", common.OptionMap[setting.WxpayAppIDOption]) + require.Equal(t, "init-wxpay-mch", common.OptionMap[setting.WxpayMchIDOption]) + require.Equal(t, "init-wxpay-private", common.OptionMap[setting.WxpayPrivateKeyOption]) + require.Equal(t, "init-merchant-serial", common.OptionMap[setting.WxpayMerchantSerialNoOption]) + require.Equal(t, "12345678901234567890123456789012", common.OptionMap[setting.WxpayAPIv3KeyOption]) + require.Equal(t, "init-platform-public", common.OptionMap[setting.WxpayPlatformPublicKeyOption]) + require.Equal(t, "init-platform-cert", common.OptionMap[setting.WxpayPlatformCertificateOption]) + require.Equal(t, "init-platform-serial", common.OptionMap[setting.WxpayPlatformSerialNoOption]) + require.Equal(t, "https://init-wxpay-gateway.test", common.OptionMap[setting.WxpayGatewayURLOption]) + require.Equal(t, "https://example.test/init-wxpay/notify", common.OptionMap[setting.WxpayNotifyURLOption]) + require.Equal(t, "https://example.test/init-wxpay/return", common.OptionMap[setting.WxpayReturnURLOption]) + require.Equal(t, "init-new-api", common.OptionMap[setting.WxpayH5AppNameOption]) + require.Equal(t, "https://init.example.test", common.OptionMap[setting.WxpayH5AppURLOption]) +} diff --git a/setting/payment_alipay.go b/setting/payment_alipay.go index 2e45ffb8..3ddf974c 100644 --- a/setting/payment_alipay.go +++ b/setting/payment_alipay.go @@ -1,5 +1,7 @@ package setting +import "strconv" + type AlipaySetting struct { Enabled bool `json:"enabled"` AppID string `json:"app_id"` @@ -13,3 +15,47 @@ type AlipaySetting struct { var Alipay = AlipaySetting{ GatewayUrl: "https://openapi.alipay.com/gateway.do", } + +const ( + AlipayEnabledOption = "AlipayEnabled" + AlipayAppIDOption = "AlipayAppID" + AlipayPrivateKeyOption = "AlipayPrivateKey" + AlipayPublicKeyOption = "AlipayPublicKey" + AlipayGatewayUrlOption = "AlipayGatewayUrl" + AlipayNotifyURLOption = "AlipayNotifyURL" + AlipayReturnURLOption = "AlipayReturnURL" +) + +func AlipayOptionValues() map[string]string { + return map[string]string{ + AlipayEnabledOption: strconv.FormatBool(Alipay.Enabled), + AlipayAppIDOption: Alipay.AppID, + AlipayPrivateKeyOption: Alipay.PrivateKey, + AlipayPublicKeyOption: Alipay.PublicKey, + AlipayGatewayUrlOption: Alipay.GatewayUrl, + AlipayNotifyURLOption: Alipay.NotifyURL, + AlipayReturnURLOption: Alipay.ReturnURL, + } +} + +func UpdateAlipayOption(key string, value string) bool { + switch key { + case AlipayEnabledOption: + Alipay.Enabled = value == "true" + case AlipayAppIDOption: + Alipay.AppID = value + case AlipayPrivateKeyOption: + Alipay.PrivateKey = value + case AlipayPublicKeyOption: + Alipay.PublicKey = value + case AlipayGatewayUrlOption: + Alipay.GatewayUrl = value + case AlipayNotifyURLOption: + Alipay.NotifyURL = value + case AlipayReturnURLOption: + Alipay.ReturnURL = value + default: + return false + } + return true +} diff --git a/setting/payment_wxpay.go b/setting/payment_wxpay.go index fbebc436..fb2a62a9 100644 --- a/setting/payment_wxpay.go +++ b/setting/payment_wxpay.go @@ -1,5 +1,7 @@ package setting +import "strconv" + type WxpaySetting struct { Enabled bool `json:"enabled"` AppID string `json:"app_id"` @@ -20,3 +22,75 @@ type WxpaySetting struct { var Wxpay = WxpaySetting{ GatewayURL: "https://api.mch.weixin.qq.com", } + +const ( + WxpayEnabledOption = "WxpayEnabled" + WxpayAppIDOption = "WxpayAppID" + WxpayMchIDOption = "WxpayMchID" + WxpayPrivateKeyOption = "WxpayPrivateKey" + WxpayMerchantSerialNoOption = "WxpayMerchantSerialNo" + WxpayAPIv3KeyOption = "WxpayAPIv3Key" + WxpayPlatformPublicKeyOption = "WxpayPlatformPublicKey" + WxpayPlatformCertificateOption = "WxpayPlatformCertificate" + WxpayPlatformSerialNoOption = "WxpayPlatformSerialNo" + WxpayGatewayURLOption = "WxpayGatewayURL" + WxpayNotifyURLOption = "WxpayNotifyURL" + WxpayReturnURLOption = "WxpayReturnURL" + WxpayH5AppNameOption = "WxpayH5AppName" + WxpayH5AppURLOption = "WxpayH5AppURL" +) + +func WxpayOptionValues() map[string]string { + return map[string]string{ + WxpayEnabledOption: strconv.FormatBool(Wxpay.Enabled), + WxpayAppIDOption: Wxpay.AppID, + WxpayMchIDOption: Wxpay.MchID, + WxpayPrivateKeyOption: Wxpay.PrivateKey, + WxpayMerchantSerialNoOption: Wxpay.MerchantSerialNo, + WxpayAPIv3KeyOption: Wxpay.APIv3Key, + WxpayPlatformPublicKeyOption: Wxpay.PlatformPublicKey, + WxpayPlatformCertificateOption: Wxpay.PlatformCertificate, + WxpayPlatformSerialNoOption: Wxpay.PlatformSerialNo, + WxpayGatewayURLOption: Wxpay.GatewayURL, + WxpayNotifyURLOption: Wxpay.NotifyURL, + WxpayReturnURLOption: Wxpay.ReturnURL, + WxpayH5AppNameOption: Wxpay.H5AppName, + WxpayH5AppURLOption: Wxpay.H5AppURL, + } +} + +func UpdateWxpayOption(key string, value string) bool { + switch key { + case WxpayEnabledOption: + Wxpay.Enabled = value == "true" + case WxpayAppIDOption: + Wxpay.AppID = value + case WxpayMchIDOption: + Wxpay.MchID = value + case WxpayPrivateKeyOption: + Wxpay.PrivateKey = value + case WxpayMerchantSerialNoOption: + Wxpay.MerchantSerialNo = value + case WxpayAPIv3KeyOption: + Wxpay.APIv3Key = value + case WxpayPlatformPublicKeyOption: + Wxpay.PlatformPublicKey = value + case WxpayPlatformCertificateOption: + Wxpay.PlatformCertificate = value + case WxpayPlatformSerialNoOption: + Wxpay.PlatformSerialNo = value + case WxpayGatewayURLOption: + Wxpay.GatewayURL = value + case WxpayNotifyURLOption: + Wxpay.NotifyURL = value + case WxpayReturnURLOption: + Wxpay.ReturnURL = value + case WxpayH5AppNameOption: + Wxpay.H5AppName = value + case WxpayH5AppURLOption: + Wxpay.H5AppURL = value + default: + return false + } + return true +}