Перейти к содержанию

Коллбэки (callbacks)#

Для уведомлений мерчанта об изменениях ордера в системе MoneyMania предусмотрен механизм коллбэков.

Структура запроса#

Если при создании ордера мерчант указал webhook URL, на него будут отправляться POST-запросы.

Заголовки:

  • Content-Type: application/json
  • X-Signature: <SIGNATURE> - подпись запроса. См. ниже раздел "Аутентификация"

Тело запроса:

{
  "id": "9c37e448-84b5-4639-9ffa-29558f8f2567",
  "idTransactionMerchant": null,
  "status": "payment_pending",
  "orderType": "PayIn",
  "amount": 10,
  "amountComission": 0.5,
  "usdtAmount": 5.617978,
  "usdtAmountComission": 0.280899,
  "currency": "AZN",
  "dateAdded": "2025-11-28T16:08:06.310479Z",
  "dateUpdated": "2025-11-28T16:08:06.825346Z",
  "exchangeRate": 1.78,
  "merchantID": "e7eb6ae1-f477-4712-99ca-b93e6e95824b"
}

Описание полей:

Поле Тип Обязательное Описание
id string да Уникальный ID ордера в системе MoneyMania
idTransactionMerchant string нет ID ордера в системе мерчанта (если был указан при создании ордера)
status string да Статус ордера. См. статусную модель
orderType string да Тип ордера
amount float64 нет Сумма ордера в валюте ордера
amountComission float64 нет Сумма комиссии мерчанта в валюте ордера
usdtAmount float64 нет Сумма ордера в USDT
usdtAmountComission float64 нет Сумма комиссии по ордеру мерчанта в USDT
currency string нет Валюта ордера
dateAdded string нет Дата и время создания ордера
dateUpdated string нет Дата и время последнего обновления ордера
exchangeRate float64 нет Курс валюты ордера к USDT (1 USDT = X currency)
merchantID string нет ID мерчанта, от которого поступил ордер

Верификация#

Для проверки подлинности полученных запросов в системе мерчанта в каждом запросе отправляется подпись запроса.

Алгоритм получения подписи:

  1. Вычислить SHA256 хэш от тела запроса
  2. Подписать приватным RSA (PKCS #1 v1.5) ключом
  3. Закодировать в base64 std encoding

Полученная подпись передается в заголовке X-Signature.

Алгоритм верификации#

При получении запроса на webhook endpoint необходимо верифицировать его подпись по следующему алгоритму:

  1. Декодировать из base64 значение заголовка X-Signature
  2. Вычислить SHA256 хэша от полученного тела запроса
  3. Верифицировать подпись при помощи публичного ключа RSA
Пример реализации на Go
package main

import (
    "crypto"
    "crypto/rsa"
    "crypto/sha256"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "errors"
    "fmt"
)

func VerifyRSASignature(publicKey *rsa.PublicKey, data []byte, signatureBase64 string) error {
    signature, err := base64.StdEncoding.DecodeString(signatureBase64)
    if err != nil {
        return err
    }

    hash := sha256.Sum256(data)

    err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hash[:], signature)
    if err != nil {
        return err
    }

    return nil
}

func main() {
    data := []byte(`<HTTP-REQUEST-BODY>`)
    signature := "<X-SIGNATURE-HEADER-VALUE>"
    pubKeyPEM := `<PUBLIC-KEY>`

    block, _ := pem.Decode([]byte(pubKeyPEM))
    if block == nil || block.Type != "PUBLIC KEY" {
        panic("не удалось декодировать публичный ключ")
    }

    pubKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }

    pubKey, ok := pubKeyInterface.(*rsa.PublicKey)
    if !ok {
        panic("не удалось привести ключ к *rsa.PublicKey")
    }

    err = VerifyRSASignature(pubKey, data, signature)
    if err != nil {
        fmt.Println("Подпись недействительна:", err)
    } else {
        fmt.Println("Подпись верна!")
    }
}

Публичные RSA ключи#

Stage контур:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuev9IuK5dNP7jck6SMJv
0Mz9g6uEOUec07qZzl0C7wYIz6Rn6NXlFIjnmhA1oVTU+dv3aOKnSouxXOeJWnZj
zTaXoxoLSctQ/JCwo10khhj6yMKA82fXsnrPWnueeXHAg+Fyuck2d/6slrnhRJFB
NEFZqX9M24aA5/BenJ627NSOk+TaaYWAfwNmNc51Ywuc+F47F7ddmSGb/qt60TR8
43pxcX/VqJ7NrIs2dPbKA1I6DSYHmEO5omzrMDEYOtjFkDhwpNzmhAqHaM+K+sXV
32cu8N76SdCjVTuXdw9oyKbc/2lMsyBIAN9Jv5xeo3oyRAHOw5/8siERY1OIdDh+
wQIDAQAB
-----END PUBLIC KEY-----

Prod контур:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAva6UlkdG8Sy9w/u62YIN
0Hc55OIGw0C2zcx66mEuJUUyISst1olgpE4edSPlVSjxVDQh3k4L0EOy2SoqDLqR
qHGrHqG5jIaiqSTUUFTHmmkORbWD0aMpsZr1jFC/eKGLplp0fjfuOegB35rryF/o
8AKEDiy7Pm2s5KCelS4blet9on7FEYR0C+j1ZzZQK05Vh3diHUbiNNdgZHWtvDHC
Fk5VksPPG1rkhqJcZrb5pnqIkIIBVeTuYS9ZpPeOljckkKNNc3dIGzidyyzv9D7L
oFFcjWK2HTRTyPryaPy0jf+iWTcDeuGmI4j97S7NilcY+iu9ZvvspJZqDFBSTlrg
wwIDAQAB
-----END PUBLIC KEY-----

Условия отправки callback-запросов#

Условия отправки callback-запросов зависят от направления, типа и флоу ордера. Описаны на страницах отдельных интеграций.