Vai al contenuto principale

Panoramica

Le sottoscrizioni on-demand ti consentono di autorizzare un metodo di pagamento di un cliente una sola volta e poi addebitare importi variabili ogni volta che ne hai bisogno, invece di seguire un programma fisso. Questa funzionalità è disponibile per tutti gli account—non è necessaria alcuna approvazione. Usa questa guida per:
  • Creare una sottoscrizione on-demand (autorizzare un mandato con un prezzo iniziale opzionale)
  • Attivare addebiti successivi con importi personalizzati
  • Monitorare i risultati utilizzando i webhook
Per una configurazione generale della sottoscrizione, consulta la Guida all’integrazione delle sottoscrizioni.

Requisiti

  • Account commerciante Dodo Payments e chiave API
  • Segreto del webhook configurato e un endpoint per ricevere eventi
  • Un prodotto in abbonamento nel tuo catalogo
Se vuoi che il cliente approvi il mandato tramite il checkout ospitato, imposta payment_link: true e fornisci un return_url.

Come funziona l’on-demand

  1. Crei un abbonamento con l’oggetto on_demand per autorizzare un metodo di pagamento e, facoltativamente, addebitare una somma iniziale.
  2. Successivamente, crei addebiti contro tale abbonamento con importi personalizzati usando l’endpoint dedicato agli addebiti.
  3. Ascolti i webhook (es. payment.succeeded, payment.failed) per aggiornare il tuo sistema.

Crea una sottoscrizione on-demand

Endpoint: POST /checkouts Campi chiave della richiesta (corpo):
Trovali in Crea sessione di checkout

Crea una sottoscrizione on-demand

import DodoPayments from 'dodopayments';

const client = new DodoPayments({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'test_mode', // defaults to 'live_mode'
});

async function main() {
  const subscription = await client.checkoutSessions.create({
    product_cart: [{ product_id: 'pdt_123', quantity: 1 }],
    billing_address:  { city: 'SF', country: 'US', state: 'CA', street: '1 Market St', zipcode: '94105' },
    customer: { customer_id: 'cus_123' },
    return_url: 'https://example.com/billing/success',
    subscription_data: {
        on_demand: {
            mandate_only: true // set false to collect an initial charge
            // product_price: 1000, // optional: charge $10.00 now if mandate_only is false
            // product_currency: 'USD',
            // product_description: 'Custom initial charge',
            // adaptive_currency_fees_inclusive: false,
        }
    }
  });

  console.log(subscription.checkout_url);
}

main().catch(console.error);
Success
{
  "session_id": "cks_123",
  "checkout_url": "https://test.checkout.dodopayments.com/session/cks123"
}

Addebita una sottoscrizione on-demand

Dopo che il mandato è stato autorizzato, crea addebiti secondo necessità. Endpoint: POST /subscriptions/{subscription_id}/charge Campi chiave della richiesta (corpo):
product_price
integer
obbligatorio
Importo da addebitare (nell’unità monetaria più piccola). Esempio: per addebitare $25,00, passa 2500.
product_currency
string
Sovrascrittura facoltativa della valuta per l’addebito.
product_description
string
Sovrascrittura facoltativa della descrizione per questo addebito.
adaptive_currency_fees_inclusive
boolean
Se true, include le commissioni in valuta adattiva all’interno di product_price. Se false, le commissioni vengono aggiunte sopra.
metadata
object
Metadata aggiuntivi per il pagamento. Se omessi, vengono usati i metadata dell’abbonamento.
import DodoPayments from 'dodopayments';

const client = new DodoPayments({ bearerToken: process.env.DODO_PAYMENTS_API_KEY });

async function chargeNow(subscriptionId) {
  const res = await client.subscriptions.charge(subscriptionId, { product_price: 2500 });
  console.log(res.payment_id);
}

chargeNow('sub_123').catch(console.error);
Success
{ "payment_id": "pay_abc123" }
Addebitare un abbonamento che non è on-demand potrebbe fallire. Assicurati che l’abbonamento abbia on_demand: true nei suoi dettagli prima dell’addebito.

Riprova ai pagamenti

Il nostro sistema di rilevamento delle frodi potrebbe bloccare schemi di ripetizione aggressivi (e può contrassegnarli come potenziale test di carte). Segui una politica di ripetizione sicura.
I modelli di retry a raffica possono essere segnalati come frode o come test di carte dai nostri sistemi di rischio e dai processori. Evita ritentativi ravvicinati; segui la pianificazione di backoff e l’allineamento temporale indicati di seguito.

