Skip to main content

Integrating Once-off Card with Stitch-Hosted UI

Once-off Card payments can be made easily by creating payment requests via the API. Users can then be guided to the returned redirect URLs, for them to complete their card payments within the Stitch-hosted UI.

Generate Payment Request URL

Much like Pay By Bank, Card creation is protected by a client token. You'll need to follow the steps described in the client token guide to obtain a client token with the client_paymentrequest scope. To create a payment initiation request, you'll need to ensure that the feature is enabled on your client.

To create the request, a GraphQL mutation is used to specify the requested amount, references and merchant information.

The GraphQL API URL https://api.stitch.money/graphql can be used for all payment requests (whether on test or live clients).

An example of a GraphQL request to create a payment initiation request with the Card payment method is shown below:

Card Payment Method Details

Please note that:

  • The paymentMethods.card type requires client configuration. Contact the technical team to assist in enabling your client for this feature.
  • Not setting the paymentMethods field results in the Pay by Bank method being enabled on your payment request. To explicitly omit Pay by Bank as payment method, specify the paymentMethods.eft.enabled field with a value of false.

Expiring payment requests

It is highly recommended that an expireAt Date (ISO 8601) is supplied in the creation of any payment initiation request. At the specified date and time, the payment request status will automatically move to PaymentInitiationRequestExpired, if the payment is not yet successfully completed.

Surface URL and Handle Callback

The URL returned by the API requires that a whitelisted redirect_uri is appended to it as a query string argument. If you direct a user to this URL, they will be guided through the process of completing the payment. For test clients, we do have the following URLs whitelisted by default:

For example, if your whitelist URL configuration included the URL https://example.com/payment for payment requests, you'd append the following query string to the url returned from the API: ?redirect_uri=https%3A%2F%2Fexample.com%2Fpayment. The full URL you expose to the user should look like this

https://secure.stitch.money/connect/payment-request/2b068bd5-6a5a-42e1-8a45-673cb3ede612?redirect_uri=https%3A%2F%2Fexample.com%2Fpayment
Whitelisting Redirect URLs

To add or remove a URL from the whitelist, please reach out to a Stitch Engineer via our Support Form

Please note that production clients will not be allowed to use unsecure redirect_uri params such as http. For example

http://example.com/payment

https://example.com/payment

Once the user completes or cancels the payment request, they'll be redirected back to the redirect_uri. The below query string parameters will be passed back to the redirect_uri.

Request FieldDescriptionType
idThe unique id of this payment requestID
statusStatus will have the value complete if successful, closed if the user clicked close in the UI, or failed if something went wrong when attempting the paymentString
payment_methodThe method used to complete the payment, card or eftString
externalReferenceThe value that was provided to the externalReference field when the payment initiation request was created. It can be used to correlate transaction IDs within your system with the payment request initiated by StitchString

The id can be used to retrieve the final payment request status and other details from the Stitch API, as well as relate to incoming webhooks.

danger

The status field should not be used for any database operations since an external party can tweak it. To secure yourself from attackers who can send a fake payload to your redirect or webhook endpoint, we recommend:

  1. using the webhooks as the source of truth as they are secure and will always be sent from Stitch.
  2. making use of signed webhooks since you'll be able to verify the signature of each incoming webhook's request payload.

Using the webhooks also ensures you'll still be able to know the final status of a payment request if for example the request times out due to a network issue.

Using Multiple Internal Redirect URIs

For a situation where different callbacks lead to different internal URLs, you SHOULD have a single whitelisted redirect URL which can then have the logic handling the Stitch callback and redirect to the internal URLs. An overview of how to do this in NodeJS is as shown below:

const status = params.status;

switch (status) {
case "complete":
redirect("/card-success");
case "closed":
case "failed":
redirect("/card-retry");
default:
break;
}

Cancelling Pending Payment Initiation Requests

If the user clicks the X on the dialog box, the payment initiation request will remain in the PaymentInitiationRequestPending status. To cancel the payment request, you should call the clientPaymentInitiationRequestCancel mutation, which also triggers the cancel webhook event.

Payment Initiation Request Statuses

The table below describes the different statuses a Card request can have, with the initial status always being PaymentInitiationRequestPending:

StatusDescription
PaymentInitiationRequestCompletedThis is a final payment state.
PaymentInitiationRequestPendingThe user hasn't yet completed the payment initiation request, or they exited the Stitch dialog box before completing the bank selection process.
PaymentInitiationRequestCancelledThe payment initiation request was manually cancelled by the client. More information on this can be found here.
PaymentInitiationRequestExpiredThe payment initiation request has expired while awaiting user interaction. More information on this can be found here.

