Skip to main content

Manual EFT Integration Process

Manual EFT payments can be made easily by creating payment requests via the API. Users can then be guided to the returned redirect URLs, in which the Stitch-hosted UI advises them on to how to make their EFT payments.

Generate Payment Request URL

Much like Pay By Bank, Manual EFT 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, the references that will appear on the user and beneficiary's accounts, and the beneficiary details themselves.

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

Additional Payment Methods

For now, Manual EFT is only available as an additional payment method to bank transfer on Pay By Bank. Payment Requests that are created with the Manual EFT payment method will allow customers to choose Manual EFT in addition to bank transfer. Currently, we do not support Manual EFT without Pay By Bank.

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

The following table outlines the possible inputs for Manual EFT:

StatusDescription
enabledBoolean field used to specify enable or disable Manual EFT. Note that by default, this will be enabled.
mobileNumberThe mobile number of the user, used for OTP verification. Either this or the email field must be specified per request.
emailThe email address of the user, used for OTP verification. Either this or the mobileNumber field must be specified per request.
referenceOptional field for the reference that the user specifies when making their payment. Reference must contain 6 to 20 alphanumeric characters. By default, a unique reference is generated and returned on the response.
Payment Methods

Please note that:

  • The paymentMethods.eft.manual field requires client configuration. Contact the technical team to assist in enabling your client for this feature.
  • Specifying a reference for the payment is supported but not recommended. Stitch will generate a unique reference for the payment if not provided.
  • The email and mobileNumber fields are used to verify users and reduce the risk of third-party deposits.
  • The payerInformation object is required to be populated, as this facilitates with handling risk and fraud measures around this payment method. More information on these particular fields can be found here.
  • Not setting the paymentMethods field results in a Pay By Bank payment request. To explicitly omit Pay By Bank as a payment method, provide the paymentMethods.eft.enabled field with a value of false, as shown below:
variables: {
"amount": {
"quantity": 1,
"currency": "ZAR"
},
"payerReference": "KombuchaFizz",
"beneficiaryReference": "Joe-Fizz-01",
"externalReference": "example-e32e5478-325b-4869-a53e-2021727d2afe",
"beneficiaryName": "FizzBuzz Co.",
"beneficiaryBankId": "fnb",
"beneficiaryAccountNumber": "123456789",
"paymentMethods": {
"eft": {
"enabled": false,
"manual": {
"enabled": true,
"mobileNumber": "0812345678"
}
}
}
}

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:

@include "docs/partials/default_redirect_uris.md"

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

@include "docs/partials/whitelist_uris.md"

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 the user successfully went through the UI and clicked 'I've paid', closed if the user clicked close in the UI, or failed if something went wrong while viewing the UI and payment instructionsString
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 parameter does not directly relate to the user successfully finalizing the transaction, as they are required to make the actual payment with their bank separately from the Stitch UI.

To secure yourself from attackers who can send a fake payload to your redirect or webhook endpoint, and update the payment at the same time as funds are successfully received from the payer, 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 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("/eft-pending");
case "closed":
case "failed":
redirect("/eft-retry");
default:
break;
}

Subscribe to Webhooks

As Manual EFT is built upon the same integration as Pay By Bank, we subscribe to webhooks and receive updates in the same way:

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 Manual EFT payment request works much like Pay By Bank

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

Which payment method did the customer choose?

To determine which payment method was used to complete the payment request, look at the payer field on the PaymentInitiationRequestCompleted state.

The PaymentInitiationEftManualPayer type indicates that the payment was completed using Manual EFT.

Simulating Completed Payment Requests

When using your test client, you may simulate completion of a payment request, directly over the API. This replicates payment updates that would be made when a real manual EFT payment is completed on a live client.

This is done by running the mutation shown below, containing the following input values:

  • The paymentRequestId of the pending payment request to be completed, and
  • The paymentMethod specified with the value eft_manual.

This results in the payment request moving to the final status PaymentInitiationRequestCompleted. A corresponding webhook notification will also be sent to your configured receiving endpoint.

Postman Collection

Manual EFT 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.