מנויים עם תשלומים חוזרים הופכים את ההכנסה לצפויה. אבל עד 30% מהעסקאות החוזרות נכשלות: כרטיסים שפגו תוקף, חוסר בכספים, חסימות בנק. ללא טיפול אוטומטי בכשלים, אתה מאבד עד 15% מההכנסות ממנויים. עבור מחזור חודשי, זהו הפסד ממשי. שילוב תשלומים חוזרים עם טוקניזציה ואסטרטגיית dunning משחזר עד 80% מהחיובים שנכשלו. יישמנו מערכות כאלה עבור Stripe ו-CloudPayments בפרויקטים עם אלפי מנויים. ניסיון: 10+ שנים בעיבוד תשלומים ויותר מ-50 פרויקטי מנויים. קבל ייעוץ על אינטגרציה היום.
כיצד ליישם אינטגרציית תשלומים חוזרים באמצעות טוקניזציה?
טוקניזציה פירושה אחסון נתוני תשלום כטוקן בשער התשלומים. התשלום הראשון דורש מעורבות משתמש; התשלומים הבאים מתבצעים יזומים מהשרת. Stripe משתמש ב-SetupIntent לאיסוף מאובטח של פרטי כרטיס, ולאחר מכן יוצר PaymentIntent עם off_session: true כדי לחייב ללא 3DS. זוהי הגישה הסטנדרטית בתיעוד של Stripe.
שרת — שמירת אמצעי התשלום
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$stripeCustomer = \Stripe\Customer::create([
'email' => $user->email,
'metadata' => ['user_id' => $user->id],
]);
$user->update(['stripe_customer_id' => $stripeCustomer->id]);
$setupIntent = \Stripe\SetupIntent::create([
'customer' => $user->stripe_customer_id,
'usage' => 'off_session',
'automatic_payment_methods' => ['enabled' => true],
]);
return response()->json(['clientSecret' => $setupIntent->client_secret]); שרת — חיובים עוקבים ללא מעורבות משתמש
public function chargeRecurring(User $user, int $amountCents): void
{
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$paymentMethod = $user->default_payment_method_id;
try {
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => $amountCents,
'currency' => 'usd',
'customer' => $user->stripe_customer_id,
'payment_method' => $paymentMethod,
'confirm' => true,
'off_session' => true,
'description' => "Subscription - {$user->id}",
]);
if ($paymentIntent->status === 'succeeded') {
$this->recordSuccessfulCharge($user, $paymentIntent);
}
} catch (\Stripe\Exception\CardException $e) {
$this->handleFailedCharge($user, $e->getError()->decline_code);
} catch (\Stripe\Exception\InvalidRequestException $e) {
if ($e->getStripeCode() === 'authentication_required') {
$this->sendAuthenticationEmail($user, $e->getError()->payment_intent->id);
}
}
} מדוע עד 30% מהתשלומים נכשלים?
הסיבות העיקריות: כרטיס שפג תוקף, חוסר בכספים, ניטור הונאות של הבנק, שגיאות טכניות. עם טיפול ידני, כל כשל הוא הכנסה אבודה. אסטרטגיית ניסיון חוזר אוטומטית (dunning) משחזרת את רוב התשלומים הללו. לדוגמה, בפרויקטי שירותי הענן שלנו, לאחר יישום dunning, שיעור הכשלים ירד מ-25% ל-8%.
טיפול בחיובים שנכשלו
כשלים הם נורמליים בתשלומים חוזרים. אנו מיישמים dunning עם השהיה אקספוננציאלית: ניסיון ראשון לאחר יום אחד, שני לאחר 3 ימים, שלישי לאחר 7 ימים. אם לאחר שלושה ניסיונות החיוב עדיין נכשל, סטטוס המנוי משתנה ל-\Stripe\Stripe::setApiKey(config('services.stripe.secret')); $stripeCustomer = \Stripe\Customer::create([ 'email' => $user->email, 'metadata' => ['user_id' => $user->id], ]); $user->update(['stripe_customer_id' => $stripeCustomer->id]); $setupIntent = \Stripe\SetupIntent::create([ 'customer' => $user->stripe_customer_id, 'usage' => 'off_session', 'automatic_payment_methods' => ['enabled' => true], ]); return response()->json(['clientSecret' => $setupIntent->client_secret]); , והלקוח מקבל אימייל לעדכון הכרטיס. בנוסף, מתחיל תהליך dunning — סדרה של 3-5 תזכורות. הנה דוגמה למחלקה:
class RecurringChargeJob implements ShouldQueue {
public int $tries = 3;
public function backoff(): array
{
return [86400, 259200, 604800];
}
public function handle(): void
{
$subscription = Subscription::find($this->subscriptionId);
if ($subscription->failed_attempts >= 3) {
$subscription->update(['status' => 'past_due']);
Mail::to($subscription->user)->send(new PaymentFailedMail($subscription));
return;
}
try {
app(RecurringPaymentService::class)->charge($subscription);
$subscription->update([
'failed_attempts' => 0,
'status' => 'active',
'next_charge_at' => now()->addMonth(),
]);
} catch (PaymentFailedException $e) {
$subscription->increment('failed_attempts');
throw $e;
}
}
} Stripe Billing — פתרון מוכן
אם אינך רוצה לנהל לוחות זמנים בעצמך, Stripe Billing עושה זאת עבורך. פשוט צור מוצר ומחיר, ולאחר מכן מנוי. Webhooks מטפלים בכל האירועים: תשלומים מוצלחים, כשלים, חידושים. Stripe Billing מיושם פי 2 מהר יותר מטוקניזציה מותאמת אישית ומפחית את העומס על השרת.
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$product = \Stripe\Product::create(['name' => 'Pro Plan']);
$price = \Stripe\Price::create([
'unit_amount' => 2900,
'currency' => 'usd',
'recurring' => ['interval' => 'month'],
'product' => $product->id,
]);
$subscription = \Stripe\Subscription::create([
'customer' => $user->stripe_customer_id,
'items' => [['price' => $price->id]],
'payment_behavior' => 'default_incomplete',
'expand' => ['latest_invoice.payment_intent'],
]);
מטפל ה-webhook צריך להאזין לאירועי public function chargeRecurring(User $user, int $amountCents): void { \Stripe\Stripe::setApiKey(config('services.stripe.secret')); $paymentMethod = $user->default_payment_method_id; try { $paymentIntent = \Stripe\PaymentIntent::create([ 'amount' => $amountCents, 'currency' => 'usd', 'customer' => $user->stripe_customer_id, 'payment_method' => $paymentMethod, 'confirm' => true, 'off_session' => true, 'description' => "Subscription - {$user->id}", ]); if ($paymentIntent->status === 'succeeded') { $this->recordSuccessfulCharge($user, $paymentIntent); } } catch (\Stripe\Exception\CardException $e) { $this->handleFailedCharge($user, $e->getError()->decline_code); } catch (\Stripe\Exception\InvalidRequestException $e) { if ($e->getStripeCode() === 'authentication_required') { $this->sendAuthenticationEmail($user, $e->getError()->payment_intent->id); } } } , past_due ו-class RecurringChargeJob implements ShouldQueue { public int $tries = 3; public function backoff(): array { return [86400, 259200, 604800]; } public function handle(): void { $subscription = Subscription::find($this->subscriptionId); if ($subscription->failed_attempts >= 3) { $subscription->update(['status' => 'past_due']); Mail::to($subscription->user)->send(new PaymentFailedMail($subscription)); return; } try { app(RecurringPaymentService::class)->charge($subscription); $subscription->update([ 'failed_attempts' => 0, 'status' => 'active', 'next_charge_at' => now()->addMonth(), ]); } catch (PaymentFailedException $e) { $subscription->increment('failed_attempts'); throw $e; } } } . כל אירוע מעדכן את סטטוס המנוי במסד הנתונים המקומי שלך. חשוב לטפל בהודעות כפולות באופן אידמפוטנטי — בדוק לפי Stripe Event ID. לבדיקות, השתמש ב-Stripe CLI עם \Stripe\Stripe::setApiKey(config('services.stripe.secret')); $product = \Stripe\Product::create(['name' => 'Pro Plan']); $price = \Stripe\Price::create([ 'unit_amount' => 2900, 'currency' => 'usd', 'recurring' => ['interval' => 'month'], 'product' => $product->id, ]); $subscription = \Stripe\Subscription::create([ 'customer' => $user->stripe_customer_id, 'items' => [['price' => $price->id]], 'payment_behavior' => 'default_incomplete', 'expand' => ['latest_invoice.payment_intent'], ]); .
באיזו גישה לבחור: טוקניזציה או Subscription API?
הבחירה בין טוקניזציה ל-Subscription API קובעת את רמת השליטה ומהירות הפיתוח. טוקניזציה נותנת שליטה מלאה על לוחות הזמנים והנתונים אך דורשת יותר קוד ובדיקות. Subscription API מפשטת את ניהול המנויים על ידי הסתמכות על שער התשלומים אך כובלת אותך אליו ומגבילה גמישות.
השוואה בין טוקניזציה ל-Subscription API
| קריטריון | טוקניזציה | Subscription API |
|---|---|---|
| שליטה | מלאה | חלקית |
| אמינות | נמוכה יותר (עומס גבוה יותר) | גבוהה יותר (שער התשלומים מנהל) |
| תלות בשער התשלומים | חלשה (ניתן להעביר) | חזקה |
| מורכבות יישום | בינונית | נמוכה |
| זמן פיתוח | 3-6 שבועות | 1-3 שבועות |
קבל ייעוץ על בחירת הגישה הנכונה לעסק שלך.
מה כלול בעבודה
- תיעוד: מפרט API של האינטגרציה, תיאור אירועי webhook, סכמת מסד נתונים למנויים.
- גישה: הגדרת סביבות (dev/staging/prod), יצירת חשבונות שער תשלומים, הגדרת סודות webhook.
- הדרכה: העברת ידע לצוות שלך, הדגמת פאנל הניהול לניהול מנויים.
- תמיכה: חודש אחריות לאחר המסירה, תיקוני באגים באמצעות hotfix.
תהליך
- ניתוח — אנו לומדים את הלוגיקה העסקית שלך, תדירות החיובים ודרישות ה-dunning.
- עיצוב — אנו בוחרים את המחסנית (Stripe, CloudPayments), מודל טוקניזציה או Subscription API.
- יישום — שילוב שער התשלומים, יצירת טבלאות מנויים, מטפלי webhook, משימות.
- בדיקות — אימות תשלומים, כשלים, תקופות חסד, ניסיונות חוזרים.
- פריסה וניטור — הגדרת התראות, רישום שגיאות, עדכון תיעוד.
צור קשר כדי לדון בפרטי הפרויקט שלך.
לוחות זמנים ועלות
| אפשרות | זמן פיתוח |
|---|---|
| טוקניזציה | 3–6 שבועות |
| Stripe Billing | 1–3 שבועות |
אינטגרציה בסיסית עם שער תשלומים אחד אורכת בין 3 ל-6 שבועות. אם אתה צריך מחזורי חיוב מורכבים, מספר שערי תשלומים או אסטרטגיות ניסיון חוזר לא סטנדרטיות, לוח הזמנים גדל ל-8–10 שבועות. העלות מחושבת באופן אישי.
הזמן אינטגרציית תשלומים חוזרים סוהר — אנו מבטיחים אמינות ושקיפות בכל שלב.







