Skip to content

Commit

Permalink
Merge branch 'stripe2'
Browse files Browse the repository at this point in the history
# Conflicts:
#	go.mod
#	go.sum
#	http_server/handle/auto_order_create.go
  • Loading branch information
scorpiotzh committed Aug 16, 2023
2 parents a4945c1 + 96efbe6 commit caf9eef
Show file tree
Hide file tree
Showing 16 changed files with 257 additions and 67 deletions.
16 changes: 14 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,9 @@ Please familiarize yourself with the meaning of some common parameters before re
"max_year": 2,
"status": 0,
"is_self": false,
"order_id": ""
"order_id": "" ,
"premium_percentage": "0.036", // for usd premium
"premium_base": "0.52" // for usd premium
}
}
```
Expand All @@ -1131,6 +1133,14 @@ Please familiarize yourself with the meaning of some common parameters before re
#### Request

* path: /v1/auto/order/create
* token_id
* eth_eth
* tron_trx
* bsc_bnb
* stripe_usd
* tron_trc20_usdt
* bsc_bep20_usdt
* polygon_matic

```json
{
Expand All @@ -1155,7 +1165,9 @@ Please familiarize yourself with the meaning of some common parameters before re
"data": {
"order_id": "" ,
"payment_address": "" ,
"amount": ""
"amount": "",
"contract_address": "", // for usdt contract
"client_secret": "", // for stripe usd
}
}
```
Expand Down
4 changes: 4 additions & 0 deletions config/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ das:
- "eth_eth"
- "tron_trx"
- "bsc_bnb"
- "stripe_usd"
- "tron_trc20_usdt"
- "bsc_bep20_usdt"
- "polygon_matic"
background_colors:
eth_eth: "#f0fdf4"
tron_trx: "#eff6ff"
Expand Down
5 changes: 5 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/fsnotify/fsnotify"
"github.com/scorpiotzh/mylog"
"github.com/scorpiotzh/toolib"
"github.com/shopspring/decimal"
)

var (
Expand Down Expand Up @@ -116,6 +117,10 @@ type CfgServer struct {
} `json:"cache" yaml:"cache"`
SuspendMap map[string]string `json:"suspend_map" yaml:"suspend_map"`
UnipayAddressMap map[string]string `json:"unipay_address_map" yaml:"unipay_address_map"`
Stripe struct {
PremiumPercentage decimal.Decimal `json:"premium_percentage" yaml:"premium_percentage"`
PremiumBase decimal.Decimal `json:"premium_base" yaml:"premium_base"`
} `json:"stripe" yaml:"stripe"`
}

type Server struct {
Expand Down
16 changes: 13 additions & 3 deletions dao/t_order_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,18 @@ func (d *DbDao) GetMintOrderInProgressByAccountIdWithAddr(accountId, addr string
return
}

func (d *DbDao) CreateOrderInfo(info tables.OrderInfo) error {
return d.db.Create(&info).Error
func (d *DbDao) CreateOrderInfo(info tables.OrderInfo, paymentInfo tables.PaymentInfo) error {
return d.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&info).Error; err != nil {
return err
}
if paymentInfo.PayHash != "" {
if err := tx.Create(&paymentInfo).Error; err != nil {
return err
}
}
return nil
})
}

type OrderAmountInfo struct {
Expand All @@ -124,7 +134,7 @@ type OrderAmountInfo struct {

func (d *DbDao) GetOrderAmount(accountId string, paid bool) (result map[string]decimal.Decimal, err error) {
list := make([]*OrderAmountInfo, 0)
db := d.db.Model(&tables.OrderInfo{}).Select("token_id, sum(amount) as amount").
db := d.db.Model(&tables.OrderInfo{}).Select("token_id, sum(amount-premium_amount) as amount").
Where("parent_account_id=? and pay_status=? and order_status=?", accountId, tables.PayStatusPaid, tables.OrderStatusSuccess)
if paid {
db = db.Where("auto_payment_id != ''")
Expand Down
22 changes: 22 additions & 0 deletions dao/t_payment_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,25 @@ func (d *DbDao) GetRefundStatusRefundingList() (list []tables.PaymentInfo, err e
timestamp, tables.PayHashStatusConfirmed, tables.RefundStatusRefunding).Find(&list).Error
return
}

func (d *DbDao) UpdatePayHashStatusToFailByDispute(payHash, orderId string) error {
return d.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Model(tables.OrderInfo{}).
Where("order_id=? AND pay_status=?",
orderId, tables.PayStatusPaid).
Updates(map[string]interface{}{
"order_status": tables.OrderStatusFail,
}).Error; err != nil {
return err
}
if err := tx.Model(tables.PaymentInfo{}).
Where("pay_hash=? AND order_id=? AND pay_hash_status=?",
payHash, orderId, tables.PayHashStatusConfirmed).
Updates(map[string]interface{}{
"pay_hash_status": tables.PayHashStatusFailByDispute,
}).Error; err != nil {
return err
}
return nil
})
}
26 changes: 26 additions & 0 deletions example/stripe_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package example

import (
"fmt"
"github.com/shopspring/decimal"
"testing"
)

func TestAmount(t *testing.T) {
//tokenID, price, decimals := tables.TokenIdErc20USDT, 1.0, int32(6)
//usdAmount := decimal.NewFromFloat(5.52)
//decPrice := decimal.NewFromFloat(price)
//dec := decimal.New(1, decimals)
//amount := usdAmount.Mul(dec).Div(decPrice).Ceil()
//fmt.Println(amount)
//amount = handle.RoundAmount(amount, tokenID)
//fmt.Println(amount)

amount := decimal.NewFromInt(10)
premiumPercentage := decimal.NewFromFloat(0.036)
premiumBase := decimal.NewFromFloat(0.52)
amount = amount.Mul(premiumPercentage.Add(decimal.NewFromInt(1))).Add(premiumBase.Mul(decimal.NewFromInt(100)))
fmt.Println(amount)
amount = decimal.NewFromInt(amount.Ceil().IntPart())
fmt.Println(amount)
}
17 changes: 11 additions & 6 deletions http_server/handle/auto_account_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ type ReqAutoAccountSearch struct {
}

type RespAutoAccountSearch struct {
Price decimal.Decimal `json:"price"`
MaxYear uint64 `json:"max_year"`
Status AccStatus `json:"status"`
IsSelf bool `json:"is_self"`
OrderId string `json:"order_id"`
ExpiredAt uint64 `json:"expired_at"`
Price decimal.Decimal `json:"price"`
MaxYear uint64 `json:"max_year"`
Status AccStatus `json:"status"`
IsSelf bool `json:"is_self"`
OrderId string `json:"order_id"`
ExpiredAt uint64 `json:"expired_at"`
PremiumPercentage decimal.Decimal `json:"premium_percentage"`
PremiumBase decimal.Decimal `json:"premium_base"`
}

type AccStatus int
Expand Down Expand Up @@ -119,6 +121,9 @@ func (h *HttpHandle) doAutoAccountSearch(req *ReqAutoAccountSearch, apiResp *api
return nil
}

resp.PremiumPercentage = config.Cfg.Stripe.PremiumPercentage
resp.PremiumBase = config.Cfg.Stripe.PremiumBase

apiResp.ApiRespOK(resp)
return nil
}
Expand Down
97 changes: 74 additions & 23 deletions http_server/handle/auto_order_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type RespAutoOrderCreate struct {
OrderId string `json:"order_id"`
PaymentAddress string `json:"payment_address"`
ContractAddress string `json:"contract_address"`
ClientSecret string `json:"client_secret"`
Amount decimal.Decimal `json:"amount"`
}

Expand Down Expand Up @@ -139,44 +140,77 @@ func (h *HttpHandle) doAutoOrderCreate(req *ReqAutoOrderCreate, apiResp *api_cod
}
log.Info("usdAmount:", usdAmount.String(), req.Years)
usdAmount = usdAmount.Mul(decimal.NewFromInt(int64(req.Years)))
log.Info("usdAmount:", usdAmount.String(), req.Years)
//log.Info("usdAmount:", usdAmount.String(), req.Years)
amount := usdAmount.Mul(decimal.New(1, tokenPrice.Decimals)).Div(tokenPrice.Price).Ceil()
if amount.Cmp(decimal.Zero) != 1 {
apiResp.ApiRespErr(api_code.ApiCodeError500, fmt.Sprintf("price err: %s", amount.String()))
return nil
}
amount = RoundAmount(amount, req.TokenId)
//
//if req.TokenId == tables.TokenIdStripeUSD && amount.Cmp(decimal.NewFromFloat(0.52)) == -1 {
// apiResp.ApiRespErr(http_api.ApiCodeAmountIsTooLow, "Prices must not be lower than 0.52$")
// return nil
//}
// create order
premiumPercentage := decimal.Zero
premiumBase := decimal.Zero
premiumAmount := decimal.Zero
if req.TokenId == tables.TokenIdStripeUSD {
premiumPercentage = config.Cfg.Stripe.PremiumPercentage
premiumBase = config.Cfg.Stripe.PremiumBase
premiumAmount = amount
amount = amount.Mul(premiumPercentage.Add(decimal.NewFromInt(1))).Add(premiumBase.Mul(decimal.NewFromInt(100)))
amount = decimal.NewFromInt(amount.Ceil().IntPart())
premiumAmount = amount.Sub(premiumAmount)
usdAmount = usdAmount.Mul(premiumPercentage.Add(decimal.NewFromInt(1))).Add(premiumBase.Mul(decimal.NewFromInt(100)))
}

res, err := unipay.CreateOrder(unipay.ReqOrderCreate{
ChainTypeAddress: req.ChainTypeAddress,
BusinessId: unipay.BusinessIdAutoSubAccount,
Amount: amount,
PayTokenId: req.TokenId,
PaymentAddress: config.GetUnipayAddress(req.TokenId),
ChainTypeAddress: req.ChainTypeAddress,
BusinessId: unipay.BusinessIdAutoSubAccount,
Amount: amount,
PayTokenId: req.TokenId,
PaymentAddress: config.GetUnipayAddress(req.TokenId),
PremiumPercentage: premiumPercentage,
PremiumBase: premiumBase,
PremiumAmount: premiumAmount,
})
if err != nil {
apiResp.ApiRespErr(api_code.ApiCodeError500, "Failed to create order by unipay")
return fmt.Errorf("unipay.CreateOrder err: %s", err.Error())
}
log.Info("doAutoOrderCreate:", res.OrderId, res.PaymentAddress, res.ContractAddress, amount)
orderInfo := tables.OrderInfo{
OrderId: res.OrderId,
ActionType: req.ActionType,
Account: req.SubAccount,
AccountId: subAccountId,
ParentAccountId: parentAccountId,
Years: req.Years,
AlgorithmId: hexAddr.DasAlgorithmId,
PayAddress: hexAddr.AddressHex,
TokenId: string(req.TokenId),
Amount: amount,
USDAmount: usdAmount,
PayStatus: tables.PayStatusUnpaid,
OrderStatus: tables.OrderStatusDefault,
Timestamp: time.Now().UnixMilli(),
SvrName: config.Cfg.Slb.SvrName,
}
if err = h.DbDao.CreateOrderInfo(orderInfo); err != nil {
OrderId: res.OrderId,
ActionType: req.ActionType,
Account: req.SubAccount,
AccountId: subAccountId,
ParentAccountId: parentAccountId,
Years: req.Years,
AlgorithmId: hexAddr.DasAlgorithmId,
PayAddress: hexAddr.AddressHex,
TokenId: string(req.TokenId),
Amount: amount,
USDAmount: usdAmount,
PayStatus: tables.PayStatusUnpaid,
OrderStatus: tables.OrderStatusDefault,
Timestamp: time.Now().UnixMilli(),
SvrName: config.Cfg.Slb.SvrName,
PremiumPercentage: premiumPercentage,
PremiumBase: premiumBase,
PremiumAmount: premiumAmount,
}
var paymentInfo tables.PaymentInfo
if req.TokenId == tables.TokenIdStripeUSD && res.StripePaymentIntentId != "" {
paymentInfo = tables.PaymentInfo{
PayHash: res.StripePaymentIntentId,
OrderId: res.OrderId,
PayHashStatus: tables.PayHashStatusPending,
Timestamp: time.Now().UnixMilli(),
}
}
if err = h.DbDao.CreateOrderInfo(orderInfo, paymentInfo); err != nil {
apiResp.ApiRespErr(api_code.ApiCodeDbError, "Failed to create order")
return fmt.Errorf("CreateOrderInfo err: %s", err.Error())
}
Expand All @@ -185,7 +219,24 @@ func (h *HttpHandle) doAutoOrderCreate(req *ReqAutoOrderCreate, apiResp *api_cod
resp.Amount = amount
resp.PaymentAddress = res.PaymentAddress
resp.ContractAddress = res.ContractAddress
resp.ClientSecret = res.ClientSecret

apiResp.ApiRespOK(resp)
return nil
}

func RoundAmount(amount decimal.Decimal, tokenId tables.TokenId) decimal.Decimal {
switch tokenId {
case tables.TokenIdEth, tables.TokenIdBnb, tables.TokenIdMatic:
dec := decimal.New(1, 8)
amount = amount.Div(dec).Ceil().Mul(dec)
case tables.TokenIdCkb, tables.TokenIdDoge:
dec := decimal.New(1, 4)
amount = amount.Div(dec).Ceil().Mul(dec)
case tables.TokenIdTrx, tables.TokenIdErc20USDT,
tables.TokenIdBep20USDT, tables.TokenIdTrc20USDT:
dec := decimal.New(1, 3)
amount = amount.Div(dec).Ceil().Mul(dec)
}
return amount
}
25 changes: 25 additions & 0 deletions http_server/handle/currency_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,31 @@ func (h *HttpHandle) doCurrencyUpdate(req *ReqCurrencyUpdate, apiResp *api_code.
return err
}

// check price
//accountId := common.Bytes2Hex(common.GetAccountIdByAccount(req.Account))
//if req.TokenId == string(tables.TokenIdStripeUSD) {
// ruleConfig, err := h.DbDao.GetRuleConfigByAccountId(accountId)
// if err != nil {
// apiResp.ApiRespErr(api_code.ApiCodeDbError, "Failed to search rule config")
// return fmt.Errorf("GetRuleConfigByAccountId err: %s", err.Error())
// }
// ruleTx, err := h.DasCore.Client().GetTransaction(h.Ctx, types.HexToHash(ruleConfig.TxHash))
// if err != nil {
// apiResp.ApiRespErr(api_code.ApiCodeError500, "Failed to search rule tx")
// return fmt.Errorf("GetTransaction err: %s", err.Error())
// }
// rulePrice := witness.NewSubAccountRuleEntity(req.Account)
// if err = rulePrice.ParseFromTx(ruleTx.Transaction, common.ActionDataTypeSubAccountPriceRules); err != nil {
// apiResp.ApiRespErr(api_code.ApiCodeError500, "Failed to search rules")
// return fmt.Errorf("ParseFromTx err: %s", err.Error())
// }
// for _, v := range rulePrice.Rules {
// if v.Price < 0.52 {
// apiResp.ApiRespErr(http_api.ApiCodeAmountIsTooLow, "Prices must not be lower than 0.52$")
// return nil
// }
// }
//}
//
signKey, signMsg, reqDataStr := req.GetSignInfo()
if err := h.RC.Red.Set(signKey, reqDataStr, time.Minute*10).Err(); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion http_server/handle/distribution_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func (h *HttpHandle) doDistributionList(req *ReqDistributionList, apiResp *api_c
}
log.Infof("account: %s %d", order.Account, order.Amount.IntPart())
token := tokens[order.TokenId]
amount := order.Amount.Div(decimal.NewFromInt(int64(math.Pow10(int(token.Decimals)))))
amount := order.Amount.Sub(order.PremiumAmount).Div(decimal.NewFromInt(int64(math.Pow10(int(token.Decimals)))))
resp.List[idx].Amount = amount.String()
resp.List[idx].Symbol = token.Symbol
}
Expand Down
15 changes: 15 additions & 0 deletions http_server/handle/price_rule_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ func (h *HttpHandle) doPriceRuleUpdate(req *ReqPriceRuleUpdate, apiResp *api_cod
}
parentAccountId := common.Bytes2Hex(common.GetAccountIdByAccount(req.Account))

// check price
//paymentConfig, err := h.DbDao.GetUserPaymentConfig(parentAccountId)
//if err != nil {
// apiResp.ApiRespErr(api_code.ApiCodeDbError, "Failed to get payment config")
// return err
//}
//if _, ok := paymentConfig.CfgMap[string(tables.TokenIdStripeUSD)]; ok {
// for _, v := range req.List {
// if v.Price < 0.52 {
// apiResp.ApiRespErr(http_api.ApiCodeAmountIsTooLow, "Prices must not be lower than 0.52$")
// return nil
// }
// }
//}

txParams, whiteListMap, err := h.rulesTxAssemble(RulesTxAssembleParams{
Req: req,
ApiResp: apiResp,
Expand Down
Loading

0 comments on commit caf9eef

Please sign in to comment.