الانتقال إلى المحتوى الرئيسي

Change Plan API

Full API docs for updating subscriptions.

Plan Change Preview

See charge amounts before changing plans.

Integration Guide

Step-by-step subscription setup.

What is a subscription upgrade or downgrade?

Changing plans lets you move a customer between subscription tiers or quantities. Use it to:
  • Align pricing with usage or features
  • Move from monthly to annual (or vice versa)
  • Adjust quantity for seat-based products
Plan changes can trigger an immediate charge depending on the proration mode you choose.

When to use plan changes

  • Upgrade when a customer needs more features, usage, or seats
  • Downgrade when usage decreases
  • Migrate users to a new product or price without cancelling their subscription

Plan Change Flow

Prerequisites

Before implementing subscription plan changes, ensure you have:
  • A Dodo Payments merchant account with active subscription products
  • API credentials (API key and webhook secret key) from the dashboard
  • An existing active subscription to modify
  • Webhook endpoint configured to handle subscription events
For detailed setup instructions, see our Integration Guide.

Step-by-Step Implementation Guide

Follow this comprehensive guide to implement subscription plan changes in your application:
1

Understand Plan Change Requirements

Before implementing, determine:
  • Which subscription products can be changed to which others
  • What proration mode fits your business model
  • How to handle failed plan changes gracefully
  • Which webhook events to track for state management
Test plan changes thoroughly in test mode before implementing in production.
2

Choose Your Proration Strategy

Select the billing approach that aligns with your business needs:
Best for: SaaS applications wanting to charge fairly for unused time
  • Calculates exact prorated amount based on remaining cycle time
  • Charges a prorated amount based on unused time remaining in the cycle
  • Provides transparent billing to customers
3

Implement the Change Plan API

Use the Change Plan API to modify subscription details:
subscription_id
string
مطلوب
The ID of the active subscription to modify.
product_id
string
مطلوب
The new product ID to change the subscription to.
quantity
integer
افتراضي:"1"
Number of units for the new plan (for seat-based products).
proration_billing_mode
string
مطلوب
How to handle immediate billing: prorated_immediately, full_immediately, difference_immediately, or do_not_bill.
addons
array
Optional addons for the new plan. Leaving this empty removes any existing addons.
on_payment_failure
string
Controls behavior when the plan change payment fails:
  • prevent_change: Keep subscription on current plan until payment succeeds
  • apply_change (default): Apply plan change immediately regardless of payment outcome
If not specified, uses the business-level default setting.
discount_codes
array
رموز الخصم المكدسة الاختيارية للتطبيق على الخطة الجديدة (بحد أقصى 20، تتم التطبيقة حسب ترتيب المصفوفة). يختلف السلوك بناءً على ما ترسله:
  • غير متوفر / null — سيتم الحفاظ على الخصومات الحالية مع preserve_on_plan_change=true إذا كانت تنطبق على المنتج الجديد.
  • [] (مصفوفة فارغة) — إزالة جميع الخصومات الحالية من الاشتراك.
  • ["CODE_A", "CODE_B", ...] — استبدال أي خصومات موجودة بهذه المجموعة المكدسة.
discount_code
string
مهمل
مهمل — يفضل استخدام discount_codes للتكاملات الجديدة. هذا الحقل لا يزال يعمل للتوافق مع النسخ القديمة، ولكنه لا يمكن دمجه مع discount_codes في نفس الطلب.
effective_at
string
افتراضي:"immediately"
متى ينبغي تطبيق تغيير الخطة:
  • immediately (الافتراضي): تطبيق تغيير الخطة فورًا
  • next_billing_date: جدولة التغيير لتاريخ الفواتير التالي. يبقى العميل على خطته الحالية حتى نهاية دورة الفواتير.
استخدم next_billing_date للتخفيضات حتى يحتفظ العملاء بفوائد خطتهم الحالية حتى نهاية فترة الفواتير.
4

Handle Webhook Events

إعداد التعامل مع الويب هوك لمتابعة نتائج تغيير الخطة:
  • subscription.active: تغيير الخطة ناجح، تم تحديث الاشتراك
  • subscription.plan_changed: تم تغيير خطة الاشتراك (تحديث الترقية/التخفيض/الإضافة)
  • subscription.on_hold: فشل شحن تغيير الخطة، تم تعليق الاشتراك
  • payment.succeeded: نجاح الشحن الفوري لتغيير الخطة
  • payment.failed: فشل الشحن الفوري
