DEV Community

Cover image for Rapyd API Request Signatures in PHP
Drew Harris for Rapyd

Posted on • Edited on • Originally published at community.rapyd.net

Rapyd API Request Signatures in PHP

By Amr Abdou

Rapyd is a global payment-processing platform that provides developers with secure and easy-to-use payment solutions that work with over 190 countries. As a global payment services provider, Rapyd is continuously developing new and innovative ways to facilitate online transactions.

The Rapyd API offers a wide range of services that can be used by businesses to accept, and disburse payments, hold funds and issue payment cards. Some of the services offered via the Rapyd API include the following:

  • Rapyd Collect: to accept payments from customers in their own currency
  • Rapyd Disburse: to disburse payments to vendors and suppliers
  • Rapyd Wallet: to create branded e-wallets to send, receive, and store money
  • Rapyd Issuing: to create virtual and physical payment cards and create loyalty programs
  • Rapyd Point-of-Sale (POS): to offer countertop, wireless, and mobile card machines
  • Rapyd Verify: to gather business information in order to perform KYB verification

In this article, you'll learn how to implement request signatures in PHP in order to authenticate and send requests to the Rapyd API. To do so, you'll create a fresh PHP application that sends requests to the Rapyd API to retrieve the available payment methods for a specific country and displays the response in HTML. PHP powers applications like Facebook, Wordpress, Wikipedia, Slack, Mailchimp, and Etsy. Creating an integration with the Rapyd API can help connect applications around the world.

Implementing API Requests to the Rapyd API

A secure connection is necessary when it comes to online payment processing and money transfers. For your requests to be authenticated securely by the Rapyd platform, you must include specific header parameters in the API requests, which you'll learn about more in the following section.

One of these parameters is the signature that is used to verify that the request is coming from an authorized source and has not been tampered with during transmission. In this article, you'll learn how to generate signatures to authorize Rapyd API requests by completing the following actions:

Prerequisites

To follow this tutorial and create signatures using the Rapyd API, you need to have PHP 8+ and Composer installed on your local machine. You also need a Rapyd account. If you haven't created a Rapyd account yet, go ahead and sign up.

Obtaining Your API Keys

To retrieve your API keys, log in to your Rapyd account and activate the Sandbox button at the top right corner of your account dashboard.

Sandbox button

Then, open the Developers menu on the left-hand side of your screen to retrieve your Sandbox credentials. Copy these credentials so you can use them as environment variables later in this tutorial:

Rapyd Developer Dashboard API keys

Create a Fresh PHP App

To create a fresh PHP app, create a new folder for this project and create these three files inside it:

  1. .env: to store the environment variables
  2. utilities.php: to include the logic for authorizing and sending API requests
  3. get_payment_methods.php: to create a function that retrieves payment methods by country

To set the API keys as environment variables, you need to install the phpdotenv package using Composer. Navigate to the project folder in your terminal and run the following command.

composer require vlucas/phpdotenv
Enter fullscreen mode Exit fullscreen mode

Set Environment Variables

The .env file holds the environment variables that your application will use to authorize the API requests. The two environment variables you'll use here are the API key and the secret key.

To add your API key and secret key as environment variables, open the .env file and paste the following code into it:

ACCESS_KEY={your-access-key-here}
SECRET_KEY={your-secret-key-here}
Enter fullscreen mode Exit fullscreen mode

Remember to replace {your-access-key-here} with your access key and {your-secret-key-here} with your secret key.

Create a Utilities File

The utilities.php file contains the logic to create the request signatures and authorize and send HTTP requests.

Open the utilities.php file and paste the following code:

<?php
require __DIR__ . '/vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

function generate_string($length=12) {
    $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    return substr(str_shuffle($permitted_chars), 0, $length);
}


