Create a payment request

Create a payment request

Payment requests are references to payments that you can present to your users in order to complete the payment.

The following code generates a new payment request:

const axios = require("axios").default;

const options = {
  method: 'POST',
  url: 'https://cloud.handcash.io/v2/paymentRequests',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    'app-secret': 'your-app-secret',
    'app-id': 'your-app-id'
  },
  data: {
    product: {
      name: 'Jump · Micro',
      description: 'Play a game to Jump in the Micro division.',
      imageUrl: 'https://haste-developer-portal-production-game-art.s3.amazonaws.com/Jump/gameicon.png'
    },
    receivers: [
      {sendAmount: 0.08, currencyCode: 'USD', destination: 'imaWinner'},
      {sendAmount: 0.02, currencyCode: 'USD', destination: 'haste'}
    ],
    requestedUserData: ['paymail'],
    notifications: {
      webhook: {
        customParameters: {gameId: '199491921'},
        webhookUrl: 'https://app.hastearcade.com/wehbooks/handcash'
      },
      email: '[email protected]'
    },
    expirationType: 'never',
    redirectUrl: 'https://app.hastearcade.com/games/ec04e9ca-71b6-4fb2-abb0-b6a2da072fb9'
  }
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});
import requests

url = "https://cloud.handcash.io/v2/paymentRequests"

payload = {
    "product": {
        "name": "Jump · Micro",
        "description": "Play a game to Jump in the Micro division.",
        "imageUrl": "https://haste-developer-portal-production-game-art.s3.amazonaws.com/Jump/gameicon.png"
    },
    "receivers": [
        {
            "sendAmount": 0.08,
            "currencyCode": "USD",
            "destination": "imaWinner"
        },
        {
            "sendAmount": 0.02,
            "currencyCode": "USD",
            "destination": "haste"
        }
    ],
    "requestedUserData": ["paymail"],
    "notifications": {
        "webhook": {
            "customParameters": {
                "gameId": "9ac9182acae19902"
            },
            "webhookUrl": "https://app.hastearcade.com/wehbooks/handcash"
        },
        "email": "[email protected]"
    },
    "expirationType": "never",
    "redirectUrl": "https://app.hastearcade.com/games/ec04e9ca-71b6-4fb2-abb0-b6a2da072fb9"
}
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "app-secret": "your-app-secret",
    "app-id": "your-app-id"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://cloud.handcash.io/v2/paymentRequests")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/json'
request["app-secret"] = 'your-app-secret'
request["app-id"] = 'your-app-id'
request.body = "{\"product\":{\"name\":\"Jump · Micro\",\"description\":\"Play a game to Jump in the Micro division.\",\"imageUrl\":\"https://haste-developer-portal-production-game-art.s3.amazonaws.com/Jump/gameicon.png\"},\"receivers\":[{\"sendAmount\":0.08,\"currencyCode\":\"USD\",\"destination\":\"imaWinner\"},{\"sendAmount\":0.02,\"currencyCode\":\"USD\",\"destination\":\"haste\"}],\"requestedUserData\":[\"paymail\"],\"notifications\":{\"webhook\":{\"customParameters\":{\"gameId\":\"9ac9182acae19902\"},\"webhookUrl\":\"https://app.hastearcade.com/wehbooks/handcash\"},\"email\":\"[email protected]\"},\"expirationType\":\"never\",\"redirectUrl\":\"https://app.hastearcade.com/games/ec04e9ca-71b6-4fb2-abb0-b6a2da072fb9\"}"

response = http.request(request)
puts response.read_body
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://cloud.handcash.io/v2/paymentRequests', [
  'body' => '{"product":{"name":"Jump · Micro","description":"Play a game to Jump in the Micro division.","imageUrl":"https://haste-developer-portal-production-game-art.s3.amazonaws.com/Jump/gameicon.png"},"receivers":[{"sendAmount":0.08,"currencyCode":"USD","destination":"imaWinner"},{"sendAmount":0.02,"currencyCode":"USD","destination":"haste"}],"requestedUserData":["paymail"],"notifications":{"webhook":{"customParameters":{"gameId":"9ac9182acae19902"},"webhookUrl":"https://app.hastearcade.com/wehbooks/handcash"},"email":"[email protected]"},"expirationType":"never","redirectUrl":"https://app.hastearcade.com/games/ec04e9ca-71b6-4fb2-abb0-b6a2da072fb9"}',
  'headers' => [
    'Accept' => 'application/json',
    'Content-Type' => 'application/json',
    'app-id' => 'your-app-id',
    'app-secret' => 'your-app-secret',
  ],
]);