Principi per politiche di ripetizione sicure

  • Meccanismo di backoff: Usa il backoff esponenziale tra i retry.
  • Limiti di retry: Limita i retry totali (max 3–4 tentativi).
  • Filtraggio intelligente: Riprova solo su errori ripetibili (es. errori di rete/issuer, fondi insufficienti); non riprovare mai rifiuti hard.
  • Prevenzione dei test di carte: Non riprovare errori come DO_NOT_HONOR, STOLEN_CARD, LOST_CARD, PICKUP_CARD, FRAUDULENT, AUTHENTICATION_FAILURE.
  • Varia i metadata (opzionale): Se gestisci il tuo sistema di retry, differenzia i retry tramite metadata (es. retry_attempt).

Programma di ripetizione suggerito (sottoscrizioni)

  • 1° tentativo: Immediato quando crei l’addebito
  • 2° tentativo: Dopo 3 giorni
  • 3° tentativo: Dopo altri 7 giorni (10 giorni totali)
  • 4° tentativo (finale): Dopo altri 7 giorni (17 giorni totali)
Passaggio finale: se ancora non pagato, contrassegna la sottoscrizione come non pagata o annullala, in base alla tua politica. Notifica il cliente durante il periodo per aggiornare il proprio metodo di pagamento.

Evita ripetizioni a raffica; allineati all’orario di autorizzazione

  • Ancorare i retry al timestamp originale dell’autorizzazione per evitare comportamenti a «raffica» nel tuo portfolio.
  • Esempio: se il cliente avvia una prova o un mandato alle 13:10 di oggi, pianifica i retry successivi alle 13:10 dei giorni successivi secondo il tuo backoff (es. +3 giorni → 13:10, +7 giorni → 13:10).
  • In alternativa, se conservi l’ultimo pagamento riuscito T, programma il tentativo successivo all’T + X days per mantenere l’allineamento con l’orario del giorno.
Fuso orario e ora legale: usa uno standard temporale coerente per la pianificazione e converti solo per la visualizzazione, per mantenere gli intervalli.

Codici di rifiuto che non dovresti ripetere

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
Per un elenco completo dei motivi di rifiuto e se sono correggibili dall’utente, consulta la documentazione su Transaction Failures.
Riprova solo su problemi soft/temporanei (es. insufficient_funds, issuer_unavailable, processing_error, timeout di rete). Se lo stesso rifiuto si ripete, interrompi ulteriori retry.

Linee guida per l’implementazione (senza codice)

  • Usa un scheduler/queue che conservi timestamp precisi; calcola il prossimo tentativo allo stesso offset orario (es. T + 3 days alla stessa HH:MM).
  • Mantieni e fai riferimento all’ultimo timestamp di pagamento riuscito T per calcolare il tentativo successivo; non concentrare più abbonamenti nello stesso istante.
  • Valuta sempre l’ultimo motivo di rifiuto; interrompi i retry per i rifiuti hard nella lista di esclusione sopra.
  • Limita i retry concorrenti per cliente e per account per evitare picchi accidentali.
  • Comunica proattivamente: invia email/SMS al cliente per aggiornare il metodo di pagamento prima del prossimo tentativo programmato.
  • Usa i metadata solo per l’osservabilità (es. retry_attempt); non cercare di «eludere» i sistemi antifrode/rischio ruotando campi irrilevanti.

Monitora i risultati con i webhook

Implementa la gestione dei webhook per monitorare il percorso del cliente. Consulta Implementazione dei webhook.
  • subscription.active: Mandato autorizzato e sottoscrizione attivata
  • subscription.failed: Creazione fallita (ad es., fallimento del mandato)
  • subscription.on_hold: Sottoscrizione messa in attesa (ad es., stato non pagato)
  • payment.succeeded: Addebito riuscito
  • payment.failed: Addebito fallito
Per i flussi on-demand, concentra l’attenzione su payment.succeeded e payment.failed per riconciliare gli addebiti basati sull’utilizzo.

Test e prossimi passi

1

Create in test mode

Usa la tua chiave API di test per creare l’abbonamento con payment_link: true, poi apri il link e completa il mandato.
2

Trigger a charge

Chiama l’endpoint degli addebiti con un piccolo product_price (es. 100) e verifica di ricevere payment.succeeded.
3

Go live

Passa alla tua chiave API live una volta validati gli eventi e gli aggiornamenti dello stato interno.

Risoluzione dei problemi

  • 422 Invalid Request: Assicurati che on_demand.mandate_only venga fornito alla creazione e product_price venga fornito per gli addebiti.
  • Errori di valuta: Se sovrascrivi product_currency, conferma che sia supportato per il tuo account e cliente.
  • Nessun webhook ricevuto: Verifica la configurazione del tuo URL webhook e del segreto di firma.