Taking Direct Debit payments using Billing Requests and Custom Payment Pages

What is a billing request?

For the purposes of this tutorial, a Billing Request is a wrapper around all of the GoCardless APIs required to take a payment from a customer. This allows you, the integrator, to define desired outcomes upfront (for example, "I want to take a payment from X") and guides you through the process to achieve them.

What is the aim of this tutorial?

This tutorial aims to familiarise beginners with using Billing Requests to collect Direct Debit payments using Custom Payment Pages. It will not cover Instant Bank payments (IBP) or VerifiedMandates (VM).

Getting started

For this tutorial, you will need:

  • An API token

  • The GoCardless client library of your choice configured in your language of choice

  • A Creditor to collect payments against

Creating a Billing Request

We can start by creating a Billing Request. This will allow us to request a Mandate to take a payment against that is linked to a Creditor.

1POST https://api.gocardless.com/billing_requests HTTP/1.1 2Content-Type: application/json 3{ 4 "billing_requests": { 5 "mandate_request": { 6 "scheme": "bacs" 7 }, 8 "links": { 9 "creditor": "CR123" 10 } 11 } 12} 13 14HTTP/1.1 201 Created 15Location: /billing_requests/BRQ123 16Content-Type: application/json 17{ 18 "billing_requests": { 19 "id": "BRQ123", 20 "created_at": "2023-03-22T15:20:08.397Z", 21 "status": "pending", 22 "mandate_request": { 23 "currency": "GBP", 24 "scheme": "bacs", 25 "links": {} 26 }, 27 ... 28}

For the purposes of this tutorial, we only need to keep track of the ID of the Billing Request: BRQ123

We request the desired scheme, in this instance, we are going to use bacs for a GBP mandate. If you want to collect in EUR, use sepa_core. We link the Billing Request to the creditor we wish to pay out to, CR123.

In the next steps, we complete the required Billing Request actions to fulfil our request. The actions returned from the API describe steps that must be taken for a Billing Request to be fulfilled. They can change depending on the type of payment being taken or set up (e.g a Direct Debit or Instant Bank payment). We don’t need to worry about them too much in this tutorial - but it’s good to be aware of them! You can read more about them here if you’re interested.

Collect customer details

Next, we need to collect the details of our customer

1POST https://api.gocardless.com/billing_requests/BRQ123/actions/collect_customer_details HTTP/1.1 2Content-Type: application/json 3{ 4 "data": { 5 "customer": { 6 "email": "alice@example.com", 7 "given_name": "Alice", 8 "family_name": "Smith" 9 }, 10 "customer_billing_detail": { 11 "address_line1": "1 Somewhere Lane", 12 "city": "London", 13 "postal_code": "E5 8EE", 14 "country_code": "GB" 15 } 16 } 17} 18 19HTTP/1.1 200 20Content-Type: application/json 21{ 22 "billing_requests": { 23 "id": "BRQ123", 24 ... 25 "links": { 26 "customer": "CU123", 27 "customer_billing_detail": "CBD123" 28 }, 29 ... 30 }, 31 "resources": { 32 "customer": { 33 "id": "CU123", 34 "created_at": "2021-03-22T12:20:04.238Z", 35 "email": "alice@example.com", 36 "given_name": "Alice", 37 "family_name": "Smith", 38 ... 39 }, 40 "customer_billing_detail": { 41 "id": "CBD123", 42 "created_at": "2021-03-22T12:20:04.374Z", 43 "address_line1": "1 Somewhere Lane", 44 ... 45 } 46 } 47}

Note we now have a link to a Customer and Customer Billing Detail

Collect bank account details

Now we need to collect the customer bank account details to be able to create a Mandate against the customer.