Subscribe to Webhooks

Since Card is similar to Pay By Bank, we subscribe to webhooks and receive payment updates in the same way.

If the subscription is successfully created, the body returned by the request will look like the sample in the Example Response tab in widget above.

For more information on receiving webhook events, listing active webhook subscriptions, unsubscribing from webhooks and validating signed webhook subscriptions, please visit the Webhooks page.

Webhook Statuses

The payment webhook will be dispatched for each of the following status updates:

  • PaymentInitiationRequestCompleted
  • PaymentInitiationRequestCancelled
  • PaymentInitiationRequestExpired
Example Payload
{
"data": {
"client": {
"paymentInitiationRequests": {
"node": {
"__typename": "PaymentInitiationRequest",
"amount": {
"currency": "ZAR",
"quantity": "1"
},
"bankBeneficiaries": [
{
"__typename": "BankBeneficiary",
"accountNumber": "1223273660",
"bankAccountNumber": "1223273660",
"bankId": "nedbank",
"name": "FizzBuzz Co."
}
],
"beneficiaries": [
{
"__typename": "BankBeneficiary",
"accountNumber": "1223273660",
"bankAccountNumber": "1223273660",
"bankId": "nedbank",
"name": "FizzBuzz Co."
}
],
"beneficiaryReference": "KombuchaFizz",
"cancellationReason": null,
"created": "2022-10-11T09:52:13.312Z",
"createdAt": "2022-10-11T09:52:13.312Z",
"currency": "ZAR",
"events": [],
"externalReference": "79261d16-c53b-48eb-9019-dc9cfb6c5126",
"failureReason": null,
"id": "cGF5cmVxLzk2YjUyODU1LTBkMzQtNDI0MS04YmM2LWE4ODBlMDQ1ZGQzOQ==",
"payerConstraints": null,
"payerReference": "Joe-Fizz-01",
"paymentConfirmation": {
"__typename": "PaymentPending",
"date": "2022-10-11T09:52:53.128Z"
},
"paymentMethods": [
{
"cash": {
"atm": {
"enabled": true
},
"retailer": {
"barcodeNumber": "test-11132098754321",
"barcodeUrl": "https://test-barcode-url.com",
"enabled": true
}
}
},
{
"eft": {
"enabled": true
}
}
],
"paymentRequestPayerConstraintRelationship": null,
"quantity": "1",
"refunds": [],
"state": {
"__typename": "PaymentInitiationRequestCompleted",
"amount": {
"currency": "ZAR",
"quantity": 1
},
"beneficiary": {
"__typename": "BankBeneficiary",
"accountNumber": "1223273660",
"bankAccountNumber": "1223273660",
"bankId": "nedbank",
"name": "FizzBuzz Co."
},
"date": "2022-10-11T09:52:53.114Z",
"id": "96b52855-0d34-4241-8bc6-a880e045dd39",
"payer": {
"__typename": "PaymentInitiationBankAccountPayer",
"accountName": "Current account",
"accountNumber": "4104754941",
"accountType": "current",
"bankId": "absa"
},
"proofOfPayment": null
},
"updated": "2022-10-11T09:52:53.128Z",
"updatedAt": "2022-10-11T09:52:53.128Z",
"url": "https://secure-local.stitchmoney.com/connect/payment-request/96b52855-0d34-4241-8bc6-a880e045dd39",
"userReference": "Joe-Fizz-01"
}
}
}
}
}

Retrieving Payment Request Status

The status of a Card request works much like Pay By Bank.

To determine if and how a payment request was completed, we will need to retrieve its status.

The two pieces of information you need from the response at this stage are the payment request id, and the url. The payment request id is used to correlate responses and to look up the status of the request in the API, and so should be retained for later usage. The url is used to enable the user to authorize the payment request, and you'll need to redirect the user to this URL. We'll cover this in the next section.

Test Card Numbers

Our sandbox environment allows simulating success and failure cases when initiating a card transaction, without requiring real debit or credit card details.

You may use the below card numbers on the card input screen to trigger the corresponding scenario.

tip

For all cards numbers, any future date for the expiry date (in the format MM/YY), as well as any 3-digit value for the CVC, will process as expected.

ScenarioCard Number
3DS successful and payment completed4032035421088592
Transaction fails during 3DS verification4018884230103383, 4004462059871392
Transaction fails during payment authorization4009546746099840, 4032033425469975

Postman Collection

Card requests can be created and tested using the Postman collection available here. These can be used by specifying your client credentials and supplying the custom request variables where required.