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.
On-demand-prenumeration är nu tillgängliga för alla företag. Denna funktion möjliggör flexibel fakturering för användningsbaserade och mätbara tjänster.
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 en värd-checkout, ställ in 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 samla in en initial avgift.
  2. Senare skapar du avgifter mot den prenumerationen med anpassade belopp via den dedikerade avgiftsslutpunkten.
  3. Du lyssnar på webhooks (t.ex. payment.succeeded, payment.failed) för att uppdatera ditt system.

Skapa en on-demand-prenumeration

Slutpunkt: POST /subscriptions Nyckelfält för begäran (kropp):
product_id
string
obligatorisk
Produkt-ID för prenumerationen.
quantity
integer
obligatorisk
Antal enheter. Minst 1.
billing
object
obligatorisk
Faktureringsadress för kunden.
customer
object
obligatorisk
Antingen koppla en befintlig kund eller tillhandahålla kundinformation.
Om sant, skapar en värd-checkout-länk för mandatauktorisering och valfri initial betalning.
return_url
string
Var kunden ska omdirigeras efter att ha slutfört värd-checkouten.
on_demand.mandate_only
boolean
obligatorisk
Om sant, auktoriserar betalningsmetoden utan att ta betalt från kunden vid skapandet.
on_demand.product_price
integer
Initial avgiftsbelopp (i den minsta valutaenheten). Om angivet, åsidosätter detta värde produktens ursprungliga pris som ställts in vid produktens skapande. Om utelämnat används produktens lagrade pris. Exempel: för att ta betalt $1.00, skicka 100.
on_demand.product_currency
string
Valfritt valutaöverskrivning för den initiala avgiften. Standard till produktens valuta.
on_demand.product_description
string
Valfritt beskrivningsöverskrivning för fakturering och linjeposter.
on_demand.adaptive_currency_fees_inclusive
boolean
Om sant, inkluderar adaptiva valutavgifter inom product_price. Om falskt, läggs avgifterna till ovanpå. Ignoreras när adaptiv prissättning är inaktiverad.

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.subscriptions.create({
    billing: { city: 'SF', country: 'US', state: 'CA', street: '1 Market St', zipcode: '94105' },
    customer: { customer_id: 'customer_123' },
    product_id: 'prod_sub_123',
    quantity: 1,
    payment_link: true,
    return_url: 'https://example.com/billing/success',
    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,
    },
  });

  // If payment_link was true, redirect the customer to authorize the mandate
  console.log(subscription.payment_link);
}

main().catch(console.error);
Ställ in payment_link: true, omdirigera kunden till payment_link för att slutföra mandatauktoriseringen.
Success
{
  "subscription_id": "sub_123",
  "payment_link": "https://pay.dodopayments.com/checkout/...",
  "customer": { "customer_id": "customer_123", "email": "[email protected]", "name": "Alex Doe" },
  "metadata": {},
  "recurring_pre_tax_amount": 0,
  "addons": []
}

Ta betalt 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 ta betalt (i den minsta valutaenheten). Exempel: för att ta betalt $25.00, skicka 2500.
product_currency
string
Valfritt valutaöverskrivning för avgiften.
product_description
string
Valfritt beskrivningsöverskrivning för denna avgift.
adaptive_currency_fees_inclusive
boolean
Om sant, inkluderar adaptiva valutavgifter inom product_price. Om falskt, läggs avgifterna till ovanpå.
metadata
object
Ytterligare metadata för betalningen. Om utelämnat används prenumerationsmetadata.
import DodoPayments from 'dodopayments';

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

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" }
Att ta betalt för en prenumeration som inte är on-demand kan misslyckas. Se till att prenumerationen har on_demand: true i sina detaljer innan du tar betalt.

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-återförsöksmönster kan flaggas som bedrägliga eller misstänkta korttestningar av våra risk- och processor-system. Undvik klusteråterförsök; följ nedtrappningsschemat och tidsjusteringsguiden nedan.

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

  • Nedtrappningsmekanism: Använd exponentiell nedtrappning mellan återförsök.
  • Återförsöksgränser: Sätt ett tak för totala återförsök (3–4 försök max).
  • Intelligent filtrering: Återförsök endast vid återförsökbara fel (t.ex. nätverks-/utfärdarfel, otillräckliga medel); återförsök aldrig hårda avslag.
  • Förhindra korttestning: Återförsök inte fel som DO_NOT_HONOR, STOLEN_CARD, LOST_CARD, PICKUP_CARD, FRAUDULENT, AUTHENTICATION_FAILURE.
  • Variera metadata (valfritt): Om du upprätthåller ditt eget återförsökssystem, differentiera återförsök 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 (totalt 10 dagar)
  • 4:e försök (slutgiltigt): Efter ytterligare 7 dagar (totalt 17 dagar)
Slutligt steg: 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

  • Ankare återförsök till den ursprungliga auktoriseringstidsstämpeln för att undvika “burst”-beteende över din portfölj.
  • Exempel: Om kunden börjar en provperiod eller mandat klockan 13:10 idag, schemalägg uppföljningsåterförsök klockan 13:10 på följande dagar enligt din nedtrappning (t.ex. +3 dagar → 13:10, +7 dagar → 13:10).
  • Alternativt, om du lagrar den senaste framgångsrika betalningstiden T, schemalägg nästa försök vid T + X days för att bevara tidsjusteringen.
Tidszon och sommartid: använd en konsekvent tidsstandard för schemaläggning och konvertera endast för visning för att upprätthålla intervall.

Avslag koder du inte bör återförsöka

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
För en omfattande lista över avslagsskäl och huruvida de kan rättas av användaren, se Transaktionsfel dokumentationen.
Återförsök endast vid mjuka/tillfälliga problem (t.ex. insufficient_funds, issuer_unavailable, processing_error, nätverksavbrott). Om samma avslag upprepas, pausa ytterligare återförsök.

Implementeringsriktlinjer (ingen kod)

  • Använd en schemaläggare/kö som bevarar exakta tidsstämplar; beräkna nästa försök vid exakt tidpunkt (t.ex. T + 3 days vid samma HH:MM).
  • Upprätthåll och referera till den senaste framgångsrika betalningstidsstämpeln T för att beräkna nästa försök; gruppera aldrig flera prenumerationer vid samma tillfälle.
  • Utvärdera alltid den senaste avslagsskäl; stoppa återförsök för hårda avslag i hoppa-listan ovan.
  • Sätt ett tak för samtidiga återförsök per kund och per konto för att förhindra oavsiktliga toppar.
  • Kommunicera proaktivt: e-posta/SMS:a kunden för att uppdatera sin betalningsmetod innan nästa schemalagda försök.
  • Använd metadata endast för observabilitet (t.ex. retry_attempt); försök aldrig att “undvika” bedrägeri/risk-system genom att rotera oväsentliga fält.

Spåra resultat med webhooks

Implementera webhookhantering 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 satt på paus (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 avstämma användningsbaserade avgifter.

Testning och nästa steg

1

Skapa i testläge

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

Utlösa en avgift

Anropa avgifts-slutpunkten med en liten product_price (t.ex. 100) och verifiera att du får payment.succeeded.
3

Gå live

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

Felsökning

  • 422 Ogiltig begäran: Se till att on_demand.mandate_only tillhandahålls vid skapande och product_price tillhandahålls för avgifter.
  • Valuta fel: Om du åsidosätter product_currency, bekräfta att den stöds för ditt konto och kund.
  • Inga webhooks mottagna: Verifiera din webhook-URL och signaturhemlighetskonfiguration.