// make_request method - Includes the logic to communicate with the Rapyd sandbox server.
function make_request($method, $path, $body = null) {
    $base_url = 'https://sandboxapi.rapyd.net';
    $secret_key = $_ENV['SECRET_KEY'];     // Never transmit the secret key by itself.
    $access_key = $_ENV['ACCESS_KEY'];     // The access key received from Rapyd.

    $idempotency = generate_string();      // Unique for each request.
    $http_method = $method;                // Lower case.
    $salt = generate_string();             // Randomly generated for each request.
    $date = new DateTime();
    $timestamp = $date->getTimestamp();    // Current Unix time.

    // Generate Signature
    $body_string = !is_null($body) ? json_encode($body,JSON_UNESCAPED_SLASHES) : '';
    $sig_string = "$http_method$path$salt$timestamp$access_key$secret_key$body_string";

    $hash_sig_string = hash_hmac("sha256", $sig_string, $secret_key);
    $signature = base64_encode($hash_sig_string);


    $request_data = NULL;

    if ($method === 'post') {
        $request_data = array(
            CURLOPT_URL => "$base_url$path",
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $body_string
        );
    } else {
        $request_data = array(
            CURLOPT_URL => "$base_url$path",
            CURLOPT_RETURNTRANSFER => true,
        );
    }

    $curl = curl_init();
    curl_setopt_array($curl, $request_data);

    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json",
        "access_key: $access_key",
        "salt: $salt",
        "timestamp: $timestamp",
        "signature: $signature",
        "idempotency: $idempotency"
    ));

    $response = curl_exec($curl);
    $err = curl_error($curl);
    curl_close($curl);

    if ($err) {
        throw new Exception("cURL Error #:".$err);
    } else {
        return json_decode($response, true); 
    }
}
?>
Enter fullscreen mode Exit fullscreen mode

This code includes two functions: generate_string and make_request. The generate_string function generates a random string that is used to create the idempotency, salt, and signature values that are required to authorize the API request. The make_request function creates and sends an API request. This function takes three arguments: the HTTP method, the request URI path, and the request body.

Each Rapyd API request includes the following header parameters:

  • access_key: This is your sandbox API access key.
  • content-Type: This is used to indicate that the data is sent in JSON format.
  • salt: This is a random string generated for each request. This string should be eight to sixteen digits, including special characters. This is a necessity as it's used to generate the request signature.
  • timestamp: This is a timestamp for each request in UNIX format.
  • idempotency: This is an optional parameter to test for idempotency. If this value is the same in another request within twenty-four hours, the second request is ignored and the response of the first request is returned.
  • signature: This is a unique signature calculated for each request and is vital for ensuring each request is secure.

Calculate the Signature

The request signature is a critical parameter for the security of your requests because it helps secure the requests in these three ways:

  • Verifying the requester
  • Protecting data from tampering in transit
  • Rejecting requests from unauthorized users

The Rapyd API request signature is calculated as a hash of a concatenation of strings according to this formula:

BASE64 ( HASH ( http_method + url_path + salt + timestamp + access_key + secret_key + body_string ) )
Enter fullscreen mode Exit fullscreen mode

Here, BASE64 is a Base64 encoding algorithm, and HASH is the HMAC-SHA256 cryptographic authentication algorithm.

In the utilities.php file, the following code is responsible for generating the request signature according to the Rapyd API signature formula:

$body_string = !is_null($body) ? json_encode($body,JSON_UNESCAPED_SLASHES) : '';
$sig_string = "$http_method$path$salt$timestamp$access_key$secret_key$body_string";

$hash_sig_string = hash_hmac("sha256", $sig_string, $secret_key);
$signature = base64_encode($hash_sig_string);
Enter fullscreen mode Exit fullscreen mode

In this code snippet, the hash_hmac PHP function generates the hash value of the signature string using HMAC-SHA256 algorithm, and the base64_encode PHP function encodes the hash value with the Base64 encoding algorithm.

When you send a request to Rapyd API, the Rapyd platform creates a signature using the same calculation. If the signatures don't match due to an incorrect formula, the request is rejected and an UNAUTHENTICATED_API_CALL error is returned.

Write a Function to Retrieve the Available Payment Methods

In order to be able to test the API authorization using the header parameters and the signature that you generated, you need to create a method to fetch the available payment methods for a specific country.

