Приём USDT в WooCommerce без плагина
Плагина WooCommerce для ChainPay пока нет. API достаточно маленькое, чтобы интегрировать его примерно шестьюдесятью строками PHP: показать адрес для депозита на странице заказа и пометить заказ оплаченным, когда придёт вебхук.
Как это работает
- Клиент оформляет заказ со способом оплаты, после которого статус остаётся
pendingилиon-hold(например, «Прямой банковский перевод», переименованный в «USDT»). - Страница благодарности просит у ChainPay адрес для депозита на этот заказ и показывает его.
- Клиент платит. ChainPay переводит средства на ваш кошелёк и отправляет вебхук на ваш сайт.
- Обработчик вебхука проверяет секрет и сумму и вызывает
payment_complete().
mu-плагин
Сохраните как wp-content/mu-plugins/chainpay.php:
<?php
// wp-content/mu-plugins/chainpay.php
const CHAINPAY_API = 'https://api.chainpay.site';
const CHAINPAY_SECRET = 'change-me';
const CHAINPAY_WALLET = 'TYourOwnTronWallet...';
function chainpay_address(WC_Order $order): ?string {
$cached = $order->get_meta('_chainpay_address');
if ($cached) {
return $cached;
}
$res = wp_remote_post(CHAINPAY_API . '/deposit-address', [
'headers' => ['Content-Type' => 'application/json'],
'timeout' => 15,
'body' => wp_json_encode([
'ticker' => 'trc20/usdt',
'callbackUrl' => rest_url('chainpay/v1/webhook') . '?token=' . CHAINPAY_SECRET,
'forwardAddress' => CHAINPAY_WALLET,
'externalReference' => 'wc-' . $order->get_id(),
]),
]);
if (is_wp_error($res)) {
return null;
}
$address = json_decode(wp_remote_retrieve_body($res), true)['address'] ?? null;
if ($address) {
$order->update_meta_data('_chainpay_address', $address);
$order->save();
}
return $address;
}
add_action('woocommerce_thankyou', function ($order_id) {
$order = wc_get_order($order_id);
if (!$order || !$order->has_status(['pending', 'on-hold'])) {
return;
}
$address = chainpay_address($order);
if ($address) {
echo '<p>Send ' . esc_html($order->get_total()) . ' USDT (TRC20) to <code>'
. esc_html($address) . '</code></p>';
}
});
add_action('rest_api_init', function () {
register_rest_route('chainpay/v1', '/webhook', [
'methods' => 'POST',
'permission_callback' => '__return_true',
'callback' => function (WP_REST_Request $req) {
if (!hash_equals(CHAINPAY_SECRET, (string) $req->get_param('token'))) {
return new WP_REST_Response(null, 403);
}
$event = $req->get_json_params();
if (($event['status'] ?? '') !== 'confirmed') {
return ['ok' => true];
}
$order = wc_get_order((int) str_replace('wc-', '', $event['externalReference'] ?? ''));
if ($order && !$order->is_paid() && (float) $event['amount'] >= (float) $order->get_total()) {
$order->payment_complete($event['txHash']);
}
return ['ok' => true];
},
]);
});
Заметки
- Задайте валюту магазина USD (или другую, привязанную к доллару), чтобы сумма заказа равнялась сумме USDT. Для других валют сначала конвертируйте, например через
GET /rates/convert. - Замените
CHAINPAY_SECRETдлинным случайным значением и не коммитьте его. - URL вебхука должен быть публично доступен по HTTPS. Для работы
rest_url()нужны «красивые» постоянные ссылки. payment_complete()защищён проверкойis_paid(), поэтому повторные доставки не обработают заказ дважды.- Недоплаты отсекает проверка суммы; обрабатывайте их вручную или добавьте в обработчик заметку к заказу.
- Для BNB Smart Chain используйте
bep20/usdtи кошелёк0x…вместоtrc20/usdt.