echo $response->getBody();
curl --request POST \
     --url https://cloud.handcash.io/v2/paymentRequests \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --header 'app-id: your-app-id' \
     --header 'app-secret: your-app-secret' \
     --data '
{
     "product": {
          "name": "Jump · Micro",
          "description": "Play a game to Jump in the Micro division.",
          "imageUrl": "https://haste-developer-portal-production-game-art.s3.amazonaws.com/Jump/gameicon.png"
     },
     "receivers": [
          {
               "sendAmount": 0.08,
               "currencyCode": "USD",
               "destination": "imaWinner"
          },
          {
               "sendAmount": 0.02,
               "currencyCode": "USD",
               "destination": "haste"
          }
     ],
     "requestedUserData": [
          "paymail"
     ],
     "notifications": {
          "webhook": {
               "customParameters": {
                    "gameId": "9ac9182acae19902"
               },
               "webhookUrl": "https://app.hastearcade.com/wehbooks/handcash"
          },
          "email": "[email protected]"
     },
     "expirationType": "never",
     "redirectUrl": "https://app.hastearcade.com/games/ec04e9ca-71b6-4fb2-abb0-b6a2da072fb9"
}
'

The Haste app would use the payment request created with the code above to create a paywall to play a game (Jump) at a specific category (micro division).

A few interesting aspects to comment on:

  • The payment has 2 different receivers: imaWinner and haste.
  • The service will receive the user's paymail in the body of the webhook notification.
  • The service will receive the custom parameter gameId in the body of the webhook notification.
  • This payment request never expires as specified by "expirationType": "never" so the same link can be presented to users multiple times.
  • HandCash will notify the server every time a payment is successfully completed to the URL specified under notifications.webhookUrl (<https://app.hastearcade.com/wehbooks/handcash>).
  • HandCash will send an email every time a payment is successfully completed to [email protected].
  • The user will be redirected to redirectionUrl when the payment has been completed (<https://app.hastearcade.com/games/ec04e9ca-71b6-4fb2-abb0-b6a2da072fb9>).

The request would return the following:

{
  "id": "9ac9182acae19902",
  "paymentRequestUrl": "https://pay.handcash.io/9ac9182acae19902",
  "paymentRequestQrCode": "<base-64-qrcode-pay-bip270-scheme>",
  "isEnabled": true,
  "product": {
    "name": "Jump · Micro",
    "description": "Play a game to Jump in the Micro division.",
        "imageUrl": "https://haste-developer-portal-production-game-art.s3.amazonaws.com/Jump/gameicon.png"
  },
  "receivers": [
    {
      "sendAmount": 0.08,
      "currencyCode": "USD",
      "destination": "imaWinner"
    },
    {
      "sendAmount": 0.02,
      "currencyCode": "USD",
      "destination": "haste"
    }
  ],
  "requestedUserData": ["paymail"],
  "customParameters": {
    "gameId": "9ac9182acae19902"
    },
  "notifications": {
    "webhook": {
        "webhookUrl": "https://app.hastearcade.com/wehbooks/handcash"
      "customParameters": {
        "gameId": "9ac9182acae19902"
        },
    },
    "email": "[email protected]"
  },
  "redirectUrl": "https://app.hastearcade.com/games/ec04e9ca-71b6-4fb2-abb0-b6a2da072fb9",
  "expirationType": "never",
  "expiresAt": 1650558683
}

There are different ways for users to engage with the payment request:

  • paymentRequestUrl: URL to open the payment request in their device (browser or native app).
  • paymentRequestQrCode: QR to scan the payment request - Compatible with any BSV wallet.

Ultimately, developers decide which is the most convenient way of presenting the link to their users.

The image below represents what the payment request looks like in HandCash for the user.

968968

How the payment is presented to the user when the link is launched.

📘

Payment request expiration

Either because the payment was completed or because the expiration time has been reached, isEnabled will be set to false.

Check out the API Endpoint to find out more about creating payment requests.

Payment webhooks

If you set the notifications.webhook parameter as part of the payment requests, you will receive a notification every time a payment is successfully completed. In other words, HandCash will send an HTTP request to your server under the defined URL.

The endpoint you specified will receive a POST request with the following parameters:

{
  appSecret: "your-app-secret",
  paymentRequestId: "9ac9182acae19902",
  transactionId: "cc066a86e48f9f5715ba12f37c2cee0f525daf310eada76217b41771d6e67e66"
  customParameters: {
    // The specified customParameters in the PaymentLink notifications (if any)
  },
  userData: {
    // The requested user data (if any)
  }
}

Your server must return 200 once you have successfully processed the notification. Otherwise, HandCash will retry exponentially for 24 hours.

Payment webhooks provide you with all the flexibility you need to trigger any custom process in your product:

  • Unlock premium content - Build your custom paywall
  • Send a digital good like an ebook via email
  • Send a confirmation email and ship the product
  • Build your own Point-of-Sale system
  • Any custom online checkout

👍

Keep it secure

Make sure the appSecret included in the body of the webhook matches your appSecret. This HTTP call is invoked directly from HandCash to your service.


Did this page help you?