tkcashgame_v4/app/eonline/internal/biz/shushu/client.go

241 lines
8.4 KiB
Go
Raw Normal View History

2025-10-22 10:01:11 +00:00
package shushu
import (
"encoding/json"
"fmt"
"time"
"sandc/pkg/bhttp"
"sandc/pkg/utils"
"github.com/go-kratos/kratos/v2/log"
)
// 定义数数client的接口
type Client interface {
SyncIapData(accountId, distinctId, eventName string, ip string, properties SSProperties) error
ReportError(accountId, distinctId, eventName string, ip string, properties SSProperties) error
}
// 定义数数client的实例
type client struct {
serverUrl string
appId string
env string
service *bhttp.BhttpService
}
// SyncData 定义数数上传结构体
type SyncData struct {
Appid string `json:"appid,omitempty"`
Debug int `json:"debug,omitempty"`
Data Data `json:"data,omitempty"`
}
type Data struct {
AccountId string `json:"#account_id,omitempty"`
DistinctId string `json:"#distinct_id,omitempty"`
Type string `json:"#type,omitempty"`
Ip string `json:"#ip,omitempty"`
Uuid string `json:"#uuid,omitempty"`
Time string `json:"#time,omitempty"`
EventName string `json:"#event_name,omitempty"`
Properties interface{} `json:"properties,omitempty"`
}
// SSIapProperties 定义数数上传Properties结构体
type SSIapProperties struct {
// Add your properties here
GpsAdid string `json:"gps_adid"` // 用户的gaid
AppToken string `json:"app_token"` // 控制面板上的 Adjust 应用识别码
EventToken string `json:"event_token"` // 控制面板上的 Adjust 事件识别码
S2S string `json:"s2s"` // s2s 参数设置为 1
AndroidId string `json:"android_id"` // 原始安卓 ID
Adid string `json:"adid"` // 与设备关联的 Adjust 标识符
IpAddress string `json:"ip_address"` // 设备 IP 地址。用于将事件关联至第三方 (例如 Google) 并在回传中包含位置相关信息 (例如city 、 postal_code )。 ip_address参数仅接受 IPv4 地址。当前不支持 IPv6。
CreatedAtUnix string `json:"created_at_unix"` // 事件发生的日期和时间。
UserAgent string `json:"user_agent"` // 设备的User-Agent。必须进行 URL 编码。
Price string `json:"price"` // 客户端上报的价格
Currency string `json:"currency"` // 货币单位
FailReason string `json:"fail_reason"` // 失败原因
PayoutId string `json:"payout_id"` // 提现订单号1实例TS202504150316045rg110SPMDjPB
MerchantReference string `json:"merchant_reference"` // 提现订单号2实例PGs bfd267c7823a80d97519197a30bfdf28
PaymentMethod string `json:"payment_method"` // 收款方式
PaymentType string `json:"payment_type"` // 账户形式
PaymentNumber string `json:"payment_number"` // 账户号码
IapName string `json:"iap_name"` // 商品名称
GamecoinNumber string `json:"gamecoin_number"` // 提现消耗的虚拟货币数
GamecoinType string `json:"gamecoin_type"` // 提现消耗的虚拟货币类型
SsAccountId string `json:"ss_account_id"` // 数数账号ID
SsDistinctId string `json:"ss_distinct_id"` // 数数访客ID
SsSuperProperties string `json:"ss_super_properties"` // 数数的公共属性和预制属性
ClientName string `json:"client_name"` // 客户端包名
// Value float64 `json:"value"`
// Platform string `json:"platform"`
// PlatformChannel string `json:"platform_channel"`
// PlatformOs string `json:"platform_os"`
// ProductId string `json:"product_id"`
// OrderId string `json:"order_id"`
// Currency string `json:"currency"`
// Environment string `json:"environment"`
// AdNetwork string `json:"ad_network"`
// Campaign string `json:"campaign"`
// Adgroup string `json:"adgroup"`
// Creative string `json:"creative"`
}
// SSErrorProperties 定义数数上报的错误信息
type SSErrorProperties struct {
Value float64 `json:"value"`
Platform string `json:"platform"`
ProductId string `json:"product_id"`
OrderId string `json:"order_id"`
Currency string `json:"currency"`
Environment string `json:"environment"`
Msg string `json:"msg"`
AdNetwork string `json:"ad_network"`
Campaign string `json:"campaign"`
Adgroup string `json:"adgroup"`
Creative string `json:"creative"`
PlatformChannel string `json:"platform_channel"`
PlatformOs string `json:"platform_os"`
}
type SSProperties map[string]interface{}
// SyncRes 定义数数上传返回结构体
type SyncRes struct {
Code int `json:"code"`
Message string `json:"msg"`
}
func NewClient(serverUrl string, appId string, env string) (Client, error) {
service, err := bhttp.NewBhttpService(bhttp.WithCheckStatusOk(true), bhttp.WithTimeout(30))
if err != nil {
return nil, err
}
service.Client.SetHeader("Content-Type", "application/json")
return &client{
appId: appId,
serverUrl: serverUrl,
env: env,
service: service,
}, nil
}
func (c *client) syncJson(accountId, distinctId, eventName string, ip string, properties interface{}) error {
debug := 0
if !c.IsProd() {
debug = 1
}
if accountId == "" && distinctId == "" {
return fmt.Errorf("accountId or distinctId is empty")
}
// 根据properties生成唯一的uuid
propertiesStr := utils.MD5Any(properties)
uuid := utils.GenerateUUID(propertiesStr)
syncData := &SyncData{
Appid: c.appId,
Debug: debug,
Data: Data{
AccountId: accountId,
DistinctId: distinctId,
Type: "track",
Ip: ip,
Uuid: uuid,
Time: time.Now().Format("2006-01-02 15:04:05.000"),
EventName: eventName,
Properties: properties,
},
}
postBody, err := json.Marshal(syncData)
if err != nil {
return fmt.Errorf("json.Marshal SyncIapData error: %v", err)
}
c.service.Client.SetBody(postBody)
url := fmt.Sprintf("%s/sync_json", c.serverUrl)
// utils.PrintLog("SyncIapData-url: %s", url)
// utils.PrintLog("SyncIapData-postbody: %s", postBody)
log.Infof("SyncIapData-url: %s", url)
log.Infof("SyncIapData-postbody: %s", postBody)
sendData := postBody
numMax := 1
for i := 0; i < numMax; i++ {
body, err := c.service.Client.DoPost(url)
if err != nil {
return fmt.Errorf("shushu server err: %s, reader: %s", err, sendData)
}
var res SyncRes
err = json.Unmarshal(body, &res)
if err != nil {
return fmt.Errorf("shushu Unmarshal err: %s, reader: %s", res.Message, sendData)
}
if res.Code == 0 {
log.Infof("shushu send successed: i[%d] reader: %s", i, sendData)
break
} else {
log.Infof("shushu res error: %s, i[%d] reader: %s", res.Message, i, sendData)
if i+1 >= numMax {
return fmt.Errorf("shushu res err: %s, reader: %s", res.Message, sendData)
}
}
}
return nil
}
func setSsSuperPropertiesMap(propertiesMap SSProperties) {
v, ok := propertiesMap["ss_super_properties"]
if !ok || v == nil {
log.Infof("setSsSuperPropertiesMap error: ss_super_properties not found in propertiesMap[%v]", propertiesMap)
return
}
ssSuperProperties, ok := v.(string)
if !ok {
log.Infof("setSsSuperPropertiesMap error: ss_super_properties not string[%v]", propertiesMap)
return
}
// 解析 ss_super_properties
var ssSuperPropertiesMap SSProperties
if ssSuperProperties != "" {
err := json.Unmarshal([]byte(ssSuperProperties), &ssSuperPropertiesMap)
if err != nil {
log.Infof("setSsSuperPropertiesMap error: unmarshal err[%v], ssSuperProperties[%s]", err, ssSuperProperties)
return
}
// 插入解析出来的新字段
for key, value := range ssSuperPropertiesMap {
if _, ok := propertiesMap[key]; !ok && key != "#zone_offset" {
propertiesMap[key] = value
}
}
} else {
log.Infof("setSsSuperPropertiesMap error: ss_super_properties is empty[%v]", propertiesMap)
}
}
func (c *client) ReportError(accountId, distinctId, eventName string, ip string, properties SSProperties) error {
setSsSuperPropertiesMap(properties)
return c.syncJson(accountId, distinctId, eventName, ip, properties)
}
func (c *client) SyncIapData(accountId, distinctId, eventName string, ip string, properties SSProperties) error {
setSsSuperPropertiesMap(properties)
return c.syncJson(accountId, distinctId, eventName, ip, properties)
}
func (c *client) IsProd() bool {
return c.env == "prod"
}