← Tüm eğitimler

EĞİTİM 11 / 12

Kripto pazaryerini kur.

Pratik $300 örneği ve sunucu tarafı kodla ortak sepetten satıcılara ödemeye.

Elde edeceğin sonuç

Müşteri ödemelerini satıcı ödemeleriyle karıştırmadan test edebileceğin, uzlaştırabileceğin ve otomatikleştirebileceğin ödeme entegrasyonu.

1. Kimin neyi yöneteceğine karar ver

Kataloğu, satıcı hesaplarını, sepeti, kargoyu ve sipariş karşılamayı mağazan yönetir. Wholly Crypto ödeme sayfasını, ödeme doğrulamasını, satıcı tahsislerini ve onaylı ödemeleri yönetir. Satıcı kaydı bir satıcı girişi değildir; mevcut mağaza eklentileri çok satıcılı sepetleri otomatik bölmez.

  1. Tek ortak sepet
  2. Tek müşteri faturası
  3. Doğrulanmış satıcı payları
  4. Onaylı satıcı ödemeleri

Müşteriler önce proje cüzdanlarına öder. Anahtarları sen kontrol eder, satıcılara borçlu olunan fonları sen tutarsın. Bu doğrudan müşteriden satıcıya paylaşım veya satıcıların için saklama hizmeti olmayan çözüm değildir.

Pazaryeri Bitcoin ana ağını, desteklenen EVM coin'lerini ve standart ERC-20 token'larını destekler. Satıcılar otomatik itibari para dönüşümü değil, müşterinin kullandığı varlığı ve ağı alır. Ödeme alınan 30 zincirin tamamı Pazaryeri ödemelerinde desteklenmez.

2. Tutarları hesapla

Üç satıcının her biri $100 tutarında ürün satar. Bu örnekte mağaza veya satıcı geçersiz kılması olmadan proje komisyonunu %4 ayarla.

PayBrütKomisyonunSatıcının aldığı
Her satıcı$100$4$96
Üçünün toplamı$300$12$288

Bunlar faturanın kilitli fiyatındaki karşılıklardır ve kriptoyla ödenir. Gelecekteki dolar değeri garanti edilmez. Olağan %1 işlem ücreti, bu $300 faturada ön ödemeli kredilerden $3 kullanır; satıcı başına değil, bir kez. Bu ücret uygulandığında $12 brüt komisyonun ağ maliyetlerinden önce $9 bırakır.

Bitcoin ücretleri veya EVM gas'ı için serbest yerel coin'leri ayrı tut. Ücretler satıcıların korunan anaparasını tüketmemelidir. Olağan bakiye aktarımları Pazaryeri ödeme alma adreslerinden harcayamaz.

3. Cüzdanları ve satıcıları hazırla

  1. Proje → Pazaryeri → Ayarlar'da Pazaryeri'ni etkinleştir, mağazaları seç ve komisyonu ayarla. Kurulum sırasında ödemeleri duraklatılmış, otomatik politikaları kapalı tut.
  2. Proje cüzdanlarını ve veritabanını yedekle. Mağazada hedeflenen BTC/EVM yöntemlerini etkinleştir, tarayıcının hazır olmasını kontrol et, işlem kredilerini ve ayrı yerel ücretleri fonla.
  3. Her satıcıyı ekle. UUID'sini mağazanın satıcı kimliğiyle ilişkilendirerek kaydet; external_id bu satıcı referansını tutabilir. Tam zincir ve ağda her ödeme adresini bağımsız doğrula ve onayla.

Ödeme sayfasındaki yöntem, katılan her satıcı için onaylı eşleşen hedef gerektirir. Satıcının adresini daha sonra değiştirmek mevcut yükümlülükleri sessizce yönlendirmez.

Ödeme sayfası sıfır onaya veya tek tarayıcıya izin verse bile satıcı ödemesi doğrulaması pozitif onaylar ve iki bağımsız uyumlu sağlayıcı gerektirir.

Konsol kurulumu adımları · Yedekleme ve geri yükleme

4. Ortak sepeti bağla

Ayarlar → API erişimi'nde proje kapsamlı Pazaryeri kimlik bilgisi oluştur. Ödeme sayfası arka ucuna marketplace.read ve invoices.write ver; uygun olduğunda mağazasıyla sınırla. Adres onayı ve ödeme onayı izinlerini bu anahtara verme.

Fiyatları, indirimleri, vergiyi ve kargoyu sunucunda hesapla, ardından satıcı paylarına ata. Pozitif ondalık dizelerle 1–100 farklı satıcı gönder; brüt tutarları fatura toplamına birebir eşit olmalıdır. Tarayıcının sağladığı paylaşıma güvenme veya para için kayan nokta aritmetiği kullanma.

