Ресурсы разработчика

Разработка API

Справочник API, примеры серверов и мобильных приложений, возврат и уведомления в одном руководстве. PHP, Node.js, Python, C#, Java, iOS Swift и Android Kotlin поддерживают ON_SITE и HPP.

REST API · ИНТЕРФЕЙС ОПЛАТЫ

Один заказ. Выберите ON_SITE или HPP.

Создайте заказ на сервере и сохраните связь с локальным заказом. Оба режима используют order_id.

См.Синхронный возврат HPP и асинхронные уведомления ON_SITE/HPP, с кодом PHP, Node.js, Python, C# и Java.

ON_SITE

Окно оплаты на вашей странице

Показывайте сумму, адрес, сеть и QR на своем домене. Сервер запрашивает MochiPay и возвращает безопасные детали.

Посмотреть HTML + PHP →
HPP

Переход на оплату MochiPay

Сервер перенаправляет на payment_url. Проверьте возврат или уведомление через защищенный Query Order.

Посмотреть переход PHP →

Фрагменты checkout.php и функций PHP Demo 1.1.4 (PHP 7.0–8.4). Сначала создайте заказ через order.php для получения обеих ссылок. В рабочей системе загружайте авторизованный заказ из сессии/БД и завершайте идемпотентной транзакцией.

Переход после серверной проверки

HPP · PHP

Validate the stored order binding and destination, then send the Location header before any page output.

checkout.php · HPP branch
// checkout.php: after loading the saved attempt and
// verifying its token, order binding and payment URL.
// $payment is the authenticated Query Order response.
if ($mode === 'HPP') {
    header('Location: ' . $payment['payment_url'], true, 303);
    exit; // Send the header before any HTML output.
}
// Verify the notification/return server-side before fulfillment.

The complete file loads the saved attempt and validates its token, authenticated query and expected payment_url before this branch.

Платёжное окно на своей странице

ON_SITE · PHP + HTML

Include the local dialog assets in your checkout HTML. The browser talks to your local poll endpoint; it never signs requests or receives API credentials.

