DM Champ Docs

Reîncărcare automată pentru sub-conturi (Furnizor de plăți personalizat)

Dacă preferi să gestionezi plățile de credit pentru sub-conturi prin propriul tău furnizor în loc de Stripe (transferuri bancare, gateway-uri de plată locale, sisteme de facturare personalizate), platforma pune la dispoziție o pereche webhook + API pentru a putea rula singur întregul proces de taxare și alocare. Prezentarea generală non-tehnică se află pe pagina Conturi de agenție; această pagină acoperă payload-ul exact al webhook-ului și apelul API pe care îl faci pentru a acorda creditele ulterior.

Webhook-ul este doar una dintre modalitățile prin care se plătesc reîncărcările automate. Dacă ați conectat Stripe sau PayPal în modul SaaS, platforma taxează automat cardul salvat al clientului sau contul PayPal și acordă creditele, deci nu aveți nimic de construit pe această pagină. Citiți mai departe doar dacă doriți să gestionați plata pe cont propriu.


Fluxul pe scurt

  1. Soldul de credite al unui sub-cont scade sub pragul de reîncărcare automată.
  2. Platforma apelează URL-ul tău de webhook cu detaliile sub-contului și numărul de credite de care are nevoie.
  3. Serverul tău taxează clientul prin furnizorul pe care îl utilizezi.
  4. Serverul tău apelează API-ul de acordare a creditelor pentru a adăuga credite acelui sub-cont.
  5. Serverul tău răspunde cu 200 pentru a confirma primirea webhook-ului.

1. Webhook: agency_sub_account_auto_recharge

Configurați URL-ul webhook-ului făcând clic pe SaaS Mode în bara laterală principală, alegând Use a Custom Payment Provider Instead (sau, odată configurat, deschizând cardul Custom Payment Provider) și completând câmpul Auto-Recharge Webhook.

Când se declanșează

Când soldul de credite al unui sub-cont scade sub pragul de reîncărcare automată configurat.

Payload

{
  "event": "agency_sub_account_auto_recharge",
  "sub_account_id": "<sub-account-id>",
  "sub_account_email": "customer@example.com",
  "sub_account_name": "John Doe",
  "agency_id": "<agency-id>",
  "credits_requested": 500,
  "current_balance": 42,
  "threshold": 100,
  "price_per_credit_cents": 10,
  "price_per_credit_currency": "usd",
  "total_amount_cents": 5000,
  "timestamp": "2026-04-13T12:00:00.000Z",
  "idempotency_key": "auto_recharge_abc123_1681387200000"
}
Câmp Descriere
event Întotdeauna agency_sub_account_auto_recharge pentru acest webhook.
sub_account_id ID-ul unic al sub-contului care are nevoie de credite.
sub_account_email Adresa de e-mail a sub-contului.
sub_account_name Numele afișat al sub-contului.
agency_id ID-ul unic al contului tău de agenție.
credits_requested Câte credite să acorzi. Aceasta este suma de reîncărcare configurată de tine, dar dacă soldul a scăzut mai mult sub prag decât ar acoperi acea sumă, aceasta este ridicată automat la valoarea necesară pentru a readuce soldul peste prag dintr-o singură mișcare. Taxează întotdeauna pentru (și acordă) valoarea credits_requested din payload — nu introduce manual suma de reîncărcare în cod.
current_balance Soldul de credite al sub-contului în momentul în care a fost trimis webhook-ul.
threshold Pragul de sold care a declanșat reîncărcarea.
price_per_credit_cents Prețul tău configurat per credit, în cenți.
price_per_credit_currency Moneda pentru preț (de exemplu, usd).
total_amount_cents Suma totală de taxat, în cenți (credits_requested × price_per_credit_cents).
timestamp Când a fost trimis webhook-ul (format ISO 8601).
idempotency_key O cheie unică pentru această cerere specifică de reîncărcare. Folosește-o pentru a preveni acordarea creditelor de două ori dacă serverul tău primește același webhook de mai multe ori.

