Skip to content

Instantly share code, notes, and snippets.

@dimitarminchev
Last active October 30, 2024 04:46
Show Gist options
  • Select an option

  • Save dimitarminchev/08d8ab833fa481a8cc5c1e365a16c05e to your computer and use it in GitHub Desktop.

Select an option

Save dimitarminchev/08d8ab833fa481a8cc5c1e365a16c05e to your computer and use it in GitHub Desktop.
Borica Request 4.0
<?php
/*
# Borica Request 4.0
Изпращане на заявка за извършване на електронно плащане: [borica_request.php](https://gist.github.com/dimitarminchev/08d8ab833fa481a8cc5c1e365a16c05e)
- Документация: [Borica APGW e-Gateway Resources](https://3dsgate-dev.borica.bg/)
- Автор: [доц. д-р Димитър Минчев](http://www.minchev.eu)
- Eлектронна поща: [[email protected]](mailto:[email protected])
*/
// Gateway
$GATEWAY = "https://3dsgate-dev.borica.bg/cgi-bin/cgi_link"; // Development
// $GATEWAY = "https://3dsgate.borica.bg/cgi-bin/cgi_link"; // Production
// DATA: MAC_GENERAL = TERMINAL, TRTYPE, AMOUNT, CURRENCY, ORDER, DESC, MERCHANT, MERCH_NAME, ADDENDUM, AD.CUST_BOR_ORDER_ID, TIMESTAMP, NONCE, P_SIGN
$TERMINAL = "V1800001"; // Идентификатор на терминала получен от БОРИКА, Размер: 8
$TRTYPE = "1"; // Тип на транзацията: 1, 12, 21, 22, 24, 90, Разпер: 1-2
$AMOUNT = "1.23"; // Сума на плащането, Формат: xx.xx, Размер: 1-12
$CURRENCY = "BGN"; // Валута на плащането, Размер: 3, Формат: ISO-4217
$ORDER = "001234"; // Номер поръчка, Размер: 6
$DESC = "Наименование на поръчката"; // Наименование на поръчката, Размер: 8-50
$MERCHANT = "V1800001"; // Идентификатор на търговеца получен от БОРИКА, Размер: 10-15, Тест: $MERCHANT = "1600000001";
$MERCH_NAME = "Наименование на търговеца"; // Наименование на търговеца, Размер: 18
$ADDENDUM = "AD,TD";
$AD_CUST_BOR_ORDER_ID = $ORDER."@".$ORDER; // ORDER + 16 символа
$TIMESTAMP = gmdate("YmdHis"); // Формат: YYYYMMDDHHMMSS, UTC, Размер: 14
$NONCE = strtoupper(bin2hex(openssl_random_pseudo_bytes(16))); // Формиране на сигнатура за подписване, Размер: 1-64
$RFU = "-"; // Резервирано поле за бъдеща употреба
$COUNTRY = "BG"; // Страна, Размер: 2
$MERCH_GMT = "+03"; // Часова зона на търговеца: GMT 3
$MERCH_URL = "https://www.xxx.bg"; // Линк на страницата на търговеца, Размер: 1-250
$BACKREF = "https://www.xxx.bg/borica_response.php"; // Линк при връщане след плащане, Размер: 1-250
$EMAIL = "[email protected]"; // Електронна поща, Размер: 26
// SIGN: MAC_GENERAL = TERMINAL, TRTYPE, AMOUNT, CURRENCY, ORDER, TIMESTAMP, NONCE, RFU
$P_SIGN =
strlen($TERMINAL).$TERMINAL.
strlen($TRTYPE).$TRTYPE.
strlen($AMOUNT).$AMOUNT.
strlen($CURRENCY).$CURRENCY.
strlen($ORDER).$ORDER.
strlen($TIMESTAMP).$TIMESTAMP.
strlen($NONCE).$NONCE.
$RFU;
// Информация за цифровия частен ключ
$private_key = '-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5z1/LHY1GcX9f
vMOBZPx3edgmqFkPd7eV136Nog9+VeM4UMfg22d64LAwpRHdfFigTPkc9leR68xT
JXGeiiGJSaG+Vb9oUK3yb9W7YMhk1vJy4p2oyo77Sirki4bhh8RPIVWAqeVUgEL/
f5ZuZSNzB2cFkUOknbRwM/j98fft4lgZN/nYkYjW22UaPA7ULEBMxmQUKrJKi04S
PVIG1iKzLh3jVyRsxi+giFrlQ+/jVWA0wJm8B25jsRcwObjL6+MczutVKmaNjaVy
FNkBtLOWSCf4A6i4xOfafWoEx4tEa4Dl5PTqQI4PBvH6SW3lKulfNpa5m1wvnlA3
hFy9IfUPAgMBAAECggEBAJz/stI9yxQ9bEGpjovzlzsgcdngHzhpkG6EocLsryix
S4dXAjxlRp9V4KmJoHnDymLQByFIqJ98XK3YkpNB5apJ0+euLkfm+8NAaZik404J
LNyTzGFFneCIP4vStQo1HFM8ODG53DM1GOcnmCT5QiW8mHjk0AH02vR/haCU5kdR
qQeMBnGAuqOcO3T7QcuK2AMO7BoGrkq0+V58DyCdf1UpeLoi71HCdBpj8FPHcU0H
ScsPUrWXSkJSVj7R68AUtI4Sss3CEk7DbbSLcW1DfmX6esujM/fx1SLc9Bue4Ipa
0ec7wKvvMbLap0gWOOxZGRtxS9ALJ3T75AOjDx38q6ECgYEA86cPMYUePy/l9CEu
F2fsr0LnpB3clwEhhMeIIjKMCTVnPlHMy8Sm9WrRdErKMpsIbOWgeIqUaPPCt3NZ
FTgJnIJnFR4KI5qPOb3ZRA9OI6eliVvdgxe7e/bHe74b/v/uE6378ddtniHCIvgk
6Oi9/luImv3kYzX1pmJr/8VZQdECgYEAwznqU1QiPaUFtZwkb3hIoTcIYlKwIbmP
3HYdsS2p20WHh3XJC9nojABIBgJJYKdACzQyIy1FJJ3ga0fgkSZ5KL1LXmclXXL6
lzdQNIyF/boRP+XC7fB9MNwIClqJCnmciKWE4xCt9GgEiLnJDYnOhGiQ50BuxJFn
RU6RxjAPoN8CgYEA3LmYr/mx/vf7T3/Ha3jAF716b1iF/14M6WaA0soLxkPUtcYQ
yv/paCZOfRVLuzBrH4ueJdUUwUciPGKIbwqG2nvfumeuM7bOzTZJXrimxvIWqirI
rvuO4qwa5uTAI+/h034n4VyRd1GJt3gop75Ab+6oABDFF4NIeGRtBhXX2CECgYB9
/QRCHouyaKsUlt3UqjWFBPT+LwrH2O8EgZ2L2EJD5c0fGF5UrZ4rq4rPhe5A1+62
zEqG9RIoHVLVKR+9zKxoJDFdjQdKFYeuyt2R7BYUtl2ndOmlkIvaWkU+GUtTXUQt
01O9DeiVUAONEQi1GfgS70CEXMqfRI725UuiMSYE1QJ/EkPO8VPbWf+BgKovYFf1
AsStOfMMvrgVn8e/vZmWluaGb40L34Dxuvv3YRk1EsQFirGZ5XDDCm5r8H1IY8Ne
PXnxLP2opIuch1JHQdebFZqN1C68pX6hopEixOmwShhaNXNJ5RN8c9q+4NXIu73n
lKFJBDsxoMVB/VEoVeQEMg==
-----END PRIVATE KEY-----';
$private_pass = '';
/*
// Отваряне на файла съдържащ цифровия частен ключ
$private_key_file = "private.key";
$fp = fopen($private_key_file, "r");
$private_key = fread($fp, filesize($private_key_file));
fclose($fp);
*/
// Подписване на съобщението с цифров сертификат
$private_key_id = openssl_get_privatekey($private_key, $private_pass);
openssl_sign($P_SIGN, $signature, $private_key_id, OPENSSL_ALGO_SHA256);
openssl_free_key($private_key_id);
// Формиране окончателна подписана сигнатура
$P_SIGN = strtoupper(bin2hex($signature));
// Формуляр за извършване на плащане
echo<<<EOT
<h1>Borica Request 4.0</h1>
<pre>
GATEWAY: $GATEWAY
TERMINAL: $TERMINAL
TRTYPE: $TRTYPE
AMOUNT: $AMOUNT
CURRENCY: $CURRENCY
ORDER: $ORDER
DESC: $DESC
MERCHANT: $MERCHANT
MERCH_NAME: $MERCH_NAME
MERCH_NAME: $ADDENDUM
AD_CUST_BOR_ORDER_ID: $AD_CUST_BOR_ORDER_ID
TIMESTAMP: $TIMESTAMP
NONCE: $NONCE
RFU: $RFU
COUNTRY: $COUNTRY
MERCH_GMT: $MERCH_GMT
MERCH_URL: $MERCH_URL
BACKREF: $BACKREF
EMAIL: $EMAIL
P_SIGN: $P_SIGN
</pre>
<form action="$GATEWAY" method="post">
<!-- TERMINAL: 8 -->
<input type="hidden" name="TERMINAL" value="$TERMINAL" />
<!-- TRTYPE: 1, 12, 21, 22, 24, 90 -->
<input type="hidden" name="TRTYPE" value="$TRTYPE" />
<!-- AMOUNT: 1-12 -->
<input type="hidden" name="AMOUNT" value="$AMOUNT" />
<!-- CURRENCY: 3 -->
<input type="hidden" name="CURRENCY" value="$CURRENCY" />
<!-- ORDER: 6 -->
<input type="hidden" name="ORDER" value="$ORDER" />
<!-- DESC: 8-50 -->
<input type="hidden" name="DESC" value="$DESC" />
<!-- MERCHANT: 10-15 -->
<input type="hidden" name="MERCHANT" value="$MERCHANT" />
<!-- MERCH_NAME: 18 -->
<input type="hidden" name="MERCH_NAME" value="$MERCH_NAME" />
<!-- ADDENDUM -->
<input type="hidden" name="ADDENDUM" value="$ADDENDUM" />
<!-- AD.CUST_BOR_ORDER_ID -->
<input type="hidden" name="AD.CUST_BOR_ORDER_ID" value="$AD_CUST_BOR_ORDER_ID" />
<!-- TIMESTAMP: 14 -->
<input type="hidden" name="TIMESTAMP" value="$TIMESTAMP" />
<!-- NONCE: 64 -->
<input type="hidden" name="NONCE" value="$NONCE" />
<!-- RFU: - -->
<input type="hidden" name="RFU" value="-" />
<!-- COUNTRY: 2 -->
<input type="hidden" name="COUNTRY" value="$COUNTRY" />
<!-- MERCH_GMT: 3 -->
<input type="hidden" name="MERCH_GMT" value="$MERCH_GMT" />
<!-- MERCH_URL: 1-250 -->
<input type="hidden" name="MERCH_URL" value="$MERCH_URL" />
<!-- BACKREF: 1-250 -->
<input type="hidden" name="BACKREF" value="$BACKREF" />
<!-- EMAIL: 26 -->
<input type="hidden" name="EMAIL" value="$EMAIL" />
<!-- P_SIGN: 512 -->
<input type="hidden" name="P_SIGN" value="$P_SIGN" />
<!-- BUTTON -->
<input type="submit" value="Payment" />
</form>
EOT;
@crs-bg
Copy link

