Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
f4b938e
Changes generated by 3be91a644360483e5342390b8a3021593cd65d66
gocardless-ci-robot[bot] Mar 23, 2026
409dea8
Changes generated by 8b11b29c01bad5a3e25ac50c5641547d4c0311ed
gocardless-ci-robot[bot] May 1, 2026
304a583
Changes generated by b173d4bd48fb87ad99068b740e8e83e52fdca485
gocardless-ci-robot[bot] May 8, 2026
76d9bbe
Changes generated by 2ef8e5130f5a0bcedd89b298dc2f742fd6417b41
gocardless-ci-robot[bot] May 8, 2026
b618b27
Changes generated by fe5b9706d5cd471e209b7dbeb90ac9927ef6da5d
gocardless-ci-robot[bot] May 13, 2026
ac0a23d
Changes generated by 3f78777e56609f4ccdddafe8228375716322d807
gocardless-ci-robot[bot] May 14, 2026
63e4d4c
Changes generated by 6ca63e56bfca4f8ea6d5563c1df8ddc59404db3c
gocardless-ci-robot[bot] May 14, 2026
a3adb68
Changes generated by 072c0250a5cabd3578679c838c7bf8d678094c03
gocardless-ci-robot[bot] May 20, 2026
92ae34c
Changes generated by bf5abdca6f98fa1650947e8c026d66fe23221d21
gocardless-ci-robot[bot] May 21, 2026
c2013f3
Changes generated by 910ac344ba159c3062fd091a93180b6d691acee4
gocardless-ci-robot[bot] May 27, 2026
a0e334b
Changes generated by 9e9326f7ec745661267a9c9df5d244f1e5e5097c
gocardless-ci-robot[bot] Jun 9, 2026
6a4497d
Changes generated by 1258658d08ecd803fec49d89f44c8c3d1b6c43e8
gocardless-ci-robot[bot] Jun 9, 2026
666fd9d
Changes generated by c1a246cf193597d4a75b4787fe464fa9d5cbf101
gocardless-ci-robot[bot] Jun 16, 2026
fd8d432
Changes generated by d97c5f53b394eaa852733dc030b77590b491794c
gocardless-ci-robot[bot] Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# GoCardless Pro PHP client library
# GoCardless PHP client library

A PHP client for interacting with the GoCardless Pro API.
A PHP client for interacting with the GoCardless API.

