PHP ile Kripto Ödeme Entegrasyonu: USDT ve TRX Rehberi
PHP ile kripto ödeme entegrasyonu: mercanpay-php kütüphanesiyle fatura oluşturma, ödeme sayfasına yönlendirme ve webhook doğrulamayı örnek kodlarla öğrenin.

PHP ile kripto ödeme entegrasyonu, resmi mercanpay/mercanpay-php kütüphanesiyle birkaç dosyalık bir iştir. Siparişte fatura açarsınız, müşteriyi ödeme sayfasına yönlendirirsiniz ve imzalı webhook geldiğinde siparişi onaylarsınız. Bu rehberde USDT ve TRX (TRC20) ödemelerini PHP sitenize adım adım bağlıyoruz.
Gereksinimler
- PHP 8 veya üzeri
ext-curlveext-jsoneklentileri (çoğu sunucuda varsayılan olarak açıktır)- Composer
- Onaylı bir MercanPay satıcı hesabı ve
invoicesyetkili bir API anahtarı
Hesabınız yoksa önce satıcı başvurusu yapın. API anahtarını panelde API Anahtarları sayfasından oluşturabilirsiniz.
1. Kütüphaneyi kurun
composer require mercanpay/mercanpay-php
Kütüphanenin curl dışında bağımlılığı yoktur. API anahtarınızı ve webhook imza sırrınızı koda yazmak yerine ortam değişkeni olarak saklayın:
MERCANPAY_API_KEY=mp_...
MERCANPAY_WEBHOOK_SECRET=whsec_...
API anahtarını asla tarayıcı koduna, mobil uygulamaya ya da herkese açık bir Git deposuna koymayın. Sızdığından şüphelenirseniz panelden hemen iptal edin.
2. PHP ile kripto ödeme için fatura oluşturun
Müşteri "Ödemeye geç" butonuna bastığında sunucunuzda bir fatura açıp onu ödeme sayfasına yönlendirirsiniz. İki seçeneğiniz var.
USD fiyatlı fatura (müşteri coin seçer)
<?php
require 'vendor/autoload.php';
use MercanPay\MercanPay;
use MercanPay\MercanPayException;
$zp = new MercanPay('https://mercanpay.com', getenv('MERCANPAY_API_KEY'));
try {
$invoice = $zp->createUsdInvoice('49.90', [
'order_id' => 'order-1001',
'description' => 'Pro lisans (1 yıl)',
'success_url' => 'https://magazam.com/siparis/1001/tesekkurler',
'return_url' => 'https://magazam.com/sepet',
'callback_url' => 'https://magazam.com/mercanpay-webhook.php',
'metadata' => ['customer_id' => 42],
]);
header('Location: ' . $invoice['payment_url']);
exit;
} catch (MercanPayException $e) {
error_log('MercanPay: ' . $e->getErrorCode() . ' ' . $e->getMessage());
http_response_code(502);
echo 'Ödeme sayfası şu an açılamadı, lütfen tekrar deneyin.';
}
Müşteri ödeme sayfasında TRX veya USDT seçer ve kur o anda kilitlenir. Seçenekleri daraltmak için 'tokens' => ['USDT'] gönderebilirsiniz.
Sabit coin faturası
$invoice = $zp->createInvoice('USDT', '49.90', ['order_id' => 'order-1001']);
Birkaç önemli ayrıntı:
- Tutarlar her zaman metin (string) olarak gönderilir:
'49.90'. Float kullanmayın, yuvarlama hataları ödemeyi bozabilir. order_ididempotenttir: Aynıorder_idile tekrar istek atarsanız yeni fatura açılmaz, mevcut fatura döner. Zaman aşımında güvenle tekrar deneyebilirsiniz.metadatamüşteriye gösterilmez. Webhook ve API yanıtlarında size aynen geri döner.expires_in_minutesile faturanın süresini 5 ile 1440 dakika (24 saat) arasında belirleyebilirsiniz.- Minimum fatura tutarı 10 $'dır. USDT faturalarına, müşterinin ödediği 1 USDT ağ ücreti eklenir.
Tüm alanların listesi API dokümantasyonunda.
3. Webhook uç noktasını yazın
Ödeme 20 blok onayıyla kesinleştiğinde (genellikle yaklaşık bir dakika) MercanPay sunucunuza imzalı bir POST isteği gönderir. Webhook adresini panelde Ayarlar → Webhook URL alanına girin. Yukarıdaki gibi fatura bazında callback_url de verebilirsiniz.
mercanpay-webhook.php:
<?php
require 'vendor/autoload.php';
use MercanPay\MercanPay;
$body = file_get_contents('php://input'); // ham gövde, json_decode öncesi
$header = $_SERVER['HTTP_X_MERCANPAY_SIGNATURE'] ?? '';
if (!MercanPay::verifyWebhook(getenv('MERCANPAY_WEBHOOK_SECRET'), $body, $header)) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
$invoice = $event['data']['invoice'] ?? null;
switch ($event['type']) {
case 'invoice.paid':
case 'invoice.overpaid':
markOrderPaid($event['id'], $invoice['order_id'], $invoice['token'], $invoice['paid_amount']);
break;
case 'invoice.partial':
// eksik ödeme: müşteriye kalan tutarı hatırlatabilirsiniz
break;
case 'invoice.expired':
case 'invoice.cancelled':
// siparişi iptal edin veya yeni fatura önerin
break;
}
http_response_code(200);
verifyWebhook üç şeyi kontrol eder: başlığın t=...,v1=... biçiminde olmasını, zaman damgasının 5 dakikadan eski olmamasını ve HMAC-SHA256 imzasının sabit zamanlı karşılaştırmayla eşleşmesini. İmzanın arka planını webhook imzası doğrulama yazısında ayrıntılı anlattık.
4. Siparişi idempotent biçimde onaylayın
Webhook'lar yeniden denenebildiği için aynı olay size birden fazla kez ulaşabilir. Siparişi iki kez teslim etmemek için olay kimliğini ($event['id']) kaydedin:
function markOrderPaid(string $eventId, string $orderId, string $token, string $paid): void
{
$pdo = new PDO(getenv('DB_DSN'), getenv('DB_USER'), getenv('DB_PASS'));
$pdo->beginTransaction();
// processed_events.event_id sütunu UNIQUE olmalı
$stmt = $pdo->prepare('INSERT IGNORE INTO processed_events (event_id) VALUES (?)');
$stmt->execute([$eventId]);
if ($stmt->rowCount() === 0) { // bu olay daha önce işlendi
$pdo->rollBack();
return;
}
$pdo->prepare("UPDATE orders SET status = 'paid', paid_token = ?, paid_amount = ? WHERE id = ? AND status <> 'paid'")
->execute([$token, $paid, $orderId]);
$pdo->commit();
}
Ayrıca webhook'taki coin ve tutarın siparişinizle eşleştiğini kontrol etmek iyi bir alışkanlıktır.
Webhook işleyicinizin hızlı yanıt vermesi de önemlidir. 10 saniye içinde 2xx dönmezseniz istek artan aralıklarla tekrar gönderilir. E-posta gönderimi gibi ağır işleri bir kuyruğa bırakın.
5. Başarılı sayfası ≠ ödeme onayı
Müşteri ödemeyi tamamlayınca tarayıcısı success_url adresine yönlendirilir ve adrese invoice_id, order_id ve status parametreleri eklenir. Bu sayfada "Ödemeniz alındı" mesajı gösterebilirsiniz, ancak siparişi bu yönlendirmeye göre onaylamayın, çünkü URL parametreleri taklit edilebilir. Emin olmak istediğiniz durumlarda faturayı API'den sorgulayın:
$invoice = $zp->getInvoiceByOrder($_GET['order_id'] ?? '');
if (in_array($invoice['status'], ['paid', 'overpaid'], true)) {
echo 'Ödemeniz onaylandı, teşekkürler!';
} else {
echo 'Ödemeniz onaylanıyor, birkaç dakika içinde e-posta alacaksınız.';
}
6. Hata yönetimi
Başarısız isteklerde kütüphane MercanPayException fırlatır:
| Yöntem | Döndürdüğü |
|---|---|
getHttpStatus() |
HTTP kodu (ör. 400, 401, 403) |
getErrorCode() |
Makine okunur kod (ör. validation_error, unauthorized) |
getMessage() |
Açıklama |
429 (hız sınırı) ve 5xx hatalarında kısa bir bekleme sonrası aynı isteği tekrar deneyebilirsiniz. order_id sayesinde çift fatura oluşmaz.
WooCommerce veya başka bir platform kullanıyorsanız
MercanPay için hazır bir WooCommerce veya WHMCS eklentisi şu an yoktur. Ancak bu platformlar PHP ile yazıldığı için, yukarıdaki fatura oluşturma ve webhook adımlarını kullanarak kendi ödeme eklentinizi geliştirebilirsiniz. Mantık aynıdır: ödeme adımında createUsdInvoice çağrılır, webhook'ta sipariş durumu güncellenir.
Canlıya geçmeden önce kontrol listesi
- API anahtarı yalnızca sunucuda, ortam değişkeninde duruyor.
- Webhook URL HTTPS ve imza doğrulaması açık.
- Her siparişin benzersiz bir
order_iddeğeri var. invoice.partialveinvoice.overpaidolayları ele alınıyor.- Sipariş, tarayıcı yönlendirmesine değil webhook'a göre onaylanıyor.
- Akış, küçük tutarlı gerçek bir ödemeyle uçtan uca denendi.
Sık sorulan sorular
Webhook'u yerelde nasıl test ederim?
Panelde Webhooklar sayfasındaki "Test gönder" özelliği bir test.ping olayı yollar. Teslimat geçmişinde her isteğin yanıt kodunu görebilir ve gerekirse tekrar gönderebilirsiniz.
PHP 7 destekleniyor mu?
Kütüphane PHP 8 ve üzerini hedefler. Daha eski sürümlerde REST API'yi doğrudan curl ile çağırabilirsiniz.
Çekimleri de PHP ile yapabilir miyim?
Evet. withdrawals yetkili bir anahtarla createWithdrawal('USDT', '50', 'T...', 'benzersiz-anahtar') çağrısını kullanabilirsiniz. Güvenlik gereği API çekimleri yalnızca panelde güvenilir olarak işaretlenmiş kayıtlı adreslere yapılabilir.
MercanPay ile başlayın
PHP ile kripto ödeme entegrasyonu için ihtiyacınız olan her şey tek bir Composer paketinde. Python kullanıyorsanız Python entegrasyon rehberine göz atın. Satıcı hesabınızı açın, API anahtarınızı alın ve ilk faturanızı bugün oluşturun.


