treasurer/payway/payways/fk/api.go

330 lines
7.5 KiB
Go
Raw Normal View History

2023-05-16 16:21:56 +00:00
package fk
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"sort"
"strings"
"time"
)
const UrlFk = "https://api.freekassa.ru/v1"
type ReqCreateInvoice struct {
ShopId int64 `json:"shopId"`
Nonce int64 `json:"none"`
Signature string `json:"signature"`
PaymentId string `json:"paymentId"`
I int64 `json:"i"`
Email string `json:"email"`
IP string `json:"ip"`
Amount float64 `json:"amount"`
Currency string `json:"currency"`
Tel string `json:"tel"`
SuccessUrl string `json:"successUrl,omitempty"`
FailureUrl string `json:"failureUrl,omitempty"`
NotificationUrl string `json:"motificationUrl,omitempty"`
}
type RespCreateInvoice struct {
Type string `json:"type"`
OrderId int `json:"order_id"`
OrderHash string `json:"order_hash"`
Location string `json:"location"`
}
func (pw *FreeKassa) CreatePaymentUrl(paymentType int64, amount float64, orderId, email, ip, currency, phone string) (string, error) {
body, err := pw.create(&ReqCreateInvoice{
ShopId: pw.ShopId,
Nonce: time.Now().Unix(),
PaymentId: orderId,
I: paymentType,
Email: email,
IP: ip,
Amount: amount,
Currency: currency,
Tel: phone,
})
if err != nil {
return "", err
}
resp, err := http.Post(UrlFk+"/orders/create", "application/json", bytes.NewReader(body))
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return "", err
}
var result RespCreateInvoice
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return "", err
}
if result.Type != "success" {
return "", fmt.Errorf("create link bad response: %v", result)
}
return result.Location, nil
}
type ReqOrdersHistory struct {
ShopId int64 `json:"id"`
Nonce int64 `json:"nonce"`
Signature string `json:"signature"`
DateFrom string `json:"dateFrom"`
DateTo string `json:"dateTo"`
}
type RespOrdersHistory struct {
Type string `json:"type"`
Pages int64 `json:"pages"`
Orders []Order `json:"orders"`
}
type Order struct {
MerchantOrderId string `json:"merchant_order_id"`
FkOrderId int64 `json:"fk_order_id"`
Amount float64 `json:"amount"`
Currency string `json:"currency"`
Email string `json:"email"`
Account string `json:"account"`
Date string `json:"date"`
Status int `json:"status"`
}
func (pw *FreeKassa) GetOrdersHistory() ([]Order, error) {
var resp RespOrdersHistory
if err := pw.apiRequest("https://api.freekassa.ru/v1/orders", &pw.getOrders, &ReqOrdersHistory{
ShopId: pw.ShopId,
Nonce: time.Now().Unix(),
}, &resp); err != nil {
return nil, err
}
return resp.Orders, nil
}
type ReqGetWallet struct {
ShopId int64 `json:"shopId"`
Nonce int64 `json:"nonce"`
Signature string `json:"signature"`
}
type WalletResp struct {
Type string `json:"type"`
Balance []Wallet `json:"balance"`
}
type Wallet struct {
Currency string `json:"currency" bson:"cur"`
Value string `json:"value" bson:"val"`
}
func (pw *FreeKassa) GetWallet() ([]Wallet, error) {
var resp WalletResp
if err := pw.apiRequest("https://api.freekassa.ru/v1/balance", &pw.wallet, &ReqGetWallet{
ShopId: pw.ShopId,
Nonce: time.Now().Unix(),
}, &resp); err != nil {
return nil, err
}
fmt.Println("wallet", resp)
return resp.Balance, nil
}
type CurreciesResp struct {
Type string `json:"type"`
Currencies []Currency `json:"currencies"`
}
type Currency struct {
Id int `json:"id" bson:"id"`
Name string `json:"name" bson:"name"`
Currency string `json:"currency" bson:"cur"`
IsEnabled uint8 `json:"is_enabled" bson:"is_enabled"`
IsFavourite uint8 `json:"is_favourite" bson:"is_fav"`
}
func (pw *FreeKassa) GetCurrencies() ([]Currency, error) {
var resp CurreciesResp
if err := pw.apiRequest("https://api.freekassa.ru/v1/currencies", &pw.wallet, &ReqGetWallet{
ShopId: pw.ShopId,
Nonce: time.Now().Unix(),
}, &resp); err != nil {
return nil, err
}
fmt.Println("currencies", resp)
return resp.Currencies, nil
}
type ShopResp struct {
Type string `json:"type"`
Shops []Shop `json:"shops"`
}
type Shop struct {
Id int `json:"id" bson:"id"`
Name string `json:"name" bson:"name"`
Url string `json:"url" bson:"url"`
}
func (pw *FreeKassa) GetShops() ([]Shop, error) {
var resp ShopResp
if err := pw.apiRequest("https://api.freekassa.ru/v1/shops", &pw.wallet, &ReqGetWallet{
ShopId: pw.ShopId,
Nonce: time.Now().Unix(),
}, &resp); err != nil {
return nil, err
}
fmt.Println("shops", resp)
return resp.Shops, nil
}
type WithdrawalCurrenciesResp struct {
Type string `json:"type"`
Currencies []WithdrawalCurrencie `json:"currencies"`
}
type WithdrawalCurrencie struct {
Id int `json:"id" bson:"id"`
Name string `json:"name" bson:"name"`
Min float64 `json:"min" bson:"min"`
Max float64 `json:"max" bson:"max"`
Currency string `json:"currency" bson:"cur"`
CanExcahnge uint8 `json:"can_exchange" bson:"can_exch"`
}
func (pw *FreeKassa) GetWithdrawalCurrencies() ([]WithdrawalCurrencie, error) {
var resp WithdrawalCurrenciesResp
if err := pw.apiRequest("https://api.freekassa.ru/v1/withdrawals/currencies", &pw.wallet, &ReqGetWallet{
ShopId: pw.ShopId,
Nonce: time.Now().Unix(),
}, &resp); err != nil {
return nil, err
}
fmt.Println("withdrawals cur", resp)
return resp.Currencies, nil
}
type Access struct {
Type string `json:"type"`
}
func (pw *FreeKassa) Accesable(id int) (bool, error) {
var resp Access
if err := pw.apiRequest(fmt.Sprintf("https://api.freekassa.ru/currencies/%d/status", id), &pw.wallet, &ReqGetWallet{
ShopId: pw.ShopId,
Nonce: time.Now().Unix(),
}, &resp); err != nil {
return false, nil
}
if resp.Type != "success" {
return false, nil
}
return true, nil
}
func (pw *FreeKassa) apiRequest(url string, p *preparer, r, dest any) error {
body, err := (*p)(r)
if err != nil {
return err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(body))
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
return fmt.Errorf("status code: %d\nbad response: %s", resp.StatusCode, string(b))
}
if err := json.NewDecoder(resp.Body).Decode(dest); err != nil {
return err
}
return nil
}
func (pw *FreeKassa) prepareData(shape any) func(data any) ([]byte, error) {
var (
sind []int
indexes [][]int
)
func() {
var (
fieldNames []string
ind = map[string][]int{}
)
for _, f := range reflect.VisibleFields(reflect.Indirect(reflect.ValueOf(shape)).Type()) {
name := strings.Split(f.Tag.Get("json"), ",")[0]
if name != "signature" {
fieldNames = append(fieldNames, name)
ind[name] = f.Index
} else {
sind = f.Index
}
}
sort.Strings(fieldNames)
for _, i := range fieldNames {
indexes = append(indexes, ind[i])
}
}()
return func(data any) ([]byte, error) {
val := reflect.Indirect(reflect.ValueOf(data))
var forsign []string
for _, fn := range indexes {
forsign = append(forsign, fmt.Sprint(val.FieldByIndex(fn)))
}
val.FieldByIndex(sind).Set(reflect.ValueOf(pw.createSign([]byte(strings.Join(forsign, "|")))))
return json.Marshal(data)
}
}
func (pw *FreeKassa) createSign(data []byte) string {
sign := hmac.New(sha256.New, pw.byteKey)
sign.Write(data)
return fmt.Sprintf("%x", sign.Sum(nil))
}