-
-
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