checkout.php · local dialog assets
// checkout.php: use the SAME saved reference/token.
$pollUrl = 'order.php?' . http_build_query([
    'view' => $reference, 'token' => $token, 'poll' => 1
], '', '&', PHP_QUERY_RFC3986);
$completeUrl = 'callback.php?' . http_build_query([
    'mode' => 'return', 'merchant_order_id' => $reference
], '', '&', PHP_QUERY_RFC3986);
$config = json_encode([
    'poll' => $pollUrl, 'complete' => $completeUrl
], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
?>
<!-- Inside your own checkout page: -->
<link rel="stylesheet" href="portable/onsite.css">
<button id="reopen" type="button">Open payment dialog</button>
<script>window.MochiPayConfig = <?php echo $config; ?>;</script>
<script src="portable/qrcode.min.js"></script>
<script src="portable/onsite.js"></script>

onsite.js opens the dialog over your existing page. Closing it leaves checkout visible; the Open payment dialog button reopens the same payment.

Сервер проверяет заказ

Authorize the saved reference/token, query by the stored MochiPay order_id, and compare the original amount/currency, asset/network, address and exact payable amount. Return only a safe payment view with decimal strings.

order.php · local polling endpoint
// order.php?view=...&token=...&poll=1 (server-side)
// The demo has already authorized the saved attempt/token.
$response = mochipay_query_order(
    'order_id', $record['snapshot']['order_id']
);
if (!$response['ok'] || !mochipay_bound($record, $response['data'])) {
    http_response_code(403);
    exit;
}
// Also check the expected received amount before accepting PAID.
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
echo json_encode([
    'success' => true,
    'data' => MochiPayPortable::view($response['data'])
]); // Safe view: decimal strings; no credentials/customer fields.

The full demo additionally verifies the received amount for PAID. callback.php verifies notifications and browser returns. A screenshot, redirect or browser flag is never proof of payment.

Аутентификация

Every API request must include the merchant API key and a Base64-encoded HMAC-SHA256 signature.

HeaderобязательноОписание
X-Mochi-KeyYesYour merchant API key.
X-Mochi-SignatureYesBase64-encoded HMAC-SHA256 signature.
Content-TypePOST requestsapplication/json
Keep your API secret on the server. Never expose it in browser JavaScript, mobile applications or public source code.

Подпись

For Create Order, sign the exact raw JSON body. For Query Order, sign the raw query string without the leading ?.

SIGNATURE FORMULA
Base64(HMAC-SHA256(UTF8(signing_text), UTF8(api_secret)))

Поддерживаемые валюты

The order currency prices the purchase. The payment method selects the cryptocurrency and blockchain network used to pay.

ORDER CURRENCIES

28 supported fiat currencies

Use one of these exact ISO codes in the currency field.

USDEURGBPCAD AUDNZDJPYCNY HKDSGDCHFSEK NOKDKKPLNCZK HUFAEDSARINR IDRTHBMYRPHP KRWBRLMXNZAR
CRYPTO ORDER CURRENCIES

Cryptocurrency pricing

Orders may also be priced directly in these cryptocurrencies.

USDTUSDCBTCETHSOL
PAYMENT METHODS

Supported cryptocurrency and network combinations

Send one of these exact values in the payment_method field.

USDT_TRC20USDT on TRON
USDC_ERC20USDC on Ethereum
BTC_BITCOINNative BTC on Bitcoin
ETH_ERC20Native ETH on Ethereum
SOL_SOLANANative SOL on Solana
Conversion rule: If the order currency and payment asset are the same, MochiPay uses a rate of 1 without conversion. Otherwise, the stored exchange rate and merchant markup are applied when the order is created. View current reference exchange rates →
Order valueСпособ оплатыResult
49.90 USDUSDT_TRC20Uses the stored USD → USDT rate and merchant markup.
100 EURBTC_BITCOINUses the stored EUR → BTC rate and merchant markup.
25 USDCUSDC_ERC20No conversion. The exchange rate is 1.

Создать заказ

Create a payment order with a hosted payment URL and the payment instructions needed for an on-site interface.

POST https://mochi.bz/api/v1/orders/create

Request parameters

Order currency and payment method are different concepts. amountиcurrency define the merchant's original order value. payment_method defines the cryptocurrency and blockchain network used by the customer to pay. For example, 49.90 USD with USDT_TRC20 means that a USD-denominated order is paid with the calculated amount of USDT on the TRON network.
ParameterобязательноType / LengthОписание
merchant_order_idYesstring · 1–100Your order reference. Without request_id, each successful creation receives a new globally unique MochiPay order_id. With request_id, a retry reuses its original order.
amountYesdecimal(28,8)Positive original order amount. Fiat normally uses 2 decimal places; supported cryptocurrencies may use up to 8.
currencyYesstring · 1–20Original order currency code. It may be fiat, such as USD или EUR, or cryptocurrency, such as USDT или USDC.
payment_methodYesasset ≤20 + network ≤30Payment cryptocurrency and blockchain network in ASSET_NETWORK format, such as USDT_TRC20 или USDC_ERC20.
unique_amount_directionNoUP или DOWNDirection used for the small unique amount adjustment. Defaults to UP.
product_typeNoPHYSICAL или DIGITAL_SERVICEOrder type displayed at checkout. Defaults to DIGITAL_SERVICE. Shipping fields remain optional for both types.
descriptionNostring · 0–500Human-readable order description.
product_infoNoJSON/string · nvarchar(max)Product, cart or custom metadata. The complete HTTP request body must not exceed 65,536 bytes.
customer_emailNostring · 0–255Customer email address. When supplied, it must be a valid email address.
customer_phoneNostring · 0–50Customer telephone number.
first_nameNostring · 0–100Customer first name.
last_nameNostring · 0–100Customer last name.
companyNostring · 0–200Customer company or organization name.
countryNostring · 0–100Customer country or region.
stateNostring · 0–100Customer state, province or region.
cityNostring · 0–100Customer city.
address1Nostring · 0–500Primary customer address line.
address2Nostring · 0–500Additional customer address line.
postal_codeNostring · 0–30Customer postal or ZIP code.
request_idNostring · 1–64Optional retry key, scoped to your merchant. Sign it with the JSON body. Reuse the same key and payload after a timeout. See request deduplication.
notify_urlNostring · 0–1000Absolute http:// или https:// asynchronous server notification URL. Only public destinations are allowed; localhost, private/reserved IPs and redirects are blocked.
redirect_urlNostring · 0–1000Absolute customer return URL used after a successful payment.
customer_ipNoIPv4/IPv6 · 0–45Customer IP supplied by the merchant. MochiPay also records the API request IP separately.

Request example

JSON
{
  "merchant_order_id": "ORDER-20260919-001",
  "amount": 49.90,
  "currency": "USD",
  "payment_method": "USDT_TRC20",
  "unique_amount_direction": "UP",
  "product_type": "DIGITAL_SERVICE",
  "description": "MochiPay order",
  "customer_email": "customer@example.com",
  "redirect_url": "https://merchant.example.com/payment/return"
}
C# · CREATE ORDER
string baseUrl = "https://mochi.bz";
string body = @"{
  ""merchant_order_id"": ""ORDER-20260920-001"",
  ""amount"": 49.90,
  ""currency"": ""USD"",
  ""payment_method"": ""USDT_TRC20"",
  ""unique_amount_direction"": ""UP"",
  ""product_type"": ""DIGITAL_SERVICE"",
  ""description"": ""Example order"",
  ""notify_url"": ""https://merchant.example.com/mochipay/notify"",
  ""redirect_url"": ""https://merchant.example.com/payment/return""
}";

string signature;
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret)))
{
    signature = Convert.ToBase64String(
        hmac.ComputeHash(Encoding.UTF8.GetBytes(body)));
}

