拆分 service 与前端大文件,修复 CORS 配置与格式问题
- 后端 internal/service 按职责拆分: fulfillment.go(1397→527)拆出 wallet/timeout/data/order/query/dashboard/shipnotify delivery.go(1124→801)拆出 upstream/link/state/helpers merchant.go(855→251)拆出 member/product/api_client/catalog/helpers - 前端 MerchantCenter.tsx(1327→606)拆出 merchantCenterTabs/merchantCenterUtils - docker-compose backend 透传 CORS_ALLOWED_ORIGINS - CORS 白名单实现(config/router/README/.env.example 配套) - 修复 gofmt 与文件尾部多余空行
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"affiliate_dash/internal/pkg/timeutil"
|
||||
)
|
||||
|
||||
// buildShipNotifyResultData 把推送结果与游戏字段合并进 ResultData JSON。
|
||||
func buildShipNotifyResultData(existing string, in ShipNotifyInput, shippedAt *time.Time) string {
|
||||
m := map[string]interface{}{}
|
||||
if existing != "" && json.Valid([]byte(existing)) {
|
||||
_ = json.Unmarshal([]byte(existing), &m)
|
||||
}
|
||||
m["ship_status"] = in.ShipStatus
|
||||
if in.ProviderOrderNo != "" {
|
||||
m["provider_order_no"] = in.ProviderOrderNo
|
||||
}
|
||||
if in.ShipStatus == "success" {
|
||||
delete(m, "fail_reason")
|
||||
} else if in.FailReason != "" {
|
||||
m["fail_reason"] = in.FailReason
|
||||
}
|
||||
if shippedAt != nil {
|
||||
m["shipped_at"] = timeutil.FormatAPITime(*shippedAt)
|
||||
}
|
||||
if in.GameChannel != nil {
|
||||
m["game_channel"] = *in.GameChannel
|
||||
}
|
||||
if in.GameUID != nil {
|
||||
m["game_uid"] = *in.GameUID
|
||||
}
|
||||
if in.RoleName != nil {
|
||||
m["role_name"] = *in.RoleName
|
||||
}
|
||||
if in.PayScore != nil {
|
||||
m["pay_score"] = *in.PayScore
|
||||
}
|
||||
raw, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return existing
|
||||
}
|
||||
return string(raw)
|
||||
}
|
||||
|
||||
// mergeResultData 保留已有 JSON 字段,仅覆盖或新增 patch 中的字段,避免各发货阶段互相清空上下文。
|
||||
func mergeResultData(existing string, patch map[string]interface{}) string {
|
||||
if len(patch) == 0 {
|
||||
return existing
|
||||
}
|
||||
m := map[string]interface{}{}
|
||||
if existing != "" && json.Valid([]byte(existing)) {
|
||||
_ = json.Unmarshal([]byte(existing), &m)
|
||||
}
|
||||
for k, v := range patch {
|
||||
m[k] = v
|
||||
}
|
||||
raw, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return existing
|
||||
}
|
||||
return string(raw)
|
||||
}
|
||||
|
||||
func resultDataMap(raw string) map[string]interface{} {
|
||||
m := map[string]interface{}{}
|
||||
if raw != "" && json.Valid([]byte(raw)) {
|
||||
_ = json.Unmarshal([]byte(raw), &m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// requestDataMap 解析下单透传的 data(RequestData),非法或为空时返回空 map。
|
||||
func requestDataMap(raw string) map[string]interface{} {
|
||||
m := map[string]interface{}{}
|
||||
if raw != "" && json.Valid([]byte(raw)) {
|
||||
_ = json.Unmarshal([]byte(raw), &m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// requestDataString 读取下单透传 data 中的字符串字段。
|
||||
func requestDataString(raw, key string) string {
|
||||
if v, ok := requestDataMap(raw)[key].(string); ok {
|
||||
return strings.TrimSpace(v)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func resultDataString(raw, key string) string {
|
||||
if v, ok := resultDataMap(raw)[key].(string); ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func resultDataNumber(raw, key string) int64 {
|
||||
switch v := resultDataMap(raw)[key].(type) {
|
||||
case float64:
|
||||
return int64(v)
|
||||
case int64:
|
||||
return v
|
||||
case int:
|
||||
return int64(v)
|
||||
case string:
|
||||
if n, err := strconv.ParseInt(v, 10, 64); err == nil {
|
||||
return n
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// extractGameFields 从 JSON 文本中还原游戏相关字段(仅填充当前为空的字段)。
|
||||
func extractGameFields(raw string, out *OpenOrderQuery) {
|
||||
if raw == "" || !json.Valid([]byte(raw)) {
|
||||
return
|
||||
}
|
||||
var m map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(raw), &m); err != nil {
|
||||
return
|
||||
}
|
||||
if out.GameChannel == "" {
|
||||
if v, ok := m["game_channel"].(string); ok {
|
||||
out.GameChannel = v
|
||||
}
|
||||
}
|
||||
if out.GameUID == "" {
|
||||
if v, ok := m["game_uid"].(string); ok {
|
||||
out.GameUID = v
|
||||
}
|
||||
}
|
||||
if out.RoleName == "" {
|
||||
if v, ok := m["role_name"].(string); ok {
|
||||
out.RoleName = v
|
||||
}
|
||||
}
|
||||
if out.PayScore == 0 {
|
||||
if v, ok := toInt(m["pay_score"]); ok {
|
||||
out.PayScore = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toInt(v interface{}) (int, bool) {
|
||||
switch n := v.(type) {
|
||||
case float64:
|
||||
return int(n), true
|
||||
case int:
|
||||
return n, true
|
||||
case int64:
|
||||
return int(n), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
Reference in New Issue
Block a user