Plăți
Intențiile de plată și idempotența
O intenție de plată stabilește imuabil termenii economici ai tranzacției înainte ca utilizatorul să interacționeze cu widgetul. Aceasta previne ca un client rău intenționat să manipuleze suma, contul de destinație sau conceptul de transfer din frontend.
Parametri pentru crearea unei intenții de plată (POST /payments/?action=create)
1. Model standard pentru comercianți (beneficiar propriu)
În acest model, comerciantul definește toate datele de colectare:
| Câmp | Tip | Obligatoriu | Descriere și reguli |
|---|---|---|---|
amount_minor |
Număr întreg | Da | Cantitatea în unități mai mici (cenți). De exemplu, 1500 reprezintă 15,00 EUR. |
currency |
Șir de text | Da | Cod valutar ISO 4217 cu 3 litere. În prezent EUR. |
beneficiary |
Obiect de date JSON | Da | Date de cont de destinație: name (proprietar, 1 până la 140 de caractere text) și iban (IBAN valide fără spații, cu cifra de control verificată). Suportă doar aceste două chei. |
reference |
Șir de text | Da | Conceptul este vizibil pe extrasul bancar (maxim 140 de caractere de text). |
customer_reference |
Șir de text | Da | Identificatorul intern al comenzii sau clientului tău (1 până la 128 de caractere de text: litere, cifre, ., _, :, -; trebuie să înceapă cu o literă sau un număr). |
allowed_origin |
Șir de text | Da | Exact sursa HTTPS care va încorpora widget-ul (de exemplu, https://tienda.example.com), fără cale. |
allowed_institution_codes |
Array de date | Nu | Lista codurilor de entitate permise (de ex. ["santander-es", "bbva-es"]). Dacă este omisă, orice entitate din catalog este permisă. |
locale |
Șir de text | Nu | Limbajul interfeței widget-urilor. Doar essunt acceptate în această versiune; orice altă valoare returnează 422 invalid_locale. |
expected_mode |
Șir de text | Nu | mock sau live. Verifică dacă apelezi mediul așteptat; nu schimbă mediul. Dacă nu se potrivește, 409 payment_mode_mismatch. |
Corpul este o listă albă strictă: trimiterea unui câmp care nu se află în acest tabel returnează 422 invalid_request, la fel ca și omiterea unuia obligatoriu. Antetul Content-Type: application/json este obligatoriu (415 json_required) iar corpul este limitat la 32 KB.
2. Model cu profil gestionat (Donații/Demonstrații)
Pentru cazurile reglementate sau demonstrațiile publice, cum ar fi cruz_roja_demo, serverul impune regulile financiare și stabilește conturile țintă oficiale:
| Câmp | Tip | Obligatoriu | Descriere și reguli |
|---|---|---|---|
profile |
Șir de text | Da | Identificator de profil (de exemplu cruz_roja_demo). |
institution_code |
Șir de text | Da | Cod de entitate selectat de utilizator (din profile-institutions). |
amount_minor |
Număr întreg | Da | Suma limitată de polițele de profil (de exemplu, de la 1 la 100 de cenți). |
customer_reference |
Șir de text | Da | Referința de audit a sistemului tău. |
allowed_origin |
Șir de text | Da | Widget HTTPS sursă. |
locale |
Șir de text | Nu | Limbajul widget-urilor (es). |
expected_mode |
Șir de text | Nu | Modul așteptat (mock sau live). |
Când profileeste specificat, serverul atribuie automat beneficiarul oficial și conceptul corespunzător. Nu trimiteți beneficiary sau reference la cereri cu un profil administrat.
Regula Idempotency-Key
Antetul Idempotency-Key este necesar în orice cerere pentru a crea o intenție de plată. Trebuie să conțină între 16 și 128 de caractere de text ASCII vizibil, fără spații (de exemplu, un UUID v4). Domeniul său este unic pentru compania autentifică:
- Aceeași cheie de idempotență și același corp: returnează intenția inițială creată anterior împreună cu
idempotent_replay: true. Nu se generează nicio nouă taxă și ordinul bancar nu este duplicat. - Aceeași cheie de idempotență și corp diferit: răspunde imediat cu HTTP
409 Conflict. - Aceeași cheie de idempotență într-o altă companie: aparține unui alt spațiu complet izolat de idempotență.
Dacă o cerere de a crea o intenție de plată suferă o întrerupere de rețea sau un timeout, reîncearcă cu exact același antet Idempotency-Key și același corp. Nu generați o cheie nouă în cazul unei defecțiuni tranzitorii.
Persistență și ciclu de viață
- Persistență anterioară: Intenția este înregistrată în baza de date înainte de a returna răspunsul sau de a interacționa cu orice conector bancar.
- Tokenul de widget efemer: Răspunsul token (
payment.widget.token) are o valabilitate scurtă (de obicei între 15 și 30 de minute) și poate fi folosit doar dinallowed_origindeclarat. - Blocarea concurenței: Sistemul implementează un control optimist și leases pentru a preveni ca două apeluri simultane să autorizeze sau să modifice aceeași intenție.
Coduri de eroare comune
| HTTP | Cod | Cauză | Acțiune recomandată |
|---|---|---|---|
400 |
idempotency_key_required |
Antetul Idempotency-Key lipsește sau este formatat incorect. |
Generează o cheie validă între 16 și 128 de caractere de text ASCII vizibil, fără spații. |
409 |
idempotency_conflict |
Cheia a fost reutilizată cu detalii de plată diferite. | Generează o cheie nouă pentru alte plăți sau reutilizează exact același corp al cererii. |
409 |
payment_mode_mismatch |
expected_mode nu se potrivește cu modul mediului pe care îl apelezi. |
Verifică dacă țintești spre sandbox sau producție; modul este setat de implementare, nu de apel. |
401 |
invalid_api_key |
Antetul X-API-Keylipsește, formatul său este invalid sau cheia de acces nu există sau este inactivă. |
Verifică codul de acces. Nu îl include niciodată în frontend. |
403 |
payments_not_allowed |
Cheia API nu are produsul PAYMENTS activat. |
Contactează suportul Wealth Reader pentru a activa plățile pe contul tău. |
403 |
payment_profile_not_allowed |
Profilul gestionat nu este activat pentru compania ta. | Solicită înregistrarea contului de profil de la Wealth Reader. |
429 |
api_limit_reached |
Codul tău de acces a epuizat numărul cumulativ de apeluri. | Nu se rezolvă prin reîncercare sau așteptare: nu există fereastră sau resetare automată. Solicită extinderea limitei. |
415 |
json_required |
Antetul Content-Type: application/jsonlipsește. |
Trimite corpul ca JSON. |
422 |
invalid_request |
Un câmp obligatoriu lipsește sau a fost trimis un câmp nerecunoscut. | Verifică tabelul parametrilor: corpul este o listă albă strictă. |
422 |
invalid_institution |
Entitatea selectată este indisponibilă sau invalidă. | Vezi GET /payments/entities/ pentru coduri valide. |
422 |
invalid_amount |
Suma este mai mică decât minimul (€0,01) sau nu este un întreg. | Verifică dacă trimiți un întreg în cenți (amount_minor). |
Pasul următor
Continuă cu Statusuri, consultări periodice privind statutul și reconciliere.