Online Payments

Introduction

Request Network is a decentralized way to accept cryptocurrencies, in the future the Request Network Foundation will also develop an even more straight forward way to start accepting them, feel free to subscribe to the newsletter to get alerted.

Disclaimer: Note that the Request Network is still in beta and the library is subject to evolve in the coming months. The Request Network is a protocol which is not owned or controlled by a company. This website won’t hold your cryptocurrencies. You are in charge of setting up a wallet on your own.

Features:

During the first beta phase, the Request Network will only allow ether payments. During the second beta phase, the Request Network will allow ERC20 payments. Support for Bitcoin and other cryptocurrencies will follow closely.

Plugins:

Steps to integrate Request Network:

If you already have a cryptocurrency account, there are only 2 steps:

  1. Create a request for payment on your back-end

  2. Add a payment button on your front-end and redirect the user to the gateway

It can be done in under 30 lines of code for a quick integration and can also be customized more if you wish to synchronize the orders with your own system.

A full example of calling Request is available on this Github.

Preconfiguration

Create a wallet to store your currencies

If you already have your wallets set up, you can skip this part and go here.

Ether (ETH)

You need to prepare a wallet to receive the ethers.

An ether address looks like this: 0xdD76B55ee6dAfe0c7c978bff69206d476a5b9Ce7

You can create your own address on different websites including:

Create an account to store your identity.

This account is a key that does not hold your money, the purpose is to be the proof that you are the one asking for a payment.

You need to generate a 12 words mnemonic seed, then store it somewhere safe. We recommend:

If someone accesses your mnemonic seed, he won’t be able to access the money you received on the other account. However he will be able to generate Requests in your name. Consider these words as a very important password.

Integrating Request Network

The developer view of the flow can be seen in the picture below:

Developer view of the flow

1. Create a request for payment on your back-end

a. Add dependencies and instantiate Request Network

On your backend, import the libraries:

import RequestNetwork, { Types } from '@requestnetwork/request-network.js';
const HDWalletProvider = require ('truffle-hdwallet-provider');
  • Install these two dependencies:

request-network.js npm install @requestnetwork/request-network.js --save

truffle-hdwallet-provider npm install truffle-hdwallet-provider

  • Instantiate Request Network:

Instantiating requestnetwork with HDWalletProvider on Mainnet:

const mnemonic = 'twelve word mnemonic phrase of the wallet used for signing the requests';
const provider = new HDWalletProvider(mnemonic, 'https://mainnet.infura.io/');
const networkId = 1; // 1 is for Mainnet (4 for Rinkeby testnet, 99 for local rpc)
const requestnetwork = new RequestNetwork(provider, networkId);

request-network.js needs a Web3 provider to sign requests. Web3 library is a collection of modules which contain specific functionality for the ethereum ecosystem.

In this guide we use truffle-hdwallet-provider which instantiates a Web3 provider to sign transactions for addresses derived from a 12-word mnemonic phrase.

new HDWalletProvider(mnemonic, provider_uri, index) (see example)

Parameter

Type

Description

mnemonic

string

12 word mnemonic which addresses are created from.

provider_uri

number

URI of Ethereum client to send all Web3 requests.

index

number (optional)

If specified, will tell the provider to manage the address at the index specified. Defaults to the first address (index 0).

By default, the HDWalletProvider will use the address of the first address that's generated from the mnemonic. If you pass in a specific index, it will use that address instead. Currently, the HDWalletProvider manages only one address at a time.

new RequestNetwork(provider, network_id) (see example)

Parameter

Type

Description

provider

object

Web3 Provider for the library to use.

networkId

number

network id you're using, must match the network of the provider's Ethereum client.

b. Signing a request

Example:

const requestData = { reason: 'Order #030890 from Just Another Shop',
orderId: '030890' }
const signedRequest = await requestnetwork.requestEthereumService.signRequestAsPayee(
['0x8F0255e24B99825e9AD4bb7506678F18C630453F'],
['175000000000000000'],
new Date().getTime() + 3600, // we put expiration after 1 hour here
['0xf9DF490146b29418a59F43dDb4Afc57Cd3fEf856'],
JSON.stringify(requestData),
);

