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";
Hi @Chefane, Thank 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.
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.