Aşağıdaki API ana makine adını ve UUID yer tutucularını değiştir. WHOLLY_TOKEN'ı sunucu ortamından yükle. İstek yapılandırılmış %4 komisyonu devralır; komisyonu değiştirme izni gerekmez.

İsteği cURL, JavaScript, PHP veya Python'da aç
cURL
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
  --request POST \
  --url "https://api.example.com/v1/marketplace/invoices" \
  --header "Authorization: Bearer $WHOLLY_TOKEN" \
  --header 'Idempotency-Key: cart-1042-marketplace-v1' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "project_id": "YOUR_PROJECT_ID",
  "store_id": "YOUR_STORE_ID",
  "amount": "300.00",
  "currency": "USD",
  "order_id": "cart-1042",
  "description": "One order from three vendors",
  "ipn_url": "https://shop.example.com/payments/wholly-ipn",
  "metadata": {
    "cart_id": "cart-1042"
  },
  "allocations": [
    {
      "vendor_id": "VENDOR_A_UUID",
      "gross_amount": "100.00"
    },
    {
      "vendor_id": "VENDOR_B_UUID",
      "gross_amount": "100.00"
    },
    {
      "vendor_id": "VENDOR_C_UUID",
      "gross_amount": "100.00"
    }
  ]
}'
JavaScript
// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
  "project_id": "YOUR_PROJECT_ID",
  "store_id": "YOUR_STORE_ID",
  "amount": "300.00",
  "currency": "USD",
  "order_id": "cart-1042",
  "description": "One order from three vendors",
  "ipn_url": "https://shop.example.com/payments/wholly-ipn",
  "metadata": {
    "cart_id": "cart-1042"
  },
  "allocations": [
    {
      "vendor_id": "VENDOR_A_UUID",
      "gross_amount": "100.00"
    },
    {
      "vendor_id": "VENDOR_B_UUID",
      "gross_amount": "100.00"
    },
    {
      "vendor_id": "VENDOR_C_UUID",
      "gross_amount": "100.00"
    }
  ]
}`;
const response = await fetch("https://api.example.com/v1/marketplace/invoices", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Idempotency-Key": "cart-1042-marketplace-v1",
    "Content-Type": "application/json"
  },
  body,
  redirect: "error",
  signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());
PHP
<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
  "project_id": "YOUR_PROJECT_ID",
  "store_id": "YOUR_STORE_ID",
  "amount": "300.00",
  "currency": "USD",
  "order_id": "cart-1042",
  "description": "One order from three vendors",
  "ipn_url": "https://shop.example.com/payments/wholly-ipn",
  "metadata": {
    "cart_id": "cart-1042"
  },
  "allocations": [
    {
      "vendor_id": "VENDOR_A_UUID",
      "gross_amount": "100.00"
    },
    {
      "vendor_id": "VENDOR_B_UUID",
      "gross_amount": "100.00"
    },
    {
      "vendor_id": "VENDOR_C_UUID",
      "gross_amount": "100.00"
    }
  ]
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/invoices");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => false,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: cart-1042-marketplace-v1", "Content-Type: application/json"],
    CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));
Python
# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler

class NoRedirect(HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None

# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
    "Idempotency-Key": "cart-1042-marketplace-v1",
    "Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
  "project_id": "YOUR_PROJECT_ID",
  "store_id": "YOUR_STORE_ID",
  "amount": "300.00",
  "currency": "USD",
  "order_id": "cart-1042",
  "description": "One order from three vendors",
  "ipn_url": "https://shop.example.com/payments/wholly-ipn",
  "metadata": {
    "cart_id": "cart-1042"
  },
  "allocations": [
    {
      "vendor_id": "VENDOR_A_UUID",
      "gross_amount": "100.00"
    },
    {
      "vendor_id": "VENDOR_B_UUID",
      "gross_amount": "100.00"
    },
    {
      "vendor_id": "VENDOR_C_UUID",
      "gross_amount": "100.00"
    }
  ]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/invoices",
                  method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
    print(json.load(response))

Göndermeden önce istek gövdesini ve Idempotency-Key'i kalıcı kaydet. Zaman aşımından sonra aynı gövdeyi aynı anahtarla yeniden dene. data.invoice_id'yi siparişinle ilişkilendirerek kaydet ve üst düzey links.checkout'a yönlendir. API anahtarlarını müşterinin tarayıcısına asla koyma.

Proje ve mağaza UUID'leri nerede bulunur →

SDK mı tercih ediyorsun? Pazaryeri örnekleriyle başla:

5. Müşteri ve satıcı ödemelerini ayrı izle

Ödeme sayfası dönüş URL'si ödeme kanıtı değildir. Geri çağrı imzalarını ham gövde üzerinden doğrula, zaman damgasını ve beklenen projeyi kontrol et; alındığını onaylamadan önce event_id'yi benzersiz kaydet. Yeniden denemelerin siparişi iki kez karşılamaması için ayrı sipariş düzeyi koruma kullan.

OlayNe anlatır
invoice.settledMüşteri faturası tamamlandı. Siparişi karşılamadan önce inceleme işaretlerini ve Pazaryeri bekletmelerini kontrol et.
marketplace.allocations.availableDoğrulanmış paylar ödeme için kullanılabilir. Henüz hiçbir satıcıya ödeme yapılmış olması gerekmez.
marketplace.payout.confirmedSatıcı ödemesi onay kontrollerini tamamladı.

Fatura IPN'si mağazanın IPN sırrını kullanır. Pazaryeri yaşam döngüsü webhook'ları kendi uç nokta imzalama sırrını kullanır. İki alıcıyı ayrı tut. Kaçırılan veya sıra dışı gelen olayları uzlaştırırken güncel faturayı veya satıcı ödemesini API üzerinden oku.

Fatura geri çağrıları ve imza doğrulama · Pazaryeri olayları ve API başvurusu

6. Önce incele, sonra otomatikleştir

Doğrulanmış paylar kullanılabilir olunca ödemelerin duraklatmasını kaldır ama otomatik politikaları kapalı bırak. Pazaryeri → Satıcı Ödemeleri'nde tahsisleri hazırla, alıcıları ve yerel ücret/gas sınırlarını incele, ardından tam planı bir kez onayla. Yalnızca Yayınlandı'ya değil, Ödendi'ye kadar izle.

Bitcoin, seçilen faturanın ödenmemiş tüm paylarını birlikte gruplar. EVM token ödemeleri token transferlerinden önce gas fonlaması gerektirebilir. Bunlar atomik, ya hep ya hiç paylaşımı değil, birden fazla işlemdir.

Başarılı küçük testten sonra varlık başına tek otomatik politika ayarla: asgari ödeme, ödeme başına ve günlük anapara sınırları, yerel ücret/gas bütçeleri, aralık ve onaylar. Etkinleştirmek, başka tıklama olmadan gönderime yetki verir. Düşük kredi veya kapalı sunucu transfer izni yine harcamayı duraklatabilir.

7. Sorunlu durumları ele al

Eksik, geç, karma veya yeniden düzenlenen zincirdeki ödemeler

Tamamlanmış ödeme sayfası, satıcı paylaşımının tamamen fonlandığını garanti etmez. Tolerans eksik fon oluşturamaz. Bekletilen tahsisleri incele, ödemeyi bekle, iade et veya tamamen karşılığı olan daha küçük paylaşımı açıkça onayla. Fazla ödemeler otomatik ek pazaryeri geliri değildir.

Fazla ödemeler Bitcoin, EVM coin'leri veya desteklenen ERC-20 token'larında teklif edilen satıcı ödemelerini engellemez. Satıcı payları değişmez; fazlalık mutabakat için ayrı kalır.

Satıcı ödemesi takılır veya istek zaman aşımına uğrar

Kayıtlı işlem hash'lerini, kaynak bakiyelerini, gas'ı ve inceleme nedenini kontrol et. Mevcut ödemeyi sürdür veya uzlaştır; yanıt kayboldu diye ikinci transfer oluşturma. Yedeği geri yükledikten sonra zincir üstü sonuçlarla defter eşleşene kadar ödemeleri duraklatılmış tut.

Devam et, başarısız EVM transferini yalnızca iki bağımsız sağlayıcı zincir üstünde onaylanmış revert'i kanıtladıktan sonra değiştirebilir. Bilinmeyen sonuçlar ayrılmış kalır ve başarısız denemelerin ücretleri orijinal bütçeye sayılmaya devam eder.

Müşterinin iadeye ihtiyacı var

Müşterinin kontrolündeki iade adresini doğrula. Desteklenen iadeler tam ve aynı varlıktadır. Tüm satıcılara ödendikten sonra birincil cüzdanı ayrıca fonla; Wholly Crypto onlardan geri tahsil edemez. Kısmen ödenmiş satıcı grubu, varsayılan kısmi iade düğmesi değil, manuel uzlaştırma gerektirir.

8. Açmadan önce kontrol et

  • Küçük BTC ve/veya EVM ödemesini onaylanmış satıcı ödemelerine kadar çalıştır. Zinciri, token sözleşmesini, hedefleri, komisyonu ve ayrı ücretleri doğrula.
  • Yinelenen geri çağrıyı, zaman aşımına uğrayan API yanıtını, eksik ödemeyi ve bekletilen satıcı ödemesini test et. Hiçbirinin yinelenen sipariş karşılama veya gönderime yol açmadığını doğrula.
  • Özel yedekleri sunucu dışında tut, ödeme hatalarını izle ve satıcılara olan yükümlülükleri zincir üstü fonlarla düzenli uzlaştır.

İncelenen ödemeler ve az sayıda satıcıyla başla. Yalnızca test ettiğin varlıkları, bütçeleri ve hedefleri otomatikleştir.