The above command returns JSON structured like this:

{
"signedRequestData": {
"currencyContract": "0xe241d3757dad0ef86d0fcc5fe90e20f955743ed5",
"data": "QmSsrdAPhD5UkRVDKVpCwf63nrUxBaNbYmpZ2njbku9Mi5",
"expectedAmounts": [
"175000000000000000"
],
"expirationDate": 1529315288204,
"hash": "0x763ba38dca436907e0a34233a8ecc7568c0295ea03f144455defaa4e24f858ab",
"payeesIdAddress": [
"0x8F0255e24B99825e9AD4bb7506678F18C630453F"
],
"payeesPaymentAddress": [
"0xf9DF490146b29418a59F43dDb4Afc57Cd3fEf856"
],
"signature": "0xf9a5218d6a6baa8415d35ba6fe171a034fd9da8f5f458a01a2858ac5333e752813e7786fd1d57e5e81de4db493ee00ec0ef85e2863c6b7671f9df34be5eb86831c"
},
"currency": 2
}

Now we need to ask the library to create a request for payment.

async requestNetwork.createSignedRequest(as, currency, payees, expirationDate, requestOptions) (see example)

Parameter

Type

Description

as

Types.Role

Who is creating the Request (only Payee is implemented for now).

currency

Types.Currency

Currency of the Request (ETH, BTC, REQ, etc.).

payees

Types.IPayee[]

Array of payees (see below for IPayee details).

expirationDate

number

Timestamp in second of the date after which the signed request is not broadcastable anymore.

requestOptions

Types.IRequestCreationOptions

Request creation options. Includes request data, extension and ethereum transaction options.

IPayee is an object containing all the payment information, containing the following parameters:

Parameter

Type

Description

idAddress

string

ID address of the payee (see step in Preconfiguration).

paymentAddress

string

Address on which to receive the payment (see step in Preconfiguration).

expectedAmount

number

Amount in Wei of the payment Request. (1Eth = 1000000000000000000 Wei).

c. Store metadata

Request Network supports adding metadata to every request.

Privacy: The metadata are public as of today. You will be able to select the privacy during the second part of the beta phase.

Accounting: Accounting standardized data will be specified during the first beta phase.

We use the following format data = { reason: String, orderId: String }, as a parameter of requestOptions when creating the signedRequest.

2. Add a payment button on your front-end and redirect the user to the gateway

Example of Html and css code for styling a “pay with ETH” button:

