treasurer/payway/bt_api.go

323 lines
8.8 KiB
Go
Raw Normal View History

2023-05-16 16:21:56 +00:00
package payway
import (
"bitbucket.org/skeris/treasurer/dal"
"bytes"
"context"
"crypto/md5"
"encoding/json"
"errors"
"fmt"
"github.com/rs/xid"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
)
//#region ========= Payment =========
type ReqCreatePaymentUrlBt struct {
Amount string `json:"amount"` // Required
Currency string `json:"currency"` // Required
OrderId string `json:"orderId"` // Required
PaymentSystem string `json:"paymentSystem,omitempty"`
UrlResult string `json:"urlResult,omitempty"`
UrlSuccess string `json:"urlSuccess,omitempty"`
UrlFail string `json:"urlFail,omitempty"`
Locale string `json:"locale,omitempty"`
PayerPhone string `json:"payerPhone,omitempty"`
PayerName string `json:"payerName,omitempty"`
PayerEmail string `json:"payerEmail,omitempty"`
PayerFirstName string `json:"payer_firstname,omitempty"`
PayerLastName string `json:"payer_lastname,omitempty"`
PayerPostCode string `json:"payer_postcode,omitempty"`
PayerAddress string `json:"payer_address,omitempty"`
Ip string `json:"ip,omitempty"`
UserComment string `json:"user_comment"` // Returned in Callback
Sign string `json:"sign"` // Required
}
type RespCreatePaymentUrlBt struct {
Status interface{} `json:"status"`
Id int64 `json:"id"`
Url string `json:"url"`
UrlPayment string `json:"urlPayment"`
}
// CreatePaymentUrl - создает ссылку для перевода средств на кошелек (пополнение счета клиента)
func (bt *BetaTransfer) CreatePaymentUrl(amount, orderID, paymentType, currency, lang, email, phone, requesterID,
userIP string) (string, error) {
action := UrlBt + "/payment?token=" + bt.Secret1
data := ReqCreatePaymentUrlBt{
Amount: amount,
Currency: currency,
OrderId: orderID,
PaymentSystem: paymentType,
UrlResult: "",
UrlSuccess: "",
UrlFail: "",
Locale: lang,
PayerPhone: phone,
PayerName: "",
PayerEmail: email,
PayerFirstName: "",
PayerLastName: "",
PayerPostCode: "",
PayerAddress: "",
Ip: "",
UserComment: requesterID,
Sign: "",
}
body, err := bt.prepareData(data)
fmt.Println("Request:", string(body))
if err != nil {
fmt.Println("MarshalErr:", err)
}
params := url.Values{}
params.Add("amount", data.Amount)
params.Add("currency", data.Currency)
params.Add("orderId", xid.New().String())
params.Add("paymentSystem", data.PaymentSystem)
params.Add("locale", lang)
params.Add("user_comment", orderID)
json.Unmarshal(body, &data)
params.Add("sign", data.Sign)
resp, err := http.PostForm(action, params)
fmt.Println("Status:", resp.Status)
var result RespCreatePaymentUrlBt
bodyr, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(" ioutil: ", err)
}
if resp.StatusCode != 200 {
return "", errors.New("bad response: " + string(bodyr))
}
err = json.Unmarshal(bodyr,&result)
if err != nil {
log.Println(" json: ", err)
}
fmt.Println(result)
return result.Url, nil
}
// PaymentListener - Обрабатывает результат перевода
func (bt *BetaTransfer) PaymentListener(ctx context.Context,ip string, request interface{}, mc *dal.MongoConnection) error {
data := request.(*ReqPaymentListenerBt)
if data.Sign != fmt.Sprintf("%x",
md5.Sum([]byte(fmt.Sprint(data.Amount)+data.OrderId+bt.Secret2))) {
return errors.New(fmt.Sprintf("wrong sign: %v, %s, %s", data.Sign, data.OrderId, bt.Secret2))
}
// Проверка существования платежа в БД
payment, err := mc.GetPayment(ctx, data.UserComment)
if err != nil {
return err
}
if payment == nil {
return errors.New("payment not found")
}
// Проверка статуса платежа (должен быть open)
//if payment.Status != "open" || {
// return errors.New(fmt.Sprintf("payment have status: %v", payment.Status))
//}
// Проверка суммы платежа
//if data.Amount != payment.Amount {
// return errors.New(fmt.Sprintf("wrong amount: %v", data.Amount))
//}
//
//// Проверка RequesterID
//if data.RequesterID != payment.RequesterID {
// return errors.New(fmt.Sprintf("wrong us_requesterID: %v", data.RequesterID))
//}
// Обновление статуса платежа в БД
if payment.Status != "accepted" {
err = mc.UpdatePaymentStatus(ctx, data.UserComment, "accepted")
if err != nil {
return err
}
}
return nil
}
func (bt *BetaTransfer) GetPaymentList() ([]dal.PayWayPayment, error) {
//TODO: implement me
return bt.GetPaymentTypeList(), nil
}
//#endregion
//#region ========= Payout =========
type ReqCreatePayoutBt struct {
Amount string `json:"amount,omitempty"` // Required
Currency string `json:"currency"` // Required
OrderId string `json:"orderId"` // Required
PaymentSystem string `json:"paymentSystem"` // Required
UrlResult string `json:"urlResult,omitempty"`
Address string `json:"address"` // Required. Purse
Sign string `json:"sign"` // Required
}
type RespCreatePayoutBt struct {
Status string `json:"status"`
Id int `json:"id"`
PaymentSystem string `json:"paymentSystem"`
OrderId string `json:"orderId"`
OrderAmount string `json:"orderAmount"`
OrderCurrency string `json:"orderCurrency"`
PaymentAmount string `json:"paymentAmount"`
PaymentCurrency string `json:"paymentCurrency"`
Commission string `json:"commission"`
CommissionCurrency string `json:"commissionCurrency"`
}
// CreatePayout - выполняет запрос для вывода средств из кошелька (вывод средств со счета клиента).
// В ответ получает RespCreatePayoutBt
// purse - кошелек для вывода
// amount - сумма для вывода
// desc - описание/комментарий (OrderId)
// exchange = 1 - отключить автообмен
// currency - валюта для вывода
func (bt *BetaTransfer) CreatePayout(amount, orderID, payoutType, currency, address string) (string, error) {
action := UrlBt + "//withdrawal-payment?token=" + bt.Secret1
payout := bt.GetPayoutType(payoutType)
if currency == "" {
currency = payout.Currency
}
data := ReqCreatePayoutBt{
Amount: amount,
Currency: currency,
OrderId: orderID,
PaymentSystem: payoutType,
UrlResult: "",
Address: address,
Sign: "",
}
body, err := bt.prepareData(data)
if err != nil {
fmt.Println("MarshalErr:", err)
}
resp, err := http.Post(action, "application/json", bytes.NewReader(body))
defer func() {
resp.Body.Close()
}()
fmt.Println("Status:", resp.Status)
var result RespCreatePayoutBt
err = json.NewDecoder(resp.Body).Decode(&result)
if resp.StatusCode != 200 {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(" ioutil: ", err)
}
return "", errors.New("bad response: " + string(body))
}
fmt.Println(result)
return strconv.Itoa(result.Id), nil
}
// PayoutListener - обрабатывает результат вывода
func (bt *BetaTransfer) PayoutListener(ctx context.Context, ip string, request interface{}, mc *dal.MongoConnection) error {
fmt.Println("bt.PayoutListener:", request)
return nil
}
func (bt *BetaTransfer) GetPayoutList() ([]dal.PayoutType, error) {
//TODO: implement me
return bt.GetPayoutTypeList(), nil
}
//#endregion
//#region ========= Wallet =========
type RespGetWalletBalanceBt struct {
Account struct {
LockWithdrawal bool `json:"lockWithdrawal"`
LockAccount bool `json:"lockAccount"`
AuthAt int `json:"authAt"`
} `json:"account"`
Balance map[string]string `json:"balance"`
BalanceOnHold map[string]string `json:"balance_on_hold"`
}
// GetWalletBalance - выполняет запрос чтобы узнать баланс кошелька
func (bt *BetaTransfer) GetWalletBalance() (map[string]float64, error) {
action := UrlBt + "/account-info"
params := url.Values{
"token": {bt.Secret1},
"sign": {bt.createSign([]string{bt.Secret1})},
}
action += fmt.Sprintf("?%v", params.Encode())
client := &http.Client{}
resp, err := client.Get(action)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, errors.New(fmt.Sprintf("got bad status: %v", resp.Status))
}
var response RespGetWalletBalanceBt
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}
var result map[string]float64
for key, val := range response.Balance {
if val == "" {
val = "0.0"
}
toFloat, err := strconv.ParseFloat(val, 64)
if err != nil {
return nil, err
}
result[key] = toFloat
}
return result, nil
}
//#endregion