jeddsaliba/laravel-apcopay

Laravel integration for ApcoPay payment gateway (hosted page and payment status)

Maintainers

Package info

github.com/jeddsaliba/laravel-apcopay

pkg:composer/jeddsaliba/laravel-apcopay

Transparency log

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

3.0.0 2026-07-31 07:43 UTC

This package is auto-updated.

Last update: 2026-07-31 07:52:34 UTC


README

Laravel integration for the ApcoPay payment gateway: hosted payment page and payment status (GetPayment / PreparePayment).

Requirements

  • PHP 8.2+
  • Laravel 10.x, 11.x or 12.x
  • GuzzleHTTP 7.x

Installation

composer require jeddsaliba/laravel-apcopay

Publish the config file (optional; defaults are used from the package):

php artisan vendor:publish --tag=apcopay-config

Configuration

Add to your .env:

APCO_PAY_ENV=local
APCO_PAY_USERNAME=
APCO_PAY_PASSWORD=
APCO_PAY_PID=
APCOPAY_BASE_URL=https://www.apsp.biz/GPG/RESTAPI/api/OnlinePayments
APCOPAY_SANDBOX_BASE_URL=https://www.apsp.biz/GPGTest/RESTAPI/api/OnlinePayments

APCO_PAY_ENV accepts (case-insensitively) production, prod, or live for the live gateway, and local, sandbox, staging, or testing for the sandbox gateway. Any other value throws a RuntimeException at resolution time rather than silently falling back to the sandbox — this is deliberate, since a typo here would otherwise route real transactions to the wrong endpoint without any warning.

username, password, and pid are required. If any are left blank, resolving the service throws a RuntimeException naming the missing config key(s) instead of failing later with an opaque authentication error from ApcoPay.

After publishing the config, you can optionally customize http (e.g. timeout, connect_timeout) for the Guzzle client. Avoid setting verify => false in production — this disables TLS certificate verification for requests that carry your ApcoPay credentials in plaintext.

Retry / backoff configuration

getPaymentWithRetry() blocks synchronously between attempts using an exponential backoff (base_delay_seconds * backoff_multiplier ^ attempt, capped at max_delay_seconds). Configure it via .env or config/apcopay.php:

APCO_PAY_RETRY_BASE_DELAY=1
APCO_PAY_RETRY_MAX_DELAY=10
APCO_PAY_RETRY_BACKOFF_MULTIPLIER=2.0

Because the delay is a real, blocking sleep(), avoid calling getPaymentWithRetry() directly inside a web request with a large retry count — prefer dispatching a queued job that polls instead, so you don't tie up an application worker or risk a load-balancer timeout.

Usage

Inject Jeddsaliba\ApcoPay\Contracts\ApcoPayServiceInterface:

use Jeddsaliba\ApcoPay\Contracts\ApcoPayServiceInterface;
use Jeddsaliba\ApcoPay\Enums\PaymentStateFields;

// Get hosted page URL for redirect
$response = $apcoPay->getHostedPage(
    sessionReference: $sessionReference,
    amount: $amount,
    returnUrl: $returnUrl
);
$paymentUrl = $response['paymentURLField'];

// Get payment status
$payment = $apcoPay->getPayment($sessionReference);

// Get payment with retries (e.g. while processing)
$payment = $apcoPay->getPaymentWithRetry($sessionReference, 3);

// Check state
PaymentStateFields::PENDING->value;   // 1
PaymentStateFields::CANCELLED->value; // 2
PaymentStateFields::SUCCESS->value;   // 3
PaymentStateFields::FAILED->value;    // 4

Exceptions: the service throws Jeddsaliba\ApcoPay\Exceptions\ApcoPayException when the HTTP request to ApcoPay fails, when ApcoPay returns a response that isn't valid JSON, and when getPaymentWithRetry() exhausts all retry attempts. It throws \InvalidArgumentException for invalid input (a non-positive $amount, or $retries < 1).

Each request sent to ApcoPay includes a freshly generated MessageId (a UUID) so that retried or duplicated requests can be deduplicated/reconciled on ApcoPay's side.

Note: this package only wraps ApcoPay's synchronous PreparePayment/GetPayment calls. It does not implement or verify any asynchronous payment notification/webhook ApcoPay may send; if your integration relies on that, you'll need to build and secure that endpoint yourself (verify the request against ApcoPay's documented signing/authentication mechanism before trusting it).

Using the Facade

When the package is installed in a Laravel app, you can use the ApcoPay facade:

use Jeddsaliba\ApcoPay\Facades\ApcoPay;

$response = ApcoPay::getHostedPage($sessionReference, $amount, $returnUrl);
$payment = ApcoPay::getPayment($sessionReference);
$payment = ApcoPay::getPaymentWithRetry($sessionReference, 3); // with retries

Testing

composer test

Or with PHPUnit directly:

./vendor/bin/phpunit

License

The MIT License (MIT). Please see the License File for more information.