go-common/app/service/live/wallet/model/helper.go
2019-04-22 18:49:16 +08:00

483 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package model
import (
"fmt"
"go-common/library/ecode"
"time"
)
/*
const STREAM_OP_RESULT_SUCCESS = 0 //交易成功
const STREAM_OP_RESULT_IN_PROGRESS = 1 //交易进行中
const STREAM_OP_RESULT_FAILED = 2 //交易失败
const STREAM_OP_RESULT_ROLLBACK_SUCC = 2 //回滚成功
const STREAM_OP_RESULT_ROLLBACK_IN_PROGRESS = 2 //交易回滚中
const STREAM_OP_RESULT_ROLLBACK_FAILED = 2 //回滚成功
*/
const STREAM_OP_RESULT_SUB_SUCC = 1 //扣款成功
const STREAM_OP_RESULT_ADD_SUCC = 2 //加款成功
const STREAM_OP_RESULT_SUB_FAILED = -1 //扣款失败
const STREAM_OP_RESULT_ADD_FAILED = -2 //加款失败
const STREAM_OP_REASON_EXECUTE_UNKNOWN = -6 //系统内部逻辑错误: 结果未知,当作失败
const STREAM_OP_REASON_POST_QUERY_FAILED = -5 //系统内部错误,后置查询失败
const STREAM_OP_REASON_QUERY_FAILED = -4 //系统内部错误,查询失败
const STREAM_OP_REASON_LOCK_ERROR = -3 //系统内部错误,获取锁异常
const STREAM_OP_REASON_EXECUTE_FAILED = -2 //系统内部逻辑错误: 执行失败,连接异常 OR SQL错误 OR 修改要求的条件不满足(有别的进程越过用户锁,对货币数进行了变更)
const STREAM_OP_REASON_PRE_QUERY_FAILED = -1 //前置查询失败
const STREAM_OP_REASON_NOT_ENOUGH_COIN = 1
const STREAM_OP_REASON_LOCK_FAILED = 2
const (
LIVE_PLATFORM_IOS = "ios"
LIVE_PLATFORM_PC = "pc"
LIVE_PLATFORM_ANDROID = "android"
LIVE_PLATFORM_H5 = "h5"
COIN_TYPE_IOS_GOLD = "iap_gold"
COIN_TYPE_GOLD = "gold"
COIN_TYPE_SILVER = "silver"
COIN_TYPE_METAL = "metal" //主站硬币(主站提供硬币数查询、硬币扣除接口供调用)
)
type RechargeOrPayForm struct {
Uid int64 `form:"uid" validate:"required"`
CoinType string `form:"coin_type" validate:"required"`
CoinNum int64 `form:"coin_num" validate:"required"`
ExtendTid string `form:"extend_tid" validate:"required"`
Timestamp int64 `form:"timestamp" validate:"required"`
TransactionId string `form:"transaction_id" validate:"required"`
}
type ExchangeForm struct {
Uid int64 `form:"uid" validate:"required"`
ExtendTid string `form:"extend_tid" validate:"required"`
Timestamp int64 `form:"timestamp" validate:"required"`
TransactionId string `form:"transaction_id" validate:"required"`
SrcCoinType string `form:"src_coin_type" validate:"required"`
SrcCoinNum int64 `form:"src_coin_num" validate:"required"`
DestCoinType string `form:"dest_coin_type" validate:"required"`
DestCoinNum int64 `form:"dest_coin_num" validate:"required"`
}
type RecordCoinStreamForm struct {
Uid int64 `form:"uid" validate:"required"`
Data string `form:"data" validate:"required"`
}
type ServiceType int32
const (
PAYTYPE ServiceType = 0
RECHARGETYPE ServiceType = 1
EXCHANGETYPE ServiceType = 2
ROLLBACKTYPE ServiceType = 3
SysCoinTypeIosGold int32 = 2
SysCoinTypeGold int32 = 1
SysCoinTypeSilver int32 = 0
SysCoinTypeMetal int32 = 3
)
func IsValidServiceType(serviceType int32) bool {
st := ServiceType(serviceType)
return st == PAYTYPE ||
st == RECHARGETYPE ||
st == EXCHANGETYPE ||
st == ROLLBACKTYPE
}
var (
validPlatformMap = map[string]string{LIVE_PLATFORM_ANDROID: LIVE_PLATFORM_ANDROID, LIVE_PLATFORM_H5: LIVE_PLATFORM_H5, LIVE_PLATFORM_PC: LIVE_PLATFORM_PC, LIVE_PLATFORM_IOS: LIVE_PLATFORM_IOS}
validCoinTypeMap = map[string]int32{COIN_TYPE_IOS_GOLD: SysCoinTypeIosGold, COIN_TYPE_GOLD: SysCoinTypeGold, COIN_TYPE_SILVER: SysCoinTypeSilver, COIN_TYPE_METAL: SysCoinTypeMetal}
validPlatformNoMap = map[string]int32{LIVE_PLATFORM_PC: 1, LIVE_PLATFORM_ANDROID: 2, LIVE_PLATFORM_IOS: 3, LIVE_PLATFORM_H5: 4}
)
func IsValidCoinType(coinType string) bool {
_, ok := validCoinTypeMap[coinType]
return ok
}
func GetCoinTypeNumber(coinType string) int32 {
n := validCoinTypeMap[coinType]
return n
}
func IsValidPlatform(platform string) bool {
_, ok := validPlatformMap[platform]
return ok
}
func IsPlatformIOS(platform string) bool {
return platform == LIVE_PLATFORM_IOS
}
func IsLocalCoin(coinTypeNo int32) bool {
return coinTypeNo != SysCoinTypeMetal
}
func GetSysCoinType(coinType string, platform string) string {
if IsPlatformIOS(platform) && coinType == COIN_TYPE_GOLD {
coinType = COIN_TYPE_IOS_GOLD
}
return coinType
}
func GetSysCoinTypeByNo(coinTypeNo int32) string {
switch coinTypeNo {
case SysCoinTypeGold:
return COIN_TYPE_GOLD
case SysCoinTypeIosGold:
return COIN_TYPE_IOS_GOLD
case SysCoinTypeSilver:
return COIN_TYPE_SILVER
case SysCoinTypeMetal:
return COIN_TYPE_METAL
default:
return "not_define"
}
}
func GetRechargeCnt(coinTypeNo int32) string {
var rechargeCntField string
if coinTypeNo == SysCoinTypeSilver {
rechargeCntField = ""
} else if coinTypeNo == SysCoinTypeIosGold {
rechargeCntField = "gold_recharge_cnt"
} else if coinTypeNo == SysCoinTypeGold {
rechargeCntField = "gold_recharge_cnt"
}
return rechargeCntField
}
func GetPayCnt(coinTypeNo int32) string {
var cntField string
if coinTypeNo == SysCoinTypeSilver {
cntField = "silver_pay_cnt"
} else if coinTypeNo == SysCoinTypeIosGold {
cntField = "gold_pay_cnt"
} else if coinTypeNo == SysCoinTypeGold {
cntField = "gold_pay_cnt"
}
return cntField
}
func GetWalletFormatTime(opTime int64) string {
tm := time.Unix(opTime, 0)
date := tm.Format("2006-01-02 15:04:05")
return date
}
func NewCoinStream(uid int64, tid string, extendTid string, coinType int32, coinNum int64, opType int32, opTime int64, bizCode string, area int64, source string, bizSource string, metadata string) *CoinStreamRecord {
return &CoinStreamRecord{
Uid: uid,
TransactionId: tid,
ExtendTid: extendTid,
CoinType: coinType,
DeltaCoinNum: coinNum,
OpType: opType,
OpTime: opTime,
BizCode: bizCode,
Area: area,
Source: source,
BizSource: bizSource,
MetaData: metadata,
}
}
func NewExchangeSteam(uid int64, tid string, srcCoinType int32, srcCoinNum int32, destCoinType int32, destCoinNum int32, opTime int64, status int32) *CoinExchangeRecord {
return &CoinExchangeRecord{
Uid: uid,
TransactionId: tid,
SrcType: srcCoinType,
SrcNum: srcCoinNum,
DestType: destCoinType,
DestNum: destCoinNum,
ExchangeTime: opTime,
Status: status,
}
}
func (m *CoinStreamRecord) SetOpReason(r int32) {
m.OpReason = r
}
func GetMelonseedResp(platform string, melonseed *Melonseed) *MelonseedResp {
gold := getPlatformGold(melonseed.Gold, melonseed.IapGold, platform)
return &MelonseedResp{
Silver: fmt.Sprintf("%d", melonseed.Silver),
Gold: fmt.Sprintf("%d", gold),
}
}
func GetMelonseedWithMetalResp(platform string, melonseed *Melonseed, metal float64) *MelonseedWithMetalResp {
gold := getPlatformGold(melonseed.Gold, melonseed.IapGold, platform)
return &MelonseedWithMetalResp{
Silver: fmt.Sprintf("%d", melonseed.Silver),
Gold: fmt.Sprintf("%d", gold),
Metal: fmt.Sprintf("%.2f", metal),
}
}
func GetDetailResp(platform string, detail *Detail) *DetailResp {
gold := getPlatformGold(detail.Gold, detail.IapGold, platform)
return &DetailResp{
Silver: fmt.Sprintf("%d", detail.Silver),
Gold: fmt.Sprintf("%d", gold),
GoldPayCnt: fmt.Sprintf("%d", detail.GoldPayCnt),
GoldRechargeCnt: fmt.Sprintf("%d", detail.GoldRechargeCnt),
SilverPayCnt: fmt.Sprintf("%d", detail.SilverPayCnt),
CostBase: detail.CostBase,
}
}
func GetDetailWithMetalResp(platform string, detail *Detail, metal float64) *DetailWithMetalResp {
gold := getPlatformGold(detail.Gold, detail.IapGold, platform)
return &DetailWithMetalResp{
Silver: fmt.Sprintf("%d", detail.Silver),
Gold: fmt.Sprintf("%d", gold),
GoldPayCnt: fmt.Sprintf("%d", detail.GoldPayCnt),
GoldRechargeCnt: fmt.Sprintf("%d", detail.GoldRechargeCnt),
SilverPayCnt: fmt.Sprintf("%d", detail.SilverPayCnt),
Metal: fmt.Sprintf("%.2f", metal),
CostBase: detail.CostBase,
}
}
func GetTidResp(tid string) *TidResp {
return &TidResp{TransactionId: tid}
}
func getPlatformGold(normalGold int64, iapGold int64, platform string) int64 {
gold := normalGold
if IsPlatformIOS(platform) {
gold = iapGold
}
return gold
}
func IncrMelonseedCoin(userCoins *Melonseed, num int64, coinTypeNo int32) {
switch coinTypeNo {
case SysCoinTypeIosGold:
userCoins.IapGold += num
case SysCoinTypeGold:
userCoins.Gold += num
case SysCoinTypeSilver:
userCoins.Silver += num
default:
}
}
func GetCoinByMelonseed(coinTypeNo int32, userCoin *Melonseed) int64 {
switch coinTypeNo {
case SysCoinTypeIosGold:
return userCoin.IapGold
case SysCoinTypeGold:
return userCoin.Gold
case SysCoinTypeSilver:
return userCoin.Silver
default:
return 0
}
}
func GetCoinByDetailWithSnapShot(coinTypeNo int32, userCoin *DetailWithSnapShot) int64 {
switch coinTypeNo {
case SysCoinTypeIosGold:
return userCoin.IapGold
case SysCoinTypeGold:
return userCoin.Gold
case SysCoinTypeSilver:
return userCoin.Silver
default:
return 0
}
}
func CompareCoin(origin interface{}, num int64) bool {
switch origin.(type) {
case int64:
return origin.(int64) >= num
case float64:
return int64(origin.(float64)) >= num
default:
return false
}
}
// 得到数据库适配的货币数据由于数据库的org_coin_num delta_coin_num都是整型但是硬币的类型是浮点数所以做一下适配
func GetDbFitCoin(v interface{}) int64 {
switch v.(type) {
case int64:
return v.(int64)
case float64:
return int64(v.(float64))
default:
return 0
}
}
func SubCoin(v1 interface{}, v2 interface{}) int64 {
switch v1.(type) {
case int64:
return v1.(int64) - v2.(int64)
case float64:
return int64(v1.(float64) - v2.(float64))
default:
return 0
}
}
func AddMoreParam2CoinStream(stream *CoinStreamRecord, bp *BasicParam, platform string) {
platformNo := GetPlatformNo(platform)
stream.Platform = platformNo
stream.Reserved1 = bp.Reason
stream.Version = bp.Version
}
type CoinStreamFieldInject interface {
GetExtendTid() string
GetTimestamp() int64
GetTransactionId() string
GetBizCode() string
GetArea() int64
GetBizSource() string
GetSource() string
GetReason() int64
GetVersion() int64
GetMetaData() string
GetPlatform() string
GetUid() int64
}
func InjectFieldToCoinStream(stream *CoinStreamRecord, inject CoinStreamFieldInject) {
stream.ExtendTid = inject.GetExtendTid()
stream.TransactionId = inject.GetTransactionId()
stream.OpTime = inject.GetTimestamp()
stream.BizCode = inject.GetBizCode()
stream.Area = inject.GetArea()
stream.BizSource = inject.GetBizSource()
stream.MetaData = inject.GetMetaData()
stream.Source = inject.GetSource()
stream.Reserved1 = inject.GetReason()
stream.Version = inject.GetVersion()
platformNo := GetPlatformNo(inject.GetPlatform())
stream.Platform = platformNo
stream.Uid = inject.GetUid()
}
func GetPlatformNo(platform string) int32 {
platformNo, ok := validPlatformNoMap[platform]
if !ok {
platformNo = 0
}
return platformNo
}
var (
validRecordCoinStreamItemType = map[string]bool{"recharge": true, "pay": true}
)
func (m *RecordCoinStreamItem) IsValidType() bool {
_, ok := validRecordCoinStreamItemType[m.Type]
return ok
}
func (m *RecordCoinStreamItem) IsPayType() bool {
return m.Type == "pay"
}
func (m *RecordCoinStreamItem) IsRechargeType() bool {
return m.Type == "recharge"
}
func (m *RecordCoinStreamItem) GetOpType() int32 {
if m.IsPayType() {
return int32(PAYTYPE)
} else {
return int32(RECHARGETYPE)
}
}
func (m *RecordCoinStreamItem) GetOpResult() int32 {
if m.IsPayType() {
return STREAM_OP_RESULT_SUB_SUCC
} else {
return STREAM_OP_RESULT_ADD_SUCC
}
}
func (m *RecordCoinStreamItem) IsValid() (valid bool) {
valid = false
if m.OrgCoinNum < 0 {
return
}
if !m.IsValidType() {
return
}
if !IsValidCoinType(m.CoinType) {
return
}
if m.IsPayType() && m.CoinNum >= 0 {
return
}
if m.IsRechargeType() && m.CoinNum <= 0 {
return
}
valid = true
return
}
func GetMelonByDetailWithSnapShot(wallet *DetailWithSnapShot, platform string) (melon *MelonseedResp) {
gold := wallet.Gold
if platform == LIVE_PLATFORM_IOS {
gold = wallet.IapGold
}
return &MelonseedResp{
Silver: fmt.Sprintf("%d", wallet.Silver),
Gold: fmt.Sprintf("%d", gold),
}
}
func ModifyCoinInDetailWithSnapShot(wallet *DetailWithSnapShot, sysCoinTypeNo int32, coinNum int64) {
switch sysCoinTypeNo {
case SysCoinTypeGold:
wallet.Gold += coinNum
case SysCoinTypeIosGold:
wallet.IapGold += coinNum
case SysCoinTypeSilver:
wallet.Silver += coinNum
}
}
// 根据锁的错误设置数据库的reason
func SetReasonByLockErr(lockErr error, coinStream *CoinStreamRecord) {
if lockErr == ecode.TargetBlocked {
coinStream.OpReason = STREAM_OP_REASON_LOCK_FAILED
} else {
coinStream.OpReason = STREAM_OP_REASON_LOCK_ERROR
}
}
func NeedSnapshot(wallet *DetailWithSnapShot, now time.Time) bool {
lastTime, _ := time.Parse("2006-01-02 15:04:05", wallet.SnapShotTime)
return now.After(lastTime)
}
func GetTodayTime(now time.Time) time.Time {
timeStr := now.Format("2006-01-02") + " 00:00:00"
today, _ := time.Parse("2006-01-02 15:04:05", timeStr)
return today
}
func TodayNeedSnapShot(wallet *DetailWithSnapShot) bool {
now := GetTodayTime(time.Now())
return NeedSnapshot(wallet, now)
}