using (var client = new HttpClient())
using (var request = new HttpRequestMessage(
    HttpMethod.Post, baseUrl + "/api/v1/orders/create"))
{
    request.Headers.Add("X-Mochi-Key", apiKey);
    request.Headers.Add("X-Mochi-Signature", signature);
    request.Content = new StringContent(body, Encoding.UTF8, "application/json");
    HttpResponseMessage response = await client.SendAsync(request);
    string json = await response.Content.ReadAsStringAsync();
}
PHP 7.0–8.4 · CREATE ORDER
<?php
$baseUrl = 'https://mochi.bz';
$apiKey = 'YOUR_API_KEY';
$apiSecret = 'YOUR_API_SECRET';

$payload = [
    'merchant_order_id' => 'ORDER-20260920-001',
    'amount' => '49.90',
    'currency' => 'USD',
    'payment_method' => 'USDT_TRC20',
    'unique_amount_direction' => 'UP',
    'product_type' => 'DIGITAL_SERVICE',
    'description' => 'Example order',
    'notify_url' => 'https://merchant.example.com/mochipay/notify',
    'redirect_url' => 'https://merchant.example.com/payment/return'
];

$body = json_encode($payload, JSON_UNESCAPED_SLASHES);
$signature = base64_encode(
    hash_hmac('sha256', $body, $apiSecret, true)
);

$ch = curl_init($baseUrl . '/api/v1/orders/create');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-Mochi-Key: ' . $apiKey,
        'X-Mochi-Signature: ' . $signature
    ],
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_TIMEOUT => 30
]);

$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);

if ($json === false) {
    throw new RuntimeException($error);
}

// Preserve decimal JSON numbers as text before decoding.
$json = preg_replace(
    '/("(?:amount|base_pay_amount|pay_amount|received_amount|exchange_rate|rate_markup_percent|unique_amount_delta)"\s*:\s*)(-?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?)(?=\s*[,}])/',
    '$1"$2"', $json
);
$result = json_decode($json, true);
if ($httpCode < 200 || $httpCode >= 300 || empty($result['success'])) {
    throw new RuntimeException('MochiPay request failed. Review before retrying creation.');
}
?>

Success response

FieldType / LengthОписание
successbooleanTrue when creation succeeds.
order_idstring · 32MochiPay system identifier. Store it with your local order.
merchant_order_idstring · ≤100Your original merchant reference.
product_typestring · ≤20PHYSICAL or DIGITAL_SERVICE.
statusstring · ≤20Current payment status.
amountdecimal(28,8)Original order amount; preserve decimal precision.
currencystring · ≤20Original pricing currency.
base_pay_amountdecimal(28,8)Converted amount before the unique adjustment.
unique_amount_deltadecimal(28,8)Signed matching adjustment.
unique_amount_directionstring · ≤10UP or DOWN.
pay_amountdecimal(28,8)Exact chain amount to display and send. Do not round.
payment_methodstringSelected asset/network, e.g. USDT_TRC20.
payment_addressstring · ≤255Receiving address for this payment and network.
payment_urlstring · URLHPP URL. On-site uses the same order instructions.
expires_atdatetimeExpiration in yyyy-MM-dd HH:mm:ss format.
HTTP 200 · JSON
{
  "success": true,
  "order_id": "41ad45477bd444f3bd89f0bab7f571bb",
  "merchant_order_id": "ORDER-20261003-001",
  "product_type": "DIGITAL_SERVICE",
  "status": "WAITING_PAYMENT",
  "amount": 49.90,
  "currency": "USD",
  "base_pay_amount": 49.90,
  "unique_amount_delta": 0.001,
  "unique_amount_direction": "UP",
  "pay_amount": 49.901,
  "payment_method": "USDT_TRC20",
  "payment_address": "TExampleReceivingAddressForIllustrationOnly",
  "payment_url": "https://mochi.bz/pay/41ad45477bd444f3bd89f0bab7f571bb",
  "expires_at": "2026-10-03 15:30:00"
}

Запросить заказ

Retrieve an order owned by the authenticated merchant using exactly one order identifier.

GET https://mochi.bz/api/v1/orders/query
Query parameterобязательноType / LengthОписание
order_idOne of twostring · 32MochiPay order identifier.
merchant_order_idOne of twostring · 1–100Your merchant order identifier. If it was reused, the newest matching order is returned.
Use order_id once stored. After an uncertain Create response, query the same unique merchant reference before deciding what happened; repeated Create requests are not guaranteed to be idempotent. Send only one identifier. Sign the exact raw query string, for example merchant_order_id=ORDER-20260919-001.

Query examples

C# · QUERY ORDER
string baseUrl = "https://mochi.bz";
string query = "merchant_order_id=ORDER-20260919-001";

using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret)))
{
    string signature = Convert.ToBase64String(
        hmac.ComputeHash(Encoding.UTF8.GetBytes(query)));

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("X-Mochi-Key", apiKey);
        client.DefaultRequestHeaders.Add("X-Mochi-Signature", signature);
        string json = await client.GetStringAsync(
            baseUrl + "/api/v1/orders/query?" + query);
    }
}
PHP 7.0–8.4 · QUERY ORDER
<?php
$baseUrl = 'https://mochi.bz';
$apiKey = 'YOUR_API_KEY';
$apiSecret = 'YOUR_API_SECRET';
$query = http_build_query(
    ['merchant_order_id' => 'ORDER-20260919-001'],
    '',
    '&',
    PHP_QUERY_RFC3986
);
$signature = base64_encode(
    hash_hmac('sha256', $query, $apiSecret, true)
);

