fix(delivery): 绑定失败回退 DLC,并补齐乐玩角色名展示

乐玩写接口失败时清除渠道锁定改试 DLC;免扫码/查绑/提交路径回传 role_name 与 game_channel。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yml2213
2026-09-15 12:39:53 +08:00
co-authored by Cursor
parent 6c41834274
commit 848d3da809
2 changed files with 121 additions and 5 deletions
+25
View File
@@ -415,7 +415,9 @@ func (s *DeliveryService) bindWithOrder(orderNo, gameAccount string, auth *Deliv
var lastErr error
var bindRes *ProviderBindResult
var usedProvider FulfillmentProvider
tried := map[string]bool{}
for _, p := range providers {
tried[p.Name()] = true
res, err := p.Bind(context.Background(), order, gameAccount)
if err == nil && res != nil {
bindRes = res
@@ -424,6 +426,29 @@ func (s *DeliveryService) bindWithOrder(orderNo, gameAccount string, auth *Deliv
}
lastErr = err
}
// Prepare 可能因 GET 成功先锁住乐玩;随后写接口凭据/IP 校验失败时,清除锁定并尝试其余渠道(如 DLC)。
if bindRes == nil {
lockedName := resultDataString(order.ResultData, "provider")
if lockedName != "" || lastErr != nil {
s.clearSelectedProvider(order)
fallbackProviders, _ := s.router.ResolveProviders(order)
for _, p := range fallbackProviders {
if tried[p.Name()] {
continue
}
tried[p.Name()] = true
res, err := p.Bind(context.Background(), order, gameAccount)
if err == nil && res != nil {
bindRes = res
usedProvider = p
break
}
lastErr = err
}
}
}
if bindRes == nil {
if lastErr != nil {
return nil, lastErr
+96 -5
View File
@@ -181,11 +181,39 @@ func (p *LewanProvider) Bind(ctx context.Context, order *model.FulfillmentOrder,
// 3. 判断是否需要绑定
if bindingAction != nil && !bindingAction.BindingRequired {
// 角色已在乐玩绑定过,免扫码直接已绑定
// 角色已在乐玩绑定过,免扫码直接已绑定;尽量补齐角色名/区服,便于领取页展示。
roleName, gameChannel, boundRoleID := extractLewanRoleDisplay(lewanOrder, nil)
if refreshRes, refreshErr := p.client.RefreshBinding(ctx, lewanOrderID); refreshErr == nil {
rn, gc, rid := extractLewanRoleDisplay(nil, refreshRes)
if rn != "" {
roleName = rn
}
if gc != "" {
gameChannel = gc
}
if rid != "" {
boundRoleID = rid
}
}
if roleName != "" {
patch["role_name"] = roleName
}
if gameChannel != "" {
patch["game_channel"] = gameChannel
}
bindURL := strings.TrimSpace(bindingAction.BindingUrl)
qrURL := ""
if bindURL != "" {
qrURL = qrCodeURL(bindURL)
}
return &ProviderBindResult{
BindUUID: lewanOrderID,
BindURL: bindURL,
QRURL: qrURL,
Bound: true,
GameAccount: gameAccount,
GameAccount: firstNonEmpty(boundRoleID, gameAccount),
RoleName: roleName,
GameChannel: gameChannel,
Message: "账号已在平台授权,免扫码直接进入发货",
Provider: ProviderLewan,
PatchResultData: patch,
@@ -231,10 +259,13 @@ func (p *LewanProvider) CheckBind(ctx context.Context, order *model.FulfillmentO
orderDetail, getErr := p.client.GetOrder(ctx, lewanOrderID)
if getErr == nil && orderDetail != nil {
if orderDetail.Status != "WAITING_BINDING" {
roleName, gameChannel, boundRoleID := extractLewanRoleDisplay(orderDetail, nil)
return &ProviderBindResult{
BindUUID: lewanOrderID,
Bound: true,
GameAccount: orderDetail.RoleID,
GameAccount: firstNonEmpty(boundRoleID, orderDetail.RoleID),
RoleName: roleName,
GameChannel: gameChannel,
Message: "绑定已完成",
Provider: ProviderLewan,
}, nil
@@ -251,13 +282,27 @@ func (p *LewanProvider) CheckBind(ctx context.Context, order *model.FulfillmentO
bound := false
gameAccount := ""
roleName := ""
gameChannel := ""
if refreshRes != nil && refreshRes.Binding != nil {
bound = refreshRes.Binding.Matched
gameAccount = refreshRes.Binding.RoleID
roleName = refreshRes.Binding.RoleName
gameChannel = firstNonEmpty(refreshRes.Binding.RoleArea, refreshRes.Binding.ServerName)
}
if refreshRes != nil && refreshRes.Order != nil && refreshRes.Order.Status != "WAITING_BINDING" {
bound = true
if refreshRes != nil && refreshRes.Order != nil {
if refreshRes.Order.Status != "WAITING_BINDING" {
bound = true
}
rn, gc, rid := extractLewanRoleDisplay(refreshRes.Order, nil)
if roleName == "" {
roleName = rn
}
if gameChannel == "" {
gameChannel = gc
}
if gameAccount == "" {
gameAccount = rid
}
}
msg := "绑定成功"
@@ -270,6 +315,7 @@ func (p *LewanProvider) CheckBind(ctx context.Context, order *model.FulfillmentO
Bound: bound,
GameAccount: gameAccount,
RoleName: roleName,
GameChannel: gameChannel,
Message: msg,
Provider: ProviderLewan,
}, nil
@@ -323,8 +369,19 @@ func (p *LewanProvider) Submit(ctx context.Context, order *model.FulfillmentOrde
}
roleName := ""
gameChannel := ""
if refreshRes != nil && refreshRes.Binding != nil {
roleName = refreshRes.Binding.RoleName
gameChannel = firstNonEmpty(refreshRes.Binding.RoleArea, refreshRes.Binding.ServerName)
}
if roleName == "" || gameChannel == "" {
rn, gc, _ := extractLewanRoleDisplay(lewanOrder, nil)
if roleName == "" {
roleName = rn
}
if gameChannel == "" {
gameChannel = gc
}
}
return &ProviderSubmitResult{
@@ -334,6 +391,7 @@ func (p *LewanProvider) Submit(ctx context.Context, order *model.FulfillmentOrde
GameAccount: map[string]interface{}{
"game_account": gameAccount,
"role_name": roleName,
"game_channel": gameChannel,
},
UpstreamOrder: lewanOrder,
PatchResultData: map[string]interface{}{
@@ -345,6 +403,7 @@ func (p *LewanProvider) Submit(ctx context.Context, order *model.FulfillmentOrde
"lewan_status": lewanOrder.Status,
"game_uid": gameAccount,
"role_name": roleName,
"game_channel": gameChannel,
"delivery": lewanOrder,
},
}, nil
@@ -472,3 +531,35 @@ func (p *LewanProvider) SyncStatus(ctx context.Context, order *model.Fulfillment
}, nil
}
}
// extractLewanRoleDisplay 从乐玩订单/刷新结果提取角色名、区服与 RoleID,供领取页展示。
func extractLewanRoleDisplay(
order *lewan.LewanOrder,
refresh *lewan.RefreshBindingResult,
) (roleName, gameChannel, roleID string) {
if refresh != nil && refresh.Binding != nil {
roleName = strings.TrimSpace(refresh.Binding.RoleName)
gameChannel = firstNonEmpty(refresh.Binding.RoleArea, refresh.Binding.ServerName)
roleID = strings.TrimSpace(refresh.Binding.RoleID)
}
if refresh != nil && refresh.Order != nil && order == nil {
order = refresh.Order
}
if order != nil {
if roleID == "" {
roleID = strings.TrimSpace(order.RoleID)
}
if order.Binding != nil {
if roleName == "" {
roleName = strings.TrimSpace(order.Binding.RoleName)
}
if gameChannel == "" {
gameChannel = firstNonEmpty(order.Binding.RoleArea, order.Binding.ServerName)
}
if roleID == "" {
roleID = strings.TrimSpace(order.Binding.RoleID)
}
}
}
return roleName, gameChannel, roleID
}