diff --git a/bin/marketserver/config/currencys/13473/currency.json b/bin/marketserver/config/currencys/13473/currency.json new file mode 100644 index 00000000..5016b3e6 --- /dev/null +++ b/bin/marketserver/config/currencys/13473/currency.json @@ -0,0 +1,5 @@ +{ + "currency_name": "TestToken", + "exchange_rate": 50, + "currency_decimal": 6 +} diff --git a/bin/marketserver/res/recharge@recharge.json b/bin/marketserver/res/recharge@recharge.json index 8471d911..6dc055d9 100644 --- a/bin/marketserver/res/recharge@recharge.json +++ b/bin/marketserver/res/recharge@recharge.json @@ -1,56 +1,8 @@ [ - { - "recharge_cost_num": "15", - "recharge_icon": "itemIcon_diamond01", - "recharge_item": 10014, - "recharge_type": 1, - "recharge_item_num": 15, - "recharge_currency": "test currency", - "id": "1001" - }, - { - "recharge_cost_num": "62", - "recharge_icon": "itemIcon_diamond02", - "recharge_item": 10014, - "recharge_type": 1, - "recharge_item_num": 62, - "recharge_currency": "test currency", - "id": "1002" - }, - { - "recharge_cost_num": "162", - "recharge_icon": "itemIcon_diamond03", - "recharge_item": 10014, - "recharge_type": 1, - "recharge_item_num": 162, - "recharge_currency": "test currency", - "id": "1003" - }, - { - "recharge_cost_num": "325", - "recharge_icon": "itemIcon_diamond04", - "recharge_item": 10014, - "recharge_type": 1, - "recharge_item_num": 325, - "recharge_currency": "test currency", - "id": "1004" - }, - { - "recharge_cost_num": "800", - "recharge_icon": "itemIcon_diamond05", - "recharge_item": 10014, - "recharge_type": 1, - "recharge_item_num": 800, - "recharge_currency": "test currency", - "id": "1005" - }, - { - "recharge_cost_num": "", - "recharge_icon": "itemIcon_diamond06", - "recharge_item": 10014, - "recharge_type": 1, - "recharge_item_num": 0, - "recharge_currency": "test currency", - "id": "1006" - } - ] \ No newline at end of file + { + "id": 1001, + "diamond": 50, + "price": 1, + "max_buy_times": 9999 + } +] diff --git a/server/gamesapi/service/sapi_forward.go b/server/gamesapi/service/sapi_forward.go index 04b8e8be..45027915 100644 --- a/server/gamesapi/service/sapi_forward.go +++ b/server/gamesapi/service/sapi_forward.go @@ -39,7 +39,7 @@ func (this *sApiForward) init() { for i := 0; i < len(this.userCache); i++ { p := new(SApiForwardLockCache) p.lock = new(sync.Mutex) - p.userHash = new(map[string]*SApiForwardLock) + p.userHash = &map[string]*SApiForwardLock{} this.userCache[i] = p } } diff --git a/server/marketserver/api/v1/recharge/recharge.go b/server/marketserver/api/v1/recharge/recharge.go index 9f0efde4..bf3be71a 100644 --- a/server/marketserver/api/v1/recharge/recharge.go +++ b/server/marketserver/api/v1/recharge/recharge.go @@ -20,18 +20,25 @@ type RechargeApi struct { } func (ea *RechargeApi) RechargeList(c *gin.Context) { + netId := q5.ToInt32(c.Param("net_id")) rspObj := struct { ErrCode int32 `json:"errcode"` ErrMsg string `json:"errmsg"` Rows []interface{} `json:"rows"` }{} - mt.Table.Recharge.RawMetaTable.Traverse(func(tb *mt.Recharge) bool { + currencyMeta := mt.Table.Currency.Get(netId) + if currencyMeta == nil { + f5.RspErr(c, 2, "server internal error") + return + } + + mt.Table.Recharge.Traverse(func(tb *mt.Recharge) bool { tmpmap := map[string]interface{}{} tmpmap["goods_id"] = tb.GetId() - tmpmap["diamond"] = tb.GetRechargeItemNum() - tmpmap["currency"] = tb.GetRechargeCurrency() - tmpmap["price"] = tb.GetRechargeCostNum() + tmpmap["diamond"] = tb.GetDiamond() + tmpmap["price"] = tb.GetPrice() + tmpmap["max_buy_times"] = tb.GetMaxBuyTimes() rspObj.Rows = append(rspObj.Rows, tmpmap) @@ -46,26 +53,46 @@ func (this *RechargeApi) Buy(c *gin.Context) { reqJson := struct { NetId int32 `json:"net_id"` GoodsId int32 `json:"goods_id"` - Num int32 `json:"num"` + Num int32 `json:"goods_num"` AccountAddress string `json:"account_address"` }{} if err := c.ShouldBindJSON(&reqJson); err != nil { - c.JSON(http.StatusOK, gin.H{ - "errcode": 1, - "errmsg": err.Error(), - }) + f5.RspErr(c, 1, err.Error()) return } - currencyMeta := mt.Table.Contract.GetByNetIdName(reqJson.NetId, "TestToken") + currencyMeta := mt.Table.Currency.Get(reqJson.NetId) if currencyMeta == nil { f5.RspErr(c, 2, "server internal error") return } + if currencyMeta.GetExchangeRate() <= 0 || + currencyMeta.GetExchangeRate() > constant.RECHARGE_CURRENCY_MAX_EXCHANGE_RAET { + f5.RspErr(c, 2, "server internal error") + return + } + if currencyMeta.GetCurrencyDecimal() <= 0 || + currencyMeta.GetCurrencyDecimal() > constant.RECHARGE_CURRENCY_MAX_DECIMAL { + f5.RspErr(c, 2, "server internal error") + return + } + currencyContractMeta := mt.Table.Contract.GetByNetIdName(reqJson.NetId, currencyMeta.GetCurrencyName()) + if currencyContractMeta == nil { + f5.RspErr(c, 2, "server internal error") + return + } goodsMeta := mt.Table.Recharge.GetById(q5.ToInt64(reqJson.GoodsId)) if goodsMeta == nil { f5.RspErr(c, 2, "goods id param error") return } + if goodsMeta.GetPrice() <= 0 { + f5.RspErr(c, 2, "goods id param error") + return + } + if reqJson.Num <= 0 || reqJson.Num > goodsMeta.GetMaxBuyTimes() { + f5.RspErr(c, 2, "num param error") + return + } nowTime := q5.ToInt32(f5.GetApp().GetRealSeconds()) shortOrderId := f5.GetApp().NewLockNodeUuid() orderId := "" @@ -76,7 +103,7 @@ func (this *RechargeApi) Buy(c *gin.Context) { nowTime, 0, [3]int64{ - 0, + q5.ToInt64(reqJson.Num), q5.ToInt64(goodsMeta.GetId()), shortOrderId, }) @@ -87,7 +114,12 @@ func (this *RechargeApi) Buy(c *gin.Context) { return } } - price := "1" + price := q5.PowInt64(10, currencyMeta.GetCurrencyDecimal()) * q5.ToInt64(goodsMeta.GetPrice()) * + q5.ToInt64(reqJson.Num) + if price <= 0 || price < q5.ToInt64(goodsMeta.GetPrice()) { + f5.RspErr(c, 3, "server internal error") + return + } params := map[string]string{ "c": "BcService", "a": "recharge", @@ -95,17 +127,17 @@ func (this *RechargeApi) Buy(c *gin.Context) { "order_id": orderId, "account_address": reqJson.AccountAddress, "passport_address": passportAddress, - "amount": price, - "currency_name": currencyMeta.GetName(), - "currency_address": currencyMeta.GetAddress(), + "amount": q5.ToString(price), + "currency_name": currencyContractMeta.GetName(), + "currency_address": currencyContractMeta.GetAddress(), } jsonRspObj := &struct { ErrCode int32 `json:"errcode"` ErrMsg string `json:"errmsg"` Calls []jccommon.ContractCall `json:"calls"` }{} - var itemNum int32 = 1 - var diamond int64 = 1 + var itemNum int32 = reqJson.Num + var diamond int64 = q5.ToInt64(goodsMeta.GetDiamond()) * int64(itemNum) url := fmt.Sprintf("%s/webapp/index.php", mt.Table.Web3SignCluster.RandElement().GetUrl()) f5.GetHttpCliMgr().SendGoStyleRequest( url, @@ -129,11 +161,11 @@ func (this *RechargeApi) Buy(c *gin.Context) { reqJson.NetId, reqJson.AccountAddress, passportAddress, - currencyMeta.GetName(), - currencyMeta.GetAddress(), + currencyContractMeta.GetName(), + currencyContractMeta.GetAddress(), goodsMeta.GetId(), itemNum, - price, + q5.ToString(price), diamond) { f5.RspErr(c, 500, "server internal error") return diff --git a/server/marketserver/constant/constant.go b/server/marketserver/constant/constant.go index eed5e807..03ac120b 100644 --- a/server/marketserver/constant/constant.go +++ b/server/marketserver/constant/constant.go @@ -17,3 +17,9 @@ const ( const ( SHOPCART_MAX_GOODS_NUM = 20 ) + +const ( + RECHARGE_CURRENCY_MAX_EXCHANGE_RAET = 50 + RECHARGE_CURRENCY_MAX_DECIMAL = 6 + RECHARGE_CURRENCY_MAX_BUY_NUM = 9999 +) diff --git a/server/marketserver/mt/Currency.go b/server/marketserver/mt/Currency.go new file mode 100644 index 00000000..68c349a7 --- /dev/null +++ b/server/marketserver/mt/Currency.go @@ -0,0 +1,114 @@ +package mt + +import ( + "q5" + "f5" + "fmt" + "main/constant" +) + +type Currency struct { + currencyName string + exchangeRate int64 + currencyDecimal int64 +} + +type CurrencyTable struct { + f5.CustomMetaTable + netIdHash *q5.ConcurrentMap[int32, *Currency] +} + +func (this *Currency) init(currencyName string, exchangeRate int64, currencyDecimal int64) { + this.currencyName = currencyName + this.exchangeRate = exchangeRate + this.currencyDecimal = currencyDecimal +} + +func (this *Currency) GetCurrencyName() string { + return this.currencyName +} + +func (this *Currency) GetExchangeRate() int64 { + return this.exchangeRate +} + +func (this *Currency) GetCurrencyDecimal() int64 { + return this.currencyDecimal +} + +func (this *Currency) check() { + if this.GetExchangeRate() <= 0 { + panic("Currency exchange_rate <= 0") + return + } + if this.GetExchangeRate() != constant.RECHARGE_CURRENCY_MAX_EXCHANGE_RAET { + panic("Currency exchange_rate > uplimit") + return + } + if this.GetCurrencyDecimal() <= 0 { + panic("Currency currency_decimal <= 0") + return + } + if this.GetCurrencyDecimal() != constant.RECHARGE_CURRENCY_MAX_DECIMAL { + panic("Currency exchange_rate > uplimit") + return + } +} + +func (this *CurrencyTable) Get(netId int32) *Currency { + if v, ok := this.netIdHash.Load(netId); ok { + return *v + } else { + return nil + } +} + +func (this *CurrencyTable) Load() { + this.netIdHash = new(q5.ConcurrentMap[int32, *Currency]) + nets := []int32{} + { + if jsonStr, err := f5.ReadJsonFile("../config/nets.json"); err == nil { + if err := q5.DecodeJson(jsonStr, &nets); err != nil { + panic(fmt.Sprintf("load metafile json decode error %s %s", "nets.json", err)) + } + } else { + panic(fmt.Sprintf("load metafile error %s %s", "nets.json", err)) + } + } + { + for _, val := range nets { + netId := val + fileName := fmt.Sprintf("../config/currencys/%d/currency.json", netId) + if jsonStr, err := f5.ReadJsonFile(fileName); err == nil { + f5.GetSysLog().Info("load currency %s", fileName) + currencyCfg := struct { + CurrencyName string `json:"currency_name"` + ExchangeRate int64 `json:"exchange_rate"` + CurrencyDecimal int64 `json:"currency_decimal"` + }{} + if err := q5.DecodeJson(jsonStr, ¤cyCfg); err != nil { + panic(fmt.Sprintf("load metafile json decode error %s %s", "currency.json", err)) + } + p := new(Currency) + p.init(currencyCfg.CurrencyName, currencyCfg.ExchangeRate, currencyCfg.CurrencyDecimal) + p.check() + this.netIdHash.Store(netId, p) + } + } + } +} + +func (this *CurrencyTable) PostInit1() { + this.netIdHash.Range( + func (key int32, val *Currency) bool { + netId := key + currencyMeta := val + Table.Recharge.Traverse(func(ele *Recharge) bool { + if int64(ele.GetPrice()) * currencyMeta.GetExchangeRate() != int64(ele.GetDiamond()) { + panic(fmt.Sprintf("Currency verifyerror net_id:%d id:%d", netId, ele.GetId())) + } + return true + }) + return true + }) +} diff --git a/server/marketserver/mt/Recharge.go b/server/marketserver/mt/Recharge.go index cc658238..b8769943 100644 --- a/server/marketserver/mt/Recharge.go +++ b/server/marketserver/mt/Recharge.go @@ -3,6 +3,7 @@ package mt import ( "f5" "main/mtb" + "main/constant" ) type Recharge struct { @@ -12,3 +13,22 @@ type Recharge struct { type RechargeTable struct { f5.IdMetaTable[Recharge] } + +func (this *Recharge) Init1() { + if this.GetDiamond() <= 0 { + panic("Recharge diamond <= 0") + return + } + if this.GetPrice() <= 0 { + panic("Recharge price <= 0") + return + } + if this.GetMaxBuyTimes() <= 0 { + panic("Recharge max_buy_times <= 0") + return + } + if this.GetMaxBuyTimes() > constant.RECHARGE_CURRENCY_MAX_BUY_NUM { + panic("Recharge max_buy_times > uplimit") + return + } +} diff --git a/server/marketserver/mt/export.go b/server/marketserver/mt/export.go index 45fedb45..9072795f 100644 --- a/server/marketserver/mt/export.go +++ b/server/marketserver/mt/export.go @@ -16,6 +16,7 @@ type table struct { Web3ServiceCluster *Web3ServiceClusterTable Web3SignCluster *Web3SignClusterTable Recharge *RechargeTable + Currency *CurrencyTable } var Table = f5.New(func(this *table) { @@ -66,6 +67,8 @@ var Table = f5.New(func(this *table) { this.PrimKey = "" }) + this.Currency = new(CurrencyTable) + this.Recharge = f5.New(func(this *RechargeTable) { this.FileName = "../res/recharge@recharge.json" this.PrimKey = "id" diff --git a/server/marketserver/mtb/mtb.auto_gen.go b/server/marketserver/mtb/mtb.auto_gen.go index 0689ba4d..cdc502b1 100644 --- a/server/marketserver/mtb/mtb.auto_gen.go +++ b/server/marketserver/mtb/mtb.auto_gen.go @@ -60,6 +60,15 @@ type Config struct { _flags2_ uint64 } +type RechargeCurrency struct { + currency_name string + exchange_rate int64 + currency_decimal int64 + + _flags1_ uint64 + _flags2_ uint64 +} + type Item struct { name string id int32 @@ -79,13 +88,10 @@ type Language struct { } type Recharge struct { - recharge_cost_num string - recharge_icon string - recharge_item int32 - recharge_type int32 - recharge_item_num int32 id int32 - recharge_currency string + diamond int32 + price int32 + max_buy_times int32 _flags1_ uint64 _flags2_ uint64 @@ -313,6 +319,30 @@ func (this *Config) HasJwksUri() bool { return (this._flags1_ & (uint64(1) << 2)) > 0 } +func (this *RechargeCurrency) GetCurrencyName() string { + return this.currency_name +} + +func (this *RechargeCurrency) HasCurrencyName() bool { + return (this._flags1_ & (uint64(1) << 1)) > 0 +} + +func (this *RechargeCurrency) GetExchangeRate() int64 { + return this.exchange_rate +} + +func (this *RechargeCurrency) HasExchangeRate() bool { + return (this._flags1_ & (uint64(1) << 2)) > 0 +} + +func (this *RechargeCurrency) GetCurrencyDecimal() int64 { + return this.currency_decimal +} + +func (this *RechargeCurrency) HasCurrencyDecimal() bool { + return (this._flags1_ & (uint64(1) << 3)) > 0 +} + func (this *Item) GetName() string { return this.name } @@ -361,60 +391,36 @@ func (this *Language) HasEn() bool { return (this._flags1_ & (uint64(1) << 2)) > 0 } -func (this *Recharge) GetRechargeCostNum() string { - return this.recharge_cost_num -} - -func (this *Recharge) HasRechargeCostNum() bool { - return (this._flags1_ & (uint64(1) << 1)) > 0 -} - -func (this *Recharge) GetRechargeIcon() string { - return this.recharge_icon -} - -func (this *Recharge) HasRechargeIcon() bool { - return (this._flags1_ & (uint64(1) << 2)) > 0 -} - -func (this *Recharge) GetRechargeItem() int32 { - return this.recharge_item -} - -func (this *Recharge) HasRechargeItem() bool { - return (this._flags1_ & (uint64(1) << 3)) > 0 -} - -func (this *Recharge) GetRechargeType() int32 { - return this.recharge_type -} - -func (this *Recharge) HasRechargeType() bool { - return (this._flags1_ & (uint64(1) << 4)) > 0 -} - -func (this *Recharge) GetRechargeItemNum() int32 { - return this.recharge_item_num -} - -func (this *Recharge) HasRechargeItemNum() bool { - return (this._flags1_ & (uint64(1) << 5)) > 0 -} - func (this *Recharge) GetId() int32 { return this.id } func (this *Recharge) HasId() bool { - return (this._flags1_ & (uint64(1) << 6)) > 0 + return (this._flags1_ & (uint64(1) << 1)) > 0 } -func (this *Recharge) GetRechargeCurrency() string { - return this.recharge_currency +func (this *Recharge) GetDiamond() int32 { + return this.diamond } -func (this *Recharge) HasRechargeCurrency() bool { - return (this._flags1_ & (uint64(1) << 7)) > 0 +func (this *Recharge) HasDiamond() bool { + return (this._flags1_ & (uint64(1) << 2)) > 0 +} + +func (this *Recharge) GetPrice() int32 { + return this.price +} + +func (this *Recharge) HasPrice() bool { + return (this._flags1_ & (uint64(1) << 3)) > 0 +} + +func (this *Recharge) GetMaxBuyTimes() int32 { + return this.max_buy_times +} + +func (this *Recharge) HasMaxBuyTimes() bool { + return (this._flags1_ & (uint64(1) << 4)) > 0 } func (this *Web3ServiceCluster) GetUrl() string { @@ -475,6 +481,12 @@ func (this *Config) LoadFromKv(kv map[string]interface{}) { f5.ReadMetaTableField(&this.jwks_uri, "jwks_uri", &this._flags1_, 2, kv) } +func (this *RechargeCurrency) LoadFromKv(kv map[string]interface{}) { + f5.ReadMetaTableField(&this.currency_name, "currency_name", &this._flags1_, 1, kv) + f5.ReadMetaTableField(&this.exchange_rate, "exchange_rate", &this._flags1_, 2, kv) + f5.ReadMetaTableField(&this.currency_decimal, "currency_decimal", &this._flags1_, 3, kv) +} + func (this *Item) LoadFromKv(kv map[string]interface{}) { f5.ReadMetaTableField(&this.name, "name", &this._flags1_, 1, kv) f5.ReadMetaTableField(&this.id, "id", &this._flags1_, 2, kv) @@ -488,13 +500,10 @@ func (this *Language) LoadFromKv(kv map[string]interface{}) { } func (this *Recharge) LoadFromKv(kv map[string]interface{}) { - f5.ReadMetaTableField(&this.recharge_cost_num, "recharge_cost_num", &this._flags1_, 1, kv) - f5.ReadMetaTableField(&this.recharge_icon, "recharge_icon", &this._flags1_, 2, kv) - f5.ReadMetaTableField(&this.recharge_item, "recharge_item", &this._flags1_, 3, kv) - f5.ReadMetaTableField(&this.recharge_type, "recharge_type", &this._flags1_, 4, kv) - f5.ReadMetaTableField(&this.recharge_item_num, "recharge_item_num", &this._flags1_, 5, kv) - f5.ReadMetaTableField(&this.id, "id", &this._flags1_, 6, kv) - f5.ReadMetaTableField(&this.recharge_currency, "recharge_currency", &this._flags1_, 7, kv) + f5.ReadMetaTableField(&this.id, "id", &this._flags1_, 1, kv) + f5.ReadMetaTableField(&this.diamond, "diamond", &this._flags1_, 2, kv) + f5.ReadMetaTableField(&this.price, "price", &this._flags1_, 3, kv) + f5.ReadMetaTableField(&this.max_buy_times, "max_buy_times", &this._flags1_, 4, kv) } func (this *Web3ServiceCluster) LoadFromKv(kv map[string]interface{}) { diff --git a/server/marketserver/proto/mt.proto b/server/marketserver/proto/mt.proto index e7547be8..c9c4e5e2 100644 --- a/server/marketserver/proto/mt.proto +++ b/server/marketserver/proto/mt.proto @@ -48,6 +48,13 @@ message Config optional string jwks_uri = 2; } +message RechargeCurrency +{ + optional string currency_name = 1; + optional int64 exchange_rate = 2; + optional int64 currency_decimal = 3; +} + message Item { optional string name = 1; @@ -64,13 +71,10 @@ message Language message Recharge { - optional string recharge_cost_num = 1; - optional string recharge_icon =2; - optional int32 recharge_item =3; - optional int32 recharge_type =4; - optional int32 recharge_item_num =5; - optional int32 id =6; - optional string recharge_currency = 7; + optional int32 id = 1; + optional int32 diamond = 2; + optional int32 price = 3; + optional int32 max_buy_times = 4; } message Web3ServiceCluster diff --git a/third_party/q5 b/third_party/q5 index 489449c6..b065fccf 160000 --- a/third_party/q5 +++ b/third_party/q5 @@ -1 +1 @@ -Subproject commit 489449c65d408c649ec4ceeb3fa1ad48a692eb61 +Subproject commit b065fccf5cc960b8a411841424ef1de29dceb3ec