$ch = curl_init($baseUrl . '/api/v1/orders/query?' . $query);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'X-Mochi-Key: ' . $apiKey,
        'X-Mochi-Signature: ' . $signature
    ],
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_TIMEOUT => 30
]);

$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);

if ($json === false) {
    throw new RuntimeException($error);
}

// Preserve decimal JSON numbers as text before decoding.
$json = preg_replace(
    '/("(?:amount|base_pay_amount|pay_amount|received_amount|exchange_rate|rate_markup_percent|unique_amount_delta)"\s*:\s*)(-?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?)(?=\s*[,}])/',
    '$1"$2"', $json
);
$result = json_decode($json, true);
if ($httpCode < 200 || $httpCode >= 300 || empty($result['success'])) {
    throw new RuntimeException('MochiPay request failed. Review before retrying creation.');
}
?>

Success response fields

The query returns wallet_typeиnetwork separately; Create Order returns their combined payment_method. Compare them with the method saved on your local order. Return only necessary payment fields to the customer browser.

FieldType / LengthОписание
order_idstring · 32MochiPay order identifier.
merchant_order_idstring · ≤100Your merchant order identifier.
sourcestring · ≤20Order source, such as API.
descriptionstring · ≤500Order description.
product_typestring · ≤20PHYSICAL или DIGITAL_SERVICE.
product_infoJSON/string/nullProduct or cart information supplied when the order was created.
statusstring · ≤20Overall order payment status.
merchant_statusstring · ≤50Merchant-facing order status.
amountdecimal(28,8)Original order amount.
currencystring · ≤20Original order currency, such as USD, EUR, USDT или USDC.
base_pay_amountdecimal(28,8)Converted payment amount before the unique matching adjustment.
unique_amount_deltadecimal(28,8)Small signed amount added to or subtracted from the base amount.
unique_amount_directionstring · ≤10UP или DOWN.
pay_amountdecimal(28,8)Exact cryptocurrency amount the customer must pay.
received_amountdecimal(28,8)Cryptocurrency amount received so far.
exchange_ratedecimal(38,18)Exchange-rate snapshot used when the order was created.
rate_markup_percentdecimal(9,4)Merchant rate markup snapshot used for the order.
wallet_typestring · ≤20Payment asset: USDT, USDC, BTC, ETH или SOL.
networkstring · ≤30Blockchain network, such as TRC20 или ERC20.
payment_addressstring · ≤255Merchant receiving address selected for this order.
tx_hashstring/null · ≤255Detected customer payment transaction hash.
confirmationsintegerCurrent blockchain confirmation count.
customer_email … postal_codestring/nullOptional customer and shipping fields supplied at order creation.
payment_urlstring · URLHPP checkout URL; on-site integrations query the same order for status and payment instructions.
expires_atdatetimeOrder expiration time.
paid_atdatetime/nullPayment completion time.
created_atdatetimeOrder creation time.
updated_atdatetimeLast order update time.

Примеры кода

PHP, Node.js, Python, C# / .NET Framework, Java, iOS Swift и Android Kotlin. Один сохранённый платёж поддерживает ON_SITE и HPP.

Выберите исходники для приложения

Один актуальный ZIP для каждого языка или мобильной платформы, инструкции на английском. Плагины магазинов поставляются отдельно; существующие интеграции работают.

ПРИМЕР СЕРВЕРА · ON_SITE + HPP

PHP

7.0–8.4

Исходные маршруты PHP: order.php, checkout.php и callback.php

Скачать ZIP
ПРИМЕР СЕРВЕРА · ON_SITE + HPP

Node.js

22+

Общие серверные и мобильные маршруты

Скачать ZIP
ПРИМЕР СЕРВЕРА · ON_SITE + HPP

Python

3.10+

Общие серверные и мобильные маршруты

Скачать ZIP
ПРИМЕР СЕРВЕРА · ON_SITE + HPP

C# / .NET Framework

4.6.1 / VS2019

Общие серверные и мобильные маршруты

Скачать ZIP
ПРИМЕР СЕРВЕРА · ON_SITE + HPP

Java

JDK17+

Общие серверные и мобильные маршруты

Скачать ZIP
МОБИЛЬНЫЕ ИСХОДНИКИ · ON_SITE + HPP

iOS Swift

iOS15+ / Xcode14+

Используйте общий сервер; только исходный проект

Скачать ZIP
МОБИЛЬНЫЕ ИСХОДНИКИ · ON_SITE + HPP

Android Kotlin

API26+ / SDK35 / JDK17

Используйте общий сервер; только исходный проект

Скачать ZIP

