package couponser import ( "91porn-server/app/appg" "91porn-server/common" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/common/stderr" "91porn-server/models/commod" "91porn-server/models/v/advanceordermod" "91porn-server/models/v/backpackmod" "91porn-server/models/v/coupon_record_mod" "91porn-server/models/v/prize_record_mod" "91porn-server/models/v/productmod" "91porn-server/models/v/txnmod" "91porn-server/models/v/usermod" "91porn-server/models/v/walletmod" "91porn-server/web/service/userser" "bytes" "crypto/aes" "crypto/cipher" "encoding/base64" "encoding/json" "fmt" "time" "github.com/gin-gonic/gin" "github.com/shopspring/decimal" "go.mongodb.org/mongo-driver/bson/primitive" ) // List 优惠券列表 func List(uid uint64, in *coupon_record_mod.AppListReq) (*coupon_record_mod.QueryAllRes, error) { var out = &coupon_record_mod.QueryAllRes{} count, err := coupon_record_mod.QueryAllCount(in.Filter(uid)) if err != nil { return nil, err } if count == 0 { out.List = []*coupon_record_mod.AppCouponRecordRes{} out.Total = 0 return out, nil } out.Total = count out.List, err = coupon_record_mod.QueryAllList(in.Filter(uid), in.Options()) if err != nil { log.Error(fmt.Sprintf("coupon_record_mod.QueryAllList err:%v", err), log.Any("uid", uid), log.Any("params", in)) return nil, stderr.ErrDbQueryError } return out, nil } // Upload 上传优惠券列表 func Upload(uid uint64, in *prize_record_mod.AppUploadReq) error { var ( prizes []*prize_record_mod.Prize transactionLogs []txnmod.TransactionLog ) // 获取用户信息 u, err := usermod.FindUserByUID(uid) if err != nil { return stderr.ErrDbQueryError } if u == nil { return stderr.UserIsNotExists } prizes = in.Prizes if len(prizes) == 0 { return stderr.PrizeRecordNoExists } // 优先使用预售卡权益免费次数 hasPrivilege, advance := advanceordermod.GetUserValidOrder(uid) if hasPrivilege { // 获取可用免费次数 validCount := advance.PrepaidPrivilege.LuckyDrawLimitPerDay - advance.TodayUse.LuckyDrawCount if validCount >= in.Count { // 扣除免费次数 debitPlan := advanceordermod.DebitPlan{} debitPlan.LuckyDrawCount = &in.Count if err := advanceordermod.Debit(nil, uid, debitPlan); err != nil { return stderr.ErrDbUpdateError } in.Count = 0 } else if validCount > 0 { // 扣除免费次数 debitPlan := advanceordermod.DebitPlan{} debitPlan.LuckyDrawCount = &validCount if err := advanceordermod.Debit(nil, uid, debitPlan); err != nil { return stderr.ErrDbUpdateError } in.Count -= validCount } } wal, err := walletmod.GetWallet(uid) if err != nil { return stderr.ErrDbQueryError } totalMoney := wal.Amount + wal.Income if totalMoney <= 0 && wal.LotteryTimes < in.Count { log.Warn(fmt.Sprintf("用户ID:%d;用户余额不足,当前剩余次数:%v;抽奖扣除次数:%v", uid, wal.LotteryTimes, in.Count)) return stderr.InsufficientBalance } if in.Gold > 0 && in.Gold > totalMoney { log.Warn(fmt.Sprintf("用户ID:%d;用户余额不足,当前剩余总余额:%v;抽奖扣除金额:%v", uid, totalMoney, in.Gold)) return stderr.InsufficientBalance } if wal.LotteryTimes < in.Count && in.Gold == 0 { log.Warn(fmt.Sprintf("用户ID:%d;用户余额不足,当前剩余次数:%v;抽奖扣除次数:%v", uid, wal.LotteryTimes, in.Count)) return stderr.InsufficientBalance } if in.Count != 0 || in.Gold != 0 { var creditPlan = walletmod.CreditPlan{} // 处理扣钱 if in.Count > 0 && in.Gold == 0 { inc := -in.Count creditPlan.LotteryTimes = &inc } if in.Gold != 0 { desc := -in.Gold if wal.Amount < in.Gold { descAmt := -wal.Amount creditPlan.Amount = &descAmt descInc := -(in.Gold - wal.Amount) creditPlan.Income = &descInc log.Info(fmt.Sprintf("用户ID:%d;抽奖进入这里扣出income:%v;amount:%v", uid, descInc, descAmt)) } else if wal.Amount >= in.Gold { creditPlan.Amount = &desc log.Info(fmt.Sprintf("用户ID:%d;抽奖进入这里扣出;amount:%v", uid, in.Gold)) } } if err = appg.VideoDB.Trans(func(t *db.MongoTool) error { // 增加金币与总充值金额 wal, err = walletmod.DescCredit(t, creditPlan, uid) if err != nil { return err } if in.Gold > 0 { out := txnmod.TransactionLog{ TransNo: primitive.NewObjectID(), UID: uid, Amount: in.Gold, ActualAmount: -float64(in.Gold), TranType: txnmod.RaffleDeduction.Key(), TranTypeInt: int64(txnmod.RaffleDeduction), Desc: fmt.Sprintf("%s-金币[%d个]", txnmod.RaffleDeduction.Key(), in.Gold), RealAmount: wal.RealAmount(), CreatedAt: time.Now(), } transactionLogs = append(transactionLogs, out) } if len(transactionLogs) > 0 { err = txnmod.InsertManyTransactionLog(t, transactionLogs) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;奖品派发资金流水日志插入异常:%v", uid, err)) return err } } return nil }); err != nil { return stderr.ErrDbTransError } } common.Go(func() { _ = HandlePrize(uid, in, u, wal) }) log.Info(fmt.Sprintf("用户ID:%d;业务处理完成", uid)) return nil } func HandlePrize(uid uint64, in *prize_record_mod.AppUploadReq, u *usermod.User, wal *walletmod.Wallet) error { var ( prizes []*prize_record_mod.Prize transactionLogs []txnmod.TransactionLog couponRecords []coupon_record_mod.CouponRecord goodsList []backpackmod.Backpack totalInc int64 totalAIUndressInc int64 err error ) prizes = in.Prizes vipStatus := false // 处理同类型 for _, p := range prizes { log.Info(fmt.Sprintf("--------------开始任务:%+v", p)) if p.PrizeType == prize_record_mod.PrizeTypeVIPCard { id, _ := primitive.ObjectIDFromHex(p.Param1) // 查询会员卡详情 productDetail, err := productmod.FindProduct(id, "android") if err != nil { continue } vipExpire, vipLevel, payVidDiscount := prize_record_mod.CheckVipRenew(u, productDetail) u.VipExpireDate = vipExpire u.VipLevel = vipLevel u.PayVidDiscount = payVidDiscount vipStatus = true } if p.PrizeType == prize_record_mod.PrizeTypeVIP { if u.VipLevel == 0 { u.VipLevel = 1 } vipExpire, vipLevel := userser.CheckVipRenew(u, int(p.Price), u.VipLevel) u.VipExpireDate = vipExpire u.VipLevel = vipLevel vipStatus = true } if p.PrizeType == prize_record_mod.PrizeTypeGold { totalInc += p.Price transactionLogs = append(transactionLogs, txnmod.TransactionLog{ TransNo: primitive.NewObjectID(), UID: u.UID, Amount: p.Price, ActualAmount: float64(p.Price), TranType: txnmod.PrizeRecord.Key(), TranTypeInt: int64(txnmod.PrizeRecord), Desc: fmt.Sprintf("%s-金币[%d个]", txnmod.PrizeRecord.Key(), p.Price), RealAmount: wal.RealAmount().Add(decimal.NewFromInt(totalInc)), }) } if p.PrizeType == prize_record_mod.PrizeTypeGoldCoinBonus { cId := prize_record_mod.HandleCId(p.ID) // 获取观影券是否存在 c, err := coupon_record_mod.FindOneByCId(cId) if err != nil { return err } if !c.ID.IsZero() { return stderr.New(400, "coupon_record is exist") } // 保存用户优惠券 now := time.Now() newCo := coupon_record_mod.CouponRecord{ CID: cId, PID: p.ID, UID: u.UID, UserName: u.Name, Name: p.Name, Count: p.Count, Price: p.Price, Type: coupon_record_mod.PrizeTypeGoldCoinBonus, Used: false, IsDelete: false, ExpireTime: now.Add(time.Hour * 24 * time.Duration(p.ValidDate)), } couponRecords = append(couponRecords, newCo) } // AI脱衣 if p.PrizeType == prize_record_mod.PrizeTypeAiUndress { totalAIUndressInc += p.Price aiLog := txnmod.TransactionLog{ UID: uid, Amount: p.Price, ActualAmount: float64(p.Price), TranType: txnmod.PrizeRecord.Key(), TranTypeInt: int64(txnmod.PrizeRecord), TransNo: primitive.NewObjectID(), Desc: fmt.Sprintf("%s-赠送AI脱衣免费次数[%v次]", txnmod.PrizeRecord.Key(), p.Price), DiscDoc: u.DiscDoc, SysType: u.SysType, } transactionLogs = append(transactionLogs, aiLog) } // AI金币抵扣券 if p.PrizeType == prize_record_mod.PrizeTypeGoldDiscountCoupon { nowTime := time.Now() goodsList = append(goodsList, backpackmod.Backpack{ UID: uid, GoodsName: p.Name, GoodsType: backpackmod.AiChangeFaceDiscount, GoodsValue: p.Price, GoodsOrigin: "抽奖获得AI金币抵扣券", Status: backpackmod.Unused, ExpiredTime: nowTime.Add(time.Hour * 24 * time.Duration(p.ValidDate)), CreateTime: nowTime, }) } } set := usermod.UserSelector{VipExpireDate: &u.VipExpireDate, VipLevel: &u.VipLevel, PayVidDiscount: &u.PayVidDiscount} // 根据类型处理业务 if err = appg.VideoDB.Trans(func(t *db.MongoTool) error { if vipStatus { if err = usermod.UpdateUserById(t, uid, set); err != nil { log.Error(fmt.Sprintf("用户ID:%d;奖品派发VIP更新异常:%v", uid, err)) return err } } if len(couponRecords) > 0 { err = coupon_record_mod.InsertManyCouponRecords(t, couponRecords) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;奖品派发加赠券日志插入异常:%v", uid, err)) return err } } if totalInc > 0 { _, err = walletmod.CreditAmount(t, totalInc, uid) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;奖品派发金币流水异常:%v", uid, err)) return err } } if len(transactionLogs) > 0 { err = txnmod.InsertManyTransactionLog(t, transactionLogs) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;奖品派发资金流水日志插入异常:%v", uid, err)) return err } } if totalAIUndressInc > 0 { _, err := walletmod.DebitAiFreeTimes(t, -totalAIUndressInc, uid) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;奖品派发AI免费次数异常:%v", uid, err)) return err } } if len(goodsList) > 0 { if err := backpackmod.AddGoodsMany(t, uid, goodsList); err != nil { log.Error(fmt.Sprintf("用户ID:%d;奖品派发AI抵扣券插入异常:%v", uid, err)) return err } } return nil }); err != nil { return stderr.ErrDbTransError } log.Info(fmt.Sprintf("用户ID:%d;抽奖派发成功", uid)) return nil } // Delete 删除优惠券列表 func Delete(uid uint64, in *prize_record_mod.AppDeleteReq) error { // 获取用户信息 u, err := usermod.FindUserByUID(uid) if err != nil { return err } if u == nil { return stderr.UserIsNotExists } // 删除成功 if err = coupon_record_mod.Remove(in.Filter()); err != nil { return err } log.Info(fmt.Sprintf("用户ID:%d;优惠券删除发成功", uid)) return nil } // Gain 获取用户信息 func Gain(c *gin.Context, uid uint64) (data *coupon_record_mod.AppGainUserInfoRes, err error) { info := coupon_record_mod.AppGainUserInfoRes{UID: uid, LotteryTimes: 0} var conAmt int64 = 0 // 获取用户信息 u, err := usermod.FindUserByUID(uid) if err != nil { return nil, err } if u == nil { return nil, stderr.UserIsNotExists } w, err := walletmod.GetWallet(uid) if err != nil { return nil, stderr.ErrDbQueryError } if w.Consumption != 0 { //conAmt = w.Consumption / 10 } if w.LotteryTimes != 0 { info.LotteryTimes = w.LotteryTimes } // 检查预售权益免费次数 hasPrivilege, advance := advanceordermod.GetUserValidOrder(uid) if hasPrivilege { // 获取可用免费次数 validCount := advance.PrepaidPrivilege.LuckyDrawLimitPerDay - advance.TodayUse.LuckyDrawCount if validCount > 0 { info.LotteryTimes += validCount } } t := c.Request.Header.Get("authorization") sReq := coupon_record_mod.AppGainUserInfoReq{ AppID: commod.KFK_APPID, Token: t, UserName: u.Name, UID: uid, TotalRecharge: conAmt, Balance: w.Amount + w.Income, } ct, _ := json.Marshal(sReq) log.Info(fmt.Sprintf("Gain userInfo:%+v:", string(ct))) aesKey := []byte("nU7cLOX7t3yJHq8yeIMCfO9emiOWtdlN") encrypt, err := AesPCK5Encrypt(ct, aesKey) if err != nil { log.Error(fmt.Sprintf("Gain userInfo aes err:%+v:", err)) return nil, err } log.Info(fmt.Sprintf("Gain userInfo aes string:%+v:", encrypt)) info.Data = *encrypt return &info, nil } func PKCS5Padding(plaintext []byte, blockSize int) []byte { padding := blockSize - len(plaintext)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(plaintext, padtext...) } func PKCS5UnPadding(origData []byte) []byte { length := len(origData) unpadding := int(origData[length-1]) return origData[:(length - unpadding)] } // AesPCK5Encrypt 加密 func AesPCK5Encrypt(origData, key []byte) (*string, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() origData = PKCS5Padding(origData, blockSize) blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) encrypted := make([]byte, len(origData)) blockMode.CryptBlocks(encrypted, origData) enData := base64.StdEncoding.EncodeToString(encrypted) return &enData, nil } // 解密 func AesPCK5Decrypt(crypted, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) origData := make([]byte, len(crypted)) blockMode.CryptBlocks(origData, crypted) origData = PKCS5UnPadding(origData) return origData, nil }