You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
356 lines
8.1 KiB
356 lines
8.1 KiB
|
1 year ago
|
package blockpay
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"server/call"
|
||
|
|
"server/common"
|
||
|
|
"server/config"
|
||
|
|
"server/db"
|
||
|
|
"server/pb"
|
||
|
|
"server/util"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/fbsobreira/gotron-sdk/pkg/account"
|
||
|
|
"github.com/fbsobreira/gotron-sdk/pkg/proto/core"
|
||
|
|
"github.com/fbsobreira/gotron-sdk/pkg/store"
|
||
|
|
"github.com/gogo/protobuf/proto"
|
||
|
|
"github.com/liangdas/mqant/log"
|
||
|
|
"gorm.io/gorm"
|
||
|
|
)
|
||
|
|
|
||
|
|
func Recharge(req *pb.InnerRechargeReq) (ret []byte, err error) {
|
||
|
|
log.Debug("player recharge:%+v", *req)
|
||
|
|
accountName := fmt.Sprintf("user%d", req.UID)
|
||
|
|
addr, _ := store.AddressFromAccountName(accountName)
|
||
|
|
if addr == "" {
|
||
|
|
account.CreateNewLocalAccount(&account.Creation{
|
||
|
|
Name: accountName,
|
||
|
|
})
|
||
|
|
addr, _ = store.AddressFromAccountName(accountName)
|
||
|
|
} else {
|
||
|
|
_, _, err := store.UnlockedKeystore(addr, "")
|
||
|
|
if err != nil {
|
||
|
|
log.Error("UnlockedKeystore err:%v", err)
|
||
|
|
|
||
|
|
account.RemoveAccount(accountName)
|
||
|
|
account.CreateNewLocalAccount(&account.Creation{
|
||
|
|
Name: accountName,
|
||
|
|
})
|
||
|
|
addr, _ = store.AddressFromAccountName(accountName)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
util.Go(func() {
|
||
|
|
td := &common.TronData{UID: int(req.UID)}
|
||
|
|
db.Mysql().Get(td)
|
||
|
|
if td.Addr == addr {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if td.ID > 0 {
|
||
|
|
db.Mysql().Update(&common.TronData{UID: int(req.UID)}, map[string]interface{}{"addr": addr})
|
||
|
|
} else {
|
||
|
|
db.Mysql().Create(&common.TronData{UID: int(req.UID), Addr: addr})
|
||
|
|
}
|
||
|
|
})
|
||
|
|
mux.Lock()
|
||
|
|
one := &OneListen{OrderID: req.OrderID, Amount: req.Amount, Expire: time.Now().Unix() + ExpireTime}
|
||
|
|
listens, ok := listenMap[addr]
|
||
|
|
if !ok {
|
||
|
|
listenMap[addr] = []*OneListen{one}
|
||
|
|
} else {
|
||
|
|
listens = append(listens, one)
|
||
|
|
listenMap[addr] = listens
|
||
|
|
}
|
||
|
|
mux.Unlock()
|
||
|
|
|
||
|
|
pbResp := &pb.InnerRechargeResp{APIOrderID: req.OrderID, URL: addr}
|
||
|
|
ret, _ = proto.Marshal(pbResp)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
func Withdraw(req *pb.InnerWithdrawReq) (ret []byte, err error) {
|
||
|
|
log.Debug("player withdraw:%+v", *req)
|
||
|
|
or := &common.WithdrawOrder{OrderID: req.OrderID}
|
||
|
|
db.Mysql().Get(or)
|
||
|
|
if or.Status > common.StatusROrderPay {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
amount := req.Amount / 100
|
||
|
|
if config.GetBase().Release {
|
||
|
|
or.APIPayID, err = transferUSDT("", req.Address, or.OrderID, amount, 1)
|
||
|
|
} else {
|
||
|
|
or.APIPayID, err = transferTRX("", req.Address, or.OrderID, amount, 1)
|
||
|
|
}
|
||
|
|
success := err == nil
|
||
|
|
if success {
|
||
|
|
or.Status = common.StatusROrderFinish
|
||
|
|
} else {
|
||
|
|
or.Status = common.StatusROrderFail
|
||
|
|
}
|
||
|
|
call.WithdrawCallback(or)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
func QueryOrder(req *pb.BlockPayQueryOrderReq) (ret []byte, err error) {
|
||
|
|
log.Debug("query order:%+v", req)
|
||
|
|
resp := new(pb.CommonResp)
|
||
|
|
defer func() {
|
||
|
|
ret, err = proto.Marshal(resp)
|
||
|
|
}()
|
||
|
|
|
||
|
|
or := &common.RechargeOrder{OrderID: req.OrderID}
|
||
|
|
db.Mysql().Get(or)
|
||
|
|
if or.Status == common.StatusROrderPay {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "该订单已完成"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
or = &common.RechargeOrder{APIPayID: req.TxID, Status: common.StatusROrderPay}
|
||
|
|
db.Mysql().Get(or)
|
||
|
|
if len(or.OrderID) > 0 {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = fmt.Sprintf("该交易单号已绑定订单%s", or.OrderID)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
tx, err := tc.GetTransactionByID(req.TxID)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("err:%e", err)
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "查询交易出错"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if len(tx.Ret) == 0 {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "该交易存疑,请联系管理员"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if tx.Ret[0].ContractRet != core.Transaction_Result_SUCCESS {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "该交易已失败"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
for _, v := range tx.RawData.Contract {
|
||
|
|
toAddr, amount := scanContracts(v)
|
||
|
|
if toAddr == "" || amount == 0 {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if amount != or.Amount {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "交易金额与订单不符"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
addr, err1 := store.AddressFromAccountName(fmt.Sprintf("user%d", or.UID))
|
||
|
|
if err1 != nil {
|
||
|
|
log.Error("err:%e", err)
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "获取地址失败"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if addr != toAddr {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "交易地址有误"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
_, _, err2 := store.UnlockedKeystore(addr, "")
|
||
|
|
if err2 != nil {
|
||
|
|
log.Error("err:%e", err2)
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "获取私钥失败"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
// ok
|
||
|
|
paySuccess(or.OrderID, toAddr, req.TxID, or.Amount)
|
||
|
|
break
|
||
|
|
}
|
||
|
|
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
func QueryLocalOfficialAddr(req *pb.CommonMsg) (ret []byte, err error) {
|
||
|
|
resp := &pb.BlockPayQueryLocalAddrResp{}
|
||
|
|
for _, v := range OfficialAddrs {
|
||
|
|
if v == "" {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
one := &pb.OneBlockAddr{
|
||
|
|
Addrres: v,
|
||
|
|
}
|
||
|
|
trx, err := tc.GetAccount(v)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("err:%v")
|
||
|
|
}
|
||
|
|
var bal int64
|
||
|
|
if trx != nil {
|
||
|
|
bal = trx.Balance
|
||
|
|
}
|
||
|
|
one.TRX = util.FormatFloat(float64(bal)/1e6, 6)
|
||
|
|
usdt, err := tc.TRC20ContractBalance(v, TronUSDTAddr)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("err:%v")
|
||
|
|
}
|
||
|
|
var usBal int64
|
||
|
|
if usdt != nil {
|
||
|
|
usBal = usdt.Int64()
|
||
|
|
}
|
||
|
|
one.USDT = util.FormatFloat(float64(usBal)/1e6, 6)
|
||
|
|
resp.Addrs = append(resp.Addrs, one)
|
||
|
|
}
|
||
|
|
log.Debug("get local addr:%v", OfficialAddrs)
|
||
|
|
ret, err = proto.Marshal(resp)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
func AddLocalOfficialAddr(req *pb.BlockPayAddLocalAddrReq) (ret []byte, err error) {
|
||
|
|
log.Debug("add addr:%+v", *req)
|
||
|
|
resp := &pb.CommonResp{}
|
||
|
|
defer func() {
|
||
|
|
ret, err = proto.Marshal(resp)
|
||
|
|
}()
|
||
|
|
if req.Address == "" || req.Private == "" {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "请求参数有误"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if store.FromAddress(req.Address) != nil {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "该地址已添加"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
for i := 1; i < MaxLocalAddress; i++ {
|
||
|
|
name := fmt.Sprintf("official%d", i)
|
||
|
|
addr, _ := store.AddressFromAccountName(name)
|
||
|
|
if addr == "" {
|
||
|
|
_, err = account.ImportFromPrivateKey(req.Private, name, "")
|
||
|
|
OfficialAddrs[i-1] = req.Address
|
||
|
|
if err != nil {
|
||
|
|
log.Error("err:%e", err)
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "导入地址失败"
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "本地地址过多"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
func RemoveLocalOfficialAddr(req *pb.BlockPayAddLocalAddrReq) (ret []byte, err error) {
|
||
|
|
log.Debug("remove addr:%+v", *req)
|
||
|
|
resp := &pb.CommonResp{}
|
||
|
|
defer func() {
|
||
|
|
ret, err = proto.Marshal(resp)
|
||
|
|
}()
|
||
|
|
if req.Address == "" {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "请求参数有误"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
for i, v := range OfficialAddrs {
|
||
|
|
if v == req.Address {
|
||
|
|
err1 := account.RemoveAccount(fmt.Sprintf("official%d", i+1))
|
||
|
|
if err1 != nil {
|
||
|
|
log.Error("err:%e", err1)
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "移除地址失败"
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "地址不存在"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
func Transfer(req *pb.BlockPayTransferReq) (ret []byte, err error) {
|
||
|
|
log.Debug("transfer:%+v", *req)
|
||
|
|
resp := &pb.BlockPayTransferResp{}
|
||
|
|
defer func() {
|
||
|
|
ret, err = proto.Marshal(resp)
|
||
|
|
}()
|
||
|
|
if req.Amount <= 0 || req.FromAddr == "" || req.ToAddr == "" {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "请求参数有误"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
var txid string
|
||
|
|
if req.Type == 1 {
|
||
|
|
txid, err = transferTRX(req.FromAddr, req.ToAddr, "", req.Amount, 3)
|
||
|
|
} else if req.Type == 2 {
|
||
|
|
txid, err = transferUSDT(req.FromAddr, req.ToAddr, "", req.Amount, 3)
|
||
|
|
} else {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "请求参数有误"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "转账失败"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
resp.TxID = txid
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
func GetFee(req *pb.CommonMsg) (ret []byte, err error) {
|
||
|
|
resp := &pb.BlockPayGetFeeResp{}
|
||
|
|
defer func() {
|
||
|
|
ret, err = proto.Marshal(resp)
|
||
|
|
}()
|
||
|
|
resp.Fee = getEnergyUse(0, "")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
func ScanPlayerWallet(req *pb.BlockPayScanPlayerWalletReq) (ret []byte, err error) {
|
||
|
|
log.Debug("ScanPlayerWallet:%+v", *req)
|
||
|
|
resp := &pb.BlockPayScanPlayerWalletResp{}
|
||
|
|
defer func() {
|
||
|
|
ret, err = proto.Marshal(resp)
|
||
|
|
}()
|
||
|
|
sql := ""
|
||
|
|
if req.Down > 0 {
|
||
|
|
sql = fmt.Sprintf("usdt >= %v", req.Down)
|
||
|
|
} else {
|
||
|
|
sql = "usdt > 0"
|
||
|
|
}
|
||
|
|
if req.Up > 0 {
|
||
|
|
sql += fmt.Sprintf(" and usdt <= %v", req.Up)
|
||
|
|
}
|
||
|
|
list := []common.TronData{}
|
||
|
|
db.Mysql().QueryAll(sql, "", &common.TronData{}, &list)
|
||
|
|
|
||
|
|
fee := getEnergyUse(0, "")
|
||
|
|
needTotal := fee * int64(len(list))
|
||
|
|
toaddr := ""
|
||
|
|
for _, v := range OfficialAddrs {
|
||
|
|
if v == "" {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
trx, _ := tc.GetAccount(v)
|
||
|
|
if trx.Balance < needTotal {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
toaddr = v
|
||
|
|
break
|
||
|
|
}
|
||
|
|
|
||
|
|
if toaddr == "" {
|
||
|
|
resp.Code = 2
|
||
|
|
resp.Msg = "trx余额不足"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, v := range list {
|
||
|
|
_, err := transferUSDT(v.Addr, toaddr, "", v.Usdt, 2)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
resp.Fail++
|
||
|
|
} else {
|
||
|
|
resp.Success++
|
||
|
|
db.Mysql().UpdateW(&common.TronData{}, map[string]interface{}{"usdt": gorm.Expr("usdt - ?", v.Usdt)}, fmt.Sprintf("uid = %v and usdt >=%v", v.UID, v.Usdt))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|