Payment Link Setup for 1C-Bitrix
Payment by link — a manager generates a link and sends it to the buyer via messenger, email, or SMS. The buyer follows the link and pays without logging into the site. Popular for phone orders, B2B sales, and personal offers. Technically, it is a special URL with a token that leads to the payment page for a specific order or an arbitrary amount.
Two Payment Link Scenarios
Link to an existing order — the order has already been created in the system, the manager sends a payment link. The buyer does not see the checkout form, only the payment form.
Link for an arbitrary payment — the manager specifies the amount and description; the order in Bitrix is created at the moment the link is followed or payment is confirmed.
Generating a Payment Link
class PaymentLinkService
{
public function generateForOrder(int $orderId, int $expiresInHours = 24): string
{
$order = \Bitrix\Sale\Order::load($orderId);
if (!$order || $order->isPaid()) {
throw new \InvalidArgumentException('Order not found or already paid');
}
// Generate a one-time token
$token = bin2hex(random_bytes(32));
$expires = (new \DateTime())->modify('+' . $expiresInHours . ' hours');
PaymentLinkTable::add([
'ORDER_ID' => $orderId,
'TOKEN' => $token,
'EXPIRES_AT' => \Bitrix\Main\Type\DateTime::createFromPhp($expires),
'USED' => 'N',
'CREATED_BY' => $GLOBALS['USER']->GetID(),
]);
return 'https://' . $_SERVER['HTTP_HOST'] . '/pay/' . $token . '/';
}
public function generateCustom(float $amount, string $description): string
{
$token = bin2hex(random_bytes(32));
PaymentLinkTable::add([
'ORDER_ID' => null,
'AMOUNT' => $amount,
'DESCRIPTION' => $description,
'TOKEN' => $token,
'EXPIRES_AT' => \Bitrix\Main\Type\DateTime::createFromPhp(
(new \DateTime())->modify('+24 hours')
),
'USED' => 'N',
]);
return 'https://' . $_SERVER['HTTP_HOST'] . '/pay/' . $token . '/';
}
}
Payment Link Page
// Component /local/components/my/payment.link/class.php
class PaymentLinkComponent extends \CBitrixComponent
{
public function executeComponent(): void
{
$token = $this->arParams['TOKEN'] ?? $GLOBALS['APPLICATION']->GetCurDir();
$token = trim($token, '/');
// Find the link by token
$link = PaymentLinkTable::getList([
'filter' => [
'TOKEN' => $token,
'USED' => 'N',
'>EXPIRES_AT' => new \Bitrix\Main\Type\DateTime(),
],
])->fetch();
if (!$link) {
$this->arResult['ERROR'] = 'Link is invalid or has expired';
$this->includeComponentTemplate();
return;
}
// If the link points to an order — show the payment form for the existing order
if ($link['ORDER_ID']) {
$order = \Bitrix\Sale\Order::load($link['ORDER_ID']);
$this->arResult['ORDER'] = $order;
$this->arResult['AMOUNT'] = $order->getPrice();
} else {
// Arbitrary payment — create an order on the fly
$order = $this->createOrderFromLink($link);
$this->arResult['ORDER'] = $order;
$this->arResult['AMOUNT'] = $link['AMOUNT'];
}
// Initiate payment
$paySystem = \Bitrix\Sale\PaySystem\Manager::getObjectById(DEFAULT_PAY_SYSTEM_ID);
$payment = $order->getPaymentCollection()->current();
$response = $paySystem->initiatePay($payment, null);
if ($response->isSuccess()) {
// Mark the link as used only after a successful payment
// (via callback)
$this->arResult['PAYMENT_URL'] = $response->getPaymentUrl();
}
$this->includeComponentTemplate();
}
}
Managing Links from the Admin Panel
In the CRM or orders admin section, add a "Send Payment Link" button:
// On the order admin page — add a button
$adminPage->AddAdminContextMenuItem([
'TEXT' => 'Create Payment Link',
'LINK' => '/bitrix/admin/payment_link_create.php?ORDER_ID=' . $orderId,
'ICON' => 'btn_pay',
]);
The page /bitrix/admin/payment_link_create.php displays the generated link, which the manager copies and sends to the buyer.
Limiting the Number of Uses
A link can be made single-use or multi-use:
// In the callback after successful payment
if ($payment->isPaid()) {
PaymentLinkTable::update($linkId, [
'USED' => 'Y',
'PAID_AT' => new \Bitrix\Main\Type\DateTime(),
]);
}
Timeline
| Task | Duration |
|---|---|
| Token generation + link table | 0.5 day |
| Payment link page | 1 day |
| Admin panel creation interface | 0.5 day |