Запустите полный серверный сценарий

  1. Настройте закрытые ключи MochiPay, активные кошельки, публичный HTTPS-адрес callback и отдельный тестовый токен. Цену задаёт сервер, браузер её не меняет.
  2. Создавайте или восстанавливайте с сохранённым request_id и неизменным содержимым. Подписывайте точные байты UTF-8 и закодированные запросы через HMAC-SHA256.
  3. Откройте сохранённое окно ON_SITE или переход HPP; оба используют один заказ. ON_SITE включает QR, копирование и выбор десяти языков.
  4. Обработайте notify_url на сервере и повторно запросите сохранённый ID. Возврат и опрос используют одинаковую проверку привязки и точной суммы.
  5. Запишите проверенный платёж один раз. Перед запуском замените тестовые файлы и отметки авторизацией пользователя и атомарным обновлением БД.

PHP сохраняет order.php / checkout.php / callback.php. Четыре других сервера предоставляют общие маршруты ниже для браузера и приложений.

МаршрутНазначение
POST /paymentsСоздать или восстановить товар с серверной ценой; request_id, payment_method и тестовый bearer-токен.
GET /checkout?r=…&t=…&mode=ON_SITEЛокальное платёжное окно продавца для сохранённого заказа.
GET /checkout?…&mode=HPPПереход 303 после проверки привязки и адреса назначения.
GET /status?r=…&t=…Подписанный запрос MochiPay; минимальный DTO с суммами как десятичными строками.
POST /callback?r=…&t=…Асинхронная проверка и однократная отметка оплаты.
GET /complete?r=…&t=…Страница синхронного возврата с проверенным результатом.

Мобильная оплата без секретов API в приложении

Swift и Kotlin используют любой из четырёх общих серверов. В приложении задайте только HTTPS-адрес продавца. ON_SITE показывает локальную оплату в WKWebView или Android WebView; HPP открывает переход продавца во внешнем браузере. При активации приложение снова проверяет сервер; закрытие не прекращает серверные уведомления.

Сохранённый ID переживает повторы и перезапуск. Смена интерфейса или языка использует тот же заказ. Тестовый токен независим от ключей MochiPay; замените его авторизованной пользовательской сессией приложения.

Это исходные примеры интеграции, не нативные SDK и не одобрения магазинов приложений. Проверьте актуальныеправила оплаты Appleиполитику платежей Google Playдля продукта и региона.

Проверка перед запуском

Следуйте README и TESTING.md каждого пакета. Локальные подписанные тесты проверяют повторы, неверные привязки, неоплаченные состояния и дубли уведомлений. Нужна проверка в staging через Xcode/Android Studio, реальные устройства и небольшой реальный платёж. Новые таблицы MochiPay и переустановка плагинов не требуются.

Реализовать синхронный возврат и асинхронные уведомления →

Возврат и уведомления

Один серверный проверяющий модуль обрабатывает синхронный возврат HPP, асинхронные уведомления HPP и обновления ON_SITE.

Разные входы. Одно проверенное обновление заказа.

СценарийПоле API / входЦель
Синхронный возврат HPPredirect_url · GET браузераПоказ результата после подписанного серверного запроса. Клиент может не вернуться.
Асинхронное уведомление HPPnotify_url · POST сервераПроверка и обновление локального заказа независимо от браузера.
Асинхронное уведомление ON_SITEТот же notify_url · POST сервераОбновление заказа даже при закрытом окне или приложении.
Отображение статуса ON_SITEБраузер/приложение опрашивает /status продавцаМинимальный результат той же серверной проверки.

HPP: синхронный возврат браузера

При создании сохраните redirect_url с токеном локального заказа. Пример: HTTPS /complete?r=…&t=…. После размещённой оплаты загрузите заказ, проверьте владельца/токен и подпишите Query Order с сохранённым order_id MochiPay.

Показывайте PAID только после проверки привязки и точной полученной суммы; иначе ожидание или проверка. URL, сообщение браузера или снимок не доказывают оплату. Callback может прийти до или после возврата.

HPP и ON_SITE: асинхронное серверное уведомление

Сохраните notify_url при создании; примеры: /callback?r=…&t=…. MochiPay отправляет POST независимо от браузера. Входящие поля — только подсказки для поиска. Запросите авторизованный API и сравните сохранённые ID, ссылку заказа, исходную сумму/валюту, актив/сеть, адрес и точную сумму оплаты.

Требуйте PAID и received_amount строго равное pay_amount. Атомарно запишите один раз; повторные корректные уведомления получают OK без двойного обновления или доставки. Неподтверждённые состояния, неверные привязки и ошибки запроса/хранения не подтверждаются как успешная оплата.

Примеры сохраняют однократную отметку paid_verified. Замените её транзакцией в своей БД заказов; она не доставляет товары. Только тело callback никогда не обновляет заказ.

ON_SITE: асинхронные обновления и опрос окна

ON_SITE использует тот же notify_url и продолжает проверку при закрытом окне или offline-приложении. Видимое окно опрашивает только авторизованный сервер каждые 15 секунд. Сервер запрашивает MochiPay и возвращает необходимые поля с десятичными суммами в строках. PAID использует ту же проверку, что callback; секреты API и полные клиентские данные не попадают в браузер.

