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

241 lines
8.4 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 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"
}