crs-bg commented Jan 9, 2022

Здравейте,

Това означава ли, че след като клиента си е попълнил данните за плащането, трябва да се зареди нова страница на сайта, но вече с автоматично попълнената формата от скрипта и след това да се направи submit на формата?

@dyanakiev
Copy link

Не използвам този код, но малко рандъм въпрос, на който едва ли ще ми отговори някой тук, утре ще питам Борика, но знаете ли дали трябва да се спазва Dailight time saving за стойността която се сетва в MERCH_GMT/merchant timezone?

@dimitarminchev
Copy link
Author

Актуализация за версия 4.0.
За повече информация: https://3dsgate-dev.borica.bg/

@pgp69
Copy link

pgp69 commented Jun 29, 2023

Здравейте,
при схема на подписване MAC_GENERAL от къде се взима поле MERCH_TOKEN_ID. Не го намирам никъде.,

@dimitarminchev
Copy link
Author

Здравейте, при схема на подписване MAC_GENERAL от къде се взима поле MERCH_TOKEN_ID. Не го намирам никъде.

При формиране на сигнатура за подписване MERCH_TOKEN_ID не е необходим:
SIGNATURE: MAC_GENERAL = TERMINAL, TRTYPE, AMOUNT, CURRENCY, ORDER, TIMESTAMP, NONCE, RFU