Закрытие, повторное открытие или смена ON_SITE/HPP использует сохранённый платёж. После тайм-аута сохраняйте request_id и точное содержимое; смена ссылки заказа может создать лишний заказ.

Исполняемый код в каждом серверном пакете

Каждый пример включает оба режима, уведомления, возврат, безопасный статус и сохранённую попытку. notify_url и redirect_url — поля API; режим выбирается локально, не в Create Order.

Node.js · проверка, возврат и уведомление

Фрагменты исполняемого пакета. Переменные маршрутов и функции хранения определены в полном коде; используйте полную интеграцию.

async function verify(r,t){const a=load(r);if(!equal(a.token,t)||!a.snapshot)throw Error('Invalid payment capability');const d=await api('/api/v1/orders/query','order_id='+encodeURIComponent(a.snapshot.order_id));bind(a,d);if(d.status==='PAID'&&!a.paid_verified){a.paid_verified=true;save(r,a)}return d}

// HPP redirect_url -> GET /complete: verify before displaying result.
await verify(r,t);
// notify_url -> POST /callback: same verification and atomic once-only marker.
const d=await verify(r,t);
output(res,d.status==='PAID'?200:409,'text/plain',d.status==='PAID'?'OK':'Payment not confirmed');
// ON_SITE polling -> GET /status: only the safe DTO reaches the browser.
json(res,200,{success:true,data:safe(await verify(r,t))});
Python · проверка, возврат и уведомление

Фрагменты исполняемого пакета. Переменные маршрутов и функции хранения определены в полном коде; используйте полную интеграцию.

def verify(r, t):
    a = load(r)
    if not isinstance(t,str) or not hmac.compare_digest(a['token'],t) or not a.get('snapshot'): raise ValueError('Invalid capability')
    d = api('/api/v1/orders/query',urlencode({'order_id':a['snapshot']['order_id']})); bind(a,d)
    if d.get('status') == 'PAID' and not a['paid_verified']: a['paid_verified'] = True; save(r,a)
    return d

# HPP browser return
verify(r,t)
# HPP and ON_SITE server notification (inside the handler lock)
d = verify(r,t)
self.out(200 if d['status']=='PAID' else 409,'text/plain','OK' if d['status']=='PAID' else 'Payment not confirmed')
# ON_SITE display only
self.jout(200,dict(success=True,data=safe(verify(r,t))))
C# / .NET Framework · проверка, возврат и уведомление

Фрагменты исполняемого пакета. Переменные маршрутов и функции хранения определены в полном коде; используйте полную интеграцию.

        static JObject Verify(string r,string t)
        {
            var a=Load(r);if(!Equal(S(a,"token"),t)||a["snapshot"]==null)throw new Exception("Invalid capability");var d=Api("/api/v1/orders/query",null,"order_id="+Uri.EscapeDataString(S(a["snapshot"],"order_id")));Bind(a,d);
            if(S(d,"status")=="PAID"&&!(bool)a["paid_verified"]){a["paid_verified"]=true;Save(r,a);}return d;
        }

// GET /complete: verified HPP return.
Verify(r,t);
// POST /callback: asynchronous notification for both modes.
var d=Verify(r,t);
Out(res,S(d,"status")=="PAID"?200:409,"text/plain",S(d,"status")=="PAID"?"OK":"Payment not confirmed");
// GET /status: display only the minimal DTO.
JOut(res,200,new JObject {{"success",true},{"data",Safe(Verify(r,t))}});
Java · проверка, возврат и уведомление

Фрагменты исполняемого пакета. Переменные маршрутов и функции хранения определены в полном коде; используйте полную интеграцию.

    static JsonObject verify(String r,String t)throws Exception{JsonObject a=load(r);if(!equal(s(a,"token"),t)||!a.has("snapshot"))throw new IllegalArgumentException("Invalid capability");JsonObject d=api("/api/v1/orders/query",null,"order_id="+enc(s(a.getAsJsonObject("snapshot"),"order_id")));bind(a,d);if(s(d,"status").equals("PAID")&&!a.get("paid_verified").getAsBoolean()){a.addProperty("paid_verified",true);save(r,a);}return d;}

// GET /complete: verified HPP return.
verify(r,t);
// POST /callback: both presentation modes use this route.
boolean paid=s(verify(r,t),"status").equals("PAID");
out(x,paid?200:409,"text/plain",paid?"OK":"Payment not confirmed");
// GET /status: minimal safe display DTO.
jout(x,200,object("success",true,"data",safe(verify(r,t))));
PHP · проверка, возврат и уведомление

