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.
355 lines
8.1 KiB
355 lines
8.1 KiB
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 |
|
}
|
|
|