@pgp69
Copy link

pgp69 commented Jul 30, 2023 via email

@Peter-Georgiev
Copy link

Здравейте,
Позволено ли е да вградя https://3dsgate-dev.borica.bg/cgi-bin/cgi_link в iframe на сайта, като нещо от типа:

<iframe src="https://3dsgate-dev.borica.bg/cgi-bin/cgi_link" width="600" height="400" ></iframe>. Може ли някакво примерче. Благодаря предварително!

@a-veselinova
Copy link

Здравейте @dimitarminchev, използвах Вашия код за тестови цели, но ако сменя BACKREF, не се актуализира. Има някакъв кеш или нещо друго трябва да се направи?
Благодаря!

@smilegalaxy
Copy link

smilegalaxy commented Aug 15, 2024

Здравейте, получих известие от Борика, че ми изтичат сертификатите и сега с генерирането на новите ми изпратих и нова документация Версия: 5.0 / 29.05.2024 в моято има задължително поле M_INFO:

"Опционален Ннабор от данни по протокола EMV
3DS v.2
Трябва да бъде Base64 Basic-encoded string of
JSON-formatted “parameter”:”value” data.
Задължителни данни

  • Име и фамилия на картодържател ( до 45
    символа на латиница),
  • е-mail и / или телефонен номер"

