<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
blinkpay-nz / blink-debit-api-client-php example snippets
linkPay\BlinkDebit\BlinkDebitApiException;
use BlinkPay\BlinkDebit\BlinkDebitClient;
use BlinkPay\BlinkDebit\Pcr;
use BlinkPay\BlinkDebit\Uuid;
// Reads BLINKPAY_CLIENT_ID, BLINKPAY_CLIENT_SECRET, BLINKPAY_SANDBOX and BLINKPAY_TIMEOUT.
// An unset or blank BLINKPAY_SANDBOX means sandbox; production must be opted into with "false".
$client = BlinkDebitClient::fromEnvironment();
$idempotencyKey = Uuid::v4(); // persist this against the order so a retry reuses it
try {
$response = $client->createGatewayQuickPayment(
'0.01', // NZD total as a decimal string
'https://www.blinkpay.co.nz/sample-merchant-return-page', // must be whitelisted for your merchant
Pcr::build('particulars', 'code', 'reference'), // what the customer sees on their statement
$idempotencyKey
);
$redirectUri = $response['redirect_uri']; // Redirect the consumer to this URL
$quickPaymentId = $response['quick_payment_id'];
// From a queue job or CLI script, wait for the money to move (see Polling and Settlement Behaviour).
$quickPayment = $client->awaitSuccessfulQuickPayment($quickPaymentId, 300);
} catch (BlinkDebitApiException $e) {
error_log('BlinkPay error: ' . $e->getMessage()); // safe to log: never contains credentials
}
use BlinkPay\BlinkDebit\BlinkDebitClient;
// From the environment variables above:
$client = BlinkDebitClient::fromEnvironment($tokenCache = null, $transport = null);
// Or explicitly:
$client = new BlinkDebitClient(
$clientId,
$clientSecret,
$sandbox = true,
$tokenCache = null, // TokenCacheInterface; default ApcuTokenCache when available, else InMemoryTokenCache
$transport = null // HttpTransportInterface; default CurlTransport
);
$client->setRequestTimeout(30);
use BlinkPay\BlinkDebit\BlinkDebitClient;
class CheckoutController extends Controller
{
public function __construct(private BlinkDebitClient $blink)
{
}
}
// config/app_local.php
'BlinkPay' => [
'clientId' => env('BLINKPAY_CLIENT_ID', ''),
'clientSecret' => env('BLINKPAY_CLIENT_SECRET', ''),
'sandbox' => env('BLINKPAY_SANDBOX'), // parsed by the plugin; unset or blank means sandbox
// 'cacheConfig' => 'default', // prefer a Redis, Memcached or APCu engine over FileEngine
// 'timeout' => 30,
],
// src/Application.php, in bootstrap()
$this->addPlugin(\BlinkPay\BlinkDebit\CakePHP\BlinkDebitPlugin::class);
use BlinkPay\BlinkDebit\RequestOptions;
$options = RequestOptions::create()
->withRequestId($uuid) // overrides the interaction ID Blink Debit would generate
->withCorrelationId($uuid) // your own UUID for log correlation
->withCustomerIp($request->ip()) // when the customer is logged in with you
->withCustomerUserAgent($request->userAgent());
$client->getQuickPayment($quickPaymentId, $options);
use BlinkPay\BlinkDebit\BlinkDebitApiException;
use BlinkPay\BlinkDebit\Exception\ConflictException;
use BlinkPay\BlinkDebit\Exception\RateLimitExceededException;
try {
$payment = $client->createSingleConsentPayment($consentId, $idempotencyKey);
} catch (ConflictException $e) {
$e->getErrorCode(); // e.g. "BP712": read the consent's payments before retrying
} catch (RateLimitExceededException $e) {
// already retried three times; back off and retry later with the same idempotency key
} catch (BlinkDebitApiException $e) {
$e->getStatusCode(); // HTTP status, or 0 for transport and local validation failures
$e->getResponseBody(); // decoded error body, when one was returned
$e->getErrorCode(); // the BPxxx code from that body, or null
$e->getMessage(); // safe to log: never contains credentials, tokens or request bodies
}
use BlinkPay\BlinkDebit\Enum\ConsentStatus;
use BlinkPay\BlinkDebit\Enum\PaymentStatus;
$response = $client->createGatewayQuickPayment(
'0.01',
'https://www.blinkpay.co.nz/sample-merchant-return-page',
Pcr::build('particulars', 'code', 'reference'),
$idempotencyKey,
hash('sha256', $customerId) // optional; omit when no per-customer value exists
);
$redirectUri = $response['redirect_uri']; // Redirect the consumer to this URL
$quickPaymentId = $response['quick_payment_id'];
// After the consumer returns: confirm server-side, never from query parameters.
$quickPayment = $client->getQuickPayment($quickPaymentId);
$consentStatus = $quickPayment['consent']['status']; // ConsentStatus::CONSUMED, ::REJECTED, ...
$paymentStatus = $quickPayment['consent']['payments'][0]['status'] ?? null; // PaymentStatus::* once a payment exists
// Or, from a background job, block until settled (throws on rejection or timeout):
$quickPayment = $client->awaitSuccessfulQuickPayment($quickPaymentId, 300);
$consent = $client->createGatewaySingleConsent(
'0.01',
'https://www.blinkpay.co.nz/sample-merchant-return-page',
Pcr::build('particulars'),
$idempotencyKey
);
$redirectUri = $consent['redirect_uri']; // Redirect the consumer to this URL
// After the consumer returns, from a job: wait for authorisation, debit, wait for settlement.
$client->awaitAuthorisedSingleConsent($consent['consent_id'], 300);
$payment = $client->createSingleConsentPayment($consent['consent_id'], $paymentIdempotencyKey);
$settled = $client->awaitSuccessfulPayment($payment['payment_id'], 300);
use BlinkPay\BlinkDebit\Enum\PaymentStatus;
$payment = $client->getPayment($paymentId);
if ($payment['status'] === PaymentStatus::ACCEPTED_SETTLEMENT_COMPLETED) { /* fulfil */ }
use BlinkPay\BlinkDebit\Enum\Bank;
use BlinkPay\BlinkDebit\Enum\IdentifierType;
use BlinkPay\BlinkDebit\Enum\Period;
use BlinkPay\BlinkDebit\Enum\RetryStrategy;
use BlinkPay\BlinkDebit\Pcr;
use BlinkPay\BlinkDebit\Request\EnduringConsentRequest;
use BlinkPay\BlinkDebit\Request\FixedRecurringPaymentRequest;
use BlinkPay\BlinkDebit\Request\Flow;
use BlinkPay\BlinkDebit\Request\QuickPaymentRequest;
use BlinkPay\BlinkDebit\Request\SingleConsentRequest;
$subscription = $client->createSubscription('https://shop.example/blinkpay/webhook', [
BlinkDebitClient::EVENT_FIXED_RECURRING_PAYMENT_COMPLETED,
BlinkDebitClient::EVENT_FIXED_RECURRING_PAYMENT_FAILED,
BlinkDebitClient::EVENT_FIXED_RECURRING_PAYMENT_CANCELLED,
]);
$secret = $subscription['secret']; // whsec_…, shown only now
$subscriptions = $client->getSubscriptions();
$client->deleteSubscription($subscriptionId);
use BlinkPay\BlinkDebit\WebhookSignature;
$rawBody = file_get_contents('php://input');
if (!WebhookSignature::verify($rawBody, $_SERVER['HTTP_X_SIGNATURE'] ?? '', $secret)) {
http_response_code(400); // 4xx is final: BlinkPay will not retry a delivery you reject
exit;
}
$event = json_decode($rawBody, true);
// event_type, event_id, timestamp, frp_id, consent_id, and payment_id when one exists
use BlinkPay\BlinkDebit\Psr\Psr18Transport;
// Guzzle 7: the client is PSR-18, HttpFactory implements both PSR-17 factories.
$factory = new GuzzleHttp\Psr7\HttpFactory();
$transport = new Psr18Transport(new GuzzleHttp\Client(['timeout' => 30]), $factory, $factory);
// Symfony HttpClient: Psr18Client implements all three interfaces itself.
$psr18 = new Symfony\Component\HttpClient\Psr18Client();
$transport = new Psr18Transport($psr18, $psr18, $psr18);
$client = new BlinkDebitClient($clientId, $clientSecret, true, $tokenCache, $transport);
use BlinkPay\BlinkDebit\Psr\Psr16TokenCache;
use BlinkPay\BlinkDebit\Psr\Psr6TokenCache;
$tokenCache = new Psr16TokenCache($anyPsr16Cache); // e.g. Cache::store() in Laravel
$tokenCache = new Psr6TokenCache($anyPsr6CachePool); // e.g. cache.app in Symfony