- 移除 买点 (user acquisition tracking) 子系统:dataReport SDK、eventmod 事件模型、reportdata 定时上报 job、reportser/srv_report 包装层,以及业务 侧的 ~20 处 Report* 调用点;去掉 proto.ConfigInfo 的 ReportSDKConfig 字段、DataReport yaml 配置块和 pubdef.TrackerAppId。 - 广告获取改走 versionUrl /api/stat/advitise/v2/get(appId=12),移除 adcenter(Jt) 调用;新增 POST /api/app/ads/click 异步上报; proto.AdvitiseData 别名 proxy.AdvitiseData,AList/BList 改名 AppInfoAList/AppInfoBList。 - web 后台登录取消谷歌验证码(srv_mwacc.AccLogin 去掉 code 参数),密码 正确即发放 token。 - app 端取消注册/登录/找回密码/游客登录接口及密码、token 相关代码;鉴权 中间件按 X-User-Agent 中的 devID 识别用户,首次访问自动建号,Redis 缓存 10 分钟;修改资料不再支持改密码。 - app m3u8 ticket 校验失败不再降级到 fallback 路径,仍按原 m3u8Name 返回。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
138 lines
4.5 KiB
Go
138 lines
4.5 KiB
Go
package coinser
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
"videoweb/app/service/rechargeser"
|
|
"videoweb/pub/common/log"
|
|
"videoweb/pub/common/srvdef"
|
|
"videoweb/pub/common/useragent"
|
|
"videoweb/pub/models/rechargepackagemod"
|
|
"videoweb/pub/models/usermod"
|
|
"videoweb/pub/models/vipordermod"
|
|
"videoweb/pub/mongos"
|
|
"videoweb/pub/pubdef"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
// BuyCoinResp 购买金币下单响应
|
|
type BuyCoinResp struct {
|
|
TradeNo string `json:"tradeNo"`
|
|
PayUrl string `json:"payUrl"`
|
|
PayUrlMode string `json:"payUrlMode"`
|
|
IsOpenNewBrowser bool `json:"isOpenNewBrowser"`
|
|
}
|
|
|
|
// GetUserInfo 获取用户信息
|
|
func GetUserInfo(ctx context.Context, userId int64) (*usermod.User, *srvdef.SrvErr) {
|
|
return usermod.FindOneUser(ctx, bson.M{usermod.FN.User.Id: userId})
|
|
}
|
|
|
|
// CreateCoinOrder 创建金币购买订单(统一写入 vip_order 表,OrderType=2)。
|
|
// 防重复:15 秒内同一用户+同一套餐的 pending 订单直接返回原支付链接。
|
|
func CreateCoinOrder(ctx context.Context,
|
|
userId int64, userName string,
|
|
packageId int64, payMode string,
|
|
sysType string, devType string, deviceID string, ip string,
|
|
districtCode string, sourcePageKey string, sourcePageName string,
|
|
) (*BuyCoinResp, *srvdef.SrvErr) {
|
|
|
|
pkg, serr := rechargepackagemod.FindOneRechargePackage(ctx, bson.M{
|
|
rechargepackagemod.FN.RechargePackage.Id: packageId,
|
|
rechargepackagemod.FN.RechargePackage.PackageType: rechargepackagemod.PackageTypeCoin,
|
|
rechargepackagemod.FN.RechargePackage.Status: rechargepackagemod.StatusEnabled,
|
|
})
|
|
if serr != nil || pkg == nil {
|
|
return nil, srvdef.New(srvdef.ErrNoData, "金币套餐不存在或已下架", "")
|
|
}
|
|
coinAmount := pkg.BaseCoin + pkg.GiftCoin
|
|
if coinAmount <= 0 {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "金币套餐到账数量无效", "")
|
|
}
|
|
|
|
now := time.Now()
|
|
dupFilter := bson.M{
|
|
vipordermod.FN.VipOrder.UserId: userId,
|
|
vipordermod.FN.VipOrder.CoinCfgId: packageId,
|
|
vipordermod.FN.VipOrder.OrderType: vipordermod.OrderTypeCoin,
|
|
vipordermod.FN.VipOrder.PayMode: payMode,
|
|
vipordermod.FN.VipOrder.Status: pubdef.VipOrderPending,
|
|
vipordermod.FN.VipOrder.CreatedAt: bson.M{"$gte": now.Add(-15 * time.Second)},
|
|
}
|
|
existing, _ := vipordermod.FindOneVipOrder(ctx, dupFilter)
|
|
if existing != nil && existing.PayUrl != "" {
|
|
return &BuyCoinResp{
|
|
TradeNo: existing.TradeNo,
|
|
PayUrl: existing.PayUrl,
|
|
PayUrlMode: existing.PayUrlMode,
|
|
IsOpenNewBrowser: true,
|
|
}, nil
|
|
}
|
|
|
|
tradeNo := pubdef.GetTrandNoWithUUID()
|
|
|
|
payInfo, serr := rechargeser.SubmitPayOrder(ctx, userId, userName, tradeNo, pkg.Price, payMode, sysType, devType, deviceID, ip)
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
|
|
order := &vipordermod.VipOrder{
|
|
Id: mongos.Lid.VipOrder.Get(),
|
|
OrderType: vipordermod.OrderTypeCoin,
|
|
UserId: userId,
|
|
CoinCfgId: packageId, // 兼容历史字段,存购买套餐ID
|
|
Coin: coinAmount,
|
|
BaseCoin: pkg.BaseCoin,
|
|
GiftCoin: pkg.GiftCoin,
|
|
Amount: pkg.Price,
|
|
PayMode: payMode,
|
|
TradeNo: tradeNo,
|
|
Oid: payInfo.Oid,
|
|
Status: pubdef.VipOrderPending,
|
|
PayUrl: payInfo.PayUrl,
|
|
PayUrlMode: payInfo.PayUrlMode,
|
|
PayChannel: payInfo.PayChannel,
|
|
PayRate: payInfo.PayRate,
|
|
IPAddr: ip,
|
|
SysType: sysType,
|
|
DistrictCode: strings.TrimSpace(districtCode),
|
|
Client: vipordermod.NewOrderClient(useragent.FromContext(ctx), sourcePageKey, sourcePageName),
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
if serr = vipordermod.InsertOneVipOrder(ctx, order); serr != nil {
|
|
log.Error("coinser:CreateCoinOrder InsertOneVipOrder failed",
|
|
log.Any("tradeNo", tradeNo), log.E(serr))
|
|
return nil, serr
|
|
}
|
|
|
|
return &BuyCoinResp{
|
|
TradeNo: tradeNo,
|
|
PayUrl: payInfo.PayUrl,
|
|
PayUrlMode: payInfo.PayUrlMode,
|
|
IsOpenNewBrowser: true,
|
|
}, nil
|
|
}
|
|
|
|
// GetCoinOrderHistory 查询用户金币购买记录
|
|
func GetCoinOrderHistory(ctx context.Context, userId int64, page, pageSize int64) (vipordermod.VipOrderList, int64, *srvdef.SrvErr) {
|
|
filter := bson.M{
|
|
vipordermod.FN.VipOrder.UserId: userId,
|
|
vipordermod.FN.VipOrder.OrderType: vipordermod.OrderTypeCoin,
|
|
}
|
|
total, serr := vipordermod.CountVipOrder(ctx, filter)
|
|
if serr != nil {
|
|
return nil, 0, serr
|
|
}
|
|
skip := (page - 1) * pageSize
|
|
opts := options.Find().
|
|
SetSort(bson.M{vipordermod.FN.VipOrder.CreatedAt: -1}).
|
|
SetSkip(skip).
|
|
SetLimit(pageSize)
|
|
list, serr := vipordermod.FindManyVipOrder(ctx, filter, opts)
|
|
return list, total, serr
|
|
}
|