Фрагменты исполняемого пакета. Переменные маршрутов и функции хранения определены в полном коде; используйте полную интеграцию.

    // Authenticate the result by querying MochiPay server-to-server.
    $verified = mochipay_query_order('order_id', $orderId);
    if (!$verified['ok'] || !is_array($verified['data'])) {
        callback_text(503, 'VERIFICATION_FAILED');
    }

    $order = $verified['data'];
    if (!isset($order['order_id']) || !hash_equals((string) $order['order_id'], $orderId)) {
        callback_text(409, 'ORDER_MISMATCH');
    }

    $verifiedMerchantId = isset($order['merchant_order_id']) ? (string)$order['merchant_order_id'] : '';
    try { $record = mochipay_load($verifiedMerchantId); }
    catch (Exception $e) { callback_text(503, 'LOCAL_STORAGE_UNAVAILABLE'); }
    if (!mochipay_bound($record, $order) || (isset($callback['merchant_order_id']) && !hash_equals($verifiedMerchantId, (string)$callback['merchant_order_id']))) callback_text(409, 'LOCAL_ORDER_MISMATCH');
    if (!isset($order['received_amount']) || MochiPayPortable::decimal($order['received_amount']) !== MochiPayPortable::decimal($order['pay_amount'])) callback_text(409, 'PAYMENT_AMOUNT_REQUIRES_REVIEW');

    if (!isset($order['status']) || strtoupper((string) $order['status']) !== 'PAID') {
        callback_text(409, 'ORDER_NOT_PAID');
    }

    /*
     * TODO: In your production database, atomically fulfill the bound local order.
     * This demo acknowledges verification only; it does not deliver goods.
     * Make the operation idempotent: repeated callbacks must not deliver goods
     * or credit the customer more than once.
     */
    try { mochipay_record_verified($record, $order); }
    catch (Exception $e) { callback_text(503, 'LOCAL_UPDATE_FAILED'); }
    callback_text(200, 'OK');
}

// GET browser return verifies the saved capability, then queries the saved ID.
$authorized = $record && $returnToken !== '' && hash_equals($record['token'], $returnToken);
if ($authorized) {
    $verified = mochipay_query_order('order_id', $record['snapshot']['order_id']);
    $paid = $verified['ok'] && mochipay_record_verified($record, $verified['data']);
}
Скачать полные примеры

Ответы об ошибках

Errors return an HTTP status code and a stable machine-readable message.

JSON
{ "success": false, "message": "INVALID_SIGNATURE" }
HTTPMessageОписание
400INVALID_JSON / INVALID_AMOUNTRequest data is invalid.
400INVALID_CURRENCY / INVALID_PAYMENT_METHODCurrency or payment method is unsupported.
400INVALID_UNIQUE_AMOUNT_DIRECTION / INVALID_PRODUCT_TYPEThe direction or product-type value is unsupported.
400FIELD_TOO_LONG / INVALID_REDIRECT_URL / INVALID_NOTIFY_URLAn optional field exceeds its limit or a supplied URL is invalid.
400ORDER_ID_REQUIRED / ORDER_IDENTIFIER_CONFLICTQuery identifier is missing or conflicting.
401INVALID_API_KEY / INVALID_SIGNATUREAuthentication failed.
403SUBSCRIPTION_REQUIRED / SUBSCRIPTION_EXPIREDMerchant subscription is unavailable.
403MERCHANT_DISABLEDMerchant account is disabled.
404ORDER_NOT_FOUNDNo matching merchant-owned order was found.
500SYSTEM_ERRORThe request could not be completed.

Интеграция классических SaaS-магазинов

HPP-only compatibility for Shopyy / Shopoem, Shoplus, Wooshoppaas and Fecify. No plugin download or SaaS source-code change is required.

POST https://mochi.bz/api/v/orders/legacy_create/{MerchantApiKey}/{PaymentMethod}
Use the API key, never the API secret, in this URL. The URL identifies the merchant and payment method. The SaaS platform continues to send its existing application/x-www-form-urlencoded order fields.

Supported platforms

Shopyy / ShopoemSame company and compatible gateway format
ShoplusConfigure the payment interface URL
WooshoppaasConfigure the payment interface URL
FecifyConfigure the payment interface URL

Setup

  1. Copy the merchant API key from the MochiPay merchant dashboard.
  2. Choose one supported payment method for this SaaS payment option.
  3. Replace {MerchantApiKey}и{PaymentMethod} in the endpoint URL.
  4. Paste the completed URL into the SaaS payment gateway's interface or submit URL setting.
  5. Keep the SaaS platform's existing POST parameters, return URL and notify URL unchanged.

URL examples

LEGACY PAYMENT INTERFACE URL
https://mochi.bz/api/v/orders/legacy_create/YOUR_MERCHANT_API_KEY/USDT_TRC20

https://mochi.bz/api/v/orders/legacy_create/YOUR_MERCHANT_API_KEY/USDC_ERC20

https://mochi.bz/api/v/orders/legacy_create/YOUR_MERCHANT_API_KEY/SOL_SOLANA

Payment methods

USDT_TRC20USDT on TRON
USDC_ERC20USDC on Ethereum
BTC_BITCOINNative BTC on Bitcoin
ETH_ERC20Native ETH on Ethereum
SOL_SOLANANative SOL on Solana

Required legacy fields