تحقق دائمًا من توقيعات الويب هوك وطبق معالجة الأحداث بدون آثار جانبية.
5

Update Your Application State

بناءً على أحداث الويب هوك، قم بتحديث تطبيقك:
  • منح/إلغاء الميزات بناءً على الخطة الجديدة
  • تحديث لوحة تحكم العميل بتفاصيل الخطة الجديدة
  • إرسال رسائل تأكيد عبر البريد الإلكتروني حول تغييرات الخطة
  • تسجيل تغييرات الفوترة لأغراض التدقيق
6

Test and Monitor

اختبر تنفيذك بدقة:
  • اختبر كافة أوضاع القسمة مع سيناريوهات مختلفة
  • تحقق من أن التعامل مع الويب هوك يعمل بشكل صحيح
  • راقب معدلات نجاح تغيير الخطة
  • إعداد تنبيهات للتغييرات الفاشلة للخطة
تنفيذ تغيير خطة الاشتراك لديك الآن جاهز للاستخدام في الإنتاج.

معاينة تغييرات الخطة

قبل الالتزام بتغيير الخطة، استخدم واجهة برمجة التطبيقات للمعاينة لعرض تكلفة العملاء بدقة:
const preview = await client.subscriptions.previewChangePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
});

// Show customer the charge before confirming
console.log('Immediate charge:', preview.immediate_charge.summary);
console.log('New plan details:', preview.new_plan);
استخدم واجهة برمجة التطبيقات للمعاينة لإنشاء حوارات التأكيد التي تعرض للعملاء المبلغ الدقيق الذي سيتم تحصيله منهم قبل تأكيد تغيير الخطة.

واجهة برمجة التطبيقات لتغيير الخطة

استخدم واجهة برمجة التطبيقات لتغيير الخطة لتعديل المنتج والكمية وسلوك القسمة للاشتراك النشط.

أمثلة سريعة للبدء

import DodoPayments from 'dodopayments';

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

async function changePlan() {
  const result = await client.subscriptions.changePlan('sub_123', {
    product_id: 'prod_new',
    quantity: 3,
    proration_billing_mode: 'prorated_immediately',
    on_payment_failure: 'prevent_change', // Optional: control behavior on payment failure
  });
  console.log(result.status, result.invoice_id, result.payment_id);
}

changePlan();
Success
{
  "status": "processing",
  "subscription_id": "sub_123",
  "invoice_id": "inv_789",
  "payment_id": "pay_456",
  "proration_billing_mode": "prorated_immediately"
}
يتم إرجاع الحقول مثل invoice_id وpayment_id فقط عند إنشاء شحن فوري و/أو فاتورة أثناء تغيير الخطة. اعتمد دائمًا على أحداث الويب هوك ( مثل payment.succeeded, subscription.plan_changed) لتأكيد النتائج.
إذا فشل الشحن الفوري، فقد ينتقل الاشتراك إلى subscription.on_hold حتى ينجح الدفع.

إدارة الإضافات

عند تغيير خطط الاشتراك، يمكنك أيضًا تعديل الإضافات:
// Add addons to the new plan
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [
    { addon_id: 'addon_123', quantity: 2 }
  ]
});

// Remove all existing addons
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [] // Empty array removes all existing addons
});
تشمل الإضافات في حساب القسمة وستتحمل الرسوم وفقًا لوضع القسمة المختار.

تطبيق رموز الخصم

يمكنك تطبيق رموز خصم مكدسة عند تغيير خطط الاشتراك (بحد أقصى 20، تطبق بترتيب المصفوفة). يكون هذا مفيدًا لتقديم أسعار ترويجية على الترقيات أو النقلات.
// Apply stacked discount codes during plan change
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately',
  discount_codes: ['UPGRADE20']
});

سلوك الخصم عند تغيير الخطة

