שילוב שער תשלום Stripe באפליקציות מובייל
הטמעתם שדה קלט לכרטיס, אבל משתמשים מתלוננים על כשלי 3DS? או שחיובים מנויים לא מתבצעים אוטומטית? Stripe הוא שער התשלום הבוגר ביותר טכנית מבחינת SDK למובייל. הוא מכסה לא רק קלט כרטיס בסיסי אלא גם Apple Pay, Google Pay, 3DS2, Link, ושמירת אמצעי תשלום דרך SetupIntent. בחירת הזרימה הנכונה תלויה במשימה: תשלום חד-פעמי, מנוי, שמירת כרטיס ללא חיוב מיידי — אלו API שונים. הניסיון שלנו מראה שרוב הבעיות נובעות מבחירת זרימה שגויה או מחוסר זהירות בצד השרת.
Stripe SDK מטפל ב-3DS2 באופן מובנה, מה שמאושר על ידי התיעוד של Stripe. הגדרה נכונה מפחיתה את שיעור הסירובים ב-10–15%.
איך Stripe מטפל ב-3DS2
Stripe SDK מעבד 3DS2 אוטומטית בתוך confirmPayment / PaymentSheet.present. כשהבנק דורש אימות, ה-SDK פותח אתגר 3DS2 מקורי (ביומטריה או OTP) ישירות בתוך האפליקציה — ללא הפניית דפדפן. זה חשוב: הפניית 3DS1 דרך WebView לעיתים קרובות מאבדת קריאות חוזרות, והעסקה נתקעת. אם הספק שלך מחזיר requires_action בסטטוס PaymentIntent, זה נורמלי; Stripe SDK מטפל באתגר בעצמו. דרך ניסיון זה מושגת פעולה יציבה של 3DS2.
למה לבחור ב-PaymentSheet על פני ממשק מותאם אישית
PaymentSheet מאיץ את הפיתוח פי 2 בהשוואה לממשק מותאם אישית. הוא כולל תמיכה מובנית ב-Apple Pay ו-Google Pay, מטפל אוטומטית ב-3DS2 ובלוקליזציה. הזרימה המותאמת אישית דרך STPPaymentHandler נותנת שליטה מלאה אך דורשת יותר קוד ובדיקות. אם אין לך צורך באלמנטים ייחודיים של ממשק — לך עם PaymentSheet.
מדריך שלב-אחר-שלב לשילוב Stripe
- הגדר נקודת קצה בשרת ליצירת PaymentIntent ו-SetupIntent.
- קבל מפתח publishable מלוח הבקרה של Stripe.
- באפליקציית המובייל, אתחל את Stripe SDK עם המפתח publishable.
- צור הגדרת PaymentSheet עם customer, ephemeralKey, ו-applePay/googlePay.
- קרא ל-
presentWithPaymentIntentוטפל בתוצאה. - הגדר webhooks לקבלת סטטוס תשלום סופי.
- בדוק עם כרטיסי בדיקה של Stripe.
איך לבחור בין PaymentIntent ל-SetupIntent
PaymentIntent — לחיוב מיידי. נוצר בשרת, מועבר ללקוח דרך client_secret, והלקוח מאשר אותו. SetupIntent — לשמירת כרטיס ללא חיוב (לדוגמה, במהלך הרשמה, לחיוב מאוחר יותר דרך API). זרימה דומה, אך ללא סכום. הטעות העיקרית היא יצירת PaymentIntent בצד הלקוח. secret_key אסור שייכנס לאפליקציה. רק publishable_key הוא בצד הלקוח. כך, המפתח הסודי לעולם לא מגיע לאפליקציית הלקוח.
iOS: PaymentSheet וזרימה מותאמת אישית
PaymentSheet (מומלץ להתחלה)
import StripePaymentSheet
var paymentSheet: PaymentSheet?
func preparePaymentSheet(clientSecret: String, customerId: String, ephemeralKeySecret: String) {
var config = PaymentSheet.Configuration()
config.merchantDisplayName = "Your Company"
config.customer = .init(id: customerId, ephemeralKeySecret: ephemeralKeySecret)
config.applePay = .init(
merchantId: "merchant.com.yourcompany.app",
merchantCountryCode: "US"
)
config.defaultBillingDetails.address.country = "RU"
config.allowsDelayedPaymentMethods = true
paymentSheet = PaymentSheet(
paymentIntentClientSecret: clientSecret,
configuration: config
)
}
@IBAction func checkoutTapped(_ sender: UIButton) {
paymentSheet?.present(from: self) { [weak self] result in
switch result {
case .completed:
self?.handleSuccess()
case .failed(let error):
print("Payment failed: \(error.localizedDescription)")
case .canceled:
break
}
}
} זרימה מותאמת אישית עם CardField
let cardField = STPPaymentCardTextField() // Подтверждение платежа
STPPaymentHandler.shared().confirmPayment(
paymentParams,
with: self
) { [weak self] status, paymentIntent, error in
switch status {
case .succeeded:
self?.handleSuccess()
case .failed:
print("Error: \(error?.localizedDescription ?? "")")
case .canceled:
break
@unknown default:
break
}
} Android: PaymentSheet ו-CardInputWidget
import com.stripe.android.paymentsheet.PaymentSheet
import com.stripe.android.paymentsheet.PaymentSheetResult
private lateinit var paymentSheet: PaymentSheet
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
paymentSheet = PaymentSheet(this) { result ->
when (result) {
is PaymentSheetResult.Completed -> handleSuccess()
is PaymentSheetResult.Failed -> {
Log.e("Stripe", result.error.message ?: "Unknown error")
}
is PaymentSheetResult.Canceled -> {}
}
}
}
fun launchPaymentSheet(clientSecret: String, customerId: String, ephemeralKey: String) {
val config = PaymentSheet.Configuration(
merchantDisplayName = "Your Company",
customer = PaymentSheet.CustomerConfiguration(customerId, ephemeralKey),
googlePay = PaymentSheet.GooglePayConfiguration(
environment = PaymentSheet.GooglePayConfiguration.Environment.Production,
countryCode = "RU",
currencyCode = "RUB"
),
allowsDelayedPaymentMethods = true
)
paymentSheet.presentWithPaymentIntent(clientSecret, config)
} שגיאות נפוצות ופתרונות
| בעיה | סיבה | פתרון |
|---|---|---|
import StripePaymentSheet var paymentSheet: PaymentSheet? func preparePaymentSheet(clientSecret: String, customerId: String, ephemeralKeySecret: String) { var config = PaymentSheet.Configuration() config.merchantDisplayName = "Your Company" config.customer = .init(id: customerId, ephemeralKeySecret: ephemeralKeySecret) config.applePay = .init( merchantId: "merchant.com.yourcompany.app", merchantCountryCode: "US" ) config.defaultBillingDetails.address.country = "RU" config.allowsDelayedPaymentMethods = true paymentSheet = PaymentSheet( paymentIntentClientSecret: clientSecret, configuration: config ) } @IBAction func checkoutTapped(_ sender: UIButton) { paymentSheet?.present(from: self) { [weak self] result in switch result { case .completed: self?.handleSuccess() case .failed(let error): print("Payment failed: \(error.localizedDescription)") case .canceled: break } } } | הלקוח משתמש ב-let cardField = STPPaymentCardTextField() // Подтверждение платежа STPPaymentHandler.shared().confirmPayment( paymentParams, with: self ) { [weak self] status, paymentIntent, error in switch status { case .succeeded: self?.handleSuccess() case .failed: print("Error: \(error?.localizedDescription ?? "")") case .canceled: break @unknown default: break } } מסביבה אחרת | ודא שהמפתח publishable וה-client_secret הם מאותה סביבה |
| PaymentSheet לא נפתח באנדרואיד, ללא שגיאה | PaymentSheet דורש FragmentActivity | שנה את מחלקת ה-Activity הבסיסית ל-FragmentActivity |
| מפתח ephemeral פג תוקף | מפתחות Ephemeral של Stripe חיים שעה אחת | רענן את המפתח לפני פתיחת ה-sheet |
| אתגר 3DS לא מופיע | הגדרת PaymentIntent שגויה | ודא ש-import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheetResult private lateinit var paymentSheet: PaymentSheet override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) paymentSheet = PaymentSheet(this) { result -> when (result) { is PaymentSheetResult.Completed -> handleSuccess() is PaymentSheetResult.Failed -> { Log.e("Stripe", result.error.message ?: "Unknown error") } is PaymentSheetResult.Canceled -> {} } } } fun launchPaymentSheet(clientSecret: String, customerId: String, ephemeralKey: String) { val config = PaymentSheet.Configuration( merchantDisplayName = "Your Company", customer = PaymentSheet.CustomerConfiguration(customerId, ephemeralKey), googlePay = PaymentSheet.GooglePayConfiguration( environment = PaymentSheet.GooglePayConfiguration.Environment.Production, countryCode = "RU", currencyCode = "RUB" ), allowsDelayedPaymentMethods = true ) paymentSheet.presentWithPaymentIntent(clientSecret, config) } ו-No such PaymentIntent או client_secret |
צד השרת (backend מינימלי)
# FastAPI / Django / Laravel — логика одинакова
stripe.api_key = settings.STRIPE_SECRET_KEY
@app.post("/create-payment-intent")
async def create_payment_intent(amount: int, currency: str = "rub"):
intent = stripe.PaymentIntent.create(
amount=amount, # в копейках
currency=currency,
automatic_payment_methods={"enabled": True},
)
return {"clientSecret": intent.client_secret} מה כלול בעבודה
- הטמעת PaymentSheet או זרימת כרטיס מותאמת אישית ב-iOS וב-Android
- נקודת קצה בשרת ליצירת PaymentIntent / SetupIntent
- שילוב Apple Pay ו-Google Pay דרך Stripe
- הגדרת Webhook לאישור סטטוס תשלום סופי
- בדיקות עם כרטיסי בדיקה של Stripe
לוחות זמנים משוערים
טווח: 3–5 ימים לשילוב מלא עם Apple Pay, Google Pay ו-3DS2. זרימת כרטיס בסיסית בלבד — 1–2 ימים. חיסכון ממוצע בעלויות תפעול עם שילוב נכון הוא 15–20%. העלות המדויקת נקבעת לאחר ניתוח הפרויקט שלך.
| שלב | משך |
|---|---|
| ניתוח ועיצוב | 0.5 יום |
| פיתוח נקודת קצה בשרת | 0.5–1 יום |
| שילוב SDK ב-iOS | 1–2 ימים |
| שילוב SDK ב-Android | 1–2 ימים |
| שילוב Apple Pay / Google Pay | +1 יום |
| בדיקות וניפוי שגיאות | 0.5–1 יום |
המהנדסים שלנו מחזיקים בהסמכות Stripe (Stripe Certified Developer) ויש להם שנים של ניסיון בתשלומים במובייל. צור קשר להערכה אישית של הפרויקט שלך. קבל ייעוץ על שילוב Stripe.