ParameterЦель
merchant_urlOriginal SaaS store value, retained in the complete request record for diagnostics.
system_nameExisting SaaS platform identifier, retained in the complete request record.
account_type / payment_modeKeep the platform's existing values, normally liveиsale.
orders_idOriginal SaaS order identifier.
amount / currencyOriginal order amount and currency.
return_urlCustomer return URL after confirmed payment.
notify_urlServer notification URL for the completed payment.
securityTokenOptional passthrough token returned unchanged.
productsOptional product or cart data.
customer_*Existing customer, address, IP and user-agent fields.

Create-order response

The existing SaaS integration extracts the hosted checkout URL from the three-part plain-text response.

TEXT
_____https://mochi.bz/pay/ORDER_ID_____

Successful return and notification fields

FieldValue
securityTokenThe original passthrough value.
paymentMethodonlinepay
paymentStatusCompleted
paymentTransactionThe confirmed blockchain transaction hash.
paymentCommentsMochiPay payment confirmed
orderIDThe original SaaS orders_id.

Скачать плагины магазинов

Add MochiPay to your independent store with a platform-specific extension. Choose your platform and version branch below. Each of the 19 downloads is an independent ZIP with English instructions and PHP requirements inside. Use the PHP environment allowed by your exact store release.

ON-SITE + HPP

OpenCart 2.0–2.2

Старые маршруты оплаты и шаблоны для конкретных версий.

PlatformOpenCart 2.0.x-2.2.x
PHPPHP 5.6–7.4; newer PHP needs core patches

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

OpenCart 3

Шаблоны Twig и платёжный шлюз OpenCart 3.

PlatformOpenCart 3.0.x
PHPPHP 5.6–8.4; exact core/dependency requirements apply

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

OpenCart 4

Пространства имён, маршруты и пакет расширения 4.x.

PlatformOpenCart 4.0.2.x-4.1.x
PHPPHP 8.0.2–8.4; 4.1.0.4 requires 8.1+

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

Zen Cart 1.5.3–1.5.7

Старые языковые файлы define и настройки статусов.

PlatformZen Cart 1.5.3-1.5.7
PHPPHP 5.6–8.0, depending on the core version

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

Zen Cart 1.5.8–2.2

Современные языковые массивы и настройки статусов.

PlatformZen Cart 1.5.8 / 2.0.x / 2.1.x / 2.2.x
PHPPHP 7.3–8.4, depending on the core version

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

Magento 1 / OpenMage

Magento CE 1.9.3.0–1.9.4.5 и совместимый OpenMage 19/20.

PlatformMagento CE 1.9.3.0-1.9.4.5; OpenMage 19/20 native M1 API
PHPPHP 5.6–8.4; PHP 8 requires a compatible OpenMage core

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

Magento 2

Magento Open Source 2.3.7–2.4.8 со встроенной оплатой.

PlatformMagento Open Source 2.3.7-2.4.8 using native checkout
PHPPHP 7.3–8.4, depending on the core version

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

PrestaShop 1.7 / 8 / 9

paymentOptions для PrestaShop 1.7.6–1.7.8, 8.x и 9.0.x.

PlatformPrestaShop 1.7.6-1.7.8 / 8.x / 9.0.x
PHPPHP 5.6–8.4, depending on the core version

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

Drupal Commerce

Шлюз Commerce для поддерживаемых веток Drupal и Commerce.

PlatformCommerce 2.40.x with Drupal 9.3–10.x; or Commerce 3.3.10+ <3.4 with Drupal 10.3–11.x
PHPDrupal 9.3–9.5: PHP 7.4–8.1; Drupal 10: PHP 8.1–8.3; Drupal 11: PHP 8.3–8.4, only when allowed by the exact Drupal release

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

Bagisto 2.3

Пакет Laravel с заказами и счетами.

PlatformBagisto >=2.3.0 <2.4.0
PHPPHP 8.2.x / 8.3.x / 8.4.x (also satisfy the store dependency lock)

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

Sylius 2.0

Оплата Payum и состояния платежей Sylius.

PlatformSylius >=2.0.0 <2.1.0 with PayumBundle 2.6+ / Payum 1.7-compatible core
PHPPHP 8.2.x / 8.3.x / 8.4.x (also satisfy the store dependency lock)

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

osCommerce 4.14

Платёжный модуль V4, отдельно от старых osCommerce 2.x и 3.x.

PlatformosCommerce 4.14.x; native V4 orderPayment module API
PHPPHP 7.4.x–8.3.x, subject to the installed osCommerce release and dependency lock

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →
ON-SITE + HPP

thirty bees 1.6

Платёжный модуль и история заказов thirty bees 1.6.

Platformthirty bees >=1.6.0 <1.7.0
PHPPHP 7.4.x / 8.0.x / 8.1.x / 8.2.x / 8.3.x; use the matching thirty bees distribution

Инструкция на английском и таблица PHP находятся в ZIP.

Скачать ZIPРуководство настройки →

New adapters are initial integration builds. Complete installation and real-payment acceptance in your own staging store before enabling live traffic.

Start Building With MochiPay

Create a MochiPay account and choose the integration method that fits your payment workflow.

Начать