Files
web_hgdjc_server/app/service/coinser/coin_buy.go
T
rootandClaude Opus 4.7 eb8840a3af 同步 web_hga 的五项改造
- 移除 买点 (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>
2026-11-07 11:26:52 +08:00

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
}