قيمة discount_codesالسلوك
غير متوفر / nullيتم تلقائيًا الحفاظ على الخصومات الحالية مع preserve_on_plan_change=true إذا كانت تنطبق على المنتج الجديد.
[] (مصفوفة فارغة)جميع الخصومات الحالية يتم إزالتها من الاشتراك.
["CODE_A", "CODE_B", ...]يحل محل أي خصومات موجودة بهذه المجموعة المكدسة، التي يتم التحقق منها وتطبيقها بترتيب المصفوفة.
الحقل الفريد discount_code في هذه النقطة النهاية مهمل ولكن لا يزال يعمل للتوافق مع النسخ القديمة — لا تحتاج التكاملات الحالية لتغييرها على الفور. لا يمكن دمجه مع discount_codes في نفس الطلب. انتقل إلى النموذج المصفوفة عندما يكون ذلك مناسبًا.
استخدم واجهة معاينة تغيير الخطة مع discount_codes لعرض العملاء كم سيوفرون قبل تأكيد تغيير الخطة.

أوضاع القسمة

اختر كيفية فرض الفواتير على العميل عند تغيير الخطط:

prorated_immediately

  • رسوم الفرق الجزئي في الدورة الحالية
  • إذا كان في فترة تجريبية، فإنه يفرض الرسوم فورًا وينتقل إلى الخطة الجديدة الآن
  • خفض: قد ينشئ رصيدًا مقسطًا يتم تطبيقه على التجديدات المستقبلية

full_immediately

  • يفرض المبلغ الكامل للخطة الجديدة فورًا
  • يتجاهل الوقت المتبقي من الخطة القديمة
الائتمانات التي تم إنشاؤها عن طريق التخفيضات باستخدام difference_immediately مرتبطة بالاشتراك ومختلفة عن استحقاقات الفوترة المستندة إلى الائتمان. يتم تطبيقها تلقائيًا على التجديدات المستقبلية لذات الاشتراك ولا يمكن نقلها بين الاشتراكات.

difference_immediately

  • ترقية: يفرض فورًا فرق السعر بين الخطط القديمة والجديدة
  • خفض: يضيف القيمة المتبقية كائتمان داخلي للاشتراك ويتم تطبيقه تلقائيًا عند التجديدات

do_not_bill

  • لا يتم حساب رسوم أو ائتمانات
  • ينتقل العميل إلى الخطة الجديدة فورًا بدون أي تعديل في الفواتير
  • تبقى دورة الفواتير دون تغيير
  • الأفضل للمراحلة الطوعية، تحويلات الخطة الحرة، أو استيعاب فروقات التكلفة
الميزةprorated_immediatelydifference_immediatelyfull_immediatelydo_not_bill
رسوم الترقيةالفرق المقسط للأيام المتبقيةفرق السعر الكامل بين الخططسعر الخطة الجديدة بالكاملبدون رسوم
رصيد التخفيضرصيد مقسط للأيام المتبقيةفرق السعر الكامل كائتمانلا يوجد رصيدلا يوجد رصيد
دورة الفواتيربدون تغييربدون تغييريعاد تعيينها إلى اليومبدون تغيير
سلوك الفترة التجريبيةتنتهي الفترة التجريبية، تفرض فورًاتنتهي الفترة التجريبية، تفرض فورًاتنتهي الفترة التجريبية، تفرض المبلغ الكاملتنتهي الفترة التجريبية، بدون رسوم
الأفضل لالفوترة العادلة المستندة إلى الوقتالرياضيات البسيطة للترقية/التخفيضإعادة تعيين دورات الفواتيرالتحويلات الطوعية أو التحولات المجانية
التعقيدمتوسط (حساب الأيام)منخفض (طرح بسيط)منخفض (رسوم كاملة)لا يوجد

سيناريوهات نموذجية

استخدم هذه الأرقام الكنسية باستمرار:
  • الخطة الحالية: أساسي بسعر 30$/شهر
  • هدف الترقية: محترف بسعر 80$/شهر
  • هدف التخفيض (من محترف): مبتدئ بسعر 20$/شهر
  • دورة الفوترة: 30 يومًا، بدأت في 1 يناير
  • يحدث تغيير الخطة في 16 يناير (تبقى 15 يومًا، استخدمت 15 يومًا)
Step 1: Calculate unused credit from current plan
  Unused days = 15 out of 30 days
  Credit = $30 × (15/30) = $15.00

Step 2: Calculate prorated cost of new plan
  Remaining days = 15 out of 30 days
  New plan cost = $80 × (15/30) = $40.00

