支付和广告调试
This commit is contained in:
@@ -50,6 +50,8 @@ type AdvertiseInfo struct {
|
||||
JumpType int32 `json:"jumpType"` // 跳转方式 0:外部浏览器跳转 1:内部浏览器跳转 2:app内部跳转
|
||||
Link string `json:"link"` // 链接地址
|
||||
Sort int64 `json:"sort"` // 排序
|
||||
Tags string `json:"tags"` // 标签
|
||||
Remark string `json:"remark"` // 备注描述
|
||||
}
|
||||
|
||||
func AdvertiseThreeServer(userId uint64, ip string) (*AdvertiseRes, error) {
|
||||
|
||||
@@ -9,16 +9,17 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"sync"
|
||||
|
||||
"91porn-server/app/appg"
|
||||
"91porn-server/app/service/activityclient"
|
||||
"91porn-server/common"
|
||||
"91porn-server/common/crypt"
|
||||
"91porn-server/common/httputil"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/models/v/usermod"
|
||||
"91porn-server/models/v/walletmod"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -120,115 +121,148 @@ func (ad AdDetailInfo) GetAdvertiseType() int {
|
||||
return ad.AdvertiseType
|
||||
}
|
||||
|
||||
// JtAdvertiseThreeServer 集团广告中心
|
||||
func JtAdvertiseThreeServer() ([]AdSlot, error) {
|
||||
var foreverCacheKey = fmt.Sprintf("jtAdForever-%s-%s", appg.Conf.AdCenter.MerchantCode, appg.Conf.AdCenter.AppCode)
|
||||
redisKey := fmt.Sprintf("jtAd-%s-%s", appg.Conf.AdCenter.MerchantCode, appg.Conf.AdCenter.AppCode)
|
||||
str, err := appg.Redis.Get(redisKey)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("JtAdvertiseThreeServer 缓存获取广告列表信息异常:%v", err))
|
||||
}
|
||||
var resp []AdSlot
|
||||
if str != nil {
|
||||
if err = json.Unmarshal([]byte(*str), &resp); err == nil {
|
||||
return resp, nil
|
||||
}
|
||||
log.Error(fmt.Sprintf("JtAdvertiseThreeServer 解析缓存数据异常:%v", err))
|
||||
}
|
||||
req := JtAdvertiseReq{
|
||||
MerchantCode: appg.Conf.AdCenter.MerchantCode,
|
||||
AppCode: appg.Conf.AdCenter.AppCode,
|
||||
AdStatus: 1,
|
||||
}
|
||||
// advertiseAppId 广告中心应用ID
|
||||
const advertiseAppId int32 = 2
|
||||
|
||||
var serverResp *JtAdvertiseRes
|
||||
url := appg.Conf.AdCenter.ApiDomain + "/openapi/getAdvertiseList"
|
||||
type advertiseClickReq struct {
|
||||
Id int64 `json:"id"` // 广告id
|
||||
AppId int32 `json:"appId"` // 应用id
|
||||
}
|
||||
|
||||
type advertiseClickResp struct {
|
||||
Code int64 `json:"code"` // 错误码
|
||||
}
|
||||
|
||||
// AdvertiseClickCenter 上报广告点击到广告中心
|
||||
func AdvertiseClickCenter(advertiseId int64) error {
|
||||
req := advertiseClickReq{
|
||||
Id: advertiseId,
|
||||
AppId: advertiseAppId,
|
||||
}
|
||||
resp := advertiseClickResp{}
|
||||
url := appg.Conf.URL.VersionUrl + "/api/stat/advitise/v2/click"
|
||||
bodyStr, _ := json.Marshal(req)
|
||||
code, err := httputil.DefaultClientPostJsonWithResp(&serverResp, url, nil, bodyStr)
|
||||
code, err := httputil.DefaultClientPostJsonWithResp(&resp, url, nil, bodyStr)
|
||||
if err != nil {
|
||||
log.Error("JtAdvertiseThreeServer POSTWithJResp ", log.Any("url", url), log.E(err))
|
||||
// 从最后请求成功的一次拿数据
|
||||
return getFromLastTime(foreverCacheKey, err)
|
||||
log.Error("AdvertiseClickCenter POSTWithJResp", log.Any("url", url), log.Any("req", req), log.E(err))
|
||||
return err
|
||||
}
|
||||
if code != http.StatusOK {
|
||||
log.Error("JtAdvertiseThreeServer response status ", log.Any("code", code))
|
||||
// 从最后请求成功的一次拿数据
|
||||
return getFromLastTime(foreverCacheKey, errors.New("response status err"))
|
||||
log.Error("AdvertiseClickCenter response status", log.Any("code", code), log.Any("req", req))
|
||||
return fmt.Errorf("response status err")
|
||||
}
|
||||
|
||||
if serverResp.Code != 0 {
|
||||
log.Error("JtAdvertiseThreeServer response code ", log.Any("code", serverResp.Code), log.Any("msg", serverResp.Msg))
|
||||
// 从最后请求成功的一次拿数据
|
||||
return getFromLastTime(foreverCacheKey, errors.New("response code err"))
|
||||
}
|
||||
|
||||
adsData, err := crypt.AdDecrypt(serverResp.Data, appg.Conf.AdCenter.AesKey)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("JtAdvertiseThreeServer 解密广告数据异常:%v", err))
|
||||
return nil, errors.New("response data err")
|
||||
}
|
||||
err = json.Unmarshal([]byte(adsData), &resp)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("JtAdvertiseThreeServer 解析 JSON 失败:%v", err))
|
||||
return nil, errors.New("data format error")
|
||||
}
|
||||
|
||||
// 对广告进行升序排序
|
||||
for i := range resp {
|
||||
sort.Slice(resp[i].AdDetailInfoList, func(j, k int) bool {
|
||||
return resp[i].AdDetailInfoList[j].Sort < resp[i].AdDetailInfoList[k].Sort
|
||||
})
|
||||
}
|
||||
|
||||
// 将最后一次请求成功的数据更新到二级缓存
|
||||
common.Go(func() {
|
||||
setAdsCache(foreverCacheKey, resp)
|
||||
})
|
||||
|
||||
common.Go(func() {
|
||||
data, err := json.Marshal(&resp)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("JtAdvertiseThreeServer json序列化缓存数据异常:%v", err))
|
||||
return
|
||||
}
|
||||
if err = appg.Redis.Set(redisKey, data, time.Minute); err != nil {
|
||||
log.Error(fmt.Sprintf("JtAdvertiseThreeServer 保存缓存数据异常:%v", err))
|
||||
}
|
||||
})
|
||||
|
||||
return resp, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// getFromLastTime 返回最后一次请求的广告数据
|
||||
func getFromLastTime(foreverCacheKey string, e error) ([]AdSlot, error) {
|
||||
str, err := appg.Redis.Get(foreverCacheKey)
|
||||
// AsyncAdvertiseClick 异步上报广告点击,广告id非数字时忽略
|
||||
func AsyncAdvertiseClick(id string) {
|
||||
advertiseId, err := strconv.ParseInt(strings.TrimSpace(id), 10, 64)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("getFromLastTime 缓存获取广告列表信息异常:%v", err))
|
||||
return nil, e
|
||||
log.Warn("AsyncAdvertiseClick invalid advertise id", log.Any("id", id))
|
||||
return
|
||||
}
|
||||
|
||||
var resp []AdSlot
|
||||
if str != nil {
|
||||
if err = json.Unmarshal([]byte(*str), &resp); err == nil {
|
||||
return resp, nil
|
||||
}
|
||||
log.Error(fmt.Sprintf("getFromLastTime 解析缓存数据异常:%v", err))
|
||||
}
|
||||
|
||||
return nil, e
|
||||
common.Go(func() {
|
||||
_ = AdvertiseClickCenter(advertiseId)
|
||||
})
|
||||
}
|
||||
|
||||
// setAdsCache 更新最后一次请求的广告数据
|
||||
func setAdsCache(foreverCacheKey string, resp []AdSlot) {
|
||||
data, err := json.Marshal(&resp)
|
||||
var (
|
||||
advertiseCacheOnce sync.Once
|
||||
advertiseCacheMu sync.RWMutex
|
||||
advertiseCache []AdSlot
|
||||
advertiseCacheOK bool
|
||||
)
|
||||
|
||||
// JtAdvertiseThreeServer 获取广告位列表(内存缓存,每两分钟从广告中心刷新一次)
|
||||
func JtAdvertiseThreeServer() ([]AdSlot, error) {
|
||||
advertiseCacheOnce.Do(startAdvertiseCache)
|
||||
|
||||
advertiseCacheMu.RLock()
|
||||
defer advertiseCacheMu.RUnlock()
|
||||
if !advertiseCacheOK {
|
||||
return nil, errors.New("advertise cache not ready")
|
||||
}
|
||||
res := make([]AdSlot, len(advertiseCache))
|
||||
copy(res, advertiseCache)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// startAdvertiseCache 首次加载广告并启动定时刷新
|
||||
func startAdvertiseCache() {
|
||||
updataAdvertiseInfo()
|
||||
c := cron.New(cron.WithSeconds())
|
||||
_, _ = c.AddFunc("0 */2 * * * ?", updataAdvertiseInfo) // 两分钟更新一次
|
||||
c.Start()
|
||||
}
|
||||
|
||||
// updataAdvertiseInfo 从广告中心拉取广告并更新缓存,列表为空时重试一次
|
||||
func updataAdvertiseInfo() {
|
||||
advertiseResp, err := advertiseCenterServer()
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("setAdsCache json序列化缓存数据异常:%v", err))
|
||||
log.Error("advertiseCenterServer", log.E(err))
|
||||
return
|
||||
}
|
||||
|
||||
if err := appg.Redis.Set(foreverCacheKey, data, time.Hour*72); err != nil {
|
||||
log.Error(fmt.Sprintf("setAdsCache 保存缓存数据异常:%v", err))
|
||||
log.Error("advertiseCenterServer", log.Any("advertiseResp", advertiseResp))
|
||||
|
||||
if len(advertiseResp.AdvertiseList) == 0 {
|
||||
advertiseResp, err = advertiseCenterServer()
|
||||
if err != nil {
|
||||
log.Error("advertiseCenterServer", log.E(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
list := advertiseResp.AdvertiseList
|
||||
sort.SliceStable(list, func(i, j int) bool {
|
||||
if list[i].LocId != list[j].LocId {
|
||||
return list[i].LocId < list[j].LocId
|
||||
}
|
||||
return list[i].Sort < list[j].Sort
|
||||
})
|
||||
// 每条广告单独作为一个广告位返回,广告位名称取广告标题
|
||||
slots := make([]AdSlot, 0, len(list))
|
||||
for _, value := range list {
|
||||
slots = append(slots, AdSlot{
|
||||
AdvertiseLocationCode: strconv.FormatInt(int64(value.LocId), 10),
|
||||
AdvertiseLocationName: value.Title,
|
||||
AdDetailInfoList: []AdDetailInfo{{
|
||||
AdvertiseCode: strconv.FormatInt(value.Id, 10),
|
||||
AdvertiseName: value.Title,
|
||||
AdvertiseUrl: value.Link,
|
||||
AdvertiseIcon: value.CoverImg,
|
||||
AdvertiseDesc: value.Remark,
|
||||
Sort: int(value.Sort),
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
advertiseCacheMu.Lock()
|
||||
advertiseCache = slots
|
||||
advertiseCacheOK = true
|
||||
advertiseCacheMu.Unlock()
|
||||
}
|
||||
|
||||
// advertiseCenterServer 请求广告中心广告列表
|
||||
func advertiseCenterServer() (resp AdvertiseRes, err error) {
|
||||
req := AdvertiseReq{
|
||||
AppId: advertiseAppId,
|
||||
}
|
||||
url := appg.Conf.URL.VersionUrl + "/api/stat/advitise/v2/get"
|
||||
bodyStr, _ := json.Marshal(req)
|
||||
code, err := httputil.DefaultClientPostJsonWithResp(&resp, url, nil, bodyStr)
|
||||
if err != nil {
|
||||
log.Error("advertiseCenterServer POSTWithJResp ", log.Any("url", url), log.E(err))
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("*************\n\n\n", log.Any("", resp))
|
||||
if code != http.StatusOK {
|
||||
log.Error("advertiseCenterServer response status ", log.Any("code", code))
|
||||
err = fmt.Errorf("response status err")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetAdvertiseLocation(adverId string) (res proto.AdsInfo) {
|
||||
|
||||
@@ -85,7 +85,7 @@ func New_CurrencyList(ctx context.Context, uid uint64, sysType string, t commod.
|
||||
moneys = append(moneys, FenToYuan(c.Price))
|
||||
}
|
||||
|
||||
req := rchgutil.GainPayTypeReq{Money: moneys}
|
||||
req := rchgutil.GainPayTypeReq{Money: moneys, DevType: sysType, DistrictCode: userDistrictCode(uid)}
|
||||
bc, err := req.GetPayType()
|
||||
if err != nil {
|
||||
log.ErrorX(ctx, "获取支付通道列表异常", log.Any("moneys", moneys), log.Any("sysType", sysType),
|
||||
@@ -119,6 +119,18 @@ func New_CurrencyList(ctx context.Context, uid uint64, sysType string, t commod.
|
||||
return data, stderr.Success
|
||||
}
|
||||
|
||||
// userDistrictCode 获取用户渠道码,查询失败按空渠道码处理
|
||||
func userDistrictCode(uid uint64) string {
|
||||
if uid == 0 {
|
||||
return ""
|
||||
}
|
||||
u, err := usermod.FindUserByUID(uid)
|
||||
if err != nil || u == nil {
|
||||
return ""
|
||||
}
|
||||
return u.DistrictCode
|
||||
}
|
||||
|
||||
// getChannelDisplayName 获取支付渠道显示名称
|
||||
func getChannelDisplayName(pType string) string {
|
||||
channelNames := map[string]string{
|
||||
@@ -283,7 +295,7 @@ func New_ProductList(uid uint64, sysType string, newUser bool, proT int) (res []
|
||||
moneys := GetUniqueMoneys(data)
|
||||
|
||||
// 缓存支付通道信息
|
||||
req := rchgutil.GainPayTypeReq{Money: moneys}
|
||||
req := rchgutil.GainPayTypeReq{Money: moneys, DevType: sysType, DistrictCode: userDistrictCode(uid)}
|
||||
bc, err := req.GetPayTypeFromCache()
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("用户ID:%d;rchgutil GetPayType:%v", uid, err))
|
||||
|
||||
@@ -97,17 +97,19 @@ func Recharge(ctx context.Context, in *RechargeRequest, ua ua.UA, deduct *Activi
|
||||
|
||||
// 下单
|
||||
now := time.Now()
|
||||
res, err := (&rchgutil.Recharge{
|
||||
TradeNo: order.ID.Hex(),
|
||||
Money: rchgutil.FenToYuan(order.Money),
|
||||
Type: order.RechargeType,
|
||||
Info: rchgutil.PayInfo{
|
||||
PlayerId: strconv.FormatUint(order.UID, 10),
|
||||
PlayerIp: order.UserIP,
|
||||
DeviceId: order.DevID,
|
||||
Tel: order.Tel,
|
||||
DeviceType: order.DevType,
|
||||
},
|
||||
res, err := (&rchgutil.Rchg{
|
||||
TransNo: order.ID.Hex(),
|
||||
UID: strconv.FormatUint(order.UID, 10),
|
||||
DevID: order.DevID,
|
||||
UserIP: order.UserIP,
|
||||
Name: u.Name,
|
||||
Tel: order.Tel,
|
||||
DevType: order.DevType,
|
||||
Money: order.Money,
|
||||
Channel: "self",
|
||||
CreatedAt: now,
|
||||
PayMethod: order.RechargeType,
|
||||
ProductType: 0,
|
||||
}).ToPayNew(ctx)
|
||||
if err != nil {
|
||||
log.ErrorX(ctx, fmt.Sprintf("用户ID[%d] 支付方式[%s] 购买类型[%d] 产品ID[%v] 产品子ID[%v] 下单请求异常[%v]",
|
||||
@@ -123,8 +125,8 @@ func Recharge(ctx context.Context, in *RechargeRequest, ua ua.UA, deduct *Activi
|
||||
ProgressAt: &now,
|
||||
OID: &res.OID,
|
||||
Mode: &res.Mode,
|
||||
//Channel: &res.CID,
|
||||
Rate: &res.Rebate,
|
||||
Channel: &res.CID,
|
||||
Rate: &res.Rate,
|
||||
}
|
||||
if err = rchgordmod.Update(nil, order.ID, set); err != nil {
|
||||
log.ErrorX(ctx, fmt.Sprintf("用户ID[%d] 支付方式[%s] 购买类型[%d] 产品ID[%v] 产品子ID[%v] 更新订单异常[%v]",
|
||||
@@ -507,6 +509,11 @@ func RechargeCallBack(ctx context.Context, oid string, payMoney int64, tradeNo s
|
||||
if r.ProductType == 1 {
|
||||
return errors.New("瓦力游戏已下架")
|
||||
}
|
||||
// 回调订单号需与下单时支付平台返回的订单号一致
|
||||
if r.OID != "" && oid != r.OID {
|
||||
log.ErrorX(ctx, "充值回调支付平台订单号不一致", log.Any("oid", oid), log.Any("orderOid", r.OID), log.Any("tradeNo", tradeNo))
|
||||
return errors.New("oid 错误")
|
||||
}
|
||||
// 新版充值---根据购买类型处理
|
||||
var (
|
||||
fn func(*db.MongoTool) error
|
||||
|
||||
Reference in New Issue
Block a user