1C-Bitrix Integration with Cherepakha Instalment Service (Belarus)
"Cherepakha" is an instalment service from MTBank (Belarus). It is positioned as fast instalment without a bank visit: the buyer goes through the verification online in a few minutes. For the store — receiving the full amount minus the commission. MTBank provides a REST API for integration with eCommerce platforms.
MTBank API Interaction Scheme
MTBank uses OAuth 2.0 Client Credentials for partner authorisation:
class MtbankOAuthClient
{
private ?string $accessToken = null;
private ?int $expiresAt = null;
public function getToken(): string
{
if ($this->accessToken && $this->expiresAt > time() + 60) {
return $this->accessToken;
}
$response = $this->httpPost('/oauth/token', [
'grant_type' => 'client_credentials',
'client_id' => MTBANK_CLIENT_ID,
'client_secret' => MTBANK_CLIENT_SECRET,
'scope' => 'installment',
]);
$this->accessToken = $response['access_token'];
$this->expiresAt = time() + $response['expires_in'];
// Cache in Bitrix Cache
\Bitrix\Main\Data\Cache::createInstance()->set(
'mtbank_token',
['token' => $this->accessToken, 'expires' => $this->expiresAt],
$response['expires_in'] - 120
);
return $this->accessToken;
}
}
Creating an Instalment Order
public function initiatePay(\Bitrix\Sale\Payment $payment, \Bitrix\Main\Request $request = null)
{
$order = $payment->getOrder();
$termMap = ['3' => 3, '6' => 6, '12' => 12, '18' => 18, '24' => 24];
$term = $termMap[$this->getBusinessValue($payment, 'TERM')] ?? 12;
$payload = [
'externalOrderId' => 'BITRIX-' . $order->getId(),
'amount' => (float)$payment->getSum(),
'currency' => 'BYN',
'term' => $term,
'description' => 'Order ' . $order->getField('ACCOUNT_NUMBER'),
'successUrl' => $this->getSuccessUrl($payment),
'failUrl' => $this->getFailUrl($payment),
'notifyUrl' => $this->getNotificationUrl($payment),
'customer' => [
'firstName' => $order->getPropertyValueByCode('NAME'),
'lastName' => $order->getPropertyValueByCode('LAST_NAME'),
'phone' => preg_replace('/\D/', '', $order->getPropertyValueByCode('PHONE')),
'email' => $order->getPropertyValueByCode('EMAIL'),
],
'items' => $this->formatBasketItems($order->getBasket()),
];
$token = $this->oauthClient->getToken();
$response = $this->httpPost('/v1/installment/orders', $payload, [
'Authorization' => "Bearer {$token}",
]);
if (empty($response['paymentUrl'])) {
throw new \RuntimeException('MTBank Cherepakha: empty paymentUrl');
}
// Save MTBank orderId for callbacks and refunds
\Bitrix\Main\Application::getConnection()->queryExecute(
"INSERT INTO bl_mtbank_orders (bitrix_order_id, mtbank_order_id, status, created_at)
VALUES (?, ?, 'pending', NOW())",
[$order->getId(), $response['orderId']]
);
$result = new \Bitrix\Sale\PaySystem\ServiceResult();
$result->setPaymentUrl($response['paymentUrl']);
return $result;
}
Basket Items Formatting
MTBank API requires the order items for amount verification:
private function formatBasketItems(\Bitrix\Sale\Basket $basket): array
{
$items = [];
foreach ($basket as $item) {
$items[] = [
'name' => mb_substr($item->getField('NAME'), 0, 255),
'quantity' => (int)$item->getQuantity(),
'unitPrice' => round($item->getPrice(), 2),
'totalPrice'=> round($item->getFinalPrice(), 2),
'sku' => (string)$item->getProductId(),
];
}
// Add delivery if present
$shipment = $basket->getOrder()->getShipmentCollection()->getIterator()->current();
$deliveryPrice = $shipment ? $shipment->getPrice() : 0;
if ($deliveryPrice > 0) {
$items[] = [
'name' => 'Delivery',
'quantity' => 1,
'unitPrice' => $deliveryPrice,
'totalPrice' => $deliveryPrice,
'sku' => 'DELIVERY',
];
}
return $items;
}
Callback Processing
MTBank signs notifications with HMAC-SHA256 using a secret key:
public function processRequest(\Bitrix\Sale\Payment $payment, \Bitrix\Main\Request $request)
{
$body = file_get_contents('php://input');
$signature = $request->getServer()->get('HTTP_X_MTBANK_SIGNATURE');
$expected = hash_hmac('sha256', $body, MTBANK_WEBHOOK_SECRET);
if (!hash_equals($expected, $signature ?? '')) {
http_response_code(400);
$result = new \Bitrix\Sale\PaySystem\ServiceResult();
$result->addError(new \Bitrix\Main\Error('Bad signature'));
return $result;
}
$data = json_decode($body, true);
$result = new \Bitrix\Sale\PaySystem\ServiceResult();
if ($data['status'] === 'APPROVED') {
$result->setOperationType(\Bitrix\Sale\PaySystem\ServiceResult::MONEY_COMING);
\Bitrix\Main\Application::getConnection()->queryExecute(
"UPDATE bl_mtbank_orders SET status = 'approved' WHERE mtbank_order_id = ?",
[$data['orderId']]
);
$payment->setPaid('Y');
}
return $result;
}
Service Limitations
The minimum order amount and maximum instalment term are defined by the contract with MTBank. In the handler we implement an isAvailable() method that checks the basket total before displaying the "Cherepakha" button.
Timeline
| Phase | Duration |
|---|---|
| MTBank OAuth client + token cache | 1 day |
| Payment system handler | 2 days |
| Callback + signature verification | 1 day |
| Refunds | 1 day |
| Testing in MTBank environment | 2 days |
| Total | 7–8 days |







