package reportser import ( "91jd-server/common/dataReport" "91jd-server/common/db" "91jd-server/middleware/ua" "91jd-server/models/v/eventmod" "91jd-server/models/v/rchgordmod" "91jd-server/models/v/usermod" "91jd-server/models/v/vidmod" "crypto/md5" "encoding/hex" "encoding/json" "fmt" "strconv" "time" ) // ReportOrderCreatedEvent 订单创建事件 func ReportOrderCreatedEvent(t *db.MongoTool, user *usermod.User, ua ua.UA, ip string, order *rchgordmod.RechargeOrder) (err error) { orderType := "coin_purchase" page := KeyCoinPage coin := order.Amount if order.Category == 1 { orderType = "vip_subscription" page = KeyVipPage coin = 0 } eventId := newEventId(dataReport.ReportAppId(), user.UID, order.ID.Hex(), order.CreatedAt.Unix()) event := dataReport.NewCommonField(eventId, dataReport.EventTypeOrderCreated, user.UID, user.DistrictCode, ua, ip) var vipDurationID string var vipDurationName string if order.Category == 1 { vipDurationID = order.ProductID.Hex() vipDurationName = order.ProductName } event.Payload = jsonRawMessage(&dataReport.OrderCreatedEvent{ OrderID: order.ID.Hex(), // 订单号(唯一标识) OrderType: orderType, // 订单类型 ProductID: order.ProductID.Hex(), // 商品ID ProductName: order.ProductName, // 商品名称 Amount: jsonNumber(order.Money), // 订单金额(分) Currency: "CNY", // 货币类型 CoinQuantity: jsonNumber(coin), // 金币数量 VIPDurationID: vipDurationID, VIPDurationName: vipDurationName, SourcePageKey: page.Key(), // 来源页面标识 SourcePageName: page.Name(), // 来源页面名称 CreateTime: jsonNumber(order.CreatedAt.Unix()), }) b, _ := json.Marshal(event) // 写入数据库 return eventmod.Insert(t, &eventmod.Event{ EventId: event.EventID, EventType: event.Event, Data: string(b), Status: eventmod.Default, CreatedAt: time.Now(), UpdatedAt: time.Now(), }) } // ReportOrderPaidEvent 订单支付事件 func ReportOrderPaidEvent(t *db.MongoTool, order rchgordmod.RechargeOrder, transactionID string, amount int64, coin int64, vipExpirationTime, successAt time.Time) (err error) { user, err := usermod.FindUserByUID(order.UID) if err != nil || user == nil { return } orderType := "coin_purchase" var vipExpirationUnix int64 if order.Category == 1 { orderType = "vip_subscription" coin = 0 if vipExpirationTime.Unix() > 0 { vipExpirationUnix = vipExpirationTime.Unix() } } eventId := newEventId(dataReport.ReportAppId(), user.UID, order.ID.Hex(), successAt.Unix()) event := dataReport.NewCommonField(eventId, dataReport.EventTypeOrderPaid, user.UID, user.DistrictCode, order.Ua, order.UserIP) event.Payload = jsonRawMessage(&dataReport.OrderPaidEvent{ OrderID: order.ID.Hex(), // 订单号(关联创建事件) OrderType: orderType, // 订单类型:coin_purchase, vip_subscription ProductID: order.ProductID.Hex(), // 商品ID Amount: jsonNumber(amount), // 实际支付金额(分) Currency: "CNY", // 货币类型:CNY, USD CoinQuantity: jsonNumber(coin), // 金币数量(仅金币订单) VIPExpirationTime: jsonNumber(vipExpirationUnix), // VIP过期时间(10位时间戳) PayType: order.RechargeType, // 支付方式:wechat, alipay, bank_card PayChannel: "", // 支付渠道:银行名称 TransactionID: transactionID, // 第三方支付交易号 CreateTime: jsonNumber(successAt.Unix()), }) b, _ := json.Marshal(event) // 写入数据库 return eventmod.Insert(t, &eventmod.Event{ EventId: event.EventID, EventType: event.Event, Data: string(b), Status: eventmod.Default, CreatedAt: time.Now(), UpdatedAt: time.Now(), }) } // ReportCoinConsumeEvent 金币消耗事件 func ReportCoinConsumeEvent(t *db.MongoTool, orderId string, orderCreatedAt time.Time, user *usermod.User, ua ua.UA, ip string, productId, productName string, amount, balanceBefore, balanceAfter int64, reason Key) (err error) { if amount == 0 { return } if productId == "" { if productName == "" { productName = "金币消耗" } productId = Md5String(productName) } eventId := newEventId(dataReport.ReportAppId(), user.UID, orderId, orderCreatedAt.Unix()) event := dataReport.NewCommonField(eventId, dataReport.EventTypeCoinConsume, user.UID, user.DistrictCode, ua, ip) event.Payload = jsonRawMessage(&dataReport.CoinConsumeEvent{ ProductID: productId, // 商品ID ProductName: productName, // 商品名称 CoinConsumeAmount: jsonNumber(amount), // 金币消耗数量 CoinBalanceBefore: jsonNumber(balanceBefore), // 消耗前金币余额 CoinBalanceAfter: jsonNumber(balanceAfter), // 消耗后金币余额 ConsumeReasonKey: reason.Key(), // 消耗原因 ConsumeReasonName: reason.Name(), // 消耗原因名称 CreateTime: jsonNumber(orderCreatedAt.Unix()), OrderId: orderId, }) b, _ := json.Marshal(event) // 写入数据库 return eventmod.Insert(t, &eventmod.Event{ EventId: event.EventID, EventType: event.Event, Data: string(b), Status: eventmod.Default, CreatedAt: time.Now(), UpdatedAt: time.Now(), }) } // ReportVideoPurchase 视频购买事件 func ReportVideoPurchase(t *db.MongoTool, user *usermod.User, ua ua.UA, ip string, video *vidmod.VideoModel, orderId string) (err error) { meta := extractVideoMeta(video) event := dataReport.NewCommonField(dataReport.GenerateGlobalEventID(), dataReport.EventTypeVideoPurchase, user.UID, user.DistrictCode, ua, ip) event.Payload = jsonRawMessage(&dataReport.VideoPurchaseEvent{ VideoEventCore: meta.toEventCore(video.ID.Hex(), video.Title, ""), CoinQuantity: jsonNumber(video.Coins), // 金币数量 OrderID: orderId, // 订单号 }) b, _ := json.Marshal(event) // 写入数据库 return eventmod.Insert(t, &eventmod.Event{ EventId: event.EventID, EventType: event.Event, Data: string(b), Status: eventmod.Default, CreatedAt: time.Now(), UpdatedAt: time.Now(), }) } // ReportUserRegister 用户注册事件 func ReportUserRegister(t *db.MongoTool, user *usermod.User, ua ua.UA, ip string) (err error) { registerType := "deviceid" eventId := newEventId(dataReport.ReportAppId(), user.UID, "", user.CreatedAt.Unix()) event := dataReport.NewCommonField(eventId, dataReport.EventTypeUserRegister, user.UID, user.DistrictCode, ua, ip) event.Payload = jsonRawMessage(&dataReport.UserRegisterEvent{ Type: registerType, TraceID: user.Tid, CreateTime: jsonNumber(user.CreatedAt.Unix()), }) b, _ := json.Marshal(event) // 写入数据库 return eventmod.Insert(t, &eventmod.Event{ EventId: event.EventID, EventType: event.Event, Data: string(b), Status: eventmod.Default, CreatedAt: time.Now(), UpdatedAt: time.Now(), }) } func newEventId(appId string, uid uint64, orderId string, createTime int64) string { input := fmt.Sprintf("%v%v%v%v", appId, uid, orderId, createTime) return Md5String(input) } func jsonNumber(v int64) json.Number { return json.Number(strconv.FormatInt(v, 10)) } func jsonRawMessage(v interface{}) json.RawMessage { b, _ := json.Marshal(v) return b } func Md5String[T string | []byte](input T) string { h := md5.New() h.Write([]byte(input)) return hex.EncodeToString(h.Sum(nil)) }