# Welcome to Rocketfuel

Easiest way to pay with crypto and bank transfers

RocketFuel is global payments processing company offering highly efficient one-click check-out solutions using Bitcoin, other cryptocurrencies, and bank transfers to merchants and their customers.

RocketFuel’s solution focuses on enhanced customer privacy protection eliminating the risk of a data breach while improving speed, security, and ease of use. Users can enjoy seamless check-out using their favorite cryptocurrencies or direct bank transfers and forget the clunky cart paradigm of the past. Merchants can implement new impulse buying schemes and generate new sales channels unavailable in current eCommerce solutions.

### Why Use RocketFuel

![](/files/42fyXdD3ZHIcfS2mZXO0)


# Core Concepts


# Overview

This guide helps you understand the core concepts used to structure RocketFuel API data. Understanding these core concepts will make it easier for you to work with our resources and build integrations with the RocketFuel APIs. It's helpful to understand these terms within our platform and how they relate to each other.

**Core Concepts**

1. Partners
2. Merchants
3. Shoppers
4. Exchanges
5. QR Payments
6. Bank Payments
7. Invoices
8. Settlements

Partners introduce merchants to RocketFuel's bank transfer and volatility-proof cryptocurrency payment solution and earn a commission on every transaction they process. Merchants can choose to sign up on RocketFuel's system by visiting the link [https://merchant-sandbox.rocketfuelblockchain.com](<https://merchant-sandbox.rocketfuelblockchain.com&#xD;&#xA;>). They can offer their goods/services on their website and accept payments in Cryptocurrency or via bank using RocketFuel's solution. Shoppers are the customers who buy goods or services from merchants and pay them in exchange for goods/services they are purchasing.

When shoppers pay to merchants, they can connect their exchanges, such as Coinbase, OkCoin, Gemini, etc. and pay using those exchanges. Also, the other payment options available to shoppers are from their crypto wallet by scanning the QR code or bank. For bank payments, shoppers will need to connect their bank account.

Invoices help merchants use RocketFuel's solution outside their website, and shoppers can just visit an invoice link to make the payment.

All the money earned by the merchants using RocketFuel's solution is settled daily to the merchants by RocketFuel.


# Partners

Partners introduce merchants to RocketFuel's bank transfer and volatility-proof cryptocurrency payment solution and earn a commission on every transaction they process.

![](/files/xr8HQIkam9juz4QhsxjV)


# Merchants

Merchants can choose to sign up on RocketFuel's system by visiting the link [https://merchant-sandbox.rocketfuelblockchain.com](<https://merchant-sandbox.rocketfuelblockchain.com&#xD;&#xA;>). They can offer their goods/services on their website and accept payments in Cryptocurrency or via bank using RocketFuel's solution.

Once a merchant is registered with RocketFuel, they are given a <mark style="color:red;">`merchant_id`</mark>. They are also given authorization keys to access our APIs.&#x20;

With a host of benefits like low fees, protection from crypto price volatility, a feature-rich dashboard, invoice generation, and no chargebacks, RocketFuel provides the most competitive and advanced payment service to merchants who wish to accept payments in crypto and bank transfers.

Merchants can receive payment in 120+ cryptocurrencies.

![120+ crypto options to receive payment](/files/Eu7OQuOSX3Krmtq0OjpS)


# Shoppers

Shoppers are the customers who buy goods or services from merchants and pay them in exchange for goods/services they are purchasing.

Shoppers are the ones who will have to connect their crypto exchange and bank to make payments using RocketFuel's solution.

A shopper can choose to sign up and have a RocketFuel account or can also be a guest shopper. A regular shopper has their own shopper portal once they sign up, and they can check/track their transactions, request refunds, and set default exchange and currency for their iframe. A guest shopper does not have these functionalities.

A shopper can sign up on RocketFuel by visiting the link [https://shopper-sandbox.rocketfuelblockchain.com.](<https://shopper-sandbox.rocketfuelblockchain.com&#xD;&#xA;>)

![RocketFuel Shopper Portal](/files/dvgjKWqrSsd4Jg4wjfvq)

![](/files/OOcylgk9aFHpYpGLcvKD)


# Exchanges

Cryptocurrency exchanges facilitate the trading of cryptocurrencies for other assets, including digital and fiat currencies. In effect, cryptocurrency exchanges act as an intermediary between a buyer and a seller and make money through commissions and transaction fees.

When shoppers pay to merchants, they can connect their exchanges, such as Coinbase, OkCoin, Gemini, etc., and pay using those exchanges.

The balance is also tracked and shown on iFrame for each cryptocurrency available in the exchange to make the shoppers aware of the same.

![](/files/3CvkzxRh9jKsbWKIpTMo)


# QR Payments

The other payment options available to shoppers are from their crypto wallet by scanning the QR code showing up on iFrame. They can also copy the QR code address and paste it into their wallet app to make the payment.

![](/files/C459YgUZpGN3xOy9DrnZ)


# Bank Payments

Besides crypto payments, shoppers can pay from their bank by connecting their bank accounts. Only payments in USD can be made using bank transfers for now.&#x20;

The bank accounts are linked to the RocketFuel solution using Plaid. Therefore, the safety of shoppers is not compromised.

![](/files/G78SDHBxurxLanxhsd6j)


# Invoices

Invoices help merchants use RocketFuel's solution outside their website, and shoppers can visit an invoice link to make the payment using crypto exchange/wallet or bank transfers.

We are working on an invoice payment tracking feature, after which merchants will be able to track the payment status of an invoice.

Merchants who don't want to use iFrame for payment solutions can use our hosted checkout solution.

![](/files/xAQtdKsQu0DDzbjoGa9x)


# Settlements

All the money earned by the merchants using RocketFuel's solution is settled to the merchants by RocketFuel daily. Merchants have the option to go through their Remittance report to reconcile the amount they have received from RocketFuel.


# Bigcommerce

## How to Setup Rocketfuel on Bigcommerce

BigCommerce is a powerful, open Saas (Software-as-a-service) platform that lets you build your own custom online stores. With our integration, you can now use Rocketfuel as a payment provider in your store, and accept payments anywhere in the world. Here's how to set it up and get started!

Note: To install the app on your BigCommerce store, your store must be using BigCommerce's [Stencil Themes](https://support.bigcommerce.com/s/article/Stencil-Themes) and [Optimized One Page Checkout](https://support.bigcommerce.com/s/article/Optimized-Single-Page-Checkout)

**Step 1:**\
Go to BigCommerce Dashboard → Store Setup → Payments

![](/files/98qfYAeu6R2NBNLGzzb8)

**Step 2:**\
Select Offline Payment Methods → Choose Money Order and click Setup

![](/files/7VPstBkNqwKLQbyYQj4u)

**Step 3:**\
Choose the Display Name like, 'Pay with Rocketfuel for Crypto'.

You can also select countries where you want the payment option to be available.

Also, you can set the message that is displayed after payment by changing the text in Payment information. \
For example, you can change it to\
'Your order has been received, An email will be sent containing information about your purchase'

Click Save.

![](/files/WSN4xJnC1a9ZWMsIAvTT)

**Step 4:**

Search Rocketfuel app from BigCommerce Store.

Click ‘Get This App’.

It will automatically redirect to sign in to your store

Click ‘Install’

You will see a screen as shown below:

Check mark the option and click ‘Confirm’.

![](/files/xTPyiqymztLp674jAATV)

**Step 5:**

Once you click ‘Confirm’, you will be directed to ‘Welcome To Rocketfuel’ page.

For filling in mandatory details, go to [Merchant Dashboard](https://merchant.rocketfuelblockchain.com/sign-in), you will get Merchant ID and Public key mentioned there.

Come back to the app page and fill in the Email, Password, Merchant ID and Public key.

You can select an environment as Sandbox or Production.

Click 'Save Details'

Note: You have to select the details like Email, Password, Merchant ID and Public Key based on the environment you choose to work on.

Congratulations!!! You are now all set to receive Payments.

![](/files/eiAtdzN4zXlTzq4MndTF)

### CALLBACK URL

To get transaction update from Rocketfuel, you will need to fill in your callback url on the portal. Follow this [link](https://docs.rocketfuelblockchain.com/user-guide-and-help-videos/merchant-user-guide/settings) to setup your callback url. \
You can find the callback url highlighted red on the "Welcome to Rocketfuel" page on the Bigcommerce App.

### ORDER STATUS

When an order is placed on Bigcommerce through Rocketfuel, it will initially be marked **incomplete** on Bigcommerce until the payment is confirmed by Rocketfuel.

### EMAIL SETTINGS

To change the email template, navigate to Marketing -> Transactional Emails.\
![](/files/IKhgnycegXCJUo9pw4Rr)


# Magento

## How to install Rocketfuel Module for Magento

**Pre-requisite:**\
1\. A Magento store\
2\. A verified merchant account on Rocketfuel.\
3\. Composer installed on server

**STEPS TO INSTALL MAGENTO MODULE IN YOUR STORE**

**Step 1:**\
Run `composer require rkfl/module-rocketfuel-payment-magento2` in the root directory of your store.

This will install the module in the vendor folder of your server.

**Step 2:**\
Run `php bin/magento module:enable RKFL_Rocketfuel` to enable the module.

Then run\
`php bin/magento setup:upgrade` to ensure the module is properly installed.

### **STEPS TO SETUP MERCHANT DETAILS**

After successfully installing the module, the next phase is to set up the merchant details.

**Step 1:**\
Visit your store's admin dashboard - (usually at https\://{your\_store\_url}/admin).\
On Admin Dashboard, Click on Stores

In Stores, select Sales

![](/files/yOus9XQ9IIjgcoxzbe82)

**Step 2:**\
Click on Payments Methods

![Once you click Payment Methods, you should be able to see Rocketfuel Payment Gateway, listed as one of the available payment gateways.](/files/fYhk5Zh2cTcJ1fpePvk2)

Click the down arrow on the extreme right side of ' Rocketfuel Payment Gateway ' to fill the details.

To find the Merchant details to be filled in here, follow the instructions given below along with the screenshot

### **HOW TO RETRIEVE MERCHANT DETAILS**

The Email and Password refers to the email/password you use in signing into your merchant portal on <https://merchant.rocketfuel.inc/sign-in>.

The environment refers to the type of details you are using. You should choose production for real transactions and select sandbox when you are testing.

To retrieve Public Key, visit <https://merchant.rocketfuel.inc/settings> and copy the string highlighted in the screenshot below.

![](/files/qZEJkeJGJ0JzxNlurKsY)

Next, click on "Save Config" to save the details to your store Database.

![](/files/zNitzq92srEYIN9zBoZC)


# PrestaShop

## How to install Rocketfuel Module for Prestashop

**Pre-requisite:**

1\. A Prestashop store (version 1.7 or higher)

2\. A verified merchant account on Rocketfuel.

**MODULE INSTALLATION**

**Step 1:**

From your admin dashboard, navigate to Modules Manager and click on “Upload a Module”

![](/files/lcsgwM4ObqjiTdujszqb)

**Step 2:**\
Download the plugin (v2.0.0) from the given URL <https://bitbucket.org/rocketfuelblockchain/rocketfuel-plugin-prestashop/get/07358a48a9f4821c994642ce387a30a274f2cad5.zip>. Open the zip file and upload the rocketfuel.zip to Prestashop.

<figure><img src="/files/RGui7Q6Lbyoetu50a1C5" alt=""><figcaption></figcaption></figure>

Upload the rocketfuel.zip file as shown in the screenshot below.

![](/files/ZSC59eLf6Xi6QKOXOAOz)

**Step 3:**

Next click on Configure to proceed to the next step

![](/files/0i57PR0Kt04y0plv4VWj)

**MERCHANT DETAILS SETUP**

After successfully uploading and installing the module, the next phase is to set up the merchant details. You need to be registered as a Merchant on <https://merchant.rocketfuel.inc> to start using the service.

**Step 1:**

Visit your admin dashboard and click on Stores, then Sales.

![](/files/g8gDmaPIiuSukyyJSTms)

**GETTING MERCHANT DETAILS**

![](/files/G7K5bfVxuoZBxvdY2DBb)

1. Navigate to your Rocketfuel merchant account and click on settings (<https://Merchant.rocketfuel.inc/settings>).

* Copy the merchant ID and Public Key into the appropriate fields on the plugin.
* Also, fill in the Email and password for your merchant account into the appropriate field
* You can generate a new public key If you do not have any setup for you

![](/files/X6hGnniLGVHxM2dVCq4z)

2\. Save changes. Click on “Save” to save your details.

![](/files/Bylf6EvFyKvGMxnbnbDg)

**Callback URL**

Copy the Callback URL and save in your Rocketfuel Merchant Account.

To save the callback URL on your merchant account, navigate to <https://Merchant.rocketfuel.inc/settings>[ ](https://merchant.rocketfuelblockchain.com/settings/)and click on edit

![](/files/9vJiyojRUeAX1D1Vgo07)

Add in the callback URL you copied on Prestashop and click Save.


# WooCommerce

How to install Rocketfuel Gateway Plugin on Woocommerce

**Pre-requisite:**\
\
1\. WooCommerce installed on your WordPress website\
2\. A verified merchant account on Rocketfuel.

### **STEPS TO INSTALL WOOCOMMERCE PLUGIN**

**Step 1:**\
Visit your admin dashboard and click on Plugins then 'Add New'

![](/files/GXTL0IzIGkfdyOAKp0SU)

**Step 2:**\
Type in "Rocketfuel Payment" in the search box and click on "Install now" on the plugin with Rocketfuel Logo.

![](/files/h5pB0lMJrjf0d9g96IHU)

Afterwards, click on "Activate"

![](/files/6pD4mARcyMFvooItYFXD)

After successfully installing and activating the plugin, proceed to set up the merchant details on woocommerce.

### **STEPS TO SETUP MERCHANT DETAILS**

\
**Step 1:**\
Click on WooCommerce menu, then click on settings.

![](/files/Tr8aOCCDaiwbQz3qYdKq)

Next click on payment.

![](/files/kiAvymstdJXBXZJUUezM)

**Step 2:**

Once you reach the Payments settings, enable the toggle button, as shown below in the screenshot.

Click ‘Manage’

![](/files/AG6vXd8RmyPlqVxogQZK)

**Step 3:**\
On clicking ‘Manage’, it will take you to the next page, where you can fill your Merchant details.

<figure><img src="/files/WA6rBZrjKiB2crYNYkwz" alt=""><figcaption></figcaption></figure>

**Step 4:**\
Merchant can go to store settings > Button Text and change the button to say anything - Pay with Bank, Pay with Crypto and Bank, etc.

<figure><img src="/files/YwrSkAlxCX2NerOFcx6z" alt=""><figcaption></figcaption></figure>

### STEPS TO GET MERCHANT DETAILS

![](/files/rHVcukO1DWslGCZBJ0ho)

Please refer to the instructions given below:\
**Step 1:**

Navigate to your Rocketfuel merchant account and click on settings ([https://merchant.rocketfuel.inc/settings](https://Merchant.rocketfuel.inc/settings)). You will see Merchant ID and Public Key on the page. Copy and Paste in the ‘Payments’ page. Also, fill in the Client Id and Client Secret for your merchant account into the appropriate field. You can generate a new public key, If you do not have any setup for you.

![](/files/Zccy4IC5SdQee4rhdv0x)

The ‘Callback URL’ will be auto generated. Copy the URL, to be used as per the instructions given below.

Click ‘Save Changes’.

**Step 2:**

The Callback URL, you copied, has to be saved in the Rocketfuel Merchant Account.

To do this, navigate to <https://Merchant.rocketfuel.inc/settings> and click on edit, as shown in the screenshot below:

![](/files/GHlhkEienCHgP7Bbogdw)

**Step 3:**

Add the Callback URL on the screen you see once you click ’Edit'.

Click ‘Save’.

![](/files/Hz5OmMhvXI90ejWUIYu7)

### **Features**

**1. Order Status for Completed Payment:**

This gives you control over the order status set by the plugin when payment is confirmed.

<figure><img src="/files/hjIIP3ks3S5sywg4cBJB" alt=""><figcaption></figcaption></figure>

**2. Working Environment:**

You can set the working environment endpoint using this selection

<figure><img src="/files/U29fFxxCArxU2XIpjIyR" alt=""><figcaption></figcaption></figure>

**3. Plugin Details:**

You can get the merchant Id from your portal at <https://merchant.rocketfuel.inc/settings>

**a. Merchant ID** - This can be found at the top left of the settings page

<figure><img src="/files/gEbEblt6eGyAoj60gmJH" alt=""><figcaption></figcaption></figure>

**b. Client Id and Client Secret** - To obtain these keys, scroll down on the settings page till you see **"Integration Keys".** Click on create and you can copy the Client secret and Client Id  and add it to the plugin configuration page

<img src="/files/ci1ZP4uaHOw5uNDbwR5W" alt="" data-size="original">\
**c. Public key** - Copy the public key on the settings page by clicking on the copy icon\
![](/files/cE2TA6zSTzjTmW069eHS)


# Webflow

Integrate Rocketfuel on Webflow

{% hint style="warning" %}
To be depricated soon!
{% endhint %}

To integrate Rocketfuel on Webflow, you need the below

i. Custom place order button on the checkout page.

ii. JS SDK on the checkout page.

iii. Two Backend endpoints. One generates invoice links and the other receives webhooks to update transactions after payment confirmation.

### Place Order Button

This can be added through webflow, anywhere on the checkout page. The button must have an id of `rocketfuel-payment-button`.This will trigger the payment iframe on click.

### Checkout JS SDK <a href="#checkout-js-sdk" id="checkout-js-sdk"></a>

Add the below&#x20;

```javascript
const currentHostDomain = new URL(window.location.href).origin
function updateOrder(result) {
		let status = "pending";
		let result_status = parseInt(result.status);
		switch (result_status) {
			case 101:
				status = "partial-payment";
				break;
			case 1:
				status = "completed";
				break;
			default:
				status = "failed";
				break;
		}
		const url = 'ENDPOINT_TO_UPDATE_WEBFLOW_ORDER';
		const options = {
			method: 'POST',
			body: JSON.stringify({
				"status": status,
				"order_id": rocketFuelOptions.order.id
			}),
			headers: {
				'Content-Type': 'application/json'
			}
		}
		let response = fetch(url, options);
	}
    let rocketFuelOptions = {
        order: {},
        rkfl: {},
        iframe_url: 'https://iframe.rocketfuelblockchain.com',
        fetch_url: ''
    }

async function getUUID() {
    let body = getCartFunctionData();
    url = 'BACKEND_URL_TO_GET_UUID';
    const options = {
        method: 'POST',
        body: JSON.stringify(body),
        headers: {
            'Content-Type': 'application/json'
        }
    }
    let response = await fetch(url, options);

    let result = await response.json();
    return result.uuid;
}
async function start() {
    let csrf = document.cookie.split('csrf=')[1].split(';')[0]

    let apolloEndpoint = `${currentHostDomain}/.wf_graphql/apollo`;
    let response = await fetch(apolloEndpoint, {
        method: "post", headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-wf-csrf': csrf, 'Content-Type': 'application/json' }, body: JSON.stringify([{
            operationName: 'Dynamo2',
            variables: {},
            query: 'query Dynamo2 { database { id commerceOrder { availableShippingMethods { description id mode name price { value unit decimalValue string } selected } comment customData { checkbox name textArea textInput } customerInfo { identity { email fullName } } extraItems { name pluginId pluginName price { value unit decimalValue string } } id paymentProcessor startedOn statusFlags { billingAddressRequiresPostalCode hasDownloads hasSubscription isFreeOrder needAddress needIdentity needItems needPayment requiresShipping shippingAddressRequiresPostalCode shouldRecalc } subtotal { value unit decimalValue string } total { value unit decimalValue string } updatedOn userItems { count rowTotal { value unit decimalValue string } sku { f__draft_0ht f__archived_0ht f_main_image_4dr { url file { size origFileName createdOn updatedOn mimeType width height variants { origFileName quality height width s3Url error size } } alt } f_sku_values_3dr { property { id } value { id } } id } product { id f__draft_0ht f__archived_0ht f_name_ f_sku_properties_3dr { id name enum { id name slug } } } id } userItemsCount } } site { id commerce { businessAddress { country } defaultCountry defaultCurrency quickCheckoutEnabled } } }'
        }])
    })
    let result = await response.json();
    rocketFuelOptions.order = result[0].data.database.commerceOrder;
}

function getCartFunctionData() {
    let cart = rocketFuelOptions.order.userItems.map(item => {
        return { id: item.product.id, name: item.product.f_name_, price: item.rowTotal.decimalValue, quantity: item.count }
      }
    )
    data = {
        'amount': rocketFuelOptions.order.total.decimalValue.toString(),
        'currency': 'USD',
        cart,
        order_id: rocketFuelOptions.order.id
    };
    return data
}

async function initializePayment() {
    if (document.querySelector('#rocketfuel-payment-button').disabled) return;
    document.querySelector('#rocketfuel-payment-button').disabled = true
    document.querySelector('#rocketfuel-payment-button').innerHTML = `<strong class="bold-text-2">Processing Payment...</strong>`

    try {
        await start();
        let uuid = await getUUID();

        rocketFuelOptions.rkfl = new RocketFuel({
            uuid: uuid,
            callback: updateOrder,
            environment: "prod"
        });
        let checkIframe = setInterval(() => {

            if (rocketFuelOptions.rkfl.iframeInfo.iframe) {
                document.querySelector('#rocketfuel-payment-button').innerHTML = `<strong class="bold-text-2">Preparing window...</strong>`;
                rocketFuelOptions.rkfl.initPayment();
                clearInterval(checkIframe);
            }

        }, 500);
 
    } catch (e) {
        document.querySelector('#rocketfuel-payment-button').disabled = false
        document.querySelector('#rocketfuel-payment-button').innerHTML = `<strong class="bold-text-2">Error! Please reload</strong>`

    }

}

function initRocketfuelProcess() {
    if (document.querySelector('#rocketfuel-payment-button')) {
      const rkflSDK = document.createElement('script');
      rkflSDK.src='https://d3rpjm0wf8u2co.cloudfront.net/static/rkfl.js';
      document.body.appendChild(rkflSDK);

        document.querySelector('#rocketfuel-payment-button').addEventListener('click', async () => {

            initializePayment();

        })
    }
    rocketfuelWindowListener();
}
function rocketfuelWindowListener() {

    window.addEventListener('message', (event) => {
        switch (event.data.type) {
            case 'rocketfuel_iframe_close':
                document.querySelector('#rocketfuel-payment-button').disabled = false;
                document.querySelector('#rocketfuel-payment-button').innerHTML = `<strong class="bold-text-2">Resume Payment...</strong>`
                break;
            default:
                break;
        }

    })
}
initRocketfuelProcess();
```

### Generate Invoice ID <a href="#generate-invoice-id" id="generate-invoice-id"></a>

Invoice Id also known as UUID is needed to complete transaction on the iframe.&#x20;

To generate an invoice link, you will need to run a backend server that will serve as a bridge between the Checkout script explained above and RKFL.&#x20;

Follow [Generate Invoice Link](https://docs.rocketfuel.inc/developer-guides/api-reference/generate-invoice-link) on how to generate invoice ID.&#x20;

In `getUUID(),` replace `ENDPOINT_TO_UPDATE_UUID` with the backend endpoint, you have created to generate UUID.

### Update Order Status <a href="#update-order-status" id="update-order-status"></a>

After a successful transaction, update the order status on Webflow to reflect the new status.&#x20;

To do this, replace `ENDPOINT_TO_UPDATE_WEBFLOW_ORDER` with the endpoint created to receive webhook and update webflow order status.

You can follow [Webhooks](https://docs.rocketfuelblockchain.com/webhooks) to set up the endpoint to handle webhook.


# PHP

### BACKEND

#### PHP SDK - How to Use Rocketfuel with PHP SDK

*This is a technical guide for developers and it requires programming experience to follow through the guide.*

**Prerequisite:**

1. An approved Rocketfuel Merchant Account
2. Composer installed on the server

#### How to Install PHP SDK on your PHP app

There are two ways to install PHP SDK

**a. Installation via composer**

`composer require rkfl/rocketfuel-php-sdk`

**b. Manual installation**

```
git clone https://bitbucket.org/rocketfuelblockchain/rocketfuel-php-sdk.git 
cd rocketfuel-php-sdk 
composer install
```

For php integration without composer, follow

#### Usage Examples

1. Get UUID for triggering iFrame - (\*UUID is a Unique User Identifier).

```
<?php
use RKFL\Api\Client\Options;
use RKFL\Api\Client\Rocketfuel;
require_once <PATH_TO_VENDOR> . '/autoload.php';

$options = new Options(
    [
        'environment' => 'sandbox', //or prod
        'merchant_id' => 'MERCHANT_ID',
        'merchant_public_key' => "PUBLIC_KEY",
        'client_id'=>"CLIENT_ID",
        'client_secret'=>"CLIENT_SECRET",
    ]
);

$rocketfuel = new RocketFuel($options);

$payload = [
    'amount' => '100',
    'cart' => [
        [
            'id' => '1',
            'name' => 'test',
            'price' => '100',
            'quantity' => '1'
        ]
    ],
    'currency' => 'USD',
    'order' => '001'
];

$response = $rocketfuel->service()->getUUID($payload);

```

2\. Verify callback from RocketFuel

```
<?php
    use RKFL\Api\Client\Options;
    use RKFL\Api\Client\Rocketfuel;
    require_once <PATH_TO_VENDOR> . '/autoload.php';
    
    $options = new Options(
    [
        'environment' => 'sandbox', //or prod
        'merchant_id' => 'MERCHANT_ID',
        'merchant_public_key' => "PUBLIC_KEY",
        'client_id'=>"CLIENT_ID",
        'client_secret'=>"CLIENT_SECRET",
    ]
);
    
    $rocketfuel = new RocketFuel($options);
    
    $status= $rocketfuel->helpers()->verifyWebhook($data, $signature);
    
```

3\. Manually Cancel a Subscription

```
<?php
use RKFL\Api\Client\Options;
use RKFL\Api\Client\Rocketfuel;
require_once <PATH_TO_VENDOR> . '/autoload.php';

$options = new Options(
    [
        'environment' => 'sandbox', //or prod
        'merchant_id' => 'MERCHANT_ID',
        'merchant_public_key' => "PUBLIC_KEY",
        'client_id'=>"CLIENT_ID",
        'client_secret'=>"CLIENT_SECRET",
    ]
);

$rocketfuel = new RocketFuel($options);

$subscriptionId = '123_sub';

$status= $rocketfuel->subscription()->cancel($subscriptionId);

```

4\. Manually Debit a Subscription

```
<?php
use RKFL\Api\Client\Options;
use RKFL\Api\Client\Rocketfuel;
require_once <PATH_TO_VENDOR> . '/autoload.php';

$options = new Options(
    [
        'environment' => 'sandbox', //or prod
        'merchant_id' => 'MERCHANT_ID',
        'merchant_public_key' => "PUBLIC_KEY",
        'client_id'=>"CLIENT_ID",
        'client_secret'=>"CLIENT_SECRET",
    ]
);

$rocketfuel = new RocketFuel($options);

$orderId= '123';

$subscriptionData = [
  ...,
  [
    subscriptionId=>'123_sub',
    amount=>1,
    currency=>'USD'
  ],
  ...
];

$status= $rocketfuel->subscription()->debit($orderId, $subscriptionData);
```

#### How to configure SDK <a href="#how-to-configure-sdk" id="how-to-configure-sdk"></a>

Use this code snippet for setting it up.

```
<?php
use RKFL\Api\Client\Options;
use RKFL\Api\Client\RocketFuel;

$options = new Options(
    [
        'environment' => 'sandbox', //or prod
        'merchant_id' => 'MERCHANT_ID',
        'merchant_public_key' => "PUBLIC_KEY",
        'client_id'=>"CLIENT_ID",
        'client_secret'=>"CLIENT_SECRET",
    ]
);

$rocketfuel = new RocketFuel($options);
```

`MERCHANT_ID`,`PASSWORD`,`EMAIL`,`PUBLIC_KEY` are merchant details. See [below ](#how-to-retrieve-merchant-details)to retrieve these details&#x20;

### PHP SDK WITHOUT COMPOSER

To integrate with PHP without composer, you will need to use [this](https://github.com/RocketFuel-BlockChain-Inc/rocketfuel-php-client/blob/development/readme.md).

Step 1: Clone repo into project

```
git clone git@bitbucket.org:rocketfuelblockchain/rocketfuel-php-client.git
```

Step 2: Configure the client and access its methods

```
   require_once(PATH_TO_RKFL.'../src/RKFL_CLIENT.php');
   //configure Options
   $options = array(
       'environment'=>'sandbox', //sandbox -- prod,
       'merchantId'=>'MERCHANT_ID',
        'secret'=>'CLIENTSECRET',
        'clientId'=>'CLIENTID'
   );

   $rkfl = new \RKFL\Client\RKFL_CLIENT($options);

   $payload = array(
       "amount" => "100",
       "cart" => array(
           array(
               "name" => "Test",
               "id" => "200",
               "price" => 100,
               "quantity" => "1"
           )
       ),
       "merchant_id" => MERCHANT_ID,
       "currency" => "USD",
       "order" => "20",
       "redirectUrl" => ""
   );

   $rkfl->rkflgenerateUUID($payload);
```

#### Using webhook

For more information, visit[ webhook ](https:docs.rocketfuelblockchain.com/webhooks)

```
   require_once(PATH_TO_RKFL.'../src/WEBHOOK_CLASS.php');
    use RKFL\Client\WEBHOOK_CLASS as rkflWebhook

    /**
     * $_REQUEST wont work because the webhook is application/json format and not formdata format
     */
    $payload = file_get_contents('php://input'); //use for receiving payload from RKFL SERVER

    $payload = json_decode($payload);

    $result = rkflWebhook::verify_callback($payload->data->data, $payload->signature);

    if ($result) {
        echo "verified \n";
    } else {
        echo 'not verified';
        return;
    }
    rkflWebhook::validate_payment($payload->data);
```

### FRONTEND

#### **RKFL JS** [**CDN**](https://d3rpjm0wf8u2co.cloudfront.net/static/rkfl.js) **and Implementation**

* Add the script from [**CDN**](https://d3rpjm0wf8u2co.cloudfront.net/static/rkfl.js) to the Merchant site.
* Once we get the response with the UUID from the backend. We will initialise an object of the above included script. We pass the following :
  * uuid
  * callback function&#x20;
  * environment
  * Token

```
    const  uuidInfo = JSON.parse(result);
   
     if(uuidInfo.error !== undefined){
        alert("Order placement failed");
        return  false;
    }
    
    uuid = uuidInfo.uuid;
    
    rkfl = new RocketFuel({
        uuid,
        callback:  callBackFunc,
        environment:  "<%= developmentEnv %>"  // prod, preprod
    });
```

* After initialising the object, start the payment by calling the initPayment method of the above script.

```
    function  startPayment(){
        rkfl.initPayment();
    }
```

* Callback payload

```
 // In case of Bank/Exchange payment
          {
            paymentMode: 'Bank/Exchange',
            txn_id: 
            status: 
            meta:
          },

          Sample response:
          {
            paymentMode: 'Bank/Exchange',
            txn_id: "7df55d22-fa5e-4ca2-9af4-a39c95f18b3a"
            status: 0
            meta: {offerId: "1630402767550"}
          },



// In case of Wallet payment
      {
        paymentMode: 'Wallet',
        status: 
        recievedAmount:
        currency:
      },

       Sample response:
       {
           paymentMode: 'Wallet',
           status:"completed",
           recievedAmount:10.00,
           currency:"ETH"
       }
```

## SSO Login <a href="#markdown-header-sso-login" id="markdown-header-sso-login"></a>

### Create merchant Auth using the [PUBLIC\_KEY](https://github.com/RocketFuel-BlockChain-Inc/rocketfuel-readme/blob/master/notification.md) <a href="#markdown-header-create-merchant-auth-using-the-public_key" id="markdown-header-create-merchant-auth-using-the-public_key"></a>

```
    ### JS Code snippet

        var merchantAuth = function(merchantId) {
            var buffer = Buffer.from(merchantId);
            var encrypted = crypto.publicEncrypt(process.env.PUBLIC_KEY, buffer);
            return encrypted.toString("base64");
        }
```

### RKFL Token usage <a href="#markdown-header-rkfl-token-usage" id="markdown-header-rkfl-token-usage"></a>

* Autosignup

  ```
      const payload = {
          firstName: firstName,
          lastName, lastName,
          email: email,
          merchantAuth: "<%= merchantAuth %>",
      }
      rkfl = new RocketFuel({ environment: "<%= developmentEnv %>", });
      rkfl.rkflAutoSignUp(payload, environment = "<%= developmentEnv %>").then((res) => {
          // save this rkflToken for reference in the DB 
          // It is unique to each customer
          res.result.rkflToken;
      })})
  ```
* Existing RKFL Token

  ```
      rkfl = new  RocketFuel({
          token, // rkfltoken
          uuid,
          callback:  callBackFunc,
          environment:  "<%= developmentEnv %>"  // prod, preprod
      })
  ```

You can refer to the [REFERENCE\_LINK](https://github.com/RocketFuel-BlockChain-Inc/rocketfuel-demo-hosted-v2) for demonstration.

### How To Retrieve Merchant Details <a href="#how-to-retrieve-merchant-details" id="how-to-retrieve-merchant-details"></a>

The Email and Password refer to the email/password you use in signing into your merchant portal on <https://merchant.rocketfuel.inc> or equivalent.

The environment refers to the type of details you are using. You should choose production for real transactions and select sandbox when you are testing.

To retrieve Public Key, visit  <https://Merchant.rocketfuel.inc/settings> and copy the string highlighted in the screenshot below.

![](/files/gzt0wR1KBbz31XqS1wgn)

You can also retrieve Merchant Id from the same page. Simply scroll up on the settings page and copy from the section highlighted below

![](/files/f1ztPHEd8hqN8pv93j3x)


# Javascript(JS)

## 🚀 Rocketfuel SDK Overview

The Rocketfuel SDK simplifies the integration of **age verification** and **payment (PayIn)** features into your web and mobile applications. It provides both **server-side** and **client-side** SDKs, ensuring secure and seamless integration across environments.

### Pre-Requisites

1. Setup your rocketfuel Account
2. Generate clientId, clientSecret and whitelist your domain
3. For ZKP
   1. Download CryptoX app from Goole play / ios app store
   2. OR download chrome extension

## Domain Whitelisting

Domain whitelisting ensures that your SDK can only be accessed from approved domains. This helps protect your merchant account from unauthorized usage.

<figure><img src="/files/k0QEU0iPT30XCcJRUBEZ" alt=""><figcaption></figcaption></figure>

### Steps to Whitelist a Domain

1. **Login to your Merchant Portal**
2. **Navigate to Domain Whitelisting**\
   Go to: `Settings > Domain Whitelisting`
3. **Add Your Domain**
   * Enter the URL of the domain where you will be using the SDK.
   * Supported URL formats:

     * [http://example.com](http://example.com/)
     * [https://example.com](https://example.com/)
     * [http://localhost:3000](http://localhost:3000/) (for local development)

     **Note:** Do not include trailing slashes (`/`) in your URLs.
4. **Save Changes**\
   Click on the **Save** or **Add** button to whitelist the domain.
5. **Verify**\
   Once added, your domain should appear in the list of approved domains. Only requests originating from these domains will be allowed to use the SDK.

{% hint style="info" %}
**Important Notes:**

* Only URLs from whitelisted domains can load the SDK.
* Subdomains must be added explicitly if required, e.g., [https://app.example.com](https://app.example.com/).
  {% endhint %}

#### 📚 Documentation

* **Server SDK (Node.js)**\
  Use the server SDK for secure operations, including order creation, token management, and backend verification.\
  👉 [Rocketfuel Server SDK (Node.js)](https://docs.rocketfuel.inc/plug-ins-and-sdks/javascript-js/rocketfuel-sdk-nodejs?utm_source=chatgpt.com)
* **Client SDK (JavaScript)**\
  Use the client SDK to embed age verification widgets and payment buttons into your website or app.\
  👉 [Rocketfuel Client SDK](https://docs.rocketfuel.inc/plug-ins-and-sdks/javascript-js/rocketfuel-sdk-client?utm_source=chatgpt.com)

#### 🔑 Key Features

* **Age Verification (`AGE_VERIFICATION`)**: Ensure compliance by verifying user age before restricted actions.
* **Payment Collection (`PAYIN`)**: Collect payments securely using BTC, ETH and other supported currencies.
* **Cross-environment support**: Sandbox and production environments for smooth testing and deployment.
* **Modular integration**: Use via CDN, npm package, or with popular frameworks (React, Vue, Angular).

## Wallets That Can Be Used for Age Verification

Our system supports two environments: **Sandbox and Production.**

{% hint style="warning" %}
Important: If you are using the Sandbox environment, you must connect via Testnet wallets (mobile apps or browser extensions). Production wallets will not work with Sandbox.
{% endhint %}

### 1. Android

Sandbox (Testnet App): [Download Android Testnet App](https://play.google.com/store/apps/details?id=com.pioneeringtechventures.wallet.testnet\&hl=en_IN)

Production (Mainnet App): [Download Android Production App](https://play.google.com/store/apps/details?id=com.pioneeringtechventures.wallet\&hl=en_IN)

### 2. iOS

Sandbox (Testnet App via TestFlight): [Download iOS Testnet App](https://apps.apple.com/us/app/testflight/id899247664)

Production (Mainnet App - App Store): [Download iOS Production App](https://apps.apple.com/sg/app/cryptox-concordium-wallet/id1593386457)

### 3. Browser Wallet Chrome Extension

Extension Download (same for Sandbox & Production):\
[Download Chrome Wallet Extension](https://chromewebstore.google.com/detail/concordium-wallet/mnnkpffndmickbiakofclnpoiajlegmg?hl=en)

**Switching Network in Browser Wallet**

* Open the wallet extension in your browser.
* Click on the Network dropdown (usually at the top).
* Select the correct network:
  * Testnet → for Sandbox
  * Mainnet → for Production

<figure><img src="/files/RKNKOgOBZJi21spxufv9" alt=""><figcaption></figcaption></figure>


# Rocketfuel SDK nodejs

## Rocketfuel Node.js SDK Integration Guide <a href="#undefined" id="undefined"></a>

This document provides a step-by-step guide for integrating Rocketfuel’s Node.js SDK (`rocketfuel-sdk`) to generate invoices and perform purchase checks in your application.

### Prerequisites <a href="#undefined" id="undefined"></a>

* Node.js installed
* An active Rocketfuel account with access credentials:
  * `CLIENT_ID`
  * `CLIENT_SECRET`
  * `MERCHANT_ID`

### Installation

<pre class="language-bash"><code class="lang-bash"><strong>npm install @rkfl/transact-server
</strong></code></pre>

```javascript
import { Rocketfuel } from '@rkfl/transact-server';
```

### **Reading Credentials from Environment Variables**

Use environment variables for security and flexibility.

```javascript
export const CLIENT_ID = process.env.CLIENT_ID;
export const CLIENT_SECRET = process.env.CLIENT_SECRET;
export const MERCHANT_ID = process.env.MERCHANT_ID;
```

### **Initializing the Rocketfuel Client**

Initialize the `RocketfuelClient` with appropriate parameters:

```javascript
const client = new Rocketfuel({
  clientId: CLIENT_ID,
  clientSecret: CLIENT_SECRET,
  merchantId: MERCHANT_ID,
  environment: 'sandbox', // or 'production'
});
```

### References

* PayIn Integration - [Link](/plug-ins-and-sdks/javascript-js/rocketfuel-sdk-nodejs/payin)
* Payout Integration - [Link](/plug-ins-and-sdks/javascript-js/rocketfuel-sdk-nodejs/payouts)
* Age Verification - [Link](/plug-ins-and-sdks/javascript-js/rocketfuel-sdk-nodejs/age-verification)

####


# PayIn

PayIn is Rocketfuel’s server-side integration flow for securely collecting payments from buyers. The SDK allows you to authenticate requests, create payment orders, open the hosted checkout page, and fetch transaction status using an order ID or Rocketfuel transaction ID.

It also includes utilities for verifying webhook signatures and validating age verification results, helping ensure your backend processes only trusted events.

### 1. Generate Order

```javascript
export const generateUUID = async (req, res) => {
  try {
    const payload = req.body;
    console.log(payload);

    // Call Rocketfuel purchase check API
    const result = await client.createOrder(payload);
    console.log('Hosted Page Result:', result.uuid);

    // Send success response with uuid and it can be used with the frontend sdk
    res.json({ success: true, uuid: result.uuid });
  } catch (err) {
    console.log('Error in generateInvoice:', err);

    // Send failure response with error message
    res.status(500).json({ success: false, error: err.message || 'Internal Server Error' });
  }
};
```

#### Cart payload example

```json
{
  "merchant_id": "b682f8e6-4df8-ae7f-6f94era353d2", // required
  "amount": "59.99", // required
  "cart": [
    {
      "id": "vid1", // required
      "price": 19.99,   // required
      "name": "Amazing Nature Documentary",  // required
      "quantity": 2,    // required
      "key": 101, // optional
      "totalPrice": 39.98, // optional
      "isSubscription": false, // optional
      "frequency": "monthly", // optional
      "subscriptionPeriod": "1m", // optional
      "merchantSubscriptionId": "sub-12345", // optional
      "autoRenewal": true, // optional
      "isSubscriptionRenewal": false, // optional
      "subscriptionId": null, // optional
      "refundable": true // optional (default true if omitted)
    },
  ],
  "currency": "USD", // required
  "order": "ORD-2024-0001", // optional
  "redirectUrl": "https://example.com/return", // optional
  "customerInfo": {
    "name": "John Doe", // optional (whole object)
    "email": "john.doe@example.com", // optional
    "phone": "+1234567890", // optional
    "address": "123 Main Street, NY", // optional
    "allowLoginWithoutEmail": true, // optional
    "userIdentifier": "user-001" // optional
  },
  "shippingAddress": { // optional (whole object)
    "firstname": "John", // optional
    "lastname": "Doe", // optional
    "phoneNo": "+1234567890", // optional
    "address1": "123 Main Street",
    "address2": "Apt 4B", // optional
    "state": "NY",
    "city": "New York",
    "zipcode": "10001", // optional
    "country": "USA",
    "landmark": "Near Central Park", // optional
    "email": "john.doe@example.com" // optional
  },
  "customParameter": { // optional
    "returnMethod": "POST",
    "params": [
      { "name": "submerchant", "value": "streamflix" }
    ]
  },
  "feeConfiguration": { // optional
    "type": "PERCENT",
    "value": 2.5 // optional (default 0 if omitted)
  },
  "siteInfo": { // optional
    "siteUrl": "https://exmaple.com", // optional
    "siteName": "StreamFlix", // optional
    "siteLogo": "https://exmaple.com/logo.png" // optional
  },
}
 
```

#### Root Level Fields

| Field            | Type   | Required | Description                                              |
| ---------------- | ------ | -------- | -------------------------------------------------------- |
| merchant\_id     | string | ✅ Yes    | Unique identifier of the merchant.                       |
| amount           | string | ✅ Yes    | Total amount of the transaction.                         |
| cart             | array  | ✅ Yes    | List of items in the cart.                               |
| currency         | string | ✅ Yes    | Currency code (e.g., USD).                               |
| order            | string | ❌ No     | Merchant’s order reference/ID.                           |
| redirectUrl      | string | ❌ No     | URL where the customer will be redirected after payment. |
| customerInfo     | object | ❌ No     | Information about the customer.                          |
| shippingAddress  | object | ❌ No     | Shipping address details.                                |
| customParameter  | object | ❌ No     | Custom key-value pairs for callback or extra data.       |
| feeConfiguration | object | ❌ No     | Fee-related configuration for the transaction.           |
| siteInfo         | object | ❌ No     | Website or platform information.                         |

#### Cart Object (cart\[])

| Field                  | Type         | Required | Description                                        |
| ---------------------- | ------------ | -------- | -------------------------------------------------- |
| id                     | string       | ✅ Yes    | Unique identifier for the product/item.            |
| price                  | number       | ✅ Yes    | Price of a single unit.                            |
| name                   | string       | ✅ Yes    | Name/description of the product.                   |
| quantity               | number       | ✅ Yes    | Number of units purchased.                         |
| key                    | number       | ❌ No     | Custom product key/reference.                      |
| totalPrice             | number       | ❌ No     | Total price (price \* quantity).                   |
| isSubscription         | boolean      | ❌ No     | Whether this item is a subscription.               |
| frequency              | string       | ❌ No     | Subscription frequency (e.g., monthly).            |
| subscriptionPeriod     | string       | ❌ No     | Subscription period (e.g., 1m).                    |
| merchantSubscriptionId | string       | ❌ No     | Merchant’s subscription reference ID.              |
| autoRenewal            | boolean      | ❌ No     | Whether subscription will auto-renew.              |
| isSubscriptionRenewal  | boolean      | ❌ No     | Marks if this is a renewal payment.                |
| subscriptionId         | string\|null | ❌ No     | Unique identifier of the subscription (if exists). |
| refundable             | boolean      | ❌ No     | Whether item is refundable (default: true).        |

#### Customer Info (customerInfo)

| Field                  | Type    | Required | Description                            |
| ---------------------- | ------- | -------- | -------------------------------------- |
| name                   | string  | ❌ No     | Customer’s full name.                  |
| email                  | string  | ❌ No     | Customer’s email address.              |
| phone                  | string  | ❌ No     | Customer’s phone number.               |
| address                | string  | ❌ No     | Customer’s address.                    |
| allowLoginWithoutEmail | boolean | ❌ No     | Allow login without requiring email.   |
| userIdentifier         | string  | ❌ No     | Custom unique identifier for customer. |

#### Shipping Address (shippingAddress)

| Field     | Type   | Required | Description                       |
| --------- | ------ | -------- | --------------------------------- |
| firstname | string | ❌ No     | Recipient’s first name.           |
| lastname  | string | ❌ No     | Recipient’s last name.            |
| phoneNo   | string | ❌ No     | Recipient’s phone number.         |
| address1  | string | ✅ Yes    | Street address line 1.            |
| address2  | string | ❌ No     | Street address line 2 (optional). |
| state     | string | ✅ Yes    | State/Province.                   |
| city      | string | ✅ Yes    | City name.                        |
| zipcode   | string | ❌ No     | Postal code.                      |
| country   | string | ✅ Yes    | Country name.                     |
| landmark  | string | ❌ No     | Landmark for easier delivery.     |
| email     | string | ❌ No     | Recipient’s email.                |

#### Custom Parameter (customParameter)

| Field        | Type   | Required | Description                          |
| ------------ | ------ | -------- | ------------------------------------ |
| returnMethod | string | ❌ No     | Callback method (e.g., POST).        |
| params       | array  | ❌ No     | Extra parameters as key-value pairs. |

**Params Object**

| Field | Type   | Required | Description      |
| ----- | ------ | -------- | ---------------- |
| name  | string | ✅ Yes    | Parameter key.   |
| value | string | ✅ Yes    | Parameter value. |

#### Fee Configuration (feeConfiguration)

| Field | Type   | Required | Description                  |
| ----- | ------ | -------- | ---------------------------- |
| type  | string | ❌ No     | Type of fee (e.g., PERCENT). |
| value | number | ❌ No     | Fee value (default: 0).      |

#### Site Info (siteInfo)

| Field    | Type   | Required | Description     |
| -------- | ------ | -------- | --------------- |
| siteUrl  | string | ❌ No     | Website URL.    |
| siteName | string | ❌ No     | Website name.   |
| siteLogo | string | ❌ No     | Logo image URL. |

### 2. Transaction lookup

The `transactionLookup` Function is an asynchronous method that lets you retrieve details about a specific transaction from Rocketfuel’s API. You provide a transaction ID (`txId`) and specify the type of ID (`'ORDERID'` or `'TXID'`). The function ensures you have a valid access token, then makes a POST request to the transaction lookup endpoint.

* **Input parameters:**
  * `txId`: The identifier for the transaction you want to look up.
  * `type`: (Optional) Specifies if `txId` it is an order ID (`'ORDERID'`) or transaction ID (`'TXID'`). Defaults to `'ORDERID'`.
* **Purpose:**\
  Use this to verify transaction status, get payment info, or troubleshoot payments.

**Usage Example**

Assuming you have an instance of your SDK client (e.g., named `client`) that includes the `transactionLookup` method:

```javascript
async function checkTransaction(txId) {
  try {
    const result = await client.transactionLookup(txId, 'ORDERID');
    console.log('Transaction Details:', result);
    // Process the transaction details as needed
  } catch (error) {
    console.error('Error fetching transaction details:', error.message);
  }
}

// Example call:
checkTransaction('12345ABC');
```

* Replace `'12345ABC'` with the actual order ID or transaction ID.
* Change `'ORDERID'` to `'TXID'` If you are using the transaction ID.\\

### 3. Webhook Signature Verification

The `verifyWebhookSignature` Function is a synchronous method that ensures the authenticity and integrity of incoming webhook payloads sent by Rocketfuel. It uses **RSA-SHA256** to verify that the payload hasn’t been tampered with and was genuinely sent from Rocketfuel’s backend.

{% hint style="info" %}
For more information, you can refer to this link to retrieve the transaction status for any received webhooks: [RocketFuel Webhook Documentation](/developer-guides/api-reference/payins/rocketfuel-ui-integration/webhooks#markdown-header-rocketfuel-webhook-and-events)
{% endhint %}

**Input Parameters**

* **`body`**: The full parsed JSON object received in the webhook request. It must contain:

**Purpose**

Use this function to **verify that a webhook is valid and trusted** before processing its contents. It prevents spoofed requests, data tampering, and unauthorized events.

**Usage Example**

Assuming you have an instance of your SDK client (e.g., named `client`) that includes the `verifyWebhookSignature` method:

```ts
function handleWebhook(req, res) {
  const isValid = client.verifyWebhookSignature(req.body);

  if (!isValid) {
    console.warn('Webhook signature verification failed');
    return res.status(403).send('Invalid signature');
  }

  const payload = JSON.parse(req.body.data.data);
  console.log('Verified Webhook Payload:', payload);

  // Process your payload
  res.status(200).send('Webhook received');
}
```

> Make sure `req.body` is already parsed into an object. If you're using Express, use a raw body parser middleware to retain the exact content for verification if needed.


# Payouts

Rocketfuel Payouts provides a secure server-side flow for sending fiat bank transfers and crypto payouts to payees. The SDK includes APIs for payee onboarding, bank account management, payout execution, transfer tracking, KYC handling, balance management, and webhook verification.

The SDK supports both fiat and crypto payout flows while automatically handling authentication and token refresh internally.

**Package:** `@rkfl/transact-server`\
**Entry class:** `RocketfuelPayouts`\
**Sub-clients:** `fiat`, `crypto`, `admin`\
**Related exports:** `PayoutWebhookVerifier`, `PAYOUT_WEBHOOK_EVENT_TYPE`, `PAYOUT_WEBHOOK_EVENTS`

***

## 1. Install and construct the client

Follow the installation guide from here - [Link](/plug-ins-and-sdks/javascript-js/rocketfuel-sdk-nodejs)

## 2. Function index (quick map)

| Namespace                      | Function                                                   | Description                                       |
| ------------------------------ | ---------------------------------------------------------- | ------------------------------------------------- |
| `payouts.fiat`                 | `getBankConfiguration`                                     | Load bank account form configuration for a payee. |
| `payouts.fiat`                 | `saveBankDetails`                                          | Save or update payee bank details.                |
| `payouts.fiat`                 | `listBankDetails`                                          | List saved bank accounts for a payee.             |
| `payouts.fiat`                 | `deleteBankDetails`                                        | Delete a saved bank account.                      |
| `payouts.fiat`                 | `getTransferFee`                                           | Fetch payout fee estimate.                        |
| `payouts.fiat`                 | `transfer`                                                 | Execute fiat payout transfer.                     |
| `payouts.fiat`                 | `getTransferStatus`                                        | Get payout transfer status.                       |
| `payouts.crypto`               | `getCurrencies`                                            | Get supported crypto payout currencies.           |
| `payouts.crypto`               | `checkAddress`                                             | Validate wallet address risk/compliance.          |
| `payouts.crypto`               | `getTransferFee`                                           | Fetch crypto payout fee estimate.                 |
| `payouts.crypto`               | `checkTransfer`                                            | Validate crypto payout before execution.          |
| `payouts.crypto`               | `transfer`                                                 | Execute crypto payout transfer.                   |
| `payouts.admin`                | `invitePayee`                                              | Invite and create a new payee.                    |
| `payouts.admin`                | `submitPayeeKyc`                                           | Submit payee KYC details.                         |
| `payouts.admin`                | `getPayeeBalance`                                          | Get payee balance.                                |
| `payouts.admin`                | `getBalance`                                               | Get merchant payout balance.                      |
| `payouts.admin`                | `createTransferAllocation`                                 | Create payout allocation.                         |
| `PayoutWebhookVerifier.verify` | Verify webhook signatures before processing payout events. |                                                   |

## 3. Admin APIs

Manage payees, balances, KYC, and payout allocations.

### 3.1 Invite Payee

```js
 await payouts.admin.invitePayee({
    firstName: 'Jane',
    lastName: 'Doe',
    extra: {
      email: 'jane@example.com',
      refId: 'internal-ref-id',
    },
  });
```

### 3.2 Register Payee with Payouts

```js
await payouts.fiat.createPayeeUserExternal({
      payeeId,
      fName: 'Jane',
      lName: 'Doe',
      email: 'jane@example.com',
      country: 'USA',
    });
```

### **3.3 Su**bmit Payee KYC

<pre class="language-javascript"><code class="lang-javascript"><strong> await payouts.admin.submitPayeeKyc({
</strong>    referenceId: 'PAYEE_REFERENCE_ID',
    type: 'payee',
    kycData: {},
  });
</code></pre>

***

### 3.4 Get Merchant Balance

```js
payouts.admin.getBalance();
```

***

## 4. Fiat Payout Flow

Typical flow: **discover fields → save bank details → quote fee → transfer → poll status**.

Typical payout flow:

1. Load bank configuration
2. Save payee bank details
3. Fetch payout fee
4. Execute transfer
5. Poll payout status
6. Handle webhook events

### 4.1 Get Bank Configuration

Fetch the required bank account and personal detail schema for a payee.

```javascript
const form = await payouts.fiat.getBankConfiguration({
    payeeId,
    country: 'US',
    currency: 'USD',
  });
```

***

### 4.2 Save Bank Details

Save payee bank and personal information.

```js
 const saved = await payouts.fiat.saveBankDetails(
    payeeId,
    {
      currency: 'USD',
      country: 'US',
      bankDetail: {
        bankAccountId: 'BANK_ACCOUNT_ID',
        bankId: 'BANK_ID',
      },
      personalDetail: {
        firstName: 'Jane',
        lastName: 'Doe',
        address: '123 Main St',
      },
    }
  );
```

#### Example Payload

```json
{
  "currency": "USD",
  "country": "US",
  "bankDetail": {
    "bankAccountId": "BANK_ACCOUNT_ID",
    "bankId": "BANK_ID"
  },
  "personalDetail": {
    "firstName": "Jane",
    "lastName": "Doe",
    "address": "123 Main St"
  }
}
```

***

### 4.3 Get Transfer Fee

Fetch payout fee estimate before executing transfer.

```js
const fee = await payouts.fiat.getTransferFee(
    {
      payeeId,
      country: 'US',
      currency: 'USD',
    },
    {
      currency: 'USD',
      accountToken,
      amount: '100.00',
    }
);
```

***

### 4.4 Execute Fiat Transfer

Execute a fiat bank payout.

```js
const transfer = await payouts.fiat.transfer(
    {
      payeeId,
      country: 'US',
      currency: 'USD',
    },
    {
      accountToken,
      amount: '100.00',
      currency: 'USD',
      recordId,
    }
  )
```

#### Example Response

```json
{  "success": true,  "orderId": "payout_order_123456" }
```

### 4.5 Get Transfer Status

Retrieve payout status using order ID and payee ID.

```js
await payouts.fiat.getTransferStatus(orderId, payeeId);
```

#### Payout Statuses

| Status | Description                   |
| ------ | ----------------------------- |
| `0`    | Payout is pending             |
| `1`    | Payout completed successfully |
| `-1`   | Payout failed                 |

Refer to the webhook section for real-time payout status updates.

***

## 5. Crypto Payout Flow

Typical crypto payout flow:

1. Fetch supported currencies
2. Validate wallet address
3. Fetch transfer fee
4. Validate transfer
5. Execute payout
6. Poll transfer status

### 5.1 Get Supported Crypto Currencies

```js
payouts.crypto.getCurrencies(payeeId);
```

### 5.2 Validate Wallet Address

```js
await payouts.crypto.checkAddress({
    walletAddress: '0x0000000000000000000000000000000000000000',
    currency: 'ETH',
 });
```

### 5.3 Execute Crypto Transfer

```js
return payouts.crypto.transfer(payeeId, {
    amount: '10',
    currency: 'ETH',
    cryptoCurrency: 'ETH',
    cryptoNetwork: 'ETH',
    walletAddress: '0x0000000000000000000000000000000000000000',
 });
```

***

## 6. Payout Webhooks

Always verify webhook signatures before processing payout events.

```js
import {
  PayoutWebhookVerifier,
  PAYOUT_WEBHOOK_EVENTS,
} from '@rkfl/transact-server';

function handleWebhook(req, res) {
  const isValid = PayoutWebhookVerifier.verify(req.body);

  if (!isValid) {
    return res.status(403).send('invalid signature');
  }

  const payload = JSON.parse(String(req.body.data));
  const event = req.body.event;

  if (event === PAYOUT_WEBHOOK_EVENTS.PayoutStatusChange) {
    // handle payout status update
  }

  return res.status(200).send('ok');
}
```

#### Supported Webhook Events

| Event                  | Description                             |
| ---------------------- | --------------------------------------- |
| `PayeeAdded`           | Triggered when a payee is created       |
| `PayeeKycStarted`      | Triggered when KYC starts               |
| `PayeeKycStatusChange` | Triggered when KYC status changes       |
| `PayeeFundAllocated`   | Triggered when funds are allocated      |
| `PayoutStarted`        | Triggered when payout processing starts |
| `PayoutStatusChange`   | Triggered when payout status changes    |

***

## 7. Errors

Failed SDK requests throw an `Error` object with HTTP status information.

Always wrap SDK calls with `try/catch`.

```js
try {
  const result = await payouts.fiat.transfer(query, payload);
  console.log(result);
} catch (err) {
  console.error(err);
}
```

***

##


# Age Verification

### Age Verification Status

The `verifyAgeVerification` function is an asynchronous method that checks the status of an age verification request by using the unique **audit ID** generated during the verification process. It communicates with RocketFuel’s backend to determine whether the user has successfully completed age verification.\
Use this function to confirm whether a user has passed or failed age verification. This is essential when handling age-restricted products or services, ensuring compliance with legal and regulatory requirements.

**Input Parameters**

* **auditId**: `string`\
  The unique identifier of the audit log that was created when the age verification attempt was initiated.

**Usage Example**

Assuming you have an instance of your SDK client (e.g., named `client`) that includes the `verifyAgeVerification` method:

```javascript
async function checkAgeVerification(auditId: string) {
  try {
    const result = await client.verifyAgeVerification(auditId);
    console.log("✅ User age verified successfully:", result);
  } catch (error) {
    console.error("Error verifying age:", error);
  }
}

```

**Response**

```json
{
    "id": "d27d3b78-cd99-42f9-87f6-2a17b01f7820",
    "status": "status_verified",
    "verifiedOn": "2025-09-10T17:59:37.002Z",
    "createdAt": "2025-09-10T17:59:21.122Z",
    "timezone": "UTC"
}
```

| Field        | Type                  | Description                                                                     |
| ------------ | --------------------- | ------------------------------------------------------------------------------- |
| `id`         | string                | Unique identifier of the verification record (audit ID).                        |
| `status`     | string                | Current verification status (see **Status Values** below).                      |
| `verifiedOn` | string (ISO datetime) | Timestamp when the user was successfully verified (only available if verified). |
| `createdAt`  | string (ISO datetime) | Timestamp when the verification request was created.                            |
| `timezone`   | string                | Timezone used in the verification process.                                      |

| Status             | Description                                                                |
| ------------------ | -------------------------------------------------------------------------- |
| `expired`          | The verification session expired before completion.                        |
| `status_initiated` | Age verification process has started but not yet completed.                |
| `status_verified`  | User successfully completed age verification.                              |
| `status_failed`    | Age verification attempt failed.                                           |
| `widget_started`   | The verification widget was launched, but final status not yet determined. |

**📌 Notes**

* This function returns `true` if the signature is valid, otherwise `false`.
* Your webhook endpoint must always return a successful response (e.g., HTTP 200), as Rocketfuel verifies the endpoint only once during registration through the merchant dashboard.


# Rocketfuel SDK Client

## 1. Introduction <a href="#pdf-page-u3rixqofbkbqflvwrqyt-id-1-introduction" id="pdf-page-u3rixqofbkbqflvwrqyt-id-1-introduction"></a>

The Rocketfuel SDK enables quick integration of payment and verification features into your web app or site. Use it to display age verification prompts or securely process payments within your flow.

**Demo:** <https://zkp-demo.rocketfuel.inc/>

You can use the SDK:

* Via **CDN script** in traditional HTML/JS projects.
* Via **npm package** in React, Vue, Angular, or other frontend frameworks.

**Features supported:**

* Age Verification (`AGE_VERIFICATION`)
* Payment Collection (`PAYIN`)

{% hint style="warning" %}
**Important:** You must whitelist the domain from which you are accessing the SDK in your merchant portal. Without whitelisting, the SDK will not work. For detailed instructions, please see the [Domain Whitelisting Guide](https://docs.rocketfuel.inc/plug-ins-and-sdks/javascript-js#domain-whitelisting).
{% endhint %}

## 2. Integration <a href="#pdf-page-u3rixqofbkbqflvwrqyt-id-2.-integration" id="pdf-page-u3rixqofbkbqflvwrqyt-id-2.-integration"></a>

### a. Installation and import <a href="#pdf-page-u3rixqofbkbqflvwrqyt-a.-installation" id="pdf-page-u3rixqofbkbqflvwrqyt-a.-installation"></a>

**React (or Module Bundler) Integration**

```bash
npm install @rkfl/transact-client
```

```javascript
import { RkflPlugin } from '@rkfl/transact-client';
```

\
Or add the SDK at the bottom of your page:

```html
<script src="https://sdk.rocketfuel.inc/rkfl-transact-client.min-1.1.0.js" defer></script>

```

*Using* `defer` *ensures the script loads after the HTML has been parsed*. (Not mandatory).

### b. Preparing Container Elements <a href="#pdf-page-u3rixqofbkbqflvwrqyt-b.-preparing-container-elements" id="pdf-page-u3rixqofbkbqflvwrqyt-b.-preparing-container-elements"></a>

Create HTML elements with IDs where the SDK will render widgets:

```html
<div id="verification-container"></div> <!-- for age verification -->
<div id="sdk-buttons-payin"></div>       <!-- for payment buttons -->

<!-- or if you want to load both the button in the same container, 
You can use the code below -->

<div id="sdk-buttons-container"></div> 
```

### c. Initialize SDK with Plugins <a href="#pdf-page-u3rixqofbkbqflvwrqyt-c.-initialize-sdk-with-plugins" id="pdf-page-u3rixqofbkbqflvwrqyt-c.-initialize-sdk-with-plugins"></a>

Example initialization to enable **AGE\_VERIFICATION** and **PAYIN** at the same time:

```javascript
const agePlugin = {
  feature: "AGE_VERIFICATION",
  containerId: "verification-container" // (optional) default: sdk-buttons-container
  // inject: false //(option) @default - true 
};

const payinPlugin = {
  feature: "PAYIN",
  containerId: "sdk-buttons-payin" // (optional) default: sdk-buttons-container
  // inject: false //(option) @default - true
};

const sdk = new RkflPlugin({
  clientId: 'YOUR_CLIENT_ID',
  environment: 'sandbox',  // (optional @default - production  'production' or 'sandbox'.
  plugins: [agePlugin, payinPlugin],
  // redirect: false, // Optional redirect flow @default - false
});
await sdk.init(); // async process that returns true/false 
// if the initialization is successful true is returned else, false
/* 
  Using the "Pay In" feature:

  1. Make sure the cart data is already prepared.
  2. Call your backend API to generate a UUID for the transaction.
     - Note: UUIDs should always be generated on the backend 
     for security and consistency.
*/
sdk.prepareOrder(uuid) // this will launch the payment widget for the Pay In feature

/* 
If you pass an inject parameter as false in the age verification/payment plugin options,
The button for age verification/payment will not be injected into your website.
You can use a custom function to trigger the age verification/payment process.
*/
// NOTE: Make sure your RkflPlugin is initialized before using this function
sdk.launchAgeVerificationWidget() // use this to customize the launch of age verification
sdk.launchPaymentWidget(uuid); // use this to customize the launch of payment widget


```

### d. Trigger the age verification/payment modal manually <a href="#pdf-page-u3rixqofbkbqflvwrqyt-id-4-additional-integration-tips" id="pdf-page-u3rixqofbkbqflvwrqyt-id-4-additional-integration-tips"></a>

The `launchAgeVerificationWidget` The function is used to trigger a modal or iframe-based age verification UI. It is typically called when a user attempts to access age-restricted content or initiate an action that requires age verification, such as connecting a wallet.

The `launchPaymentWidget` function is used to trigger a modal or iframe-based payment interface. It is typically called when a user initiates a transaction, such as making a purchase, subscribing to a service, or completing a checkout flow. The widget handles secure payment collection.

Note: Make sure your SDK is initialized, and if you don't want to use the injected button, you can pass the *inject parameter* as false with the plugin object, for example:

```javascript
const agePlugin = {
  feature: "AGE_VERIFICATION",
  containerId: "verification-container",
  inject: false
};
const payinPlugin = {
  feature: "PAYIN",
  containerId: "sdk-buttons-payin",
  inject: false
};

```

### **e. Setting up user info**

You can optionally provide user details before launching the widget using the `setUserInfo()` method. This is useful if you want to prefill user information or associate the verification with a specific **refId** in your system.

Note:

1. If `setUserInfo()` is not called, the widget will still launch and return results normally. In this case, the user ref is automatically created and returned at the verification success response.

```javascript
sdk.setUserInfo({
  email: 'user@example.com', // Optional: Prefills the user's email
  refId: '12345678'          // Optional: Your internal reference ID
});
```

```html
<button onclick="sdk.launchAgeVerificationWidget()">Verify Now</button>
```

### f. Age Verification Status Check <a href="#pdf-page-u3rixqofbkbqflvwrqyt-id-4-additional-integration-tips-1" id="pdf-page-u3rixqofbkbqflvwrqyt-id-4-additional-integration-tips-1"></a>

The **sdk.verifyAgeVerification** function allows the client application (e.g., browser frontend) to check the status of an age verification request by passing the `auditId` received from the verification flow.

It returns the same verification result object as the server-side function and can be used to unlock restricted UI elements or content.

```javascript
sdk.verifyAgeVerification(event.data.auditId).then(res => {
              console.log('Age verification response:', res);
})
```

\
**Response:**

```json
{
"id": "d27d3b78-cd99-42f9-87f6-2a17b01f7820",
"status": "status_verified",
"verifiedOn": "2025-09-10T17:59:37.002Z",
"createdAt": "2025-09-10T17:59:21.122Z",
"timezone": "UTC"
}
```

| Field        | Type                  | Description                                                                     |
| ------------ | --------------------- | ------------------------------------------------------------------------------- |
| `id`         | string                | Unique identifier of the verification record (audit ID).                        |
| `status`     | string                | Current verification status (see **Status Values** below).                      |
| `verifiedOn` | string (ISO datetime) | Timestamp when the user was successfully verified (only available if verified). |
| `createdAt`  | string (ISO datetime) | Timestamp when the verification request was created.                            |
| `timezone`   | string                | Timezone used in the verification process.                                      |

| Status             | Description                                                                |
| ------------------ | -------------------------------------------------------------------------- |
| `expired`          | The verification session expired before completion.                        |
| `status_initiated` | Age verification process has started but not yet completed.                |
| `status_verified`  | User successfully completed age verification.                              |
| `status_failed`    | Age verification attempt failed.                                           |
| `widget_started`   | The verification widget was launched, but final status not yet determined. |

## 3. Window Events <a href="#pdf-page-u3rixqofbkbqflvwrqyt-id-4-additional-integration-tips-1" id="pdf-page-u3rixqofbkbqflvwrqyt-id-4-additional-integration-tips-1"></a>

NOTE: This feature is only available when you don't use the redirect mode. i.e, your **`redirect : true`**

* Both integrations communicate important state changes (like age verification results or payment completion) via the same standard `window` event messages.
* You listen to them using the same code:

```javascript
window.addEventListener('message', (event) => {
  const data = event.data;

  // Age verification result
  if (data.type === "AGE_VERIFICATION") {
    if (data.verified === true) {
      console.log("User is age verified ✅");
      console.log("refId:", data.refId); // Always returned 
      // Save or use refId for future reference
      // if the ref id is passed via setUserInfo, the same will be returned
      // if the ref id was not passed, a new ref id is returned.
    } else {
      console.log("User failed age verification ❌");
    }
  }

  // Payment result (only if payment flow is used)
  if (data.type === "rocketfuel_result_ok" && data.paymentCompleted === 1) {
    console.log("Payment completed successfully 💰");
  }
});

```

### Allowed Domains Validation for PostMessage Events

1. **Define allowed domains**\
   Only production and sandbox payment domains are allowed:

```javascript
const allowedDomains = [
  "https://payments.rocketfuel.inc",
  "https://payments-sandbox.rocketfuelblockchain.com",
];
```

2. **Validate message origin**\
   Every incoming message is checked against the `allowedDomains` array. Messages from untrusted origins are ignored and logged:

```javascript
if (!allowedDomains.includes(event.origin)) {
  console.warn('Message from untrusted origin:', event.origin);
  return;
}
```

* **Security:** Prevents scripts from unknown domains from sending messages or executing actions in your app.
* **Controlled communication:** Ensures only production and sandbox payment environments can interact with your client via `postMessage`.

### Sample Success Response for Age Verification:

```json
{
    "type": "AGE_VERIFICATION",
    "verified": true,
    "auditId": "5eb81fd8-4cf8-46f3-a09a-7d9f68aeb369",
    "refId": "5a3752af-58b8-4a3d-9700-b90afe6e67a6"
}

```

### **Sample Event for Audit log ID**

When a user initiates the age verification flow, the SDK emits a **window event** containing the generated **audit ID**.

{% hint style="info" %}
Developers can listen for this event, store the `auditId`, and later use it with the `verifyAgeVerification` function to check the user’s verification status.
{% endhint %}

```javascript
window.addEventListener("message", (event) => {
  if (event.data?.type === "AUDIT_ID_GENERATED") {
    console.log("📌 Audit ID received:", event.data.auditId);
    console.log("User Ref ID:", event.data.refId);

    // Store auditId for later verification checks
    localStorage.setItem("auditId", event.data.auditId);
  }
});

```

#### Event data

```json
{
  "type": "AUDIT_ID_GENERATED",
  "auditId": "<audit-id>",
  "refId": "<user-reference-id>"
}
```

### **Sample Success Response for Payment Confirmation:**

{% hint style="warning" %}
Upon receiving the transaction event via postMessage from the payment widget, you should move the transaction to a pending state. This does not indicate the final status of the transaction. To track the final outcome, you should either perform a transaction lookup using the provided API or configure a server-side webhook to receive real-time updates on the transaction status. For quick integration, you can utilize the server-side SDK in Node.js.
{% endhint %}

```json
{
  "type": "rocketfuel_result_ok",
  "response": {
    "paymentMode": "Wallet",
    "status": "completed",
    "recievedAmount": null,
    "currency": "ETH",
    "offerId": "a98afcf0-9d8a-492a-a8b4-5658eafc954f"
  },
  "paymentCompleted": 1
}
```

{% hint style="info" %}
Every Rocketfuel SDK plugin you use—whether initialized through a `<script>` tag or imported as a JavaScript module—will send events to the window when a user completes a step (age check, checkout, etc.), using the same event `type`s and payloads. You can write your logic and UI reactions for these events in a single, unified way across your full app.
{% endhint %}

### Additional Integration Tips <a href="#pdf-page-u3rixqofbkbqflvwrqyt-id-4-additional-integration-tips-2" id="pdf-page-u3rixqofbkbqflvwrqyt-id-4-additional-integration-tips-2"></a>

* **Order Management:** Store cart/order details in `localStorage` or your app state, and use SDKs `prepareOrder(uuid)` (for PAYIN) with a backend-generated order UUID to track transactions.
* **Backend Invoice Generation:** Call your backend API to generate an invoice/order UUID, then pass it to `sdk.prepareOrder(uuid)` to link the frontend SDK with the backend order data.
* **Redirect Flow:** Optionally enable `redirect: true` in SDK options for redirect-based flows instead of inline widgets.
* **Security:**
  * Keep `clientId` and `merchantId` secure, do not expose sensitive data publicly.
  * Only accept `window` messages from trusted origins.

### Summary of Important Fields <a href="#pdf-page-u3rixqofbkbqflvwrqyt-summary-of-important-fields" id="pdf-page-u3rixqofbkbqflvwrqyt-summary-of-important-fields"></a>

1. `feature` : (required) What plugin to load, e.g., `"AGE_VERIFICATION"`, `"PAYIN"`
2. `containerId`: (optional) DOM element ID where the widget will be rendered. default: sdk-buttons-container
3. `clientId` : (required) Your Rocketfuel client ID.
4. `merchantId`: (required) Merchant ID (required for payments).
5. `environment` :(optional) `'`production`'`, `'sandbox'` *default: '*&#x70;roductio&#x6E;*'.*
6. `redirect`: (optional) Optional boolean to enable redirect flows. `default: true`


# Overview

RKFL Developer Guide offers a quick way to get up and running and familiarize yourself with its concepts. For detailed information on our endpoints, check out our [API Reference](https://docs.rocketfuelblockchain.com/developer-guides/api-reference).&#x20;

Following is a breakdown of these guides:

### Quick Start

Our [quick start](https://docs.rocketfuelblockchain.com/developer-guides/quick-start) takes you through the bare essentials required to begin using RKFL.

### API reference&#x20;

This section provides deep knowledge of RKFL APIs to build custom payment solutions at the integrator website.&#x20;

### Webhooks&#x20;

Our [webhooks](https://docs.rocketfuelblockchain.com/webhooks) sections allow you to register your URL in RKFL to get an automatic notification when an event occurs in the RKFL ecosystem.


# Quick Start

If you want to use the RKFL API to design a custom payment solution for your website, you will need to register as a merchant at the RKFL merchant portal.&#x20;

For development and testing purposes, RKFL provides a [merchant sandbox environment](https://merchant-sandbox.rocketfuelblockchain.com/sign-up). This sandbox environment provides a real crypto payment experience in the public blockchain network. All cryptocurrencies spent on RKFL are stored in the RKFL crypto wallet, which can refund into shoppers' crypto wallets. A network fee will apply to blockchain transactions.&#x20;

The RKFL provides a simulator experience with Plaid and Dwolla integration for bank payments. Currently, the Bank transfer facility is only available to USA shoppers. However, we are also working to provide the bank transfer facility in some other countries. Plaid and Dwolla are Rocketfuel's banking partners for bank services.<br>

This guide will walk you through the steps needed to obtain access to RKFL APIs, so you can begin developing.

Step 1. [Register as a merchant ](https://docs.rocketfuelblockchain.com/user-guide-and-help-videos/merchant-user-guide/sign-up-process)

Step 2. [Verify your business information](https://docs.rocketfuelblockchain.com/user-guide-and-help-videos/merchant-user-guide/verification)

Step 3. [Generate a public key and integration keys](https://docs.rocketfuelblockchain.com/user-guide-and-help-videos/merchant-user-guide/settings)

{% hint style="warning" %}
**ATTENTION**

This quickstart assumes you are testing in the Sandbox Environment and uses the base URL of <https://app-sandbox.rocketfuelblockchain.com/api>
{% endhint %}

{% hint style="info" %}
**Note**

If you have developed your payment solution using the RKFL sandbox API and are ready to move into production. The API base URL will require to point to the RKFL production APIs at <https://app.rocketfuelblockchain.com/api>
{% endhint %}


# API Reference

The purpose of publishing the RKFL API document is to guide the merchants who want to design their own user experience for crypto/bank payment solutions, similar to the RKFL features.

The inner pages of this section provide a detailed explanation and purpose of the RKFL APIs.


# PayIns


# Overview

**Rocketfuel PayIns API Overview**

1. #### **Sign Up**

   Merchants begin by signing up with Rocketfuel. They must provide basic business and personal information to create an account.
2. **KYB (Know Your Business)**

   The KYB process verifies a merchant's legal and financial standing. This includes submitting company documentation to ensure compliance with regulatory standards.
3. **Approval**

   After KYB verification, Rocketfuel reviews the submitted documents. Once approved, the merchant receives authorization to use the platform for transactions.
4. **Keys Generation**

   After approval, the merchant generates their public and private keys. These keys are essential for securing API communications and handling transactions securely.
5. **Ready to Use APIs**

   Once set up, merchants gain access to Rocketfuel’s PayIns APIs, allowing them to integrate payment processing into their platform and start accepting transactions seamlessly.

   * **RKFL Widget/Payment Page**
     * **Redirect**: Merchants can redirect customers to a pre-built Rocketfuel payment page. This simplifies the payment process without needing custom development.
     * **RKFL Widget**: A customizable payment widget that can be embedded directly into a merchant’s website, allowing customers to complete transactions seamlessly within the site.
   * **Custom User Interface**\
     For businesses seeking full control over the payment experience, Rocketfuel offers APIs to build a custom interface.

***

For detailed information, refer to each section under PayIns.


# Rocketfuel payment solution workflow

The RKFL provides a complete payment solution through various open-source plugins, an iFrame to integrate at the merchant's website, and an RKFL-hosted checkout page.

The merchant who wants to design their own custom user experience similar to the RKFL features can use the RKFL's APIs to do the same.

The RKFL payment solution integrates through a sequence of API calls. In the API reference section, there are details of all the required APIs.&#x20;

The below diagram shows a sequential workflow of the complete payment solution that help to understand the API calls.

![](/files/tpdEB4rdbsg2MdlDflAX)


# Encryption Algorithm


# Public Key Based

A few of the Rest APIs require an encrypted request payload. The merchant application must use the RSA algorithm to encrypt the request payload from the "Public Key."

Rocketfuel uses the RSA algorithm for encryption and decryption in the REST APIs.

```
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2e4stIYooUrKHVQmwztC
/l0YktX6uz4bE1iDtA2qu4OaXx+IKkwBWa0hO2mzv6dAoawyzxa2jmN01vrpMkMj
rB+Dxmoq7tRvRTx1hXzZWaKuv37BAYosOIKjom8S8axM1j6zPkX1zpMLE8ys3dUX
FN5Dl/kBfeCTwGRV4PZjP4a+QwgFRzZVVfnpcRI/O6zhfkdlRah8MrAPWYSoGBpG
CPiAjUeHO/4JA5zZ6IdfZuy/DKxbcOlt9H+z14iJwB7eVUByoeCE+Bkw+QE4msKs
aIn4xl9GBoyfDZKajTzL50W/oeoE1UcuvVfaULZ9DWnHOy6idCFH1WbYDxYYIWLi
AQIDAQAB
-----END PUBLIC KEY-----
```

{% tabs %}
{% tab title="Node.js" %}

```typescript
export const encryptedReq = async (toEncrypt, publicKey) => {
  const buffer = Buffer.from(toEncrypt);
  const encrypted = crypto.publicEncrypt(publicKey, buffer);
  return encrypted.toString('base64');
};
```

{% endtab %}

{% tab title="Java" %}

```java
public static String encryptData(String text) {
    String encoded = "";
    byte[] encrypted;
    String s1 = PUBLIC_KEY.replaceAll("^.*\n|\n-+END PUBLIC KEY-+$", "");
    try {
        byte[] publicBytes = Base64.decode(s1, Base64.NO_WRAP);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        encrypted = cipher.doFinal(text.getBytes());
        encoded = Base64.encodeToString(encrypted, Base64.DEFAULT);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (InvalidKeySpecException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    }

    return encoded;
}
```

{% endtab %}

{% tab title="PHP" %}

```php
function encrypt_data(string $to_crypt,string $certificate):string
{
    $encryptedText = '';
    $formatted_cert = str_replace('\n', '', $certificate);
    $public_key = openssl_pkey_get_public($formatted_cert); //extract public key from certificate
    $key_details = openssl_pkey_get_details($public_key); // get public key details
    $part_len = $key_details['bits'] / 8 - 11;
    $parts = str_split($to_crypt, $part_len); // split string data into parts
    foreach ($parts as $part) { //encrypt in part
        $encrypted_temp = '';
        openssl_public_encrypt($part, $encrypted_temp, $public_key, OPENSSL_PKCS1_OAEP_PADDING);
        $encryptedText .=  $encrypted_temp;
    }
    return base64_encode($encryptedText); //encode cipher text to base64
}
```

{% endtab %}
{% endtabs %}


# Secret Key Based

A few of the Rest APIs require an encrypted request payload. The merchant application must encrypt payload with shared secret key in order to call Rocketfuel REST API's.

{% tabs %}
{% tab title="Node.Js" %}

```typescript
const CryptoJS = require("crypto-js");

//Enryption
const stringifyData = JSON.stringify(payload)
const encrypted = CryptoJS.AES.encrypt(stringifyData, key).toString();
 
//Decryption
const bytes = CryptoJS.AES.decrypt(value, key);
const data = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));  
```

{% endtab %}

{% tab title="Python" %}

```python
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import hashlib
import base64

def generate_salt():
    return get_random_bytes(8)

def evpkdf(passphrase, salt, key_size=32, iv_size=16):
    """
    Derives a key and IV from the passphrase and salt using OpenSSL compatible method.
    """
    d = d_i = b''  # Initialize empty bytes for key and IV derivation
    while len(d) < key_size + iv_size:
        d_i = hashlib.md5(d_i + passphrase.encode('utf-8') + salt).digest()
        d += d_i
    return d[:key_size], d[key_size:key_size + iv_size]

def pad(data):
    """Pads data to a multiple of AES block size (16 bytes)."""
    padding_len = 16 - len(data) % 16
    return data + chr(padding_len) * padding_len

def encrypt_data(data, passphrase, salt):
    key, iv = evpkdf(passphrase, salt)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted_data = cipher.encrypt(pad(data).encode())
    return encrypted_data

def create_encrypted_payload(data, passphrase):
    salt = generate_salt()
    encrypted_data = encrypt_data(data, passphrase, salt)
    encrypted_data_with_salt = b"Salted__" + salt + encrypted_data
    return base64.b64encode(encrypted_data_with_salt).decode('utf-8')

# Data to be encrypted
data = {
    'merchantId': MERCHANT_ID,
    'totp': ''
}

# Convert the data to a JSON string
data_str = json.dumps(data)

# Create the encrypted payload
encrypted_payload = create_encrypted_payload(data_str, CLIENT_SECRET)
```

{% endtab %}

{% tab title="PHP" %}

```php
function encrypt($toEncrypt, $secret){
    $salt = openssl_random_pseudo_bytes(8);
    $salted = $dx = '';
    while (strlen($salted) < 48) {
        $dx = md5($dx . $secret . $salt, true);
        $salted .= $dx;
    }

    $key = substr($salted, 0, 32);
    $iv = substr($salted, 32, 16);

    // encrypt with PKCS7 padding
    return base64_encode('Salted__' . $salt . openssl_encrypt($toEncrypt . '', 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv));
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
using System;
using System.Security.Cryptography;
using System.Text;
using System.Linq;

public class EncryptionAES
{
    private static readonly Random SecureRandom = new Random();

    public static byte[] EvpKDF(byte[] password, byte[] salt, int keySize = 48, string hasher = "MD5", int iterations = 1)
    {
        byte[] keyMaterial = new byte[keySize];
        int generatedBytes = 0;
        byte[] block = null;
        using (var md = MD5.Create())
        {
            while (generatedBytes < keySize)
            {
                md.Initialize();

                if (block != null)
                    md.TransformBlock(block, 0, block.Length, null, 0);

                md.TransformBlock(password, 0, password.Length, null, 0);
                md.TransformFinalBlock(salt, 0, salt.Length);
                block = md.Hash;

                for (int i = 1; i < iterations; i++)
                {
                    block = md.ComputeHash(block);
                }

                int remaining = Math.Min(block.Length, keySize - generatedBytes);
                Array.Copy(block, 0, keyMaterial, generatedBytes, remaining);
                generatedBytes += remaining;
            }
        }

        return keyMaterial;
    }

    public static string EncryptAES(string data, string key)
    {
        using (var aes = Aes.Create())
        {
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            byte[] salt = new byte[8];
            SecureRandom.NextBytes(salt);

            byte[] derivedKey = EvpKDF(Encoding.UTF8.GetBytes(key), salt);
            byte[] keyBytes = derivedKey.Take(32).ToArray();
            byte[] ivBytes = derivedKey.Skip(32).Take(16).ToArray();

            aes.Key = keyBytes;
            aes.IV = ivBytes;

            using (var encryptor = aes.CreateEncryptor())
            using (var ms = new System.IO.MemoryStream())
            {
                ms.Write(Encoding.ASCII.GetBytes("Salted__"), 0, 8);
                ms.Write(salt, 0, salt.Length);

                using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                using (var sw = new System.IO.StreamWriter(cs))
                {
                    sw.Write(data);
                }

                return Convert.ToBase64String(ms.ToArray());
            }
        }
    }
}


//how to use
    var data = new { merchantId = "861331d4-aa85-42c2-8a4f-a8e78043809a",totp=""};
    string toEncrypt = JsonSerializer.Serialize(data);
    string secret = "SECRET";
    string encrypted = EncryptionAES.EncryptAES(toEncrypt, secret);
    Console.WriteLine("Encrypted: " + encrypted);
```

{% endtab %}

{% tab title="Java" %}

```java
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

public class EncryptionAES {
    public static byte[] evpKDF(String key, byte[] salt, int keySize) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] keyBytes = new byte[keySize];
        byte[] previous = new byte[0];
        int generated = 0;

        while (generated < keySize) {
            md.update(previous);
            md.update(key.getBytes(StandardCharsets.UTF_8));
            md.update(salt);
            previous = md.digest();

            int bytesToCopy = Math.min(previous.length, keySize - generated);
            System.arraycopy(previous, 0, keyBytes, generated, bytesToCopy);
            generated += bytesToCopy;
        }
        return keyBytes;
    }

    public static String encryptAES(String data, String secret) throws Exception {
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[8];
        random.nextBytes(salt);

        byte[] keyIv = evpKDF(secret, salt, 48);
        byte[] key = Arrays.copyOfRange(keyIv, 0, 32);
        byte[] iv = Arrays.copyOfRange(keyIv, 32, 48);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));

        byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

        byte[] saltedData = new byte[8 + salt.length + encryptedData.length];
        System.arraycopy("Salted__".getBytes(StandardCharsets.US_ASCII), 0, saltedData, 0, 8);
        System.arraycopy(salt, 0, saltedData, 8, salt.length);
        System.arraycopy(encryptedData, 0, saltedData, 16, encryptedData.length);

        return Base64.getEncoder().encodeToString(saltedData);
    }

    public static void main(String[] args) throws Exception {
        String json = "{\"merchantId\":\"MERCHANT_ID\",\"totop\":\"\"}";
        String secret = "SECRET";

        String encrypted = encryptAES(json, secret);
        System.out.println("Encrypted: " + encrypted);
    }
}
```

{% endtab %}
{% endtabs %}


# Authentication


# Authenticate a merchant

This API allows the merchant to login into the RKFL system. After the successful login, API returns the "access token" and "refresh token". The access token would be used as a Bearer token for the subsequent API calls, while the refresh token will generate a new access token if the existing access token expires.

The concept of the refresh token usually works in a mobile application where users stay login for a long time. The use of the refresh token is subject to the policy of the integrated platform.

> The current expiry time of the access token is 30 min

{% hint style="info" %}
This API should be used for Server <-> Server communication only.
{% endhint %}

<mark style="color:green;">`POST`</mark> `/auth/signin`

#### Request Body

| Name         | Type   | Description                                                                                                                                          |
| ------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| encryptedReq | String | Encrypted data containing email<mark style="color:red;">\*</mark>, password<mark style="color:red;">\*</mark>, deviceId, deviceToken, fcmToken, totp |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
    "ok": true,
    "result": {
        "access": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZlNWNjODU0LWUxMzYtNDZiNy04OGRjLTRhMzNkZDdjMzFhMSIsImlhdCI6MTY1NDE2NDg3OCwiZXhwIjoxNjU0MTY2Njc4fQ.TqURCCKw8bjHv1hYKE6PAJgNdpvU-wD3zH3tPefhZP8"",
        "refresh": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZlNWNjODU0LWUxMzYtNDZiNy04OGRjLTRhMzNkZDdjMzFhMSIsImlhdCI6MTY1NDE2NDg3OCwiZXhwIjoxNjU0MTY3Mjc4fQ.2MCHnI_ONxt9Yxg-po9lfe9I827IKPiANs2eO8neNsU"",
        "status": 1
    }
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid credentials" %}

```javascript
{
  "ok": false,
  "statusCode": 401,
  "data": {
    
  },
  "message": "Incorrect email and password pair"
}
```

{% endtab %}

{% tab title="500: Internal Server Error Server unavailable or server error" %}

```javascript
{
  "ok": false,
  "statusCode": 500,
  "message": "Internal Server Error"
}
```

{% endtab %}
{% endtabs %}


# Authentication Without Email / Password

### Obtaining Authentication Keys

Client Id and Client Secret are available over the merchant portal in the Settings menu.

<figure><img src="/files/YkpOFOLxOSzNWgqfr2xP" alt=""><figcaption></figcaption></figure>

### Authentication

Encryption is done using AES algorithm with PKCS7 padding, CBC mode and a key size of 256. Encryption of the body payload is as follows:-

{% tabs %}
{% tab title="Javascript" %}

```javascript
var CryptoJS = require('crypto-js');
var data = CryptoJS.AES.encrypt(JSON.stringify({
    merchantId: 'MERCHANT_ID',
    totp:''
}), 'CLIENT_SECRET').toString();

pm.variables.set("encryptedPayload", data);
```

{% endtab %}

{% tab title="Python" %}

```python
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import hashlib
import base64

def generate_salt():
    return get_random_bytes(8)

def evpkdf(passphrase, salt, key_size=32, iv_size=16):
    """
    Derives a key and IV from the passphrase and salt using OpenSSL compatible method.
    """
    d = d_i = b''  # Initialize empty bytes for key and IV derivation
    while len(d) < key_size + iv_size:
        d_i = hashlib.md5(d_i + passphrase.encode('utf-8') + salt).digest()
        d += d_i
    return d[:key_size], d[key_size:key_size + iv_size]

def pad(data):
    """Pads data to a multiple of AES block size (16 bytes)."""
    padding_len = 16 - len(data) % 16
    return data + chr(padding_len) * padding_len

def encrypt_data(data, passphrase, salt):
    key, iv = evpkdf(passphrase, salt)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted_data = cipher.encrypt(pad(data).encode())
    return encrypted_data

def create_encrypted_payload(data, passphrase):
    salt = generate_salt()
    encrypted_data = encrypt_data(data, passphrase, salt)
    encrypted_data_with_salt = b"Salted__" + salt + encrypted_data
    return base64.b64encode(encrypted_data_with_salt).decode('utf-8')

# Data to be encrypted
data = {
    'merchantId': MERCHANT_ID,
    'totp': ''
}

# Convert the data to a JSON string
data_str = json.dumps(data)

# Create the encrypted payload
encrypted_payload = create_encrypted_payload(data_str, CLIENT_SECRET)
```

{% endtab %}

{% tab title="PHP" %}

```php
function encrypt($toEncrypt, $secret){
    $salt = openssl_random_pseudo_bytes(8);
    $salted = $dx = '';
    while (strlen($salted) < 48) {
        $dx = md5($dx . $secret . $salt, true);
        $salted .= $dx;
    }

    $key = substr($salted, 0, 32);
    $iv = substr($salted, 32, 16);

    // encrypt with PKCS7 padding
    return base64_encode('Salted__' . $salt . openssl_encrypt($toEncrypt . '', 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv));
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
using System;
using System.Security.Cryptography;
using System.Text;
using System.Linq;

public class EncryptionAES
{
    private static readonly Random SecureRandom = new Random();

    public static byte[] EvpKDF(byte[] password, byte[] salt, int keySize = 48, string hasher = "MD5", int iterations = 1)
    {
        byte[] keyMaterial = new byte[keySize];
        int generatedBytes = 0;
        byte[] block = null;
        using (var md = MD5.Create())
        {
            while (generatedBytes < keySize)
            {
                md.Initialize();

                if (block != null)
                    md.TransformBlock(block, 0, block.Length, null, 0);

                md.TransformBlock(password, 0, password.Length, null, 0);
                md.TransformFinalBlock(salt, 0, salt.Length);
                block = md.Hash;

                for (int i = 1; i < iterations; i++)
                {
                    block = md.ComputeHash(block);
                }

                int remaining = Math.Min(block.Length, keySize - generatedBytes);
                Array.Copy(block, 0, keyMaterial, generatedBytes, remaining);
                generatedBytes += remaining;
            }
        }

        return keyMaterial;
    }

    public static string EncryptAES(string data, string key)
    {
        using (var aes = Aes.Create())
        {
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            byte[] salt = new byte[8];
            SecureRandom.NextBytes(salt);

            byte[] derivedKey = EvpKDF(Encoding.UTF8.GetBytes(key), salt);
            byte[] keyBytes = derivedKey.Take(32).ToArray();
            byte[] ivBytes = derivedKey.Skip(32).Take(16).ToArray();

            aes.Key = keyBytes;
            aes.IV = ivBytes;

            using (var encryptor = aes.CreateEncryptor())
            using (var ms = new System.IO.MemoryStream())
            {
                ms.Write(Encoding.ASCII.GetBytes("Salted__"), 0, 8);
                ms.Write(salt, 0, salt.Length);

                using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                using (var sw = new System.IO.StreamWriter(cs))
                {
                    sw.Write(data);
                }

                return Convert.ToBase64String(ms.ToArray());
            }
        }
    }
}


//how to use
    var data = new { merchantId = "861331d4-aa85-42c2-8a4f-a8e78043809a",totp=""};
    string toEncrypt = JsonSerializer.Serialize(data);
    string secret = "SECRET";
    string encrypted = EncryptionAES.EncryptAES(toEncrypt, secret);
    Console.WriteLine("Encrypted: " + encrypted);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If we provide the clientSecret as string it will not use it as a key but a passphrase to derive the key value using a KDF. The default KDF for this library is similar to the open SSL EVP function. (for reference: <https://www.openssl.org/docs/manmaster/man3/EVP_BytesToKey.html>) This function generates the actual AES keys using MD5 hashing and uses 1 iteration.
{% endhint %}

```kotlin
/**
* based on: www.openssl.org/docs/crypto/EVP_BytesToKey.html
*/
fun evpKDF(password: ByteArray, salt: ByteArray, keySize: Int = 48, hasher: String = "MD5", iterations: Int = 1): ByteArray {
val keyMaterial = ByteArray(keySize)
var generatedBytes = 0
var block: ByteArray? = null
val md = MessageDigest.getInstance(hasher)

while (generatedBytes < keySize) {
        md.reset()

if (block != null)
            md.update(block)

        md.update(password)
        block = md.digest(salt)

for (i in 1 until iterations)
            block = md.digest(block)

val remaining = block!!.size.coerceAtMost(keySize - generatedBytes)
System.arraycopy(block, 0, keyMaterial, generatedBytes, remaining)
        generatedBytes += remaining
    }

return keyMaterial
}

fun encryptAES(data: String, key: String): String {
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
val salt = ByteArray(8)
secureRandom.nextBytes(salt)

val derivedKey = evpKDF(key.toByteArray(), salt)
val secretKey = SecretKeySpec(derivedKey.sliceArray(0..31), "AES")
val iv = IvParameterSpec(derivedKey.sliceArray(32..47))

    cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv)

val encrypted = cipher.doFinal(data.toByteArray())
val encryptedWithIv = "Salted__".toByteArray() + salt + encrypted

return Base64.getEncoder().encodeToString(encryptedWithIv)
}
```

### Generating access and refresh token using encrypted payload and clientId

<mark style="color:green;">`POST`</mark> `api/auth/generate-auth-token`

This endpoint is used for generating access and refresh tokens without using merchant email and password. It requires clientId and encrypted string generated from the encryption logic discussed above.&#x20;

#### Request Body

| Name                                               | Type   | Description                                                                 |
| -------------------------------------------------- | ------ | --------------------------------------------------------------------------- |
| clientId<mark style="color:red;">\*</mark>         | String | Client Id can be accessed in Settings menu                                  |
| encryptedPayload<mark style="color:red;">\*</mark> | String | AES encrypted (using client secret) payload containing merchant Id and totp |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "ok": true,
    "result": {
        "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImM1MzlkZWVjLTYwNDktNDZlMC1hZTJjLTUwZTJhNjQ2ZmMzMSIsImlhdCI6MTY2MjczOTczOSwiZXhwIjoxNjYyODI2MTM5fQ.AkvmP2oTAfj91w5w9arOAsiAAnfg1o-Ia-3b3PkZSaw",
        "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImM1MzlkZWVjLTYwNDktNDZlMC1hZTJjLTUwZTJhNjQ2ZmMzMSIsImlhdCI6MTY2MjczOTczOSwiZXhwIjoxNjY1MzMxNzM5fQ.CFjoO4XwZpuQNBpkVoQtpUbu1_yYVIFoMO5MqDWYGeg",
        "status": 2
    }
}
```

{% endtab %}
{% endtabs %}


# RocketFuel UI Integration

<div data-full-width="true"><figure><img src="/files/XWRN1TldoqfHparHhgi4" alt=""><figcaption></figcaption></figure></div>


# Generate Invoice Link

RKFL create an invoice in their system before processing the payment. Once the payment is processed, the invoice turns into an order.&#x20;

The merchant website must send the cart info to RKFL for creating an invoice. The API returns a redirect URL with a UUID. The merchant website can save this redirect URL for future purposes.&#x20;

There are two ways of integration

1. Redirect: If merchant wants to use redirect approach, they can redirect shopper to the redirect link
2. Widget (Popup): In case merchant wants to use inline experience(without redirection), they can use UUID with JavaScript SDK. See here for the [Javascript SDK Documentation](#rocketfuel-js-sdk)&#x20;

The RKFL also supports recurring payments on subscribed products. If the shopper subscribed to a product and paid from the connected exchange, the RKFL can manage the recurring payment on the defined frequency and update the merchant server through a registered webhook. The subscription facility is only available on exchange payment.&#x20;

The request payload also supports receiving some custom parameters from the merchant website. These custom parameters will return in the transaction status update webhook. The merchant can also define the HTTP method (GET/POST) to receive the webhook.

{% hint style="info" %}
The length of the complete payload, including the custom parameters, must not exceed the max length of "GET" and "POST" requests.

The max length of the "GET" request is 2048 characters, and the max length of the "POST" request is 2M.
{% endhint %}

The merchants who want to integrate the RKFL-hosted checkout experience redirect the shopper to this URL.

> The RKFL-hosted checkout page is the simplest way to use the RKFL services

### Subscription

To add a subscription product to the invoice, you must pass additional details with the product object in the cart.

These details include &#x20;

"isSubscription" - This should be set to true if the product is a subscription product

"frequency" - This describes how frequently the subscription will be charged

"subscriptionPeriod" - The duration for which the subscription will be active

"merchantSubscriptionId" -  The unique subscription Id generated by the merchant

```
// Here is the sample of the request payload. 
{
  "amount": "",
  "cart":[{
    "id": "",
    "price": "",
    "name": "",
    "quantity": "",
    "key": "",
    "totalPrice": "",
    //only add the below, if the product is a subscription item.
    "isSubscription": "", 
    "frequency": "",
    "subscriptionPeriod":""
    "merchantSubscriptionId": "",
    "autoRenewal": true/false, // pass false on null for subscription item
  }],
  "currency": "",
  "order": "",
  "redirectUrl": "",
   "customParameter": {
    "returnMethod": "POST/GET",
    "params": [
      {
        "name": "var",
        "value": "1302*6649c8793fa687fe708618ae52344e26*1685*2*1*128*76"
      },
      {
          "name": "custom",
          "value": "1302|6649c8793fa687fe708618ae52344e26|2|1|128|2|1685"
      }
    ]
  },
  customerInfo{
    name: required (string)
    email: required (string)
    phone: optional (string)
    address: optional (string)
  },
  shippingAddress{
    firstname:optional (string)
    lastname: optional (string)
    phoneNo: optional (string)
    address1: required (string)
    address2: optional (string)
    state: required (string)
    city: required (string)
    zipcode: optional (string)
    country: required (string)
    landmark: optional (string)
    email: optional (string)
  }
}

// isSubscription: true/false 
// subscriptionPeriod: [number][period] - for example 1y, 2m, 3w
// autoRenewal: true/false // if false is passed merchants can manage the debit of subscription items 
  on their own or if passed true Rocketfuel will manage the subscriptions based on the frequency passed.
// frequency: weekly/monthly/quarterly/half-yearly/yearly
// merchantSubscriptionId: Subscription id for merchant system. This key will use to communicate the recurring payment status.
// If no shipping details are available, shippingAddress can be assigned null
i.e., shippingAddress : null
```

{% hint style="info" %}
You can use **siteInfo** in the parameter to generate invoices from different websites/stores.
{% endhint %}

<mark style="color:green;">`POST`</mark> `/hosted-page`

#### Headers

| Name                                              | Type   | Description                      |
| ------------------------------------------------- | ------ | -------------------------------- |
| "authorization"<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |
| "Content-Type"                                    | String | "application/json"               |

#### Request Body

| Name                                       | Type   | Description                                                                                        |
| ------------------------------------------ | ------ | -------------------------------------------------------------------------------------------------- |
| amount<mark style="color:red;">\*</mark>   | String |                                                                                                    |
| cart<mark style="color:red;">\*</mark>     | Object | id, price, name, quantity, key, totalPrice, isSubscription, frequency, merchantSubscriptionId      |
| currency<mark style="color:red;">\*</mark> | String | USD/EUR                                                                                            |
| order                                      | String | Unique order id from the merchant's system                                                         |
| redirectUrl                                | String | Return URL of merchant's website, in case of RKFL hosted checkout integrated                       |
| customerInfo                               | Object | name, email, phone, address                                                                        |
| shippingAddress                            | Object | firstname, lastname, phoneNoaddress1, address2, state, city, zipcode, country, landmark, email     |
| customParameter                            | Object | returnMethod could be GET or POST only. The supplied custom parameters will return in the webhook. |
| merchant\_id                               | String | Unique merchant ID which each merchant has                                                         |
| siteInfo                                   | Object | siteUrl, siteName, siteLogo                                                                        |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
    "ok":true,
    "result":{
        "url":"https://payments-sandbox.rocketfuelblockchain.com/hostedPage/f7cb4141-3030-4245-8aa1-f5cf95b5d504",
        "uuid": "f7cb4141-3030-4245-8aa1-f5cf95b5d504"
    }
}
```

{% endtab %}
{% endtabs %}

## RocketFuel JS SDK

Follow the guide to embed RocketFuel Hosted Page on the Merchant's website.

## Prerequisites:-

Merchant should send below JSON input details to display the same on RocketFuel hosted page

```
Sample Format of JSON Data-
{
    amount: "11.00",
    merchant_id: process.env.MERCHANT_ID,
    cart: [
    {
	    id: "23",
	    name: "Album",
	    price: "11",
	    quantity: "1",
    },
    ],
	 currency: "USD",
    order: "390",
    redirectUrl: "",
}
```

where

1. Amount - total price of whole order for payment, in USD only
2. Cart -\
   a. ID - Article unique Id\
   b. Name - Article Name\
   c. Price - Article price\
   d. Quantity - Article Quantity
3. Currency - Currency in which Merchant recieved the payment, in USD only
4. Order - Unique Order Id
5. RedirectUrl - URL of the Merchant site where the Merchant wants to redirect from the Hosted page to their site after payment.

#### Follow the steps below :-

1. Merchant need to be authenticated on RocketFuel by passing the input parameters - MERCHANT\_EMAIL and MERCHANT\_PASSWORD.

**Request**

```
var options = {
	method: "POST",
	url: process.env.API_ENDPOINT + "auth/login",
    headers: {
	    "Content-Type": "application/json",
    },
    body: JSON.stringify({
	    email: process.env.MERCHANT_EMAIL,
	    password: process.env.MERCHANT_PASS,
    }),
};
```

**Response**

```
{ "ok":true, "result"{ "access":"eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp
XVCJ9.eyJpZCI6ImViMDE1NWU4 LTkwNzItNGMyYi05NWFjLTAxZDhiMWFlZDI3ZC
IsImlhdCI6MTYyMzQwMz g0OSwiZXhwIjoxNjIzNDkwMjQ5fQ.t1wL6LYkr8y5sau
CuOWMmGbGNDZH qXzUjo6WeT370c","refresh":"eyJhbGciOiJIUzI1NiIsInR5
cCI6IkpXVCJ9.eyJpZC I6ImViMDE1NWU4LTkwNzItNGMyYi05NWFjLTAxZDhiMWF
lZDI3ZCIsImlhd CI6MTYyMzQwMzg0OSwiZXhwIjoxNjI1OTk1ODQ5fQ.A_JF1ODt
cRCRc7Yn TcT5JBFDDMkgQtlQXYkhBFw3dgM", "status":2 }
```

2\. Once Merchant is verified, details of the items purchased with the access token will be sent in a different request.

Note - Token needs to send in the Header and details of the items purchased in the Body.

**Request**

```
var options = {
    method: "POST",
    url: process.env.API_ENDPOINT + "hosted-page",
    headers: {
	    authorization: "Bearer " + accessToken,
	    "Content-Type": "application/json",
    },
    body: JSON.stringify({
    amount: "11.00",
    merchant_id: process.env.MERCHANT_ID,
    cart: [
    {
	    id: "23",
	    name: "Album",
	    price: "11",
	    quantity: "1",
    },
    ],
    currency: "USD",
    order: "390",
    redirectUrl: "",
    }),
};
```

**Response** -

```
{
    "ok":true,
    "result":{"url":"[https://dev.rocketdemo.net/hostedPage
    /f7cb4141-3030-4245-8aa1-](https://dev.rocketdemo.net/hostedP
    age/f7cb4141-3030-4245-8aa1-)[f5cf95b5d504](https://dev.rocke
    tdemo.net/hostedPage/f7cb4141-3030-4245-8aa1-f5cf95b5d504)"}

}
```

3\. Once Merchant received the response as a True, then send the UUID as the response to the Merchant site.

***On click of \[Pay for your order with RocketFuel] paste below Code Snippet.***

**Code Snippet--**

```
const request=require('request');
var options = {

    method: "POST",
    url: process.env.API_ENDPOINT + "auth/login",
    headers: {
    "Content-Type": "application/json",
    },
    body: JSON.stringify({
	    email: process.env.MERCHANT_EMAIL,
	    password: process.env.MERCHANT_PASS,
    }),
};

request(options, function (error, response) {

    if (error) throw new Error(error);    
    let accessToken = JSON.parse(response.body).result.access;

    //place the order API Call
    var options = {
	    method: "POST",
	    url: process.env.API_ENDPOINT + "hosted-page",
	    headers: {
		    authorization: "Bearer " + accessToken,
		    "Content-Type": "application/const" 
		    } 
	    },
	    body: JSON.stringify({
	    amount: "11.00",
	    merchant_id: process.env.MERCHANT_ID,
	    cart: [
	    {
		    id: "23",
		    name: "Album",
		    price: "11",
		    quantity: "1",
		   },
	   ],
	    currency: "USD",
	    order: "390",
	    redirectUrl: "",
}),
};

request(options, function (error, response) {

    if (error) throw new Error(error);
    let resp = JSON.parse(response.body);
    if(resp.result !== undefined && resp.result.url !==undefined){
		let  urlArr = resp.result.url.split("/");
		let  uuid = urlArr[urlArr.length - 1];
		res.status(200).send({ uuid:  uuid });
	}else{
		res.status(400).send({ error:  "Failed to place order" });
		}
	 });
});
```

## Javascript Library

4. **RKFL JS** [**CDN**](https://d3rpjm0wf8u2co.cloudfront.net/static/rkfl.js) **and Implementation**

   4.1. Add the script from [**CDN**](https://d3rpjm0wf8u2co.cloudfront.net/static/rkfl.js) to the Merchant site.

   4.2 Once we get the response with the uuid. We will initialise an object of the above included script, while initialising the object we will pass following :-

   * uuid
   * callback function
   * environment
   * Token

     ```
     const  uuidInfo = JSON.parse(result);
     if(uuidInfo.error !== undefined){
     	alert("Order placement failed");
     	return  false;
     }
     uuid = uuidInfo.uuid;
     rkfl = new  RocketFuel({
     	uuid,
     	callback:  callBackFunc,
     	environment:  "<%= developmentEnv %>"  // prod, preprod
     });
     ```

4.3. After initialising the object start the payment by calling the initPayment method of the above script.

```
	function  startPayment(){
		rkfl.initPayment();
	}
```

4.4. Callback payload

```
 // In case of Bank/Exchange payment
	      {
            paymentMode: 'Bank/Exchange',
            txn_id: 
            status: 
            meta:
          },

		  Sample response:
		  {
            paymentMode: 'Bank/Exchange',
            txn_id: "7df55d22-fa5e-4ca2-9af4-a39c95f18b3a"
            status: 0
            meta: {offerId: "1630402767550"}
          },
	 


// In case of Wallet payment
      {
        paymentMode: 'Wallet',
        status: 
        recievedAmount:
        currency:
      },

       Sample response:
	   {
		   paymentMode: 'Wallet',
		   status:"completed",
		   recievedAmount:10.00,
		   currency:"ETH"
	   }
```

### You can refer to the [REFERENCE\_LINK](https://github.com/RocketFuel-BlockChain-Inc/rocketfuel-readme/tree/master) for demonstration.


# Payment Processing

There are two ways to use payment processing:

1. Payment page
   1. After payment, the shopper will be redirected to "redirectUrl" passed during Invoice link generation.
2. Payment Widget
   1. After payment a window callback message will be sent byu our widget to update on the status of the payment


# RKFL Payment Page

**Prerequisite: An invoice link was generated and redirected to the payment page.**

![](/files/dDdX2P4S8TMz0PZKI6aN)

When paying using a crypto exchange, shoppers need to connect their exchange; once connected, it will show connected. They also have the option to select the currency using which they wish to pay. Shoppers can also connect to other exchanges besides Coinbase, such as BinanceUS, Kraken, etc.

![](/files/zB48XAwgsILzLCovfXyO)

If shoppers want to pay using their wallet, they have to change the tab to 'Crypto Wallet' and scan the QR code in their wallet app to pay. They also have the option to select the currency using which they wish to pay. Once paid, they will have to click on 'Confirm Payment' to confirm their payment.

![](/files/C2UqYmmxBAh3K7UU3SRg)

One more option which shoppers have is to pay using bank transfers. For this, they must click on the 'Bank Transfer' tab, connect their bank account, and select USD as payment currency.

To connect their bank account, shoppers can click on '+Connect Your Bank' ,button, and on the next screen click "+Add Bank Account." Then they have to select their bank.

![](/files/ZjeDij2KDzu4ofVI42rS)

After selecting the bank they can fill in their Username and Password and submit it. Post this they have to verify their identity by requesting security code on their mobile or email.

![](/files/Io91W3bPH9PSfiP3Utl0)

After you have received your code, fill that in and click Submit. After this, you can select the account you want to connect to and click Continue. You will see a success message. You will now be able to pay using bank transfer.

![](/files/lsJ2LFF7EEfZ73iuxoSG)

![](/files/LfZ0UN0NGofGWekxbZoZ)

{% hint style="info" %}
Note: Bank transfer is only available if the shopper has set USD as currency. For any other currency, bank transfer is not available at this time.
{% endhint %}


# RKFL Payment Widget

**RKFL JS** [**CDN**](https://d3rpjm0wf8u2co.cloudfront.net/static/rkfl.js) **and Implementation**

* Add the script from [**CDN**](https://d3rpjm0wf8u2co.cloudfront.net/static/rkfl.js) to the Merchant site.
* Once we get the response with the UUID from the backend. We will initialize an object of the above-included script. We pass the following :
  * uuid
  * callback function
  * environment
  * Token

Copy

```
    const  uuidInfo = JSON.parse(result);
   
     if(uuidInfo.error !== undefined){
        alert("Order placement failed");
        return  false;
    }
    
    uuid = uuidInfo.uuid;
    
    rkfl = new RocketFuel({
        uuid,
        callback:  callBackFunc,
        environment:  "<%= developmentEnv %>"  // prod, preprod
    });
```

* After initialising the object, start the payment by calling the initPayment method of the above script.

Copy

```
    function  startPayment(){
        rkfl.initPayment();
    }
```

* Callback payload

Copy

```
 // In case of Bank/Exchange payment
          {
            paymentMode: 'Bank/Exchange',
            txn_id: 
            status: 
            meta:
          },

          Sample response:
          {
            paymentMode: 'Bank/Exchange',
            txn_id: "7df55d22-fa5e-4ca2-9af4-a39c95f18b3a"
            status: 0
            meta: {offerId: "1630402767550"}
          },



// In case of Wallet payment
      {
        paymentMode: 'Wallet',
        status: 
        recievedAmount:
        currency:
      },

       Sample response:
       {
           paymentMode: 'Wallet',
           status:"completed",
           recievedAmount:10.00,
           currency:"ETH"
       }
```


# Transaction Lookup

For more information on transaction statuses, [click here](/developer-guides/api-reference/payins/rocketfuel-ui-integration/transaction-statuses) to access the full guide.


# Lookup using Auth

RKFL system offers Transaction lookup functionality. The merchant should have access token to call Transaction lookup API, Authentication API can be used to get access token.

<mark style="color:green;">`POST`</mark> `/purchase/transactionLookup`

#### Headers

| Name                                            | Type   | Description                      |
| ----------------------------------------------- | ------ | -------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |
| Content-Type<mark style="color:red;">\*</mark>  | String | application/json                 |

#### Request Body

| Name                                   | Type   | Description                                                                      |
| -------------------------------------- | ------ | -------------------------------------------------------------------------------- |
| txId<mark style="color:red;">\*</mark> | String |                                                                                  |
| type                                   | String | <p>Allowed values:</p><p>     'TXID', 'ORDERID'<br><br>Default value: 'TXID'</p> |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
    "ok": true,
    "result": {
        "id": "f84d01c4-587f-496f-8b7e-6bad916e95dd",
        "status": 1,
        "meta": {
            "hash": {
                "value": [
                    "66ce480ab083bc352dc852f440a3d671afde583d44da8b7ca2288225ff46aae2",
                    "5fcb0933fea8b80080c5f4ed2f4786b1acc5b33bbd71327dff6e0add96a4031d"
                ],
                "network": "ethereum"
            },
            "offerId": "DEFG123"
            "receiverAddress": "0xEcb977e1d467FC5f8Deb0f0dc4D7b7D0E96Fa6F9"
        },
        "totalAmount": "0.00130036",
        "receivedAmount": "0.0015",
        "currency": "USD",
        "crytoCurrency": "ETH"
    }
}
```

{% endtab %}
{% endtabs %}

For more information on transaction statuses, [click here](/developer-guides/api-reference/payins/rocketfuel-ui-integration/transaction-statuses) to access the full guide.


# Lookup using Public Key

The RKFL provides a separate API to get the latest transaction status. This API accepts "merchant\_i&#x64;*" and "transaction*\_id" as a request payload encrypted by the public RSA key and returns the response in JSON format.

```
// Object to encrypt
const toEncrypt = {
      merchantId: <merchant_id>, 
      transactionId: <transaction_id>
};

// Generate an encrypted request payload
export const data = async (toEncrypt, publicKey) => {
  const buffer = Buffer.from(toEncrypt);
  const encrypted = crypto.publicEncrypt(publicKey, buffer);
  return encrypted.toString('base64');
};

// merchantId – Unique identifier of the Merchant in the Rocketfuel, will get it from the portal. 
// transactionId – Unique identifier of the Transaction initiated by Shopper using RocketFuel, will get it from the Webhook/callback. 
```

<mark style="color:green;">`POST`</mark> `/purchase/invoiceLookup`

#### Headers

| Name                                            | Type   | Description                      |
| ----------------------------------------------- | ------ | -------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |

#### Request Body

| Name                                   | Type   | Description               |
| -------------------------------------- | ------ | ------------------------- |
| data<mark style="color:red;">\*</mark> | String | Encrypted request payload |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
    "ok": true,
    "result": [
        {
            "id": <Transaction_id>,
            "status": <Status>,
            "meta": {
                "offerId": <Offer_id>
            },
            "amount": "1.598457239956444619",
            "receivedAmount": "0",
            "currency": "ETH"
        }
    ]
}
```

{% endtab %}
{% endtabs %}

### The webhook payload contains the following fields:

1. **id** – RocketFuel transaction identifier.
2. **status** – 10/0/1 etc. For more information on transaction statuses, [click here](/developer-guides/api-reference/payins/rocketfuel-ui-integration/transaction-statuses) to access the full guide.
3. **meta**
   * **offerId** – Unique identifier assigned to the merchant.
4. **amount** – The total price of the complete order.
5. **receivedAmount** – The amount actually received by RocketFuel for the order.
6. **currency** – The unit of currency used by the shopper to make the payment.


# Webhooks

To register Webhook URL, use Shop callback URL.

Callback URL should respond with status 200 for GET request

![](/files/qfhShdsNZgbYJEokiGH1)

## Rocketfuel Webhook and Events <a href="#markdown-header-rocketfuel-webhook-and-events" id="markdown-header-rocketfuel-webhook-and-events"></a>

RocketFuel webhook calls are triggered to update the merchant on the updated status of the transaction.

Rocketfuel webhooks support the following events:-

* Transaction is marked as pending/initiated
* Transaction is marked as partial paid
* Transaction is marked as successful
* Transaction is marked as failed

## Securing Callbacks <a href="#markdown-header-securing-callbacks" id="markdown-header-securing-callbacks"></a>

Order callbacks originating from RocketFuel will be signed using our callback signing RSA private key.

If you would like to verify callbacks manually in the language of your choice, the message digest used is SHA256, the message that is signed is the POST body, the padding scheme is PKCS1\_v1\_5, and the signature to be verified is present in the ‘signature’ HTTP data encoded as base64.

**Examples**

{% tabs %}
{% tab title="PHP" %}

```php
public function verifyCallback($body, $signature)
{
    $signature_buffer = base64_decode( $signature );
    return (1 == openssl_verify($body, $signature_buffer, self::getCallbackPublicKey(), OPENSSL_ALGO_SHA256));
}
```

{% endtab %}

{% tab title="Node.js" %}

```
function verifySignature(body, public_key_rsa, signature) {
  const verifier = crypto.createVerify('RSA-SHA256');
  verifier.update(body);
  return verifier.verify(public_key_rsa, signature, 'base64');
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Linq;

public class EncryptionUtility
{
    public static bool VerifySignature(string body, string signature)
    {
        try
        {
            // Decode the base64 signature
            byte[] signatureBuffer = Convert.FromBase64String(signature);
            byte[] bodyBuffer = Encoding.UTF8.GetBytes(body);

            using (RSA rsa = RSA.Create())
            {
                // Import the public key
                rsa.ImportFromPem("public_key_rsa");

                // Verify the signature using SHA256
                return rsa.VerifyData(
                    bodyBuffer,
                    signatureBuffer,
                    HashAlgorithmName.SHA256,
                    RSASignaturePadding.Pkcs1
                );
            }
        }
        catch (Exception ex)
        {
            // Handle or log the exception as needed
            Console.WriteLine($"Verification error: {ex.Message}");
            return false;
        }
    }
}
```

{% endtab %}
{% endtabs %}

### Test data <a href="#markdown-header-test-data" id="markdown-header-test-data"></a>

RKFL provides support to custom parameters (optional) in the response based on the type of response Method passed in the invoicing API. Following is an example for GET & POST Custom parameter payload

1\. GET\
&#x20;   Query Parameters in webhook URL :- \<callback URL>?<mark style="color:green;">custom1=crypto\&custom2=RKFL\&custom3=credit</mark>

**Body Payload**

```
{
  type: 'rf:alert',
  data: {
    data: '{"amount":"11","conversionRate":{"fiatCurrency":"USD","rate":1},"cryptoAmount":"11","cryptoCurrency":"USD","currency":"USD","offerId":"3910","paymentStatus":"0","receivedAmount":"0","referenceId":"d30290d4-7c91-44ef-930a-9baa81733702","status":true,"transactionId":"874eba00-674c-4a39-afd2-3e3a5f8d521f"}',
    conversionRate: { fiatCurrency: 'USD', rate: 1 },
    amount: '11',
    currency: 'USD',
    referenceId: 'd30290d4-7c91-44ef-930a-9baa81733702',
    offerId: '3910',
    transactionId: '874eba00-674c-4a39-afd2-3e3a5f8d521f',
    status: true,
    paymentStatus: '0',
    cryptoAmount: '11',
    cryptoCurrency: 'USD',
    receivedAmount: '0',
    isSubscription: false,
    subscription: {}
  },
  signature: 'n/3otT5xpyG2AoUKnIhOhIFcpHhnqyUE8h044IO04zp1EevcH62CRyPmXqv2z6AJSv2pplEy8IlBWeVFCwkEF6KIJeANeagJNSUevAqgd437W+BjpFmR9M3vj353m26h4hSnAeEYWl375iQfl7sQ0tnmDyFXOKyz42ssvsYcL0bKywsYOlKwyusoNGVjC1yCkTTVBFIMUQXgFHceRkbhEFUMQA7inw2Ux2s+Ncj+u0IVGXsFcRk/CdkcQX0r1/Q6i6rmpujovDyKyn/JGkJOKH3B62tSFy0hilH36t7vY2Q8o7Re/9cFXQNayGszY89Ijn8qNAgr4P7hn7q/goMrfQ=='
}
```

2\. POST

&#x20;   Webhook URL :- \<Callback URL>

Custom parameters will be received under key <mark style="color:green;">customParameter</mark>

**Body Payload**

```
  {
  type: 'rf:alert',
  data: {    data: '{"amount":"11","conversionRate":{"fiatCurrency":"USD","rate":1},"cryptoAmount":"11","cryptoCurrency":"USD","currency":"USD","offerId":"3917","paymentStatus":"0","receivedAmount":"0","referenceId":"7459f87b-c5f0-4752-a1ed-96f73cbeae94","status":true,"transactionId":"13c40f35-fef4-4107-9abe-e15834a09def"}',
    conversionRate: { fiatCurrency: 'USD', rate: 1 },
    amount: '11',
    currency: 'USD',
    referenceId: '7459f87b-c5f0-4752-a1ed-96f73cbeae94',
    offerId: '3917',
    transactionId: '13c40f35-fef4-4107-9abe-e15834a09def',
    status: true,
    paymentStatus: '0',
    cryptoAmount: '11',
    cryptoCurrency: 'USD',
    receivedAmount: '0',
    isSubscription: false,
    subscription: {}
  }, 
  signature: 'FBPIcIKGFQQFRzDWffca96F9Hb8iK+K4zSYxK1csGyJCAAjN1z59vki9Hgx9+tFo2a/qAPavGm8w+5VgSLIGR5UYadaAD2cy2RR4RRhShH4RtkjPiRd8iurR977FEnLjDjKLkL3lFs17Lli6nWzSsom1pj/nWlnNgaN3EdiB16ZMtVVeqXhULYk/N/yKGonsWiRxwQS5rhaD+wFXAiDwT49uK4vDkgbC4UCvz7Sz7/gsuzfj3ULqkoPPg9tWLezlovl99iFZ/WpRKV4iv3eDadNhLcFarRNGDcIbH98S0ueZCBiM1aSmQaOF/YiUAVq6qjlfCd85KIDc7FKYKQSWwg==',
  customParameter: {
    custom1: 'crypto',
    custom2: 'RKFL',
    custom3: 'credit'
  }
}
```

**NOTE: There can be multiple custom parameters.**

**Where**

1. amount :- Amount (Float)
2. currency :- Currency of transaction
3. offerId :- Merchant database Order/offer id
4. referenceId :- RKFL database reference transaction id
5. status:-
   * true:- successful
   * false:- pending/failed/partial
6. paymentStatus (For more information on transaction statuses, [click here](/developer-guides/api-reference/payins/rocketfuel-ui-integration/transaction-statuses) to access the full guide.)
   * 0 - pending
   * 1/2/3/4 - successful
   * -1 - failed
   * 101 - partial
   * 19 - timedout
7. cryptoAmount :- Crypto value of transaction
8. cryptoCurrency :- Crypto currency used
9. receivedAmount :- Received crypto amount
10. conversionRate :- Rate of conversion from fiat to crypto during transaction
    * fiatCurrency - Base currency for conversion
    * rate - conversion rate (multiplier)
11. isSubscription: true if the cart contains subscription item else false
12. subscription: subscription id of the cart item (string)
13. customParameter: Custom parameters are the passthrough variables passed from merchant at the time of invoice link/uuid generation. It consist of array of object (name, value). All "name" variables serve as the key for customParameter while "value" serves as the value of keys. This is helpful if merchant wishes to get back some custom parameters to identify or apply any business logic.&#x20;

**Authenticity/Verification of request from RKFL**

You can test the authenticity of the request emerging from Rocketfuel by using following public key to generate signature. Once the signature is generated, you can tally the signature sent by Rocketfuel.

#### Signature: <a href="#markdown-header-signature" id="markdown-header-signature"></a>

```json
f09HYBeZFqMkeo/ri5kZI0DGnCiSnYSl2KSZLaB3tIL722a1IsnCSsWsfdZRAiv/7e/MdqguXTBmEUdBzKnzR2ATBJF5VRtLeD7LhnNxpSs1+sAAgIwI2JS6nkRj8DTKZbZUzweGSdgARZfxxoVqQaaW4DPb8kXhGPVo/tOG8Rw62Vbyg279ysgWCtNuYltKg05DFxfWy287LtBnvs3kaw0xoTuR5rCnEncFFLRozSCPRSRU0Ebb3kfWNK6surso9OrqVkdbzXLCpLuLkkakxNvNpahzvB3DuT2zZn0NFxP8YGJquAVcWLh2aj0syRPDArHY5An5CtQ6nuiiJB6jTw==
```

#### Public RSA key <a href="#markdown-header-public-rsa-key" id="markdown-header-public-rsa-key"></a>

```
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2e4stIYooUrKHVQmwztC
/l0YktX6uz4bE1iDtA2qu4OaXx+IKkwBWa0hO2mzv6dAoawyzxa2jmN01vrpMkMj
rB+Dxmoq7tRvRTx1hXzZWaKuv37BAYosOIKjom8S8axM1j6zPkX1zpMLE8ys3dUX
FN5Dl/kBfeCTwGRV4PZjP4a+QwgFRzZVVfnpcRI/O6zhfkdlRah8MrAPWYSoGBpG
CPiAjUeHO/4JA5zZ6IdfZuy/DKxbcOlt9H+z14iJwB7eVUByoeCE+Bkw+QE4msKs
aIn4xl9GBoyfDZKajTzL50W/oeoE1UcuvVfaULZ9DWnHOy6idCFH1WbYDxYYIWLi
AQIDAQAB
-----END PUBLIC KEY-----
```


# Handling Partial Payments

There is a possibility of shoppers making a partial payment when paying using a crypto wallet. We do update the shoppers to complete the partial payment. However, some merchants are okay with whatever the shopper has paid and want to issue goods/services as per the payment amount. In this case, merchants may close the partial payment so that they can give the goods/service for the amount paid by the shopper, and we can settle the partial payments to the merchants. This API will help the merchants to mark a partial payment as closed.

{% hint style="info" %}
It is advised to merchants that they should give shoppers up to 24 hours to pay the remaining amount before marking the transaction as closed.
{% endhint %}

{% hint style="info" %}
The merchants are requested to mark the transaction closed within two weeks of the partial payment by the shopper. After two weeks, the transaction cannot be marked closed.
{% endhint %}

<mark style="color:green;">`POST`</mark> `/closePartialTx`

#### Headers

| Name                                             | Type   | Description        |
| ------------------------------------------------ | ------ | ------------------ |
| "Content-Type"<mark style="color:red;">\*</mark> | String | "application/json" |

#### Request Body

| Name                                           | Type   | Description                                  |
| ---------------------------------------------- | ------ | -------------------------------------------- |
| clientId<mark style="color:red;">\*</mark>     | String | Merchant Client Id                           |
| encryptedReq<mark style="color:red;">\*</mark> | String | Encrypted string of offerId by client secret |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "ok": true,
    "result": {
        "success": true
    }
}
```

{% endtab %}

{% tab title="400: Bad Request " %}

```javascript
{
    "ok": false,
    "statusCode": 400,
    "data": {},
    "message": "No partial transaction found"
}
```

{% endtab %}
{% endtabs %}

```
// Example
 
offerId: "d21c44a5-9ff7-44d6-9dbc-158753184d5d"
clientSecret: "8e6e7524-202d-424d-b2a2-431ff1117e27" 

Then encrypt this offerId (JSON format) with clientSecret:
i.e, Encrypt JSON {"offerId":"d21c44a5-9ff7-44d6-9dbc-158753184d5d"} with "8e6e7524-202d-424d-b2a2-431ff1117e27"

And its output will be encryptedReq param 

For above offerId and clientSecret, encryptedReq is "U2FsdGVkX1+T1BocXOZHJA2paoYtiFC1GIl99jjtPQEWuxF2ikm8VT8eaenS5TDc67idkKfwFqBBd9dli/Ssdd28aXp6SKaBEtkkytTAtiA="
```

**Below is the sample postman Request**

Copy the following to the Pre-script

```
var CryptoJS = require('crypto-js');
var data = CryptoJS.AES.encrypt(JSON.stringify({
 offerId: '<<TRANSACTION_ORDER_ID>>'
}), '<<MERCHANT_CLIENT_SECRET>>').toString();
pm.variables.set("encryptedPartialPayload", data);
```

**Sample Curl Request**

```
curl --location 'https://app.rocketfuelblockchain.com/api/closePartialTx' \
--header 'Content-Type: application/json' \
--data '{
"clientId":"<<MERCHANT_CLIENT_ID>>",
"encryptedReq":"{{encryptedPartialPayload}}",
"forceUpdate": false
}'
```

forceUpdate is an optional parameter and its default value is true. If passed will value false, it will not close partial transaction if there is a refund request on the transaction


# Transaction  Statuses

***

This section provides a reference for all possible transaction statuses and how to handle them. You will also receive webhook updates whenever a status changes, and you can consult this guide when using the transaction lookup APIs.

### Status Codes

| Status Code       | Description                                                                                                                                                                                                              |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 10                | Initial state. No payment detected yet. Transaction is marked as unpaid.                                                                                                                                                 |
| **0**             | Pending transaction. Payment detected but awaiting final confirmation.                                                                                                                                                   |
| **1 / 2 / 3 / 4** | Treated as **Success**. Indicates the payment has been successfully received.                                                                                                                                            |
| **101**           | Partial payment received. The order remains open, and the user can send additional payment to complete it.                                                                                                               |
| **1011**          | Partial payment closed by the merchant. No further payments are accepted. can be close by this api:[ handling partial cases](/developer-guides/api-reference/payins/rocketfuel-ui-integration/handling-partial-payments) |
| **201**           | Payment amount less than order value (**Underpaid**). *Enabled only if the merchant opts into handling such cases. Write us at <contact@rocketfuel.inc> to enable this feature.*                                         |
| **202**           | Payment amount greater than order value (**Overpaid**). *Enabled only if the merchant opts into handling such cases. Write us at <contact@rocketfuel.inc> to enable this feature.*                                       |
| **-1**            | Transaction rejected or failed.                                                                                                                                                                                          |
| 19                | **Timed Out** transaction.                                                                                                                                                                                               |

***

### Timed Out Transactions

A **Timed Out** transaction occurs when a payment cannot be confirmed within the expected timeframe. This can happen due to network congestion, delays in confirmation, or other technical reasons.

**Key Points:**

* Status code for timed-out transactions: **19**
* These transactions are not marked as successful.
* A **webhook event** is triggered whenever a transaction moves to this status.
* Depending on your system, you can treat this as a failed payment or allow the user to retry the payment.

### Partial Payment Use Cases

1. **Allow Completion of Partial Payment**
   * User makes a partial payment and can send additional payment(s) to complete the order.
   * If the remaining amount is not received within the allowed time, the transaction moves into a final **Partial** state, and a refund can be requested by the shopper.
2. **Do Not Allow Partial Payments**
   * If the first payment is partial, no further payments are accepted.
   * A **Refund** button is displayed to the user immediately. (check the screenshot below)<br>

     <figure><img src="/files/4cSA6ViYCtwpN9CkrzR5" alt=""><figcaption></figcaption></figure>

***

### Force Refund Use Case

To enable this feature, contact us at <_contact@rocketfuel.inc>.\_

* Merchants can trigger a **force refund** to immediately close a transaction and refund the user.
* No further payments are accepted once the refund is initiated.
* This is useful when merchants do not want to handle incomplete or partial payments.


# Custom UI Integration

You can refer to this link for custom integration: <https://payin-api.rocketfuel.inc/>

<div data-full-width="true"><figure><img src="/files/cqvqPW7Qg8O7ZNNIPy3S" alt=""><figcaption></figcaption></figure></div>


# Cryptocurrencies listing

RKFL supports 'N' numbers of cryptocurrencies for crypto wallet payments. A merchant can configure which cryptocurrencies will display on his payment page.&#x20;

The RKFL supports a faster payment mechanism for a few of the cryptocurrencies. The API returns these cryptocurrencies with a key "fasterConfirmation: true" that helps to display an icon on the UI. At the rocketfuel plugins, RKFL-hosted checkout page, and iFame a "rocket" icon is displayed to indicate the faster payment cryptocurrencies. See the attached screenshot of the idea of showing a "rocket" icon in the cryptocurrency list.&#x20;

This API returns the merchant's enabled exchanges list, ex: in the below screenshot, the merchant "Hush Puppies" has enabled three exchanges (Coinbase, BinanceUs, and Kraken) to display on his page.

![](/files/r2UCDO4O9rNCNJCL8EJQ)

<mark style="color:blue;">`GET`</mark> `/currencies?amount={cart_total}&currency=USD&merchant_id={merchant_id}&include_merchant=1`

Only include `include_merchant` and `merchant_id` query paramaters if you wish to filter list by selected cryptocurrencies.\
\
To select cryptocurrencies, visit the [settings page](broken://spaces/fHQ9KraQxfbb088JTCbe/pages/fP1GRK0qWTcDeJruRE6u) on  your portal.

#### Headers

| Name                                            | Type   | Description                      |
| ----------------------------------------------- | ------ | -------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |
| Content-Type                                    | String |                                  |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": [
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/doge.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/doge.png",
      "id": "DOGE",
      "fullTitle": "DogeCoin",
      "decimals": 8,
      "currentRate": "0.05266249166666666667",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": 1,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "dogecoin:%%address%%?amount=%%amount%%",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/eth.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/eth.png",
      "id": "ETH",
      "fullTitle": "Ethereum",
      "decimals": 8,
      "currentRate": "854.620833325",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": 2,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "ethereum:%%address%%?amount=%%amount%%&value=%%amount%%",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/ltc.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/ltc.png",
      "id": "LTC",
      "fullTitle": "Litecoin",
      "decimals": 8,
      "currentRate": "42.13333333333333333333",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": 3,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "litecoin:%%address%%?amount=%%amount%%",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/usdc.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/usdc.png",
      "id": "USDC",
      "fullTitle": "USDC",
      "decimals": 6,
      "currentRate": "0.83333333333333333333",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": "USD",
      "sort": 4,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "usdc:%%address%%?amount=%%amount%%",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/btc.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/btc.png",
      "id": "BTC",
      "fullTitle": "Bitcoin",
      "decimals": 8,
      "currentRate": "15932.89999999166666666667",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": 5,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "bitcoin:%%address%%?amount=%%amount%%",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/usdt.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/usdt.png",
      "id": "USDT",
      "fullTitle": "Tether",
      "decimals": 6,
      "currentRate": "0.8322125",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/shib.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/shib.png",
      "id": "SHIB",
      "fullTitle": "SHIB",
      "decimals": 8,
      "currentRate": "0.00000815833333333333",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "shiba:%%address%%?amount=%%amount%%",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/dash.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/dash.png",
      "id": "DASH",
      "fullTitle": "Dash",
      "decimals": 8,
      "currentRate": "34.60416666666666666667",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "dash:%%address%%?amount=%%amount%%",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/wluna.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/wluna.png",
      "id": "WLUNA",
      "fullTitle": "WLUNA",
      "decimals": 8,
      "currentRate": "0.00010071666666666667",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/ust.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/ust.png",
      "id": "UST",
      "fullTitle": "UST",
      "decimals": 8,
      "currentRate": "0.04031583333333333333",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "",
      "fasterConfirmation": true
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/cgld.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/cgld.png",
      "id": "CGLD",
      "fullTitle": "CGLD",
      "decimals": 8,
      "currentRate": "0.69",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "",
      "fasterConfirmation": false
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/xrp.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/xrp.png",
      "id": "XRP",
      "fullTitle": "Ripple",
      "decimals": 6,
      "currentRate": "0.258751775",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "ripple:%%address%%?amount=%%amount%%",
      "fasterConfirmation": false
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/stx.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/stx.png",
      "id": "STX",
      "fullTitle": "Stox",
      "decimals": 6,
      "currentRate": "0.32116666666666666667",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "",
      "fasterConfirmation": false
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/req.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/req.png",
      "id": "REQ",
      "fullTitle": "Request Network",
      "decimals": 8,
      "currentRate": "0.10279165833333333333",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "",
      "fasterConfirmation": false
    },
    {
      "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/gala.svg",
      "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/gala.png",
      "id": "GALA",
      "fullTitle": "GALA",
      "decimals": 8,
      "currentRate": "0.04323333333333333333",
      "symbol": "",
      "isPayment": true,
      "isFiat": false,
      "fiatEquivalent": null,
      "sort": null,
      "isEnabled": true,
      "isStableCoin": false,
      "isTopCoin": false,
      "network": "",
      "fasterConfirmation": false
    }
  ]
}
```

{% endtab %}
{% endtabs %}


# Generate QR Code

{% hint style="warning" %}
DEPRECATED&#x20;
{% endhint %}

RKFL system provides API to generate transaction and in response provides transaction id and qrString which can be useful for merchant.

API endpoint: POST /purchase/qr/generate

```
// Headers
Authorization: "Bearer" + merchant access token
x-transaction-source: qr-code-api
```

```
// Here is the sample of the request payload. 
POST /purchase/qr/generate
{
    "amount":"1.00",
    "currency":"USD",
    "cryptoCurrency":"ETH",
    "orderId":"ABCD123",
    "cart":[
        {
            "id":"1",                   //Required
            "name":"Bag",          //Required
            "price":1,                  //Required
            "quantity":1,               //Required
            //only add the below, if the product is a subscription item.
            "isSubscription": "",            //Optional
            "frequency": "",                 //Optional
            "subscriptionPeriod":""          //Optional
            "merchantSubscriptionId": ""     //Optional
        }
    ],
    "customerInfo": {
        name: required (string)
        email: required (string)
        phone: optional (string)
        address: optional (string)
    },
    //"customParameter" is optional field
    "customParameter": {
        "returnMethod": "POST/GET",
        "params": [
          {
            "name": "var",
            "value": "1302*6649c8793fa687fe708618ae52344e26*1685*2*1*128*76"
          },
          {
              "name": "custom",
              "value": "1302|6649c8793fa687fe708618ae52344e26|2|1|128|2|1685"
          }
        ]
    }
}

// isSubscription: true/false 
// subscriptionPeriod: [number][period] - for example 1y, 2m, 3w
// frequency: weekly/monthly/quarterly/half-yearly/yearly
// merchantSubscriptionId: Subscription id for merchant system. This key will use to communicate the recurring payment status.
```

```
// Here is the sample of the response payload.
200:Ok   Success
{
    "ok": true,
    "result": {
        "totalAmount": "0.17800800",
        "currency": "USD",
        "crytoCurrency": "ETH",
        "id": "ee802a07-d857-4792-ae48-619775daf85b",
        "meta": {
            "offerId": "ABCD123",
            "receiverAddress": "0xB5d71af0A642ef800E013B996E8116318EF9B520",
            "qrString": "ethereum:0xB5d71af0A642ef800E013B996E8116318EF9B520?amount=0.21360960&value=0.21360960"
        }
    }
}
```

#### Payment Status

* 10 = QR code/receiving wallet address generated for shopper
* 0 = pending
* 1/2/3/4 = successful
* -1 = failed
* 101 = partial
* 19 = timedout


# QR Payment Status

RKFL provides transactionExternalStatus API for checking transactions status, status can be pending, partial or completed

<mark style="color:green;">`POST`</mark> `/purchase/transactionExternalStatus`

#### Headers

| Name                                            | Type   | Description                      |
| ----------------------------------------------- | ------ | -------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |

#### Request Body

| Name                                   | Type   | Description |
| -------------------------------------- | ------ | ----------- |
| txId<mark style="color:red;">\*</mark> | String |             |

{% tabs %}
{% tab title="200: OK Success" %}

```json
{
  "ok": true,
  "result": {
    "responseObj": {
      "txStatus": "completed",
      "recievedAmount": null,
      "disablePartialSuccess": false,
      "forceRefundOnPartialPayment": false,
      "cryptoCurrency": "ETH"
    }
  },
  "tracingId": "26c8acd0-60fd-4dce-829b-221a205e2c0f#1726759070994"
}
```

{% endtab %}
{% endtabs %}


# Transactions Lookup

Please refer to this link: <https://docs.rocketfuel.inc/developer-guides/api-reference/payins/rocketfuel-ui-integration/transaction-lookup>


# Webhooks

Please refer to this link: <https://docs.rocketfuel.inc/developer-guides/api-reference/payins/rocketfuel-ui-integration/webhooks>


# Handle Partial Payment

Please refer to this link: <https://docs.rocketfuel.inc/developer-guides/api-reference/payins/rocketfuel-ui-integration/handling-partial-payments>


# Utility APIs


# Subscriptions/Recurring Payments

Following are the APIs that are required to create, debit, and cancel a subscription.

1. Create subscription - You can refer to the link given below to know the parameters required for creating a subscription:\
   \
   <https://docs.rocketfuel.inc/developer-guides/api-reference/generate-invoice-link><br>
2. Request a debit of funds for the subscription&#x20;

{% hint style="info" %}
Reminder emails are sent to the shoppers to make the pre-payment for the subscriptions with the invoice link or maintain the exchange balance equal to the bill amount.&#x20;
{% endhint %}

<mark style="color:green;">`POST`</mark> `/subscription/debit`

#### Request Body

| Name                                             | Type   | Description |
| ------------------------------------------------ | ------ | ----------- |
| merchantAuth<mark style="color:red;">\*</mark>   | String |             |
| merchantId<mark style="color:red;">\*</mark>     | String |             |
| orderId                                          | String |             |
| items                                            | Array  |             |
| subscriptionId<mark style="color:red;">\*</mark> | String |             |
| amount<mark style="color:red;">\*</mark>         | Number |             |
| currency<mark style="color:red;">\*</mark>       | String |             |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{

status: 200,

result: {

data: [{

      transactionId: response.id,

      amount: response.localAmount,

      currency: response.localCurrency,

      rateDivisor: response.rateDivisor,

      orderId: response.meta.offerId,

      status: response.status,

      userId,

      merchantId,

subscriptionId

}],

errors: [],

}
```

{% endtab %}
{% endtabs %}

3\. To cancel a subscription

<mark style="color:green;">`POST`</mark> `/subscription/cancel`

#### Request Body

| Name           | Type   | Description |
| -------------- | ------ | ----------- |
| merchantId     | String |             |
| merchantAuth   | String |             |
| subscriptionId | String |             |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{

status: 200,

result: { success: true }

}
```

{% endtab %}

{% tab title="400: Bad Request " %}

```javascript
{

  "ok": false,

  "statusCode": 400,

  "data": {

}

"message": "Subscription not found"

}
```

{% endtab %}

{% tab title="500: Internal Server Error " %}

```javascript
{
  "ok": false,

  "statusCode": 500,
  "data": {

}

"message": "Internal server error"

  }
```

{% endtab %}
{% endtabs %}


# Store info

The RKFL provides an API to return the store information to display on the payment page. However, the merchant website already has the shopper information to show on any page, and the RKFL API is optional.

The idea of the store info on the payment page is similar to the below image. Please note the logo of the merchant and " <*store\_name*>" next to it.

![](/files/qP0g64YNhqm1vDfD1tlP)

<mark style="color:blue;">`GET`</mark> `/stores`

#### Headers

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + mechant access token |
| Content-Type                                    | String | application/json                |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": {
    "merchant": {
      "id": "2335689b-7a4d-420a-9cc0-f5d765a96967",
      "shopData": {
        "url": "https://qa-woocommerce.rocketdemo.net/",
        "logo": "https://dev-rocketfuel-videos.s3.us-east-1.amazonaws.com/shoplogo/MjMzNTY4OWItN2E0ZC00MjBhLTljYzAtZjVkNzY1YTk2OTY3_1642923504.png",
        "companyName": "Hush Puppies ",
        "description": "Hush Puppies "
      }
    },
    "whiteLabel": {
      "id": 67,
      "partnerId": "089ee3b5-50fd-4cb2-9397-0f7a2d34613f",
      "colorSchema": {
        "partnerUrl": "https://rocketfuelblockchain.com",
        "contactEmail": "support@rocketfuelblockchain.com",
        "partnerLabel": "Rocketfuel"
      },
      "createdAt": "2022-03-31T08:17:54.759Z",
      "updatedAt": "2022-05-23T11:23:06.127Z",
      "partner": {
        "fullname": "mucofin"
      }
    },
    "settings": {
      "bankPaymentEnabled": true,
      "walletPaymentEnabled": true,
      "exchangePaymentEnabled": true,
      "tabs": [
        "Crypto Exchange",
        "Crypto Wallet",
        "Bank Transfer"
      ]
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Shopper


# Shopper manual signup

A shopper should register to the RKFL system to proceed with the payment. The RKFL system provides a seamless register & login experience with [shopper SSO login](https://docs.rocketfuelblockchain.com/developer-guides/api-reference/shopper-sso-login).

In any case, if SSO is not successful, the RKFL supports a manual signup process. The merchant website should display a signup form similar to the attached screenshot and ask the shopper to enter the details and register.

In the manual registration process, the shopper must [verify the email id](/developer-guides/api-reference/payins/utility-apis/shopper/verify-shoppers-email-id). &#x20;

![](/files/OfGuPtQiDtVUlRnsdbOf)

The register API accepts data in an encrypted format. The encryption algorithm is RSA, and the encryption key is the merchant's "Public Key."

```
// The key "encryptedReq" should generate from the below way.
export const encryptedReq = async (toEncrypt, publicKey) => {
  const buffer = Buffer.from(toEncrypt);
  const encrypted = crypto.publicEncrypt(publicKey, buffer);
  return encrypted.toString('base64');
};
```

<mark style="color:green;">`POST`</mark> `/auth/signup`

#### Headers

| Name         | Type   | Description      |
| ------------ | ------ | ---------------- |
| Content-Type | String | application/json |

#### Request Body

| Name                                           | Type   | Description      |
| ---------------------------------------------- | ------ | ---------------- |
| encryptedReq<mark style="color:red;">\*</mark> | String | Encrypted string |
| recaptcha                                      | String | Google recaptcha |

{% tabs %}
{% tab title="400: Bad Request Validation error" %}

```javascript
{
  "ok": false,
  "statusCode": 400,
  "data": {
    
  },
  "message": "Email is already in use"
}
```

{% endtab %}

{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": {
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjBkZTIyMDk5LTEzM2MtNDAzZi1hMTgxLWRmMjFhMGM2M2NhNiIsImlhdCI6MTY1NjQxNTU5OSwiZXhwIjoxNjU2NDE3Mzk5fQ.sfQxkh-LislyDFRJVjaWeCqIy4Gg6SK5yGUSf8zA4gU",
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjBkZTIyMDk5LTEzM2MtNDAzZi1hMTgxLWRmMjFhMGM2M2NhNiIsImlhdCI6MTY1NjQxNTU5OSwiZXhwIjoxNjU2NDE3Mzk5fQ.sfQxkh-LislyDFRJVjaWeCqIy4Gg6SK5yGUSf8zA4gU",
    "newResendTime": 1656415629744
  }
}
```

{% endtab %}
{% endtabs %}


# Verify shopper's email id

For manual registration, the shopper must verify his email address to activate his account. The merchant website should display a form to accept the OTP, similar to the below screenshot.

![](/files/dzN45alu6BbJlmsjplXR)

<mark style="color:green;">`POST`</mark> `/auth/validate-email`

#### Headers

| Name                                            | Type   | Description                                                                                    |
| ----------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>"Bearer" + shopper access token</p><p>Shopper access token return in /auth/register API</p> |
| Content-Type                                    | String | application/json                                                                               |

#### Request Body

| Name | Type   | Description                  |
| ---- | ------ | ---------------------------- |
| code | String | OTP received at the email id |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": {
    "success": true
  }
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid code" %}

```javascript
{
  "ok": false,
  "statusCode": 400,
  "data": {
    
  },
  "message": "Code invalid"
}
```

{% endtab %}
{% endtabs %}


# Shopper manual login

A shopper should log in to the RKFL system to make and track the payment. The RKFL system provides a seamless login experience with shopper SSO login.

In any case, if SSO is not successful, the RKFL supports a manual login process. The merchant website should display a login form similar to the attached screenshot and ask the shopper to enter the credentials and log in.

![](/files/p8HvkKp6n6HsS2DG29AC)

The register API accepts data in an encrypted format. The encryption algorithm is RSA, and the encryption key is the merchant's "Public Key."

```
// The key "encryptedReq" should generate from the below way.
export const encryptedReq = async (toEncrypt, publicKey) => {
  const buffer = Buffer.from(toEncrypt);
  const encrypted = crypto.publicEncrypt(publicKey, buffer);
  return encrypted.toString('base64');
};
```

<mark style="color:green;">`POST`</mark> `/auth/signin`

#### Headers

| Name                                           | Type   | Description      |
| ---------------------------------------------- | ------ | ---------------- |
| Content-Type<mark style="color:red;">\*</mark> | String | application/json |

#### Request Body

| Name         | Type   | Description      |
| ------------ | ------ | ---------------- |
| encryptedReq | String | Encrypted string |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": {
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRiNmJkMTZhLTIyZjUtNDExYS1hN2U0LTEwY2Q3ODcxMzU1YiIsImlhdCI6MTY1NTk4MjQ4MCwiZXhwIjoxNjU1OTg0MjgwfQ.aKnfIs_KnRSASZC8C1GYJCLZsA7pbhPc8QX9ql7Xf08",
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRiNmJkMTZhLTIyZjUtNDExYS1hN2U0LTEwY2Q3ODcxMzU1YiIsImlhdCI6MTY1NTk4MjQ4MCwiZXhwIjoxNjU1OTg0MjgwfQ.aKnfIs_KnRSASZC8C1GYJCLZsA7pbhPc8QX9ql7Xf08",
    "status": 1
  }
}
```

{% endtab %}

{% tab title="401: Unauthorized Unauthorized" %}

```javascript
{
    "ok": false,
    "statusCode": 401,
    "data": {},
    "message": "Incorrect email and password pair"
}
```

{% endtab %}
{% endtabs %}


# Shopper info

The RKFL provides an API to return the logged-in shopper's information to display on the payment page. However, the merchant website already has the shopper information to show on any page, and the RKFL API is optional.

The idea of the shopper's info on the payment page is similar to the below image. Please note the text "Welcome <*shopper first\_name*>"

![](/files/qP0g64YNhqm1vDfD1tlP)

<mark style="color:blue;">`GET`</mark> `/users/me`

#### Headers

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + shopper access token |
| Content-Type                                    | String | application/json                |

{% tabs %}
{% tab title="200: OK Success" %}

```json
{
  "ok": true,
  "result": {
    "id": "4c93f824-a6e0-41fb-9035-f278116b2945",
    "email": "anuj.r@rocketfuelblockchain.com",
    "username": "Anuj",
    "fullname": "Test Name",
    "avatar": null,
    "profile": {
      "zip": "201301",
      "city": "NDA",
      "phone": "121 212 1211",
      "state": "UP",
      "address": "Address",
      "country": "IN",
      "lastName": "Name",
      "firstName": "Test",
      "dateOfBirth": "06-14-2002",
      "phoneCountry": 91
    },
    "status": 1,
    "type": 0,
    "kybCryptoStatus": 0,
    "kybBankStatus": 0,
    "shopData": {},
    "withdrawalAddresses": [],
    "ssoStatus": false,
    "enableCancelSubscription": false,
    "verification": null,
    "graphSettings": [],
    "is2faEnabled": false,
    "enableBankPayment": true,
    "verificationStatus": null
  }
}
```

{% endtab %}
{% endtabs %}


# Shopper wallet balance

This API is NOT a core element of the payment flow. However, this helps to make a user-friendly payment solution.

In case of exchange payment, the merchant website can display the shopper's wallet balance in the wallet listing. The wallet balance can show in the cryptocurrency and/or USD

This API returns the wallet listing enabled by the partner and the merchant. With the help of this API, the shopper will have information on his wallet balance and can avoid choosing the wallet whose balance is lower than the order amount.

In the below screenshot, please note the wallet listing of the connected OKcoin exchange where the wallet balance is showing for Litecoin in 0.00021890 LTC and 0.01 USD

![](/files/vCRCl709VqHtvLkvTJ4D)

<mark style="color:blue;">`GET`</mark> `/exchanges/check-balance/{exchange_name}?merchantId={RKFL_merchantId}`

![](/files/LzLdq4kvD9pupzLBp9ED) The value of exchange\_name are "coinbase/okcoin/kraken/gemini/binanceus"

#### Headers

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + shopper access token |
| Content-Type                                    | String | application/json                |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": {
    "message": "Updated now!/partner enabled currencies/merchant enabled currencies",
    "accounts": [
      {
        "id": "LTC",
        "accountId": "1ff90cc5-9d7b-5665-8861-3159f60415f1",
        "balance": "0.00021890",
        "currency": "LTC",
        "lastUpdate": "2022-07-01T18:56:10.460Z",
        "fullTitle": "Litecoin",
        "currentRate": "51.005",
        "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/ltc.svg",
        "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/ltc.png"
      },
      {
        "id": "ETH",
        "accountId": "a65fa908-9dd6-5810-866c-e6540038e5a6",
        "balance": "0.00000073",
        "currency": "ETH",
        "lastUpdate": "2022-07-01T18:56:10.460Z",
        "fullTitle": "Ethereum",
        "currentRate": "1067.785",
        "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/eth.svg",
        "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/eth.png"
      },
      {
        "id": "XRP",
        "accountId": "93a7b451-2f5e-5974-903d-6031c31ddb96",
        "balance": 0,
        "currency": "XRP",
        "lastUpdate": "2022-07-01T18:56:10.448Z",
        "fullTitle": "XRP",
        "currentRate": "0.313031",
        "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/xrp.svg",
        "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/xrp.png"
      },
      {
        "id": "LINK",
        "accountId": "d2759824-b198-5a02-a260-4f4365c70221",
        "balance": 0,
        "currency": "LINK",
        "lastUpdate": "2022-07-01T18:56:10.454Z",
        "fullTitle": "Chainlink",
        "currentRate": "6.07",
        "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/link.svg",
        "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/link.png"
      },
      {
        "id": "ALGO",
        "accountId": "c290ea3b-fe5a-5c85-9d1f-02857250bd91",
        "balance": 0,
        "currency": "ALGO",
        "lastUpdate": "2022-07-01T18:56:10.455Z",
        "fullTitle": "Algorand",
        "currentRate": "0.30629999",
        "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/algo.svg",
        "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/algo.png"
      },
      {
        "id": "BTC",
        "accountId": "fe04f6bf-c7e0-549c-b8f1-3a16d120d3e0",
        "balance": 0,
        "currency": "BTC",
        "lastUpdate": "2022-07-01T18:56:10.459Z",
        "fullTitle": "Bitcoin",
        "currentRate": "19391.42999998",
        "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/btc.svg",
        "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/btc.png"
      },
      {
        "id": "WBTC",
        "accountId": "823073dd-0544-5505-9f43-0c1087b8f46f",
        "balance": 0,
        "currency": "WBTC",
        "lastUpdate": "2022-07-01T18:56:10.459Z",
        "fullTitle": "Wrapped Bitcoin",
        "currentRate": "19416.87500001",
        "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/wbtc.svg",
        "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/wbtc.png"
      },
      {
        "id": "USDC",
        "accountId": "9304c6ce-0127-5234-a5a5-2fd9cbe4cad5",
        "balance": 0,
        "currency": "USDC",
        "lastUpdate": "2022-07-01T18:56:10.460Z",
        "fullTitle": "USD Coin",
        "currentRate": "1",
        "logo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/usdc.svg",
        "mobileLogo": "https://rocketfuel-assets.s3.amazonaws.com/assets/coins/mobile/currencies/usdc.png"
      }
    ]
  }
}
```

{% endtab %}
{% endtabs %}


# Exchange Payment


# Exchanges listing

RKFL supports 'N' numbers of crypto exchanges. A merchant can configure which exchanges will display on his payment page.

This API accepts the merchant access token and shopper access token in headers. It returns the merchant's enabled exchanges list and a key "connected: true" if the logged-in shopper is already connected with the exchange.

In the below screenshot, the merchant "Hush Puppies" has enabled three exchanges (Coinbase, BinanceUs, and Kraken) to display on his page, and the logged-in shopper is not connected with any exchange.

![](/files/Utcnp1XcS8vTKZo7xSyY)

The screenshot below shows that the merchant "Woo Commerce Dev" has enabled four exchanges (OKcoin, Coinbase, Kraken, and Gemini) to display on his page, and the logged-in shopper is not connected with OKcoin.

![](/files/G6R8UwVBM4j2uhbp3K8P)

Once the shopper is connected to any exchange and provides permission, the RKFL remembers the connection and keeps him connected until the connection string is invalid or the shopper closes the connection.

<mark style="color:blue;">`GET`</mark> `exchanges/my`

#### Headers

| Name                                            | Type   | Description                      |
| ----------------------------------------------- | ------ | -------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |
| Content-Type                                    | String | application/json                 |
| X-Shopper-Key<mark style="color:red;">\*</mark> | String | "Bearer" + shopper access token  |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": {
    "exchanges": [
      {
        "name": "coinbase",
        "value": "coinbase",
        "stockId": "",
        "limit": 0,
        "supportedCurrencies": [
          
        ],
        "default": false,
        "priority": 1,
        "connected": false
      },
      {
        "name": "okcoin",
        "value": "okcoin",
        "stockId": "58b989dd-f1a2-4227-90cc-44c9dafb92a7",
        "limit": "1000",
        "supportedCurrencies": [
          "BTC",
          "LTC",
          "ETH",
          "XRP",
          "BCH",
          "USDC"
        ],
        "default": false,
        "priority": 0,
        "connected": true
      },
      {
        "name": "kraken",
        "value": "kraken",
        "stockId": "46f34b67-cdaa-4a21-8d77-3096105c54c8",
        "limit": "1000",
        "supportedCurrencies": [
          "BTC",
          "LTC",
          "ETH",
          "XRP",
          "BCH",
          "USDC"
        ],
        "default": false,
        "priority": 0,
        "connected": true
      },
      {
        "name": "gemini",
        "value": "gemini",
        "stockId": "",
        "limit": 0,
        "supportedCurrencies": [
          
        ],
        "default": false,
        "priority": 0,
        "connected": false
      }
    ],
    "defaultCurrency": "BTC"
  }
}
```

{% endtab %}
{% endtabs %}


# Pre-payment validation check

In case of exchange payment, the merchant can check a few validations before initiating a payment ex:

1. Insufficient Balance
2. The deposit address is not whitelisted
3. Password is required
4. etc

This API is NOT a core element of the payment flow. However, this helps to make a user-friendly payment solution.

The validation messages vary from exchange to exchange, but the API returns the same object with a different code that needs to handle at the merchant website.

Example:

1. OKcoin needs the deposit address for the whitelist, so this API checks whether or not the user has already whitelisted this address. In the API response, if the key "showWhitelistElement: true" means the deposit address is not whitelisted and merchant website should display the customer error.
2. A shopper's password is needed to withdraw the fund. If API returns a key "password: true," the shopper didn't provide the password, and the merchant's website should display a message to enter the password.

This API accepts the request payload in an encrypted format. The encryption algo is <*algo\_name> and encryption key is \<client\_*&#x73;ecret>.

```
// The sample request payload that needs to encrypt
{
  "clientId": "merchantid",
  "assets": "Selected exchange currency",
  "cart": "cart array",
  "offerId": "Order_id",
  "confirmation": "true",
  "nativeAmount": "cart amount in usd"
}

// clientId: The RKFL merchant identifier
// assets: Selected exchange currency (BTC/ETH)
// cart: cart array [{},{}]
// offerId: merchant unique identifie
// confirmation: true/false, true if shopper accept term and condition
// nativeAmount: cart total amount in USD

// The key "data" should generate from the below way.
export const data = async (toEncrypt, publicKey) => {
  const buffer = Buffer.from(toEncrypt);
  const encrypted = crypto.publicEncrypt(publicKey, buffer);
  return encrypted.toString('base64');
};
```

<mark style="color:green;">`POST`</mark> `/exchanges/payment-validate/{exchange_name}`

The value of exchange\_name are "coinbase/okcoin/kraken/gemini/binanceus"

#### Headers

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + shopper access token |
| Content-Type                                    | String | application/json                |

#### Request Body

| Name                                   | Type   | Description      |
| -------------------------------------- | ------ | ---------------- |
| data<mark style="color:red;">\*</mark> | String | Encrypted string |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
    "ok": true,
    "result": {
        "receiverAddress": "3Jmmku8JTHP2YsqNZ3RuhZdburbdHMtSjT",
        "receiverMemo": null,
        "amount": 0,
        "currency": "BTC",
        "fee": 0.00000526,
        "password": false,
        "showWhitelistElement": false,
        "exchange": "coinbase",
        "nativeAmount": 5,
        "newRate": {
            "percentRate": 0,
            "newFiatRate": 0
        }
    }
}
```

{% endtab %}
{% endtabs %}


# Payable amount

The RKFL provides an API to return the payable amount for the selected cryptocurrency. The cryptocurrency market is volatile and changes frequently. The RKFL backend system calculates the payable amount based on the current cryptocurrency rate.

Merchant websites should call this API whenever a shopper switches between cryptocurrencies. This API also returns a unit rate of the cryptocurrency.

{% hint style="info" %}
The merchant website should never cache the rate of the cryptocurrencies to use in the future because it changes frequently.
{% endhint %}

The below screenshot shows the payable amount in the bold text of "You Pay" and the crypto conversion rate just below.

![](/files/vCRCl709VqHtvLkvTJ4D)

<mark style="color:blue;">`GET`</mark> `/users/payable-amounts?invoice={uuid}&cc={cryptocurrency}`

![](/files/LzLdq4kvD9pupzLBp9ED) The value of "invoice", returns as "uuid" in the "POST /invoices"

![](/files/LzLdq4kvD9pupzLBp9ED) The value of "cryptocurrency" could be "btc/eth/ltc/xrp/etc"

#### Headers

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + shopper access token |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
    "ok": true,
    "result": {
        "order_amount": 2,
        "order_currency": "2.00",
        "payable_amount": 31.47376371,
        "payable_currency": "DOGE",
        "conversion_rate_per_unit": "0.06507"
    }
}
```

{% endtab %}
{% endtabs %}


# Trigger Exchange payment

When the shopper makes the exchange payment, this API creates a transaction record in the RKFL system.&#x20;

A crypto transaction may take 2 min to 2 hours to complete the transaction. When a crypto transaction is initiated successfully, this API returns the immediate status of the transaction, which can be pending/processing/canceled/completed.&#x20;

The RKFL wallet receives all crypto transactions and settles with the merchant daily.&#x20;

The merchant can set up a webhook through the merchant portal to receive updates on every status change in the RKFL system. The merchant must set up only one webhook for crypto and bank transfer.&#x20;

This API receives the request payload in an encrypted format, where the encryption algorithm is RSA, and the encryption key is the merchant's public key.

```
// The sample request payload that needs to encrypt
{
  "clientId": "cc238708-02a0-48af-a70d-9d05cfe3a66d",
  "assets": "BTC",
  "cart": [
    {
      "id": "1",
      "name": "Starbucks Gift Card",
      "price": 2,
      "quantity": 1,
      "localAmount": 2,
      "localCurrency": "USD"
    },
    {
      "id": "3",
      "name": "Best Buy Gift Card",
      "price": 2,
      "quantity": 1,
      "localAmount": 2,
      "localCurrency": "USD"
    },
    {
      "id": "5",
      "name": "Amazon Gift Card",
      "price": 1,
      "quantity": 1,
      "localAmount": 1,
      "localCurrency": "USD"
    }
  ],
  "shippingAddress": {
    "city": "jam",
    "email": "john@exmaple.com",
    "state": "jh",
    "country": "india",
    "phoneNo": "+1 123456789",
    "zipcode": "831008",
    "address1": "some address",
    "address2": "",
    "landmark": "",
    "lastname": "Doe",
    "firstname": "John"
  },
  "offerId": "1656674750778",
  "nativeAmount": "5",
  "savepassword": false,
  "code2fa": "",
  "merchantStoreCurrency": "USD"
}

// clientId is the RKFL merchant id.

// The key "data" should generate from the below way.
export const data = async (toEncrypt, publicKey) => {
  const buffer = Buffer.from(toEncrypt);
  const encrypted = crypto.publicEncrypt(publicKey, buffer);
  return encrypted.toString('base64');
};
```

<mark style="color:green;">`POST`</mark> `/exchanges/payments/{exchange_name}`

The value of exchange\_name are "coinbase/okcoin/kraken/gemini/binanceus"

**Error codes to be handled over the front end in payment API**

code: 418,&#x20;

message: 'Authentication Failed! Please try again after some time.'&#x20;

&#x20;

code: 419,&#x20;

message: 'Insufficient Balance'&#x20;

&#x20;\
&#x20;code: 420,&#x20;

message: 'Address whitelist is pending!' \
&#x20;

&#x20;code: 421,&#x20;

&#x20;message: 'Coin Wallet is not supported at this moment! please try again after some time.' \
&#x20;

&#x20; code: 422,&#x20;

message: 'Amount is less than minimum transaction amount supported by'&#x20;

&#x20; &#x20;

#### Headers

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + shopper access token |
| Content-Type                                    | String | application/json                |

#### Request Body

| Name | Type   | Description       |
| ---- | ------ | ----------------- |
| data | String | Enctrypted string |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "id": "176c7937-b4c9-48ac-bda9-a9b1a9472de1",
  "status": 1,
  "nativeAmount": "5.00",
  "nativeCurrency": "USD",
  "amount": "0.00423297",
  "receivedAmount": "0.00423227",
  "currency": "ETH",
  "type": 0,
  "description": null,
  "check": [
    {
      "id": "1",
      "num": 0,
      "name": "In store",
      "price": 5,
      "quantity": 1,
      "localAmount": 5,
      "statusRefund": {
        "pending": 0,
        "success": 0,
        "rejected": 0
      },
      "amountFinal": 5
    }
  ],
  "subscriptionIds": [
    
  ],
  "subscriptionOrder": false,
  "meta": {
    "hash": {
      "value": [
        "794afe809c063d6655d638dd731f07212063ebc967a8fc963334ab65fa0dfc2b"
      ],
      "network": "ethereum"
    },
    "offerId": "8ac346d4-19c2-4f55-b1f0-c3588ca16140",
    "receiverAddress": "0x27544a72AcB6567Dc261cB38c651dA96DD4C9bf4"
  },
  "stockId": null,
  "userId": null,
  "merchantId": "14ec584d-53af-476d-aacd-2b7f025cf21b",
  "settlementId": "fcec8a08-dd19-485d-9657-dd64498b0f83",
  "statusRefund": 20,
  "localAmount": "5.00",
  "referenceDwolla": null,
  "localCurrency": "USD",
  "merchantPayableAmount": "5",
  "errorMessage": null,
  "settlementStatus": 1,
  "txMetaId": "9504cebd-841a-4eb2-aed4-660522fed92d",
  "partnerId": null,
  "createdBy": "14ec584d-53af-476d-aacd-2b7f025cf21b",
  "createdAt": "2022-06-21T14:32:34.529Z",
  "updatedAt": "2022-06-21T15:44:55.400Z",
  "merchant": {
    "shopData": {
      "url": "https://webhook.site",
      "logo": "https://dev-rocketfuel-videos.s3.us-east-1.amazonaws.com/shoplogo/MTRlYzU4NGQtNTNhZi00NzZkLWFhY2QtMmI3ZjAyNWNmMjFi_1651734165.png",
      "companyName": "Rocketfuel",
      "description": "buy rocket fuel at cheap price"
    }
  },
  "customer": {
    "email": "",
    "fullname": ""
  },
  "currencyInfo": {
    "isFiat": false
  },
  "stock": null,
  "partner": null,
  "txMetadata": {
    "id": "9504cebd-841a-4eb2-aed4-660522fed92d",
    "shippingAddress": null,
    "nativeConversionRate": "1"
  },
  "receivedAmountFinal": 5,
  "receivedAmountCal": 4.999178485307677
}
```

{% endtab %}
{% endtabs %}


# Bank Payment


# Bank listing

Currently, the ACH Bank transfer facility is available to US shoppers only. A US shopper interested in making a bank transfer will be required to link his bank account through Plaid. Rocketfuel uses Dwolla for all the bank transfers.

The process of linking a bank account is described here.

If a shopper has already linked a bank account(s), this API returns the list of the connected bank account.

The below screenshot displays a way of showing a list of connected bank account(s).&#x20;

![](/files/FXqMvI5cyFHbOqqYyYLF)

<mark style="color:blue;">`GET`</mark> `/banks/my`

#### Headers

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + Shopper access token |
| Content-Type                                    | String | application/jsom                |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": {
    "banks": [
      {
        "name": "dwolla",
        "value": "dwolla",
        "stockId": "4cb09b90-9765-47a2-8a28-f91c7c0694d8",
        "limit": "0",
        "accounts": [
          {
            "accountName": "Plaid Saving",
            "bankName": "Chase",
            "mask": "1111",
            "id": "BQzE1gXJvgSozwvyo3qnfDgZeGnnZMiwXwV9k",
            "customerUrl": "https://api-sandbox.dwolla.com/customers/0f7bef60-fc98-421b-85fd-6d340955bdf7",
            "customerId": "0f7bef60-fc98-421b-85fd-6d340955bdf7",
            "fundingSource": "https://api-sandbox.dwolla.com/funding-sources/be768c4c-7c41-4676-8499-6489088c3283",
            "isPrimary": null,
            "currency": "USD",
            "isBalanceInfo": false,
            "balanceInfo": null,
            "status": 2
          }
        ],
        "default": false,
        "priority": 1,
        "connected": true
      }
    ],
    "defaultCurrency": "USD"
  }
}
```

{% endtab %}
{% endtabs %}


# Bank payment

{% hint style="warning" %}
DEPRECATED
{% endhint %}

When the shopper makes the bank payment, this API creates a transaction record in the RKFL system.&#x20;

An ACH bank transaction may take 3 - 4 working days to complete the transaction. This API returns the pending status of a bank transaction once it has been successfully initiated.&#x20;

The bank transfer is P2P means from the shopper's bank account to the merchant's bank account. To enable the bank transfer, the merchant must complete the KYB process and link his bank account to the RKFL merchant portal to receive the payment.

The RKFL system deducts the configured merchant fee from the transaction and credits the remaining amount into the merchant's linked bank account.

The merchant can set up a webhook through the merchant portal to receive updates on every status change in the RKFL system. The merchant must set up only one webhook for crypto and bank transfer.&#x20;

This API receives the request payload in an encrypted format. The encryption algo is RSA, and the encryption key is the merchant's public key.

```
// The sample request payload that needs to encrypt
{
  clientId: '2335689b-7a4d-420a-9cc0-f5d765a96967',
  amount: 1,
  accountId: '8ebzpaLqdqtlgXB53LemsalJ88ZpWMiwrKnkZ',
  cart: [
    {
      id: '2763',
      name: 'Data cable',
      price: 1,
      quantity: 1,
      localAmount: 1,
      localCurrency: 'USD'
    }
  ],
  stockId: 'd56b7410-4d39-4b32-a055-0828e9ab1ce5',
  offerId: '4e3c59b0a14519ee6d620be63241bd71',
  merchantStoreCurrency: 'USD',
  hostedPageId: ''
  shippingAddress{
    "firstname": "",
    "lastname": "",
    "phoneNo": "",
    "address1": "",
    "address2": "",
    "state": "",
    "city": "",
    "zipcode": "",
    "country": "",
    "landmark": "",
    "email": ""
  }
}

// clientId: The RKFL merchant id
// amount: cart total
// account Id: the merchant bank account id where the fund is to be transferred
// stockId: shopper connected bank account identifier
// offerId: merchant's unique identifier

// The key "data" should generate from the below way.
export const data = async (toEncrypt, publicKey) => {
  const buffer = Buffer.from(toEncrypt);
  const encrypted = crypto.publicEncrypt(publicKey, buffer);
  return encrypted.toString('base64');
};
```

<mark style="color:green;">`POST`</mark> `/purchases`

#### Headers

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + shopper access token |
| Content-Type                                    | String | application/json                |

#### Request Body

| Name                                   | Type   | Description      |
| -------------------------------------- | ------ | ---------------- |
| data<mark style="color:red;">\*</mark> | String | Encrypted object |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "id": "176c7937-b4c9-48ac-bda9-a9b1a9472de1",
  "status": 1,
  "nativeAmount": "5.00",
  "nativeCurrency": "USD",
  "amount": "0.00423297",
  "receivedAmount": "0.00423227",
  "currency": "ETH",
  "type": 0,
  "description": null,
  "check": [
    {
      "id": "1",
      "num": 0,
      "name": "In store",
      "price": 5,
      "quantity": 1,
      "localAmount": 5,
      "statusRefund": {
        "pending": 0,
        "success": 0,
        "rejected": 0
      },
      "amountFinal": 5
    }
  ],
  "subscriptionIds": [
    
  ],
  "subscriptionOrder": false,
  "meta": {
    "hash": {
      "value": [
        "794afe809c063d6655d638dd731f07212063ebc967a8fc963334ab65fa0dfc2b"
      ],
      "network": "ethereum"
    },
    "offerId": "8ac346d4-19c2-4f55-b1f0-c3588ca16140",
    "receiverAddress": "0x27544a72AcB6567Dc261cB38c651dA96DD4C9bf4"
  },
  "stockId": null,
  "userId": null,
  "merchantId": "14ec584d-53af-476d-aacd-2b7f025cf21b",
  "settlementId": "fcec8a08-dd19-485d-9657-dd64498b0f83",
  "statusRefund": 20,
  "localAmount": "5.00",
  "referenceDwolla": null,
  "localCurrency": "USD",
  "merchantPayableAmount": "5",
  "errorMessage": null,
  "settlementStatus": 1,
  "txMetaId": "9504cebd-841a-4eb2-aed4-660522fed92d",
  "partnerId": null,
  "createdBy": "14ec584d-53af-476d-aacd-2b7f025cf21b",
  "createdAt": "2022-06-21T14:32:34.529Z",
  "updatedAt": "2022-06-21T15:44:55.400Z",
  "merchant": {
    "shopData": {
      "url": "https://webhook.site",
      "logo": "https://dev-rocketfuel-videos.s3.us-east-1.amazonaws.com/shoplogo/MTRlYzU4NGQtNTNhZi00NzZkLWFhY2QtMmI3ZjAyNWNmMjFi_1651734165.png",
      "companyName": "Rocketfuel",
      "description": "buy rocket fuel at cheap price"
    }
  },
  "customer": {
    "email": "",
    "fullname": ""
  },
  "currencyInfo": {
    "isFiat": false
  },
  "stock": null,
  "partner": null,
  "txMetadata": {
    "id": "9504cebd-841a-4eb2-aed4-660522fed92d",
    "shippingAddress": null,
    "nativeConversionRate": "1"
  },
  "receivedAmountFinal": 5,
  "receivedAmountCal": 4.999178485307677
}
```

{% endtab %}
{% endtabs %}


# Transaction listing

The RKFL merchant portal is a one-stop solution for all merchant needs. The RKFL merchant portal offers a wide range of features ex: Dashboard, Transaction listing, Shopper listing, Reports,  Invoice, Fund, Account, Subscription, etc. Please see the RKFL merchant portal reference [here](https://docs.rocketfuelblockchain.com/user-guide-and-help-videos/merchant-user-guide). &#x20;

The RKFL doesn't publish all the APIs of the merchant portals. However, a few APIs are available to simulate the features on the merchant website.

This API accepts the merchant access token and returns the transaction list in a pagination manner.

The below screenshot display a transaction listing payload from the RKFL merchant portal.

![](/files/H1On9PuKfb11f92zWNDO)

<mark style="color:blue;">`GET`</mark> `transactions?limit=5&offset=0&from=2022-01-01&to=2022-07-20&timezone=-330`

#### Query Parameters

| Name                                       | Type   | Description                                                                                                                                                        |
| ------------------------------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| limit                                      | Number | The number of records to return is helpful in pagination.                                                                                                          |
| offset                                     | Number | Record starting from, helpful in pagination.                                                                                                                       |
| from                                       | Date   | Start date format "yyyy-mm-dd"                                                                                                                                     |
| to                                         | Date   | End date format "yyyy-mm-dd"                                                                                                                                       |
| timezone<mark style="color:red;">\*</mark> | Number | -330                                                                                                                                                               |
| query                                      | String | To search the record. Works on "Oder Id", "userId", "Transaction Id", "nativeAmount", "currency", "merchantId", "stockId", "firstName", "email", and "companyName" |

#### Headers

| Name                                            | Type   | Description                      |
| ----------------------------------------------- | ------ | -------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "ok": true,
    "result": [
        {
            "offerId": "1657806690208",
            "name": "golu@yopmail.com",
            "email": "golu@yopmail.com",
            "orderDate": "Jul 14 2022",
            "orderTime": "07:22 PM",
            "displayStatus": "Pending",
            "paymentMethod": "Bank",
            "fiatAmount": "10.00",
            "fiatCurrency": "USD",
            "cryptoAmount": "10",
            "cryptoCurrency": "USD",
            "paymentMode": "dwolla",
            "txnHash": "NA",
            "partnerName": "partner",
            "paymentStatus": 0,
            "status": true,
            "receivedAmount": "0",
            "conversionRate": {
                "fiatCurrency": "USD",
                "rate": 1
            }
        },
        {
            "offerId": "8a0c7a4a18159f25501815bc0ecb44989",
            "name": "Test Tester",
            "email": "test@test.com",
            "orderDate": "Jul 14 2022",
            "orderTime": "06:52 PM",
            "displayStatus": "Success",
            "paymentMethod": "Bank",
            "fiatAmount": "159.01",
            "fiatCurrency": "EUR",
            "cryptoAmount": "160.66809427",
            "cryptoCurrency": "USD",
            "paymentMode": "highriskcc",
            "txnHash": "NA",
            "partnerName": "partner",
            "paymentStatus": 1,
            "status": true,
            "receivedAmount": "160.66809426609998",
            "conversionRate": {
                "fiatCurrency": "USD",
                "rate": 0.9896800029049088
            }
        }
    ]
}
```

{% endtab %}
{% endtabs %}


# Order info

The RKFL provides an API to return the cart information to display on the payment page. However, the merchant website already has the cart information to show on any page, and the RKFL API is optional.

The idea of the cart info on the payment page is similar to the below image. Please note that in the order details section, the shopper has two items including one subscription item. The RKFL supports only the exchange payment for subscription items, so the rest of the tabs are disabled.

![](/files/AsMwGPb4Qx6c3lRwlEVn)

<mark style="color:blue;">`GET`</mark> `/invoices?uuid={uuid}`

![](/files/LzLdq4kvD9pupzLBp9ED) The "uuid" returns in the response of "POST /invoices"&#x20;

#### Query Parameters

| Name                                   | Type   | Description     |
| -------------------------------------- | ------ | --------------- |
| uuid<mark style="color:red;">\*</mark> | String | UUID of invoice |

#### Headers

| Name                                            | Type   | Description                      |
| ----------------------------------------------- | ------ | -------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |

{% tabs %}
{% tab title="200: OK Success" %}

```javascript
{
  "ok": true,
  "result": {
    "returnval": {
      "cart": [
        {
          "id": "2779",
          "name": "Mouse",
          "price": 3,
          "quantity": 2
        },
        {
          "id": "2683",
          "name": "Each 3rd Month",
          "price": 28,
          "quantity": 1,
          "frequency": "quarterly",
          "isSubscription": true,
          "merchantSubscriptionId": "c7af15070d784b4fa11ac19ffa984059-2683"
        }
      ],
      "order": "c7af15070d784b4fa11ac19ffa984059",
      "amount": "34",
      "currency": "USD",
      "encrypted": "TiFeyfAMzrZfOhgP13oKVTV+r8lVS2EX7S+2DYBS3GfNboAw09rwTeUow370uKj35d3S1WKFFd1wH71+H/9DNGJUxkEoHLjYJhvtY7HzqzyhPti08Ms53tN9Y+i/RLpTSnO2nnsV868RNG+JurE3NwvBLCpWeEvE50fyrnJcYj9qdDKhUzFzVGhUYICL/z50tOmnBfc7Onxe/8COmW7bLZDcRGtlO1I69DujhpZP4xql98UNZNgD+7se2QIq3YQLLIpYHfRx91YgINI0sj1WT68/iznVYYg1zhYtogbBjtytr/8xhF9d/WxaDAgl3YQPRxOE6NYt9myUVYJcpRpQyQ==",
      "merchant_id": "2335689b-7a4d-420a-9cc0-f5d765a96967",
      "redirectUrl": "",
      "shippingAddress": null,
      "username": "mfvth",
      "companyName": "Hush Puppies "
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Wallet payment

In confirming of the wallet payment, the RKFL provides a socket connection. The merchant website can use that socket connection to get the payment confirmation.

This document will update soon on how to use the socket connection to get the transaction status.


# Payout

The Payout Solution is a robust and versatile system designed to facilitate seamless payment collection for payees from merchants. It offers a range of payout options, including cryptocurrencies and fiat currencies, ensuring flexibility and convenience for both merchants and payees.

The payout solution consists of the following sections:

[Authentication/Token Generation](https://docs.rocketfuelblockchain.com/developer-guides/api-reference/authentication):

* This section includes an API for authentication and token generation. It generates an authentication token required for subsequent API requests, ensuring secure and authorized access to the payout solution. [Click here](https://docs.rocketfuelblockchain.com/developer-guides/api-reference/authentication) for a detailed description.

Payout APIs:

{% hint style="info" %}
For Encrypting Payload Refer to [Encryption Documentation](/developer-guides/api-reference/payins/encryption-algorithm/secret-key-based) or [Click here](/developer-guides/api-reference/payins/encryption-algorithm/secret-key-based)<br>

1. Authentication API is based on clientId and clientSecret
2. Auth header acts as a protection for subsequent API calls
3. To ensure that Data passed along with Auth Header is not in plain format
   1. Data is encrypted using a secret key that needs to requested to Rocketfuel
   2. This ensures that data is safe in transport layer
4. This key is not documented on the docs and is shared on 1 to 1 basis.
   {% endhint %}

* Add Payee API: This API allows merchants to add payees to the system. Merchants can provide necessary information such as payee's name, email, account details, or any other relevant information required for payouts.
* Create Transfer API: The Create Transfer API enables merchants to initiate payout requests, allowing them to transfer funds to payees swiftly and efficiently. Merchants can specify the amount, currency, and desired payout method, such as cryptocurrencies (e.g., Bitcoin, Ethereum) or fiat currencies (e.g., USD, EUR).
* Wallet Address KYT (Know Your Transaction) API: The Wallet Address KYT API provides functionality to perform a Know Your Transaction check on the wallet address provided by the payee. This check ensures that the provided wallet address is valid, not associated with suspicious activities, and meets the required compliance standards.


# Overview

### Setting up Postman collection

1. Import the collection.
2. Create an environment called "Rocketfuel".
3. Create an environment variable “BASE\_URL” and set the default value to:\
   Production: “<https://app.rocketfuelblockchain.com>”\
   Sandbox: "<https://app-sandbox.rocketfuelblockchain.com>"
4. Select the Rocketfuel environment.
5. Run the authentication API to set the access token variable: <https://docs.rocketfuel.inc/developer-guides/api-reference/authentication/authentication-without-email-password>

### Flow for Fund Allocation to the payee and reclaim

<figure><img src="/files/5fwL7ZXIBCxRG2HZl1mi" alt=""><figcaption></figcaption></figure>

### Flow for Withdraw of funds from Payee

<figure><img src="/files/PMYgk77eWwDDqunAde4P" alt=""><figcaption></figcaption></figure>


# Implemention Guide

This page walks through the five usual ways to use Rocketfuel Payouts.

Full collection: [Rocketfuel Payouts (Postman)](https://payout-api.rocketfuel.inc/)

## Scenario 1 — Onboard a payee

Add the person you want to pay, verify their identity, then move money from your payout account onto their balance.

#### 1. Invite the payee

**Postman:** [Payee Invite](https://payout-api.rocketfuel.inc/#726eb772-637f-4b72-82f7-8d9e9bc293b1)

Send their name, country, email, and your own reference id (for example `VENDOR-1001`).

You get back a **payee id**. Save it.

If you see “Payee already registered”, look them up with [Payee List](https://payout-api.rocketfuel.inc/#a44319a4-03a5-439d-9509-c21f4659541b) instead of inviting again.

#### 2. Submit KYC

**Postman:** [Payee KYC](https://payout-api.rocketfuel.inc/#7f9cc61d-3f5f-4078-a318-26ff7f4beab1)

Use the payee id from step 1. For a person, send name, country, date of birth, and address. For a company, use the company option in the same Postman request.

KYC can take a little time. When it is **completed**, they can receive money. You can also check status with [Payee Detail](https://payout-api.rocketfuel.inc/#9b4dfe91-6cff-47ec-bb29-4013c15e57fe).

#### 3. Put money on their balance

This is two steps: start the allocation, then confirm it. Make sure your merchant account has enough funds first (see Scenario 4).

**Start** — [Initiate Allocation](https://payout-api.rocketfuel.inc/#bdf9fed7-d7b9-4a6a-a826-16aad4e7a41c)

Send the payee id, amount, currency (usually USD), and a short note such as “March payout”. Save the **allocation id**.

**Confirm** — [Confirm Allocation](https://payout-api.rocketfuel.inc/#96af3945-5066-495c-9eec-8cd61293b6ee)

Use the allocation id and payee id. After this, the money is on the payee’s balance.

Changed your mind before confirming? Cancel it in Scenario 5.

#### 4. Check their balance

**Postman:** [Payee Balance](https://payout-api.rocketfuel.inc/#44d4fc66-0f66-48d0-b8a2-e5921c6a6af8)

You should see the amount you just allocated. They are now ready for a bank or crypto payout.

**Also useful:** [Payee List](https://payout-api.rocketfuel.inc/#a44319a4-03a5-439d-9509-c21f4659541b) · [Payee Detail](https://payout-api.rocketfuel.inc/#9b4dfe91-6cff-47ec-bb29-4013c15e57fe) · [List Allocation](https://payout-api.rocketfuel.inc/#bbd0869d-8af4-49d5-b6c8-77db1e0fe356)

***

## Scenario 2 — Pay to a bank and check status

Send money from the payee’s balance to their bank account, then check whether it arrived.

Finish Scenario 1 first. In Postman, put the **payee id** on every request in this flow.

#### 1. Make sure bank payouts are available

**Postman:** [Fiat Transfer Availability Check](https://payout-api.rocketfuel.inc/#9815ebce-06c5-4cb8-98e8-e1abaaa69d6b)

If fiat is not enabled, email [**support@rocketfuel.inc**](mailto:support@rocketfuel.inc).

#### 2. Create their payout profile

**Postman:** [Create payout account](https://payout-api.rocketfuel.inc/#19c83dde-46af-4408-a5ee-769ddd885167)

Send first name, last name, email, and country (three-letter code such as `USA`).

#### 3. Pick country, currency, and method

Open these in order and keep what Postman returns:

* [Fiat Supported Countries](https://payout-api.rocketfuel.inc/#79422571-1850-4cdc-8be1-494694cefd25)
* [Fiat Supported Currencies](https://payout-api.rocketfuel.inc/#84aaae43-f64b-46b5-83c9-eb47e97901e2)
* [Payment Methods](https://payout-api.rocketfuel.inc/#6a9efde5-ffdd-49f2-a718-5296a66e30e3)
* [Payment options](https://payout-api.rocketfuel.inc/#b672f73a-5f4e-4477-b196-ee0e22ddf66d) (wire, instant, next day, and similar)

#### 4. Save their bank details

Load the form first — fields change by country.

* [Fiat Transfer Bank Form](https://payout-api.rocketfuel.inc/#acfd0232-2d2b-4833-b7de-b160ba128926)
* [Save Bank Details](https://payout-api.rocketfuel.inc/#c1c35791-569b-473a-9e72-15a25ae6d503)

You get back an **account token**. That is the bank account you will pay into.

Later: [List Bank Details](https://payout-api.rocketfuel.inc/#e0cee5fc-0c86-40f1-bb01-d0effdc6e6c0) · [Delete Bank Details](https://payout-api.rocketfuel.inc/#c90e0f7c-e724-4214-b015-3682b7f3d343)

#### 5. Check the fee, then send

**Fee** — [Pre-Validate Fiat Transfer](https://payout-api.rocketfuel.inc/#0f44197f-e799-46a4-a4a1-388652b83575)

This shows how much they will receive and gives you a **record id**. If you see an allocation error, they do not have money on their balance yet — go back to Scenario 1.

**Send** — [Fiat Transfer](https://payout-api.rocketfuel.inc/#c04ba1d9-7f51-4f8a-8e34-8c148e6d7712)

Use the account token, amount, currency, and record id. You get back an **order id**. Status starts as pending.

#### 6. Check if it went through

**Postman:** [Transfer Status](https://payout-api.rocketfuel.inc/#bcb1359c-b2e9-48d6-9a4d-9e43df9f7600)

Use the order id and payee id.

* **Pending (**`0`**)** — still processing; wait and check again
* **Success (**`1`**)** — money sent
* **Failed (**`-1`**)** — it did not go through; check the message or contact support

***

## Scenario 3 — Pay to crypto and check status

Send money from the payee’s balance to a crypto wallet, then check whether it arrived.

Finish Scenario 1 first. In Postman, put the **payee id** on the currency, fee, and transfer requests.

#### 1. See which coins you can pay in

**Postman:** [Payout Currencies](https://payout-api.rocketfuel.inc/#58f93f20-6016-4952-bfcd-25679c691d01)

Pick a currency and network (for example USDC on Ethereum). Use those same names in the next steps.

#### 2. Check the wallet address

**Postman:** [Know your address](https://payout-api.rocketfuel.inc/#b30b045d-c7ff-434c-9a1d-04f99cdc06fd)

You want **approved**. If it is not approved, do not send the payout.

#### 3. Check the fee, then double-check

* [Crypto Transfer Fee](https://payout-api.rocketfuel.inc/#619a1172-612c-414e-a7ec-c110f10441a0) — what the transfer will cost
* [Pre-Validate Crypto Transfer](https://payout-api.rocketfuel.inc/#a70d5c01-9914-4289-8c12-b15520cdf303) — confirms amount, wallet, and network

If you see “Payee is not eligible”, KYC is not finished or the payee is blocked.

#### 4. Send the transfer

**Postman:** [Crypto Transfer](https://payout-api.rocketfuel.inc/#f9bf6a92-2387-4595-b558-cff3d7422a89)

Send the amount, coin, network, and wallet address. If the wallet is not the payee’s own, fill in the owner’s name in the Postman request.

You get back an **order id**. Status starts as pending.

#### 5. Check if it went through

**Postman:** [Transfer Status](https://payout-api.rocketfuel.inc/#bcb1359c-b2e9-48d6-9a4d-9e43df9f7600)

Same as bank payouts: pending `0`, success `1`, failed `-1`. When it succeeds, you may also get a blockchain transaction hash.

***

## Scenario 4 — Check your balance

See how much you can pay out, and add more money if needed.

Do this before you allocate if you are not sure there is enough in the account.

#### 1. Check how much you can allocate

**Postman:** [Check Balance](https://payout-api.rocketfuel.inc/#990ea9d2-3ee7-4d82-8a10-0a67a0ff594d)

* **Available balance** — money you can still put on payees
* **Current balance** — money sitting in your payout account
* **Allocated funds** — money already given to payees

#### 2. Check the live balance

**Postman:** [Check Running Balance](https://payout-api.rocketfuel.inc/#fe7433b4-0db4-470b-a9f4-aade6c0711a1)

This includes allocations still in progress, so it can differ from available balance for a short time.

#### 3. Add funds

Ask Rocketfuel for your **wiring instructions** (the bank account you send money to). After the wire arrives, Check Balance should show a higher available amount. Then go back to Scenario 1 and allocate.

**Note:** You fund your merchant payout account once, then split that money across payees. You do not wire money to each payee directly.

#### 4. Check one payee’s balance

**Postman:** [Payee Balance](https://payout-api.rocketfuel.inc/#44d4fc66-0f66-48d0-b8a2-e5921c6a6af8)

Use this after an allocation to confirm they received the funds.

***

## Scenario 5 — Take money back or pause a payee

Use this if you allocated too much, a job was cancelled, or you need to stop paying someone.

**Note:** You can only take back money that is still on the payee’s Rocketfuel balance. Once it has been sent to a bank or a crypto wallet, these steps will not reverse it. Blocking does **not** take their money back. Reclaim first if you also need the unused balance.

#### Cancel a pending allocation

If you have not confirmed the allocation yet:

**Postman:** [Cancel Allocation](https://payout-api.rocketfuel.inc/#4f3096bc-5e29-4c98-b2b7-10f51787d667)

Use the allocation id and payee id. To find pending ones: [List Allocation](https://payout-api.rocketfuel.inc/#bbd0869d-8af4-49d5-b6c8-77db1e0fe356)

#### Take unused money back

1. See how much you can take — [Reclaim balance](https://payout-api.rocketfuel.inc/#55500a1d-b040-4ce9-ad3a-f4e2cd52aef3)
2. Take it back — [Reclaim Funds](https://payout-api.rocketfuel.inc/#2876fead-6ce2-447e-a11e-13d521139747)

Send the payee id, the amount (not more than the reclaimable balance), and a short reason.

Then check [Payee Balance](https://payout-api.rocketfuel.inc/#44d4fc66-0f66-48d0-b8a2-e5921c6a6af8) (should be lower) and [Check Balance](https://payout-api.rocketfuel.inc/#990ea9d2-3ee7-4d82-8a10-0a67a0ff594d) (your account should be higher).

#### Pause or restore a payee

* **Block** — [Payee Block](https://payout-api.rocketfuel.inc/#d2200702-7fe6-46b9-99a4-c1a46a82c41b) — they cannot receive more payouts
* **See who is blocked** — [List Blocked Payee](https://payout-api.rocketfuel.inc/#9ef1353f-81de-48ae-9b15-0c4c20d66951)
* **Unblock** — [Payee Unblock](https://payout-api.rocketfuel.inc/#39c9c79a-06ff-470d-b788-df8377dd53cc) — they can be paid again


# API Guide

Please refer to this API documentation for using our payout solution: <https://payout-api.rocketfuel.inc/>

The API documentation will help you with the following:

1. Payee level actions
   1. Payee Invite
   2. KYC&#x20;
   3. Payee Balance
   4. Payout Currencies&#x20;
   5. Crypto Payouts
   6. Fiat Payouts
2. Payout Admin Actions
   1. Wiring Instructions
   2. Check Balance
   3. Check Running Balance
   4. Payee List
   5. Payee Detail
   6. Initiate Allocation
   7. Confirm Allocation
   8. Cancel Allocation
   9. List Allocation
   10. Reclaim balance
   11. Reclaim Funds
   12. Payee Block
   13. Payee Unblock
   14. List Blocked Payee


# Payout Transaction Statuses

When a payout is initiated, it moves through a defined set of statuses that reflect the current state of the transaction. Use the status code returned in the payout response to determine the outcome and take appropriate action in your integration.

### Status Reference

| Code | Label   | Description                              |
| ---- | ------- | ---------------------------------------- |
| `0`  | Pending | The payout is currently being processed. |
| `1`  | Success | The payout was completed successfully.   |
| `-1` | Failed  | The payout failed.                       |

### Polling for Status Updates

If a payout is returned with a `Pending (0)` status, you can:

* Poll the payout status API at regular intervals (recommended: every 5–10 seconds), or
* Use **webhooks** to receive real-time payout status updates without repeatedly calling the API.

{% hint style="info" %}
Webhooks are the recommended approach for production integrations to avoid excessive API polling.\
Refer to the [**Webhook**](/developer-guides/api-reference/payout/webhooks) section for more details on configuring and handling webhook events
{% endhint %}


# Webhooks

To register the Webhook URL, you will need to contact RocketFuel sales team.

{% hint style="info" %}
The callback URL should respond with status 200 for GET request.
{% endhint %}

## Rocketfuel Webhook and Events <a href="#markdown-header-rocketfuel-webhook-and-events" id="markdown-header-rocketfuel-webhook-and-events"></a>

RocketFuel webhook calls are triggered to update the merchant on the status of the payouts and the payees.

Rocketfuel webhooks support the following events:-

* **PayeeAdded**: This event is triggered when a new payee is successfully added to the system. It confirms that the payee's information has been registered and is ready for further action.
* **PayeeKycStarted**: This webhook is triggered when the Know Your Customer (KYC) process for a payee begins. It signifies that the verification process for the payee's identity has been initiated.
* **PayeeKycStatusChange**: This event is sent whenever there is a change in the payee’s KYC status. It updates the current status of the verification process, such as whether it has been approved, rejected, or is pending further action.
* **PayeeFundAllocated**: This webhook is triggered when funds are successfully allocated to the payee. It signifies that the funds intended for the payout have been reserved.
* **PayoutStarted**: This event is triggered when the payout process begins. It confirms that the payout has been initiated for the payee and the payment is in progress.
* **PayoutStatusChange**: This webhook is sent when there is a change in the status of a payout. It provides updates on the current state of the payout, such as successful completion, failure, or being in progress.

## Securing Callbacks <a href="#markdown-header-securing-callbacks" id="markdown-header-securing-callbacks"></a>

Order callbacks originating from RocketFuel will be signed using our callback signing RSA private key.

If you would like to verify callbacks manually in the language of your choice, the message digest used is SHA256, the message that is signed is the POST body, the padding scheme is PKCS1\_v1\_5, and the signature to be verified is present in the ‘signature’ HTTP data encoded as base64.

**Examples**

{% tabs %}
{% tab title="PHP" %}

```php
public function verifyCallback($body, $signature)
{
    $signature_buffer = base64_decode( $signature );
    return (1 == openssl_verify($body, $signature_buffer, self::getCallbackPublicKey(), OPENSSL_ALGO_SHA256));
}
```

{% endtab %}

{% tab title="Node.js" %}

```
function verifySignature(body, public_key_rsa, signature) {
  const verifier = crypto.createVerify('RSA-SHA256');
  verifier.update(body);
  return verifier.verify(public_key_rsa, signature, 'base64');
}
```

{% endtab %}

{% tab title="Java" %}

```java
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class WebhookVerifier {

    // The public key string (including header/footer)
    private static final String PUBLIC_KEY_STRING =
            "-----BEGIN PUBLIC KEY-----\n" +
            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2e4stIYooUrKHVQmwztC\n" +
            "/l0YktX6uz4bE1iDtA2qu4OaXx+IKkwBWa0hO2mzv6dAoawyzxa2jmN01vrpMkMj\n" +
            "rB+Dxmoq7tRvRTx1hXzZWaKuv37BAYosOIKjom8S8axM1j6zPkX1zpMLE8ys3dUX\n" +
            "FN5Dl/kBfeCTwGRV4PZjP4a+QwgFRzZVVfnpcRI/O6zhfkdlRah8MrAPWYSoGBpG\n" +
            "CPiAjUeHO/4JA5zZ6IdfZuy/DKxbcOlt9H+z14iJwB7eVUByoeCE+Bkw+QE4msKs\n" +
            "aIn4xl9GBoyfDZKajTzL50W/oeoE1UcuvVfaULZ9DWnHOy6idCFH1WbYDxYYIWLi\n" +
            "AQIDAQAB\n" +
            "-----END PUBLIC KEY-----";

    /**
     * Loads a PublicKey from a PEM-formatted string.
     *
     * @param keyStr the PEM public key string
     * @return the PublicKey instance
     * @throws Exception if any error occurs during parsing
     */
    public static PublicKey loadPublicKey(String keyStr) throws Exception {
        // Remove the PEM header and footer, and any whitespace/newlines.
        String publicKeyPEM = keyStr
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s", "");
        // Base64-decode the result
        byte[] decoded = Base64.getDecoder().decode(publicKeyPEM);
        // Generate the public key
        X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

    /**
     * Verifies the RSA-SHA256 signature for the given payload.
     *
     * @param body      the message to verify (payload)
     * @param signature the Base64-encoded signature string
     * @param publicKey the public key used for verification
     * @return true if the signature is valid; false otherwise
     * @throws Exception if any error occurs during verification
     */
    public static boolean verifySignature(String body, String signature, PublicKey publicKey) throws Exception {
        Signature sig = Signature.getInstance("SHA256withRSA");
        sig.initVerify(publicKey);
        // Update the signature object with the bytes of the body
        sig.update(body.getBytes(StandardCharsets.UTF_8));
        // Decode the signature from Base64
        byte[] sigBytes = Base64.getDecoder().decode(signature);
        // Verify the signature and return the result
        return sig.verify(sigBytes);
    }

    public static void main(String[] args) {
        // Sample payload: the 'data' field from your JSON webhook
        String payloadData = "{\"data\":{\"payeeId\":\"ba2fb7c7-a94f-491a-9538-83a170557748\"," +
                "\"payeeInternalId\":\"\",\"payoutAmount\":0.00008697," +
                "\"payoutCurrency\":\"BTC\",\"payoutId\":\"e4c356dc-8fba-4713-9a00-7845d2c48c35\"," +
                "\"type\":\"crypto\"},\"event\":\"PayoutStarted\"," +
                "\"timestamp\":\"2024-07-16T12:46:30.061Z\"}";
        // The Base64-encoded signature from your webhook
        String signature = "h5EZnyA8v/24knUfnEka4QwgXeUQOb7XE21Duy5W8uV6o1g/7J2sB4gK31NAaXt3cz4TBgW0dA59LNvRogO+VUb6gzj/8jvlDXFtUj5214/cPEBPnuSddW8dy66zuBL3vYviT1qc1it0uNVmXzh2GCjfhfJ2ti3CHDornmiu3AfSROiPf40oAknt1nOpBGqvLafLzLRAcfIHa/6SxsApgdGCP9QW0A9O3WH4+uUNvehdKdGZ2t0Cv9LJGLTekc7Be4k85Tu/SsBbr9l6/laZMeZ/vsQFCzWdvbirHg/O78OjzHeLiHCdeqMrhkwVQKPE2xm1HwDqp8TSPDaX6CiNng==";

        try {
            PublicKey publicKey = loadPublicKey(PUBLIC_KEY_STRING);
            boolean isValid = verifySignature(payloadData, signature, publicKey);
            System.out.println("Signature valid: " + isValid);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```

{% endtab %}
{% endtabs %}

### Sample Webhook Payloads <a href="#markdown-header-test-data" id="markdown-header-test-data"></a>

Following is an example for GET & POST payload for the events:

1. **Payee Added**\
   Method: Post

**Body Payload**

```
{
    "type":"rf:webhook",
    "data":"{\"data\":{\"createdAt\":\"2024-07-15T09:38:30.711Z\",\"payeeId\":\"6bcb76d1-4aa9-4a81-9285-728ba42d1813\",\"payeeInternalId\":\"PAYEE101\"},\"event\":\"PayeeAdded\",\"timestamp\":\"2024-07-15T09:38:30.717Z\"}",
    "signature":"UQYgICyhmxxCd5qmKSsJKXrMsmcu66EYobvZISh72xLYeAvBClptlybO5cso+YolnB0oLovT9jA80ZgQ0082yfqVFROmeE2jNsJ3oC9M4XdzBqYrEb8gGGKXBXU2hxEblgjrgVrKqhDKFFDwt6GWMBVss4AWy0Ddb9GA/btu1tw1kYuwyWEk9Ycn2W4NTb+1EyYo+3Z8fCLIrEA9yHsLK91WF87fLUFzdmWw7/kMEfmYykF2ykTNSVNAp2bDsSr73Qu10TTfyifSu3lewLkfQTAUjlereHISMDE9/ZWF/krj0XreQ3y8kof4MnVbtz9myhSSIIxqp5yDBFPp61zBqw=="
}
```

2. **Payee KYC Started**\
   Method: POST

\
**Body Payload**

```
{
  "type": "rf:webhook",
  "data": "{\"data\":{\"payeeId\":\"6bcb76d1-4aa9-4a81-9285-728ba42d1813\",\"payeeInternalId\":\"PAYEE101\"},\"event\":\"PayeeKycStarted\",\"timestamp\":\"2024-07-15T09:40:09.970Z\"}",
  "signature": "0k+4kSI7KWMoE45dqPfUqJmhzUJaKM2SvdoSlDWvF077yC27LDCjpfEcItylWb34o7AyfNJ0cUgXNu/W7ydv5a5PNEf4jW1Ll2hjjhPN/qwYQh6J5r4Mr1CsHjRsFyA7VIRw7y6GfxS6a88Pi4N3D9E+YPz31xcdQ2X5OfzKPuEBFyEO9riWsnPzYIfynbufYSdZDFNPMzjgmrd57XqxHNxKEnW7AQ1Uo1fauCqTgW290DNovunbQlyF29s92Sf7ogHUmM6fvb5nZIY9oGVJ9Kp2JBxVaQ2FNW2WtCVWLYZa37+OqxgmWA3ORmFL1ORQvv75w/1wz4cL6qapPG38Sg=="
}
```

3. **Payee KYC Status Change**\
   Method: POST<br>

   Here’s a description for the two statuses related to KYC:

   1. **manual\_review - Pending Status**:\
      This status indicates that the payee’s KYC process is currently under manual review and pending approval. The verification is yet to be completed, and further checks or actions may be required before the KYC can be finalized.
   2. **completed - KYC is Done**:\
      This status signifies that the KYC process has been completed. The payee has passed all necessary verification checks, and their identity has been confirmed as part of the KYC process.

**Body Payload**

```
{
    "type":"rf:webhook",
    "data":"{\"data\":{\"payeeId\":\"77df710d-26b2-4583-9c56-b0e0d88d2497\",\"payeeInternalId\":\"PAYEE101\",\"status\":\"manual_review\"},\"event\":\"PayeeKycStatusChange\",\"timestamp\":\"2024-07-15T10:24:32.456Z\"}",
    "signature":"s1r80cyhzXva4xr7alLF9G6HBXW9+ZfVsX5QGFZ7xFHF+WBShZ8Gbejl4lNW2BUpDdFnMJdChLsBUud9imUmc1+Ttpz1JVWyHjFTu1zUEgl6Hy1/fkQFNbDaqTKnCKOCUZ8L6YjxSGka/l9zQBI5S6ZXQgshzkDoQQY/aPGfL1ZNSNrJInlFlPILSTJlftC4uTlNNsqryf7wMnCq2XsihaKwnoXeHjLeeIsnqQjvyN5noEQTluP/v/TPfSqIxk2pZmvaoX5Z+gIrOT6Y39SP7Q4FfAHO/oOxlFNR1tDH8wPQdrhVQ1pZ/USqHxILqGSIxyiAKsFLUgIMv2php36pOg=="
}
```

4. **Payee Fund Allocated**\
   Method: POST

**Body Payload**

```
{
  "type": "rf:webhook",
  "data": "{\"data\":{\"amount\":\"10\",\"currency\":\"USD\",\"payeeId\":\"ba2fb7c7-a94f-491a-9538-83a170557748\",\"payeeInternalId\":\"\"},\"event\":\"PayeeFundAllocated\",\"timestamp\":\"2024-07-16T12:44:59.063Z\"}",
  "signature": "PfcMW6BuaZtI1ZO4SgOE1IbL8GePr8RiFZV7HyC9z3hUtqp8JTzAsHX437b6PIkr66SIHAPRZXNCHrxipUrIX1ReN/sOQglueZeJiyanGEnKLXPAm8ozJfHb47DW5A2GwqN/dYpr61JCRlQ2zHLxlirAwZXLgJD6lI7feUPdwJL3xWpwwUai3/ym8RjpMX5RKINLcntrI+WB/gOzG72o9WiOIjX3XgqnhFlU0cgu+AJlepCxstPMYE3iyM3e87WRFW4mVzJdwSAulftR0gzuyzXvhwyQJt69kS6W9FO89VyDx6Weg3j4RYsbeoOagl8IcQeOS095LZ3Xixo+5i4U+g=="
}
```

5. **Payout Started**\
   Method: POST

**Body Payload**

```
{
  "type": "rf:webhook",
  "data": "{\"data\":{\"payeeId\":\"ba2fb7c7-a94f-491a-9538-83a170557748\",\"payeeInternalId\":\"\",\"payoutAmount\":0.00008697,\"payoutCurrency\":\"BTC\",\"payoutId\":\"e4c356dc-8fba-4713-9a00-7845d2c48c35\",\"type\":\"crypto\"},\"event\":\"PayoutStarted\",\"timestamp\":\"2024-07-16T12:46:30.061Z\"}",
  "signature": "h5EZnyA8v/24knUfnEka4QwgXeUQOb7XE21Duy5W8uV6o1g/7J2sB4gK31NAaXt3cz4TBgW0dA59LNvRogO+VUb6gzj/8jvlDXFtUj5214/cPEBPnuSddW8dy66zuBL3vYviT1qc1it0uNVmXzh2GCjfhfJ2ti3CHDornmiu3AfSROiPf40oAknt1nOpBGqvLafLzLRAcfIHa/6SxsApgdGCP9QW0A9O3WH4+uUNvehdKdGZ2t0Cv9LJGLTekc7Be4k85Tu/SsBbr9l6/laZMeZ/vsQFCzWdvbirHg/O78OjzHeLiHCdeqMrhkwVQKPE2xm1HwDqp8TSPDaX6CiNng=="
}
```

6. **Payout Status Change**\
   Method: POST

Here’s the description for the payout statuses:

1. **completed**:\
   The payout has been successfully processed, and the funds have been transferred to the payee’s account.
2. **failed**:\
   The payout process has encountered an issue, and the funds could not be transferred. Further action may be required to resolve the failure.

**Body Payload**

```
{
    "type":"rf:webhook",
    "data":"{\"data\":{\"payeeId\":\"6825a42b-d5e6-4a90-9d50-6c9edbab7b73\",\"payeeInternalId\":\"PAYEE102\",\"payoutId\":\"fb83ba30-ef92-4a5f-9bd9-4a061f5c5fb7\",\"payoutAmount\":0.01105763,\"payoutCurrency\":\"ETH\",\"type\":\"crypto\",\"additionalDetails\":{\"hash\":\"hash_string\"},\"status\":\"completed\"},\"event\":\"PayoutStatusChange\",\"timestamp\":\"2024-07-15T10:34:24.979Z\"}",
    "signature":"LnJDPysCt/eautLgth1OWJn/YDx00ZpiLDZjCn/PNlOP+gcA9XSL95o2ucKsCEvL3ozg04IUKQhjBivrwzY/2wUdj6NgoJRNn+bjSjteuJKwudTRa4tzhYRbo0wcRFTUqDi9ZeWxC+Hh+l75U5JWx/qHD++mwkC3WsMIYnJkQ2xn6sTas7CG33VfoZM6NfVpQwxQxyPEfuOD5Nd7XGfeImqSxD0BIp7lTQQyZTYcRt3bRFdin7NgkADg4llcCFCwksrEdVoeKMS2fb1q2v1d3op2ORXSvkgfMHe7hNhc0w8khbaqXHderSDb+vhMR9FyDJ+NfbvAMa6rSlLETFF/zA=="
}
```

**Authenticity/Verification of request from RKFL**

You can test the authenticity of the request emerging from Rocketfuel by using the following public key to generate the signature. Once the signature is generated, you can tally the signature sent by Rocketfuel.

#### Signature: <a href="#markdown-header-signature" id="markdown-header-signature"></a>

```json
f09HYBeZFqMkeo/ri5kZI0DGnCiSnYSl2KSZLaB3tIL722a1IsnCSsWsfdZRAiv/7e/MdqguXTBmEUdBzKnzR2ATBJF5VRtLeD7LhnNxpSs1+sAAgIwI2JS6nkRj8DTKZbZUzweGSdgARZfxxoVqQaaW4DPb8kXhGPVo/tOG8Rw62Vbyg279ysgWCtNuYltKg05DFxfWy287LtBnvs3kaw0xoTuR5rCnEncFFLRozSCPRSRU0Ebb3kfWNK6surso9OrqVkdbzXLCpLuLkkakxNvNpahzvB3DuT2zZn0NFxP8YGJquAVcWLh2aj0syRPDArHY5An5CtQ6nuiiJB6jTw==
```

#### Public RSA key <a href="#markdown-header-public-rsa-key" id="markdown-header-public-rsa-key"></a>

```
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2e4stIYooUrKHVQmwztC
/l0YktX6uz4bE1iDtA2qu4OaXx+IKkwBWa0hO2mzv6dAoawyzxa2jmN01vrpMkMj
rB+Dxmoq7tRvRTx1hXzZWaKuv37BAYosOIKjom8S8axM1j6zPkX1zpMLE8ys3dUX
FN5Dl/kBfeCTwGRV4PZjP4a+QwgFRzZVVfnpcRI/O6zhfkdlRah8MrAPWYSoGBpG
CPiAjUeHO/4JA5zZ6IdfZuy/DKxbcOlt9H+z14iJwB7eVUByoeCE+Bkw+QE4msKs
aIn4xl9GBoyfDZKajTzL50W/oeoE1UcuvVfaULZ9DWnHOy6idCFH1WbYDxYYIWLi
AQIDAQAB
-----END PUBLIC KEY-----
```


# Swagger API

Refer to this link for our Swagger API - <http://docs-api.rocketfuel.inc/>


# RocketFuel Integration


# Objective

This document aims to make the process to integrate with RocketFuel payment solutions as low friction as possible. RocketFuel is committed to working and iterating in the process and greatly values any feedback you may have. This document aims to guide vendors who wish to integrate with us to receive crypto payments from their customers.


# Target Audience

The target audience of this document is merchants who wish to expand their business by allowing their customers to pay using crypto by integrating our solution. The merchants get their own portal to check on their revenues and refunds.


# Product Feature overview


# "How To" Guide


# Sign up as a Merchant

Following link explains the process to sign up as a merchant on RocketFuel

{% embed url="<https://docs.rocketfuelblockchain.com/user-guide-and-help-videos/merchant-user-guide/sign-up-process>" %}


# KYC Verification

Following link explains the process of  KYC verification

{% embed url="<https://docs.rocketfuelblockchain.com/user-guide-and-help-videos/merchant-user-guide/verification>" %}


# Using the RocketFuel API for Custom Integration

RocketFuel has three phases of API integration:

1. Pre-Payment Activity
2. Payment Activity (Shopper ↔︎ RKFL)
3. Post-Payment Activity

Before the start of the three phases, some prerequisites are required to be completed. The below Quick Start page describes on the same.

{% embed url="<https://docs.rocketfuelblockchain.com/developer-guides/quick-start>" %}

Once the `public key` and `integration keys` have been set up, the first phase can be started.

1. **Pre-payment Activity**
   1. To start with the prepayment activity, there is one more prerequisite that needs to be understood - [Encryption Algorithm](https://docs.rocketfuelblockchain.com/developer-guides/api-reference/encryption-algorithm)
   2. After the above things are completed and understood, the first phase starts with [generating the invoice](https://docs.rocketfuel.inc/developer-guides/api-reference/generate-invoice-link).&#x20;

      i. The [inline method](https://bitbucket.org/rocketfuelblockchain/rocketfuel-readme/src/master/javascript-sdk.md) can be used as well for generating invoice
2. **Payment Activity (Shopper ↔︎ RKFL)**

   The second phase, payment activity involves the exchange of data between shoppers and RocketFuel, nothing is expected from the merchants.
3. &#x20;**Post Payment Activity**\
   The post payment activity involves knowing the transaction status which can be done with the help of webhooks and Lookup API.
   1. [Webhook](https://docs.rocketfuel.inc/webhooks)
   2. [Lookup API](https://docs.rocketfuel.inc/developer-guides/api-reference/transaction-lookup)

**Languages Supported**

1. Any coding language to call APIs (server ↔︎ server)
2. Little knowledge of JS in case of Inline /popup Integration


# Using the RocketFuel Pre-built Solutions for Custom Integration

Pre-built solutions include Plugins and Language SDKs.

1. **Plugins**
   1. WordPress

      a. [Woo-commerce](https://docs.rocketfuel.inc/plug-ins-and-sdks/woocommerce)
   2. [Bigcommerce](/plug-ins-and-sdks/bigcommerce)
   3. [Prestashop](https://docs.rocketfuel.inc/plug-ins-and-sdks/prestashop)
   4. [Magento](https://docs.rocketfuel.inc/plug-ins-and-sdks/magento)
   5. [Drupal](https://bitbucket.org/rocketfuelblockchain/rocketfuel-plugin-drupal/src/master)
2. **Language SDKs**
   1. [PHP - SDK](https://docs.rocketfuel.inc/plug-ins-and-sdks/web-sdk)
   2. [Node Js SDK](https://www.npmjs.com/package/rocketfuel-node-sdk)
   3. [Go Lang SDK](https://bitbucket.org/rocketfuelblockchain/rocketfuel-sdk-go/src/master/)


# How to Use Testnet for Transactions

In cryptocurrency payments, a "testnet" is a parallel blockchain network used primarily for testing and development purposes. It's a sandbox environment that allows developers and users to experiment with cryptocurrencies without using real assets. Testnets mimic the functionality of the main blockchain but use test tokens, which have no real-world value.

Please follow the steps below to create a testnet wallet and add balance in it.

1. Download the "Bitcoin Testnet Wallet for COI" wallet from App Store or Play Store.\
   \ <img src="/files/YxaNOL6DutR3dAsexU1g" alt="" data-size="original"><br>
2. After downloading the app, click on "Start setup of hot wallet."\
   \
   ![](/files/SPcOuwQC6nRlAhdo0Pqt)<br>
3. It will then prompt you to download COINiD Vault, proceed to download the app.\
   \
   ![](/files/fRy9OFKxTVvPsKUIzOTw)   ![](/files/ZjDCPuHDgfoxW0VA4tje)<br>
4. After Downloading, click on "Create new COINiD Vault" and proceed with saving the recovery phrase and setting up the PIN at the end. Once done, you will see the message 'COINiD Vault is all set'.\
   \
   ![](/files/fbwdmt6oYqNEFpZqUjE4)  ![](/files/9iJhHAW2zSt1VtLPWJig)  \
   \
   \
   ![](/files/Nb8E4o3wlweIOtWaB4fb)   ![](/files/c6fRnO6hSuZUa2D2x9jM)<br>
5. &#x20;After the COINiD Valut has been set, return to the "Bitcoin Testnet Wallet for COI" app and sign in using the same PIN set by you. After signing in, you will see your tBTC balance (It will be zero since it is a new wallet)\
   \
   ![](/files/hNSZ2r65sPxm9CVj4ZqQ) &#x20;
6. Click on the QR code icon as show and below and create your receiving wallet address.\
   \
   &#x20;![](/files/bZTh5E4GZYjkMZChEXpe)<br>
7. Once your wallet address is created, copy it and paste it on <https://coinfaucet.eu/en/btc-testnet/> to get tBTC in your wallet. You will see how much tBTC has been transferred to your wallet once you hit the 'Get bitcoins!' button.<br>

   <figure><img src="/files/opnKyAWXXKDLV8RgzHPB" alt=""><figcaption></figcaption></figure>

   <br>

   <figure><img src="/files/DWDFUpKo6u8uWeAxIrnU" alt=""><figcaption></figcaption></figure>
8. After some time you will see the updated balance in your testnet wallet app. You can use the balance to test crypto payments.\
   \
   ![](/files/cMSQuM9dz28jF0jVo0O2)


# FAQ and Tips


# Redirect Integration

Rocketfuel-hosted checkout web UI is the simplest and quickest way of using the Rocketfuel services. The merchant interested in obtaining this solution must submit their cart data to generate an invoice.&#x20;

The API response returns a URL where the shopper will redirect to the payment options. After the successful payment, the shopper will return to the merchant's website.

<mark style="color:green;">`POST`</mark>` ``/hosted-page`

Here is the sample of request payload.&#x20;

{ amount, cart{ id, price, name, quantity, key, totalPrice, isSubscription, frequency, merchantSubscriptionId }, currency, order, redirectUrl, customerInfo{ name, email, phone, address }, shippingAddress{ firstname, lastname, phoneNo, address1, address2, state, city, zipcode, country, landmark, email } }

isSubscription: true/false&#x20;

frequency: weekly/monthly/quarterly/half-yearly/yearly&#x20;

merchantSubscriptionId: Subscription id for merchant system. This key will use to communicate the recurring payment status.

#### Headers

| Name                                            | Type   | Description                      |
| ----------------------------------------------- | ------ | -------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | "Bearer" + merchant access token |
| Content-Type                                    | String | application/json                 |

#### Request Body

| Name            | Type   | Description                                                                                      |
| --------------- | ------ | ------------------------------------------------------------------------------------------------ |
| amount          | String |                                                                                                  |
| cart            | Array  | id, price, name, quantity, key, totalPrice, isSubscription, frequency, merchantSubscriptionId    |
| currency        | String | USD/EUR                                                                                          |
| order           | String | Order id from the merchant's system                                                              |
| redirectUrl     | String | Return URL of merchant's website, in case of RKFL-hosted checkout integrated                     |
| customerInfo    | Array  | name, email, phone, address                                                                      |
| shippingAddress | Array  | firstname, lastname, phoneNo, address1, address2, state, city, zipcode, country, landmark, email |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "ok":true,
    "result":{
        "url":"https://payments-sandbox.rocketfuelblockchain.com/hostedPage/f7cb4141-3030-4245-8aa1-f5cf95b5d504",
        "uuid": "f7cb4141-3030-4245-8aa1-f5cf95b5d504"
    }
}
```

{% endtab %}
{% endtabs %}


# White Label Requirements

The following are the requirements from the partners to set up a white label for the RocketFuel payment solution:

1. Legal Business Name&#x20;
2. Logo (To be used inside the portal, Login page, and email): \
   *<mark style="color:green;">The minimum size of the logo is 100\*100 px</mark>*
3. Terms & Conditions link&#x20;
4. Privacy Policy Link&#x20;
5. The email address for all the communications with merchants
6. Contact email & Phone (As content in the email)&#x20;
7. Domain of the partner&#x20;
8. Merchant Portal link&#x20;
9. Invoice link&#x20;
10. Help/FAQ link
11. Partner Support link/Zendesk&#x20;

### **Action Required from Partner's End**

* **Verify Email**\
  When the partner will configure email on the RocketFuel partner portal, the partner will receive a verification link in an email, they will have to verify their email address by clicking on the link.
* **Set up DNS**\
  1\. log in to your Domain Control Center\
  2\. Go to DNS management setting\
  3\. Add a new CNAME record with following details\ <br>

  <table><thead><tr><th width="266">Name / Host / Alias</th><th width="173">Time to Live (TTL)</th><th>Record Type</th><th width="348">Value / Answer / Destination</th></tr></thead><tbody><tr><td>merchant.example.com</td><td>600</td><td>CNAME</td><td><ol><li><a href="https://d2in4x5rahkphr.cloudfront.net/">d2in4x5rahkphr.cloudfront.net</a> (Sandbox)</li><li><a href="https://d3ch3jjhdztpfb.cloudfront.net/">d3ch3jjhdztpfb.cloudfront.net</a> (Production)</li></ol></td></tr><tr><td>payment.example.com</td><td>600</td><td>CNAME</td><td><ol><li><a href="https://dneialt0ftrfb.cloudfront.net">dneialt0ftrfb.cloudfront.net</a> (Sandbox)</li><li><a href="https://d19bl7tezsv50x.cloudfront.net">d19bl7tezsv50x.cloudfront.net</a> (Production)</li></ol></td></tr></tbody></table>

  \
  \
  **Name**: The hostname or prefix the CNAME record will be set to. You can include a period (.) but not as the first or last character. Consecutive periods (...) are not allowed, and the host cannot exceed 63 characters or be the @ symbol. CNAMEs can't have the same Name/Host as any other record.\
  \
  **Value**: The URL you are setting as the destination for the host. Type **@** to point directly to your root domain name.\
  \
  **TTL**: How long the server should cache information. The default setting is 1 hour.\
  \
  4\. Save your changes

Most DNS updates take effect within an hour, but could take up to 48 hours to update globally.

**Note:** Once domain pointing has been done then whitelabelled URL needs to be shared with Rocketfuel Blockchain Inc to enable SSL on the provided URL.


# ACI Merchant Onboarding Document (Certification)

## Pre-requisite:- <a href="#pre-requisite" id="pre-requisite"></a>

1. ACI (Super Partner) should invite their partner ([Reference link](https://docs.rocketfuel.inc/user-guide-and-help-videos/partner-user-guide/how-to-invite-merchants))&#x20;
2. Partner should invite merchant from their portal ([Reference link](https://docs.rocketfuel.inc/user-guide-and-help-videos/partner-user-guide/how-to-invite-merchants))
3. Merchant Store should be set up. ([Reference link](https://docs.rocketfuel.inc/user-guide-and-help-videos/merchant-user-guide/settings))
4. Merchant should have generated public and secret keys ([Reference link](https://docs.rocketfuel.inc/user-guide-and-help-videos/merchant-user-guide/settings))
5. KYB of the merchant should have been completed ([Reference link](https://docs.rocketfuel.inc/user-guide-and-help-videos/merchant-user-guide/verification))
6. The partner should have generated Auth Header for the merchant from the partner portal ([Reference link](https://docs.rocketfuel.inc/user-guide-and-help-videos/partner-user-guide/how-to-generate-auth-header-for-merchants))

## RKFL ↔︎ ACI BIP Panel Setup <a href="#rkfl-aci-bip-panel-setup" id="rkfl-aci-bip-panel-setup"></a>

Data Mapping between RKFL ↔︎ ACI is provided below. These are needed to get your ACI BIP panel set up to receive payments using the ROCKETFUEL provider.

| **RKFL Field**           | **ACI field**        |
| ------------------------ | -------------------- |
| Merchant Id              | Entity Id            |
| Partner Id               | Authorization Bearer |
| Auth header              | Custom Data          |
| Secret Key / Partner Key | Secret               |

![](/files/g4xUVuG10CV1Fy0IN6vT)

![](/files/1MbxhLVYMB1CQV5PQ0S9)

### Post Setup and Integration:- <a href="#post-setup-and-integration" id="post-setup-and-integration"></a>

The following process shall be followed to certify the integration via Rocketfuel.

1. An invoice link should be sent to Rocketfuel (<rahul.k@rocketfuelblockchain.com>)
2. Rocketfuel shall execute the payment on the provided invoice link
3. Once the payment has been made on Rocketfuel, the merchant needs to share the transaction log on the BIP panel to cross-validate the payment update on the BIP panel

![](/files/Jfw8XyquwRXE6gAlnNvc)

![](/files/GQNhDrGyjwX3yvJzpstx)

First transaction update should change the transaction to **800.400.500** (Waiting for non-instant payment confirmation)

![](/files/rcJZfpWDaBsdjXehMF40)

Final Status of the transaction should be **000.000.000**

![](/files/ncRXNccStMl04AsODykT)

***

{% hint style="warning" %}
**Do not change the default time in the below settings.**&#x20;
{% endhint %}

<figure><img src="/files/ZTRjURVpp8TZyVMxZfAW" alt=""><figcaption></figcaption></figure>


# Merchant User Guide


# Sign-up Process

Step 1: To sign up as a merchant to use the RocketFuel payment solution, please contact us. Or your partner will invite you to onboard on the RocketFuel platform.

<figure><img src="/files/INTxoG6bVmsUsICgomF6" alt=""><figcaption></figcaption></figure>

Step 2: Fill the details in fields shown above. You will land on get started page which will look as shown in the image below.

<figure><img src="/files/7hysqpiSuIOCYfO9bRlW" alt=""><figcaption></figcaption></figure>

Step 3: Click on Confirm your Email. After you have confirmed your email you can verify your business from the Dashboard or from the Verification menu.

<figure><img src="/files/f25zgFIFqhVdmrvZHXoX" alt=""><figcaption></figcaption></figure>


# Sign-in Process

Step 1: Visit <https://merchant.rocketfuel.inc/sign-in>

Step 2: Fill in your email and password on the sign-in page and click on the 'Sign in' button.

![](/files/JDMGHx8VURjkz3zowz7q)

***If you have forgotten your password:*** You can click on the 'Forgot password?' button and follow the below steps:-

Step 1: Clicking on the 'Forgot password?' button will land you on the following page.

![](/files/1YxWHrTShcNFs34tJ9PG)

Fill in your email address and click on the 'Reset password' button, after which you will see a message: "**Check your email**

The email with further instructions was sent to the submitted email address. If you don’t receive a message in 5 minutes, check the junk folder. If you are still experiencing any problems, contact support at <support@rocketfuelblockchain.com>"

![](/files/tNwieuEFolUoH6WvvdY5)

Step2: In your inbox, you will receive one email as shown in the following image.

![](/files/CldmeB9kqkr7WHCFCaoP)

Click on the 'Click here to restore your password' button.

Step 3: Clicking on the 'Click here to restore your password' button will take you to "Create new password" page. Enter your new password and confirm the same and click on the 'Reset password' button.&#x20;

![](/files/IoYdNnZzsWdpV5MmSNbL)

After this you will see a success message "Your password has been changed successfully!"

![](/files/ulH4yHqkGrYzr45TLcya)

Step 4: Click on the 'OK' button, and you will land on the sign-in page again. Enter your email and new password and click on the 'Sign in' button.

![](/files/OqZm2D4RsOVBuTgM2oS6)


# Merchant Dashboard

**Dashboard**

Dashboard offers some of the main details relevant to you as a merchant. The main information on the dashboard are verification for payments, funds you received, and your shoppers' last purchases. Also, you get the option to change language, request support, and log out, which is accessible from all the main menu pages.

1. Verification for Payments

Verification can be done in two ways, either for only crypto payments or for crypto and bank both. You can also directly go to the Verification menu for your verification.

2\. Funds Received\
This section shows you the amount of funds received by you as per the selected period, which are Today, Week, Month, and Year. This is your income. You also get to see the cryptocurrencies in which you received the payment and how much. This will help you understand which cryptocurrencies your shoppers use most.

![](/files/hiS5cPc47gKDfjRfDs0g)

3\. Last Purchases

This section will give you a brief glimpse of last purchases of your shoppers. You will be able to see the following details\
\- Order ID\
\- Shopper Name\
\- Shopper Email\
\- Status of the transaction\
\- Date of the transaction\
\- Amount of the order (Both in fiat and cryptocurrency)

You will be able to search the transactions using the name or the email of the shopper. You will also be able to go to different pages to see more purchases that were made in the past.

![](/files/Mt8I6dDCapHMLUhAbWyL)


# Transactions

**Transactions**

The transactions page offers details about your transactions and refund requests raised by the shopper. There are two tables on the Transactions page, one named Transactions and the other named Refunds. Apart from accepting or declining the refund from the Refunds section, you can also initiate refunds from the transaction table.

1. Transactions

The transactions list shows you all purchases made by the shoppers on your website. The search text field is available under the Transactions heading to filter the transactions listing based on customer email, order ID, transaction ID, and transaction hash. You will be able to see details on the main line, which are:\
\- Transaction number\
\- Order ID\
\- Subscription Icon (to know if the transaction has any subscribed item) – it is only visible when the transaction is successful, and clicking on this icon will take you to the subscription page\
\- Shopper Name\
\- Partner Name\
\- Status of the transaction\
\- Date of the transaction\
\- Amount of the order (Both in fiat and cryptocurrency)

At a time, max. ten rows are presented to a user with pagination at the bottom of the list.

![](/files/7K2U2R7bIcif8gCfBUgs)

You also get the option to expand the transaction list to see more details by clicking on the “+” icon. Once you have expanded the transaction list, you will be able to see the following details:\
\- Transaction Hash\
\- Wallet Name\
\- Discount Amount\
\- Payable to Merchant (Amount payable to you after all the deductions of fee)\
\- Shipping Address\
\- Confirmed at (Date and time at which the transaction was confirmed)\
\- Transaction Id\
\- Payment Type\
\- Total Fee Charged\
\- Item details

<figure><img src="/files/Uo8Q9nLetgrgXdKl4EGw" alt=""><figcaption></figcaption></figure>

**Initiate Refund**: After expanding the transaction you will see the Refund button, this button is used to initiate a refund for the items in the given cart/order. Clicking on the Refund button will give you the option to choose the items for which you want to initiate a refund, specify the reason for the same, and fill in the wallet address for a refund (In case of crypto payment), in case of bank payments, the refund will be initiated to the same bank account using which shopper made the transaction. Once you click on Refund after filling in the details, the request is added to the Refunds section.

![](/files/aJbt1ZJOJ0AnhsT0y3NP)

2\. Refunds

This section helps you to check for all the refund requests by your shoppers and approve or decline them. You can also see the refunds initiated by you here. You will receive an email update whenever a refund is requested and for the further status of the refund. Even shoppers get updates in their emails about the refund progress.

You will be able to see details on the main headers, which are:\
\- Refund Number\
\- Shopper Name\
\- Status of the Refund

1. Refund Requested - When the refund has been requested by the shopper
2. Refund in Progress – When you have approved the refund (An action pending icon will appear if you act on only a few items out of n items in the refund request, or refund has failed for any item)
3. Refund Declined – When you have declined the refund
4. Refund Completed – When refund for all the items have been completed
5. Refund Completed Partially – When a refund is completed for a few items and declined for a few

\- Date/Time when the refund request was raised\
\- Refund ID\
\- Amount of the refund request

At a time, max. ten rows are presented to a user with pagination at the list's bottom.

![](/files/CqbSqI61VT9j1xr6knyA)

Information

1. Refund Requested - When the refund has been requested by the shopper
2. Refund Initiated – When you have approved the refund
3. Refund Failed – When a refund has failed for any item
4. Refund Completed – When the refund for the item has been completed
5. Refund Completed Manually – When a refund has been completed manually by you after the refund has failed
6. Refund Failed – When a refund has failed for the item

\- Reason stated by the shopper and you\
\- Initiated by (Refund was initiated by you or the shopper)

![](/files/VCmo1qCYF7lPNkZ0UOl8)

**Review Refund:** You have the Review button which appears after expanding the refund list for you to approve or decline the refund. Clicking on the Review button gives you the option to approve or decline the refund along with the option to choose a full or partial amount. You can choose to act on some items out of n items and act later on the remaining items. The status will keep updating as per the response being received from the system.

{% hint style="warning" %}
The shopper will be able to request a refund only if this has been allowed for your store. Otherwise, shoppers can only request a refund on partial payments which is auto-approved given that it is not settled with the merchants.
{% endhint %}

![](/files/WQvb4dcHOP93mpugAdY1)


# Shoppers

On the Shoppers page, you can see the last six purchases along with Total Purchases and Total Unique shoppers.

![](/files/4fhRFqsJhZXAZdWvTYpN)

You will also be able to see the details of your shoppers, including:

1. Shopper name
2. Email
3. Shopper Id
4. Registration date
5. Amount (total purchase value of the given shopper)

At a time, max. 10 rows are presented to a user with pagination at the list's bottom.

<figure><img src="/files/wEHhDPH2HQF3zHDsM4Jb" alt=""><figcaption></figcaption></figure>




---

[Next Page](/llms-full.txt/1)

