Copy package main
import (
"bytes"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"io/ioutil"
"log"
"net/http"
"sort"
"time"
)
const (
// agent - код витрины на стороне Tarlan
agent = "agent"
// serviceCode - идентификатор услуги витрины
serviceCode = "service"
// project - код проекта на стороне Tarlan
project = "project"
// url - URL для отправки запроса
url = "https://agwsapi.tarlanpayments.kz/showcase-gateway/api/v1/action/status"
// secret -secret проекта
secret = "12345"
)
// Response представляет тело ответа от сервера
type Response struct {
Status bool `json:"status"`
StatusCode uint32 `json:"status_code"`
Message string `json:"message"`
Result Result `json:"result"`
}
type Result struct {
ErrorCode uint32 `json:"error_code"`
Message string `json:"message"`
Data Data `json:"data"`
AdditionalData map [ string ] interface {} `json:"additional_data"`
}
type Data struct {
StatusCode string `json:"status_code"`
StatusMessage string `json:"status_message"`
Username string `json:"username"`
Amount float64 `json:"amount"`
Datetime time . Time `json:"datetime"`
Project string `json:"project"`
ServiceCode string `json:"service_code"`
ExternalID string `json:"external_id"`
}
// Body представляет структуру запроса
type Body struct {
Agent string `json:"agent"`
Project string `json:"project"`
ServiseCode string `json:"service_code"`
ExternalID string `json:"external_id"`
}
// MakeSign генерирует подпись для HTTP-запроса
func MakeSign (body Body , secretKey string ) ( string , error ) {
// Конвертируем структуру в map для сортировки
dataMap := make ( map [ string ] interface {})
jsonData, _ := json. Marshal (body)
err := json. Unmarshal (jsonData, & dataMap)
if err != nil {
return "" , err
}
// Удаляем "additional_data", если нужно
delete (dataMap, "additional_data" )
// Сортируем ключи по алфавиту
keys := make ([] string , 0 , len (dataMap))
for key := range dataMap {
keys = append (keys, key)
}
sort. Strings (keys)
// Создаем отсортированный JSON
sortedData := make ( map [ string ] interface {})
for _, key := range keys {
sortedData[key] = dataMap[key]
}
// Преобразуем отсортированные данные в JSON
sortedJson, err := json. Marshal (sortedData)
if err != nil {
return "" , err
}
// Кодируем JSON в base64
base64EncodedData := base64.StdEncoding. EncodeToString (sortedJson)
// Конкатенируем base64-данные с секретом
dataToSign := base64EncodedData + secretKey
// Хешируем SHA-256
sha256Hash := sha256. Sum256 ([] byte (dataToSign))
sign := hex. EncodeToString (sha256Hash[:])
return sign, nil
}
// CheckStatus отправляет POST-запрос и обрабатывает ответ
func CheckStatus (body Body , url, signature string ) ( string , error ) {
// Конвертируем структуру в JSON для отправки
jsonData, err := json. Marshal (body)
if err != nil {
return "" , err
}
// Создаем и отправляем POST-запрос
req, err := http. NewRequest ( "POST" , url, bytes. NewBuffer (jsonData))
if err != nil {
return "" , err
}
// Устанавливаем подпись запроса
req.Header. Set ( "X-Signature" , signature)
req.Header. Set ( "Content-Type" , "application/json" )
client := & http . Client {}
resp, err := client. Do (req)
if err != nil {
return "" , err
}
defer resp.Body. Close ()
// Чтение и обработка ответа
bodyBytes, err := ioutil. ReadAll (resp.Body)
if err != nil {
return "" , err
}
jsonResponse := string (bodyBytes)
// Структура для парсинга ответа
var response Response
err = json. Unmarshal ([] byte (jsonResponse), & response)
if err != nil {
return "" , err
}
log. Printf ( "Status- %v , %v " , resp.StatusCode, jsonResponse)
// Определение поля message
var message string
// Извлечение ответа
if resp.StatusCode == http.StatusOK {
if response.StatusCode == 0 && response.Result.ErrorCode == 0 {
message = response.Result.Data.StatusMessage + ", reference " + response.Result.Data.ExternalID
} else {
message = response.Result.Message
}
} else {
message = response.Message
}
// Вывод ответа и результата
return message, nil
}
func main () {
// URL Запроса
RequestURL := url
// Secret Проекта
SecretKey := secret
// externalID - номер заказа
var externalID string = "reference"
// Тело запроса
requestBody := Body {
Agent: agent,
Project: project,
ServiseCode: serviceCode,
ExternalID: externalID,
}
// Генерация заголовка
sign, err := MakeSign (requestBody, SecretKey)
if err != nil {
log. Println ( "Error generating signature:" , err)
return
}
// Отправка запроса
Message, err := CheckStatus (requestBody, RequestURL, sign)
if err != nil {
log. Panic ( "Error sending request" , err)
return
}
// Вывод message из лога
if Message != "" {
log. Println (Message)
}
}