Step 3: Calculate immediate charge
  Charge = New plan cost − Credit
  Charge = $40.00 − $15.00 = $25.00

→ Customer pays $25.00 now
→ Next renewal (Feb 1): $80.00/month
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
})
Step 1: Calculate unused credit from current plan
  Unused days = 15 out of 30 days
  Credit = $80 × (15/30) = $40.00

Step 2: Calculate prorated cost of new plan
  Remaining days = 15 out of 30 days
  New plan cost = $20 × (15/30) = $10.00

Step 3: Calculate credit balance
  Credit = $40.00 − $10.00 = $30.00

→ No charge — $30.00 credit added to subscription
→ Credit auto-applies to future renewals
→ Next renewal (Feb 1): $20.00 − $30.00 credit = $0.00
→ Following renewal (Mar 1): $20.00 − $10.00 remaining credit = $10.00
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_starter',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
})
Immediate charge = New plan price − Old plan price
                 = $80 − $30
                 = $50.00

→ Customer pays $50.00 now (regardless of cycle position)
→ Next renewal (Feb 1): $80.00/month
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
Credit = Old plan price − New plan price
       = $80 − $20
       = $60.00

→ No charge — $60.00 credit added to subscription
→ Credit auto-applies to future renewals
→ Next renewal: $20.00 − $20.00 (from credit) = $0.00
→ Following renewal: $20.00 − $20.00 (from credit) = $0.00
→ Third renewal: $20.00 − $20.00 (from remaining credit) = $0.00
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_starter',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
Immediate charge = Full new plan price = $80.00

→ Customer pays $80.00 now
→ No credit for unused time on old plan
→ Billing cycle resets to today (January 16)
→ Next renewal: February 16 at $80.00/month
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'full_immediately'
})
Current: Basic plan ($30/month), no add-ons
New: Pro plan ($80/month) + Extra Seats add-on ($10/seat × 3 seats = $30/month)
Change on day 16 of 30 (15 days remaining)

Step 1: Credit from current plan
  Credit = $30 × (15/30) = $15.00

Step 2: Prorated cost of new plan + add-ons
  New plan = $80 × (15/30) = $40.00
  Add-ons = $30 × (15/30) = $15.00
  Total new = $55.00

Step 3: Immediate charge
  Charge = $55.00 − $15.00 = $40.00

→ Customer pays $40.00 now
→ Next renewal: $80.00 + $30.00 = $110.00/month
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately',
  addons: [
    { addon_id: 'addon_seats', quantity: 3 }
  ]
})

كيف يعالج كل وضع الفواتير

اختر prorated_immediately للمحاسبة العادلة على الوقت؛ اختر full_immediately لإعادة تشغيل الفواتير؛ استخدم difference_immediately للترقيات البسيطة والائتمان التلقائي عند التخفيضات؛ أو استخدم do_not_bill لتغيير الخطط بدون أي تعديل في الفواتير.

التعامل مع فشل الدفع

تحكم فيما يحدث عند فشل دفع تغيير الخطة باستخدام معلمة on_payment_failure.

أوضاع فشل الدفع

إذا لم يحدد، تستخدم معلمة on_payment_failure إعداد المستوى الخاص بالأعمال الذي تم تكوينه في لوحة التحكم.

متى يجب استخدام كل وضع

السيناريوالوضع الموصى بهالسبب
الترقية إلى ميزات متميزةprevent_changeضمان الدفع قبل منح الوصول
زيادة الكمية (مقاعد أكثر)prevent_changeمنع الاستخدام بدون دفع
تخفيض الخططapply_changeالعميل يقلل النفقات
العملاء الموثوق بهم في الشركاتapply_changeخطر عدم الدفع منخفض
التحويل من التجربة إلى الدفعprevent_changeلحظة دفع حرجة

التعامل مع الويب هوك

تتبع حالة الاشتراك من خلال الويب هوك لتأكيد التغييرات في الخطة والمدفوعات.

أنواع الأحداث للتعامل معها

  • subscription.active: الاشتراك مفعل
  • subscription.plan_changed: تم تغيير خطة الاشتراك (تحديث الترقية/التخفيض/الإضافات)
  • subscription.on_hold: فشل الشحن، تم تعليق الاشتراك
  • subscription.renewed: نجاح التجديد
  • payment.succeeded: نجاح الدفع لتغيير الخطة أو التجديد
  • payment.failed: فشل الدفع
