Recurring Payments [WIP]

{danger} This feature in technology preview and is subject to change without warning.

Create Recurring Payment

To create a recurring payment you can use the recurringPaymentCreate mutation.

The following fields are needed:

  • The title
  • A description
  • Buyer's token ID
  • A unique reference
  • The total value of the recurring payment
  • The interval at which the payment should be run
  • The fee allocation (who will pay the gateway fee)
  • Optionally additional beneficiaries (this allows you to allocate some or all of the payment to 3rd parties)

Using Beneficiaries

Beneficiaries allow you to pay some or all the recurring payment to a third party. Any number of beneficiaries can be added provided the total value for all beneficiaries does not exceed the recurring payment value.

Payment break down example:

If you have a recurring payment of R100 where the fee allocation is set to merchant. The buyer will be charged R100.00 and R3.00 transaction fee will be deducted. The total available funds equals R97.00.

If a beneficiary is included and their fees is R50.00 at the end of the month R50.00 will be paid to the beneficiary and the remaining R47.00 will be paid to the merchant.

However, if the beneficiary fee is R97.00 the beneficiary will receive R97.00 and the merchant will receive nothing at the end of the month.

mutation {
    recurringPaymentCreate(input: {
        title: "Title decribing the payment",
        description: "Description of what the payment is for",
        buyerTokenId: "4KV2DIIqyLHUm05SHG8Nw1",
        merchantReference: "Your unique identifier",
        value: 100,
        interval: MONTHLY,
        feeAllocation: BUYER,
        beneficiaries: {
            create: [
                {
                    tokenId: "2FbFYihtFmWhSNof8F7zTk",
                    value: 50
                }
            ]
        }
    }) {
        id
        title
        description
        state
        card {
            id
            cardholderName
        }
        buyer {
            id
            name
        }
        value
        fee
        totalValue
        feeAllocation
        interval
        endDate
        beneficiaries {
            token {
                id
            }
            value
        }
    }
}

Generate Payment Page URL

To generate the payment url use the recurringPaymentUrl query. This will generate a signed url that is valid for 15 minutes.

Query

query {
    recurringPaymentUrl(id: "6HBwcJ4hxt0YcH71kivRd8")
}

Result

{
    "data": {
        "recurringPaymentUrl": "https://pay.sandbox.tradesafe.dev/6HBwcJ4hxt0YcH71kivRd8?timestamp=1635507036&signature=32e4704be5dc63a624dddb6673792369c0caa6e7bfe1155bc366117cfa0153ff"
    }
}

Embedding the Payment Page

Once you have payment url you can embed the page into your application using an iframe.

The payment page is configured to send messages via the postMessage method.

To receive messages from the payment page you will need an event listener in your application.

Event listener example

window.addEventListener("message", (event) => {
    if (event.data.type !== undefined
        && event.data.type === 'tradesafeRecurringPaymentNotification') {
        console.log(event.data)
    }
}, false);

Message data

All messages include a type and a status variable. The message type is always set to tradesafeRecurringPaymentNotification this can be used to filter out events from else where in your application.

The status will be set to either success or error additional variables are available depending on the status.


Message data example - Success

Transaction completed without issue.

{
    "type": "tradesafeRecurringPaymentNotification",
    "status": "success",
    "id": "6HBwcJ4hxt0YcH71kivRd8",
    "state": "ACTIVE"
}

Message data example - Expired Card

Card has expired.

{
    "type": "tradesafeRecurringPaymentNotification",
    "status": "error",
    "id": "6HBwcJ4hxt0YcH71kivRd8",
    "message": "Could not process payment.",
    "reason": "Card Expired",
    "code": "EXPIRED"
}

Message data example - Suspected Fraud

There has been suspected fraudulent activity on this card.

{
    "type": "tradesafeRecurringPaymentNotification",
    "status": "error",
    "id": "6HBwcJ4hxt0YcH71kivRd8",
    "message": "Could not process payment.",
    "reason": "Suspected Fraud",
    "code": "FRAUD"
}

Message data example - Restricted Card

Card has been restricted by bank.

{
    "type": "tradesafeRecurringPaymentNotification",
    "status": "error",
    "id": "6HBwcJ4hxt0YcH71kivRd8",
    "message": "Could not process payment",
    "reason": "Card Restricted. Please contact your bank.",
    "code": "RESTRICTED"
}

Message data example - Lost Card

Card has been reported as lost.

{
    "type": "tradesafeRecurringPaymentNotification",
    "status": "error",
    "id": "6HBwcJ4hxt0YcH71kivRd8",
    "message": "Could not process payment",
    "reason": "Card reported as lost. Please contact your bank.",
    "code": "LOST"
}

Message data example - Stolen Card

Card has been reported as stolen.

{
    "type": "tradesafeRecurringPaymentNotification",
    "status": "error",
    "id": "6HBwcJ4hxt0YcH71kivRd8",
    "message": "Could not process payment",
    "reason": "Card reported as stolen. Please contact your bank.",
    "code": "STOLEN"
}

Message data example - Exceeded withdrawal amount

Card is reached it withdrawal limit for the day or month.

{
    "type": "tradesafeRecurringPaymentNotification",
    "status": "error",
    "id": "6HBwcJ4hxt0YcH71kivRd8",
    "message": "Could not process payment",
    "reason": "Withdrawal amount exceeds limit.",
    "code": "WITHDRAWAL_AMOUNT"
}

Message data example - Exceeded withdrawal frequency

There have been too many transactions for this card.

{
    "type": "tradesafeRecurringPaymentNotification",
    "status": "error",
    "id": "6HBwcJ4hxt0YcH71kivRd8",
    "message": "Could not process payment",
    "reason": "Withdrawal frequency exceeds limit.",
    "code": "WITHDRAWAL_FREQUENCY"
}