Integrating 1C-Bitrix with PayPal

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    745
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

1C-Bitrix Integration with PayPal Payment System

PayPal is one of the most common payment systems for international trade. In 1C-Bitrix, there is no official current PayPal module: the old PayPal Standard module is outdated, PayPal Express Checkout has been replaced with PayPal Commerce Platform (PPCP). Therefore, integration requires custom development for the current API.

Current PayPal Product for Merchants

PayPal Commerce Platform (PPCP) combines several payment methods:

  • Visa/Mastercard/AmEx card payments without PayPal account (Guest Checkout);
  • payment via customer's PayPal account;
  • Pay Later (BNPL — buy now, pay later) in supported countries;
  • Venmo (USA).

To connect, the store registers as a merchant via PayPal Partner Program or directly via business.paypal.com.

Two Technical Implementation Options

PayPal Checkout (hosted buttons / Smart Buttons). JavaScript SDK from PayPal is embedded on the checkout page. The customer clicks the PayPal button, goes through authorization in a popup window, returns to the site. Card data does not touch the merchant's server. Suitable for most stores.

Orders API (server-side). The order is created on the server via POST /v2/checkout/orders, the customer authorizes it, the server captures funds via POST /v2/checkout/orders/{id}/capture. More control, necessary for custom flows and subscriptions.

Module Architecture in Bitrix

The payment system handler inherits \Bitrix\Sale\PaySystem\ServiceHandler. Parameters are stored in b_sale_pay_system_action: CLIENT_ID, CLIENT_SECRET, ENVIRONMENT (sandbox/live).

Getting an access token:

$response = $httpClient->post(
    $baseUrl . '/v1/oauth2/token',
    ['grant_type' => 'client_credentials'],
    ['Authorization' => 'Basic ' . base64_encode($clientId . ':' . $clientSecret)]
);
$accessToken = $response['access_token'];

Creating an order (Orders API v2):

$order = $httpClient->post($baseUrl . '/v2/checkout/orders', [
    'intent' => 'CAPTURE',
    'purchase_units' => [[
        'reference_id' => 'order_' . $bitrixOrderId,
        'amount' => [
            'currency_code' => 'USD',
            'value' => '99.00',
        ],
    ]],
    'application_context' => [
        'return_url' => $returnUrl,
        'cancel_url' => $cancelUrl,
    ],
]);

The customer is redirected via links[rel=approve].href. After returning, we call POST /v2/checkout/orders/{id}/capture.

JavaScript Smart Buttons

For the Checkout approach, the JS SDK is added to the sale.order.ajax component page:

<script src="https://www.paypal.com/sdk/js?client-id=CLIENT_ID&currency=USD"></script>
<div id="paypal-button-container"></div>
<script>
paypal.Buttons({
    createOrder: function(data, actions) {
        return fetch('/api/paypal/create-order', {method: 'POST'})
            .then(r => r.json()).then(d => d.id);
    },
    onApprove: function(data, actions) {
        return fetch('/api/paypal/capture-order/' + data.orderID, {method: 'POST'})
            .then(r => r.json()).then(d => {
                if (d.status === 'COMPLETED') window.location = '/order/success/';
            });
    }
}).render('#paypal-button-container');
</script>

On the Bitrix side, two AJAX endpoints are created: create-order (initiates order in PayPal, returns id) and capture-order (captures funds, updates status in b_sale_order).

Webhooks (Webhooks IPN)

PayPal sends notifications via Webhooks v2. Subscription to events — in PayPal Developer Dashboard. Required events:

  • PAYMENT.CAPTURE.COMPLETED — confirmation of fund capture
  • PAYMENT.CAPTURE.DENIED — rejection
  • PAYMENT.CAPTURE.REFUNDED — refund

Webhook signature verification:

$result = \PayPalHttp\HttpClient::verifyWebhookSignature(
    $webhookId, $headers, $body, $accessToken
);

Refunds

Refund via POST /v2/payments/captures/{captureId}/refund. captureId is saved in b_sale_payment.PS_INVOICE_ID when captured.

$refund = $httpClient->post(
    $baseUrl . '/v2/payments/captures/' . $captureId . '/refund',
    ['amount' => ['value' => '25.00', 'currency_code' => 'USD']]
);

Full refund — request body is empty, PayPal will return the entire capture amount.

Sandbox Testing

In PayPal Developer Dashboard, create sandbox accounts: one merchant (business), one customer (personal). Test cards are available in Sandbox → Accounts → customer → Credit Cards. The sandbox is fully isolated — transactions do not affect real money.

Scenario How to Check
Successful payment Sandbox personal account, balance > order amount
Insufficient funds Sandbox account with zero balance
Cancellation by customer Close PayPal window, check cancel_url
Refund Via API after successful capture

Timeline

Option Scope Timeline
Smart Buttons + capture Module + JS widget + testing 4–6 days
Fully server-side (Orders API) Without JS dependency, API only 4–5 days
+ Subscriptions Recurring billing via Subscriptions API +3–4 days
+ Multi-currency Currency selection logic, PayPal setup +1–2 days