1POST https://api.gocardless.com/billing_requests/BRQ123/actions/collect_bank_account HTTP/1.1 2Content-Type: application/json 3{ 4 "data": { 5 "account_number": "55779911", 6 "branch_code": "200000", 7 "account_holder_name": "Alice Smith", 8 "country_code": "GB" 9 } 10} 11 12HTTP/1.1 200 13Content-Type: application/json 14{ 15 "billing_requests": { 16 "id": "BRQ123", 17 ... 18 "links": { 19 "customer": "CU123", 20 "customer_billing_detail": "CBD123" 21 }, 22 ... 23 }, 24 "resources": { 25 "customer": { 26 "id": "CU123", 27 "created_at": "2021-03-22T12:20:04.238Z", 28 "email": "alice@example.com", 29 "given_name": "Alice", 30 "family_name": "Smith", 31 ... 32 }, 33 "customer_billing_detail": { 34 "id": "CBD123", 35 "created_at": "2021-03-22T12:20:04.374Z", 36 "address_line1": "1 Somewhere Lane", 37 ... 38 }, 39 "customer_bank_account": { 40 "id": "BA123", 41 "created_at": "2021-03-22T12:20:04.374Z", 42 "account_holder_name": "Alice Smith", 43 "account_number_ending": "11", 44 "country_code": "GB", 45 "currency": "GBP", 46 "bank_name": "BARCLAYS BANK PLC", 47 "enabled": true, 48 "links": { 49 "customer": "CU123" 50 } 51 } 52 } 53}

Confirm Payer details

This is needed when you have a Mandate Request. As a scheme compliance rule, we are required to allow the payer to crosscheck the details entered by them and confirm them.

For a live integration, you would want to show a summary of the payer details (the information we took in the previous two steps) and give the option to cancel. For the purposes of this tutorial, we can just call the confirm endpoint.

1POST https://api.gocardless.com/billing_requests/BRQ123/actions/confirm_payer_details HTTP/1.1 2 3HTTP/1.1 200 4Content-Type: application/json 5{ 6 "billing_requests": { 7 "id": "BRQ123", 8 "mandate_request": { 9 "currency": "GBP", 10 "scheme": "bacs", 11 "links": { 12 "mandate": "MD123" 13 } 14 }, 15 "actions": [ 16 ... 17 { 18 "type": "confirm_payer_details", 19 "required": true, 20 "requires_actions": [ 21 "collect_customer_details", 22 "collect_bank_account" 23 ], 24 "status": "completed" 25 } 26 ... 27 ] 28 } 29}

We want to keep track of our Mandate ID for the step where we take a payment.

Fulfil

This step ‘executes’ the Billing Request, using the contents of our request to create a Mandate. This will create a Mandate within GoCardless to take payments against. The fulfil action is the step where the collected Information will be submitted to our partner bank(s).

It can be batched with the confirm payer details call above. It is a separate step (and API call) as we may sometimes want to combine different types of payment (e.g Open banking) with the creation of a Mandate.

1POST https://api.gocardless.com/billing_requests/BRQ123/actions/fulfil HTTP/1.1 2 3HTTP/1.1 200 4Content-Type: application/json 5{ 6 "billing_requests": { 7 "id": "BRQ123", 8 "status": "fulfilled", 9 ... 10 }, 11 ... 12}

Taking a payment

We can now use the GoCardless Payments API to take a payment against our newly created Mandate!

1POST https://api.gocardless.com/payments HTTP/1.1 2Content-Type: application/json 3{ 4 "payments": { 5 "amount": 1200, 6 "currency": "GBP", 7 "reference": "Wine Box", 8 "metadata": { 9 "order_dispatch_date": "2023-03-29" 10 }, 11 "links": { 12 "mandate": "MD123" 13 } 14 } 15} 16 17HTTP/1.1 201 Created 18Location: /payments/PM123 19Content-Type: application/json 20{ 21 "payments": { 22 "id": "PM123", 23 "created_at": "2023-03-22T17:01:06.000Z", 24 "charge_date": "2023-03-24", 25 "amount": 1200, 26 "currency": "GBP", 27 "status": "pending_submission", 28 "reference": "WINEBOX001", 29 "metadata": { 30 "order_dispatch_date": "2023-03-29" 31 }, 32 ... 33 "links": { 34 "mandate": "MD123", 35 "creditor": "CR123" 36 } 37 } 38}

Note that we charge the amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR).

We can see the date that the payment will be taken by looking at the charge_date in the response.

What's next?

Handling webhooks