# Billing Request (PayTo feature)

## Using the JavaScript Drop-in

This guide shows how to use the Javascript Drop-in to allow customers to complete the Billing Request Flow without leaving the integrator’s site.

Use the Drop-in when you already have a frontend website, and want to benefit from having customers stay on your site, and avoiding site-to-site redirects.

### Installation

### Javascript

Install the Drop-in by adding the initialise script to your site:

```HTML
<script src="https://pay.gocardless.com/billing/static/dropin/v2/initialise.js"></script>
```

> You are discouraged from bundling the initialisation script or vendoring it, **as GoCardless reserves the right to make non-breaking changes** to the underlying implementation, which you will want your sites to pickup automatically.
>
> _We guarantee backward compatibility between major versions of the initialise script, as denoted by the script source URL._

### React

GoCardless offer a [react-dropin](https://github.com/gocardless/react-dropin) library that provides React bindings and TypeScript definitions for the Drop-in: check the [README](https://github.com/gocardless/react-dropin) for full details, and example implementations.

You can install the package using either npm or yarn.

```shell-session
//With npm:
npm install --save @gocardless/react-dropin

// With yarn:
yarn add @gocardless/react-dropin
```

Once installed, you can import the React bindings:

```javascript
import {
  useGoCardlessDropin,
  GoCardlessDropinOptions,
  GoCardlessDropinOnSuccess,
} from "@gocardless/react-dropin";
```

### Create

### Create a Billing Request

---

As mentioned before, PayTo supports two key use cases:

1. Setting up an open mandate with your customer
2. Taking one-off real-time payments

To set up a mandate (the first use case) use the mandate_request field when creating your Billing Request. To create a real-time payment (the second use case) use the payment_request field when creating your Billing Request.

Most integrators will use Billing Requests to create a mandate alongside a new customer, so we’ll use that as our example.

Please keep in mind that the requirements below should be met to create a PayTo mandate successfully:

- the scheme is stated as `pay_to`
- the `purpose_code` attribute is set
- the `description` attribute is provided
- the `constraints` object is optionally passed

##### Purpose Code

This attribute is required to create a PayTo mandate.

It specifies the high-level purpose of a mandate and/or payment using a set of pre-defined categories; `mortgage`, `utility`, `loan`, `dependant_support`, `gambling`, `retail`, `salary`, `personal`, `government`, `pension`, `tax `and `other`.

##### Constraints

constraints specify the limits on recurring payments. We can continue to take payments without the payer needing to provide consent every time as long as they are within the constraints stated during the set up of the PayTo mandate.

You can set the following parameters:

- `start_date` - the date from which the consent will be valid. It will be shown to a payer to confirm and hence should be considered in the payer timezone. This date cannot be older than the date when the payer authorises the consent. Therefore if you want to specify it, make sure that it is not in the past and that the payer has enough time to complete the flow before the date will come.
- `end_date` - the date after which we will not be able to collect payments, as the consent stops being valid. It will be shown to a payer to confirm and hence should be considered in the payer timezone. This date cannot be in the past or older than the start date.
- `max_amount_per_payment` - maximum amount that can be charged for a single payment.
- `periodic_limits` - frequency configuration - `period` - repeating time frame presented as "year", "month", "week" or "day".
- `max_payments` - maximum amount of payments that can be taken within a period

Use the [Create a Billing Request](https://developer.gocardless.com/api-reference/#billing-requests-create-a-billing-request) endpoint:

```HTTP
POST https://api.gocardless.com/billing_requests HTTP/1.1
{
   "billing_requests": {
      "purpose_code": "mortgage",
       "mandate_request": {
           "currency": "AUD",
           "scheme": "pay_to",
           "constraints": {
               "start_date": "2030-06-27",
               "end_date": "2020-12-30",
               "max_amount_per_payment": 100,
               "periodic_limits": [{
                   "period": "month",
                   "max_payments": 2
               }]
           }
       }
   }
}
```

You’ll receive a full Billing Request object, including things like actions and resources.

It will look like this:

```json
{
  "billing_requests": {
    "id": "BR123",
    "status": "pending",
    "mandate_request": {
      "currency": "AUD",
      "scheme": "pay_to",
      "constraints": {
        "start_date": "2030-06-27",
        "end_date": "2020-12-30",
        "max_amount_per_payment": 100,
        "periodic_limits": [
          {
            "period": "month",
            "max_payments": 2
          }
        ]
      }
    },
    "payment_request": null,
    "metadata": null,
    "links": {
      "customer": "CU123",
      "customer_billing_detail": "CBD123",
      "creditor": "CR123",
      "organisation": "OR123",
      "mandate_request": "MRQ123"
    },
    "purpose_code": "mortgage",
    "creditor_name": "Hotel Park Grand",
    "actions": [
      {
        "type": "collect_customer_details",
        "required": true,
        "status": "pending"
      },
      {
        "type": "collect_bank_account",
        "required": true,
        "status": "pending"
      },
      {
        "type": "bank_authorisation",
        "required": true,
        "status": "pending"
      }
    ]
  }
}
```

The Billing Request is currently `pending`, meaning we need to complete the outstanding actions before it can be fulfilled. We can use Billing Request Flows to generate a checkout flow that guides the payer through these actions.

### Create a Billing Request Flow

---

Billing Request Flows can be created against Billing Requests, and provide an entry into a hosted GoCardless flow that completes whatever actions remain against the request.

Create a Billing Request Flow to retrieve a link that can be provided to your customer to complete the request:

```PHP
$client = new \GoCardlessPro\Client(array(
  'access_token' => 'your_access_token_here',
  'environment'  => \GoCardlessPro\Environment::SANDBOX
));

$client->billingRequestFlows()->create([
  "params" => [
    "redirect_uri" => "https://my-company.com/landing",
    "exit_uri" => "https://my-company.com/exit",
    "links" => [
      "billing_request" => "BRQ000010NMDMH2"
    ]
  ]
]);
```

```python
import gocardless_pro
client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox')

client.billing_request_flows.create(params={
  "redirect_uri": "https://my-company.com/landing",
  "exit_uri": "https://my-company.com/exit",
  "links": {
    "billing_request": "BRQ000010NMDMH2"
  }
})
```

```ruby
@client = GoCardlessPro::Client.new(
  access_token: "your_access_token",
  environment: :sandbox
)

@client.billing_request_flows.create(
  params: {
    redirect_uri: "https://my-company.com/landing",
    exit_uri: "https://my-company.com/exit",
    links: {
      billing_request: "BRQ000010NMDMH2",
    }
  }
)
```

```java
import static com.gocardless.GoCardlessClient.Environment.SANDBOX;
String accessToken = "your_access_token_here";
GoCardlessClient client = GoCardlessClient
    .newBuilder(accessToken)
    .withEnvironment(SANDBOX)
    .build();

BillingRequestFlow billingRequestFlow = client.billingRequestFlows().create()
  .withRedirectUri("https://my-company.com/landing")
  .withExitUri("https://my-company.com/exit")
  .withLinksBillingRequest("BRQ000010NMDMH2")
  .execute();
```

```javascript
const constants = require("gocardless-nodejs/constants");
const gocardless = require("gocardless-nodejs");
const client = gocardless(
  "your_access_token_here",
  constants.Environments.Sandbox,
);

const billingRequestFlow = await client.billingRequestFlows.create({
  redirect_uri: "https://my-company.com/landing",
  exit_uri: "https://my-company.com/exit",
  links: {
    billing_request: "BRQ000010NMDMH2",
  },
});
```

```.net
String accessToken = "your_access_token";
GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX);

var resp = await gocardless.BillingRequestFlows.CreateAsync(
  new GoCardless.Services.BillingRequestFlowCreateRequest()
  {
    RedirectUri = "https://my-company.com/landing",
    ExitUri = "https://my-company.com/exit",
    Links = new GoCardless.Services.BillingRequestFlowCreateRequest.BillingRequestFlowLinks {
      BillingRequest = "BRQ000010NMDMH2",
    },
  }
);

GoCardless.Resources.BillingRequestFlow billingRequestFlow = resp.BillingRequestFlow;
```

```http
POST https://api.gocardless.com/billing_request_flows HTTP/1.1
{
  "billing_request_flows": {
    "redirect_uri": "https://my-company.com/landing",
    "exit_uri": "https://my-company.com/exit",
    "links": {
      "billing_request": "BRQ000010NMDMH2"
    }
  }
}
```

```go
package main

import (
	gocardless "github.com/gocardless/gocardless-pro-go"
)

accessToken := "your_access_token_here";
opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint)
client, err := gocardless.New(accessToken, opts)

billingRequestFlowCreateParams := gocardless.BillingRequestFlowCreateParams{}
billingRequestFlowCreateParams.RedirectUri = "https://my-company.com/landing"
billingRequestFlowCreateParams.ExitUri = "https://my-company.com/exit"
billingRequestFlowCreateParams.Links.BillingRequest = "BRQ000010NMDMH2"
billingRequestFlow, err := client.BillingRequestFlows.Create(context, billingRequestFlowCreateParams)
```

```CLI
gc create billing_request_flow \
  -d "links[billing_request]= BRQ000010NMDMH2" \
  -d 'redirect_uri=https://my-company.com/landing' \
  -d 'exit_uri=https://my-company.com/exit'
```

This returns a new flow, which has an `authorisation_url` you should send to your customer:

```json
{
  "billing_request_flows": {
    "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=<brf_id>",
    "lock_customer_details": false,
    "lock_bank_account": false,
    "auto_fulfil": true,
    "created_at": "2021-03-30T16:23:10.679Z",
    "expires_at": "2021-04-06T16:23:10.679Z",
    "redirect_uri": "https://my-company.com/completed",
    "links": {
      "billing_request": "BRQ123"
    }
  }
}
```

### Initialising the Drop-in

You will need to store a reference to the Billing Request and Billing Request Flow ID, often against an internal customer record.

```javascript
// Handler is an instance of the Dropin, with methods
// open, exit, etc.
//
// You must call open() before the Dropin will activate.
//
// You can pass one of either billingRequestFlowID or billingRequestTemplateID.
const handler = GoCardlessDropin.create({
  billingRequestFlowID: "<generated-on-backend>",
  // billingRequestTemplateID: "BRT123",
  environment: "live", // either live or sandbox
  onSuccess: (billingRequest, billingRequestFlow) => {},
  onExit: (error, metadata) => {},
});
```

```React
// Use an existing Billing Request Flow ID likely generated in
// your backend, then configure hooks for Dropin lifecycle
// events.
const config : GoCardlessDropinOptions = ({
    billingRequestFlowID: "<generated-on-backend>",
    environment: "live", // either live or sandbox
    onSuccess: (billingRequest, billingRequestFlow) => {},
    onExit: (error, metadata) => {},
});

// Create state variables via the useGoCardlessDropin hook
// function, to be used inside a React component render
// function.
//
// You must call open() before the Dropin will activate.
const {
    open, exit, ready, error,
} = useGoCardlessDropin(config);
```

When using [Javascript](/billing-requests/taking-an-instant-bank-payment/using-dropin#installation), `GoCardlessDropin.create` returns an `Object` with two functions, [`open`](https://developer.gocardless.com/getting-started/billing-requests/using-dropin/#open) and [`exit`](https://developer.gocardless.com/getting-started/billing-requests/using-dropin/#exit).

With [React](/billing-requests/taking-an-instant-bank-payment/using-dropin#installation), the `useGoCardlessDropin` hook returns an `Object` with four values, [`open`](https://developer.gocardless.com/getting-started/billing-requests/using-dropin/#open), [`exit`](https://developer.gocardless.com/getting-started/billing-requests/using-dropin/#exit), ready and error. `open` and `exit` behave just as above.

The `ready` value will be `true` once the Drop-in has been loaded and the `open` function is ready to be called. You should watch `error` for any issues that occurred that prevented the Drop-in from properly loading.

### Opening and Closing the modal

### open()

Calling `open` will attach the Drop-in iframe to the DOM, and open the modal ready for a customer to complete the flow. Follow the progress of the customer via the `onSuccess` and `onExit` handlers.

```javascript
const handler = GoCardlessDropin.create({
  billingRequestFlowID: "<generated-on-backend>",
  environment: "live", // either live or sandbox
  onSuccess: (billingRequest, billingRequestFlow) => {},
  onExit: (error, metadata) => {},
});

// Create handler as above
const handler = GoCardlessDropin.create({
  /* ... */
});

// Open the Dropin modal, making it visible to the customer
handler.open();
```

```React
const config : GoCardlessDropinOptions = ({
    billingRequestFlowID: "<generated-on-backend>",
    environment: "live", // either live or sandbox
    onSuccess: (billingRequest, billingRequestFlow) => {},
    onExit: (error, metadata) => {},
});

// Create state variables via the useGoCardlessDropin hook
// function, to be used inside a React component render
// You must call open() before the Dropin will activate.
const {
    open, exit, ready, error,
} = useGoCardlessDropin(config);

// Only open the link if the Dropin is ready
if (ready) {
  open();
}
```

### exit()

Calling `exit` will close the Drop-in, removing the modal from the DOM.

If the customer had successfully completed the flow, this will trigger the `onSuccess` callback. Otherwise, the `onExit` callback is triggered with a `null` error.

### Handling Callbacks (onSuccess & onExit)

### onSuccess

`onSuccess` receives the Billing Request that has been worked.

This is called when the flow exits successfully. Depending on how the flow was configured, it may have completed but not fulfilled the Billing Request - check the status of the request before assuming it has been fulfilled.

### onExit

`onExit` is called with two arguments: an `error` `Object` and a `metadata` `Object`.

The `onExit` callback is called when the customer leaves the flow before completion. This can happen when they voluntarily leave the flow, or due to an unexpected error within it.

The `error` object is `null` if no error was encountered, such as when a customer clicks the exit button. Otherwise it is set to the error that caused the flow to fail.

The `metadata` object is populated with contextual information that can help understand the source or cause of the error.

### React Drop-in Example

```React
import React, { useCallback, useState } from "react";
import {
  useGoCardlessDropin,
  GoCardlessDropinOptions,
  GoCardlessDropinOnSuccess,
} from "@gocardless/react-dropin";

// Display a button that opens the Dropin on click, starting a checkout
// flow for the specified Billing Request Flow.
const DropinButton = (options: GoCardlessDropinOptions) => {
  const { open } = useGoCardlessDropin({ ...options });

  return (
    <button type="button" onClick={() => open()}>
      Start Dropin for <code>{options.billingRequestFlowID}</code> in{" "}
      <code>{options.environment}</code>
    </button>
  );
};

// Example checkout flow, where we create a Billing Request Flow ID by talking
// with our backend API.
const App: FunctionComponent = () => {
  const [flowID, setFlowID] = useState<string | null>(null);

  // Build your backend with an API endpoint that:
  //
  //   1. Creates a Billing Request for the resources you wish to create
  //   2. Create a Billing Request Flow against (1)
  //   3. Return the ID from (2)
  //
  // See an example of this at Taking an Instant Bank Payment:
  // https://developer.gocardless.com/getting-started/billing-requests/taking-an-instant-bank-payment/
  React.useEffect(() => {
    async function createFlow() {
      // Expecting a JSON body like:
      // {
      //   "flow_id": "BRF123456"
      // }
      let response = await fetch("/api/flows", {
        method: "POST",
      });
      const { flow_id } = await response.json();
      setFlowID(flow_id);
    }
    createFlow();
  }, []);

  // Only show the button once we have a Billing Request Flow ID
  return flowID === null ? (
    <div className="loader"></div>
  ) : (
    <DropinButton billingRequestFlowID={flowID} environment={"live"} />
  );
};
```

### What’s next?

### Get started
