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 }