نوصي بقيادة منطق الأعمال من أحداث الاشتراك واستخدام أحداث الدفع للتأكيد والمصالحة.

تحقق من التوقيعات وتعامل مع النيات

import { NextRequest, NextResponse } from 'next/server';

export async function POST(req) {
  const webhookId = req.headers.get('webhook-id');
  const webhookSignature = req.headers.get('webhook-signature');
  const webhookTimestamp = req.headers.get('webhook-timestamp');
  const secret = process.env.DODO_WEBHOOK_SECRET;

  const payload = await req.text();
  // verifySignature is a placeholder – in production, use a Standard Webhooks library
  const { valid, event } = await verifySignature(
    payload,
    { id: webhookId, signature: webhookSignature, timestamp: webhookTimestamp },
    secret
  );
  if (!valid) return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });

  switch (event.type) {
    case 'subscription.active':
      // mark subscription active in your DB
      break;
    case 'subscription.plan_changed':
      // refresh entitlements and reflect the new plan in your UI
      break;
    case 'subscription.on_hold':
      // notify user to update payment method
      break;
    case 'subscription.renewed':
      // extend access window
      break;
    case 'payment.succeeded':
      // reconcile payment for plan change
      break;
    case 'payment.failed':
      // log and alert
      break;
    default:
      // ignore unknown events
      break;
  }

  return NextResponse.json({ received: true });
}
لرؤية مخططات الحمولة المفصلة، انظر إلى حمولات الويب هوك الخاصة بالاشتراك وحمولات الويب هوك للدفع.

أفضل الممارسات

اتبع هذه التوصيات لتغييرات موثوقة في خطة الاشتراك:

استراتيجية تغيير الخطة

  • اختبر بدقة: اختبر دائمًا تغييرات الخطة في وضع الاختبار قبل الإنتاج
  • اختر القسمة بعناية: اختر وضع القسمة الذي يتماشى مع نموذج عملك
  • تعامل مع الفشل برفق: طبق معالجة أخطاء مناسبة ومنطق إعادة المحاولة
  • راقب معدلات النجاح: تتبع معدلات نجاح/فشل تغيير الخطة وقم بالتحقيق في المشكلات

تنفيذ الويب هوك

  • تحقق من التوقيعات: تحقق دائمًا من توقيعات الويب هوك لضمان الأصالة
  • طبق معالجة التكرار: تعامل مع أحداث الويب هوك المكررة برفق
  • عالج بشكل غير متزامن: لا تحظر ردود الويب هوك بعمليات ثقيلة
  • سجل كل شيء: احتفظ بسجلات مفصلة لأغراض التصحيح والتدقيق

تجربة المستخدم

  • تواصل بوضوح: أبلغ العملاء عن تغييرات الفوترة والتوقيت
  • قدم تأكيدات: أرسل تأكيدات بالبريد الإلكتروني لتغييرات الخطة الناجحة
  • تعامل مع الحالات الحرجة: فكر في فترات التجربة، القسمة، وفشل المدفوعات
  • قم بتحديث الواجهة تلقائيًا: عكس تغييرات الخطة في واجهة التطبيق الخاصة بك

المشكلات الشائعة والحلول

حل المشاكل الشائعة عند تغيير خطط الاشتراك:
الأعراض: يتم استدعاء API بنجاح لكن الاشتراك يبقى على الخطة القديمةالأسباب الشائعة:
  • فشل أو تأخر معالجة الويب هوك
  • لم يتم تحديث حالة التطبيق بعد استلام الويب هوك
  • مشكلات في معاملات قاعدة البيانات أثناء تحديث الحالة
الحلول:
  • ضع معالجة ويب هوك قوية مع منطق إعادة المحاولة
  • استخدم عمليات بدون آثار جانبية لتحديث الحالة
  • قم بإضافة مراقبة للكشف عن تنبيهات بشأن أحداث الويب هوك الفائتة
  • تأكد من أن نقطة نهاية الويب هوك متاحة وتستجيب بشكل صحيح