[![PHP version](https://badge.fury.io/ph/gocardless%2Fgocardless-pro.svg)](https://badge.fury.io/ph/gocardless%2Fgocardless-pro)
[![CircleCI](https://circleci.com/gh/gocardless/gocardless-pro-php.svg?style=shield)](https://circleci.com/gh/gocardless/gocardless-pro-php)
Expand Down Expand Up @@ -236,6 +236,18 @@ try {
}
```

#### Accessing the webhook ID

If you need to access the webhook ID for debugging purposes, you can use `Webhook::parseWithMeta` instead:

```php
$result = GoCardlessPro\Webhook::parseWithMeta($request_body, $signature_header, $webhook_endpoint_secret);
$events = $result->getEvents();
$webhookId = $result->getWebhookId(); // e.g. "WB123" - useful for debugging
```

Note: The webhook ID is intended for debugging and logging purposes only. It should not be used for deduplication - instead, use the event IDs to deduplicate, as each event has a unique ID that remains consistent if the same event is sent multiple times.

For more details on working with webhooks, see our ["Getting started" guide](https://developer.gocardless.com/getting-started/api/introduction/?lang=php).

## Supporting PHP >= 8.1
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "gocardless/gocardless-pro",
"description": "GoCardless PHP Client Library",
"version": "7.2.0",
"version": "7.3.0",
"keywords": [
"gocardless",
"direct debit",
Expand Down
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 32 additions & 4 deletions lib/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Client
*/
public function __construct($config)
{
$this->validate_config($config);
$this->validateConfig($config);

$access_token = $config['access_token'];

Expand Down Expand Up @@ -56,7 +56,7 @@ public function __construct($config)
'Content-Type' => 'application/json',
'Authorization' => "Bearer " . $access_token,
'GoCardless-Client-Library' => 'gocardless-pro-php',
'GoCardless-Client-Version' => '7.2.0',
'GoCardless-Client-Version' => '7.3.0',
'User-Agent' => $this->getUserAgent()
),
'http_errors' => false,
Expand Down Expand Up @@ -125,6 +125,10 @@ public function __construct($config)

$this->services['outbound_payments'] = new Services\OutboundPaymentsService($this->api_client);

$this->services['outbound_payment_imports'] = new Services\OutboundPaymentImportsService($this->api_client);

$this->services['outbound_payment_import_entries'] = new Services\OutboundPaymentImportEntriesService($this->api_client);

$this->services['payer_authorisations'] = new Services\PayerAuthorisationsService($this->api_client);

$this->services['payer_themes'] = new Services\PayerThemesService($this->api_client);
Expand Down Expand Up @@ -495,6 +499,30 @@ public function outboundPayments()
return $this->services['outbound_payments'];
}

/**
* Service for interacting with outbound payment imports
* @return Services\OutboundPaymentImportsService
*/
public function outboundPaymentImports()
{
if (!isset($this->services['outbound_payment_imports'])) {
throw new \Exception('Key outbound_payment_imports does not exist in services array');
}
return $this->services['outbound_payment_imports'];
}

/**
* Service for interacting with outbound payment import entries
* @return Services\OutboundPaymentImportEntriesService
*/
public function outboundPaymentImportEntries()
{
if (!isset($this->services['outbound_payment_import_entries'])) {
throw new \Exception('Key outbound_payment_import_entries does not exist in services array');
}
return $this->services['outbound_payment_import_entries'];
}

/**
* Service for interacting with payer authorisations
* @return Services\PayerAuthorisationsService
Expand Down Expand Up @@ -706,7 +734,7 @@ private function getUrlForEnvironment($environment)
*
* @param array[string]mixed $config the client configuration options
*/
private function validate_config(&$config)
private function validateConfig(&$config)
{
$required_option_keys = array('access_token', 'environment');

Expand Down Expand Up @@ -736,7 +764,7 @@ private function getUserAgent()
{
$curlinfo = curl_version();
$uagent = array();
$uagent[] = 'gocardless-pro-php/7.2.0';
$uagent[] = 'gocardless-pro-php/7.3.0';
$uagent[] = 'schema-version/2015-07-06';
if (defined('\GuzzleHttp\Client::MAJOR_VERSION')) {
$uagent[] = 'GuzzleHttp/' . \GuzzleHttp\Client::MAJOR_VERSION;
Expand Down
4 changes: 2 additions & 2 deletions lib/Core/ApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,14 @@ private function handleErrors(Response $response)
return null;
}

$status_code = $response->getStatusCode();
$json = json_decode($response->getBody());

if ($json === null) {
$msg = "Malformed response received from server";
throw new Exception\MalformedResponseException($msg, $response);
throw new Exception\MalformedResponseException($msg, $response, $status_code);
}

$status_code = $response->getStatusCode();
if ($status_code < 400) {
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Core/Exception/ApiConnectionException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

class ApiConnectionException extends GoCardlessProException
{
};
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/AuthenticationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

class AuthenticationException extends InvalidApiUsageException
{
};
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/GoCardlessInternalException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

class GoCardlessInternalException extends ApiException
{
};
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/GoCardlessProException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

class GoCardlessProException extends \Exception
{
};
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/InvalidApiUsageException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

class InvalidApiUsageException extends ApiException
{
};
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/InvalidSignatureException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

class InvalidSignatureException extends GoCardlessProException
{
};
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/InvalidStateException.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ private function getIdempotentCreationConflictError()
}
}
}
};
}
36 changes: 33 additions & 3 deletions lib/Core/Exception/MalformedResponseException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,47 @@

class MalformedResponseException extends GoCardlessProException
{
const BODY_PREVIEW_MAX_LENGTH = 500;

private $response;
private $statusCode;

public function __construct($message, $response)
public function __construct($message, $response, $statusCode = null)
{
$this->response = $response;
parent::__construct($message);
$this->statusCode = $statusCode;
parent::__construct(self::buildMessage($message, $response, $statusCode));
}


public function response()
{
return $this->response;
}
};

public function statusCode()
{
return $this->statusCode;
}

private static function buildMessage($message, $response, $statusCode)
{
$full = $message;
if ($statusCode !== null) {
$full .= ' (HTTP ' . $statusCode . ')';
}
$body = null;
if (is_string($response)) {
$body = $response;
} elseif (is_object($response) && method_exists($response, 'getBody')) {
$body = (string) $response->getBody();
}
if ($body !== null && $body !== '') {
if (strlen($body) > self::BODY_PREVIEW_MAX_LENGTH) {
$body = substr($body, 0, self::BODY_PREVIEW_MAX_LENGTH) . '...';
}
$full .= ': ' . $body;
}
return $full;
}
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/PermissionsException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

class PermissionsException extends InvalidApiUsageException
{
};
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/RateLimitException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

class RateLimitException extends InvalidApiUsageException
{
};
}
2 changes: 1 addition & 1 deletion lib/Core/Exception/ValidationFailedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ protected function extractErrorMessage($error)
return $error->message;
}
}
};
}
16 changes: 8 additions & 8 deletions lib/Core/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Paginator implements \Iterator
/**
* Default max records to retrieve per page
*/
const HARD_RECORD_LIMIT = 500;
public const HARD_RECORD_LIMIT = 500;

/**
* @var \GoCardlessPro\Services\BaseService The resource service to fetch records with
Expand Down Expand Up @@ -63,7 +63,7 @@ public function rewind()
{
$this->current_position = 0;
$this->current_page_position = 0;
$this->current_response = $this->initial_response();
$this->current_response = $this->initialResponse();
}

/**
Expand All @@ -74,7 +74,7 @@ public function rewind()
#[\ReturnTypeWillChange]
public function current()
{
return $this->current_records()[$this->key()];
return $this->currentRecords()[$this->key()];
}

/**
Expand All @@ -98,7 +98,7 @@ public function next()
++$this->current_position;

if (!$this->valid()) {
$this->current_response = $this->next_response();
$this->current_response = $this->nextResponse();
$this->current_page_position = $this->current_position;
}
}
Expand All @@ -112,15 +112,15 @@ public function next()
public function valid()
{
return !is_null($this->current_response) &&
array_key_exists($this->key(), $this->current_records());
array_key_exists($this->key(), $this->currentRecords());
}

/**
* Fetch the first page of results
*
* @return ListResponse
*/
private function initial_response()
private function initialResponse()
{
$options = $this->options;
$options['params']['after'] = null;
Expand All @@ -132,7 +132,7 @@ private function initial_response()
*
* @return ListResponse
*/
private function next_response()
private function nextResponse()
{
$options = $this->options;
$options['params']['after'] = $this->current_response->after;
Expand All @@ -148,7 +148,7 @@ private function next_response()
*
* @return \GoCardlessPro\Resources\BaseResource[]
*/
private function current_records()
private function currentRecords()
{
return $this->current_response->records;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Resources/Balance.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Balance extends BaseResource
protected $balance_type;

/**
* [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency
* [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency
* code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD"
* are supported.
*/
Expand Down
30 changes: 3 additions & 27 deletions lib/Resources/BillingRequestTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class BillingRequestTemplate extends BaseResource
protected $mandate_request_constraints;

/**
* [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency
* [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency
* code.
*/
protected $mandate_request_currency;
Expand Down Expand Up @@ -88,31 +88,7 @@ class BillingRequestTemplate extends BaseResource
protected $mandate_request_scheme;

/**
* Verification preference for the mandate. One of:
* <ul>
* <li>`minimum`: only verify if absolutely required, such as when part of
* scheme rules</li>
* <li>`recommended`: in addition to `minimum`, use the GoCardless payment
* intelligence solution to decide if a payer should be verified</li>
* <li>`when_available`: if verification mechanisms are available, use
* them</li>
* <li>`always`: as `when_available`, but fail to create the Billing
* Request if a mechanism isn't available</li>
* </ul>
*
* By default, all Billing Requests use the `recommended` verification
* preference. It uses GoCardless payment intelligence solution to determine
* if a payer is fraudulent or not. The verification mechanism is based on
* the response and the payer may be asked to verify themselves. If the
* feature is not available, `recommended` behaves like `minimum`.
*
* If you never wish to take advantage of our reduced risk products and
* Verified Mandates as they are released in new schemes, please use the
* `minimum` verification preference.
*
* See [Billing Requests: Creating Verified
* Mandates](https://developer.gocardless.com/getting-started/billing-requests/verified-mandates/)
* for more information.
* Verification preference for the mandate.
*/
protected $mandate_request_verify;

Expand All @@ -134,7 +110,7 @@ class BillingRequestTemplate extends BaseResource
protected $payment_request_amount;

/**
* [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency
* [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency
* code. `GBP` and `EUR` supported; `GBP` with your customers in the UK and
* for `EUR` with your customers in supported Eurozone countries only.
*/
Expand Down
Loading
Loading