<button class="pay-with-button">
<img src="https://payments.request.network/assets/request-logo.png" style="height: 30px;">
<span>Pay with&nbsp;</span>
<img src="https://payments.request.network/assets/eth-logo-white.png" style="height: 20px;">
<span _ngcontent-c1="">&nbsp;ETH</span>
</button>
`
pay-with-button {
height: 60px;
min-width: 200px;
display: flex;
align-items: center;
background-color: #103b56;
font-size: 16px;
font-weight: normal;
color: white;
border: none;
border-radius: 2px;
border-bottom: 3px solid #6CFDCC;
padding: 0 16px;
}

a. Adding the button to your website

pay-with button

See example code for styling a "paywith ETH" button.

b. Redirect to the gateway

In order to ease the process for integrating a pay-with-request button on your website, the request app provides a gateway for displaying the info of a signed request and allowing someone to pay it.

Example for redirectiong to the gateway with right parameters:

const qs = JSON.stringify({signedRequest: signedRequest.signedRequestData, callbackUrl: myCallbackUrl, networkId: 1}));
const qsBase64 = btoa(qs);
const qsb64Encoded = encodeURIComponent(qsBase64);
document.location.href = 'https://app.request.network/#/pay-with-request/' + qsb64Encoded;

The gateway url is https://app.request.network/#/pay-with-request/<qsBase64>

where qsBase64 is a base 64 encoded string of a JSON object containing the following mandatory parameters

Parameter

Type

Description

signedRequest

object

signedRequestData pamareter from the signedRequest object returned from requestnetwork.createSignedRequest method (see paragraph above for format).

callbackUrl

string

url for the gateway to redirect after request has been paid

networkId

string

id of the network on which you signed the request (see step 1.)

Paying on the gateway

You can find an example of how a signed request looks like on the gateway on this link

On the gateway, the payer connects to his ether wallet and pays the request.

Once the payment transaction is broadcasted, the gateway redirect to the callbackUrl concatenated with the string of the transaction hash.

Please note that, at the moment, the gateway only supports requests in ETH and with only one payee.

Example:

myCallbackUrl/0xb8e90ba15bb09d1b5baba628fcc01d0302d8d47dc854e85e6deeb5c60f6d3f2b

Otherwise, if the payer click on 'cancel & go back to merchant', the gateway will redirect to the callbackUrl concatenated with the signed request json object stringified.

Your signature ensure that only the information you signed can be broadcasted on ethereum's blockchain.

Additional info

Verify your orders and/or Reconcile

After paying on the gateway the user is now redirected to your callback URL and you can display a custom message to confirm the success of the operation.

Note that as a blockchain payment is only confirmed after a certain time, you can’t be sure that the payment has been done at this moment.

You can view your payments at this URL, replacing the address with your own ID address (created in paragraph Preconfiguration) https://app.request.network/#/search/0x54B4B2d8E2ECcC99385B01bE13DFB473c7885286

Reconcile the payment with your own system

Example:

try {
const txHash = 0xb8e90ba15bb09d1b5baba628fcc01d0302d8d47dc854e85e6deeb5c60f6d3f2b;
const result = await requestnetwork.requestCoreService.getRequestByTransactionHash(txHash);
} catch (err) {
console.error(err);
}
}

The above command returns JSON structured like this:

{
"transaction": {
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"blockNumber": null,
"from": "0x1AA3fFefeaeC333f9BF76b705547D08c90cC1280",
"gas": 287504,
"gasPrice": "1000000000",
"hash": "0x8083f504e6f515a5c98debcbd54fd1c98c86d9eff7098d1b701e8eacbe5856e8",
"input": "0x9dbdd85c00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000001626ac2d6390000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000008c8f0255e24b99825e9ad4bb7506678f18c630453f0000000000000000000000000000000000000000018f0255e24b99825e9ad4bb7506678f18c630453f000000000000000000000000000000000000000000000000026db992a3b180002e516d537372644150684435556b5256444b567043776636336e72557842614e62596d705a326e6a626b75394d693500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f9df490146b29418a59f43ddb4afc57cd3fef8560000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000026db992a3b180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004156d628e48ead956625124627ad2dafb4d51a9e913339038de8aeefd1b017fc921917a2c9d73e94d8836a757ac7722588063b907c14834f069627bf36a6ca0ef61b00000000000000000000000000000000000000000000000000000000000000",
"nonce": 79,
"to": "0xAFA312973909C3a541665e11C883a24a8eb10b2C",
"transactionIndex": 0,
"value": "175000000000000000",
"v": "0x2c",
"r": "0xbaf3e6351bd41581f3557a0baef9f63eaee184327b2f698a1b7697f70f9006fe",
"s": "0x664b8f600a6ce7b0806780dfcc657e84dd281d2896289eaf11da9daf303e1640",
"method": {
"name": "broadcastSignedRequestAsPayer",
"parameters": {
"0": "0x8f0255e24b99825e9ad4bb7506678f18c630453f0000000000000000000000000000000000000000018f0255e24b99825e9ad4bb7506678f18c630453f000000000000000000000000000000000000000000000000026db992a3b180002e516d537372644150684435556b5256444b567043776636336e72557842614e62596d705a326e6a626b75394d6935",
"1": [
"0xf9DF490146b29418a59F43dDb4Afc57Cd3fEf856"
],
"2": [
"175000000000000000"
],
"3": [],
"4": "1522209576505",
"5": "0x56d628e48ead956625124627ad2dafb4d51a9e913339038de8aeefd1b017fc921917a2c9d73e94d8836a757ac7722588063b907c14834f069627bf36a6ca0ef61b",
"__length__": 6,
"_requestData": "0x8f0255e24b99825e9ad4bb7506678f18c630453f0000000000000000000000000000000000000000018f0255e24b99825e9ad4bb7506678f18c630453f000000000000000000000000000000000000000000000000026db992a3b180002e516d537372644150684435556b5256444b567043776636336e72557842614e62596d705a326e6a626b75394d6935",
"_payeesPaymentAddress": [
"0xf9DF490146b29418a59F43dDb4Afc57Cd3fEf856"
],
"_payeeAmounts": [
"175000000000000000"
],
"_additionals": [],
"_expirationDate": "1522209576505",
"_signature": "0x56d628e48ead956625124627ad2dafb4d51a9e913339038de8aeefd1b017fc921917a2c9d73e94d8836a757ac7722588063b907c14834f069627bf36a6ca0ef61b"
}
}
}
}

1. Query the hash received during the callback from your backend to know which order it is

If you need to reconcile the payment with your own system, the library provides a method for getting the transaction information from a txHash:

async requestnetwork.requestCoreService.getRequestByTransactionHash(txHash)

Parameter

Type

Description

txHash

string

hash of the ethereum transaction

Transaction information may not appear instantly after user paid the request and got redirected to the callbackUrl. Also you will have to call the method getRequestByTransactionHash until you receive a response with the transaction data.

2. Compare the signature to verify the order is as expected

Once you receive the transaction object, you need to check some parameters to ensure it actually corresponds to the broadcast of a request payment transaction.

  • The first one is verifying the name of the method called is "broadcastSignedRequestAsPayer" or "broadcastSignedRequestAsPayerAction" (for ERC20 requests):

transaction.method.name === 'broadcastSignedRequestAsPayer' || transaction.method.name === 'broadcastSignedRequestAsPayerAction'

Example for getting additionnal info of the transaction:

data = requesnetwork.requestCoreService.parseBytesRequest(result.transaction.method.parameters._requestData);

The above command returns JSON structured like this:

{
"creator": "0x8f0255e24b99825e9ad4bb7506678f18c630453f",
"payer": "0x0000000000000000000000000000000000000000",
"mainPayee": {
"address": "0x8f0255e24b99825e9ad4bb7506678f18c630453f",
"expectedAmount": "26db992a3b18000"
},
"subPayees": [],
"data": "QmSsrdAPhD5UkRVDKVpCwf63nrUxBaNbYmpZ2njbku9Mi5"
}
  • Second one is verifying that the amount paid matches the total amount of the request

For that you need to call an additionnal method:

requestnetwork.requestCoreService.parseBytesRequest(requestData)

Parameter

Type

Description

requestData

string

request data bytes (variable found in transaction json object above transaction.method.parameters._requestData)

From that point if you stored the signed request information on a database, you just need to verify that transaction.method.parameters._signature matches a known signature

3. Query the blockchain until the payment is complete

You need to query getRequestByTransactionHash until you have a request object with and verify the payment is correct.

Extras

Converting currencies

A request has to be paid in the cryptocurrency it was created with for the moment.

In the future, the request will be able to convert the currency automatically.

If you would like to exchange cryptocurrency to fiat money, you will have to use one of the cryptocurrency exchange available in your country.

Disputes & Fraud

There is no chargeback on the blockchain. To protect the user, automated escrow systems will be created and adding to this documentation in S2 2018.

Recurring payments (not available yet)

Creating your own gateway

The Request Network Foundation is managing the app.request.network gateway. Anyone can create its own process or gateway to pay a request, by using the resources below.

Resources:

https://github.com/RequestNetwork/Request/wiki

https://github.com/RequestNetwork/Requestnetwork

Next steps

A dashboard is under development and will simplify the merchant process.