package productser import ( "91porn-server/app/appg" "91porn-server/app/service/taskser" "91porn-server/common" "91porn-server/common/game" "91porn-server/models/v/advanceordermod" "91porn-server/models/v/backpackmod" "91porn-server/models/v/oncetaskmod" "91porn-server/models/v/signrecordmod" "errors" "fmt" "math" "time" "go.mongodb.org/mongo-driver/bson" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/models/v/prdcthsomod" "91porn-server/models/v/productmod" "91porn-server/models/v/rchgordmod" "91porn-server/models/v/txnmod" "91porn-server/models/v/usermod" "91porn-server/models/v/videocoupon" "91porn-server/models/v/videodiscountmod" "91porn-server/models/v/walletmod" "go.mongodb.org/mongo-driver/bson/primitive" ) // NewBuyMeetingCard 新版购买约会卡 func NewBuyMeetingCard(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet) func(*db.MongoTool) error { var ( //商品购买记录 history = prdcthsomod.ProductHistory{ ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.MeetingCard, DiscDoc: order.DiscDoc, SysType: order.DevType, ProductSnapShot: p, } // 资金流水记录 transactionLog = &txnmod.TransactionLog{ UID: order.UID, TranType: txnmod.MeetingCard.Key(), TranTypeInt: int64(txnmod.MeetingCard), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -p.DiscountedPrice, ActualAmount: float64(-p.DiscountedPrice), RealAmount: w.RealAmount(), } ) return func(t *db.MongoTool) error { // 保存商品购买记录 if err := prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 保存资金流水记录 return txnmod.InsertTransactionLog(t, transactionLog) } } // NewBuyOtherCard 新版购买其他卡/实体商品 func NewBuyOtherCard(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet) func(*db.MongoTool) error { var ( //商品购买记录 history = prdcthsomod.ProductHistory{ ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.OTHER, DiscDoc: order.DiscDoc, SysType: order.DevType, ProductSnapShot: p, } // 资金流水记录 transactionLog = &txnmod.TransactionLog{ UID: order.UID, TranType: txnmod.Other.Key(), TranTypeInt: int64(txnmod.Other), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -p.DiscountedPrice, ActualAmount: float64(-p.DiscountedPrice), RealAmount: w.RealAmount(), } ) return func(t *db.MongoTool) error { // 保存商品购买记录 if err := prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 保存资金流水记录 return txnmod.InsertTransactionLog(t, transactionLog) } } func NewBuyVIP(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet) (func(*db.MongoTool) error, time.Time, error) { var ( //商品购买记录 history = prdcthsomod.ProductHistory{ ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.VIP, SysType: order.DevType, ProductSnapShot: p, IsUpgrade: p.IsUpgrade, CurrentVipName: p.CurrentVipName, CurrentVipPrice: p.CurrentVipPrice, PurchasePrice: p.PurchasePrice, DiscDoc: order.DiscDoc, } sel usermod.UserSelector creditPlan = walletmod.CreditPlan{} vipLevel int payVidDiscount int vipExpireTime time.Time ) // 资金流水记录 txnLogs := []txnmod.TransactionLog{ txnmod.TransactionLog{ UID: order.UID, TranType: txnmod.BuyVIP.Key(), TranTypeInt: int64(txnmod.BuyVIP), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -p.DiscountedPrice, ActualAmount: float64(-p.DiscountedPrice), RealAmount: w.RealAmount(), }, } // 查询用户信息 u, err := usermod.FindUserByUID(order.UID) if err != nil { log.Error(fmt.Sprintf("充值购买会员卡-订单号[%s] 查询用户信息异常 [%v]", order.ID, err)) return nil, vipExpireTime, err } // VIP变更 if p.Duration > 0 { var expire time.Time vipLevel = p.VipLevel payVidDiscount = p.PayVidDiscount // VIP未过期 if u.VipExpireDate.After(time.Now()) { expire = u.VipExpireDate.AddDate(0, 0, p.Duration) if u.VipLevel > p.VipLevel { vipLevel = u.VipLevel } if u.PayVidDiscount > 0 && u.PayVidDiscount < p.PayVidDiscount { payVidDiscount = u.PayVidDiscount } } else { expire = time.Now().AddDate(0, 0, p.Duration) } log.Info(fmt.Sprintf("到期时间:%v", expire)) sel.VipExpireDate = &expire sel.VipLevel = &vipLevel sel.PayVidDiscount = &payVidDiscount vipExpireTime = expire } if p.Duration > 0 && p.Name != "" { sel.VipName = &p.Name } // 增加金币视频免费天数 if p.GoldVideoFreeDay > 0 { var expire time.Time if u.GoldVideoFreeExpire.IsZero() || u.GoldVideoFreeExpire.Before(time.Now()) { expire = time.Now().AddDate(0, 0, p.GoldVideoFreeDay) } else { expire = u.GoldVideoFreeExpire.AddDate(0, 0, p.GoldVideoFreeDay) } sel.GoldVideoFreeExpire = &expire // 金币免费限额(只有当前卡片有金币免费免费时间,才会生效) if p.GoldVideoFreeLimit > u.GoldVideoFreeLimit { sel.GoldVideoFreeLimit = &p.GoldVideoFreeLimit } } if p.BroadcastDays > 0 { expire := time.Time{} if u.BroadcastExpire.IsZero() || u.BroadcastExpire.Before(time.Now()) { expire = time.Now().AddDate(0, 0, p.BroadcastDays) } else { expire = u.BroadcastExpire.AddDate(0, 0, p.BroadcastDays) } sel.BroadcastExpire = &expire } if p.DramaDays > 0 { expire := usermod.RenewDramaExpire(u.DramaExpire, time.Now(), p.DramaDays) sel.DramaExpire = &expire } // 赠送金币 if p.GiveCoin > 0 { creditPlan.Amount = &p.GiveCoin } if p.DownloadCount > 0 { creditPlan.DownloadCount = &p.DownloadCount } if p.LuckyDrawCount > 0 { creditPlan.LotteryTimes = &p.LuckyDrawCount } // 赠送AI免费脱衣次数 if p.AiUndressCount > 0 { aiUndressFreeTimes := int64(p.AiUndressCount) creditPlan.AiUndressFreeTimes = &aiUndressFreeTimes } var co int64 = 1 creditPlan.Consumption = &co //if p.ChatPrice > 0 { // sel.ChatPrice = &p.ChatPrice //} // 改成是 -1免费 0读配置 大于0则为会员私信价格 sel.ChatPrice = &p.ChatPrice return func(t *db.MongoTool) error { // 钱包变更 if p.GiveCoin > 0 || p.GiveFruitCoin > 0 || p.DownloadCount > 0 || p.AiUndressCount > 0 || p.LuckyDrawCount > 0 { w, err := walletmod.Credit(t, creditPlan, order.UID) if err != nil { return err } if p.LuckyDrawCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, LotteryTimes: p.LuckyDrawCount, TranType: txnmod.GiveLotteryTimesCount.Key(), TranTypeInt: int64(txnmod.GiveLotteryTimesCount), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]次抽奖", p.LuckyDrawCount), DiscDoc: u.DiscDoc, SysType: u.SysType, }) } if p.GiveFruitCoin > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, FruitCoin: p.GiveFruitCoin, TranType: txnmod.CurrencyGive.Key(), TranTypeInt: int64(txnmod.CurrencyGive), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]果币", p.GiveFruitCoin), DiscDoc: u.DiscDoc, SysType: u.SysType, FruitCoinBalance: w.FruitCoin, }) } if p.DownloadCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, DownloadCount: p.DownloadCount, TranType: txnmod.GiveDownload.Key(), TranTypeInt: int64(txnmod.GiveDownload), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]次数", p.DownloadCount), DiscDoc: u.DiscDoc, SysType: u.SysType, }) } //插入购买会员卡赠送金币流水 if p.GiveCoin > 0 { giveLog := txnmod.TransactionLog{ UID: order.UID, Amount: p.GiveCoin, ActualAmount: float64(p.GiveCoin), TranType: txnmod.VipCardGive.Key(), TranTypeInt: int64(txnmod.VipCardGive), TransNo: history.ID, Desc: fmt.Sprintf("购买%s-赠送金币[%v个]", p.Name, p.GiveCoin), SysType: u.SysType, RealAmount: w.RealAmount(), } txnLogs = append(txnLogs, giveLog) } // 赠送免费次数 if p.AiUndressCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, Amount: int64(p.AiUndressCount), ActualAmount: float64(p.AiUndressCount), TranType: txnmod.VipCardGiveAiUndressFreeCount.Key(), TranTypeInt: int64(txnmod.VipCardGiveAiUndressFreeCount), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送AI脱衣免费次数[%d次]", p.AiUndressCount), DiscDoc: u.DiscDoc, SysType: u.SysType, RealAmount: w.RealAmount(), }) } } // 用户信息变更 if p.Duration > 0 || p.GoldVideoFreeDay > 0 || p.ChatPrice > 0 || p.BroadcastDays > 0 || p.DramaDays > 0 { if _, err = usermod.UpdateTrans(t, u.UID, sel); err != nil { return err } } // 保存商品购买记录 if err = prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 保存资金流水记录 if err = txnmod.InsertManyTransactionLog(t, txnLogs); err != nil { return err } // 处理购买VIP观影券 if coupons := HandleGoldVideoCoupon(p, order.UID, videocoupon.GoldVideoCouponSourceVIP); len(coupons) > 0 { if err = videocoupon.InsertMany(coupons); err != nil { return err } } common.Go(func() { _ = taskser.CompleteOnceTask(nil, order.UID, oncetaskmod.OnceTaskTypeUserBuyVip) }) return nil }, vipExpireTime, nil } func BuyAdvanceVIP(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet, payMoney int64) (func(*db.MongoTool) error, time.Time, error) { var ( //商品购买记录 history = prdcthsomod.ProductHistory{ ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.AdvanceCard, SysType: order.DevType, ProductSnapShot: p, IsUpgrade: p.IsUpgrade, CurrentVipName: p.CurrentVipName, CurrentVipPrice: p.CurrentVipPrice, PurchasePrice: p.PurchasePrice, DiscDoc: order.DiscDoc, } sel usermod.UserSelector creditPlan = walletmod.CreditPlan{} payVidDiscount int changeStatus int price = p.AdvanceAmount vipExpireTime time.Time ) // 查询用户信息 u, err := usermod.FindUserByUID(order.UID) if err != nil { log.Error(fmt.Sprintf("充值购买会员卡-订单号[%s] 查询用户信息异常 [%v]", order.ID, err)) return nil, vipExpireTime, err } data, err := advanceordermod.IsExist(bson.M{"uid": order.UID, "productID": order.ProductID}) if err != nil { log.Error(fmt.Sprintf("充值购买预售卡-订单号[%s] 查询预售订单信息异常 [%v]", order.ID, err)) return nil, vipExpireTime, err } if data == nil || data.ID.IsZero() { log.Error(fmt.Sprintf("充值购买预售卡-订单号[%s] 查询预售订单信息异常 [%v]", order.ID, err)) return nil, vipExpireTime, errors.New("advance order is null") } // 回调的时候,刚好已经处理完成 if data.Status == advanceordermod.BalanceSUCCESS { // 处理失败,直接返回成功, //common.Go(func() { // OnCallbackFail(payMoney, order, p) //}) return func(tool *db.MongoTool) error { return nil }, vipExpireTime, nil } if data.Status != advanceordermod.AdvanceProcessing && data.Status != advanceordermod.BalanceProcessing { log.Error(fmt.Sprintf("充值购买预售卡-订单号[%s] 查询预售订单信息状态异常 [%v]", order.ID, data.Status)) return nil, vipExpireTime, errors.New("advance order status is err") } var duration = p.Duration var vipLevel = p.VipLevel var fullPrivilege bool var tranType = txnmod.BuyAdvanceVIP if data.Status == advanceordermod.AdvanceProcessing { duration = p.AdvanceDuration // 会员持续时间不能超过预付过期时间 if time.Now().AddDate(0, 0, duration).After(p.AdvanceExpires) { td := p.AdvanceExpires.Sub(time.Now()) duration = int(math.Round(td.Hours() / 24)) if duration < 1 { duration = 1 } } vipLevel = p.AdvanceVipLevel changeStatus = advanceordermod.AdvanceSUCCESS } if data.Status == advanceordermod.BalanceProcessing { changeStatus = advanceordermod.BalanceSUCCESS price = p.BalanceAmount fullPrivilege = true tranType = txnmod.BuyBalanceVIP } // 校验预售金额 status, _, diff := CheckAdvanceMoney(payMoney, price, order, p) if !status { return func(tool *db.MongoTool) error { return nil }, vipExpireTime, nil } // 资金流水记录 txnLogs := []txnmod.TransactionLog{ { UID: order.UID, TranType: tranType.Key(), TranTypeInt: int64(tranType), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -price, ActualAmount: float64(-price), RealAmount: w.RealAmount(), }, } // VIP变更 if duration > 0 { var expire time.Time payVidDiscount = p.PayVidDiscount // VIP未过期 if u.VipExpireDate.After(time.Now()) { if changeStatus == advanceordermod.BalanceSUCCESS { expire = u.VipExpireDate.AddDate(0, 0, duration) } if changeStatus == advanceordermod.AdvanceSUCCESS { expire = time.Now().AddDate(0, 0, duration) } if u.VipLevel > p.VipLevel { vipLevel = u.VipLevel } if u.PayVidDiscount > 0 && u.PayVidDiscount < p.PayVidDiscount { payVidDiscount = u.PayVidDiscount } } else { expire = time.Now().AddDate(0, 0, duration) } log.Info(fmt.Sprintf("到期时间:%v", expire)) sel.VipExpireDate = &expire sel.VipLevel = &vipLevel sel.PayVidDiscount = &payVidDiscount vipExpireTime = expire } if p.AllGoldVideoFree && fullPrivilege { free := true sel.AllGoldVideoFree = &free } if p.Name != "" { sel.VipName = &p.Name } // 增加金币视频免费天数 if p.GoldVideoFreeDay > 0 && fullPrivilege { var expire time.Time if u.GoldVideoFreeExpire.IsZero() || u.GoldVideoFreeExpire.Before(time.Now()) { if changeStatus == advanceordermod.BalanceSUCCESS { expire = time.Now().AddDate(0, 0, p.GoldVideoFreeDay) } if changeStatus == advanceordermod.AdvanceSUCCESS { expire = p.EndTime } } else { if changeStatus == advanceordermod.BalanceSUCCESS { expire = u.GoldVideoFreeExpire.AddDate(0, 0, p.GoldVideoFreeDay) } if changeStatus == advanceordermod.AdvanceSUCCESS { expire = p.EndTime } } sel.GoldVideoFreeExpire = &expire // 金币免费限额(只有当前卡片有金币免费免费时间,才会生效) if p.GoldVideoFreeLimit > u.GoldVideoFreeLimit { sel.GoldVideoFreeLimit = &p.GoldVideoFreeLimit } } if p.BroadcastDays > 0 { expire := time.Time{} if u.BroadcastExpire.IsZero() || u.BroadcastExpire.Before(time.Now()) { expire = time.Now().AddDate(0, 0, p.BroadcastDays) } else { expire = u.BroadcastExpire.AddDate(0, 0, p.BroadcastDays) } sel.BroadcastExpire = &expire } if p.DramaDays > 0 && fullPrivilege { expire := usermod.RenewDramaExpire(u.DramaExpire, time.Now(), p.DramaDays) sel.DramaExpire = &expire } // 赠送金币 if p.GiveCoin > 0 { creditPlan.Amount = &p.GiveCoin } if p.DownloadCount > 0 && fullPrivilege { creditPlan.DownloadCount = &p.DownloadCount } // 赠送AI免费脱衣次数 if p.AiUndressCount > 0 && fullPrivilege { aiUndressFreeTimes := int64(p.AiUndressCount) creditPlan.AiUndressFreeTimes = &aiUndressFreeTimes } if p.LuckyDrawCount > 0 && fullPrivilege { creditPlan.LotteryTimes = &p.LuckyDrawCount } var co int64 = 1 creditPlan.Consumption = &co //if p.ChatPrice > 0 { // sel.ChatPrice = &p.ChatPrice //} sel.ChatPrice = &p.ChatPrice return func(t *db.MongoTool) error { if diff > 0 { gold := diff / 10 crPlan := walletmod.CreditPlan{} crPlan.Amount = &gold w, err := walletmod.Credit(t, crPlan, order.UID) if err != nil { return err } txnLogs = append(txnLogs, txnmod.TransactionLog{ TransNo: order.ID, UID: order.UID, Amount: diff, ActualAmount: float64(diff), TranType: txnmod.OfficialRech.Key(), TranTypeInt: int64(txnmod.OfficialRech), ChannelType: order.RechargeType, Desc: fmt.Sprintf("官方充值购买[%s],超额转化为[%d]金币", p.Name, diff/10), DiscDoc: order.DiscDoc, SysType: order.DevType, RealAmount: w.RealAmount(), }) } if changeStatus == advanceordermod.BalanceSUCCESS { // 钱包变更 if p.GiveCoin > 0 || p.GiveFruitCoin > 0 || p.DownloadCount > 0 || p.AiUndressCount > 0 || p.LuckyDrawCount > 0 { w, err := walletmod.Credit(t, creditPlan, order.UID) if err != nil { return err } if p.GiveFruitCoin > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, FruitCoin: p.GiveFruitCoin, TranType: txnmod.CurrencyGive.Key(), TranTypeInt: int64(txnmod.CurrencyGive), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]果币", p.GiveFruitCoin), DiscDoc: u.DiscDoc, SysType: u.SysType, FruitCoinBalance: w.FruitCoin, }) } if p.DownloadCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, DownloadCount: p.DownloadCount, TranType: txnmod.GiveDownload.Key(), TranTypeInt: int64(txnmod.GiveDownload), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]次数", p.DownloadCount), DiscDoc: u.DiscDoc, SysType: u.SysType, }) } //插入购买会员卡赠送金币流水 if p.GiveCoin > 0 { giveLog := txnmod.TransactionLog{ UID: order.UID, Amount: p.GiveCoin, ActualAmount: float64(p.GiveCoin), TranType: txnmod.VipCardGive.Key(), TranTypeInt: int64(txnmod.VipCardGive), TransNo: history.ID, Desc: fmt.Sprintf("购买%s-赠送金币[%v个]", p.Name, p.GiveCoin), SysType: u.SysType, RealAmount: w.RealAmount(), } txnLogs = append(txnLogs, giveLog) } // 赠送免费次数 if p.AiUndressCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, Amount: int64(p.AiUndressCount), ActualAmount: float64(p.AiUndressCount), TranType: txnmod.VipCardGiveAiUndressFreeCount.Key(), TranTypeInt: int64(txnmod.VipCardGiveAiUndressFreeCount), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送AI脱衣免费次数[%d次]", p.AiUndressCount), DiscDoc: u.DiscDoc, SysType: u.SysType, RealAmount: w.RealAmount(), }) } if p.LuckyDrawCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, LotteryTimes: p.LuckyDrawCount, TranType: txnmod.GiveLotteryTimesCount.Key(), TranTypeInt: int64(txnmod.GiveLotteryTimesCount), TransNo: history.ID, Desc: fmt.Sprintf("预售卡购买-%v", p.Name) + fmt.Sprintf("-赠送[%d]次数", p.LuckyDrawCount), DiscDoc: u.DiscDoc, SysType: u.SysType, }) } } } // 修改预付订单状态 err := advanceordermod.Update(t, data.ID, bson.M{"status": changeStatus}) if err != nil { return err } // 用户信息变更 if p.Duration > 0 || p.GoldVideoFreeDay > 0 || p.ChatPrice > 0 || p.BroadcastDays > 0 || (p.DramaDays > 0 && fullPrivilege) { if _, err = usermod.UpdateTrans(t, u.UID, sel); err != nil { return err } } history.AdvanceOrderStatus = changeStatus // 保存商品购买记录 if err = prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 保存资金流水记录 if err = txnmod.InsertManyTransactionLog(t, txnLogs); err != nil { return err } // 处理购买VIP观影券 if coupons := HandleGoldVideoCoupon(p, order.UID, videocoupon.GoldVideoCouponSourceVIP); len(coupons) > 0 { if err = videocoupon.InsertMany(coupons); err != nil { return err } } common.Go(func() { _ = taskser.CompleteOnceTask(nil, order.UID, oncetaskmod.OnceTaskTypeUserBuyVip) }) return nil }, vipExpireTime, nil } func OnCallbackFail(payMoney int64, order rchgordmod.RechargeOrder, p *productmod.Product) (err error) { creditPlan := walletmod.CreditPlan{Consumption: &payMoney} gold := payMoney / 10 creditPlan.Amount = &gold if err = appg.VideoDB.Trans(func(t *db.MongoTool) error { w, err := walletmod.Credit(t, creditPlan, order.UID) if err != nil { return err } //插入一条支出流水 if err = txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{ TransNo: order.ID, UID: order.UID, Amount: gold, ActualAmount: float64(gold), TranType: txnmod.OfficialRech.Key(), TranTypeInt: int64(txnmod.OfficialRech), ChannelType: order.RechargeType, Desc: fmt.Sprintf("官方充值购买[%s]实际支付[%d]元;全额转化为[%d]金币", p.Name, payMoney/100, payMoney/10), DiscDoc: order.DiscDoc, SysType: order.DevType, RealAmount: w.RealAmount(), }); err != nil { log.Info(fmt.Sprintf("rechargeSer checkAdvanceMoney CallbackAddCoins Trans fail error:%v, order:%+v", err, order)) return err } return nil }); err != nil { log.Warn(fmt.Sprintf("productser buyVIP checkAdvanceMoney Transaction err %s", err.Error())) return err } return nil } func CheckAdvanceMoney(payMoney int64, price int64, order rchgordmod.RechargeOrder, p *productmod.Product) (status bool, cs int, diff int64) { var ( checkStatus bool diffAmt = payMoney - price*10 creditPlan = walletmod.CreditPlan{Consumption: &payMoney} gold = payMoney / 10 csm int ) if diffAmt >= -10 && diffAmt < 0 { checkStatus = true return checkStatus, csm, 0 } if diffAmt == 0 { checkStatus = true return checkStatus, csm, diffAmt } // 超额支付转化金币 if diffAmt > 0 { checkStatus = true return checkStatus, csm, diffAmt } // 小于全额转化金币 if diffAmt < -10 { creditPlan.Amount = &gold csm = rchgordmod.ChanShareCoin if err := appg.VideoDB.Trans(func(t *db.MongoTool) error { w, err := walletmod.Credit(t, creditPlan, order.UID) if err != nil { return err } //插入一条支出流水 if err = txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{ TransNo: order.ID, UID: order.UID, Amount: gold, ActualAmount: float64(gold), TranType: txnmod.OfficialRech.Key(), TranTypeInt: int64(txnmod.OfficialRech), ChannelType: order.RechargeType, Desc: fmt.Sprintf("官方充值购买[%s]实际支付[%d]元;全额转化为[%d]金币", p.Name, payMoney/100, payMoney/10), DiscDoc: order.DiscDoc, SysType: order.DevType, RealAmount: w.RealAmount(), }); err != nil { log.Info(fmt.Sprintf("rechargeSer checkAdvanceMoney CallbackAddCoins Trans fail error:%v, order:%+v", err, order)) return err } return nil }); err != nil { log.Warn(fmt.Sprintf("productser buyVIP checkAdvanceMoney Transaction err %s", err.Error())) return checkStatus, csm, diffAmt } } return checkStatus, csm, diffAmt } func BuyGameAdvanceVIP(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet) (func(*db.MongoTool) error, time.Time, error) { var ( // 商品购买记录 history = prdcthsomod.ProductHistory{ ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.GameAdvanceCard, DiscDoc: order.DiscDoc, SysType: order.DevType, ProductSnapShot: p, } sel usermod.UserSelector creditPlan = walletmod.CreditPlan{} vipLevel int payVidDiscount int vipExpireTime time.Time ) // 获取三方游戏码 gameCode, err := game.GainTripartiteGameCode(order.UID) if err != nil { log.Error(fmt.Sprintf("充值购买游戏预售-订单号[%s] 获取游戏码信息异常 [%v]", order.ID, err)) return nil, vipExpireTime, err } history.GameCode = gameCode // 查询用户信息 u, err := usermod.FindUserByUID(order.UID) if err != nil { log.Error(fmt.Sprintf("充值购买会员卡-订单号[%s] 查询用户信息异常 [%v]", order.ID, err)) return nil, vipExpireTime, err } // 资金流水记录 txnLogs := []txnmod.TransactionLog{ { UID: order.UID, TranType: txnmod.BuyGameAdvanceVIP.Key(), TranTypeInt: int64(txnmod.BuyGameAdvanceVIP), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -p.DiscountedPrice, ActualAmount: float64(-p.DiscountedPrice), RealAmount: w.RealAmount(), }, } goodsList := make([]backpackmod.Backpack, 1) now := time.Now() goodsList[0] = backpackmod.Backpack{ UID: order.UID, GoodsName: p.Name, GoodsType: backpackmod.GameCode, GoodsValue: p.DiscountedPrice, GoodsOrigin: fmt.Sprintf("充值购买"), GoodsDesc: gameCode, Status: backpackmod.Unused, ExpiredTime: now.AddDate(0, 0, int(p.Duration)), CreateTime: now, } // 购买游戏是否赠送VIP && VIP变更 if p.SendGame && p.Duration > 0 { var expire time.Time vipLevel = p.VipLevel payVidDiscount = p.PayVidDiscount // VIP未过期 if u.VipExpireDate.After(time.Now()) { expire = u.VipExpireDate.AddDate(0, 0, p.Duration) if u.VipLevel > p.VipLevel { vipLevel = u.VipLevel } if u.PayVidDiscount > 0 && u.PayVidDiscount < p.PayVidDiscount { payVidDiscount = u.PayVidDiscount } } else { expire = time.Now().AddDate(0, 0, p.Duration) } log.Info(fmt.Sprintf("到期时间:%v", expire)) sel.VipExpireDate = &expire sel.VipLevel = &vipLevel sel.PayVidDiscount = &payVidDiscount vipExpireTime = expire } if p.AllGoldVideoFree { free := true sel.AllGoldVideoFree = &free } if p.SendGame && p.Name != "" { sel.VipName = &p.Name } // 增加金币视频免费天数 if p.GoldVideoFreeDay > 0 { var expire time.Time if u.GoldVideoFreeExpire.IsZero() || u.GoldVideoFreeExpire.Before(time.Now()) { expire = time.Now().AddDate(0, 0, p.GoldVideoFreeDay) } else { expire = u.GoldVideoFreeExpire.AddDate(0, 0, p.GoldVideoFreeDay) } sel.GoldVideoFreeExpire = &expire } // 赠送金币 if p.GiveCoin > 0 { creditPlan.Amount = &p.GiveCoin } if p.DownloadCount > 0 { creditPlan.DownloadCount = &p.DownloadCount } // 赠送AI免费脱衣次数 if p.AiUndressCount > 0 { aiUndressFreeTimes := int64(p.AiUndressCount) creditPlan.AiUndressFreeTimes = &aiUndressFreeTimes } var co int64 = 1 creditPlan.Consumption = &co if p.ChatPrice > 0 { sel.ChatPrice = &p.ChatPrice } return func(t *db.MongoTool) error { // 钱包变更 if p.GiveCoin > 0 || p.GiveFruitCoin > 0 || p.DownloadCount > 0 || p.AiUndressCount > 0 { w, err := walletmod.Credit(t, creditPlan, order.UID) if err != nil { return err } if p.GiveFruitCoin > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, FruitCoin: p.GiveFruitCoin, TranType: txnmod.CurrencyGive.Key(), TranTypeInt: int64(txnmod.CurrencyGive), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]果币", p.GiveFruitCoin), DiscDoc: u.DiscDoc, SysType: u.SysType, FruitCoinBalance: w.FruitCoin, }) } if p.DownloadCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, DownloadCount: p.DownloadCount, TranType: txnmod.GiveDownload.Key(), TranTypeInt: int64(txnmod.GiveDownload), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]次数", p.DownloadCount), DiscDoc: u.DiscDoc, SysType: u.SysType, }) } //插入购买会员卡赠送金币流水 if p.GiveCoin > 0 { giveLog := txnmod.TransactionLog{ UID: order.UID, Amount: p.GiveCoin, ActualAmount: float64(p.GiveCoin), TranType: txnmod.VipCardGive.Key(), TranTypeInt: int64(txnmod.VipCardGive), TransNo: history.ID, Desc: fmt.Sprintf("购买%s-赠送金币[%v个]", p.Name, p.GiveCoin), SysType: u.SysType, RealAmount: w.RealAmount(), } txnLogs = append(txnLogs, giveLog) } // 赠送免费次数 if p.AiUndressCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, Amount: int64(p.AiUndressCount), ActualAmount: float64(p.AiUndressCount), TranType: txnmod.VipCardGiveAiUndressFreeCount.Key(), TranTypeInt: int64(txnmod.VipCardGiveAiUndressFreeCount), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送AI脱衣免费次数[%d次]", p.AiUndressCount), DiscDoc: u.DiscDoc, SysType: u.SysType, RealAmount: w.RealAmount(), }) } } // 用户信息变更 if p.SendGame && (p.Duration > 0 || p.GoldVideoFreeDay > 0 || p.ChatPrice > 0) { if _, err = usermod.UpdateTrans(t, u.UID, sel); err != nil { return err } } // 保存用户游戏码 err := backpackmod.AddGoodsMany(t, order.UID, goodsList) if err != nil { return err } // 保存商品购买记录 if err = prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 保存资金流水记录 if err = txnmod.InsertManyTransactionLog(t, txnLogs); err != nil { return err } return nil }, vipExpireTime, nil } func NewBuyVideoFreeCard(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet) (func(*db.MongoTool) error, error) { var ( expiration time.Time now = time.Now() history = prdcthsomod.ProductHistory{ //插入商品购买记录 ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.VideoFreeCard, DiscDoc: order.DiscDoc, SysType: order.DevType, ProductSnapShot: p, } transactionLog = &txnmod.TransactionLog{ UID: order.UID, TranType: txnmod.VideoFreeCard.Key(), TranTypeInt: int64(txnmod.VideoFreeCard), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -p.DiscountedPrice, ActualAmount: float64(-p.DiscountedPrice), RealAmount: w.RealAmount(), } ) u, err := usermod.FindUserByUID(order.UID) if err != nil { return nil, err } if u.VideoFreeExpiration != nil && u.VideoFreeExpiration.After(now) { expiration = u.VideoFreeExpiration.AddDate(0, 0, p.Duration) } else { expiration = now.AddDate(0, 0, p.Duration) } return func(t *db.MongoTool) error { // 保存资金流水记录 if err = txnmod.InsertTransactionLog(t, transactionLog); err != nil { return err } // 保存商品购买记录 if err = prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 用户楼凤全免信息更新 _, err = usermod.UpdateTrans(t, order.UID, usermod.UserSelector{ VideoFreeExpiration: &expiration, }) return err }, err } func NewBuyVideoDiscountCard(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet) ( func(*db.MongoTool) error, error) { var ( videoDiscount int expiration time.Time now = time.Now() history = prdcthsomod.ProductHistory{ //插入商品购买记录 ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.VideoDiscount, DiscDoc: order.DiscDoc, SysType: order.DevType, ProductSnapShot: p, } transactionLog = &txnmod.TransactionLog{ UID: order.UID, TranType: txnmod.VideoDiscount.Key(), TranTypeInt: int64(txnmod.VideoDiscount), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -p.DiscountedPrice, ActualAmount: float64(-p.DiscountedPrice), RealAmount: w.RealAmount(), } ) videoDiscountLog, err := videodiscountmod.GetByUID(order.UID) if err != nil { return nil, err } if videoDiscountLog.Expiration.After(now) { if p.VideoDiscount > videoDiscountLog.VideoDiscount { videoDiscount = p.VideoDiscount } else { videoDiscount = videoDiscountLog.VideoDiscount } expiration = videoDiscountLog.Expiration.AddDate(0, 0, p.Duration) } else { videoDiscount = p.VideoDiscount expiration = now.AddDate(0, 0, p.Duration) } setLd := videodiscountmod.EditSelector{ UID: &order.UID, Expiration: &expiration, VideoDiscount: &videoDiscount, } return func(t *db.MongoTool) error { // 保存资金流水记录 if err = txnmod.InsertTransactionLog(t, transactionLog); err != nil { return err } // 保存商品购买记录 if err = prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 楼凤折扣变更 return videodiscountmod.Upsert(t, &setLd) }, nil } func NewBuyCoinMonthCard(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet) (func(*db.MongoTool) error, error) { var ( creditPlan = walletmod.CreditPlan{} sel usermod.UserSelector vipLevel int payVidDiscount int history = prdcthsomod.ProductHistory{ //插入商品购买记录 ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.CoinMonthCard, DiscDoc: order.DiscDoc, SysType: order.DevType, ProductSnapShot: p, } transactionLog = &txnmod.TransactionLog{ UID: order.UID, TranType: txnmod.CoinMonthCard.Key(), TranTypeInt: int64(txnmod.CoinMonthCard), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -p.DiscountedPrice, ActualAmount: float64(-p.DiscountedPrice), RealAmount: w.RealAmount(), } ) // 查询用户信息 u, err := usermod.FindUserByUID(order.UID) if err != nil { log.Error(fmt.Sprintf("充值购买会员卡-订单号[%s] 查询用户信息异常 [%v]", order.ID, err)) return nil, err } //vip变更 if p.Duration > 0 { var expire time.Time vipLevel = p.VipLevel payVidDiscount = p.PayVidDiscount // VIP未过期 if u.CoinMouthExpireDate.After(time.Now()) { expire = u.CoinMouthExpireDate.AddDate(0, 0, p.Duration) if u.VipLevel > p.VipLevel { vipLevel = u.VipLevel } if u.PayVidDiscount > 0 && u.PayVidDiscount < p.PayVidDiscount { payVidDiscount = u.PayVidDiscount } } else { expire = time.Now().AddDate(0, 0, p.Duration) } log.Info(fmt.Sprintf("到期时间:%v", expire)) sel.CoinMouthExpireDate = &expire sel.VipLevel = &vipLevel sel.PayVidDiscount = &payVidDiscount } //赠送金币----首次购买赠送金币 if p.GiveCoin > 0 { creditPlan.Amount = &p.GiveCoin } return func(t *db.MongoTool) error { //钱包变更 if p.GiveCoin > 0 || p.GiveFruitCoin > 0 { _, err = walletmod.Credit(t, creditPlan, order.UID) if err != nil { return err } } fmt.Println("----------------p", p, "user", sel) // 用户信息变更 if p.Duration > 0 || p.GoldVideoFreeDay > 0 { if _, err = usermod.UpdateTrans(t, u.UID, sel); err != nil { return err } } // 保存商品购买记录 if err = prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 保存资金流水记录 return txnmod.InsertTransactionLog(t, transactionLog) }, nil } func NewBuyWhoringCard(order rchgordmod.RechargeOrder, p *productmod.Product, desc string, w *walletmod.Wallet) (func(*db.MongoTool) error, error) { var ( // 商品购买记录 history = prdcthsomod.ProductHistory{ ID: primitive.NewObjectID(), UID: order.UID, ProductID: p.ID, Name: p.Name, Amount: p.DiscountedPrice, ProductType: prdcthsomod.WhoringCard, DiscDoc: order.DiscDoc, SysType: order.DevType, ProductSnapShot: p, } sel usermod.UserSelector creditPlan = walletmod.CreditPlan{} vipLevel int payVidDiscount int record signrecordmod.SignRecord ) creditPlan.Consumption = &order.PayMoney // 资金流水记录 txnLogs := []txnmod.TransactionLog{ { UID: order.UID, TranType: txnmod.BuyWhoringCard.Key(), TranTypeInt: int64(txnmod.BuyWhoringCard), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name), DiscDoc: order.DiscDoc, SysType: order.DevType, CurrencyType: txnmod.CurrencyTypeCash, Amount: -p.DiscountedPrice, ActualAmount: float64(-p.DiscountedPrice), RealAmount: w.RealAmount(), }, } // 查询用户信息 u, err := usermod.FindUserByUID(order.UID) if err != nil { log.Error(fmt.Sprintf("充值购买比嫖卡-订单号[%s] 查询用户信息异常 [%v]", order.ID, err)) return nil, err } // VIP变更 if p.Duration > 0 { var expire time.Time vipLevel = p.VipLevel payVidDiscount = p.PayVidDiscount // VIP未过期 if u.VipExpireDate.After(time.Now()) { expire = u.VipExpireDate.AddDate(0, 0, p.Duration) if u.VipLevel > p.VipLevel { vipLevel = u.VipLevel } if u.PayVidDiscount > 0 && u.PayVidDiscount < p.PayVidDiscount { payVidDiscount = u.PayVidDiscount } } else { expire = time.Now().AddDate(0, 0, p.Duration) } log.Info(fmt.Sprintf("到期时间:%v", expire)) sel.VipExpireDate = &expire sel.VipLevel = &vipLevel sel.PayVidDiscount = &payVidDiscount } if p.Duration > 0 && p.Name != "" { sel.VipName = &p.Name } if p.SignDays > 0 { var buyStatus = true sel.HasWhoringCard = &buyStatus recTime := []signrecordmod.Record{} // 获取打卡记录 nowTime := time.Now() record.UID = order.UID record.PID = p.ID record.UpdateTime = nowTime record.TotalDays = int64(p.SignDays) record.CurrentSignDays = 1 record.ForgetSignDays = 0 record.RenewalSignDays = 0 record.SignTime = nowTime record.EndTime = nowTime.AddDate(0, 0, int(p.SignDays)) record.CreatedAt = nowTime record.RecordTime = recTime } // 增加金币视频免费天数 if p.GoldVideoFreeDay > 0 { var expire time.Time if u.GoldVideoFreeExpire.IsZero() || u.GoldVideoFreeExpire.Before(time.Now()) { expire = time.Now().AddDate(0, 0, p.GoldVideoFreeDay) } else { expire = u.GoldVideoFreeExpire.AddDate(0, 0, p.GoldVideoFreeDay) } sel.GoldVideoFreeExpire = &expire } // 赠送金币 if p.GiveCoin > 0 { creditPlan.Amount = &p.GiveCoin } if p.DownloadCount > 0 { creditPlan.DownloadCount = &p.DownloadCount } // 赠送AI免费脱衣次数 if p.AiUndressCount > 0 { aiUndressFreeTimes := int64(p.AiUndressCount) creditPlan.AiUndressFreeTimes = &aiUndressFreeTimes } if p.ChatPrice != 0 { sel.ChatPrice = &p.ChatPrice } // 处理购买VIP观影券 coupons := HandleGoldVideoCoupon(p, order.UID, videocoupon.GoldVideoCouponSourceVIP) return func(t *db.MongoTool) error { // 钱包变更 if p.GiveCoin > 0 || p.GiveFruitCoin > 0 || p.DownloadCount > 0 || p.AiUndressCount > 0 { w, err := walletmod.Credit(t, creditPlan, order.UID) if err != nil { return err } if p.GiveFruitCoin > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, FruitCoin: p.GiveFruitCoin, TranType: txnmod.CurrencyGive.Key(), TranTypeInt: int64(txnmod.CurrencyGive), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]果币", p.GiveFruitCoin), DiscDoc: u.DiscDoc, SysType: u.SysType, FruitCoinBalance: w.FruitCoin, }) } if p.DownloadCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, DownloadCount: p.DownloadCount, TranType: txnmod.GiveDownload.Key(), TranTypeInt: int64(txnmod.GiveDownload), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送[%d]次数", p.DownloadCount), DiscDoc: u.DiscDoc, SysType: u.SysType, }) } // 赠送免费次数 if p.AiUndressCount > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, Amount: int64(p.AiUndressCount), ActualAmount: float64(p.AiUndressCount), TranType: txnmod.VipCardGiveAiUndressFreeCount.Key(), TranTypeInt: int64(txnmod.VipCardGiveAiUndressFreeCount), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送AI脱衣免费次数[%d次]", p.AiUndressCount), DiscDoc: u.DiscDoc, SysType: u.SysType, RealAmount: w.RealAmount(), }) } // 赠送金币 if p.GiveCoin > 0 { txnLogs = append(txnLogs, txnmod.TransactionLog{ UID: order.UID, Amount: int64(p.GiveCoin), ActualAmount: float64(p.AiUndressCount), TranType: txnmod.VipCardGive.Key(), TranTypeInt: int64(txnmod.VipCardGive), TransNo: history.ID, Desc: fmt.Sprintf(desc, p.Name) + fmt.Sprintf("-赠送金币[%d个]", p.GiveCoin), DiscDoc: u.DiscDoc, SysType: u.SysType, RealAmount: w.RealAmount(), }) } } // 用户信息变更 if p.Duration > 0 || p.GoldVideoFreeDay > 0 || p.ChatPrice != 0 || p.SignDays > 0 { if _, err = usermod.UpdateTrans(t, u.UID, sel); err != nil { return err } } // 保存商品购买记录 if err = prdcthsomod.InsertProductHistory(t, &history); err != nil { return err } // 保存资金流水记录 if err = txnmod.InsertManyTransactionLog(t, txnLogs); err != nil { return err } // 赠送观影券 if len(coupons) > 0 { if err := videocoupon.InsertMany(coupons); err != nil { return err } } // 打卡记录 _, err := signrecordmod.InsertOne(t, record) if err != nil { return err } return nil }, nil }