Note importante

  • Interval de răcire de 5 minute — După o încercare de reîncărcare pentru un sub-cont, platforma nu va mai trimite un alt webhook pentru acel sub-cont timp de cel puțin 5 minute, chiar dacă soldul scade și mai mult. Previne taxările duplicate în timpul procesării.
  • Folosește cheia de idempotență — Verifică întotdeauna idempotency_key înainte de a acorda credite. Dacă serverul tău s-a blocat după acordarea creditelor, dar înainte de a răspunde, platforma ar putea retrimite webhook-ul la următoarea scădere a creditelor.
  • Eșecurile sunt sigure și se auto-repară — Dacă URL-ul tău de webhook este inaccesibil sau returnează o eroare, nu se acordă niciun credit. Platforma continuă să retransmită webhook-ul (o dată la fiecare interval de răcire de 5 minute) atâta timp cât sub-contul rămâne sub prag — nu necesită ca soldul să urce înapoi peste prag și să scadă din nou mai întâi. O singură taxare ratată nu mai poate lăsa un sub-cont nereîncărcat permanent.
  • Setează suma de reîncărcare la sau peste prag — Suma ta de reîncărcare configurată trebuie să fie mai mare sau egală cu pragul de reîncărcare automată, astfel încât o reîncărcare să restabilească întotdeauna soldul peste prag. (Dacă trebuie vreodată să repari un sub-cont care a scăzut mult sub prag, platforma completează automat întregul deficit — vezi credits_requested mai sus.)

2. API de acordare a creditelor

După ce serverul tău a procesat plata, apelează acest endpoint pentru a adăuga creditele în sub-cont.

Cerere

POST https://api.dmchamp.com/v1/subaccounts/credits
X-API-Key: YOUR_API_KEY
Content-Type: application/json

{
  "email": "customer@example.com",
  "amount": 500,
  "description": "Auto-recharge via webhook"
}
Câmp Obligatoriu Descriere
email Da Adresa de e-mail a sub-contului (trebuie să corespundă unui sub-cont existent în cadrul agenției tale).
amount Da Numărul de credite de acordat.
description Nu O notă care descrie de ce au fost adăugate creditele (afișată în istoricul tranzacțiilor de credit).

Autentificare: Trimiteți cheia API într-un antet de cerere — fie X-API-Key: YOUR_API_KEY, fie Authorization: Bearer YOUR_API_KEY. Antetele reprezintă metoda recomandată, deoarece o cheie în URL ajunge în istoricul browserului, în jurnalele proxy și în jurnalele de acces ale serverului. Parametrul de interogare ?apiKey=YOUR_API_KEY și un câmp apiKey în corpul JSON funcționează de asemenea, astfel încât integrările mai vechi să continue să ruleze fără modificări.

Răspuns

{
  "success": true,
  "sub_account_id": "abc123xyz",
  "credits_added": 500,
  "new_balance": 542
}

Sfat: Stocați idempotency_key din payload-ul webhook-ului și verificați-l înainte de a apela acest endpoint. Acest lucru previne acordarea accidentală a creditelor de două ori în cazul în care serverul dumneavoastră primește același webhook de mai multe ori.

Ce se întâmplă cu creditele acordate la resetarea lunară

Acest lucru depinde de modul în care este configurat sub-contul:

  • Revânzare (sub-contul vă plătește pentru credite): creditele pe care le acordați aici sunt înregistrate ca fiind credite achiziționate și se reportează în fiecare lună. Tot ceea ce sub-contul nu a cheltuit rămâne în sold.
  • Alocare (oferiți sub-contului o alocație lunară): soldul este completat până la valoarea alocației lunare la data resetării, astfel încât orice sumă necheltuită nu este reportată. Acest lucru este intenționat — alocația este acordată proaspăt în fiecare lună.

Dacă doriți ca soldul rămas al unui sub-cont să fie adăugat peste noua sa alocație lunară în loc să o înlocuiască, activați reportarea creditelor:

PUT https://api.dmchamp.com/v1/subaccounts/{subAccountUid}/limits
X-API-Key: YOUR_API_KEY
Content-Type: application/json

{
  "usageLimits": { "roll_over_to_next_month": true }
}

Dacă sub-contul — sau planul pe care se află acesta — are setată și o limită de reportare sau o dată de expirare, resetarea are loc în momentul în care acestea se aplică: alocația reportată este redusă la lunile permise, iar alocația neutilizată mai mult decât fereastra de expirare este eliminată, înainte ca noua alocație să fie adăugată. Creditele acordate prin acest endpoint, reîncărcările automate și propriile reîncărcări ale clientului sunt credite unice și nu sunt niciodată eliminate. Consultați Limitarea a ceea ce se reportează.


Exemplu complet

Un handler tipic arată astfel:

on POST /your-recharge-webhook:
  payload = request.body

  if seen(payload.idempotency_key):
    return 200  // already processed, ack and exit

  charge_result = your_payment_provider.charge(
    email = payload.sub_account_email,
    amount_cents = payload.total_amount_cents,
    currency = payload.price_per_credit_currency,
  )

  if not charge_result.ok:
    return 500  // platform will retry on next balance drop

  api.post("/v1/subaccounts/credits", {
    email = payload.sub_account_email,
    amount = payload.credits_requested,
    description = "Auto-recharge via " + your_provider_name,
  })

  mark_seen(payload.idempotency_key)
  return 200