الأعراض: يقوم العميل بتخفيض الخطة لكنه لا يرى رصيد الحوافزالأسباب الشائعة:
  • توقّعات وضع القسمة: تخفيضات الائتمان للفرق في السعر الكامل للخطة مع difference_immediately، في حين أن prorated_immediately تنشئ رصيدًا مقسطًا على أساس الوقت المتبقي في الدورة
  • الائتمانات خاصة بالاشتراك ولا تنتقل بين الاشتراكات
  • رصيد الحوافز غير مرئي في لوحة تحكم العميل
الحلول:
  • استخدم difference_immediately للتخفيضات عندما ترغب في حوافز تلقائية
  • وضح للعملاء أن الأرصدة تنطبق على تجديدات نفس الاشتراك
  • قم بتطبيق بوابة العملاء لعرض أرصدة الحوافز
  • تحقق من معاينة الفاتورة التالية لرؤية الأرصدة المطبقة
الأعراض: تم رفض أحداث الويب هوك بسبب توقيع غير صالحالأسباب الشائعة:
  • مفتاح الويب هوك السري غير صحيح
  • تم تعديل جسم الطلب الخام قبل التحقق من التوقيع
  • خوارزمية التحقق من التوقيع خاطئة
الحلول:
  • تحقق من أنك تستخدم DODO_WEBHOOK_SECRET الصحيح من لوحة التحكم
  • اقرأ جسم الطلب الخام قبل أي وسيطة تحليل JSON
  • استخدم مكتبة التحقق القياسية من الويب هوك لنظامك الأساسي
  • اختبر التحقق من توقيع الويب هوك في بيئة التطوير
الأعراض: ترتد API خطأ 422 Unprocessable Entityالأسباب الشائعة:
  • معرف اشتراك غير صالح أو معرف منتج غير صحيح
  • الاشتراك ليس في حالة نشطة
  • المعلمات المطلوبة مفقودة
  • المنتج غير متاح لتغييرات الخطة
الحلول:
  • تحقق من وجود الاشتراك وأنه نشط
  • تأكد من أن معرف المنتج صالحة ومتاحة
  • تأكد من توفير جميع المعلمات المطلوبة
  • راجع مستندات API لمتطلبات المعلمات
الأعراض: تم بدء تغيير الخطة لكن فشل الشحن الفوريالأسباب الشائعة:
  • أموال غير كافية على طريقة دفع العميل
  • انتهت صلاحية طريقة الدفع أو غير صالحة
  • البنك رفض المعاملة
  • اكتشاف الاحتيال حظر الشحنة
الحلول:
  • تعامل مع أحداث payment.failed بشكل مناسب
  • أبلغ العميل لتحديث طريقة الدفع
  • نفذ منطق إعادة المحاولة للفشل المؤقت
  • فكر في السماح بتغييرات الخطة مع فشل الشحنات الفورية
الأعراض: فشل شحن تغيير الخطة وتحرك الاشتراك إلى حالة on_holdما يحدث: عندما يفشل شحن تغيير الخطة، يتم تلقائيًا وضع الاشتراك في حالة on_hold. لن يتم تجديد الاشتراك تلقائيًا حتى يتم تحديث طريقة الدفع.الحل: قم بتحديث طريقة الدفع لإعادة تفعيل الاشتراكلإعادة تفعيل الاشتراك من حالة on_hold بعد فشل تغيير الخطة:
  1. قم بتحديث طريقة الدفع باستخدام API لتحديث طريقة الدفع
  2. إنشاء شحنة تلقائية: API ينشئ شحنة للديون المتبقية تلقائيًا
  3. إنشاء فاتورة: يتم إنشاء فاتورة للشحنة
  4. معالجة الدفع: يتم معالجة الدفع باستخدام طريقة الدفع الجديدة
  5. إعادة التفعيل: عند نجاح الدفع، يتم إعادة تفعيل الاشتراك إلى حالة active
// Reactivate subscription from on_hold after failed plan change
async function reactivateAfterFailedPlanChange(subscriptionId) {
  // Update payment method - automatically creates charge for remaining dues
  const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
    type: 'new',
    return_url: 'https://example.com/return'
  });
  
  if (response.payment_id) {
    console.log('Charge created for remaining dues:', response.payment_id);
    console.log('Payment link:', response.payment_link);
    
    // Redirect customer to payment_link to complete payment
    // Monitor webhooks for:
    // 1. payment.succeeded - charge succeeded
    // 2. subscription.active - subscription reactivated
  }
  
  return response;
}

