Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
54dc1767
Commit
54dc1767
authored
Apr 21, 2026
by
IanShaw027
Browse files
feat(settings): support per-channel WeChat OAuth and persist payment options
parent
d5819181
Changes
16
Expand all
Show whitespace changes
Inline
Side-by-side
backend/internal/handler/admin/setting_handler.go
View file @
54dc1767
...
...
@@ -43,6 +43,15 @@ func scopesContainOpenID(scopes string) bool {
return
false
}
func
firstNonEmpty
(
values
...
string
)
string
{
for
_
,
value
:=
range
values
{
if
trimmed
:=
strings
.
TrimSpace
(
value
);
trimmed
!=
""
{
return
trimmed
}
}
return
""
}
// SettingHandler 系统设置处理器
type
SettingHandler
struct
{
settingService
*
service
.
SettingService
...
...
@@ -125,8 +134,15 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
WeChatConnectEnabled
:
settings
.
WeChatConnectEnabled
,
WeChatConnectAppID
:
settings
.
WeChatConnectAppID
,
WeChatConnectAppSecretConfigured
:
settings
.
WeChatConnectAppSecretConfigured
,
WeChatConnectOpenAppID
:
settings
.
WeChatConnectOpenAppID
,
WeChatConnectOpenAppSecretConfigured
:
settings
.
WeChatConnectOpenAppSecretConfigured
,
WeChatConnectMPAppID
:
settings
.
WeChatConnectMPAppID
,
WeChatConnectMPAppSecretConfigured
:
settings
.
WeChatConnectMPAppSecretConfigured
,
WeChatConnectMobileAppID
:
settings
.
WeChatConnectMobileAppID
,
WeChatConnectMobileAppSecretConfigured
:
settings
.
WeChatConnectMobileAppSecretConfigured
,
WeChatConnectOpenEnabled
:
settings
.
WeChatConnectOpenEnabled
,
WeChatConnectMPEnabled
:
settings
.
WeChatConnectMPEnabled
,
WeChatConnectMobileEnabled
:
settings
.
WeChatConnectMobileEnabled
,
WeChatConnectMode
:
settings
.
WeChatConnectMode
,
WeChatConnectScopes
:
settings
.
WeChatConnectScopes
,
WeChatConnectRedirectURL
:
settings
.
WeChatConnectRedirectURL
,
...
...
@@ -259,8 +275,15 @@ type UpdateSettingsRequest struct {
WeChatConnectEnabled
bool
`json:"wechat_connect_enabled"`
WeChatConnectAppID
string
`json:"wechat_connect_app_id"`
WeChatConnectAppSecret
string
`json:"wechat_connect_app_secret"`
WeChatConnectOpenAppID
string
`json:"wechat_connect_open_app_id"`
WeChatConnectOpenAppSecret
string
`json:"wechat_connect_open_app_secret"`
WeChatConnectMPAppID
string
`json:"wechat_connect_mp_app_id"`
WeChatConnectMPAppSecret
string
`json:"wechat_connect_mp_app_secret"`
WeChatConnectMobileAppID
string
`json:"wechat_connect_mobile_app_id"`
WeChatConnectMobileAppSecret
string
`json:"wechat_connect_mobile_app_secret"`
WeChatConnectOpenEnabled
bool
`json:"wechat_connect_open_enabled"`
WeChatConnectMPEnabled
bool
`json:"wechat_connect_mp_enabled"`
WeChatConnectMobileEnabled
bool
`json:"wechat_connect_mobile_enabled"`
WeChatConnectMode
string
`json:"wechat_connect_mode"`
WeChatConnectScopes
string
`json:"wechat_connect_scopes"`
WeChatConnectRedirectURL
string
`json:"wechat_connect_redirect_url"`
...
...
@@ -532,34 +555,35 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
if
req
.
WeChatConnectEnabled
{
req
.
WeChatConnectAppID
=
strings
.
TrimSpace
(
req
.
WeChatConnectAppID
)
req
.
WeChatConnectAppSecret
=
strings
.
TrimSpace
(
req
.
WeChatConnectAppSecret
)
req
.
WeChatConnectOpenAppID
=
strings
.
TrimSpace
(
req
.
WeChatConnectOpenAppID
)
req
.
WeChatConnectOpenAppSecret
=
strings
.
TrimSpace
(
req
.
WeChatConnectOpenAppSecret
)
req
.
WeChatConnectMPAppID
=
strings
.
TrimSpace
(
req
.
WeChatConnectMPAppID
)
req
.
WeChatConnectMPAppSecret
=
strings
.
TrimSpace
(
req
.
WeChatConnectMPAppSecret
)
req
.
WeChatConnectMobileAppID
=
strings
.
TrimSpace
(
req
.
WeChatConnectMobileAppID
)
req
.
WeChatConnectMobileAppSecret
=
strings
.
TrimSpace
(
req
.
WeChatConnectMobileAppSecret
)
req
.
WeChatConnectMode
=
strings
.
ToLower
(
strings
.
TrimSpace
(
req
.
WeChatConnectMode
))
req
.
WeChatConnectScopes
=
strings
.
TrimSpace
(
req
.
WeChatConnectScopes
)
req
.
WeChatConnectRedirectURL
=
strings
.
TrimSpace
(
req
.
WeChatConnectRedirectURL
)
req
.
WeChatConnectFrontendRedirectURL
=
strings
.
TrimSpace
(
req
.
WeChatConnectFrontendRedirectURL
)
if
req
.
WeChatConnectAppID
==
""
{
response
.
BadRequest
(
c
,
"WeChat App ID is required when enabled"
)
return
}
if
req
.
WeChatConnectAppSecret
==
""
{
if
previousSettings
.
WeChatConnectAppSecret
==
""
{
response
.
BadRequest
(
c
,
"WeChat App Secret is required when enabled"
)
if
req
.
WeChatConnectMPEnabled
&&
req
.
WeChatConnectMobileEnabled
{
response
.
BadRequest
(
c
,
"WeChat Official Account and Mobile App cannot be enabled at the same time"
)
return
}
req
.
WeChatConnectAppSecret
=
previousSettings
.
WeChatConnectAppSecret
}
if
req
.
WeChatConnectMode
!=
""
{
switch
req
.
WeChatConnectMode
{
case
"open"
,
"mp"
:
case
"open"
,
"mp"
,
"mobile"
:
default
:
response
.
BadRequest
(
c
,
"WeChat mode must be open
or mp
"
)
response
.
BadRequest
(
c
,
"WeChat mode must be open
, mp, or mobile
"
)
return
}
}
if
!
req
.
WeChatConnectOpenEnabled
&&
!
req
.
WeChatConnectMPEnabled
{
if
!
req
.
WeChatConnectOpenEnabled
&&
!
req
.
WeChatConnectMPEnabled
&&
!
req
.
WeChatConnectMobileEnabled
{
switch
req
.
WeChatConnectMode
{
case
"mp"
:
req
.
WeChatConnectMPEnabled
=
true
case
"mobile"
:
req
.
WeChatConnectMobileEnabled
=
true
default
:
req
.
WeChatConnectOpenEnabled
=
true
}
...
...
@@ -567,10 +591,61 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
if
req
.
WeChatConnectMode
==
""
{
if
req
.
WeChatConnectMPEnabled
{
req
.
WeChatConnectMode
=
"mp"
}
else
if
req
.
WeChatConnectMobileEnabled
{
req
.
WeChatConnectMode
=
"mobile"
}
else
{
req
.
WeChatConnectMode
=
"open"
}
}
req
.
WeChatConnectOpenAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
req
.
WeChatConnectOpenAppID
,
req
.
WeChatConnectAppID
))
req
.
WeChatConnectMPAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
req
.
WeChatConnectMPAppID
,
req
.
WeChatConnectAppID
))
req
.
WeChatConnectMobileAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
req
.
WeChatConnectMobileAppID
,
req
.
WeChatConnectAppID
))
if
req
.
WeChatConnectOpenAppSecret
==
""
{
req
.
WeChatConnectOpenAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
previousSettings
.
WeChatConnectOpenAppSecret
,
previousSettings
.
WeChatConnectAppSecret
,
req
.
WeChatConnectAppSecret
))
}
if
req
.
WeChatConnectMPAppSecret
==
""
{
req
.
WeChatConnectMPAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
previousSettings
.
WeChatConnectMPAppSecret
,
previousSettings
.
WeChatConnectAppSecret
,
req
.
WeChatConnectAppSecret
))
}
if
req
.
WeChatConnectMobileAppSecret
==
""
{
req
.
WeChatConnectMobileAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
previousSettings
.
WeChatConnectMobileAppSecret
,
previousSettings
.
WeChatConnectAppSecret
,
req
.
WeChatConnectAppSecret
))
}
if
req
.
WeChatConnectAppSecret
==
""
{
req
.
WeChatConnectAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
req
.
WeChatConnectOpenAppSecret
,
req
.
WeChatConnectMPAppSecret
,
req
.
WeChatConnectMobileAppSecret
,
previousSettings
.
WeChatConnectAppSecret
))
}
if
req
.
WeChatConnectOpenEnabled
{
if
req
.
WeChatConnectOpenAppID
==
""
{
response
.
BadRequest
(
c
,
"WeChat PC App ID is required when enabled"
)
return
}
if
req
.
WeChatConnectOpenAppSecret
==
""
{
response
.
BadRequest
(
c
,
"WeChat PC App Secret is required when enabled"
)
return
}
}
if
req
.
WeChatConnectMPEnabled
{
if
req
.
WeChatConnectMPAppID
==
""
{
response
.
BadRequest
(
c
,
"WeChat Official Account App ID is required when enabled"
)
return
}
if
req
.
WeChatConnectMPAppSecret
==
""
{
response
.
BadRequest
(
c
,
"WeChat Official Account App Secret is required when enabled"
)
return
}
}
if
req
.
WeChatConnectMobileEnabled
{
if
req
.
WeChatConnectMobileAppID
==
""
{
response
.
BadRequest
(
c
,
"WeChat Mobile App ID is required when enabled"
)
return
}
if
req
.
WeChatConnectMobileAppSecret
==
""
{
response
.
BadRequest
(
c
,
"WeChat Mobile App Secret is required when enabled"
)
return
}
}
if
req
.
WeChatConnectScopes
==
""
{
if
req
.
WeChatConnectMPEnabled
{
req
.
WeChatConnectScopes
=
service
.
DefaultWeChatConnectScopesForMode
(
"mp"
)
...
...
@@ -946,8 +1021,15 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
WeChatConnectEnabled
:
req
.
WeChatConnectEnabled
,
WeChatConnectAppID
:
req
.
WeChatConnectAppID
,
WeChatConnectAppSecret
:
req
.
WeChatConnectAppSecret
,
WeChatConnectOpenAppID
:
req
.
WeChatConnectOpenAppID
,
WeChatConnectOpenAppSecret
:
req
.
WeChatConnectOpenAppSecret
,
WeChatConnectMPAppID
:
req
.
WeChatConnectMPAppID
,
WeChatConnectMPAppSecret
:
req
.
WeChatConnectMPAppSecret
,
WeChatConnectMobileAppID
:
req
.
WeChatConnectMobileAppID
,
WeChatConnectMobileAppSecret
:
req
.
WeChatConnectMobileAppSecret
,
WeChatConnectOpenEnabled
:
req
.
WeChatConnectOpenEnabled
,
WeChatConnectMPEnabled
:
req
.
WeChatConnectMPEnabled
,
WeChatConnectMobileEnabled
:
req
.
WeChatConnectMobileEnabled
,
WeChatConnectMode
:
req
.
WeChatConnectMode
,
WeChatConnectScopes
:
req
.
WeChatConnectScopes
,
WeChatConnectRedirectURL
:
req
.
WeChatConnectRedirectURL
,
...
...
@@ -1234,8 +1316,15 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
WeChatConnectEnabled
:
updatedSettings
.
WeChatConnectEnabled
,
WeChatConnectAppID
:
updatedSettings
.
WeChatConnectAppID
,
WeChatConnectAppSecretConfigured
:
updatedSettings
.
WeChatConnectAppSecretConfigured
,
WeChatConnectOpenAppID
:
updatedSettings
.
WeChatConnectOpenAppID
,
WeChatConnectOpenAppSecretConfigured
:
updatedSettings
.
WeChatConnectOpenAppSecretConfigured
,
WeChatConnectMPAppID
:
updatedSettings
.
WeChatConnectMPAppID
,
WeChatConnectMPAppSecretConfigured
:
updatedSettings
.
WeChatConnectMPAppSecretConfigured
,
WeChatConnectMobileAppID
:
updatedSettings
.
WeChatConnectMobileAppID
,
WeChatConnectMobileAppSecretConfigured
:
updatedSettings
.
WeChatConnectMobileAppSecretConfigured
,
WeChatConnectOpenEnabled
:
updatedSettings
.
WeChatConnectOpenEnabled
,
WeChatConnectMPEnabled
:
updatedSettings
.
WeChatConnectMPEnabled
,
WeChatConnectMobileEnabled
:
updatedSettings
.
WeChatConnectMobileEnabled
,
WeChatConnectMode
:
updatedSettings
.
WeChatConnectMode
,
WeChatConnectScopes
:
updatedSettings
.
WeChatConnectScopes
,
WeChatConnectRedirectURL
:
updatedSettings
.
WeChatConnectRedirectURL
,
...
...
@@ -1442,12 +1531,33 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
if
req
.
WeChatConnectAppSecret
!=
""
{
changed
=
append
(
changed
,
"wechat_connect_app_secret"
)
}
if
before
.
WeChatConnectOpenAppID
!=
after
.
WeChatConnectOpenAppID
{
changed
=
append
(
changed
,
"wechat_connect_open_app_id"
)
}
if
req
.
WeChatConnectOpenAppSecret
!=
""
{
changed
=
append
(
changed
,
"wechat_connect_open_app_secret"
)
}
if
before
.
WeChatConnectMPAppID
!=
after
.
WeChatConnectMPAppID
{
changed
=
append
(
changed
,
"wechat_connect_mp_app_id"
)
}
if
req
.
WeChatConnectMPAppSecret
!=
""
{
changed
=
append
(
changed
,
"wechat_connect_mp_app_secret"
)
}
if
before
.
WeChatConnectMobileAppID
!=
after
.
WeChatConnectMobileAppID
{
changed
=
append
(
changed
,
"wechat_connect_mobile_app_id"
)
}
if
req
.
WeChatConnectMobileAppSecret
!=
""
{
changed
=
append
(
changed
,
"wechat_connect_mobile_app_secret"
)
}
if
before
.
WeChatConnectOpenEnabled
!=
after
.
WeChatConnectOpenEnabled
{
changed
=
append
(
changed
,
"wechat_connect_open_enabled"
)
}
if
before
.
WeChatConnectMPEnabled
!=
after
.
WeChatConnectMPEnabled
{
changed
=
append
(
changed
,
"wechat_connect_mp_enabled"
)
}
if
before
.
WeChatConnectMobileEnabled
!=
after
.
WeChatConnectMobileEnabled
{
changed
=
append
(
changed
,
"wechat_connect_mobile_enabled"
)
}
if
before
.
WeChatConnectMode
!=
after
.
WeChatConnectMode
{
changed
=
append
(
changed
,
"wechat_connect_mode"
)
}
...
...
backend/internal/handler/auth_wechat_oauth.go
View file @
54dc1767
...
...
@@ -753,9 +753,15 @@ func (h *AuthHandler) ensureWeChatBindOwnership(
}
for
_
,
identity
:=
range
identities
{
if
identity
!=
nil
&&
identity
.
UserID
!=
userID
{
activeOwner
,
lookupErr
:=
findActiveUserByID
(
ctx
,
client
,
identity
.
UserID
)
if
lookupErr
!=
nil
{
return
lookupErr
}
if
activeOwner
!=
nil
{
return
infraerrors
.
Conflict
(
"AUTH_IDENTITY_OWNERSHIP_CONFLICT"
,
"auth identity already belongs to another user"
)
}
}
}
channelSubject
=
strings
.
TrimSpace
(
channelSubject
)
channelAppID
:=
strings
.
TrimSpace
(
cfg
.
appID
)
...
...
@@ -778,9 +784,15 @@ func (h *AuthHandler) ensureWeChatBindOwnership(
}
for
_
,
channel
:=
range
channels
{
if
channel
!=
nil
&&
channel
.
Edges
.
Identity
!=
nil
&&
channel
.
Edges
.
Identity
.
UserID
!=
userID
{
activeOwner
,
lookupErr
:=
findActiveUserByID
(
ctx
,
client
,
channel
.
Edges
.
Identity
.
UserID
)
if
lookupErr
!=
nil
{
return
lookupErr
}
if
activeOwner
!=
nil
{
return
infraerrors
.
Conflict
(
"AUTH_IDENTITY_CHANNEL_OWNERSHIP_CONFLICT"
,
"auth identity channel already belongs to another user"
)
}
}
}
return
nil
}
...
...
@@ -960,8 +972,8 @@ func (h *AuthHandler) getWeChatOAuthConfig(ctx context.Context, rawMode string,
cfg
:=
wechatOAuthConfig
{
mode
:
mode
,
appID
:
strings
.
TrimSpace
(
effective
.
AppID
),
appSecret
:
strings
.
TrimSpace
(
effective
.
AppSecret
),
appID
:
strings
.
TrimSpace
(
effective
.
AppID
ForMode
(
mode
)
),
appSecret
:
strings
.
TrimSpace
(
effective
.
AppSecret
ForMode
(
mode
)
),
redirectURI
:
firstNonEmpty
(
strings
.
TrimSpace
(
effective
.
RedirectURL
),
resolveWeChatOAuthAbsoluteURL
(
apiBaseURL
,
c
,
"/api/v1/auth/oauth/wechat/callback"
)),
frontendCallback
:
firstNonEmpty
(
strings
.
TrimSpace
(
effective
.
FrontendRedirectURL
),
wechatOAuthDefaultFrontendCB
),
scope
:
effective
.
ScopeForMode
(
mode
),
...
...
backend/internal/handler/dto/settings.go
View file @
54dc1767
...
...
@@ -54,8 +54,15 @@ type SystemSettings struct {
WeChatConnectEnabled
bool
`json:"wechat_connect_enabled"`
WeChatConnectAppID
string
`json:"wechat_connect_app_id"`
WeChatConnectAppSecretConfigured
bool
`json:"wechat_connect_app_secret_configured"`
WeChatConnectOpenAppID
string
`json:"wechat_connect_open_app_id"`
WeChatConnectOpenAppSecretConfigured
bool
`json:"wechat_connect_open_app_secret_configured"`
WeChatConnectMPAppID
string
`json:"wechat_connect_mp_app_id"`
WeChatConnectMPAppSecretConfigured
bool
`json:"wechat_connect_mp_app_secret_configured"`
WeChatConnectMobileAppID
string
`json:"wechat_connect_mobile_app_id"`
WeChatConnectMobileAppSecretConfigured
bool
`json:"wechat_connect_mobile_app_secret_configured"`
WeChatConnectOpenEnabled
bool
`json:"wechat_connect_open_enabled"`
WeChatConnectMPEnabled
bool
`json:"wechat_connect_mp_enabled"`
WeChatConnectMobileEnabled
bool
`json:"wechat_connect_mobile_enabled"`
WeChatConnectMode
string
`json:"wechat_connect_mode"`
WeChatConnectScopes
string
`json:"wechat_connect_scopes"`
WeChatConnectRedirectURL
string
`json:"wechat_connect_redirect_url"`
...
...
@@ -212,6 +219,7 @@ type PublicSettings struct {
WeChatOAuthEnabled
bool
`json:"wechat_oauth_enabled"`
WeChatOAuthOpenEnabled
bool
`json:"wechat_oauth_open_enabled"`
WeChatOAuthMPEnabled
bool
`json:"wechat_oauth_mp_enabled"`
WeChatOAuthMobileEnabled
bool
`json:"wechat_oauth_mobile_enabled"`
OIDCOAuthEnabled
bool
`json:"oidc_oauth_enabled"`
OIDCOAuthProviderName
string
`json:"oidc_oauth_provider_name"`
SoraClientEnabled
bool
`json:"sora_client_enabled"`
...
...
backend/internal/handler/setting_handler.go
View file @
54dc1767
...
...
@@ -60,6 +60,7 @@ func (h *SettingHandler) GetPublicSettings(c *gin.Context) {
WeChatOAuthEnabled
:
settings
.
WeChatOAuthEnabled
,
WeChatOAuthOpenEnabled
:
settings
.
WeChatOAuthOpenEnabled
,
WeChatOAuthMPEnabled
:
settings
.
WeChatOAuthMPEnabled
,
WeChatOAuthMobileEnabled
:
settings
.
WeChatOAuthMobileEnabled
,
OIDCOAuthEnabled
:
settings
.
OIDCOAuthEnabled
,
OIDCOAuthProviderName
:
settings
.
OIDCOAuthProviderName
,
BackendModeEnabled
:
settings
.
BackendModeEnabled
,
...
...
backend/internal/service/domain_constants.go
View file @
54dc1767
...
...
@@ -115,8 +115,15 @@ const (
SettingKeyWeChatConnectEnabled
=
"wechat_connect_enabled"
SettingKeyWeChatConnectAppID
=
"wechat_connect_app_id"
SettingKeyWeChatConnectAppSecret
=
"wechat_connect_app_secret"
SettingKeyWeChatConnectOpenAppID
=
"wechat_connect_open_app_id"
SettingKeyWeChatConnectOpenAppSecret
=
"wechat_connect_open_app_secret"
SettingKeyWeChatConnectMPAppID
=
"wechat_connect_mp_app_id"
SettingKeyWeChatConnectMPAppSecret
=
"wechat_connect_mp_app_secret"
SettingKeyWeChatConnectMobileAppID
=
"wechat_connect_mobile_app_id"
SettingKeyWeChatConnectMobileAppSecret
=
"wechat_connect_mobile_app_secret"
SettingKeyWeChatConnectOpenEnabled
=
"wechat_connect_open_enabled"
SettingKeyWeChatConnectMPEnabled
=
"wechat_connect_mp_enabled"
SettingKeyWeChatConnectMobileEnabled
=
"wechat_connect_mobile_enabled"
SettingKeyWeChatConnectMode
=
"wechat_connect_mode"
SettingKeyWeChatConnectScopes
=
"wechat_connect_scopes"
SettingKeyWeChatConnectRedirectURL
=
"wechat_connect_redirect_url"
...
...
backend/internal/service/payment_order.go
View file @
54dc1767
...
...
@@ -519,13 +519,15 @@ func (s *PaymentService) getWeChatPaymentOAuthCredential(ctx context.Context) (s
)
}
cfg
,
err
:=
(
&
SettingService
{
settingRepo
:
s
.
configService
.
settingRepo
})
.
GetWeChatConnectOAuthConfig
(
ctx
)
if
err
!=
nil
||
!
cfg
.
SupportsMode
(
"mp"
)
||
strings
.
TrimSpace
(
cfg
.
AppID
)
==
""
||
strings
.
TrimSpace
(
cfg
.
AppSecret
)
==
""
{
appID
:=
strings
.
TrimSpace
(
cfg
.
AppIDForMode
(
"mp"
))
appSecret
:=
strings
.
TrimSpace
(
cfg
.
AppSecretForMode
(
"mp"
))
if
err
!=
nil
||
!
cfg
.
SupportsMode
(
"mp"
)
||
appID
==
""
||
appSecret
==
""
{
return
""
,
""
,
infraerrors
.
ServiceUnavailable
(
"WECHAT_PAYMENT_MP_NOT_CONFIGURED"
,
"wechat in-app payment requires a complete WeChat MP OAuth credential"
,
)
}
return
strings
.
TrimSpace
(
cfg
.
A
ppID
)
,
strings
.
TrimSpace
(
cfg
.
A
ppSecret
)
,
nil
return
a
ppID
,
a
ppSecret
,
nil
}
func
classifyCreatePaymentError
(
req
CreateOrderRequest
,
providerKey
string
,
err
error
)
error
{
...
...
backend/internal/service/setting_service.go
View file @
54dc1767
...
...
@@ -181,14 +181,19 @@ func normalizeWeChatConnectModeSetting(raw string) string {
switch
strings
.
ToLower
(
strings
.
TrimSpace
(
raw
))
{
case
"mp"
:
return
"mp"
case
"mobile"
:
return
"mobile"
default
:
return
"open"
}
}
func
defaultWeChatConnectScopeForMode
(
mode
string
)
string
{
if
normalizeWeChatConnectModeSetting
(
mode
)
==
"mp"
{
switch
normalizeWeChatConnectModeSetting
(
mode
)
{
case
"mp"
:
return
"snsapi_userinfo"
case
"mobile"
:
return
""
}
return
defaultWeChatConnectScopes
}
...
...
@@ -204,37 +209,47 @@ func normalizeWeChatConnectScopeSetting(raw, mode string) string {
default
:
return
defaultWeChatConnectScopeForMode
(
mode
)
}
case
"mobile"
:
return
""
default
:
return
defaultWeChatConnectScopes
}
}
func
parseWeChatConnectCapabilitySettings
(
settings
map
[
string
]
string
,
enabled
bool
,
mode
string
)
(
bool
,
bool
)
{
func
parseWeChatConnectCapabilitySettings
(
settings
map
[
string
]
string
,
enabled
bool
,
mode
string
)
(
bool
,
bool
,
bool
)
{
mode
=
normalizeWeChatConnectModeSetting
(
mode
)
rawOpen
,
hasOpen
:=
settings
[
SettingKeyWeChatConnectOpenEnabled
]
rawMP
,
hasMP
:=
settings
[
SettingKeyWeChatConnectMPEnabled
]
rawMobile
,
hasMobile
:=
settings
[
SettingKeyWeChatConnectMobileEnabled
]
openConfigured
:=
hasOpen
&&
strings
.
TrimSpace
(
rawOpen
)
!=
""
mpConfigured
:=
hasMP
&&
strings
.
TrimSpace
(
rawMP
)
!=
""
mobileConfigured
:=
hasMobile
&&
strings
.
TrimSpace
(
rawMobile
)
!=
""
if
openConfigured
||
mpConfigured
{
if
openConfigured
||
mpConfigured
||
mobileConfigured
{
openEnabled
:=
strings
.
TrimSpace
(
rawOpen
)
==
"true"
mpEnabled
:=
strings
.
TrimSpace
(
rawMP
)
==
"true"
return
openEnabled
,
mpEnabled
mobileEnabled
:=
strings
.
TrimSpace
(
rawMobile
)
==
"true"
return
openEnabled
,
mpEnabled
,
mobileEnabled
}
if
!
enabled
{
return
false
,
false
return
false
,
false
,
false
}
if
mode
==
"mp"
{
return
false
,
true
return
false
,
true
,
false
}
if
mode
==
"mobile"
{
return
false
,
false
,
true
}
return
true
,
false
return
true
,
false
,
false
}
func
normalizeWeChatConnectStoredMode
(
openEnabled
,
mpEnabled
bool
,
mode
string
)
string
{
func
normalizeWeChatConnectStoredMode
(
openEnabled
,
mpEnabled
,
mobileEnabled
bool
,
mode
string
)
string
{
switch
{
case
mpEnabled
:
return
"mp"
case
mobileEnabled
:
return
"mobile"
case
openEnabled
:
return
"open"
default
:
...
...
@@ -310,8 +325,15 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
SettingKeyWeChatConnectEnabled
,
SettingKeyWeChatConnectAppID
,
SettingKeyWeChatConnectAppSecret
,
SettingKeyWeChatConnectOpenAppID
,
SettingKeyWeChatConnectOpenAppSecret
,
SettingKeyWeChatConnectMPAppID
,
SettingKeyWeChatConnectMPAppSecret
,
SettingKeyWeChatConnectMobileAppID
,
SettingKeyWeChatConnectMobileAppSecret
,
SettingKeyWeChatConnectOpenEnabled
,
SettingKeyWeChatConnectMPEnabled
,
SettingKeyWeChatConnectMobileEnabled
,
SettingKeyWeChatConnectMode
,
SettingKeyWeChatConnectScopes
,
SettingKeyWeChatConnectRedirectURL
,
...
...
@@ -350,7 +372,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
if
oidcProviderName
==
""
{
oidcProviderName
=
"OIDC"
}
weChatEnabled
,
weChatOpenEnabled
,
weChatMPEnabled
:=
s
.
weChatOAuthCapabilitiesFromSettings
(
settings
)
weChatEnabled
,
weChatOpenEnabled
,
weChatMPEnabled
,
weChatMobileEnabled
:=
s
.
weChatOAuthCapabilitiesFromSettings
(
settings
)
// Password reset requires email verification to be enabled
emailVerifyEnabled
:=
settings
[
SettingKeyEmailVerifyEnabled
]
==
"true"
...
...
@@ -397,6 +419,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
WeChatOAuthEnabled
:
weChatEnabled
,
WeChatOAuthOpenEnabled
:
weChatOpenEnabled
,
WeChatOAuthMPEnabled
:
weChatMPEnabled
,
WeChatOAuthMobileEnabled
:
weChatMobileEnabled
,
BackendModeEnabled
:
settings
[
SettingKeyBackendModeEnabled
]
==
"true"
,
PaymentEnabled
:
settings
[
SettingPaymentEnabled
]
==
"true"
,
OIDCOAuthEnabled
:
oidcEnabled
,
...
...
@@ -456,6 +479,7 @@ func (s *SettingService) GetPublicSettingsForInjection(ctx context.Context) (any
WeChatOAuthEnabled
bool
`json:"wechat_oauth_enabled"`
WeChatOAuthOpenEnabled
bool
`json:"wechat_oauth_open_enabled"`
WeChatOAuthMPEnabled
bool
`json:"wechat_oauth_mp_enabled"`
WeChatOAuthMobileEnabled
bool
`json:"wechat_oauth_mobile_enabled"`
BackendModeEnabled
bool
`json:"backend_mode_enabled"`
PaymentEnabled
bool
`json:"payment_enabled"`
OIDCOAuthEnabled
bool
`json:"oidc_oauth_enabled"`
...
...
@@ -493,6 +517,7 @@ func (s *SettingService) GetPublicSettingsForInjection(ctx context.Context) (any
WeChatOAuthEnabled
:
settings
.
WeChatOAuthEnabled
,
WeChatOAuthOpenEnabled
:
settings
.
WeChatOAuthOpenEnabled
,
WeChatOAuthMPEnabled
:
settings
.
WeChatOAuthMPEnabled
,
WeChatOAuthMobileEnabled
:
settings
.
WeChatOAuthMobileEnabled
,
BackendModeEnabled
:
settings
.
BackendModeEnabled
,
PaymentEnabled
:
settings
.
PaymentEnabled
,
OIDCOAuthEnabled
:
settings
.
OIDCOAuthEnabled
,
...
...
@@ -512,15 +537,22 @@ func DefaultWeChatConnectScopesForMode(mode string) string {
func
(
s
*
SettingService
)
parseWeChatConnectOAuthConfig
(
settings
map
[
string
]
string
)
(
WeChatConnectOAuthConfig
,
error
)
{
enabled
:=
settings
[
SettingKeyWeChatConnectEnabled
]
==
"true"
mode
:=
normalizeWeChatConnectModeSetting
(
settings
[
SettingKeyWeChatConnectMode
])
openEnabled
,
mpEnabled
:=
parseWeChatConnectCapabilitySettings
(
settings
,
enabled
,
mode
)
mode
=
normalizeWeChatConnectStoredMode
(
openEnabled
,
mpEnabled
,
mode
)
openEnabled
,
mpEnabled
,
mobileEnabled
:=
parseWeChatConnectCapabilitySettings
(
settings
,
enabled
,
mode
)
mode
=
normalizeWeChatConnectStoredMode
(
openEnabled
,
mpEnabled
,
mobileEnabled
,
mode
)
cfg
:=
WeChatConnectOAuthConfig
{
Enabled
:
enabled
,
AppID
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppID
]),
AppSecret
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppSecret
]),
LegacyAppID
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppID
]),
LegacyAppSecret
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppSecret
]),
OpenAppID
:
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectOpenAppID
],
settings
[
SettingKeyWeChatConnectAppID
])),
OpenAppSecret
:
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectOpenAppSecret
],
settings
[
SettingKeyWeChatConnectAppSecret
])),
MPAppID
:
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMPAppID
],
settings
[
SettingKeyWeChatConnectAppID
])),
MPAppSecret
:
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMPAppSecret
],
settings
[
SettingKeyWeChatConnectAppSecret
])),
MobileAppID
:
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMobileAppID
],
settings
[
SettingKeyWeChatConnectAppID
])),
MobileAppSecret
:
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMobileAppSecret
],
settings
[
SettingKeyWeChatConnectAppSecret
])),
OpenEnabled
:
openEnabled
,
MPEnabled
:
mpEnabled
,
MobileEnabled
:
mobileEnabled
,
Mode
:
mode
,
Scopes
:
normalizeWeChatConnectScopeSetting
(
settings
[
SettingKeyWeChatConnectScopes
],
mode
),
RedirectURL
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectRedirectURL
]),
...
...
@@ -533,11 +565,29 @@ func (s *SettingService) parseWeChatConnectOAuthConfig(settings map[string]strin
if
!
cfg
.
Enabled
||
(
!
cfg
.
OpenEnabled
&&
!
cfg
.
MPEnabled
)
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
NotFound
(
"OAUTH_DISABLED"
,
"wechat oauth is disabled"
)
}
if
cfg
.
AppID
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth app id not configured"
)
if
cfg
.
OpenEnabled
{
if
cfg
.
AppIDForMode
(
"open"
)
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth pc app id not configured"
)
}
if
cfg
.
AppSecretForMode
(
"open"
)
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth pc app secret not configured"
)
}
}
if
cfg
.
MPEnabled
{
if
cfg
.
AppIDForMode
(
"mp"
)
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth official account app id not configured"
)
}
if
cfg
.
AppSecretForMode
(
"mp"
)
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth official account app secret not configured"
)
}
}
if
cfg
.
MobileEnabled
{
if
cfg
.
AppIDForMode
(
"mobile"
)
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth mobile app id not configured"
)
}
if
cfg
.
AppSecretForMode
(
"mobile"
)
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth mobile app secret not configured"
)
}
if
cfg
.
AppSecret
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth app secret not configured"
)
}
if
cfg
.
RedirectURL
==
""
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
InternalServer
(
"OAUTH_CONFIG_INVALID"
,
"wechat oauth redirect url not configured"
)
...
...
@@ -554,12 +604,34 @@ func (s *SettingService) parseWeChatConnectOAuthConfig(settings map[string]strin
return
cfg
,
nil
}
func
(
s
*
SettingService
)
weChatOAuthCapabilitiesFromSettings
(
settings
map
[
string
]
string
)
(
bool
,
bool
,
bool
)
{
cfg
,
err
:=
s
.
parseWeChatConnectOAuthConfig
(
settings
)
if
err
!=
nil
{
return
false
,
false
,
false
func
(
s
*
SettingService
)
weChatOAuthCapabilitiesFromSettings
(
settings
map
[
string
]
string
)
(
bool
,
bool
,
bool
,
bool
)
{
if
settings
[
SettingKeyWeChatConnectEnabled
]
!=
"true"
{
return
false
,
false
,
false
,
false
}
mode
:=
normalizeWeChatConnectModeSetting
(
settings
[
SettingKeyWeChatConnectMode
])
openEnabled
,
mpEnabled
,
mobileEnabled
:=
parseWeChatConnectCapabilitySettings
(
settings
,
true
,
mode
)
redirectURL
:=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectRedirectURL
])
frontendRedirectURL
:=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectFrontendRedirectURL
])
if
frontendRedirectURL
==
""
{
frontendRedirectURL
=
defaultWeChatConnectFrontend
}
return
true
,
cfg
.
OpenEnabled
,
cfg
.
MPEnabled
legacyAppID
:=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppID
])
legacyAppSecret
:=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppSecret
])
openAppID
:=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectOpenAppID
],
legacyAppID
))
openAppSecret
:=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectOpenAppSecret
],
legacyAppSecret
))
mpAppID
:=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMPAppID
],
legacyAppID
))
mpAppSecret
:=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMPAppSecret
],
legacyAppSecret
))
mobileAppID
:=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMobileAppID
],
legacyAppID
))
mobileAppSecret
:=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMobileAppSecret
],
legacyAppSecret
))
webRedirectReady
:=
redirectURL
!=
""
&&
frontendRedirectURL
!=
""
openReady
:=
openEnabled
&&
webRedirectReady
&&
openAppID
!=
""
&&
openAppSecret
!=
""
mpReady
:=
mpEnabled
&&
webRedirectReady
&&
mpAppID
!=
""
&&
mpAppSecret
!=
""
mobileReady
:=
mobileEnabled
&&
mobileAppID
!=
""
&&
mobileAppSecret
!=
""
return
openReady
||
mpReady
||
mobileReady
,
openReady
,
mpReady
,
mobileReady
}
// filterUserVisibleMenuItems filters out admin-only menu items from a raw JSON
...
...
@@ -744,9 +816,16 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
settings
.
PaymentVisibleMethodWxpaySource
=
wxpaySource
settings
.
WeChatConnectAppID
=
strings
.
TrimSpace
(
settings
.
WeChatConnectAppID
)
settings
.
WeChatConnectAppSecret
=
strings
.
TrimSpace
(
settings
.
WeChatConnectAppSecret
)
settings
.
WeChatConnectOpenAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
.
WeChatConnectOpenAppID
,
settings
.
WeChatConnectAppID
))
settings
.
WeChatConnectOpenAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
.
WeChatConnectOpenAppSecret
,
settings
.
WeChatConnectAppSecret
))
settings
.
WeChatConnectMPAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
.
WeChatConnectMPAppID
,
settings
.
WeChatConnectAppID
))
settings
.
WeChatConnectMPAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
.
WeChatConnectMPAppSecret
,
settings
.
WeChatConnectAppSecret
))
settings
.
WeChatConnectMobileAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
.
WeChatConnectMobileAppID
,
settings
.
WeChatConnectAppID
))
settings
.
WeChatConnectMobileAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
.
WeChatConnectMobileAppSecret
,
settings
.
WeChatConnectAppSecret
))
settings
.
WeChatConnectMode
=
normalizeWeChatConnectStoredMode
(
settings
.
WeChatConnectOpenEnabled
,
settings
.
WeChatConnectMPEnabled
,
settings
.
WeChatConnectMobileEnabled
,
settings
.
WeChatConnectMode
,
)
settings
.
WeChatConnectScopes
=
normalizeWeChatConnectScopeSetting
(
settings
.
WeChatConnectScopes
,
settings
.
WeChatConnectMode
)
...
...
@@ -827,8 +906,12 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
// WeChat Connect OAuth 登录
updates
[
SettingKeyWeChatConnectEnabled
]
=
strconv
.
FormatBool
(
settings
.
WeChatConnectEnabled
)
updates
[
SettingKeyWeChatConnectAppID
]
=
settings
.
WeChatConnectAppID
updates
[
SettingKeyWeChatConnectOpenAppID
]
=
settings
.
WeChatConnectOpenAppID
updates
[
SettingKeyWeChatConnectMPAppID
]
=
settings
.
WeChatConnectMPAppID
updates
[
SettingKeyWeChatConnectMobileAppID
]
=
settings
.
WeChatConnectMobileAppID
updates
[
SettingKeyWeChatConnectOpenEnabled
]
=
strconv
.
FormatBool
(
settings
.
WeChatConnectOpenEnabled
)
updates
[
SettingKeyWeChatConnectMPEnabled
]
=
strconv
.
FormatBool
(
settings
.
WeChatConnectMPEnabled
)
updates
[
SettingKeyWeChatConnectMobileEnabled
]
=
strconv
.
FormatBool
(
settings
.
WeChatConnectMobileEnabled
)
updates
[
SettingKeyWeChatConnectMode
]
=
settings
.
WeChatConnectMode
updates
[
SettingKeyWeChatConnectScopes
]
=
settings
.
WeChatConnectScopes
updates
[
SettingKeyWeChatConnectRedirectURL
]
=
settings
.
WeChatConnectRedirectURL
...
...
@@ -836,6 +919,15 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
if
settings
.
WeChatConnectAppSecret
!=
""
{
updates
[
SettingKeyWeChatConnectAppSecret
]
=
settings
.
WeChatConnectAppSecret
}
if
settings
.
WeChatConnectOpenAppSecret
!=
""
{
updates
[
SettingKeyWeChatConnectOpenAppSecret
]
=
settings
.
WeChatConnectOpenAppSecret
}
if
settings
.
WeChatConnectMPAppSecret
!=
""
{
updates
[
SettingKeyWeChatConnectMPAppSecret
]
=
settings
.
WeChatConnectMPAppSecret
}
if
settings
.
WeChatConnectMobileAppSecret
!=
""
{
updates
[
SettingKeyWeChatConnectMobileAppSecret
]
=
settings
.
WeChatConnectMobileAppSecret
}
// OEM设置
updates
[
SettingKeySiteName
]
=
settings
.
SiteName
...
...
@@ -1344,8 +1436,15 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
SettingKeyCustomMenuItems
:
"[]"
,
SettingKeyCustomEndpoints
:
"[]"
,
SettingKeyWeChatConnectEnabled
:
"false"
,
SettingKeyWeChatConnectOpenAppID
:
""
,
SettingKeyWeChatConnectOpenAppSecret
:
""
,
SettingKeyWeChatConnectMPAppID
:
""
,
SettingKeyWeChatConnectMPAppSecret
:
""
,
SettingKeyWeChatConnectMobileAppID
:
""
,
SettingKeyWeChatConnectMobileAppSecret
:
""
,
SettingKeyWeChatConnectOpenEnabled
:
"false"
,
SettingKeyWeChatConnectMPEnabled
:
"false"
,
SettingKeyWeChatConnectMobileEnabled
:
"false"
,
SettingKeyWeChatConnectMode
:
"open"
,
SettingKeyWeChatConnectScopes
:
"snsapi_login"
,
SettingKeyWeChatConnectFrontendRedirectURL
:
defaultWeChatConnectFrontend
,
...
...
@@ -1645,7 +1744,16 @@ func (s *SettingService) parseSettings(settings map[string]string) *SystemSettin
result
.
WeChatConnectAppID
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppID
])
result
.
WeChatConnectAppSecret
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppSecret
])
result
.
WeChatConnectAppSecretConfigured
=
result
.
WeChatConnectAppSecret
!=
""
result
.
WeChatConnectOpenEnabled
,
result
.
WeChatConnectMPEnabled
=
parseWeChatConnectCapabilitySettings
(
result
.
WeChatConnectOpenAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectOpenAppID
],
result
.
WeChatConnectAppID
))
result
.
WeChatConnectOpenAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectOpenAppSecret
],
result
.
WeChatConnectAppSecret
))
result
.
WeChatConnectOpenAppSecretConfigured
=
result
.
WeChatConnectOpenAppSecret
!=
""
result
.
WeChatConnectMPAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMPAppID
],
result
.
WeChatConnectAppID
))
result
.
WeChatConnectMPAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMPAppSecret
],
result
.
WeChatConnectAppSecret
))
result
.
WeChatConnectMPAppSecretConfigured
=
result
.
WeChatConnectMPAppSecret
!=
""
result
.
WeChatConnectMobileAppID
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMobileAppID
],
result
.
WeChatConnectAppID
))
result
.
WeChatConnectMobileAppSecret
=
strings
.
TrimSpace
(
firstNonEmpty
(
settings
[
SettingKeyWeChatConnectMobileAppSecret
],
result
.
WeChatConnectAppSecret
))
result
.
WeChatConnectMobileAppSecretConfigured
=
result
.
WeChatConnectMobileAppSecret
!=
""
result
.
WeChatConnectOpenEnabled
,
result
.
WeChatConnectMPEnabled
,
result
.
WeChatConnectMobileEnabled
=
parseWeChatConnectCapabilitySettings
(
settings
,
result
.
WeChatConnectEnabled
,
settings
[
SettingKeyWeChatConnectMode
],
...
...
@@ -1653,6 +1761,7 @@ func (s *SettingService) parseSettings(settings map[string]string) *SystemSettin
result
.
WeChatConnectMode
=
normalizeWeChatConnectStoredMode
(
result
.
WeChatConnectOpenEnabled
,
result
.
WeChatConnectMPEnabled
,
result
.
WeChatConnectMobileEnabled
,
settings
[
SettingKeyWeChatConnectMode
],
)
result
.
WeChatConnectScopes
=
normalizeWeChatConnectScopeSetting
(
settings
[
SettingKeyWeChatConnectScopes
],
result
.
WeChatConnectMode
)
...
...
@@ -2151,8 +2260,15 @@ func (s *SettingService) GetWeChatConnectOAuthConfig(ctx context.Context) (WeCha
SettingKeyWeChatConnectEnabled
,
SettingKeyWeChatConnectAppID
,
SettingKeyWeChatConnectAppSecret
,
SettingKeyWeChatConnectOpenAppID
,
SettingKeyWeChatConnectOpenAppSecret
,
SettingKeyWeChatConnectMPAppID
,
SettingKeyWeChatConnectMPAppSecret
,
SettingKeyWeChatConnectMobileAppID
,
SettingKeyWeChatConnectMobileAppSecret
,
SettingKeyWeChatConnectOpenEnabled
,
SettingKeyWeChatConnectMPEnabled
,
SettingKeyWeChatConnectMobileEnabled
,
SettingKeyWeChatConnectMode
,
SettingKeyWeChatConnectScopes
,
SettingKeyWeChatConnectRedirectURL
,
...
...
backend/internal/service/settings_view.go
View file @
54dc1767
package
service
import
"strings"
func
firstNonEmpty
(
values
...
string
)
string
{
for
_
,
value
:=
range
values
{
if
trimmed
:=
strings
.
TrimSpace
(
value
);
trimmed
!=
""
{
return
trimmed
}
}
return
""
}
type
SystemSettings
struct
{
RegistrationEnabled
bool
EmailVerifyEnabled
bool
...
...
@@ -36,8 +47,18 @@ type SystemSettings struct {
WeChatConnectAppID
string
WeChatConnectAppSecret
string
WeChatConnectAppSecretConfigured
bool
WeChatConnectOpenAppID
string
WeChatConnectOpenAppSecret
string
WeChatConnectOpenAppSecretConfigured
bool
WeChatConnectMPAppID
string
WeChatConnectMPAppSecret
string
WeChatConnectMPAppSecretConfigured
bool
WeChatConnectMobileAppID
string
WeChatConnectMobileAppSecret
string
WeChatConnectMobileAppSecretConfigured
bool
WeChatConnectOpenEnabled
bool
WeChatConnectMPEnabled
bool
WeChatConnectMobileEnabled
bool
WeChatConnectMode
string
WeChatConnectScopes
string
WeChatConnectRedirectURL
string
...
...
@@ -177,6 +198,7 @@ type PublicSettings struct {
WeChatOAuthEnabled
bool
WeChatOAuthOpenEnabled
bool
WeChatOAuthMPEnabled
bool
WeChatOAuthMobileEnabled
bool
BackendModeEnabled
bool
PaymentEnabled
bool
OIDCOAuthEnabled
bool
...
...
@@ -191,10 +213,17 @@ type PublicSettings struct {
type
WeChatConnectOAuthConfig
struct
{
Enabled
bool
AppID
string
AppSecret
string
LegacyAppID
string
LegacyAppSecret
string
OpenAppID
string
OpenAppSecret
string
MPAppID
string
MPAppSecret
string
MobileAppID
string
MobileAppSecret
string
OpenEnabled
bool
MPEnabled
bool
MobileEnabled
bool
Mode
string
Scopes
string
RedirectURL
string
...
...
@@ -205,18 +234,43 @@ func (cfg WeChatConnectOAuthConfig) SupportsMode(mode string) bool {
switch
normalizeWeChatConnectModeSetting
(
mode
)
{
case
"mp"
:
return
cfg
.
MPEnabled
case
"mobile"
:
return
cfg
.
MobileEnabled
default
:
return
cfg
.
OpenEnabled
}
}
func
(
cfg
WeChatConnectOAuthConfig
)
ScopeForMode
(
mode
string
)
string
{
if
normalizeWeChatConnectModeSetting
(
mode
)
==
"mp"
{
switch
normalizeWeChatConnectModeSetting
(
mode
)
{
case
"mp"
:
return
normalizeWeChatConnectScopeSetting
(
cfg
.
Scopes
,
"mp"
)
case
"mobile"
:
return
""
}
return
defaultWeChatConnectScopeForMode
(
"open"
)
}
func
(
cfg
WeChatConnectOAuthConfig
)
AppIDForMode
(
mode
string
)
string
{
switch
normalizeWeChatConnectModeSetting
(
mode
)
{
case
"mp"
:
return
strings
.
TrimSpace
(
firstNonEmpty
(
cfg
.
MPAppID
,
cfg
.
LegacyAppID
))
case
"mobile"
:
return
strings
.
TrimSpace
(
firstNonEmpty
(
cfg
.
MobileAppID
,
cfg
.
LegacyAppID
))
}
return
strings
.
TrimSpace
(
firstNonEmpty
(
cfg
.
OpenAppID
,
cfg
.
LegacyAppID
))
}
func
(
cfg
WeChatConnectOAuthConfig
)
AppSecretForMode
(
mode
string
)
string
{
switch
normalizeWeChatConnectModeSetting
(
mode
)
{
case
"mp"
:
return
strings
.
TrimSpace
(
firstNonEmpty
(
cfg
.
MPAppSecret
,
cfg
.
LegacyAppSecret
))
case
"mobile"
:
return
strings
.
TrimSpace
(
firstNonEmpty
(
cfg
.
MobileAppSecret
,
cfg
.
LegacyAppSecret
))
}
return
strings
.
TrimSpace
(
firstNonEmpty
(
cfg
.
OpenAppSecret
,
cfg
.
LegacyAppSecret
))
}
// StreamTimeoutSettings 流超时处理配置(仅控制超时后的处理方式,超时判定由网关配置控制)
type
StreamTimeoutSettings
struct
{
// Enabled 是否启用流超时处理
...
...
frontend/src/api/admin/settings.ts
View file @
54dc1767
...
...
@@ -32,7 +32,7 @@ export type PaymentVisibleMethodSource =
|
"
easypay_alipay
"
|
"
official_wxpay
"
|
"
easypay_wxpay
"
;
export
type
WeChatConnectMode
=
"
open
"
|
"
mp
"
;
export
type
WeChatConnectMode
=
"
open
"
|
"
mp
"
|
"
mobile
"
;
export
interface
PaymentVisibleMethodSourceOption
{
value
:
PaymentVisibleMethodSource
;
...
...
@@ -108,11 +108,16 @@ const PAYMENT_VISIBLE_METHOD_SOURCE_ALIASES: Record<
},
};
const
WECHAT_CONNECT_MODE_OPTIONS
:
WeChatConnectModeOption
[]
=
[
{
value
:
"
open
"
,
labelZh
:
"
微信开放平台
"
,
labelEn
:
"
WeChat Open Platform
"
},
{
value
:
"
open
"
,
labelZh
:
"
PC 应用
"
,
labelEn
:
"
PC App
"
},
{
value
:
"
mp
"
,
labelZh
:
"
微信公众号 / 小程序
"
,
labelEn
:
"
WeChat Official Account / Mini Program
"
,
labelZh
:
"
公众号
"
,
labelEn
:
"
Official Account
"
,
},
{
value
:
"
mobile
"
,
labelZh
:
"
移动应用
"
,
labelEn
:
"
Mobile App
"
,
},
];
const
WECHAT_CONNECT_MODE_ALIASES
:
Record
<
string
,
WeChatConnectMode
>
=
{
...
...
@@ -124,6 +129,9 @@ const WECHAT_CONNECT_MODE_ALIASES: Record<string, WeChatConnectMode> = {
official_account
:
"
mp
"
,
wechat_mp
:
"
mp
"
,
mini_program
:
"
mp
"
,
mobile
:
"
mobile
"
,
mobile_app
:
"
mobile
"
,
native_app
:
"
mobile
"
,
};
export
function
normalizeDefaultSubscriptionSettings
(
...
...
@@ -234,34 +242,52 @@ export function normalizeWeChatConnectMode(source: unknown): WeChatConnectMode {
}
export
function
defaultWeChatConnectScopesForMode
(
mode
:
unknown
):
string
{
return
normalizeWeChatConnectMode
(
mode
)
===
"
mp
"
?
"
snsapi_userinfo
"
:
"
snsapi_login
"
;
switch
(
normalizeWeChatConnectMode
(
mode
))
{
case
"
mp
"
:
return
"
snsapi_userinfo
"
;
case
"
mobile
"
:
return
""
;
default
:
return
"
snsapi_login
"
;
}
}
export
function
resolveWeChatConnectModeCapabilities
(
openEnabled
:
unknown
,
mpEnabled
:
unknown
,
mobileEnabled
:
unknown
,
legacyMode
:
unknown
,
):
{
openEnabled
:
boolean
;
mpEnabled
:
boolean
}
{
if
(
typeof
openEnabled
===
"
boolean
"
||
typeof
mpEnabled
===
"
boolean
"
)
{
):
{
openEnabled
:
boolean
;
mpEnabled
:
boolean
;
mobileEnabled
:
boolean
}
{
if
(
typeof
openEnabled
===
"
boolean
"
||
typeof
mpEnabled
===
"
boolean
"
||
typeof
mobileEnabled
===
"
boolean
"
)
{
return
{
openEnabled
:
openEnabled
===
true
,
mpEnabled
:
mpEnabled
===
true
,
mobileEnabled
:
mobileEnabled
===
true
,
};
}
return
normalizeWeChatConnectMode
(
legacyMode
)
===
"
mp
"
?
{
openEnabled
:
false
,
mpEnabled
:
true
}
:
{
openEnabled
:
true
,
mpEnabled
:
false
};
switch
(
normalizeWeChatConnectMode
(
legacyMode
))
{
case
"
mp
"
:
return
{
openEnabled
:
false
,
mpEnabled
:
true
,
mobileEnabled
:
false
};
case
"
mobile
"
:
return
{
openEnabled
:
false
,
mpEnabled
:
false
,
mobileEnabled
:
true
};
default
:
return
{
openEnabled
:
true
,
mpEnabled
:
false
,
mobileEnabled
:
false
};
}
}
export
function
deriveWeChatConnectStoredMode
(
openEnabled
:
boolean
,
mpEnabled
:
boolean
,
mobileEnabled
:
boolean
,
legacyMode
:
unknown
,
):
WeChatConnectMode
{
if
(
mpEnabled
)
return
"
mp
"
;
if
(
mobileEnabled
)
return
"
mobile
"
;
if
(
openEnabled
)
return
"
open
"
;
return
normalizeWeChatConnectMode
(
legacyMode
);
}
...
...
@@ -342,8 +368,15 @@ export interface SystemSettings {
wechat_connect_enabled
:
boolean
;
wechat_connect_app_id
:
string
;
wechat_connect_app_secret_configured
:
boolean
;
wechat_connect_open_app_id
?:
string
;
wechat_connect_open_app_secret_configured
?:
boolean
;
wechat_connect_mp_app_id
?:
string
;
wechat_connect_mp_app_secret_configured
?:
boolean
;
wechat_connect_mobile_app_id
?:
string
;
wechat_connect_mobile_app_secret_configured
?:
boolean
;
wechat_connect_open_enabled
?:
boolean
;
wechat_connect_mp_enabled
?:
boolean
;
wechat_connect_mobile_enabled
?:
boolean
;
wechat_connect_mode
:
string
;
wechat_connect_scopes
:
string
;
wechat_connect_redirect_url
:
string
;
...
...
@@ -501,8 +534,15 @@ export interface UpdateSettingsRequest {
wechat_connect_enabled
?:
boolean
;
wechat_connect_app_id
?:
string
;
wechat_connect_app_secret
?:
string
;
wechat_connect_open_app_id
?:
string
;
wechat_connect_open_app_secret
?:
string
;
wechat_connect_mp_app_id
?:
string
;
wechat_connect_mp_app_secret
?:
string
;
wechat_connect_mobile_app_id
?:
string
;
wechat_connect_mobile_app_secret
?:
string
;
wechat_connect_open_enabled
?:
boolean
;
wechat_connect_mp_enabled
?:
boolean
;
wechat_connect_mobile_enabled
?:
boolean
;
wechat_connect_mode
?:
string
;
wechat_connect_scopes
?:
string
;
wechat_connect_redirect_url
?:
string
;
...
...
frontend/src/components/auth/WechatOAuthSection.vue
View file @
54dc1767
...
...
@@ -57,6 +57,11 @@ const disabledHint = computed(() => {
return
t
(
'
auth.oauthFlow.wechatSystemBrowserOnly
'
)
case
'
wechat_browser_required
'
:
return
t
(
'
auth.oauthFlow.wechatBrowserOnly
'
)
case
'
native_app_required
'
:
return
localizeWeChatHint
(
'
当前仅配置微信移动应用登录,需要在原生 App 中通过微信 SDK 发起授权。
'
,
'
This site only has WeChat mobile app login configured. Continue from the native app through the WeChat SDK.
'
,
)
case
'
not_configured
'
:
return
t
(
'
auth.oauthFlow.wechatNotConfigured
'
)
default
:
...
...
frontend/src/stores/app.ts
View file @
54dc1767
...
...
@@ -344,6 +344,7 @@ export const useAppStore = defineStore('app', () => {
wechat_oauth_enabled
:
false
,
wechat_oauth_open_enabled
:
false
,
wechat_oauth_mp_enabled
:
false
,
wechat_oauth_mobile_enabled
:
false
,
oidc_oauth_enabled
:
false
,
oidc_oauth_provider_name
:
'
OIDC
'
,
backend_mode_enabled
:
false
,
...
...
frontend/src/types/index.ts
View file @
54dc1767
...
...
@@ -168,6 +168,7 @@ export interface PublicSettings {
wechat_oauth_enabled
:
boolean
wechat_oauth_open_enabled
?:
boolean
wechat_oauth_mp_enabled
?:
boolean
wechat_oauth_mobile_enabled
?:
boolean
oidc_oauth_enabled
:
boolean
oidc_oauth_provider_name
:
string
backend_mode_enabled
:
boolean
...
...
frontend/src/views/admin/SettingsView.vue
View file @
54dc1767
This diff is collapsed.
Click to expand it.
frontend/src/views/auth/LoginView.vue
View file @
54dc1767
...
...
@@ -184,7 +184,7 @@ import TotpLoginModal from '@/components/auth/TotpLoginModal.vue'
import
Icon
from
'
@/components/icons/Icon.vue
'
import
TurnstileWidget
from
'
@/components/TurnstileWidget.vue
'
import
{
useAuthStore
,
useAppStore
}
from
'
@/stores
'
import
{
getPublicSettings
,
isTotp2FARequired
}
from
'
@/api/auth
'
import
{
getPublicSettings
,
isTotp2FARequired
,
isWeChatWebOAuthEnabled
}
from
'
@/api/auth
'
import
type
{
TotpLoginResponse
}
from
'
@/types
'
const
{
t
}
=
useI18n
()
...
...
@@ -258,7 +258,7 @@ onMounted(async () => {
turnstileEnabled
.
value
=
settings
.
turnstile_enabled
turnstileSiteKey
.
value
=
settings
.
turnstile_site_key
||
''
linuxdoOAuthEnabled
.
value
=
settings
.
linuxdo_oauth_enabled
wechatOAuthEnabled
.
value
=
settings
.
wechat_oa
uth
_e
nabled
wechatOAuthEnabled
.
value
=
isWeChatWebOA
uth
E
nabled
(
settings
)
backendModeEnabled
.
value
=
settings
.
backend_mode_enabled
oidcOAuthEnabled
.
value
=
settings
.
oidc_oauth_enabled
oidcOAuthProviderName
.
value
=
settings
.
oidc_oauth_provider_name
||
'
OIDC
'
...
...
frontend/src/views/auth/RegisterView.vue
View file @
54dc1767
...
...
@@ -282,7 +282,12 @@ import WechatOAuthSection from '@/components/auth/WechatOAuthSection.vue'
import
Icon
from
'
@/components/icons/Icon.vue
'
import
TurnstileWidget
from
'
@/components/TurnstileWidget.vue
'
import
{
useAuthStore
,
useAppStore
}
from
'
@/stores
'
import
{
getPublicSettings
,
validatePromoCode
,
validateInvitationCode
}
from
'
@/api/auth
'
import
{
getPublicSettings
,
isWeChatWebOAuthEnabled
,
validatePromoCode
,
validateInvitationCode
}
from
'
@/api/auth
'
import
{
buildAuthErrorMessage
}
from
'
@/utils/authError
'
import
{
isRegistrationEmailSuffixAllowed
,
...
...
@@ -385,7 +390,7 @@ onMounted(async () => {
turnstileSiteKey
.
value
=
settings
.
turnstile_site_key
||
''
siteName
.
value
=
settings
.
site_name
||
'
Sub2API
'
linuxdoOAuthEnabled
.
value
=
settings
.
linuxdo_oauth_enabled
wechatOAuthEnabled
.
value
=
settings
.
wechat_oa
uth
_e
nabled
wechatOAuthEnabled
.
value
=
isWeChatWebOA
uth
E
nabled
(
settings
)
oidcOAuthEnabled
.
value
=
settings
.
oidc_oauth_enabled
oidcOAuthProviderName
.
value
=
settings
.
oidc_oauth_provider_name
||
'
OIDC
'
registrationEmailSuffixWhitelist
.
value
=
normalizeRegistrationEmailSuffixWhitelist
(
...
...
frontend/src/views/auth/WechatCallbackView.vue
View file @
54dc1767
...
...
@@ -504,6 +504,8 @@ function resolveWeChatOAuthUnavailableMessage(): string {
return
t
(
'
auth.oauthFlow.wechatSystemBrowserOnly
'
)
case
'
wechat_browser_required
'
:
return
t
(
'
auth.oauthFlow.wechatBrowserOnly
'
)
case
'
native_app_required
'
:
return
'
This WeChat sign-in flow is only available from the native mobile app.
'
case
'
not_configured
'
:
return
t
(
'
auth.oauthFlow.wechatNotConfigured
'
)
default
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment