treasurer/payway/bt_api.go
2023-05-16 19:21:56 +03:00

323 lines
8.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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