支付和广告调试
This commit is contained in:
@@ -37,6 +37,7 @@ func AdsClick(ctx *gin.Context) {
|
|||||||
common.ServeJSON(ctx, stderr.ErrParamError, nil)
|
common.ServeJSON(ctx, stderr.ErrParamError, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
adser.AsyncAdvertiseClick(arg.ID)
|
||||||
common.ServeJSON(ctx, stderr.Success, nil)
|
common.ServeJSON(ctx, stderr.Success, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"91porn-server/common/constant"
|
"91porn-server/common/constant"
|
||||||
"91porn-server/common/services/message"
|
"91porn-server/common/services/message"
|
||||||
"91porn-server/common/store"
|
"91porn-server/common/store"
|
||||||
|
v10 "91porn-server/common/v10"
|
||||||
"91porn-server/models/cache/bannerjumpdata"
|
"91porn-server/models/cache/bannerjumpdata"
|
||||||
"91porn-server/models/cache/sysconfdata"
|
"91porn-server/models/cache/sysconfdata"
|
||||||
"91porn-server/models/v/bannerjumpmod"
|
"91porn-server/models/v/bannerjumpmod"
|
||||||
@@ -32,7 +33,6 @@ import (
|
|||||||
"91porn-server/common"
|
"91porn-server/common"
|
||||||
"91porn-server/common/log"
|
"91porn-server/common/log"
|
||||||
"91porn-server/common/stderr"
|
"91porn-server/common/stderr"
|
||||||
"91porn-server/common/version"
|
|
||||||
"91porn-server/models/commod"
|
"91porn-server/models/commod"
|
||||||
"91porn-server/models/v/sourcemod"
|
"91porn-server/models/v/sourcemod"
|
||||||
"91porn-server/models/v/systemmod"
|
"91porn-server/models/v/systemmod"
|
||||||
@@ -248,40 +248,29 @@ func DomainList(ctx *gin.Context) {
|
|||||||
})
|
})
|
||||||
common.Go(func() {
|
common.Go(func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
builId := v10.ExtractPureEngChar(ua.BuildID)
|
||||||
//版本、广告、公告
|
//版本、广告、公告
|
||||||
verResp, _, annouResp, _, _, _, err := versionser.AdvVersionAnnounThreeServer(ua.Ver, ua.SysType)
|
versionResp, err := VersionThreeServer(ua.Ver, ua.SysType, builId, ua.BuildID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("VersionThreeServer", log.E(err))
|
return
|
||||||
}
|
}
|
||||||
for k, v := range annouResp {
|
|
||||||
v.Href = activityclient.ReplaceActivityDomain(v.Href, user, wallet)
|
if versionResp.HasNewVersion {
|
||||||
annouResp[k] = v
|
|
||||||
}
|
|
||||||
//版本业务
|
|
||||||
//安卓不做限制;iOS 端版本 <= 1.11.2 不下发版本信息
|
|
||||||
skipVer := false
|
|
||||||
if ua.SysType == constant.SysTypeIOS {
|
|
||||||
if cur, err := version.New(ua.Ver); err == nil && cur.LTE(version.MustNew("1.11.2")) {
|
|
||||||
skipVer = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(verResp.DownloadLink) > 0 && !skipVer {
|
|
||||||
versionBody := []*versionmod.VersionBody{
|
versionBody := []*versionmod.VersionBody{
|
||||||
&versionmod.VersionBody{
|
&versionmod.VersionBody{
|
||||||
VersionName: verResp.ServerVersion,
|
VersionName: versionResp.ServerVersion,
|
||||||
Platform: ua.SysType,
|
Platform: ua.SysType,
|
||||||
Description: verResp.Description,
|
Description: versionResp.Description,
|
||||||
ForcedUpdate: verResp.IsForceUpdate,
|
ForcedUpdate: versionResp.IsForceUpdate,
|
||||||
URL: verResp.DownloadLink[0],
|
URL: versionResp.DownloadLink[0],
|
||||||
IosUrl: verResp.DownloadLink[0],
|
IosUrl: versionResp.DownloadLink[0],
|
||||||
}}
|
}}
|
||||||
sysInfo.Ver = versionBody
|
sysInfo.Ver = versionBody
|
||||||
}
|
}
|
||||||
//公告
|
|
||||||
sysInfo.Ads.AnnounList = annouResp
|
|
||||||
})
|
})
|
||||||
common.Go(func() {
|
common.Go(func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
jtAds, err := adser.JtAdvertiseThreeServer()
|
jtAds, err := adser.JtAdvertiseThreeServer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("JtAdvertiseThreeServer error occur", log.E(err))
|
log.Error("JtAdvertiseThreeServer error occur", log.E(err))
|
||||||
@@ -324,6 +313,7 @@ func DomainList(ctx *gin.Context) {
|
|||||||
adsList = append(adsList, adsinfo)
|
adsList = append(adsList, adsinfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.Info("JtAdvertiseThreeServer", log.Any("ads", adsList))
|
||||||
sysInfo.Ads.AdsList = adsList
|
sysInfo.Ads.AdsList = adsList
|
||||||
})
|
})
|
||||||
common.Go(func() {
|
common.Go(func() {
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package pingctrl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"91porn-server/app/appg"
|
||||||
|
"91porn-server/common/httputil"
|
||||||
|
"91porn-server/common/log"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PacketType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
PacketTypeEnterprise PacketType = 1 // 企业签
|
||||||
|
PacketTypeShop PacketType = 2 // 商店包
|
||||||
|
PacketTypeTestFlight PacketType = 3 // TF包
|
||||||
|
)
|
||||||
|
|
||||||
|
type AppVersionReq struct {
|
||||||
|
AppId int32 `json:"appId" binding:"required"` // AppID
|
||||||
|
SysType string `json:"sysType,omitempty"` // 终端类型
|
||||||
|
PktType PacketType `json:"pktType,omitempty"` // 包类型
|
||||||
|
CurVersion string `json:"curVersion,omitempty"` // 当前版本
|
||||||
|
CurPackageName string `json:"curPackageName,omitempty"` // 包名
|
||||||
|
}
|
||||||
|
|
||||||
|
type AppVersionResp struct {
|
||||||
|
HasNewVersion bool `json:"hasNewVersion,omitempty"` // 是否存在新版本
|
||||||
|
ServerVersion string `json:"serverVersion,omitempty"` // 服务器新版本
|
||||||
|
DownloadLink []string `json:"downloadLink,omitempty"` // 下载地址
|
||||||
|
Description string `json:"description,omitempty"` // 描述
|
||||||
|
IsForceUpdate bool `json:"isForceUpdate,omitempty"` // 是否强制升级
|
||||||
|
Size string `json:"size,omitempty"` // 大小
|
||||||
|
Md5 string `json:"md5,omitempty"` // md5
|
||||||
|
}
|
||||||
|
|
||||||
|
func VersionThreeServer(curVersion, sysType, buildID, packageName string) (resp AppVersionResp, err error) {
|
||||||
|
req := AppVersionReq{
|
||||||
|
AppId: 2,
|
||||||
|
PktType: PacketTypeEnterprise,
|
||||||
|
SysType: sysType,
|
||||||
|
CurVersion: curVersion,
|
||||||
|
CurPackageName: packageName,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TF包
|
||||||
|
if len(buildID) > 0 {
|
||||||
|
req.PktType = PacketTypeTestFlight
|
||||||
|
}
|
||||||
|
|
||||||
|
url := appg.Conf.URL.VersionUrl + "/api/stat/version/app"
|
||||||
|
bodyStr, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("VersionThreeServer json.Marshal fail", log.Any("req", req), log.E(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
code, err := httputil.New().POSTWithJResp(&resp, url, nil, bodyStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("VersionThreeServer POSTWithJResp ", log.Any("url", url), log.E(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if code != http.StatusOK {
|
||||||
|
log.Error("VersionThreeServer response status ", log.Any("code", code))
|
||||||
|
err = fmt.Errorf("response status err")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("VersionThreeServer response", log.Any("resp", resp.DownloadLink), log.Any("version", resp.HasNewVersion))
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"91porn-server/app/service/rechargeser"
|
"91porn-server/app/service/rechargeser"
|
||||||
"91porn-server/common/log"
|
"91porn-server/common/log"
|
||||||
@@ -44,6 +45,12 @@ func CallBack(ctx *gin.Context) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
rb.TransNo = rchgutil.RChgIDDisassemble(rb.TransNo)
|
rb.TransNo = rchgutil.RChgIDDisassemble(rb.TransNo)
|
||||||
|
if rb.SuccessAt.IsZero() {
|
||||||
|
rb.SuccessAt = time.Now()
|
||||||
|
}
|
||||||
|
if rb.PaymentAt.IsZero() {
|
||||||
|
rb.PaymentAt = rb.SuccessAt
|
||||||
|
}
|
||||||
if err = rechargeser.RechargeCallBack(ctx, rb.OID, rb.PayMoney, rb.TransNo, rb.Code, rb.PaymentAt, rb.SuccessAt); err != nil {
|
if err = rechargeser.RechargeCallBack(ctx, rb.OID, rb.PayMoney, rb.TransNo, rb.Code, rb.PaymentAt, rb.SuccessAt); err != nil {
|
||||||
log.Error(fmt.Sprintf("%s RechargeCallBack fail error:%+v:", name, err))
|
log.Error(fmt.Sprintf("%s RechargeCallBack fail error:%+v:", name, err))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,5 +52,6 @@ func Click(ctx *gin.Context) {
|
|||||||
common.ServeJSON(ctx, stderr.ErrTokenIsNotExist, "")
|
common.ServeJSON(ctx, stderr.ErrTokenIsNotExist, "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
adser.AsyncAdvertiseClick(p.Id)
|
||||||
common.ServeJSON(ctx, stderr.Success, nil)
|
common.ServeJSON(ctx, stderr.Success, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ type GlobalConfig struct {
|
|||||||
DataCentreURL string `json:"dataCentreUrl"` // 数据中心
|
DataCentreURL string `json:"dataCentreUrl"` // 数据中心
|
||||||
ApiUrls []string `json:"apiUrls"` // api域名
|
ApiUrls []string `json:"apiUrls"` // api域名
|
||||||
ProductUrl string `json:"productUrl"` // 产品中心
|
ProductUrl string `json:"productUrl"` // 产品中心
|
||||||
|
VersionUrl string `json:"versionUrl"` // 版本/广告中心地址
|
||||||
//Active2023 string `json:"active2023"` // 2023新春抽奖地址
|
//Active2023 string `json:"active2023"` // 2023新春抽奖地址
|
||||||
NavigateUrl string `json:"navigateUrl"` // 导航站地址
|
NavigateUrl string `json:"navigateUrl"` // 导航站地址
|
||||||
HlH5Url string `json:"hlH5Url"` // 黑料h5url
|
HlH5Url string `json:"hlH5Url"` // 黑料h5url
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ type AdvertiseInfo struct {
|
|||||||
JumpType int32 `json:"jumpType"` // 跳转方式 0:外部浏览器跳转 1:内部浏览器跳转 2:app内部跳转
|
JumpType int32 `json:"jumpType"` // 跳转方式 0:外部浏览器跳转 1:内部浏览器跳转 2:app内部跳转
|
||||||
Link string `json:"link"` // 链接地址
|
Link string `json:"link"` // 链接地址
|
||||||
Sort int64 `json:"sort"` // 排序
|
Sort int64 `json:"sort"` // 排序
|
||||||
|
Tags string `json:"tags"` // 标签
|
||||||
|
Remark string `json:"remark"` // 备注描述
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdvertiseThreeServer(userId uint64, ip string) (*AdvertiseRes, error) {
|
func AdvertiseThreeServer(userId uint64, ip string) (*AdvertiseRes, error) {
|
||||||
|
|||||||
@@ -9,16 +9,17 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"sync"
|
||||||
|
|
||||||
"91porn-server/app/appg"
|
"91porn-server/app/appg"
|
||||||
"91porn-server/app/service/activityclient"
|
"91porn-server/app/service/activityclient"
|
||||||
"91porn-server/common"
|
"91porn-server/common"
|
||||||
"91porn-server/common/crypt"
|
|
||||||
"91porn-server/common/httputil"
|
"91porn-server/common/httputil"
|
||||||
"91porn-server/common/log"
|
"91porn-server/common/log"
|
||||||
"91porn-server/models/v/usermod"
|
"91porn-server/models/v/usermod"
|
||||||
"91porn-server/models/v/walletmod"
|
"91porn-server/models/v/walletmod"
|
||||||
|
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -120,117 +121,150 @@ func (ad AdDetailInfo) GetAdvertiseType() int {
|
|||||||
return ad.AdvertiseType
|
return ad.AdvertiseType
|
||||||
}
|
}
|
||||||
|
|
||||||
// JtAdvertiseThreeServer 集团广告中心
|
// advertiseAppId 广告中心应用ID
|
||||||
func JtAdvertiseThreeServer() ([]AdSlot, error) {
|
const advertiseAppId int32 = 2
|
||||||
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)
|
type advertiseClickReq struct {
|
||||||
str, err := appg.Redis.Get(redisKey)
|
Id int64 `json:"id"` // 广告id
|
||||||
if err != nil {
|
AppId int32 `json:"appId"` // 应用id
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverResp *JtAdvertiseRes
|
type advertiseClickResp struct {
|
||||||
url := appg.Conf.AdCenter.ApiDomain + "/openapi/getAdvertiseList"
|
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)
|
bodyStr, _ := json.Marshal(req)
|
||||||
code, err := httputil.DefaultClientPostJsonWithResp(&serverResp, url, nil, bodyStr)
|
code, err := httputil.DefaultClientPostJsonWithResp(&resp, url, nil, bodyStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("JtAdvertiseThreeServer POSTWithJResp ", log.Any("url", url), log.E(err))
|
log.Error("AdvertiseClickCenter POSTWithJResp", log.Any("url", url), log.Any("req", req), log.E(err))
|
||||||
// 从最后请求成功的一次拿数据
|
return err
|
||||||
return getFromLastTime(foreverCacheKey, err)
|
|
||||||
}
|
}
|
||||||
if code != http.StatusOK {
|
if code != http.StatusOK {
|
||||||
log.Error("JtAdvertiseThreeServer response status ", log.Any("code", code))
|
log.Error("AdvertiseClickCenter response status", log.Any("code", code), log.Any("req", req))
|
||||||
// 从最后请求成功的一次拿数据
|
return fmt.Errorf("response status err")
|
||||||
return getFromLastTime(foreverCacheKey, errors.New("response status err"))
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if serverResp.Code != 0 {
|
// AsyncAdvertiseClick 异步上报广告点击,广告id非数字时忽略
|
||||||
log.Error("JtAdvertiseThreeServer response code ", log.Any("code", serverResp.Code), log.Any("msg", serverResp.Msg))
|
func AsyncAdvertiseClick(id string) {
|
||||||
// 从最后请求成功的一次拿数据
|
advertiseId, err := strconv.ParseInt(strings.TrimSpace(id), 10, 64)
|
||||||
return getFromLastTime(foreverCacheKey, errors.New("response code err"))
|
|
||||||
}
|
|
||||||
|
|
||||||
adsData, err := crypt.AdDecrypt(serverResp.Data, appg.Conf.AdCenter.AesKey)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(fmt.Sprintf("JtAdvertiseThreeServer 解密广告数据异常:%v", err))
|
log.Warn("AsyncAdvertiseClick invalid advertise id", log.Any("id", id))
|
||||||
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
|
return
|
||||||
}
|
}
|
||||||
if err = appg.Redis.Set(redisKey, data, time.Minute); err != nil {
|
common.Go(func() {
|
||||||
log.Error(fmt.Sprintf("JtAdvertiseThreeServer 保存缓存数据异常:%v", err))
|
_ = AdvertiseClickCenter(advertiseId)
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFromLastTime 返回最后一次请求的广告数据
|
var (
|
||||||
func getFromLastTime(foreverCacheKey string, e error) ([]AdSlot, error) {
|
advertiseCacheOnce sync.Once
|
||||||
str, err := appg.Redis.Get(foreverCacheKey)
|
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 {
|
if err != nil {
|
||||||
log.Error(fmt.Sprintf("getFromLastTime 缓存获取广告列表信息异常:%v", err))
|
log.Error("advertiseCenterServer", log.E(err))
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// setAdsCache 更新最后一次请求的广告数据
|
|
||||||
func setAdsCache(foreverCacheKey string, resp []AdSlot) {
|
|
||||||
data, err := json.Marshal(&resp)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(fmt.Sprintf("setAdsCache json序列化缓存数据异常:%v", err))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := appg.Redis.Set(foreverCacheKey, data, time.Hour*72); err != nil {
|
log.Error("advertiseCenterServer", log.Any("advertiseResp", advertiseResp))
|
||||||
log.Error(fmt.Sprintf("setAdsCache 保存缓存数据异常:%v", err))
|
|
||||||
|
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) {
|
func GetAdvertiseLocation(adverId string) (res proto.AdsInfo) {
|
||||||
list, err := JtAdvertiseThreeServer()
|
list, err := JtAdvertiseThreeServer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func New_CurrencyList(ctx context.Context, uid uint64, sysType string, t commod.
|
|||||||
moneys = append(moneys, FenToYuan(c.Price))
|
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()
|
bc, err := req.GetPayType()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ErrorX(ctx, "获取支付通道列表异常", log.Any("moneys", moneys), log.Any("sysType", sysType),
|
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
|
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 获取支付渠道显示名称
|
// getChannelDisplayName 获取支付渠道显示名称
|
||||||
func getChannelDisplayName(pType string) string {
|
func getChannelDisplayName(pType string) string {
|
||||||
channelNames := map[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)
|
moneys := GetUniqueMoneys(data)
|
||||||
|
|
||||||
// 缓存支付通道信息
|
// 缓存支付通道信息
|
||||||
req := rchgutil.GainPayTypeReq{Money: moneys}
|
req := rchgutil.GainPayTypeReq{Money: moneys, DevType: sysType, DistrictCode: userDistrictCode(uid)}
|
||||||
bc, err := req.GetPayTypeFromCache()
|
bc, err := req.GetPayTypeFromCache()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn(fmt.Sprintf("用户ID:%d;rchgutil GetPayType:%v", uid, err))
|
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()
|
now := time.Now()
|
||||||
res, err := (&rchgutil.Recharge{
|
res, err := (&rchgutil.Rchg{
|
||||||
TradeNo: order.ID.Hex(),
|
TransNo: order.ID.Hex(),
|
||||||
Money: rchgutil.FenToYuan(order.Money),
|
UID: strconv.FormatUint(order.UID, 10),
|
||||||
Type: order.RechargeType,
|
DevID: order.DevID,
|
||||||
Info: rchgutil.PayInfo{
|
UserIP: order.UserIP,
|
||||||
PlayerId: strconv.FormatUint(order.UID, 10),
|
Name: u.Name,
|
||||||
PlayerIp: order.UserIP,
|
|
||||||
DeviceId: order.DevID,
|
|
||||||
Tel: order.Tel,
|
Tel: order.Tel,
|
||||||
DeviceType: order.DevType,
|
DevType: order.DevType,
|
||||||
},
|
Money: order.Money,
|
||||||
|
Channel: "self",
|
||||||
|
CreatedAt: now,
|
||||||
|
PayMethod: order.RechargeType,
|
||||||
|
ProductType: 0,
|
||||||
}).ToPayNew(ctx)
|
}).ToPayNew(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ErrorX(ctx, fmt.Sprintf("用户ID[%d] 支付方式[%s] 购买类型[%d] 产品ID[%v] 产品子ID[%v] 下单请求异常[%v]",
|
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,
|
ProgressAt: &now,
|
||||||
OID: &res.OID,
|
OID: &res.OID,
|
||||||
Mode: &res.Mode,
|
Mode: &res.Mode,
|
||||||
//Channel: &res.CID,
|
Channel: &res.CID,
|
||||||
Rate: &res.Rebate,
|
Rate: &res.Rate,
|
||||||
}
|
}
|
||||||
if err = rchgordmod.Update(nil, order.ID, set); err != nil {
|
if err = rchgordmod.Update(nil, order.ID, set); err != nil {
|
||||||
log.ErrorX(ctx, fmt.Sprintf("用户ID[%d] 支付方式[%s] 购买类型[%d] 产品ID[%v] 产品子ID[%v] 更新订单异常[%v]",
|
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 {
|
if r.ProductType == 1 {
|
||||||
return errors.New("瓦力游戏已下架")
|
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 (
|
var (
|
||||||
fn func(*db.MongoTool) error
|
fn func(*db.MongoTool) error
|
||||||
|
|||||||
+26
-7
@@ -19,6 +19,18 @@ type PayTypeParam struct {
|
|||||||
ProductType int `json:"productType"` //产品类型 0站群 1棋牌
|
ProductType int `json:"productType"` //产品类型 0站群 1棋牌
|
||||||
UserLevel int `json:"userLevel"` //限定用户层级 (0默认无等级 1充值成功过的1等级)
|
UserLevel int `json:"userLevel"` //限定用户层级 (0默认无等级 1充值成功过的1等级)
|
||||||
PlatformID string `json:"platformID"` //平台
|
PlatformID string `json:"platformID"` //平台
|
||||||
|
DistrictCode string `json:"districtCode"` //用户渠道码 支付中心据此绑定可用支付渠道
|
||||||
|
}
|
||||||
|
|
||||||
|
// BillPlatformID 账单中心平台标识
|
||||||
|
const BillPlatformID = "逼哩逼哩"
|
||||||
|
|
||||||
|
// billDevType 账单中心设备类型,非android按ios处理
|
||||||
|
func billDevType(devType string) string {
|
||||||
|
if devType != "android" {
|
||||||
|
return "ios"
|
||||||
|
}
|
||||||
|
return devType
|
||||||
}
|
}
|
||||||
|
|
||||||
type RchgType struct {
|
type RchgType struct {
|
||||||
@@ -40,13 +52,19 @@ type StdMsg struct {
|
|||||||
|
|
||||||
// GetPayType 从支付中心获取充值金额对应的充值方式
|
// GetPayType 从支付中心获取充值金额对应的充值方式
|
||||||
func GetPayType(ctx context.Context, moneys []int64, devType string, productType, userLevel int) ([]RchgType, error) {
|
func GetPayType(ctx context.Context, moneys []int64, devType string, productType, userLevel int) ([]RchgType, error) {
|
||||||
|
return GetPayTypeByDistrict(ctx, moneys, devType, productType, userLevel, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPayTypeByDistrict 从支付中心获取充值金额对应的充值方式(按用户渠道码匹配)
|
||||||
|
func GetPayTypeByDistrict(ctx context.Context, moneys []int64, devType string, productType, userLevel int, districtCode string) ([]RchgType, error) {
|
||||||
var errlog string
|
var errlog string
|
||||||
p := PayTypeParam{
|
p := PayTypeParam{
|
||||||
moneys,
|
Moneys: moneys,
|
||||||
devType,
|
DevType: billDevType(devType),
|
||||||
productType,
|
ProductType: productType,
|
||||||
userLevel,
|
UserLevel: userLevel,
|
||||||
"91PORN",
|
PlatformID: BillPlatformID,
|
||||||
|
DistrictCode: districtCode,
|
||||||
}
|
}
|
||||||
res := StdMsg{}
|
res := StdMsg{}
|
||||||
code, err := httputil.DefaultClientPostJsonWithResp(&res, p.GetURL(), nil, p.GetBody())
|
code, err := httputil.DefaultClientPostJsonWithResp(&res, p.GetURL(), nil, p.GetBody())
|
||||||
@@ -143,14 +161,15 @@ func (this *Rchg) ToPayNew(ctx context.Context) (res RchgMsg, err error) {
|
|||||||
|
|
||||||
// GetURL 获取请求地址
|
// GetURL 获取请求地址
|
||||||
func (this *Rchg) fill() {
|
func (this *Rchg) fill() {
|
||||||
this.PlatformID = "91PORN"
|
this.PlatformID = BillPlatformID
|
||||||
if this.ProductType == 0 {
|
if this.ProductType == 0 {
|
||||||
this.TransNo = RChgIDAssemble(this.TransNo)
|
this.TransNo = RChgIDAssemble(this.TransNo)
|
||||||
}
|
}
|
||||||
if this.ProductType == 1 {
|
if this.ProductType == 1 {
|
||||||
this.TransNo = RChgWLIDAssemble(this.TransNo)
|
this.TransNo = RChgWLIDAssemble(this.TransNo)
|
||||||
}
|
}
|
||||||
this.NotifyUrl = appg.Conf.URL.LocalWebUrl + RCHG_NOTIFY_URL + "bill"
|
// 回调路由 /3rd/defray/callback/rchg/:name 挂在 app 服务上
|
||||||
|
this.NotifyUrl = appg.Conf.PayCenter.CallbackUrl + RCHG_NOTIFY_URL + "bill"
|
||||||
this.PType = this.PayMethod
|
this.PType = this.PayMethod
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-54
@@ -26,14 +26,11 @@ import (
|
|||||||
|
|
||||||
var payTypeCacheGroup singleflight.Group
|
var payTypeCacheGroup singleflight.Group
|
||||||
|
|
||||||
|
// GainPayTypeReq 按金额查询支付通道(账单中心 /api/recharge/payType)
|
||||||
type GainPayTypeReq struct {
|
type GainPayTypeReq struct {
|
||||||
Time string `json:"time" bson:"time"` // 时间戳,最大长度50,必填
|
Money []string // 金额数组(元),必填
|
||||||
Sign string `json:"sign" bson:"sign"` // 签名,最大长度100,必填
|
DevType string // 设备类型 android/ios,非android按ios处理
|
||||||
MercID string `json:"mercId" bson:"mercId"` // 商户ID,最大长度50,必填
|
DistrictCode string // 用户渠道码,支付中心据此绑定可用支付渠道
|
||||||
Money []string `json:"money" bson:"money"` // 金额数组,必填
|
|
||||||
Mode string `json:"mode,omitempty"` // 支付模式,兼容商户版本迭代,传sdk表示支持sdk模式,可选
|
|
||||||
Payload string `json:"payload,omitempty"` // 备用参数:1-不匹配赔付渠道 2-空单 3-兑换划转,可选
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AllPayType struct {
|
type AllPayType struct {
|
||||||
@@ -59,7 +56,7 @@ func (in *GainPayTypeReq) GetPayTypeFromCache() (bc []AllPayType, err error) {
|
|||||||
// 金额排序
|
// 金额排序
|
||||||
sort.Strings(in.Money)
|
sort.Strings(in.Money)
|
||||||
|
|
||||||
redisKey := fmt.Sprintf("paycenter-channels:%s", strings.Join(in.Money, "-"))
|
redisKey := fmt.Sprintf("paycenter-channels:%s:%s:%s", billDevType(in.DevType), in.DistrictCode, strings.Join(in.Money, "-"))
|
||||||
value, err, _ := payTypeCacheGroup.Do(redisKey, func() (interface{}, error) {
|
value, err, _ := payTypeCacheGroup.Do(redisKey, func() (interface{}, error) {
|
||||||
str, cacheErr := appg.Redis.Get(redisKey)
|
str, cacheErr := appg.Redis.Get(redisKey)
|
||||||
if cacheErr != nil {
|
if cacheErr != nil {
|
||||||
@@ -114,47 +111,46 @@ func decodeCachedPayTypes(raw string) ([]AllPayType, error) {
|
|||||||
return nil, fmt.Errorf("json decode: %v; msgpack decode: %v", jsonErr, msgpackErr)
|
return nil, fmt.Errorf("json decode: %v; msgpack decode: %v", jsonErr, msgpackErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPayType 从支付中心获取充值金额对应的充值方式
|
// GetPayType 从账单中心获取充值金额对应的充值方式
|
||||||
func (in *GainPayTypeReq) GetPayType() ([]AllPayType, error) {
|
func (in *GainPayTypeReq) GetPayType() ([]AllPayType, error) {
|
||||||
res := GainPayTypeResp{}
|
moneys := make([]int64, 0, len(in.Money))
|
||||||
code, err := httputil.DefaultClientPostJsonWithResp(&res, in.GetURL(), nil, in.GetBody())
|
for _, m := range in.Money {
|
||||||
|
moneys = append(moneys, YuanToFen(m))
|
||||||
|
}
|
||||||
|
rchgTypes, err := GetPayTypeByDistrict(context.Background(), moneys, in.DevType, 0, 0, in.DistrictCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(fmt.Sprintf("param:%+v,get pay type in bill center failed err:%v", in, err))
|
return nil, err
|
||||||
return nil, errors.New(fmt.Sprintf("bill GetPayType requset fail \nerror:%+v\n\ndata:%+v;", err, in))
|
|
||||||
}
|
}
|
||||||
if code != http.StatusOK {
|
payTypes := make([]AllPayType, 0, len(rchgTypes))
|
||||||
log.Error(fmt.Sprintf("code:%v,get pay type response status exception", code))
|
for _, r := range rchgTypes {
|
||||||
return nil, errors.New(fmt.Sprintf("bill GetPayType response status exception;\nstatus %+v;", code))
|
payTypes = append(payTypes, r.ToAllPayType())
|
||||||
}
|
}
|
||||||
if res.Code != 200 {
|
|
||||||
log.Error(fmt.Sprintf("bill GetPayType be rejected;\n param:%+v, err:%+v:", in, res))
|
|
||||||
return nil, errors.New("bill GetPayType be rejected")
|
|
||||||
}
|
|
||||||
bytes, err := json.Marshal(res.Msg)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(fmt.Sprintf("bill payUrl urlDecode fail error:%+v;", err))
|
|
||||||
return nil, errors.New("getPayType json Marshal error")
|
|
||||||
}
|
|
||||||
var payTypes []AllPayType
|
|
||||||
if err = json.Unmarshal(bytes, &payTypes); err != nil {
|
|
||||||
log.Error(fmt.Sprintf("bill payUrl urlDecode fail error:%+v;", err))
|
|
||||||
return nil, errors.New("bill payUrl urlDecode fail error")
|
|
||||||
}
|
|
||||||
log.Debug("bill GetPayType success", log.Any("payTypeCount", len(payTypes)))
|
|
||||||
return payTypes, nil
|
return payTypes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBody 获取请求body
|
// ToAllPayType 转换为按金额分组的支付类型列表
|
||||||
func (in *GainPayTypeReq) GetBody() []byte {
|
func (r RchgType) ToAllPayType() AllPayType {
|
||||||
in.MercID = appg.Conf.PayCenter.MercID
|
res := AllPayType{
|
||||||
in.Time = Generate13DigitString()
|
Money: fmt.Sprintf("%d.%02d", r.Money/100, r.Money%100),
|
||||||
in.Sign = in.GenerateSign()
|
Types: make([]mercPayTypeInfo, 0),
|
||||||
data, err := json.Marshal(in)
|
|
||||||
if err != nil {
|
|
||||||
log.Info(fmt.Sprintf("bill GetBody json.Marshal is fail error:%+v/data:%+v", err, in))
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return data
|
enabled := []struct {
|
||||||
|
ok bool
|
||||||
|
t string
|
||||||
|
}{
|
||||||
|
{r.Alipay, Alipay},
|
||||||
|
{r.Wechat, Wechat},
|
||||||
|
{r.Union, "union"},
|
||||||
|
{r.QuickUnion, "quickUnion"},
|
||||||
|
{r.USDT, "usdt"},
|
||||||
|
{r.DaiChong, "daichong"},
|
||||||
|
}
|
||||||
|
for _, e := range enabled {
|
||||||
|
if e.ok {
|
||||||
|
res.Types = append(res.Types, mercPayTypeInfo{Name: e.t, Type: e.t})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func Generate13DigitString() string {
|
func Generate13DigitString() string {
|
||||||
@@ -169,19 +165,6 @@ func generateMD5(text string) string {
|
|||||||
return hex.EncodeToString(hash[:])
|
return hex.EncodeToString(hash[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateSign 生成加密
|
|
||||||
func (in *GainPayTypeReq) GenerateSign() string {
|
|
||||||
// 默认签名方式1: md5(value+value)
|
|
||||||
signStr := in.MercID + strings.Join(in.Money, "") + appg.Conf.PayCenter.MercSecret
|
|
||||||
sign := generateMD5(signStr)
|
|
||||||
return sign
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetURL 获取请求地址
|
|
||||||
func (in *GainPayTypeReq) GetURL() string {
|
|
||||||
return appg.Conf.PayCenter.ApiUrl + "/api/shark/getPayType"
|
|
||||||
}
|
|
||||||
|
|
||||||
type Recharge struct {
|
type Recharge struct {
|
||||||
Time string `json:"time" bson:"time"` // 时间戳,最大长度50,必填
|
Time string `json:"time" bson:"time"` // 时间戳,最大长度50,必填
|
||||||
Sign string `json:"sign" bson:"sign"` // 签名,最大长度100,必填
|
Sign string `json:"sign" bson:"sign"` // 签名,最大长度100,必填
|
||||||
|
|||||||
Reference in New Issue
Block a user