Re: Testing request to pay (intiate api) using PHP

Chefane
Helper

Testing request to pay (intiate api) using PHP

I am currently trying to test request to pay API using php, now below is the error I am getting:
{"responseStatus":{"code":"9501","severity":"ERROR","message":"Invalid input found, please correct the input data","info":"","status":"400"}}]
I referred to error code documentation but looking at my code I can not figure what is wrong with my input data below is my code with test data:
<?php include_once __DIR__ . '/vendor/autoload.php'; use Jose\Component\Core\AlgorithmManager; use Jose\Component\Encryption\Algorithm\ContentEncryption\A128GCM; use Jose\Component\Encryption\Algorithm\KeyEncryption\RSAOAEP256; use Jose\Component\Encryption\Compression\CompressionMethodManager; use Jose\Component\Encryption\Compression\Deflate; use Jose\Component\Encryption\JWEBuilder; use Jose\Component\Encryption\JWEDecrypter; use Jose\Component\Encryption\JWELoader; use Jose\Component\Encryption\Serializer\CompactSerializer; use Jose\Component\Encryption\Serializer\JWESerializerManager; use Jose\Component\KeyManagement\JWKFactory; $username = 'JRQ4PF2C6FVOB1ZATU3S217WVJBkvro_IdxThoFxcuwryGSjY'; $password = 'xRyMQE8FvkOHpIz717eFg8S3bJTq4g6qP'; $client_cert = '/home/nosi/Downloads/VISA DIRECT/Request To Pay/cert (1).pem'; $private_key = '/home/nosi/Downloads/VISA DIRECT/Request To Pay/key_ef3a441c-f85c-4114-aa2c-f4165d2c351d.pem'; $mleClientPrivateKeyPath = '/home/nosi/Downloads/VISA DIRECT/Request To Pay/client_cert_77037e27-e9af-47ce-90d5-2e91b25856c6.pem'; $mleClientPublicCertificatePath = '/home/nosi/Downloads/VISA DIRECT/Request To Pay/key_77037e27-e9af-47ce-90d5-2e91b25856c6.pem'; $mleServerPublicCertificatePath = '/home/nosi/Downloads/VISA DIRECT/Request To Pay/server_cert_77037e27-e9af-47ce-90d5-2e91b25856c6.pem'; $keyId = 'key_77037e27-e9af-47ce-90d5-2e91b25856c6'; /** * This method will encrypt the payload and create a JWE token * * @param $payload * @param $keyId * @param $mleServerPublicCertificatePath * @return false|string */ function encryptPayload($payload, $keyId, $mleServerPublicCertificatePath) { // The key encryption algorithm manager with the RSA-OAEP-256 algorithm. $keyEncryptionAlgorithmManager = new AlgorithmManager([new RSAOAEP256(),]); // The content encryption algorithm manager with the A128GCM algorithm. $contentEncryptionAlgorithmManager = new AlgorithmManager([new A128GCM(),]); // The compression method manager with the DEF (Deflate) method. $compressionMethodManager = new CompressionMethodManager([new Deflate(),]); // We instantiate our JWE Builder. $jweBuilder = new JWEBuilder($keyEncryptionAlgorithmManager, $contentEncryptionAlgorithmManager, $compressionMethodManager); // Our key. $jwk = JWKFactory::createFromCertificateFile($mleServerPublicCertificatePath); $milliseconds = round(microtime(true) * 1000); $jwe = $jweBuilder ->create() // We want to create a new JWE ->withPayload($payload) // We set the payload ->withSharedProtectedHeader([ 'alg' => 'RSA-OAEP-256', // Key Encryption Algorithm 'enc' => 'A128GCM', // Content Encryption Algorithm 'iat' => $milliseconds, // Current Time Stamp in milliseconds 'kid' => $keyId ]) ->addRecipient($jwk) // We add a recipient (a shared key or public key). ->build(); // We build it $serializer = new CompactSerializer(); $token = $serializer->serialize($jwe, 0); return json_encode(['encData' => $token], JSON_PRETTY_PRINT); } /** * This method will decrypt the given JWE token. * * @param $encryptedPayload - JWE Token * @param $mleClientPrivateKeyPath * @return string|null */ function decryptJwe($encryptedPayload, $mleClientPrivateKeyPath) { // The key encryption algorithm manager with the RSA-OAEP-256 algorithm. $keyEncryptionAlgorithmManager = new AlgorithmManager([new RSAOAEP256(),]); // The content encryption algorithm manager with the A128GCM algorithm. $contentEncryptionAlgorithmManager = new AlgorithmManager([new A128GCM(),]); // The compression method manager with the DEF (Deflate) method. $compressionMethodManager = new CompressionMethodManager([new Deflate(),]); // We instantiate our JWE Decrypter. $jweDecrypter = new JWEDecrypter($keyEncryptionAlgorithmManager, $contentEncryptionAlgorithmManager, $compressionMethodManager); // Our key. $jwk = JWKFactory::createFromKeyFile($mleClientPrivateKeyPath); $encryptedPayload = json_decode($encryptedPayload, true); $token = $encryptedPayload['encData']; $serializerManager = new JWESerializerManager([new CompactSerializer(),]); $jwe = $serializerManager->unserialize($token); $success = $jweDecrypter->decryptUsingKey($jwe, $jwk, 0); if ($success) { $jweLoader = new JWELoader( $serializerManager, $jweDecrypter, null ); $jwe = $jweLoader->loadAndDecryptWithKey($token, $jwk, $recipient); return $jwe->getPayload(); } else { throw new RuntimeException('Error Decrypting JWE'); } } function invokeAPI($url, $method, $username, $password, $keyId, $clientCertPath, $clientPrivateKey, $mleClientPrivateKeyPath, $payload = '') { $curl = curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 2); if ($method == 'POST') { curl_setopt($curl, CURLOPT_POST, 1); } if ($payload != '') { curl_setopt($curl, CURLOPT_POSTFIELDS, $payload); } curl_setopt($curl, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Accept: application/json', 'keyId: ' . $keyId )); curl_setopt($curl, CURLOPT_PORT, 443); curl_setopt($curl, CURLOPT_VERBOSE, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 2); curl_setopt($curl, CURLOPT_SSLVERSION, 1); curl_setopt($curl, CURLOPT_SSLCERT, $clientCertPath); curl_setopt($curl, CURLOPT_SSLKEY, $clientPrivateKey); curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($curl, CURLOPT_USERPWD, $username . ":" . $password); //enable headers curl_setopt($curl, CURLOPT_HEADER, 1); curl_setopt($curl, CURLOPT_URL, $url); $response = curl_exec($curl); $response_info = curl_getinfo($curl); // close curl resource to free up system resources $http_header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); curl_close($curl); $http_header = httpParseHeaders(substr($response, 0, $http_header_size)); // Print all headers as array echo "<pre>"; print_r($http_header); echo "</pre>"; if ($response_info['http_code'] === 0) { $curl_error_message = curl_error($curl); // curl_exec can sometimes fail but still return a blank message from curl_error(). if (!empty($curl_error_message)) { $error_message = "<br/><br/>API call to $url failed: $curl_error_message"; } else { $error_message = "<br/><br/>API call to $url failed, but for an unknown reason. " . "This could happen if you are disconnected from the network."; } echo $error_message; } elseif ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299) { echo "<br/><br/>Your call returned with a success code - " . $response_info['http_code'] . ""; } else { echo "<br/><br/>[HTTP Status: " . $response_info['http_code'] . "]\n[" . $response . "]"; echo "<br/><br/>Error connecting to the API ($url)"; } return substr($response, $http_header_size); } function httpParseHeaders($raw_headers) { $headers = []; $key = ''; foreach (explode("\n", $raw_headers) as $h) { $h = explode(':', $h, 2); if (isset($h[1])) { if (!isset($headers[$h[0]])) { $headers[$h[0]] = trim($h[1]); } elseif (is_array($headers[$h[0]])) { $headers[$h[0]] = array_merge($headers[$h[0]], [trim($h[1])]); } else { $headers[$h[0]] = array_merge([$headers[$h[0]]], [trim($h[1])]); } $key = $h[0]; } else { if (substr($h[0], 0, 1) === "\t") { $headers[$key] .= "\r\n\t" . trim($h[0]); } elseif (!$key) { $headers[0] = trim($h[0]); } trim($h[0]); } } return $headers; } $localTransactionDateTime = date_format(new DateTime(), "Y-m-d\TH:i:s");; $payload = '{ "product": "VD", "useCase": "B2C", "requestReason": { "references": [ { "referenceType": "INVOICEID", "referenceDate": "'. $localTransactionDateTime . '", "referenceValue": "1234567890" } ], "paymentPurpose": "SVCS" }, "paymentRequests": [ { "debtorLastName": "B.", "debtorAlias": "447709123457", "debtorAgentCountry": "UA", "debtorCountry": "UA", "requestedAmount": "100.00", "requestedAmountCurrency": "UAH", "endToEndId": "RFPid0001", "debtorFirstName": "John", "debtorAgentId": "VD123445", "debtorAliasType": "MOBL" } ], "dueDate": "2024-03-17", "requestMessageId": "GG9983636387737JH", "settlementOptions": [ { "settlementSystem": "VISA_DIRECT", "primaryAccountNumber": "4145124125553222" } ], "creditor": { "creditorCountry": "UA", "creditorAgentId": "12379879797989", "creditorAgentCountry": "UA", "creditorBusinessName": "Mini-Corp Inc.", "creditorAlias": "1231231234", "creditorLastName": "F.", "creditorMcc": "1234", "creditorAliasType": "MOBL", "creditorId": "BL1234567890", "creditorIdType": "Agent", "creditorTaxId": "HMRC1234567890", "creditorFirstName": "Alex" }, "creationDateTime": "' . $localTransactionDateTime . '" }'; echo '.................END Initiate API Call...........................' . "\xA"; echo '.................START END Initiate API Call.......................' . "\xA"; $encryptedData = encryptPayload($payload, $keyId, $mleServerPublicCertificatePath); $url = 'https://sandbox.api.visa.com/rtx/api/v1/requestToPay'; $body = invokeAPI($url, 'POST', $username, $password, $keyId, $client_cert, $private_key, $mleClientPrivateKeyPath, $encryptedData); $responsePayload = decryptJwe($body, $mleClientPrivateKeyPath); echo 'Response Payload:' . "\xA"; $pushFundsResponse = json_decode($responsePayload, 1); print_r($pushFundsResponse); echo '.................END Initiate API Call.........................' . "\xA"; // $acquiringBin = '408999'; // $transactionIdentifier = $pushFundsResponse['transactionIdentifier']; // $queryString = '?acquiringBIN=' . $acquiringBin . '&transactionIdentifier=' . $transactionIdentifier; // $url = 'https://sandbox.api.visa.com/visadirect/v1/transactionquery' . $queryString; // echo '.................START Query API Call.........................' . "\xA"; // $body = invokeAPI($url, 'GET', $username, $password, $keyId, $client_cert, $private_key, $mleClientPrivateKeyPath); // $responsePayload = decryptJwe($body, $mleClientPrivateKeyPath); // echo 'Response Payload:' . "\xA"; // print_r(json_decode($responsePayload)); // echo '.................END Query API Call.........................' . "\xA";

2 REPLIES 2
SyedSa
Community Moderator

Re: Testing request to pay (intiate api) using PHP

Hi @ChefaneThank you for reaching out. One of our agents will look into this and get back to you soon. Until then, if any community members know a solution, please feel free to reply to this thread.

API_Managers
Visa Developer Support Specialist

Re: Testing request to pay (intiate api) using PHP

Hi @Chefane,

 

You're receiving this error due to a business restriction. There is a process for onboarding customers for this API. Please send an email to Visa Developer Support at developer@visa.com to inform them of this issue.




Thanks,

Tee



Was your question answered? Don't forget to click on "Accept as Solution" to help other devs find the answer to the same question.