Files
affiliate_dash/backend/internal/service/fulfillment_data.go
T
yml2213 2264851d5d 拆分 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 与文件尾部多余空行
2026-08-05 13:32:11 +08:00

158 lines
3.5 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 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 解析下单透传的 dataRequestData),非法或为空时返回空 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
}