To do so, open the get_payment_methods.php file and paste the following code in it:

<?php
require __DIR__ . '/utilities.php';
require __DIR__ . '/vendor/autoload.php';

// Get Payment Methods by Country Function
function get_payment_methods_by_country($country_code) {
    $method = 'get';
    $path = '/v1/payment_methods/country?country=' . $country_code;

    // Make the API request
    try {
        return $result = make_request($method, $path);
    } catch(Exception $e) {
        return 'Message: ' .$e->getMessage();
    }
}


// Generate HTML
function generate_payment_methods_html($country_code) {
    $payment_methods = get_payment_methods_by_country($country_code);

    if($payment_methods['data']) {
        // Create the HTML Head
        echo '<!DOCTYPE html>
        <html>
        <head>
        <title>Payment Methods by Country</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
        </head>
        <body>';

        echo '<div class="row">';
        echo '<div class="col-md-2"></div>';
        echo '<div class="col-md-8">';

        echo '<h2>Available Payment Methods</h2>';
        echo '<table class="table table-bordered table-striped">';
        echo '<tr>';
        echo '<th>Name</th>';
        echo '<th>Type</th>';
        echo '<th>Currencies</th>';
        echo '</tr>';

        // Loop The Response
        foreach ($payment_methods['data'] as $key => $value) {
            echo '<tr>';
            echo '<td>'. $value['name'] .'</td>';
            echo '<td>'. $value['type'] .'</td>';
            echo '<td>'. implode(" ", $value['currencies']) .'</td>';
            echo '</tr>';
        }

        echo '</table>';

        // Print the Response data array
        echo '<h2>Response Data</h2>';
        echo '<code>';
        var_dump($payment_methods['data']);
        echo '</code>';

        echo '</div>';
        echo '<div class="col-md-2"></div>';
        echo '</div>';
        echo '</body>';


    }
    else {
        echo $payment_methods;
    }
}


// Get Available Payment Methods in the UK
generate_payment_methods_html('GB');
Enter fullscreen mode Exit fullscreen mode

This code starts by importing the utilities.php file and a composer instance. The get_payment_methods_by_country function retrieves payment methods available in a particular country using the make_request function, which is declared in the utilities.php file. The function takes one parameter, $country_code.

The generate_payment_methods_html is a function that generates a basic HTML code to display the payment methods returned in a table and the response data object of the API request in a <code> block below the table.

Rapyd API uses two-letter ISO country codes that you'll use when you call the function. Since, in this example, you're fetching the available payment methods in the UK, the country code is "GB".

Finally, the get_payment_methods_by_country function is called with the GB parameter as its only argument to retrieve payment methods available in the UK.

Run and Test the Application

Now it's time to run and test your application. You can test the app by navigating to the project folder in your terminal and starting the PHP development server using this command:

php -S localhost:8000
Enter fullscreen mode Exit fullscreen mode

Then, open your browser and navigate to http://localhost:8000/get_payment_methods.php.

Once the request is done, the available payment methods in the UK will be listed in a table, and the full response will be displayed as an array:

Available payment methods in the UK test result

All the code for this sample application is available in this GitHub repo.

Conclusion

In this article, you learned how to create Rapyd API request signatures in PHP and why they're important.

Rapyd is a global payment platform with a mission to liberate global commerce with all the tools you need to accept, hold, and disburse funds for businesses everywhere. Rapyd's API offers a broad range of services that can be used by businesses to collect payments from customers, disburse payments to vendors and suppliers, create virtual and physical payment cards, and perform real-time business verification checks.

Top comments (1)

Collapse
 
dotenv profile image
Dotenv

Great writeup! Just one important thing to note. I recommend using $_SERVER rather than $_ENV.

"Values can come up blank (yikes!) and load works differently than the other major dotenv libraries. Luckily, the fix is straightforward. Use $_SERVER - don’t use $_ENV or getenv. Use safeLoad() - don’t use .load()""

dotenv.org/blog/2023/11/07/phpdote...