Skip to content

Popular searches

Accept payments with the PHP SDK

Updated

The Bayarcash PHP SDK lets your PHP site create payments, verify callbacks and look up transactions without writing the HTTP calls yourself. This guide uses API v3, the current version. The SDK’s README on GitHub has every method.

On Laravel, use the Laravel package instead: it wraps this SDK and adds routes and configuration. See Choose a Bayarcash SDK.

You need:

  • PHP 7.4 or newer with the json extension, and Composer.
  • Your Personal Access Token (PAT), API Secret Key and a portal key from the merchant dashboard. Use sandbox keys while you build.

Run this in your project folder:

Terminal window
composer require bayarcash/php-sdk

The package used to be called webimpian/bayarcash-php-sdk. Old installations still work, but use bayarcash/php-sdk for anything new.

Create one client with your token, then switch it to API v3. The SDK starts on v2, which is deprecated.

use Bayarcash\Bayarcash;
$bayarcash = new Bayarcash(getenv('BAYARCASH_PAT'));
$bayarcash->setApiVersion('v3');
$bayarcash->useSandbox(); // remove this line in production
$apiSecretKey = getenv('BAYARCASH_API_SECRET_KEY');

Call setApiVersion() and useSandbox() before you make any request.

To take a payment, build the request, sign it, and send your customer to the payment page:

  1. Build the request with your portal key, order details and URLs.
  2. Add a checksum signed with your API Secret Key.
  3. Create the payment intent and redirect the customer to its url.
$data = [
'portal_key' => 'your_portal_key',
'payment_channel' => Bayarcash::FPX,
'order_number' => 'INV-1001',
'amount' => '10.00',
'payer_name' => 'Ahmad bin Abdullah',
'payer_email' => 'ahmad@example.com',
'payer_telephone_number' => '0123456789',
'return_url' => 'https://your-site.com/payment/return',
'callback_url' => 'https://your-site.com/payment/callback',
];
$data['checksum'] = $bayarcash->createPaymentIntentChecksumValue($apiSecretKey, $data);
$paymentIntent = $bayarcash->createPaymentIntent($data);
header('Location: ' . $paymentIntent->url);
exit;

The main request fields are:

Field Required Notes
portal_key Yes The portal that receives the payment.
order_number Yes Your reference, up to 30 characters.
amount Yes A string with up to 2 decimals, such as '10.00'.
payer_name, payer_email Yes The customer’s name and email.
payment_channel No One Bayarcash::* constant or an array of them. Leave it out to let the customer choose.
payer_telephone_number No Needed for e-wallet and DuitNow channels.
callback_url, return_url No Where Bayarcash notifies your server, and where it sends the customer back.

The checksum is built from payment_channel, order_number, amount, payer_name and payer_email, so add it after those fields are final. To retry a timed-out request safely, pass a UUID as a second argument: createPaymentIntent($data, $idempotencyKey).

Bayarcash posts the result to your callback_url when the payment reaches a final state. Verify it before you update the order:

use Bayarcash\Fpx;
$callbackData = $_POST;
if (! $bayarcash->verifyTransactionCallbackData($callbackData, $apiSecretKey)) {
http_response_code(403);
exit;
}
if ((int) $callbackData['status'] === Fpx::STATUS_SUCCESS) {
// Mark the order with $callbackData['order_number'] as paid.
}
http_response_code(200);

Use verifyReturnUrlCallbackData() on your return_url page. On v3 the customer comes back with the fields in the query string, so pass $_GET. Show the result to the customer, but update the order from the callback only. See Verify callbacks and checksums for why.

These calls read what Bayarcash has recorded:

$intent = $bayarcash->getPaymentIntent('payment_intent_id');
$transaction = $bayarcash->getTransaction('transaction_id');
$byOrder = $bayarcash->getTransactionByOrderNumber('INV-1001');
$result = $bayarcash->getAllTransactions([
'status' => '3',
'payment_channel' => Bayarcash::FPX,
]);
// $result['data'] holds the transactions, $result['meta'] the pagination.

To cancel a payment intent the customer has not paid, call $bayarcash->cancelPaymentIntent('payment_intent_id').

Failed calls throw exceptions from Bayarcash\Exceptions:

Exception HTTP status What to do
ValidationException 422 Fix the request. $e->errors() lists the fields.
FailedActionException 400 Read $e->getMessage() for the reason.
NotFoundException 404 Check the ID you asked for.
RateLimitExceededException 429 Wait. $e->rateLimitResetsAt has the reset time.
  • Test the whole flow in the sandbox first. Create a payment, pay it, and check that your callback marks the order paid before you switch to production keys.
  • Keep the token and API Secret Key out of your code. Load them from environment variables or your framework’s secret store, as in the examples above.
  • Use the channel constants instead of numbers. Bayarcash::FPX reads better than 1, and the README lists every channel constant.

Common issues

After updating the SDK I get: Class "Webimpian\BayarcashSdk\Bayarcash" not found. What changed?

Version 3 of the SDK renamed its namespace to Bayarcash. Change your imports to use Bayarcash\Bayarcash; (and Bayarcash\Fpx, Bayarcash\FpxDirectDebit). New projects should also install bayarcash/php-sdk instead of the old webimpian/bayarcash-php-sdk package.

I get "The getTransactionByOrderNumber method is only available for API version v3." Why?

The SDK starts on API v2. Call $bayarcash->setApiVersion('v3') right after you create the client, before any request.

createPaymentIntent throws a ValidationException. How do I see what is wrong?

Call $e->errors() on the exception. It lists each field the API rejected, for example an amount outside the allowed range or an order number longer than 30 characters.

Was this article helpful?

Cookie settings

We use Google Analytics to see which guides help and where readers get stuck. It is on by default, and you can turn it off. This device keeps your choice.