-
-
Save dimitarminchev/34265c2c780ccff86a545eb4a1ffd88c to your computer and use it in GitHub Desktop.
<?php | |
/* | |
# Borica Response 4.0 | |
Получаване и обработка на отговор от електронно плащане: [borica_response.php](https://gist.github.com/dimitarminchev/34265c2c780ccff86a545eb4a1ffd88c) | |
- Документация: [Borica APGW e-Gateway Resources](https://3dsgate-dev.borica.bg/) | |
- Автор: [доц. д-р Димитър Минчев](http://www.minchev.eu) | |
- Eлектронна поща: [mitko@bfu.bg](mailto:mitko@bfu.bg) | |
*/ | |
// Проверка дали има обратно получената информация от БОРИКА? | |
if(empty($_REQUEST)) die("<h1>No Responce Error!</h1>"); | |
// Формиране на сигнатурата за проверка | |
// MAC_GENERAL: ACTION, RC, APPROVAL, TERMINAL, TRTYPE, AMOUNT, CURRENCY, ORDER, RRN, INT_REF, PARES_STATUS, ECI, TIMESTAMP, NONCE, RFU | |
$ACTION = strlen($_REQUEST["ACTION"]) > 0 ? strlen($_REQUEST["ACTION"]).$_REQUEST["ACTION"] : "-"; | |
$RC = strlen($_REQUEST["RC"]) > 0 ? strlen($_REQUEST["RC"]).$_REQUEST["RC"] : "-"; | |
$APPROVAL = strlen($_REQUEST["APPROVAL"]) > 0 ? strlen($_REQUEST["APPROVAL"]).$_REQUEST["APPROVAL"] : "-"; | |
$TERMINAL = strlen($_REQUEST["TERMINAL"]) > 0 ? strlen($_REQUEST["TERMINAL"]).$_REQUEST["TERMINAL"] : "-"; | |
$TRTYPE = strlen($_REQUEST["TRTYPE"]) > 0 ? strlen($_REQUEST["TRTYPE"]).$_REQUEST["TRTYPE"] : "-"; | |
$AMOUNT = strlen($_REQUEST["AMOUNT"]) > 0 ? strlen($_REQUEST["AMOUNT"]).$_REQUEST["AMOUNT"] : "-"; | |
$CURRENCY = strlen($_REQUEST["CURRENCY"]) > 0 ? strlen($_REQUEST["CURRENCY"]).$_REQUEST["CURRENCY"] : "-"; | |
$ORDER = strlen($_REQUEST["ORDER"]) > 0 ? strlen($_REQUEST["ORDER"]).$_REQUEST["ORDER"] : "-"; | |
$RRN = strlen($_REQUEST["RRN"]) > 0 ? strlen($_REQUEST["RRN"]).$_REQUEST["RRN"] : "-"; | |
$INT_REF = strlen($_REQUEST["INT_REF"]) > 0 ? strlen($_REQUEST["INT_REF"]).$_REQUEST["INT_REF"] : "-"; | |
$PARES_STATUS = strlen($_REQUEST["PARES_STATUS"]) > 0 ? strlen($_REQUEST["PARES_STATUS"]).$_REQUEST["PARES_STATUS"] : "-"; | |
$ECI = strlen($_REQUEST["ECI"]) > 0 ? strlen($_REQUEST["ECI"]).$_REQUEST["ECI"] : "-"; | |
$TIMESTAMP = strlen($_REQUEST["TIMESTAMP"]) > 0 ? strlen($_REQUEST["TIMESTAMP"]).$_REQUEST["TIMESTAMP"] : "-"; | |
$NONCE = strlen($_REQUEST["NONCE"]) > 0 ? strlen($_REQUEST["NONCE"]).$_REQUEST["NONCE"] : "-"; | |
$RFU = "-"; // Резервирано поле за бъдеща употреба | |
$DATA = $ACTION.$RC.$APPROVAL.$TERMINAL.$TRTYPE.$AMOUNT.$CURRENCY.$ORDER.$RRN.$INT_REF.$PARES_STATUS.$ECI.$TIMESTAMP.$NONCE.$RFU; | |
$P_SIGN = hex2bin($_REQUEST["P_SIGN"]); | |
// Информация за цифровия публичен ключ | |
$public_key = '-----BEGIN CERTIFICATE----- | |
MIIGWjCCBEKgAwIBAgIIQSHpHDZ7ASAwDQYJKoZIhvcNAQELBQAwgYoxCzAJBgNVBAYTAkJHMRgw | |
FgYDVQRhDA9OVFJCRy0yMDEyMzA0MjYxIDAeBgNVBAoMF0JPUklDQSAtIEJBTktTRVJWSUNFIEFE | |
MRAwDgYDVQQLDAdCLVRydXN0MS0wKwYDVQQDDCRCLVRydXN0IFRFU1QgT3BlcmF0aW9uYWwgQWR2 | |
YW5jZWQgQ0EwHhcNMjAwOTEwMDg0NzU5WhcNMjMwOTEwMDg0NzU5WjBkMRQwEgYDVQQDDAtNUEkg | |
T1cgQVBHVzELMAkGA1UECwwCSVMxEjAQBgNVBAoMCUJvcmljYSBBRDEOMAwGA1UECAwFU29maWEx | |
DjAMBgNVBAcMBVNvZmlhMQswCQYDVQQGEwJCRzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC | |
ggEBAMmtJ1gcFkdfY/wfEk3IbqAA1dveXj9J3dCNyliHoooj1ePsX86jlYLijrdPOgayESwH01OO | |
nVEbcF9z2qoicH12vJaa9ZEFgqkB+qv55erfQOTjgVhd+KRb8YES+uEGkIFE8D/peLMeKeiRSleN | |
corRa4J1ms/V/2Oklxg0xSnEXw8tRa0U2OoPlEwCbT01DgPMoud5EitpTvD9/gc69aWgVS477Erf | |
ro+CW89bLGNiHh6mmZt71uIXugNtGf2RhP59fmEKBKj+DSF1QI65SVvv2eYb6JBlhHX+hZss/oAN | |
xvqYFSG4k6L1tkoDwctB+q7p1EbWEuqDNxYT0RidkLkCAwEAAaOCAecwggHjMB0GA1UdDgQWBBTT | |
nQwEEjMqWryNqt8onGmGk6nm4DAfBgNVHSMEGDAWgBT1J8z325solCubZvApcg6KPWLcmDAgBgNV | |
HRIEGTAXhhVodHRwOi8vd3d3LmItdHJ1c3QuYmcwCQYDVR0TBAIwADBNBgNVHSAERjBEMEIGDCsG | |
AQQB+3YBBwEEAjAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LmItdHJ1c3Qub3JnL2RvY3VtZW50 | |
cy9jcHMwDgYDVR0PAQH/BAQDAgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBUBgNV | |
HR8ETTBLMEmgR6BFhkNodHRwOi8vY3JsdGVzdC5iLXRydXN0Lm9yZy9yZXBvc2l0b3J5L0ItVHJ1 | |
c3RUZXN0T3BlcmF0aW9uYWxBQ0EuY3JsMIGHBggrBgEFBQcBAQR7MHkwJwYIKwYBBQUHMAGGG2h0 | |
dHA6Ly9vY3NwdGVzdC5iLXRydXN0Lm9yZzBOBggrBgEFBQcwAoZCaHR0cDovL2NhdGVzdC5iLXRy | |
dXN0Lm9yZy9yZXBvc2l0b3J5L0ItVHJ1c3RUZXN0T3BlcmF0aW9uYWxBQ0EuY2VyMBYGA1UdEQQP | |
MA2CC01QSSBPVyBBUEdXMA0GCSqGSIb3DQEBCwUAA4ICAQAUJfDjTROuVORLojCzVQdppoiPs3hX | |
Ra/9MaNIUP5xlI0AamWmN7bTDQpnNfw5tlo8DPSBIMfP+5xJyfMTHAi43i+7vf1t1ZucEbVJ73FF | |
zdzZQaxw9NY0n0IBBz8WEnkaGewh45aQ6XMgNe5xcKbtP2vqq+qZiy0eyIHJwaQORKyZ9+jBlnVo | |
ZdzUbDrrSEMka98IQ52XO8EPbCmB/GhJlZ991yNo5/PVsFxT9sjG3VGm+sStD3G7+pjX+HsHLn65 | |
gwWq2oRiQqe62W/HSNb5dnIWqIJldT4Zd0Ar97hQwU1ZQVnmL5ZjswsjafI7B/0N4U5QzbOvWX1W | |
oDXCCqmXAoTP1DDEWJ0vmvVDHGrrC0rIbluBdzQEK/D1f3A1jlCzQPyKOwUuafLlpCX17b09Zwxi | |
45prDk/LBqE6CI6CM+8nF0QyN3Th+r2IqUuhGpfLApGlp6sJvJdAhnqX1VCGJCdozIhzrEJ4oha3 | |
/+HijQl+vUaYevk1d/EipZNHU1gkcocrj2qmTMOKzEw9zDs5jVSgtBZTUF5ORwUNiTXj7EZUnQUC | |
wANFl8k0EcWPhkU5L7v9/9rcGkMcm0S3bM5rbKksabvq01cvxkepS5qqvbxgugci/8sPCXMAThCK | |
eiJHilEt1uns+tFA+7RSVFKOpf07g3DBGYf5P8qKLQCFMg== | |
-----END CERTIFICATE-----'; | |
/* | |
// Отваряне на файла съдържащ цифровия публичен ключ | |
$public_key_file = "public.cer"; | |
$fp = fopen($public_key_file, "r"); | |
$public_key = fread($fp, filesize($public_key_file)); | |
fclose($fp); | |
*/ | |
// Подписване на съобщението с цифров сертификат | |
$public_key_id = openssl_get_publickey($public_key); | |
$ssl_verification = openssl_verify($DATA, $P_SIGN, $public_key_id, OPENSSL_ALGO_SHA256); | |
openssl_free_key($public_key_id); | |
// Проверка за валидност? | |
if($ssl_verification != 1) die("<h1>SSL Verification Error!</h1><p>".openssl_error_string()."</p>"); | |
// Записване на хронология в JavaScript Object Notation (JSON) файл | |
file_put_contents("$ORDER.json", json_encode($_REQUEST)); | |
// Проверка за успешна транзакция? | |
if($_REQUEST["RC"] == "00") echo "<h1>Payment Successful</h1>"; | |
else die("<h1>Payment Error ".$_REQUEST["RC"]."</h1>"); | |
// RC Error Codes (ISO-8583): https://en.wikipedia.org/wiki/ISO_8583 | |
// Отпечатване на обратно получената информация от БОРИКА | |
print_r($_REQUEST); |
Здравейте,
Първо искам да Ви благодаря за имплеметацията мисля че ще е от полза на много хора.
Второ благодаря за линка с документацията. От банката са ми изпратили версия 2.0 (не знам защо) докато тази е версия 2.2. Тъй като има промени между двете версии новата документация ми беше много полезна. Някак си с грешна документация е една идея по тегаво :D
Имам следния въпрос:
Доколкото разбрах от последната версия на документацията, когато Борика ни върне 0 байта за някое поле например (PARES_STATUS, ECI) го заменяме с "-" (както Вие сте направили),
НО в низът $DATA който проверяваме с openssl_verify мисля че те тези полета трябва да участавт БЕЗ дължианта им преди тях. В примера от документацията на страница 18 PARES_STATUS и ECI са с 0 байта и участват само с - без 1 за дължина отпред.
Пробвах и двата варианта но не успявам да получа успешна верификация openssl_verify винаги ми връща 0
Дали имате идея какъв може да е проблема
Действително, ако някое поле е празно то участва във формирането на сигнатурата като се записва само със знак минус. Примера който е даден тук на PHP верификацията минава.
PS. Добавил съм нещо което още не е документирано, а именно: $DATA = rtrim($DATA,"-"); // Fix FW: update Borica EMV 3DS ver 2.2 from 22.10.2020 г.
Благодаря Ви за отговора помогна ми, мина и при мен
Интересно е че когато ползвам публичният ключ, който е във вашият пример минава, когато ползвам този който са ми дали не :)
Също така Borica Responce 2.2
се пише синтактично коректно Borica Response 2.2.
Благодаря @budiony бележката е взета под внимание и информацията е коригирана!
Някаква идея защо Борика очаква всички търговци да използват един споделен публичен ключ за верификация на съобщенията от платежният сървър , вместо предоставените им индивидуални ?
@GeorgyPorgy БОРИКА няма да очакват всички търговци да използват един и същи споделен публичен ключ за верификация на съобщенията от платежният сървър. Това е просто един пример.
За валидация на отговора се използва публичния ключ от:
https://3dsgate-dev.borica.bg/MPI_OW_APGW.zip
Както БОРИКА, така и Търговеца имате двойка ключове публичен и частен.
БОРИКА подписва съобщенията с частния ключ, а вие ги верифицирате с публичният им ключ:
https://3dsgate-dev.borica.bg/MPI_OW_APGW.zip
Търговеца подписва с частният ключ (.key), а Борика верифицира с публичния му ключ (.cer)
Здравейте,
пробваме да имплентираме вашият код, borica_request.php работи успешно, но при borica_response.php получаваме следната грешка:
SSL Verification Error!
error:04091077:rsa routines:INT_RSA_VERIFY:wrong signature length
Кода се ползва 1:1 без да се променя нещо по него.
Ще може ли да ни дадете някакви насоки от какво може да се получава тази грешка?
Предварително благодаря!
Документацията на БОРИКА е достъпна в Интернет на адрес:
https://3dsgate-dev.borica.bg/
Здравейте, след изпозването на кода от вас имам следния проблем.
дава ми грешка Payment Error -19
[STATUSMSG] => Authentication failed. The error has occurred on ACS or Directory Server
Това е опит за плащане с тестовите карти които не изискват тество ACS
При опит с карта която изисква ACS всички минава коректно.
можете ли да помогнете?
Здравейте, след изпозването на кода от вас имам следния проблем.
дава ми грешка Payment Error -19
[STATUSMSG] => Authentication failed. The error has occurred on ACS or Directory ServerТова е опит за плащане с тестовите карти които не изискват тество ACS
При опит с карта която изисква ACS всички минава коректно.
можете ли да помогнете?
При някои от тестовите карти се получава този проблем, не е нищо обезпокоително - на продукционната среда нещата работят нормално. Ползвайте друга тестова карта.
Здравейте, след изпозването на кода от вас имам следния проблем.
дава ми грешка Payment Error -19
[STATUSMSG] => Authentication failed. The error has occurred on ACS or Directory Server
Това е опит за плащане с тестовите карти които не изискват тество ACS
При опит с карта която изисква ACS всички минава коректно.
можете ли да помогнете?При някои от тестовите карти се получава този проблем, не е нищо обезпокоително - на продукционната среда нещата работят нормално. Ползвайте друга тестова карта.
Благодаря и от банката това ми казаха, че имало проблеми с карти на тестовата среда. Благодаря много!
Здравейте,
благодаря Ви за свършената работа и насоките!
При мен работи нормално всичко > request - стигам до терминала, плащам и ме връща обратно нa request url, както е зададен предварително от банката. Даже минава бързо през екран, който закачам за справка.
Проблемът е, че post масивът е празен след като стигнем на request url-a! Да сте имали такъв случай?
Поздрав
Здравейте,
благодаря Ви за свършената работа и насоките!
При мен работи нормално всичко > request - стигам до терминала, плащам и ме връща обратно нa request url, както е зададен предварително от банката. Даже минава бързо през екран, който закачам за справка.
Проблемът е, че post масивът е празен след като стигнем на request url-a! Да сте имали такъв случай?
Поздрав
Понякога на dev средата предупреждава, че връзката не е secure и прави повече от 1 redirect.
Възможно е и при вас да се е получило.
При мен го хванах директно с var_dump($_REQUEST); die;
Здравейте, Валентин.
Благодаря ви за този отговор. Пуснахме успешно терминала. Да, в последствие и аз засякох повече от един рикуест. Трябваха за съжаление обаче повече тестове, за да се забележи. :(
Поздрав и чуден ден.
Актуализация за версия 4.0.
За повече информация: https://3dsgate-dev.borica.bg/
Borica Response 4.0
Получаване и обработка на отговор от електронно плащане: borica_response.php
Responce Codes