Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
package rchgordmod
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type UpserSelector struct {
UID *uint64 `json:"uid,omitempty" bson:"uid,omitempty"` //用户id
OID *string `json:"oid,omitempty" bson:"oid,omitempty"` //支付平台订单号
TraderId *string `json:"traderId,omitempty" bson:"traderId,omitempty"` //商户ID
UserIP *string `json:"userIp,omitempty" bson:"userIp,omitempty"` //用户IP
DevID *string `json:"devID,omitempty" bson:"devID,omitempty"` //设备id
Name *string `json:"name,omitempty" bson:"name,omitempty"` //用户名称
Tel *string `json:"tel,omitempty" bson:"tel,omitempty"` //用户手机号
DevType *string `json:"devType,omitempty" bson:"devType,omitempty"` //设备系统类型 ios pc android
Amount int64 `json:"amount" bson:"amount"` //金币数量
Money *int64 `json:"money,omitempty" bson:"money,omitempty"` //充值金额 单位角
PayMoney *int64 `json:"payMoney,omitempty" bson:"payMoney,omitempty"` //实际到账金额
RechargeType *string `json:"rechargeType,omitempty" bson:"rechargeType,omitempty"` //充值类型
Channel *string `json:"channel,omitempty" bson:"channel,omitempty"` //渠道类型 鲨鱼 金鱼 代充
Status *int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
StatusDesc *string `json:"statusDesc,omitempty" bson:"statusDesc,omitempty"` //状态描述
NotifyTime *int64 `json:"notifyTime,omitempty" bson:"notifyTime,omitempty"` //第三方回调的时间
NotifyStatus *int `json:"notifyStatus,omitempty" bson:"notifyStatus,omitempty"` //通知第三方上分情况状态
LockStatus *int `json:"lockStatus,omitempty" bson:"lockStatus,omitempty"` //订单操作锁定状态 用户订单更新操作
FailureAt *time.Time `json:"failureAt,omitempty" bson:"failureAt,omitempty"` //回调失败时间
SuccessAt *time.Time `json:"successAt,omitempty" bson:"successAt,omitempty"` //回调成功时间
PaymentAt *time.Time `json:"paymentAt,omitempty" bson:"paymentAt,omitempty"` //支付时间
UpdatedAt *time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` //刷新时间
ProductType *int `json:"productType,omitempty" bson:"productType,omitempty"` //0站群 1棋牌
ChanShareMod *int `json:"chanShareMod,omitempty" bson:"chanShareMod,omitempty"` //渠道分成类型 0 不分成 (默认) 1 金币充值分成 2正常vip消费分成
DiscDoc DiscDoc `bson:",inline"`
}
type ReplaceEditSelector struct {
OID *string `json:"oid,omitempty" bson:"oid,omitempty"` //支付平台订单号
PayMoney *int64 `json:"payMoney,omitempty" bson:"payMoney,omitempty"` //实际到账金额
Status *int `json:"status" bson:"status,omitempty"` //1进行中 2付款失败 3付款成功 4已经退款
StatusDesc *string `json:"statusDesc,omitempty" bson:"statusDesc,omitempty"` //状态描述
LockStatus *int `json:"lockStatus,omitempty" bson:"lockStatus,omitempty"` //订单操作锁定状态 用户订单更新操作
NotifyStatus *int `json:"notifyStatus,omitempty" bson:"notifyStatus,omitempty"` //通知第三方上分情况状态
Remark *string `json:"remark,omitempty" bson:"remark,omitempty"` //备注
VipID primitive.ObjectID `json:"vipID,omitempty" bson:"vipID,omitempty"` //是否是vip冲 hi
ChanShareMod *int `json:"chanShareMod,omitempty" bson:"chanShareMod,omitempty"` //渠道分成类型 0 不分成 (默认) 1 金币充值分成 2正常vip消费分成
ProgressAt *time.Time `json:"progressAt,omitempty" bson:"progressAt,omitempty"` //第三方下单成功时间
FailureAt *time.Time `json:"failureAt,omitempty" bson:"failureAt,omitempty"` //回调失败时间
SuccessAt *time.Time `json:"successAt,omitempty" bson:"successAt,omitempty"` //回调成功时间
PaymentAt *time.Time `json:"paymentAt,omitempty" bson:"paymentAt,omitempty"` //支付时间
UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` //刷新时间
ProductChildType *ChildType `json:"productChildType" bson:"productChildType"` //产品子类型
ServiceID primitive.ObjectID `json:"serviceId" bson:"serviceId"` //裸聊服务ID
ProductID primitive.ObjectID `json:"productID" bson:"productID"` //产品ID
}
type EditSelector struct {
OID *string `json:"oid,omitempty" bson:"oid,omitempty"` //支付平台订单号
PayMoney *int64 `json:"payMoney,omitempty" bson:"payMoney,omitempty"` //实际到账金额
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
StatusDesc *string `json:"statusDesc,omitempty" bson:"statusDesc,omitempty"` //状态描述
NotifyStatus *int `json:"notifyStatus,omitempty" bson:"notifyStatus,omitempty"` //通知第三方上分情况状态
ProgressAt *time.Time `json:"progressAt,omitempty" bson:"progressAt,omitempty"` //第三方下单成功时间
FailureAt *time.Time `json:"failureAt,omitempty" bson:"failureAt,omitempty"` //回调失败时间
SuccessAt *time.Time `json:"successAt,omitempty" bson:"successAt,omitempty"` //回调成功时间
PaymentAt *time.Time `json:"paymentAt,omitempty" bson:"paymentAt,omitempty"` //支付时间
RefundAt *time.Time `json:"refundAt,omitempty" bson:"refundAt,omitempty"` //退款时间
UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` //刷新时间
Mode *string `json:"mode,omitempty" bson:"mode,omitempty"` //支付模式
Channel *string `json:"channel,omitempty" bson:"channel,omitempty"` //渠道类型 鲨鱼 金鱼 代充
Rate *string `json:"rate,omitempty" bson:"rate,omitempty"` //渠道费率
ProductType *int `json:"productType,omitempty" bson:"productType,omitempty"` //支付产品类型 0 站群 1 棋牌
ChanShareMod *int `json:"chanShareMod,omitempty" bson:"chanShareMod,omitempty"` //渠道分成类型
Remark *string `json:"remark,omitempty" bson:"remark,omitempty"` //备注
}
type RechargToPayP struct {
RechargeType string `json:"rechargeType" binding:"required"` //充值类型
ProductID primitive.ObjectID `json:"productID"` //充值金币类型id
VipID primitive.ObjectID `json:"vipID"` //是否是vip冲 hi
ProductType int `json:"productType"` //充值产品 0 站群 1 棋牌
Money int64 `json:"money"` //金额
ProductChildType ChildType `json:"productChildType"` //产品子类型
ServiceID primitive.ObjectID `json:"serviceId"` //裸聊服务ID
}
// RechargeOrder 账户充值流水 App返回给前端
type RechargeOrderAppRes struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
OID string `json:"oid" bson:"oid"` //支付平台订单号
UID uint64 `json:"uid" bson:"uid"` //用户id
Name string `json:"name" bson:"name"` //用户名称
Tel string `json:"tel" bson:"tel"` //用户手机号
Money int64 `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
PayMoney int64 `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
StatusDesc string `json:"statusDesc" bson:"statusDesc"` //状态描述
Remark string `json:"remark" bson:"remark"` //备注
FailureAt time.Time `json:"failureAt" bson:"failureAt"` //回调失败时间
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
}
+162
View File
@@ -0,0 +1,162 @@
package rchgordmod
import (
"strings"
"time"
"91porn-server/common/pageopt"
"91porn-server/common/ysinterface/disc"
)
type DistrictStatKey struct {
DiscSeqe `bson:",inline"` //商区码
DevType string `bson:"devType"` //系统类型 iOS Android
}
func (d DistrictStatKey) GetDiscCode() string {
return d.DistrictCode
}
func (d DistrictStatKey) GetPromSeqe() string {
return d.PromSeqe
}
func (d DistrictStatKey) GetSysType() string {
return d.DevType
}
func (d DistrictStatKey) String() string {
if d.DiscSeqe.String() == "" {
return ""
}
return strings.ToUpper(strings.Join([]string{d.DiscSeqe.String(), d.DevType}, "-"))
}
type DistrictStater = disc.DistrictStater
// DistrictOrderCountMap districtCode->订单数 map
func DistrictOrderCountMap(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
filter := pageopt.MergeM(mats)
list := []DistrictStatKey{}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[DistrictStater]int64, len(list))
for _, v := range list {
if v.String() != "" {
m[v] += 1
}
}
return m, nil
}
// DistrictOrderMoneyMap districtCode->完成订单数 map
func DistrictOrderMoneyMap(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
filter := pageopt.MergeM(mats)
var list []struct {
DistrictStatKey `bson:",inline"` //商区码
Money int64 `bson:"money"` //充值金额 订单金额 李秋山确认
}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[DistrictStater]int64, len(list))
for _, v := range list {
if v.String() != "" {
m[v.DistrictStatKey] += v.Money
}
}
return m, nil
}
// DistrictCompleteOrderCountMap districtCode->订单金额 map
func DistrictCompleteOrderCountMap(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
filter := pageopt.MergeM(mats)
list := []DistrictStatKey{}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[DistrictStater]int64, len(list))
for _, v := range list {
if v.String() != "" {
m[v] += 1
}
}
return m, nil
}
// DistrictCompleteOrderPayMoneyMap districtCode->完成订单的用户实际支付金额 map
func DistrictCompleteOrderPayMoneyMap(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
filter := pageopt.MergeM(mats)
var list []struct {
DistrictStatKey `bson:",inline"` //商区码
PayMoney int64 `bson:"payMoney"` //实际到账金额 实际支付金额 李秋山确认
}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[DistrictStater]int64, len(list))
for _, v := range list {
if v.String() != "" {
m[v.DistrictStatKey] += v.PayMoney
}
}
return m, nil
}
// DiscCompleteOrderUIDSMap districtCode->完成订单的用户列表 map key:District
func DiscCompleteOrderUIDSMap(start, end time.Time, mats ...Matcher) (map[DistrictStater][]uint64, error) {
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
filter := pageopt.MergeM(mats)
var list []struct {
DistrictCode string `json:"districtCode" bson:"districtCode"` //商区码
UID uint64 `bson:"uid"` //uid
}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[DistrictStater][]uint64, len(list))
for _, v := range list {
key := DistrictStatKey{
DiscSeqe: DiscSeqe{DistrictCode: v.DistrictCode},
}
if key.String() != "" {
m[key] = append(m[key], v.UID)
}
}
return m, nil
}
// DistrictCompleteOrderUIDSMap districtCode->完成订单的用户列表 map key:DiscSeqeSystem
func DistrictCompleteOrderUIDSMap(start, end time.Time, mats ...Matcher) (map[DistrictStater][]uint64, error) {
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
filter := pageopt.MergeM(mats)
var list []struct {
DistrictStatKey `bson:",inline"` //商区码
UID uint64 `bson:"uid"` //uid
}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[DistrictStater][]uint64, len(list))
for _, v := range list {
if v.String() != "" {
m[v.DistrictStatKey] = append(m[v.DistrictStatKey], v.UID)
}
}
return m, nil
}
// 时间内购买VIP次数
func CompleteOrderCountByDiscCode(start, end time.Time, discCode string) (int64, error) {
mats := []Matcher{
(&SuccessAtGTEAndLTMatch{GTE: &start, LT: &end}).New(),
(&DistrictCodeMatch{DistrictCode: &discCode}).New(),
}
filter := pageopt.MergeM(mats)
return coll(nil).Count(filter)
}
+204
View File
@@ -0,0 +1,204 @@
package rchgordmod
import (
"time"
"91porn-server/common/log"
"91porn-server/common/pageopt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Matcher = pageopt.Matcher
// ChannelMatch
type ChannelMatch struct {
Channel *string
}
func (c *ChannelMatch) New() Matcher {
return pageopt.NewAssignMatch("channel", c.Channel)
}
// StatusMatch
type StatusMatch struct {
Status *int
}
func (s *StatusMatch) New() Matcher {
return pageopt.NewAssignMatch("status", s.Status)
}
// IDMatch
type IDMatch = pageopt.IDMatch
// UIDMatch
type UIDMatch = pageopt.UIDMatch
// UIDInMatch
type UIDInMatch = pageopt.UIDInMatch
// RechargeTypeMatch
type RechargeTypeMatch struct {
RechargeType *string
}
func (s *RechargeTypeMatch) New() Matcher {
return pageopt.NewAssignMatch("rechargeType", s.RechargeType)
}
// RechargeTypeINMatch
type RechargeTypeINMatch struct {
RechargeTypes []RechType
}
func (s *RechargeTypeINMatch) New() Matcher {
return pageopt.NewInMatch("rechargeType", s.RechargeTypes)
}
// DistrictCodeMatch
type DistrictCodeMatch struct {
DistrictCode *string
}
func (s *DistrictCodeMatch) New() Matcher {
return pageopt.NewAssignMatch("districtCode", s.DistrictCode)
}
// PromSeqeMatch
type PromSeqeMatch struct {
PromSeqe *string
}
func (s *PromSeqeMatch) New() Matcher {
return pageopt.NewAssignMatch("promSeqe", s.PromSeqe)
}
// IsDirectMatch
type IsDirectMatch struct {
IsDirect *bool
}
func (b *IsDirectMatch) New() Matcher {
return pageopt.NewAssignMatch("isDirect", b.IsDirect)
}
type DevTypeMatch struct {
DevType *string
}
func (d *DevTypeMatch) New() Matcher {
return pageopt.NewAssignMatch("devType", d.DevType)
}
// StatusInMatch
type StatusInMatch struct {
Status []int
}
func (d *StatusInMatch) New() Matcher {
return pageopt.NewInMatch("status", d.Status)
}
// NotifyStatusMatch
type NotifyStatusMatch struct {
NotifyStatus []int
}
func (d *NotifyStatusMatch) New() Matcher {
return pageopt.NewInMatch("notifyStatus", d.NotifyStatus)
}
// ProgressAtGTEAndLTMatch
type ProgressAtGTEAndLTMatch struct {
GTE *time.Time
LT *time.Time
}
func (s *ProgressAtGTEAndLTMatch) New() Matcher {
return pageopt.NewGTEAndLTMatch("progressAt", s.GTE, s.LT)
}
// FailureAtGTEAndLTMatch
type FailureAtGTEAndLTMatch struct {
GTE *time.Time
LT *time.Time
}
func (s *FailureAtGTEAndLTMatch) New() Matcher {
return pageopt.NewGTEAndLTMatch("failureAt", s.GTE, s.LT)
}
// SuccessAtGTEAndLTMatch
type SuccessAtGTEAndLTMatch struct {
GTE *time.Time
LT *time.Time
}
func (s *SuccessAtGTEAndLTMatch) New() Matcher {
return pageopt.NewGTEAndLTMatch("successAt", s.GTE, s.LT)
}
//PaymentAtGTEAndLTMatch
//type PaymentAtGTEAndLTMatch struct {
// GTE *time.Time
// LT *time.Time
//}
//
//func (s *PaymentAtGTEAndLTMatch) New() Matcher {
// return pageopt.NewGTEAndLTMatch("paymentAt", s.GTE, s.LT)
//}
// CreatedAtGTEAndLTMatch
type CreatedAtGTEAndLTMatch = pageopt.CreatedAtGTEAndLTMatch
// CreatedAtLTMatch
type CreatedAtLTMatch = pageopt.CreatedAtLTMatch
type Sort = bson.D
type M = bson.M
var Sort_CreatedAt_n1 = Sort{{Key: "createdAt", Value: -1}}
type RechargeOrderSlice []*RechargeOrder
func (this RechargeOrderSlice) Map() map[primitive.ObjectID]*RechargeOrder {
m := map[primitive.ObjectID]*RechargeOrder{}
for _, v := range this {
m[v.ID] = v
}
return m
}
func List(sort Sort, skip, limit *int64, matchers ...Matcher) (RechargeOrderSlice, error) {
filter := pageopt.MergeM(matchers)
opt := (&options.FindOptions{})
if len(sort) != 0 {
opt.SetSort(sort)
}
if skip != nil {
opt.SetSkip(*skip)
}
if limit != nil {
opt.SetLimit(*limit)
}
list := RechargeOrderSlice{}
if err := coll(nil).Find(&list, filter, opt); err != nil {
log.Error("rchgordmod List error", log.E(err))
return nil, err
}
return list, nil
}
func Count(matchers ...Matcher) (int64, error) {
filter := pageopt.MergeM(matchers)
count, err := coll(nil).Count(filter)
if err != nil {
log.Error("rchgordmod Count error", log.E(err))
return 0, err
}
return count, nil
}
+775
View File
@@ -0,0 +1,775 @@
/*
* @Description: 账户充值流水
* @Author: your name
* @Date: 2019-08-29 20:45:27
* @LastEditTime: 2019-08-30 13:44:36
* @LastEditors: Please set LastEditors
*/
package rchgordmod
import (
"context"
"errors"
"fmt"
"time"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/pageopt"
"91porn-server/common/timeutil"
"91porn-server/common/timeutil/timerange"
"91porn-server/models"
"91porn-server/models/v/usermod"
"github.com/shopspring/decimal"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
const table = models.RechargeOrder
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// InitARDIndex 设置账户充值流水表索引
func initIndex() {
many := []mongo.IndexModel{ //batch set indexes //value is the type 1 or -1
{
Keys: bson.D{{Key: "oid", Value: 1}},
// Options: options.Index().SetUnique(true).SetPartialFilterExpression(bson.M{"oid": bson.M{"$gt": ""}}),
},
{
Keys: bson.D{{Key: "channel", Value: 1}},
},
{
Keys: bson.D{{Key: "createdAt", Value: 1}},
},
{
Keys: bson.D{{Key: "updatedAt", Value: 1}},
},
{
Keys: bson.D{{Key: "progressAt", Value: 1}},
},
{
Keys: bson.D{{Key: "paymentAt", Value: 1}},
},
{
Keys: bson.D{{Key: "failureAt", Value: 1}},
},
{
Keys: bson.D{{Key: "successAt", Value: 1}},
},
{
Keys: bson.D{{Key: "districtCode", Value: 1}, {Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "isDirect", Value: 1}, {Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "traderId", Value: 1}},
},
{
Keys: bson.D{{Key: "rechargeType", Value: 1}, {Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "status", Value: 1}, {Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "devType", Value: 1}, {Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "productType", Value: 1}, {Key: "status", Value: 1}},
},
{
Keys: bson.D{{Key: "deductType", Value: 1}, {Key: "createdAt", Value: -1}},
Options: options.Index().SetSparse(true),
},
{
Keys: bson.D{
{Key: "experimentId", Value: 1},
{Key: "experimentVariant", Value: 1},
{Key: "productID", Value: 1},
{Key: "status", Value: 1},
},
Options: options.Index().
SetName("vip_experiment_order_statistics").
SetPartialFilterExpression(bson.M{"experimentId": bson.M{"$gt": ""}}),
},
{
Keys: bson.D{{Key: "sourcePage", Value: 1}, {Key: "createdAt", Value: -1}},
Options: options.Index().
SetName("order_source_created_at").
SetPartialFilterExpression(bson.M{"sourcePage": bson.M{"$gt": ""}}),
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("RechageOrderIndex err+%v", err))
}
}
// InsertRechargeOrder 插入一条充值订单
func InsertRechargeOrder(a *RechargeOrder) (err error) {
a.CreatedAt = time.Now()
a.UpdatedAt = a.CreatedAt
res, err := coll(nil).InsertOne(a)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertRechargeOrder", table, "InsertOne", err))
return
}
a.ID = res.InsertedID.(primitive.ObjectID)
return
}
// FindRechargesOrders 查询充值订单
func FindRechargesOrders(cond bson.M, opts *options.FindOptions) (total int64, data []*RechargeOrder, err error) {
data = make([]*RechargeOrder, 0)
if err = coll(nil).Find(&data, cond, opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargesOrders", table, "Find", err),
log.Any("cond", cond),
)
return
}
total, err = coll(nil).Count(cond)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargesOrders", table, "Count", err),
log.Any("cond", cond),
)
return
}
return
}
func FindOne(t *db.MongoTool, cond bson.M, opts ...*options.FindOneOptions) (data *RechargeOrder, err error) {
if err = coll(nil).FindOne(&data, cond, opts...); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindOne", table, "FindOne", err),
log.Any("cond", cond),
)
return
}
return
}
// FindRechargesOrders 查询充值订单
func FindMyOrders(uid, pgSz, pgCt uint64) (total int64, data []*RechargeOrder, hasNext bool, err error) {
data = make([]*RechargeOrder, 0)
opts := options.FindOptions{}
skip := int64((pgCt - 1) * pgSz)
limit := int64(pgSz + 1)
opts.Skip = &skip
opts.Limit = &limit
opts.SetSort(bson.D{{Key: "createdAt", Value: -1}})
startTime := timeutil.BeforeMinute(20)
cond := bson.M{
"$or": []bson.M{
{"uid": uid, "status": bson.M{"$gt": Processing}},
{"uid": uid, "status": bson.M{"$lte": Processing}, "createdAt": bson.M{"$gte": startTime}},
},
}
if err = coll(nil).Find(&data, cond, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMyOrders", table, "Find", err),
log.Any("uid", uid),
log.Any("pgSz", pgSz),
log.Any("pgCt", pgCt),
)
return
}
total, err = coll(nil).Count(cond)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMyOrders", table, "Count", err),
log.Any("uid", uid),
log.Any("pgSz", pgSz),
log.Any("pgCt", pgCt),
)
}
if len(data) > int(pgSz) {
hasNext = true
data = data[:pgSz]
}
return
}
// Update 修改订单
func UpdateRechargeOrder(id string, set RechargeUpdateReq) error {
set.UpdatedAt = time.Now()
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateRechargeOrder", table, "ObjectIDFromHex", err),
log.Any("id", id),
log.Any("set", set),
)
return err
}
if _, err = coll(nil).UpdateOne(bson.M{"_id": objID}, bson.M{"$set": set}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateRechargeOrder", table, "UpdateOne", err),
log.Any("id", id),
log.Any("set", set),
)
return err
}
return nil
}
// CallBackModifyWithProcessing 回调修改订单
func CallBackModifyWithProcessing(ctx context.Context, t *db.MongoTool, id primitive.ObjectID, set EditSelector) error {
set.UpdatedAt = time.Now()
if _, err := coll(t).UpdateOne(bson.M{"_id": id, "status": Processing}, bson.M{"$set": set}); err != nil {
log.WarnX(ctx, fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateOne", err),
log.Any("id", id),
log.Any("set", set),
)
return err
}
return nil
}
// Update 修改订单
func Update(t *db.MongoTool, id primitive.ObjectID, set EditSelector) error {
set.UpdatedAt = time.Now()
if _, err := coll(t).UpdateOne(bson.M{"_id": id}, bson.M{"$set": set}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateOne", err),
log.Any("id", id),
log.Any("set", set),
)
return err
}
return nil
}
// 根据第三方订单号修改
func UpdateBaseOnOidAndStatus(t *db.MongoTool, oid string, status int, set ReplaceEditSelector) error {
set.UpdatedAt = time.Now()
if _, err := coll(t).UpdateOne(bson.M{"oid": oid, "status": status}, bson.M{"$set": set}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateBaseOnOid", table, "UpdateOne", err),
log.Any("id", oid),
log.Any("set", set),
)
return err
}
return nil
}
func UpdateBaseOnOid(t *db.MongoTool, oid string, set ReplaceEditSelector) error {
set.UpdatedAt = time.Now()
if _, err := coll(t).UpdateOne(bson.M{"oid": oid}, bson.M{"$set": set}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateBaseOnOid", table, "UpdateOne", err),
log.Any("id", oid),
log.Any("set", set),
)
return err
}
return nil
}
// Upsert 新增或修改订单
func Upsert(t *db.MongoTool, oid string, upsert UpserSelector) (id primitive.ObjectID, err error) {
updatedAt := time.Now()
upsert.UpdatedAt = &updatedAt
upertRest, err := coll(t).UpsertOne(bson.M{"oid": oid}, bson.M{"$setOnInsert": bson.M{"createdAt": time.Now()}, "$set": upsert})
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Upsert", table, "UpsertOne", err),
log.Any("oid", oid),
log.Any("upsert", upsert),
)
}
if tid, ok := upertRest.UpsertedID.(primitive.ObjectID); ok {
id = tid
}
return
}
// FindRechargeByID 根据订单号查询订单
func FindRechargeOrderByID(id string) (r RechargeOrder, err error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargeOrderByID", table, "ObjectIDFromHex", err),
log.Any("id", id),
)
return
}
if err = coll(nil).FindOne(&r, bson.M{"_id": objID}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargeOrderByID", table, "FindOne", err),
log.Any("objID", objID),
)
}
return
}
// FindRechargeByID 根据第三方订单号查询订单
func FindRechargeOrderByThirdOrderId(oid string) (r RechargeOrder, err error) {
if err = coll(nil).FindOne(&r, bson.M{"oid": oid}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargeOrderByID", table, "FindOne", err),
log.Any("objID", oid),
)
}
return
}
// FindRechargeByIDForApp 根据第三方订单号查询订单ForApp
func FindRechargeOrderByThirdOrderIdForApp(oid string) (r *RechargeOrderAppRes, err error) {
if err = coll(nil).FindOne(&r, bson.M{"oid": oid}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargeOrderByThirdOrderIdForApp", table, "FindOne", err),
log.Any("objID", oid),
)
}
return
}
// TotalMoney 统计总订单金额
func TotalMoney(matchers ...Matcher) (int64, error) {
var ret struct {
Money int64 `bson:"money"` //充值金额 订单金额 李秋山确认
}
filter := []bson.M{
{
"$match": pageopt.MergeM(matchers),
},
{
"$group": bson.M{
"_id": nil,
"money": bson.M{"$sum": "$money"},
},
},
}
if err := coll(nil).AggregateDecode(&ret, filter); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UsersTotalRecharge", table, "Aggregate", err),
log.Any("matchers", matchers),
)
return 0, err
}
return ret.Money, nil
}
// GetSuccessOrderUIDListByTime
func GetSuccessOrderUIDListByTime(start time.Time, end time.Time) ([]uint64, error) {
filter := (&SuccessAtGTEAndLTMatch{&start, &end}).New().Filter()
list := make([]struct {
UID uint64 `bson:"uid"`
}, 0)
if err := coll(nil).Find(&list, filter); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetSuccessOrderUIDListByTime", table, "Find", err),
log.Any("start", start),
log.Any("end", end),
)
return nil, err
}
uidList := make([]uint64, len(list))
for i, v := range list {
uidList[i] = v.UID
}
return uidList, nil
}
// 根据uid获取用户的成功订单
func GetSuccessOrderUidList(uid, pageSize, pageNum uint64) (total int64, data []RechargeOrder, hasNext bool, err error) {
filter := bson.M{"uid": uid}
skip := int64((pageNum - 1) * pageSize)
limit := int64(pageSize)
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
Sort: bson.D{{Key: "createdAt", Value: -1}},
}
if err = coll(nil).Find(&data, filter, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMyOrders", table, "Find", err),
log.Any("uid", uid),
log.Any("pgSz", pageSize),
log.Any("pgCt", pageNum),
)
return
}
total, err = coll(nil).Count(filter)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMyOrders", table, "Count", err),
log.Any("uid", uid),
log.Any("pgSz", pageSize),
log.Any("pgCt", pageNum),
)
}
return
}
// GetNewAndRechargeUIDSByTime 新增并充值uid List
func GetNewAndRechargeUIDSByTime(createStart, createEnd, recStart, recEnd time.Time) ([]uint64, error) {
createUIDList, err := usermod.UIDListByCreateTime(createStart, createEnd)
if err != nil {
return nil, err
}
filter := (&SuccessAtGTEAndLTMatch{&recStart, &recEnd}).New().Filter()
recList := make([]struct {
UID uint64 `bson:"uid"`
}, 0)
if err = coll(nil).Find(&recList, filter); err != nil {
return nil, err
}
//充值用户 Map
recUserMap := make(map[uint64]byte, len(recList))
for _, rec := range recList {
recUserMap[rec.UID] = 1
}
uidList := make([]uint64, 0, len(recUserMap))
for _, uid := range createUIDList {
if _, ok := recUserMap[uid]; ok {
uidList = append(uidList, uid)
}
}
return uidList, nil
}
// GetChannelNewAndRechargeUIDSMapByTime 渠道新增并充值用户映射
func GetChannelNewAndRechargeUIDSMapByTime(start time.Time, end time.Time) (map[string][]uint64, error) {
creatUserStartTime := timerange.LocDayRange(start).Head
creatUserEndTime := timerange.LocDayRange(end).Tail
chMap, err := usermod.ChannelMapByCreateTime(creatUserStartTime, creatUserEndTime)
if err != nil {
return nil, err
}
filter := (&SuccessAtGTEAndLTMatch{&start, &end}).New().Filter()
list := make([]struct {
UID uint64 `bson:"uid"`
}, 0)
if err = coll(nil).Find(&list, filter); err != nil {
return nil, err
}
recUIDMap := make(map[uint64]byte, len(list))
for _, v := range list {
recUIDMap[v.UID] = 1
}
ret := make(map[string][]uint64)
for uid, channel := range chMap {
if _, ok := recUIDMap[uid]; ok {
ret[channel] = append(ret[channel], uid)
}
}
return ret, nil
}
// GetChannelNewAndRechargeAmountMapByTime 渠道新增并充值金额映射
func GetChannelNewAndRechargeAmountMapByTime(start time.Time, end time.Time) (map[string]int64, error) {
creatUserStartTime := timerange.LocDayRange(start).Head
creatUserEndTime := timerange.LocDayRange(end).Tail
chMap, err := usermod.ChannelMapByCreateTime(creatUserStartTime, creatUserEndTime)
if err != nil {
return nil, err
}
filter := (&SuccessAtGTEAndLTMatch{GTE: &start, LT: &end}).New().Filter()
list := make([]struct {
UID uint64 `bson:"uid"`
Money int64 `bson:"money"`
}, 0)
if err = coll(nil).Find(&list, filter); err != nil {
return nil, err
}
moneyMap := make(map[uint64]int64, len(list))
for _, v := range list {
moneyMap[v.UID] += v.Money
}
ret := make(map[string]int64)
for uid, channel := range chMap {
money := moneyMap[uid]
ret[channel] += money
}
return ret, nil
}
// OnlineRechargeAmount OnlineRechargeAmount
func RechargeAmount(start time.Time, end time.Time, mats ...Matcher) (int64, error) {
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
filter := pageopt.MergeM(mats)
list := make([]struct {
Money int64 `bson:"money"`
}, 0)
if err := coll(nil).Find(&list, filter); err != nil {
return 0, err
}
var totalMoney int64
for _, v := range list {
totalMoney += v.Money
}
return totalMoney, nil
}
// ChannelOrderCountMap channel->订单数 map
func ChannelOrderCountMap(start, end time.Time) (map[string]int64, error) {
filter := (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New().Filter()
var list []struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[string]int64, len(list))
for _, v := range list {
m[v.Channel] += 1
}
return m, nil
}
// ChannelCompleteOrderCountMap channel->完成订单数 map
func ChannelCompleteOrderCountMap(start, end time.Time) (map[string]int64, error) {
filter := (&SuccessAtGTEAndLTMatch{&start, &end}).New().Filter()
var list []struct {
ID primitive.ObjectID `bson:"_id,omitempty"` //流水id
Channel string `bson:"channel"` //渠道类型 鲨鱼 金鱼
}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[string]int64, len(list))
for _, v := range list {
m[v.Channel] += 1
}
return m, nil
}
// ChannelOrderMoneyMap channel->订单金额 map
func ChannelOrderMoneyMap(start, end time.Time) (map[string]int64, error) {
filter := (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New().Filter()
var list []struct {
Channel string `bson:"channel"` //渠道类型 鲨鱼 金鱼
Money int64 `bson:"money"` //充值金额 订单金额 李秋山确认
}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[string]int64, len(list))
for _, v := range list {
m[v.Channel] += v.Money
}
return m, nil
}
// ChannelCompleteOrderPayMoneyMap channel->完成订单的用户实际支付金额 map
func ChannelCompleteOrderPayMoneyMap(start, end time.Time) (map[string]int64, error) {
filter := (&SuccessAtGTEAndLTMatch{&start, &end}).New().Filter()
var list []struct {
Channel string `bson:"channel"` //渠道类型 鲨鱼 金鱼
PayMoney int64 `bson:"payMoney"` //实际到账金额 实际支付金额 李秋山确认
}
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
m := make(map[string]int64, len(list))
for _, v := range list {
m[v.Channel] += v.PayMoney
}
return m, nil
}
var ChannelPaymentOrderCountMap = ChannelCompleteOrderCountMap
var ChannelPaymentMoneyMap = ChannelCompleteOrderPayMoneyMap
// SuccessRateMap 每小时成功率
func SuccessRateMap(channel string, start, end time.Time, scaleMinute int64) (map[int64]float64, error) {
var list []struct {
CreatedAt time.Time `bson:"createdAt"` //创建时间
Status int `bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
}
matList := []pageopt.Matcher{
(&ChannelMatch{&channel}).New(),
(&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New(),
}
filter := pageopt.MergeM(matList)
opt := (&options.FindOptions{}).SetProjection(M{
"createdAt": 1,
"status": 1,
})
if err := coll(nil).Find(&list, filter, opt); err != nil {
return nil, err
}
sucOrdCountMap := make(map[int64]int64)
orderCountMap := make(map[int64]int64)
successRateMap := make(map[int64]float64)
tempTime := start
for end.After(tempTime) {
tim := timerange.RecentMinute(tempTime, scaleMinute)
p := tim.Unix()
sucOrdCountMap[p] = 0
orderCountMap[p] = 0
successRateMap[p] = 0.0
tempTime = tempTime.Add(time.Duration(scaleMinute) * time.Minute)
}
for _, v := range list {
tim := timerange.RecentMinute(v.CreatedAt, scaleMinute)
p := tim.Unix()
if v.Status == SUCCESS {
sucOrdCountMap[p] += 1
}
orderCountMap[p] += 1
}
lastTime := end
if len(list) > 0 {
lastTime = list[len(list)-1].CreatedAt
}
tempTime = start
for lastTime.After(tempTime) {
tim := timerange.RecentMinute(tempTime, scaleMinute)
p := tim.Unix()
if orderCountMap[p] != 0 {
successRateMap[p] = float64(int(float64(sucOrdCountMap[p])/float64(orderCountMap[p])*1000)) / 10
}
tempTime = tempTime.Add(time.Duration(scaleMinute) * time.Minute)
}
return successRateMap, nil
}
func GetSuccessRechargeCountMapByHour(discCode string, start, end time.Time, mats ...Matcher) ([]int, map[int]int64, int64, error) {
mats = append(mats,
(&DistrictCodeMatch{&discCode}).New(),
(&SuccessAtGTEAndLTMatch{&start, &end}).New())
filter := pageopt.MergeM(mats)
opt := (&options.FindOptions{}).SetProjection(M{
"successAt": 1,
})
var list []struct {
SuccessAt time.Time `bson:"successAt"` //创建时间
}
if err := coll(nil).Find(&list, filter, opt); err != nil {
log.Error("rchgordmod GetRechargeCountMapByHour error", log.E(err))
return nil, nil, 0, err
}
hs := []int{}
m := make(map[int]int64)
startH := start.Hour()
lastH := end.Hour() + (end.Day()-start.Day())*24
for i := startH; i <= lastH; i++ {
hs = append(hs, i)
m[i] = 0
}
var total int64
for _, v := range list {
hour := v.SuccessAt.Hour() + (v.SuccessAt.Day()-start.Day())*24
m[hour] += 1
total++
}
return hs, m, total, nil
}
func UpRechOrder(mt *db.MongoTool, tradeNo string, oid string, amount int64, progressAt time.Time) error {
id, _ := primitive.ObjectIDFromHex(tradeNo)
c, err := coll(nil).Count(bson.M{"_id": id})
if err != nil {
return nil
}
if c <= 0 {
return errors.New("tradeNo不存在")
}
tStr := time.Now().Local()
filter := bson.M{"_id": id, "status": Processing}
mur, err := coll(mt).UpdateOne(filter,
bson.M{"$set": bson.M{
"status": SUCCESS,
"statusDesc": "success",
"oid": oid,
"payMoney": amount,
"updatedAt": tStr,
"progressAt": progressAt,
"successAt": progressAt,
"paymentAt": progressAt,
/*"finishedAt": tStr*/}})
if err != nil {
log.Warn("transplat:UpRechOrder rchgOderColl.UpdateOne failed", log.E(err), log.Any("filter", filter))
return err
}
if mur.ModifiedCount != 1 {
return errors.New("UpdateErr")
}
return nil
}
// 获取用户昨日棋牌充值金额
func GetUserChessSuccessOrderAmout(uid uint64, now time.Time) (int64, error) {
/** TODO: 统计用户昨日棋牌充值总金额
查询条件
1.指定用户
2.棋牌充值
3.成功订单
4.订单时间(大于等于昨日凌晨时间;小于今日凌晨时间)
*/
match := bson.M{"uid": uid,
"productType": 1,
"status": 3,
"paymentAt": bson.M{"$gte": timeutil.BeginningOfDay(now.AddDate(0, 0, -1)), "$lt": timeutil.BeginningOfDay(now)},
}
pipelines := []bson.M{
{"$match": match},
{"$group": bson.M{"_id": nil, "totalAmount": bson.M{"$sum": "$payMoney"}}},
{"$project": bson.M{"totalAmount": 1}},
}
var res struct {
TotalAmount int64 `bson:"totalAmount"`
}
if err := coll(nil).AggregateDecode(&res, pipelines); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetUserChessSuccessOrderAmout", table, "AggregateDecode", err), log.Any("uid", uid))
return 0, err
}
return decimal.NewFromInt(res.TotalAmount).Div(decimal.NewFromInt(100)).IntPart(), nil
}
// 首冲判定
func IsFirstRecharge(uid uint64) (bool, error) {
filter := bson.M{"uid": uid, "productType": 1, "status": SUCCESS}
count, err := coll(nil).Count(filter)
if err != nil {
return false, err
}
return count == 0, nil
}
func StatCenterSyncRecharge(start time.Time, size int64) ([]RechargeOrder, error) {
end := time.Now().Add(-time.Second * 240) //等用户注册信息先同步
opt := (&options.FindOptions{})
opt.SetLimit(size)
opt.SetSort(bson.M{"successAt": 1})
filter := bson.M{"status": 3, "successAt": bson.M{"$gt": start, "$lte": end}}
data := make([]RechargeOrder, 0)
return data, coll(nil).Find(&data, filter, opt)
}
func StatCenterSyncOrder(start time.Time, size int64) ([]RechargeOrder, error) {
end := time.Now().Add(-time.Second * 240) //等用户注册信息先同步
opt := (&options.FindOptions{})
opt.SetLimit(size)
opt.SetSort(bson.M{"createdAt": 1})
filter := bson.M{"createdAt": bson.M{"$gt": start, "$lte": end}}
data := make([]RechargeOrder, 0)
return data, coll(nil).Find(&data, filter, opt)
}
func GetOrderByTime(start, end time.Time) ([]RechargeStat, error) {
filter := bson.M{"status": 3, "productType": bson.M{"$ne": 1}, "successAt": bson.M{"$gt": start, "$lte": end}}
data := make([]RechargeStat, 0)
return data, coll(nil).Find(&data, filter)
}
func NewStatCenterSyncRecharge(id string, size int64) ([]RechargeOrder, error) {
_id, _ := primitive.ObjectIDFromHex(id)
opt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.M{"_id": 1})
filter := bson.M{"_id": bson.M{"$gt": _id}}
data := make([]RechargeOrder, 0)
return data, coll(nil).Find(&data, filter, opt)
}
// RefundCallBackModify 退款回调修改订单
func RefundCallBackModify(ctx context.Context, t *db.MongoTool, id primitive.ObjectID, set EditSelector) error {
set.UpdatedAt = time.Now()
if _, err := coll(t).UpdateOne(bson.M{"_id": id}, bson.M{"$set": set}); err != nil {
log.WarnX(ctx, fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateOne", err),
log.Any("id", id),
log.Any("set", set),
)
return err
}
return nil
}
+193
View File
@@ -0,0 +1,193 @@
package rchgordmod
import (
"91porn-server/middleware/ua"
"time"
"91porn-server/common/db"
"91porn-server/models/commod"
"go.mongodb.org/mongo-driver/bson/primitive"
)
const (
DEFAULT = iota //默认
Processing //1进行中
FAILURE //2失败
SUCCESS //3成功
REFUND //4退款
)
const (
UnLock = iota //0锁定 订单操作锁 解锁
Lock //1锁定 订单操作锁 加锁 目前在代充中用到
)
// 通知第三方上分结果
const (
Notify_DEFAULT = iota //默认
Notify_SUCCESS //1 成功通知第三方
Notify_FAILURE //2 通知第三方失败
)
type Status int
var status = map[Status]string{
Processing: "processing",
FAILURE: "failure",
SUCCESS: "success",
REFUND: "refund",
}
func (s Status) Desc() string {
if desc, ok := status[s]; ok {
return desc
}
return ""
}
// 支付类型
type RechType string
const (
Rech_WeChat RechType = "wechat" //微信
Rech_AliPay RechType = "alipay" //支付宝
Rech_Union RechType = "union" //支付宝
Rech_DaiChong RechType = "daichong" //代充
)
type ChildType int
const (
Gold ChildType = iota + 1 // 购买金币
VIP // 购买会员卡
FruitCoin // 购买果币
NudeChatService // 购买裸聊服务
)
const (
GoldFish = "jinyu"
Shark = "shayu"
DaBaiSha = "dabaisha"
Lucky = "lezhifu"
Rongyi = "rongyi"
GoldfishPlus = "dajinyu"
IZhiFu = "izhifu"
DXZhiFu = "dxzhifu"
LeiHuo = "leihuo"
ZhongFu = "zhongfu"
YiLianFu = "yilianfu"
YinSe = "yinse"
)
const (
ChanShareNO = iota //不分成
ChanShareCoin //金币分成
ChanShareModVIP //vip分成
)
var mdb *db.MongoDB
type DiscSeqe = commod.DiscSeqe
type DiscDoc = commod.DiscDoc
// RechargeOrder 账户充值流水
type RechargeOrder struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
UID uint64 `json:"uid" bson:"uid"` //用户id
DevID string `json:"devID" bson:"devID"` //设备id
OID string `json:"oid" bson:"oid"` //支付平台订单号
TraderId string `json:"traderId" bson:"traderId"` //商户ID
UserIP string `json:"userIP" bson:"userIP"` //用户ip
Name string `json:"name" bson:"name"` //用户名称
Tel string `json:"tel" bson:"tel"` //用户手机号
PayAct string `json:"payAct" bson:"payAct"` //支付账号
DevType string `json:"devType" bson:"devType"` //设备系统类型 ios pc android
Amount int64 `json:"amount" bson:"amount"` //虚拟币数量(金币/果币)
Money int64 `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
PayMoney int64 `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
RechargeType string `json:"rechargeType" bson:"rechargeType"` //充值类型(支付类型)
ProductID primitive.ObjectID `json:"productID" bson:"productID"` //充值金币类型id
ProductName string `json:"productName" bson:"productName"` //充值产品名
VipID primitive.ObjectID `json:"vipID" bson:"vipID"` //是否是vip冲 hi
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
Proof string `json:"proof" bson:"proof"` //代充平台 支付凭证
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
StatusDesc string `json:"statusDesc" bson:"statusDesc"` //状态描述
LockStatus int `json:"lockStatus" bson:"lockStatus"` //订单操作锁定状态 用户订单更新操作 0-未锁定 可用于编辑订单 1-已锁定 不可编辑
NotifyTime int64 `json:"notifyTime" bson:"notifyTime"` //第三方回调本地订单的时间
NotifyStatus int `json:"notifyStatus" bson:"notifyStatus"` //通知第三方上分情况状态 1-成功 2-失败
Remark string `json:"remark" bson:"remark"` //备注
ProgressAt time.Time `json:"progressAt" bson:"progressAt"` //第三方下单成功时间
RefundAt time.Time `json:"refundAt" bson:"refundAt"` // 退款失败时间
FailureAt time.Time `json:"failureAt" bson:"failureAt"` //回调失败时间
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
PaymentAt time.Time `json:"paymentAt" bson:"paymentAt"` //支付时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //刷新时间
Rate string `json:"rate" bson:"rate"` //渠道费率
ProductType int `json:"productType" bson:"productType"` //支付产品类型 0 站群 1 棋牌
BuyType commod.BuyType `json:"buyType" bson:"buyType"` //充值购买类型
ServiceID primitive.ObjectID `json:"serviceId" bson:"serviceId"` //裸聊服务ID
DiscDoc `bson:",inline"` //商区
ChanShareMod int `json:"chanShareMod" bson:"chanShareMod"` //渠道分成类型
Category int `json:"category" bson:"category"` //充值类别 0金币 1会员
GoldExtraID *primitive.ObjectID `json:"goldExtraID" bson:"goldExtraID,omitempty"` // 金币加购券
Ua ua.UA `json:"ua" bson:"ua"`
SourcePage string `json:"sourcePage,omitempty" bson:"sourcePage,omitempty"` // 下单来源页面
SourceRef string `json:"sourceRef,omitempty" bson:"sourceRef,omitempty"` // 来源业务对象
VideoID string `json:"videoId,omitempty" bson:"videoId,omitempty"` // 来源视频ID
ActivityID string `json:"activityId,omitempty" bson:"activityId,omitempty"` // 来源活动ID
ExperimentID string `json:"experimentId,omitempty" bson:"experimentId,omitempty"` // A/B实验ID
ExperimentVariant string `json:"experimentVariant,omitempty" bson:"experimentVariant,omitempty"` // A/B实验分组
SessionID string `json:"sessionId,omitempty" bson:"sessionId,omitempty"` // 前端会话ID
MediaID primitive.ObjectID `json:"mediaId,omitempty" bson:"mediaId,omitempty"` // 短剧ID
ContentID primitive.ObjectID `json:"contentId,omitempty" bson:"contentId,omitempty"` // 短剧单集ID
CheckoutContextID string `json:"checkoutContextId,omitempty" bson:"checkoutContextId,omitempty"` // 短剧付费墙上下文
CouponID string `json:"couponId,omitempty" bson:"couponId,omitempty"` // 会员抵扣券ID(活动服券号,不透明串,支付结果回调时原样回传)
DeductAmount int64 `json:"deductAmount,omitempty" bson:"deductAmount,omitempty"` // 抵扣金额(分),已按上限封顶后的实际抵扣额
}
func Init() {
mdb = db.Init(table)
initIndex()
}
type RechargeStat struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
UID uint64 `json:"uid" bson:"uid"` //用户id
DevID string `json:"devID" bson:"devID"` //设备id
OID string `json:"oid" bson:"oid"` //支付平台订单号
TraderId string `json:"traderId" bson:"traderId"` //商户ID
UserIP string `json:"userIP" bson:"userIP"` //用户ip
Name string `json:"name" bson:"name"` //用户名称
Tel string `json:"tel" bson:"tel"` //用户手机号
PayAct string `json:"payAct" bson:"payAct"` //支付账号
DevType string `json:"devType" bson:"devType"` //设备系统类型 ios pc android
Amount int64 `json:"amount" bson:"amount"` //虚拟币数量(金币/果币)
Money int64 `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
PayMoney int64 `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
RechargeType string `json:"rechargeType" bson:"rechargeType"` //充值类型(支付类型)
ProductID primitive.ObjectID `json:"productID" bson:"productID"` //充值金币类型id
VipID primitive.ObjectID `json:"vipID" bson:"vipID"` //是否是vip冲 hi
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
Proof string `json:"proof" bson:"proof"` //代充平台 支付凭证
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
StatusDesc string `json:"statusDesc" bson:"statusDesc"` //状态描述
LockStatus int `json:"lockStatus" bson:"lockStatus"` //订单操作锁定状态 用户订单更新操作 0-未锁定 可用于编辑订单 1-已锁定 不可编辑
NotifyTime int64 `json:"notifyTime" bson:"notifyTime"` //第三方回调本地订单的时间
NotifyStatus int `json:"notifyStatus" bson:"notifyStatus"` //通知第三方上分情况状态 1-成功 2-失败
Remark string `json:"remark" bson:"remark"` //备注
ProgressAt time.Time `json:"progressAt" bson:"progressAt"` //第三方下单成功时间
FailureAt time.Time `json:"failureAt" bson:"failureAt"` //回调失败时间
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
PaymentAt time.Time `json:"paymentAt" bson:"paymentAt"` //支付时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //刷新时间
Rate string `json:"rate" bson:"rate"` //渠道费率
ProductType int `json:"productType" bson:"productType"` //支付产品类型 0 站群 1 棋牌
BuyType commod.BuyType `json:"buyType" bson:"buyType"` //充值购买类型
ServiceID primitive.ObjectID `json:"serviceId" bson:"serviceId"` //裸聊服务ID
DiscDoc `bson:",inline"` //商区
ChanShareMod int `json:"chanShareMod" bson:"chanShareMod"` //渠道分成类型
}
+69
View File
@@ -0,0 +1,69 @@
package rchgordmod
import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type VIPExperimentOrderStat struct {
Variant string `json:"variant" bson:"variant"`
ProductID primitive.ObjectID `json:"productId" bson:"productId"`
CreatedOrders int `json:"createdOrders" bson:"createdOrders"`
PaidOrders int `json:"paidOrders" bson:"paidOrders"`
RefundedOrders int `json:"refundedOrders" bson:"refundedOrders"`
OrderAmount int64 `json:"orderAmount" bson:"orderAmount"`
PaidAmount int64 `json:"paidAmount" bson:"paidAmount"`
GoldPaidOrders int `json:"goldPaidOrders" bson:"goldPaidOrders"`
GoldPaidAmount int64 `json:"goldPaidAmount" bson:"goldPaidAmount"`
}
func VIPExperimentOrderStatistics(experimentID string) ([]VIPExperimentOrderStat, error) {
var raw []struct {
ID struct {
Variant string `bson:"variant"`
ProductID primitive.ObjectID `bson:"productId"`
} `bson:"_id"`
CreatedOrders int `bson:"createdOrders"`
PaidOrders int `bson:"paidOrders"`
RefundedOrders int `bson:"refundedOrders"`
OrderAmount int64 `bson:"orderAmount"`
PaidAmount int64 `bson:"paidAmount"`
}
err := coll(nil).Aggregate(&raw, []bson.M{
{"$match": bson.M{"experimentId": experimentID}},
{"$group": bson.M{
"_id": bson.M{
"variant": "$experimentVariant",
"productId": "$productID",
},
"createdOrders": bson.M{"$sum": 1},
"paidOrders": bson.M{"$sum": bson.M{"$cond": bson.A{
bson.M{"$eq": bson.A{"$status", SUCCESS}}, 1, 0,
}}},
"refundedOrders": bson.M{"$sum": bson.M{"$cond": bson.A{
bson.M{"$eq": bson.A{"$status", REFUND}}, 1, 0,
}}},
"orderAmount": bson.M{"$sum": "$money"},
"paidAmount": bson.M{"$sum": bson.M{"$cond": bson.A{
bson.M{"$eq": bson.A{"$status", SUCCESS}}, "$payMoney", 0,
}}},
}},
{"$sort": bson.D{{Key: "_id.variant", Value: 1}, {Key: "createdOrders", Value: -1}}},
})
if err != nil {
return nil, err
}
result := make([]VIPExperimentOrderStat, 0, len(raw))
for _, item := range raw {
result = append(result, VIPExperimentOrderStat{
Variant: item.ID.Variant,
ProductID: item.ID.ProductID,
CreatedOrders: item.CreatedOrders,
PaidOrders: item.PaidOrders,
RefundedOrders: item.RefundedOrders,
OrderAmount: item.OrderAmount,
PaidAmount: item.PaidAmount,
})
}
return result, nil
}
+78
View File
@@ -0,0 +1,78 @@
package rchgordmod
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// RechargeUpdateReq 修改参数
type RechargeUpdateReq struct {
StatusDesc *string `json:"statusDesc" bson:"statusDesc"` // 状态描述
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //更新时间
}
type RchgQueryReq struct {
ID *string `form:"id" json:"_id,omitempty" bson:"_id"` //流水id
UID *uint64 `form:"uid" json:"uid,omitempty" bson:"uid"` //用户id
DevID *string `form:"devID" json:"devID,omitempty" bson:"devID"` //设备id
OID *string `form:"oid" json:"oid,omitempty" bson:"oid"` //支付平台订单号
TraderId *string `form:"traderId" json:"traderId,omitempty" bson:"traderId"` //商户ID
UserIP *string `form:"userIP" json:"userIP,omitempty" bson:"userIP"` //用户ip
Name *string `form:"name" json:"name,omitempty" bson:"name"` //用户名称
Tel *string `form:"tel" json:"tel,omitempty" bson:"tel"` //用户手机号
PayAct *string `form:"payAct" json:"payAct,omitempty" bson:"payAct"` //支付账号
DevType *string `form:"devType" json:"devType,omitempty" bson:"devType"` //设备系统类型 ios pc android
Amount *int64 `form:"amount" json:"amount,omitempty" bson:"amount"` //蝴蝶币数量
Money *int64 `form:"money" json:"money,omitempty" bson:"money"` //充值金额
PayMoney *int64 `form:"payMoney" json:"payMoney,omitempty" bson:"payMoney"` //实际到账金额
RechargeType *string `form:"rechargeType" json:"rechargeType,omitempty" bson:"rechargeType"` //充值类型
Channel *string `form:"channel" json:"channel,omitempty" bson:"channel"` //渠道类型 鲨鱼 金鱼
Account *string `form:"bankAccount" json:"bankAccount,omitempty" bson:"bankAccount"` //银行账户,支付宝或微信账户
BackName *string `form:"backName" json:"backName,omitempty" bson:"backName"` //银行名称,如果是银行类型提现,必填
TranOrder *string `form:"tranOrder" json:"tranOrder,omitempty" bson:"tranOrder"` //交易充值的订单号
Status *int `form:"status" json:"status,omitempty" bson:"status"` //0代表进行中 1付款成功,可退款 2付款失败 3付款成功 4已经退款
ProductType *int `form:"productType" json:"productType,omitempty" bson:"productType"` //产品类型 0站群 1棋牌
SourcePage *string `form:"sourcePage" json:"sourcePage,omitempty" bson:"sourcePage"`
SourceRef *string `form:"sourceRef" json:"sourceRef,omitempty" bson:"sourceRef"`
VideoID *string `form:"videoId" json:"videoId,omitempty" bson:"videoId"`
ActivityID *string `form:"activityId" json:"activityId,omitempty" bson:"activityId"`
ExperimentID *string `form:"experimentId" json:"experimentId,omitempty" bson:"experimentId"`
ExperimentVariant *string `form:"experimentVariant" json:"experimentVariant,omitempty" bson:"experimentVariant"`
SessionID *string `form:"sessionId" json:"sessionId,omitempty" bson:"sessionId"`
}
type RchargeOrderExport struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
UID uint64 `json:"uid" bson:"uid"` //用户id
DevID string `json:"devID" bson:"devID" ` //设备id
OID string `json:"oid" bson:"oid"` //支付平台订单号
TraderId string `json:"traderId,omitempty" bson:"traderId,omitempty"` //商户ID
UserIP string `json:"userIP" bson:"userIP"` //用户ip
Name string `json:"name" bson:"name" ` //用户名称
Tel string `json:"tel" bson:"tel" ` //用户手机号
PayAct string `json:"payAct" bson:"payAct" ` //支付账号
DevType string `json:"devType" bson:"devType"` //设备系统类型 ios pc android
Amount string `json:"amount" bson:"amount" ` //蝴蝶币数量
Money string `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
PayMoney string `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
RechargeType string `json:"rechargeType" bson:"rechargeType"` //充值类型
ProductID primitive.ObjectID `json:"productID" bson:"productID"` //充值金币类型id
VipID primitive.ObjectID `json:"vipID" bson:"vipID"` //是否是vip冲 hi
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
Status int `json:"status" bson:"status" ` // 1进行中 2付款失败 3付款成功 4已经退款
StatusDesc string `json:"statusDesc" bson:"statusDesc"` // 状态描述
ProgressAt time.Time `json:"progressAt" bson:"progressAt"` //第三方下单成功时间
FailureAt time.Time `json:"failureAt" bson:"failureAt"` //回调失败时间
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
PaymentAt time.Time `json:"paymentAt" bson:"paymentAt"` //支付时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //刷新时间
SourcePage string `json:"sourcePage" bson:"sourcePage"`
SourceRef string `json:"sourceRef" bson:"sourceRef"`
VideoID string `json:"videoId" bson:"videoId"`
ActivityID string `json:"activityId" bson:"activityId"`
ExperimentID string `json:"experimentId" bson:"experimentId"`
ExperimentVariant string `json:"experimentVariant" bson:"experimentVariant"`
SessionID string `json:"sessionId" bson:"sessionId"`
}