Hoppa till huvudinnehåll

Översikt

On-demand-prenumerationer låter dig auktorisera en kunds betalningsmetod en gång och sedan ta ut variabla belopp när du behöver, istället för på ett fast schema. Denna funktion är tillgänglig för alla konton—ingen godkännande krävs. Använd denna guide för att:
  • Skapa en on-demand-prenumeration (auktorisera ett mandat med valfritt initialpris)
  • Utlösa efterföljande avgifter med anpassade belopp
  • Spåra resultat med hjälp av webhooks
För en allmän prenumerationsinställning, se Prenumerationsintegrationsguiden.

Förutsättningar

  • Dodo Payments handelskonto och API-nyckel
  • Webhook-hemlighet konfigurerad och en slutpunkt för att ta emot händelser
  • En prenumerationsprodukt i din katalog
Om du vill att kunden ska godkänna mandatet via hosted checkout, ange payment_link: true och tillhandahåll en return_url.

Hur on-demand fungerar

  1. Du skapar en prenumeration med on_demand-objektet för att auktorisera en betalningsmetod och eventuellt ta ut en första avgift.
  2. Senare skapar du avgifter mot den prenumerationen med anpassade belopp via den dedikerade charge-slutpunkten.
  3. Du lyssnar på webhooks (t.ex. payment.succeeded, payment.failed) för att uppdatera ditt system.

Skapa en on-demand-prenumeration

Slutpunkt: POST /checkouts Nyckelfält för begäran (kropp):
Vänligen se dem i Skapa Checkout-session

Skapa en on-demand-prenumeration

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"
}

Ta ut en avgift för en on-demand-prenumeration

Efter att mandatet har auktoriserats, skapa avgifter vid behov. Slutpunkt: POST /subscriptions/{subscription_id}/charge Nyckelfält för begäran (kropp):
product_price
integer
obligatorisk
Belopp att debitera (i den minsta valutabeteckningen). Exempel: för att debitera $25,00, skicka 2500.
product_currency
string
Valfri valutaoch överstyrning för avgiften.
product_description
string
Valfri beskrivningsöverstyrning för denna avgift.
adaptive_currency_fees_inclusive
boolean
Om sant, inkluderas adaptiva valutavgifter i product_price. Om falskt läggs avgifterna ovanpå.
metadata
object
Ytterligare metadata för betalningen. Om det utelämnas används prenumerationens metadata.
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" }
Debitering av en prenumeration som inte är on-demand kan misslyckas. Säkerställ att prenumerationen har on_demand: true i sina uppgifter innan du debiterar.

Betalningsåterförsök

Vårt bedrägeridetekteringssystem kan blockera aggressiva återförsöksmönster (och kan flagga dem som potentiell korttestning). Följ en säker återförsökspolicy.
Burst-retrymönster kan flaggas som bedrägliga eller misstänkt korttestning av våra risk system och processorer. Undvik klustrade omförsök; följ backoff-schemat och tidsanpassningsvägledningen nedan.

Principer för säkra återförsökspolicys

  • Backoff-mekanism: Använd exponentiell backoff mellan försök.
  • Retrysgränser: Begränsa totala försök (3–4 försök max).
  • Intelligent filtrering: Försök bara igen vid omförsökbara fel (t.ex. nätverks-/utfärdarfel, otillräckliga medel); försök aldrig igen vid ett fast avslag.
  • Förebygg korttestning: Försök inte igen vid fel som DO_NOT_HONOR, STOLEN_CARD, LOST_CARD, PICKUP_CARD, FRAUDULENT, AUTHENTICATION_FAILURE.
  • Variera metadata (valfritt): Om du har ett eget retry-system, särskilj retry-tillfällen via metadata (t.ex. retry_attempt).

Föreslaget återförsökschema (prenumerationer)

  • 1:a försök: Omedelbart när du skapar avgiften
  • 2:a försök: Efter 3 dagar
  • 3:e försök: Efter ytterligare 7 dagar (10 dagar totalt)
  • 4:e försök (slutgiltigt): Efter ytterligare 7 dagar (17 dagar totalt)
Slutsteg: om fortfarande obetald, markera prenumerationen som obetald eller avbryt den, baserat på din policy. Meddela kunden under fönstret för att uppdatera sin betalningsmetod.

Undvik burst-återförsök; anpassa till auktoriseringstid

  • Anslut omförsök till ursprunglig auktoriseringstidpunkt för att undvika “burst”-beteende över din portfölj.
  • Exempel: Om kunden startar en testperiod eller mandat kl. 13:10 idag, schemalägg följande omförsök kl. 13:10 på efterföljande dagar enligt din backoff (t.ex. +3 dagar → 13:10, +7 dagar → 13:10).
  • Alternativt, om du sparar den senaste lyckade betalningstiden T, planera nästa försök vid T + X days för att bevara tidpunkten.
Tidszon och sommartid: använd en konsekvent tidsstandard för schemaläggning och konvertera endast för visning för att behålla intervallen.

Avslagkoder du inte bör återförsöka

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
För en komplett lista över avvisningsorsaker och huruvida de kan rättas av användaren, se dokumentationen Transaction Failures.
Försök bara igen vid mjuka/tillfälliga problem (t.ex. insufficient_funds, issuer_unavailable, processing_error, nätverks-timeouter). Om samma avslag upprepas, pausa ytterligare omförsök.

Implementeringsriktlinjer (ingen kod)

  • Använd en schemaläggare/kö som sparar exakta tidsstämplar; beräkna nästa försök vid exakt samma tidpunkt (t.ex. T + 3 days vid samma HH:MM).
  • Behåll och referera till den senaste lyckade betalningstidsstämpeln T för att beräkna nästa försök; samla inte flera prenumerationer vid samma ögonblick.
  • Utvärdera alltid den senaste avvisningsorsaken; stoppa omförsök för fasta avslag i listan ovan.
  • Begränsa samtidiga omförsök per kund och per konto för att förhindra oavsiktliga toppar.
  • Kommunicera proaktivt: skicka e-post/SMS till kunden för att uppdatera deras betalningsmetod före nästa planerade försök.
  • Använd metadata endast för observabilitet (t.ex. retry_attempt); försök aldrig “undkomma” bedrägeri-/riskssystem genom att rotera obetydliga fält.

Spåra resultat med webhooks

Implementera webhook-hantering för att spåra kundresan. Se Implementera Webhooks.
  • subscription.active: Mandat auktoriserat och prenumeration aktiverad
  • subscription.failed: Skapande misslyckades (t.ex. mandatmisslyckande)
  • subscription.on_hold: Prenumeration placerad på håll (t.ex. obetald status)
  • payment.succeeded: Avgift lyckades
  • payment.failed: Avgift misslyckades
För on-demand-flöden, fokusera på payment.succeeded och payment.failed för att stämma av användningsbaserade avgifter.

Testning och nästa steg

1

Create in test mode

Använd din test-API-nyckel för att skapa prenumerationen med payment_link: true, öppna länken och slutför mandatet.
2

Trigger a charge

Anropa charge-slutpunkten med ett litet product_price (t.ex. 100) och verifiera att du får payment.succeeded.
3

Go live

Byt till din live API-nyckel när du har validerat händelser och interna statusuppdateringar.

Felsökning

  • 422 Ogiltig förfrågan: Säkerställ att on_demand.mandate_only tillhandahålls vid skapande och att product_price tillhandahålls för avgifter.
  • Valutafel: Om du åsidosätter product_currency, bekräfta att den stöds för ditt konto och din kund.
  • Inga webhooks mottagna: Verifiera din webhook-URL och signaturhemlighetskonfiguration.