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:

curl --request POST \
     --url https://cloud.handcash.io/v3/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": "Haste Hat",
               "description": "A hat that says Haste",
               "imageUrl": some-image-url
          },
          "receivers": [
               {
                    "sendAmount": 0.01,
                    "destination": "your-destination"
               }
          ],
          "requestedUserData": [
               "paymail"
          ],
          "notifications": {
               "webhook": {
                    "customParameters": {
                         "gameId": "199491921"
                    },
                    "webhookUrl": "https://app.hastearcade.com/wehbooks/handcash"
               },
               "email": "[email protected]"
          },
          "currencyCode": "BSV",
          "denominatedIn": "USD",
          "expirationType": "limit",
          "totalUnits": 5,
          "expirationInSeconds": 604800,
          "redirectUrl": "https://market.handcash.io/my-account/items/inventory/647a2e8e84940994f6aeb634?collectionId=659ddbeef30153e01217307e&sortBy=price&order=asc&page=1"
     }'

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

const options = {
  method: 'POST',
  url: 'https://cloud.handcash.io/v3/paymentRequests',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    'App-Secret': 'your-app-secret',
    'App-Id': 'your-app-id'
  },
  data: {
    receivers: [
      {
        sendAmount: 0.01,
        destination: 'your-destination'
      }
    ],
    product: {
      name: 'Haste Hat',
      description: 'A hat that says Haste',
      imageUrl: 'https://app.hastearcade.com/hat.jpg'
    },
    requestedUserData: ['paymail'],
    notifications: {
      webhook: {
        customParameters: { gameId: '199491921' },
        webhookUrl: 'https://app.hastearcade.com/wehbooks/handcash'
      },
      email: '[email protected]'
    },
    currencyCode: 'BSV',
    denominatedIn: 'USD',
    expirationType: 'limit',
    totalUnits: 5,
    redirectUrl: 'https://market.handcash.io/my-account/items/inventory/647a2e8e84940994f6aeb634?collectionId=659ddbeef30153e01217307e&sortBy=price&order=asc&page=1'
  }
};

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


The Haste app uses the payment request created with the code above to create a paywall for purchasing a Haste product (HandCash Hat).

Here are a few interesting aspects to comment on:

  • The payment has a single receiver: your-destination.
  • The request will expire in 604800 seconds (one week)
  • 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 expires after 5 payments as specified by "expirationType": "limit" and "totalUnits": 5.
  • HandCash will notify the server every time a payment is successfully completed to the URL specified under notifications.webhook.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 redirectUrl when the payment has been completed (https://market.handcash.io/my-account/items/inventory/647a2e8e84940994f6aeb634?collectionId=659ddbeef30153e01217307e&sortBy=price&order=asc&page=1).
  • Additionally, the redirect URL will include the transactionId as a query parameter, referring to the ID of the payment the user just completed.
  • Developers can use the redirect URL pattern to send users to a specific collection of digital items. The appId is the application's ID, and the collectionId is the ID of the collection of items the user is buying. For example:
    https://market.handcash.io/my-account/items/inventory/<appId>?collectionId=<collectionId>&sortBy=price&order=asc&page=1

The request would return the following:

{
  "id": "664391972c71a550012d28df",
  "paymentRequestUrl": "https://pay.handcash.io/664391972c71a550012d28df?domain=iae-app.handcash.io",
  "paymentRequestQrCodeUrl": "https://pay.handcash.io/api/paymentPreview/qr/664391972c71a550012d28df?domain=iae-app.handcash.io",
  "isEnabled": true,
  "product": {
    "name": "HandCash Hat",
    "description": "",
    "imageUrl": "https://res.cloudinary.com/hn8pdtayf/image/upload/v1574942466/round-handcash-logo_cj47fp.png"
  },
  "receivers": [
    {
      "sendAmount": 0.01,
      "destination": "6168647b619590b188eaed0"
    }
  ],
  "requestedUserData": ["paymail"],
  "notifications": {
    "webhook": {
      "webhookUrl": "https://app.hastearcade.com/wehbooks/handcash",
      "customParameters": {
        "gameId": "199491921"
      }
    },
    "email": "[email protected]"
  },
  "redirectUrl": "https://market.handcash.io/my-account/items/inventory/647a2e8e84940994f6aeb634?collectionId=659ddbeef30153e01217307e&sortBy=price&order=asc&page=1",
  "expirationType": "limit",
  "totalUnits": 5,
  "remainingUnits": 5,
  "expiresAt": "2024-05-14T16:35:15.111Z",
  "createdAt": "2024-05-14T16:35:15.116Z"
}

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

  • paymentRequestUrl: URL to open the payment request in the user's device (browser or native app).
  • paymentRequestQrCodeUrl: QR users can scan to engage with the payment request.

Ultimately, developers decide the most convenient way to present the link to their users.

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

Payment request preview in the HandCash app.

Payment request preview in the HandCash app.

πŸ“˜

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 learn more about creating payment requests.

Next steps

Check out the payment webhooks section to learn how to trigger any custom process when a payment is completed.