Een betalingsintegratie die je kunt testen, afstemmen en automatiseren zonder klantbetalingen en verkopersuitbetalingen te verwarren.
1. Bepaal wie wat doet
Je winkel beheert de catalogus, verkopersaccounts, winkelwagen, verzending en orderafhandeling. Wholly Crypto verzorgt afrekenen, betalingsverificatie, verkoperstoewijzingen en goedgekeurde uitbetalingen. Een verkopersrecord is geen verkoperslogin; bestaande winkelplugins splitsen winkelwagens met meerdere verkopers niet automatisch.
- Eén gedeelde winkelwagen
- Eén klantfactuur
- Geverifieerde verkopersaandelen
- Goedgekeurde uitbetalingen
Klanten betalen eerst naar de projectwallets. Jij beheert de sleutels en bewaart middelen die aan verkopers verschuldigd zijn. Dit is geen directe klant-naar-verkoperverdeling of dienst zonder bewaring voor je verkopers.
Marketplace ondersteunt Bitcoin-mainnet en ondersteunde EVM-munten en standaard-ERC-20-tokens. Verkopers ontvangen het activum en netwerk dat de klant gebruikte, geen automatische fiatconversie. Niet alle 30 ontvangstblockchains worden ondersteund voor Marketplace-uitbetalingen.
2. Bereken de bedragen
Drie verkopers verkopen elk voor $100 aan goederen. Stel de projectcommissie in op 4%, zonder winkel- of verkoperoverrides voor dit voorbeeld.
| Aandeel | Bruto | Je commissie | Verkoper ontvangt |
|---|---|---|---|
| Elke verkoper | $100 | $4 | $96 |
| Alle drie | $300 | $12 | $288 |
Dit zijn equivalenten tegen de vastgezette factuurkoers, betaald in crypto. Het zijn geen gegarandeerde toekomstige dollarwaarden. De gebruikelijke verwerkingskosten van 1% verbruiken $3 aan vooruitbetaald tegoed op deze factuur van $300, eenmaal, niet eenmaal per verkoper. Je brutocommissie van $12 laat $9 over vóór netwerkkosten wanneer die vergoeding geldt.
Houd vrije eigen munten voor Bitcoin-kosten of EVM-gas apart. Kosten mogen de beschermde hoofdsom van verkopers niet verbruiken. Gewone sweeps kunnen niet uitgeven vanaf Marketplace-ontvangstadressen.
3. Bereid wallets en verkopers voor
- Schakel Marketplace in via Project → Marketplace → Instellingen, selecteer de winkels en stel de commissie in. Houd uitbetalingen gepauzeerd en automatisch beleid uit tijdens het instellen.
- Maak back-ups van projectwallets en de database. Schakel de gewenste BTC-/EVM-methoden in de winkel in, controleer scannergereedheid en vul verwerkingstegoed plus afzonderlijke kosten in de eigen munt aan.
- Voeg elke verkoper toe. Sla de UUID op bij het verkoper-ID van je winkel; external_id kan die verkopersreferentie bevatten. Verifieer en keur elk uitbetalingsadres onafhankelijk goed op de exacte blockchain en het exacte netwerk.
Een afrekenmethode heeft voor elke deelnemende verkoper een goedgekeurde passende bestemming nodig. Een verkoperadres later wijzigen leidt bestaande verplichtingen niet stilzwijgend om.
Uitbetalingsverificatie vereist positieve bevestigingen en twee onafhankelijke compatibele providers, ook als afrekenen nul bevestigingen of één scanner toestaat.
4. Verbind de gedeelde winkelwagen
Maak een projectgebonden Marketplace-referentie aan in Instellingen → API-toegang. Geef je afrekenbackend marketplace.read en invoices.write, waar passend beperkt tot de eigen winkel. Neem geen rechten voor adres- of uitbetalingsgoedkeuring in die sleutel op.
Bereken prijzen, kortingen, belasting en verzending op je server en wijs ze daarna aan de verkopersaandelen toe. Stuur 1–100 verschillende verkopers met positieve decimale tekenreeksen; hun brutobedragen moeten exact het factuurtotaal vormen. Vertrouw nooit op een door de browser aangeleverde verdeling en gebruik geen drijvendekommaberekeningen voor geld.
Vervang hieronder de API-hostnaam en UUID-plaatshouders. Laad WHOLLY_TOKEN uit je serveromgeving. Het verzoek neemt de ingestelde commissie van 4% over; toestemming om commissie te overschrijven is niet nodig.
Open het verzoek in cURL, JavaScript, PHP of Python
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))Sla de verzoekinhoud en Idempotency-Key duurzaam op vóór verzending. Probeer na een time-out dezelfde inhoud met dezelfde sleutel opnieuw. Bewaar data.invoice_id bij je bestelling en verwijs door naar links.checkout op het hoogste niveau. Plaats nooit API-sleutels in de browser van de klant.
Waar je project- en winkel-UUID's vindt →
Liever een SDK? Begin met de Marketplace-voorbeelden:
5. Volg betaling en uitbetaling afzonderlijk
Een terugkeer-URL van afrekenen is geen betalingsbewijs. Verifieer callbackhandtekeningen over de ruwe inhoud, controleer tijdstempel en verwacht project en sla event_id uniek op voordat je bevestigt. Gebruik een afzonderlijke beveiliging op bestellingsniveau zodat nieuwe pogingen een bestelling niet tweemaal kunnen afhandelen.
| Gebeurtenis | Wat het je vertelt |
|---|---|
invoice.settled | De klantfactuur is voldaan. Controleer beoordelingsmarkeringen en Marketplace-blokkeringen vóór afhandeling. |
marketplace.allocations.available | Geverifieerde aandelen zijn beschikbaar voor uitbetaling. Er is nog niet noodzakelijk een verkoper betaald. |
marketplace.payout.confirmed | De uitbetaling heeft de bevestigingscontroles voltooid. |
Factuur-IPN gebruikt het IPN-geheim van de winkel. Marketplace-levenscycluswebhooks gebruiken hun eigen endpointondertekeningsgeheim. Houd beide ontvangers gescheiden. Lees de actuele factuur of uitbetaling via de API bij afstemming van gemiste of ongeordende gebeurtenissen.
Factuurcallbacks en handtekeningverificatie · Marketplace-gebeurtenissen en API-referentie
6. Controleer eerst, automatiseer later
Hervat uitbetalingen zodra geverifieerde aandelen beschikbaar zijn, maar laat automatisch beleid uit. Bereid in Marketplace → Uitbetalingen de toewijzingen voor, controleer ontvangers en limieten voor kosten in de eigen munt/gas en keur daarna het exacte plan eenmaal goed. Volg het tot Betaald, niet alleen Uitgezonden.
Bitcoin bundelt elk onbetaald aandeel van een geselecteerde factuur. EVM-tokenuitbetalingen kunnen gasfinanciering vóór tokenoverdrachten vereisen. Het zijn meerdere transacties, geen atomaire alles-of-nietsverdeling.
Stel na een geslaagde kleine test één automatisch beleid per activum in: minimale uitbetaling, hoofdsomlimieten per uitbetaling en per dag, budgetten voor kosten in de eigen munt/gas, interval en bevestigingen. Inschakelen autoriseert verzending zonder verdere klikken. Laag tegoed of een uitgeschakelde verzendfunctie van de server kan uitgaven nog steeds pauzeren.
7. Handel lastige gevallen af
Te lage, te late, gemengde of gereorganiseerde betalingen
Een voldane afrekening garandeert geen volledig gefinancierde verkopersverdeling. Tolerantie kan geen ontbrekende middelen creëren. Bekijk vastgehouden toewijzingen, wacht op betaling, betaal terug of keur expliciet een kleinere volledig gedekte verdeling goed. Te hoge betalingen zijn niet automatisch extra marktplaatsomzet.
Overbetalingen blokkeren geoffreerde verkopersuitbetalingen niet op Bitcoin, EVM-munten of ondersteunde ERC-20-tokens. Verkopersaandelen blijven ongewijzigd en het overschot blijft afzonderlijk voor afstemming.
Een uitbetaling loopt vast of een verzoek krijgt een time-out
Controleer de opgeslagen transactiehashes, bronsaldi, gas en beoordelingsreden. Hervat of stem de bestaande uitbetaling af; maak geen tweede overdracht omdat het antwoord verloren ging. Houd uitbetalingen na het herstellen van een back-up gepauzeerd totdat on-chainresultaten en het grootboek overeenkomen.
Hervatten kan een mislukte EVM-overdracht alleen vervangen nadat twee onafhankelijke providers een bevestigde on-chain-revert bewijzen. Onbekende uitkomsten blijven gereserveerd en kosten van mislukte pogingen blijven meetellen voor het oorspronkelijke budget.
De klant heeft een terugbetaling nodig
Verifieer een terugbetalingsadres onder beheer van de klant. Ondersteunde terugbetalingen zijn volledig en in hetzelfde activum. Financier de primaire wallet afzonderlijk nadat alle verkopers zijn betaald; Wholly Crypto kan bedragen niet bij hen terugboeken. Een deels betaalde verkopersbatch vereist handmatige afstemming, geen veronderstelde knop voor gedeeltelijke terugbetaling.
8. Controleer vóór opening
- Voer een kleine BTC- en/of EVM-betaling uit tot en met bevestigde verkopersuitbetalingen. Bevestig blockchain, tokencontract, bestemmingen, commissie en afzonderlijke kosten.
- Test een herhaalde callback, een API-antwoord met time-out, een te lage betaling en een vastgehouden uitbetaling. Verifieer dat geen daarvan dubbele afhandeling of dubbele verzending veroorzaakt.
- Bewaar privéback-ups buiten de server, houd uitbetalingsfouten in de gaten en stem verplichtingen aan verkopers regelmatig af tegen on-chainmiddelen.
Begin met gecontroleerde uitbetalingen en een klein aantal verkopers. Automatiseer alleen de activa, budgetten en bestemmingen die je hebt getest.