и оставам с впечатлението, че трябва да поискам от клиента Името написано на картата с която ще плаща преди да изпратя заявката към Борика !?!?

@dyanakiev
Copy link

dyanakiev commented Aug 19, 2024

@smilegalaxy обърни се към банката ако ти е нужна повече информация, но да, вече в m_info е нужно да се подава допълнителна информация като Имена и/или имейл адрес в документацията беше описано кое е задължително. Като информация би следвало да я имаш ако е онлайн магазин. На мен ми е интересно дали тази информация ще бъде сравнявана с истинската която е на картата, за момента си работи с всичко въведено, конкретно за името.

Иначе, аз съм си ъпдейтнал друга библиотека която ползвам https://github.com/dyanakiev-forks/borica-emv-3ds в нея подавам инфото по-следния начин:

        $borica = $this->initBorica();
        $boricaRequest = new SaleRequest();
        $boricaRequest->setTransactionType(TransactionType::SALE)
            ->setAmount($amount)
            ->setCurrency('BGN')
            ->setOrder($borica_6digits_order)
            ->setDescription($description)
            ->setMerchantName($this->merchantName)
            ->setMerchantUrl($this->merchantUrl)
            ->setMerchant($this->merchant)
            ->setTerminal($this->terminal)
            ->setEmail($this->email)
            ->setCountry('bg')
            ->setLanguage('EN')
            ->setMerchantTimezone($this->timezoneOffset)
            ->setTimestamp(time())
            ->setNonce(strtoupper(bin2hex(openssl_random_pseudo_bytes(16))))
            ->setOrderIdentifier($boricaRequest->getOrder().'ORD@<п>')
            ->setAddendum('AD,TD')
                        ->setMInfo(json_encode([
                            'cardholderName' => $payment->cardholder_name,
                            'email' => $payment->cardholder_email,
                        ], JSON_UNESCAPED_UNICODE))
            ->sign($borica);

@smilegalaxy
Copy link

Бях разбрал, че CardholderName е името изписано на картата, а реално е името на потребителя - данни, които разбира се имам.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment