1C-Bitrix Integration with Stripe Payment System
Stripe is a payment platform with REST API covering the entire cycle: card authorization, fund capture, refunds, subscriptions, 3D Secure. Documentation is comprehensive, SDK for PHP is official. For online stores on Bitrix, this is one of the most predictable payment gateways to integrate.
Stripe works with Visa, Mastercard, AmEx cards, Apple Pay, Google Pay and a number of local methods (SEPA, iDEAL, Klarna and others). Availability depends on the merchant account registration country.
Two Integration Approaches
Stripe Checkout (hosted page). The customer is redirected to a Stripe page or it opens in a modal window. Stripe handles all PCI DSS and 3D Secure issues. Minimal code on Bitrix side — just create a Checkout Session via API and provide the redirect URL.
Stripe Elements / Payment Intents. The payment form is embedded directly on the checkout page. Card data never touches the merchant's server — it is entered in an iframe on Stripe. Requires JavaScript on the front end and server logic to create a PaymentIntent. Design is fully customizable.
For most Bitrix stores, Checkout is recommended: less code, fewer failure points, Stripe updates 3DS logic automatically.
Module Architecture in Bitrix
The payment system handler is a class inherited from \Bitrix\Sale\PaySystem\ServiceHandler. Additionally, we implement \Bitrix\Sale\PaySystem\IRefund for refunds.
Key methods:
-
initiatePay()— creates aCheckout Sessionviastripe-phpSDK, recordssession_idinb_sale_payment.PS_INVOICE_ID, returns the redirect URL. -
processRequest()— handles webhookcheckout.session.completedorpayment_intent.succeeded. Verifies signature via\Stripe\Webhook::constructEvent()withSTRIPE_WEBHOOK_SECRET. -
refund()— creates a\Stripe\Refundobject frompayment_intentinPS_INVOICE_ID.
Creating Checkout Session
\Stripe\Stripe::setApiKey($secretKey);
$session = \Stripe\Checkout\Session::create([
'payment_method_types' => ['card'],
'line_items' => [[
'price_data' => [
'currency' => 'eur',
'unit_amount' => $amountInCents, // amount in cents
'product_data' => ['name' => 'Order №' . $orderId],
],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => $successUrl . '?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => $cancelUrl,
'metadata' => ['bitrix_order_id' => $orderId],
]);
{CHECKOUT_SESSION_ID} is a special Stripe placeholder, it substitutes the real ID on its side. We verify against it in processRequest() to ensure the session belongs to our order.
Handling Webhooks
Webhooks are more important than success_url — the customer can close the tab before the redirect. Stripe sends a checkout.session.completed event to our endpoint regardless of browser behavior.
In Bitrix, the webhook is handled in processRequest(). Required checks:
- Signature verification via the
Stripe-Signatureheader — without it, anyone can imitate a payment. - Idempotency — the event can arrive twice. Before changing the order status, we check the current status in
b_sale_order. - Response
200 OKwithin 3 seconds — otherwise Stripe will retry delivery.
In the Stripe Dashboard → Webhooks panel, we register the endpoint and subscribe to events: checkout.session.completed, payment_intent.payment_failed, charge.refunded.
Refunds and Partial Refunds
$refund = \Stripe\Refund::create([
'payment_intent' => $paymentIntentId,
'amount' => $refundAmountInCents, // do not pass for full refund
'reason' => 'requested_by_customer',
]);
After creating a refund, a charge.refunded webhook arrives — update the status in Bitrix. Stripe allows multiple partial refunds up to the full transaction amount.
Settings in Bitrix Admin Panel
| Parameter | Where to Get |
|---|---|
| Publishable Key | Stripe Dashboard → API keys |
| Secret Key | Stripe Dashboard → API keys (shown once) |
| Webhook Secret | Stripe Dashboard → Webhooks → Signing secret |
| Mode (test/live) | Toggle in Dashboard, changes the set of keys |
In test mode, use card 4242 4242 4242 4242, any expiration, any CVC. To check decline — 4000 0000 0000 0002.
Apple Pay and Google Pay
When using Stripe Checkout, both methods are enabled automatically if the domain is verified in Stripe Dashboard → Payment methods → Apple Pay. For Elements, additional Payment Request Button setup and domain verification via .well-known/apple-developer-merchantid-domain-association file is needed.
Timeline
| Integration Option | Scope | Timeline |
|---|---|---|
| Checkout (hosted) | Module + webhooks + testing | 3–4 days |
| Elements (embedded form) | + JS component, domain verification | 5–7 days |
| + Subscriptions (recurring) | + plan management, webhooks subscription | +3–5 days |
| + Apple/Google Pay | Domain verification + testing | +1–2 days |