// Or use existing payment method if available
async function reactivateWithExistingPaymentMethod(subscriptionId, paymentMethodId) {
  const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
    type: 'existing',
    payment_method_id: paymentMethodId
  });
  
  // Monitor webhooks for payment.succeeded and subscription.active
  return response;
}
أحداث الويب هوك لمراقبتها:
  • subscription.on_hold: تم تعليق الاشتراك (يتم استلامه عند فشل الشحنة لتغيير الخطة)
  • payment.succeeded: نجاح الدفع للديون المتبقية (بعد تحديث طريقة الدفع)
  • subscription.active: إعادة تفعيل الاشتراك بعد نجاح الدفع
أفضل الممارسات:
  • أبلغ العملاء فورًا عندما تفشل الشحنة لتغيير الخطة
  • قدم تعليمات واضحة حول كيفية تحديث طريقة الدفع الخاصة بهم
  • راقب أحداث الويب هوك لتتبع حالة إعادة التفعيل
  • فكر في تنفيذ منطق إعادة المحاولة التلقائية لفشل الدفعات المؤقتة

Update Payment Method API Reference

اطلع على وثائق API الكاملة لتحديث طرق الدفع وإعادة تفعيل الاشتراكات.

اختبار تنفيذك

اتبع هذه الخطوات لاختبار تنفيذ تغيير اشتراكك بدقة:
1

Set up test environment

  • استخدم مفاتيح API تجريبية ومنتجات تجريبية
  • أنشئ اشتراكات تجريبية بأنواع خطط مختلفة
  • إعداد نقطة نهاية ويب هوك تجريبية
  • قم بتكوين المراقبة والتسجيل
2

Test different proration modes

  • اختبر prorated_immediately مع مواقع مختلفة في دورة الفواتير
  • اختبر difference_immediately للترقيات والتخفيضات
  • اختبر full_immediately لإعادة تعيين دورات الفواتير
  • اختبر do_not_bill لتحويلات الخطط بدون رسوم/بدون حوافز
  • تحقق من صحة حسابات الحوافز
3

Test webhook handling

  • تحقق من استلام جميع أحداث الويب هوك ذات الصلة
  • اختبار التحقق من توقيع الويب هوك
  • تعامل مع أحداث الويب هوك المكررة برفق
  • اختبر سيناريوهات فشل معالجة الويب هوك
4

Test error scenarios

  • اختبر باستخدام معرفات اشتراك غير صالحة
  • اختبر باستخدام طرق دفع منتهية الصلاحية
  • اختبر فشل الشبكة وانقطاع الوقت
  • اختبر عند عدم كفاية الأموال
5

Monitor in production

  • قم بتكوين التنبيهات للتغييرات الفاشلة للخطة
  • راقب أوقات معالجة الويب هوك
  • تتبع معدلات نجاح تغيير الخطة
  • مراجعة تذاكر دعم العملاء للمشكلات المتعلقة بتغيير الخطة

معالجة الأخطاء

تعامل مع الأخطاء الشائعة في API برفق في تنفيذك:

رموز حالة HTTP

تمت معالجة طلب تغيير الخطة بنجاح. يتم تحديث الاشتراك وبدأت معالجة الدفع.
معلمات الطلب غير صحيحة. تحقق من أن جميع الحقول المطلوبة متوفرة وصيغةها صحيحة.
مفتاح API غير صالح أو مفقود. تحقق من أن DODO_PAYMENTS_API_KEY صحيح ويملك الأذونات المناسبة.
لم يتم العثور على معرف الاشتراك أو لا يخص حسابك.
لا يمكن تغيير الاشتراك (مثل: تم إلغاؤه بالفعل، المنتج غير متاح، إلخ).
حدث خطأ في الخادم. أعد محاولة الطلب بعد تأخير قصير.

تنسيق استجابة الخطأ

{
  "error": {
    "code": "subscription_not_found",
    "message": "The subscription with ID 'sub_123' was not found",
    "details": {
      "subscription_id": "sub_123"
    }
  }
}

الخطوات التالية

Last modified on May 22, 2026