rate / access-paysuite
API library to interact with Access Paysuite
Requires
- php: ^8.3
- ext-json: *
- nesbot/carbon: ^3.0
- saloonphp/cache-plugin: ^3.0
- saloonphp/saloon: ^4.0
Requires (Dev)
- illuminate/console: ^12.12
- illuminate/database: ^12.12
- illuminate/http: ^12.12
- illuminate/routing: ^12.12
- illuminate/support: ^12.12
- laravel/pint: ^1.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ~11
- swisnl/phpstan-bitbucket: ^0.4.0
- vlucas/phpdotenv: ^5
This package is auto-updated.
Last update: 2026-04-27 22:14:59 UTC
README
A PHP library for the Access Paysuite Direct Debit Management API v3, built on Saloon.
Requirements
- PHP 8.3+
- Laravel 10+ (for the service provider and caching; optional for standalone use)
Installation
composer require rate/access-paysuite
Laravel
The service provider is auto-discovered. Publish the config file:
php artisan vendor:publish --provider="Rate\AccessPaysuite\ServiceProvider\AccessPaysuiteServiceProvider"
Add your credentials to .env:
ACCESS_PAYSUITE_CLIENT_CODE=APICODE ACCESS_PAYSUITE_API_KEY=your-api-key ACCESS_PAYSUITE_CACHE=false # Set to true to use the playpen (sandbox) environment instead of production ACCESS_PAYSUITE_PLAYPEN=false
Publish the webhook-log migration and run it:
php artisan vendor:publish --tag=access-paysuite-migrations php artisan migrate
Point every DDCMS callback at the package's built-in webhook route in one go:
php artisan paysuite:callback:set all
This registers the route named access-paysuite.webhook (default path /paysuite/webhook) as the callback URL for all five entities — customer, contract, payment, bulkpayment, and schedule.
Basic Usage
With Laravel (dependency injection)
use Rate\AccessPaysuite\AccessPaysuiteConnector; use Rate\AccessPaysuite\AccessPaysuiteService; class CustomerController { public function __construct( private readonly AccessPaysuiteConnector $connector, ) {} public function show(string $customerId): Customer { $service = new AccessPaysuiteService($this->connector); return $service->getCustomer($customerId); } }
Without Laravel (standalone)
use Rate\AccessPaysuite\AccessPaysuiteConnector; use Rate\AccessPaysuite\Enums\Environment; use Rate\AccessPaysuite\AccessPaysuiteService; $connector = new AccessPaysuiteConnector( environment: Environment::PRODUCTION, // or Environment::PLAYPEN for testing clientCode: 'APICODE', apiKey: 'your-api-key', ); $connector->disableCaching(); $service = new AccessPaysuiteService($connector);
Environments
The environment is configured via a boolean in config/access-paysuite.php (or the ACCESS_PAYSUITE_PLAYPEN env var). Production is the default.
| Config | Env var | URL |
|---|---|---|
'playpen' => false |
ACCESS_PAYSUITE_PLAYPEN=false |
https://ddcms.accesspaysuite.com/api/v3 |
'playpen' => true |
ACCESS_PAYSUITE_PLAYPEN=true |
https://playpen.accesspaysuite.com/api/v3 |
When constructing the connector directly (without Laravel), pass the environment explicitly:
use Rate\AccessPaysuite\Enums\Environment; Environment::PLAYPEN; // https://playpen.accesspaysuite.com/api/v3 Environment::PRODUCTION; // https://ddcms.accesspaysuite.com/api/v3
Customer Management
use Rate\AccessPaysuite\Enums\CustomerTitle; // Create a customer $response = $service->createCustomer( title: CustomerTitle::MR, customerRef: 'CUST-001', // unique per client surname: 'Smith', postCode: 'SW1A 1AA', accountNumber: '12345678', // exactly 8 digits bankSortCode: '112233', // exactly 6 digits accountHolderName: 'John Smith', line1: '1 Test Street', line2: 'London', firstName: 'John', email: 'john@example.com', ); // Retrieve a customer $customer = $service->getCustomer('customer-uuid'); echo $customer->FirstName; // 'John' echo $customer->BankDetail->AccountNumber; // '12345678' echo $customer->AddressDetail->PostCode; // 'SW1A 1AA' // Search customers $collection = $service->getCustomers( pageSize: 20, pageNumber: 1, includePagingDetail: true, surname: 'Smith', ); echo count($collection->items); // number of results echo $collection->paging?->TotalRecords; // Update a customer (partial update — only supplied fields are changed) $service->updateCustomer('customer-uuid', email: 'new@example.com', firstName: 'Jonathan');
Contract Management
use Carbon\Carbon; use Rate\AccessPaysuite\Enums\AtTheEnd; use Rate\AccessPaysuite\Enums\TerminationType; // Get available schedules first $schedules = $service->getAvailableSchedules(); // Find the earliest valid start date $dates = $service->getPaymentDates()->json(); // Create a contract $response = $service->createContract( customerId: 'customer-uuid', terminationType: TerminationType::UNTIL_FURTHER_NOTICE, atTheEnd: AtTheEnd::EXPIRE, isGiftAid: false, start: Carbon::parse($dates['EarliestFirstPaymentDate']), scheduleName: 'Monthly', amount: 25.00, paymentDayInMonth: 1, ); // List contracts for a customer $contracts = $service->getContracts('customer-uuid'); foreach ($contracts as $contract) { echo $contract->Status->value; // 'Active' echo $contract->Amount; // 25.0 }
Payment Management
// Add an ad-hoc payment (minimum 5 working days in the future) $service->addPayment( contractId: 'contract-uuid', amount: 50.00, date: Carbon::now()->addWeekdays(6), comment: 'Additional contribution', ); // List recent payments $payments = $service->getPayments('contract-uuid', rows: 10); foreach ($payments as $payment) { echo $payment->Status->value; // 'Pending' echo $payment->Date->format('Y-m-d'); } // Update a payment (before BACS submission) $service->updatePayment('contract-uuid', 'payment-uuid', 'Corrected amount', 30.00, Carbon::parse('2025-06-01')); // Delete a payment (before BACS submission) $service->deletePayment('contract-uuid', 'payment-uuid', 'Cancelled by customer');
Bulk Payments
$service->bulkAddPayments([ [ 'contract' => 'contract-uuid-1', 'amount' => 25.00, 'date' => Carbon::now()->addWeekdays(6), 'comment' => 'Monthly collection', ], [ 'contract' => 'contract-uuid-2', 'amount' => 50.00, 'date' => Carbon::now()->addWeekdays(6), ], ]);
Contract Status Changes
$service->cancelContract('contract-uuid'); $service->reactivateContract('contract-uuid'); $service->archiveContract('contract-uuid'); // irreversible use Rate\AccessPaysuite\Enums\AtTheEnd; use Rate\AccessPaysuite\Enums\TerminationType; $service->restartContract( contractId: 'contract-uuid', terminationType: TerminationType::UNTIL_FURTHER_NOTICE, atTheEnd: AtTheEnd::EXPIRE, );
Contract Amendments
// Change the monthly payment day $service->changeMonthlyDate('contract-uuid', monthDay: '15', comment: 'Customer request', patchNextPayment: false); // Change the amount $service->changeContractAmount('contract-uuid', amount: 30.00, comment: 'Price increase');
Patches (Temporary Modifications)
use Carbon\Carbon; $from = Carbon::parse('2025-07-01'); $to = Carbon::parse('2025-09-30'); // Freeze collections for a period $service->addFreezePatch('contract-uuid', $from, $to, comment: 'Customer on holiday'); // Skip collections (contract schedule adjusts) $service->addSkipPatch('contract-uuid', $from, $to, comment: 'Waived for 3 months'); // Change amount for a period $service->addChangeAmountPatch('contract-uuid', $from, $to, amount: 10.00, comment: 'Reduced rate'); // List all patches $patches = $service->getPatches('contract-uuid');
Questions & Answers
use Rate\AccessPaysuite\Enums\QuestionType; // Create a custom question $service->createQuestion( label: 'How did you hear about us?', type: QuestionType::LIST, isMandatory: false, options: 'Website,Social Media,Word of Mouth', ); // Add an answer for a customer $service->addAnswer('customer-uuid', 'question-uuid', 'Website');
Callback URLs
use Rate\AccessPaysuite\Enums\CallbackEntity; // Register a webhook for payment BACS callbacks $service->setCallbackUrl(CallbackEntity::PAYMENT, 'https://your-app.com/webhooks/paysuite'); // Remove a callback $service->deleteCallbackUrl(CallbackEntity::PAYMENT);
Laravel Artisan Commands
When the package is installed in a Laravel application, three Artisan commands are available for managing callback URLs from the terminal.
List all callback URLs
Fetches all five entity callback URLs concurrently and displays them in a table:
php artisan paysuite:callback:list
+-------------+----------------------------------+
| Entity | Callback URL |
+-------------+----------------------------------+
| bulkpayment | https://your-app.com/webhooks/bp |
| customer | — |
| contract | — |
| payment | https://your-app.com/webhooks/py |
| schedule | — |
+-------------+----------------------------------+
Set a callback URL
php artisan paysuite:callback:set {entity} {url}
php artisan paysuite:callback:set payment https://your-app.com/webhooks/payment
Delete a callback URL
php artisan paysuite:callback:delete {entity}
php artisan paysuite:callback:delete payment
Prompts for confirmation before deleting. Pass --no-interaction to skip the prompt (the command will safely no-op when non-interactive).
Valid entity values for all three commands: bulkpayment, customer, contract, payment, schedule.
Using Requests Directly
For fine-grained control, create request objects and send them via the connector:
use Rate\AccessPaysuite\Requests\Customer\GetCustomer; $response = $connector->send(new GetCustomer('customer-uuid')); $customer = $response->dto(); // typed Customer model $raw = $response->json(); // raw array
Direct Debit Process Overview
- Create a Customer with bank details and address.
- Call
GET /paymentdateto find the earliest valid start date. - Create a Contract referencing a schedule (from
GET /schedules). - The start date must be at least the First Payment Delay (default: 10 working days) in the future.
- For ad-hoc payments, the date must be at least the Subsequent Payment Delay (default: 5 working days) ahead.
- Payments are submitted to BACS ~3 working days before their collection date; they cannot be modified after submission.
- Final payment status is available ~3 working days after the collection date.
Running Tests
# Unit tests (with mock responses — no network calls) composer test # Static analysis composer phpstan # Code style check composer check-style # All quality checks composer qa # Live integration tests against the playpen environment ./vendor/bin/phpunit tests/LiveTest.php
Configure live test credentials in tests/.env (copy from tests/.env.example).
Support
For API support: support@accesspaysuite.com
For library issues: raise a ticket in Bitbucket.