istorebox/omnipay-benefitgateway
最新稳定版本:v2.0.0
Composer 安装命令:
composer require istorebox/omnipay-benefitgateway
包简介
Benefit Payment Gateway driver for the Omnipay payment processing library
README 文档
README
A Benefit Payment Gateway driver for the Omnipay PHP payment processing library.
Benefit is the leading payment network in Bahrain, enabling merchants to accept payments in Bahraini Dinar (BHD).
Requirements
| Requirement | Version |
|---|---|
| PHP | ^8.2 |
| ext-openssl | any |
| omnipay/common | ^3.1 |
Installation
composer require istorebox/omnipay-benefitgateway
Configuration
Obtain the following credentials from your Benefit merchant account:
| Parameter | Type | Description |
|---|---|---|
id |
string |
Merchant / Portal ID issued by Benefit |
password |
string |
Gateway password issued by Benefit |
resource_key |
string |
Exactly 32-byte AES-256 encryption key issued by Benefit |
currency |
string |
ISO 4217 alpha code — must be BHD |
langid |
string |
Payment page language: USA (English, default) or ARA (Arabic) |
testMode |
bool |
true → sandbox, false (default) → production |
use Omnipay\Omnipay; $gateway = Omnipay::create('BenefitGateway'); $gateway->setId('YOUR_MERCHANT_ID'); $gateway->setPassword('YOUR_GATEWAY_PASSWORD'); $gateway->setResourceKey('YOUR_EXACTLY_32_BYTE_KEY_HERE!!'); // must be 32 bytes $gateway->setCurrency('BHD'); $gateway->setLangId('USA'); // or 'ARA' for Arabic $gateway->setTestMode(false); // true for sandbox
⚠️ Security: The
resource_keymust be exactly 32 bytes. The driver will throw an\InvalidArgumentExceptionimmediately if the key length is wrong — this prevents silent encryption failures.
Usage
1 — Initiate a Purchase
Redirects the customer to the Benefit-hosted payment page.
$response = $gateway->purchase([ 'amount' => '1.000', // 3 decimal places for BHD 'transactionId' => 'ORDER-' . time(), // your unique order/track ID 'returnUrl' => 'https://yoursite.com/payment/return', 'cancelUrl' => 'https://yoursite.com/payment/cancel', ])->send(); if ($response->isRedirect()) { $response->redirect(); // or: header('Location: ' . $response->getRedirectUrl()); }
Note: The gateway
passwordis included inside the AES-encryptedtrandatablob only. It is never exposed as a plain query string parameter in the redirect URL.
2 — Complete a Purchase (Callback)
Benefit POSTs the encrypted result back to your returnUrl. Handle it:
$response = $gateway->completePurchase()->send(); // trandata is decrypted automatically using your resource_key if ($response->isSuccessful()) { $paymentId = $response->getTransactionReference(); // Benefit payment ID $orderId = $response->getTransactionId(); // your order/track ID $authCode = $response->getAuthCode(); // authorisation code $refId = $response->getReferenceId(); // reference number // Mark order as paid ... } elseif ($response->isCancelled()) { // Customer clicked Cancel on the Benefit page } elseif ($response->isTimedOut()) { // Bank host communication timed out — advise customer to retry } else { $error = $response->getMessage(); // e.g. 'NOT CAPTURED' // Handle failure ... }
Passing Callback Data Manually
Useful in controllers or tests where you want to pass POST data explicitly:
$response = $gateway->completePurchase([ 'request_data' => $request->post(), ])->send();
Response Methods
completePurchase Response
| Method | Returns | Description |
|---|---|---|
isSuccessful() |
bool |
true only when result === 'CAPTURED' |
isCancelled() |
bool |
true when result === 'CANCELED' |
isTimedOut() |
bool |
true when result === 'HOSTIMEOUT' |
getCode() |
string|null |
Raw result from Benefit (CAPTURED, NOT CAPTURED, CANCELED, HOSTIMEOUT) |
getMessage() |
string|null |
Result string or ErrorText on failure |
getTransactionReference() |
string|null |
Benefit-assigned paymentid |
getTransactionId() |
string|null |
Your merchant trackid echoed back |
getAuthCode() |
string|null |
Authorization code (auth) |
getReferenceId() |
string|null |
Reference number (ref) |
How Encryption Works
The Benefit gateway uses AES-256-CBC with a fixed IV (PGKEYENCDECIVSPC) and PKCS#5 padding, as required by the Benefit integration specification.
- Purchase: request parameters (including
idandpassword) are encrypted into a hex string and sent astrandatain the redirect URL. - completePurchase: the
trandataPOST field is URL-decoded, then hex-decoded, then AES-decrypted and parsed back into key-value pairs. - All encryption/decryption is handled by
Omnipay\BenefitGateway\Crypto\AesEncryptor— you never call it directly.
Error Handling
| Exception | Trigger |
|---|---|
InvalidRequestException |
Required parameter missing (id, amount, resource_key, paymentid, etc.) |
InvalidRequestException |
Unsupported or missing currency code |
InvalidRequestException |
AES decryption failure on callback (wraps RuntimeException) |
\InvalidArgumentException |
resource_key is not exactly 32 bytes |
\InvalidArgumentException |
setLangId() called with value other than USA or ARA |
\InvalidArgumentException |
Unknown currency passed to CurrencyCodeResolver |
\RuntimeException |
OpenSSL failure, invalid hex, or corrupted cipher data |
Testing
composer install
composer test
Enable sandbox mode to route requests to the Benefit test environment:
https://www.test.benefit-gateway.bh/payment/PaymentHTTP.htm
Supported Currencies
The driver includes a full ISO 4217 currency map used internally for numeric code resolution. Pass BHD for all live Bahrain transactions.
You can also use CurrencyCodeResolver directly:
use Omnipay\BenefitGateway\Currency\CurrencyCodeResolver; CurrencyCodeResolver::numericCode('BHD'); // '048' CurrencyCodeResolver::getName('BHD'); // 'Bahraini Dinar' CurrencyCodeResolver::isSupported('XYZ'); // false
Changelog
v2.1.0
- Security: Validate AES key is exactly 32 bytes before any encrypt/decrypt operation
- Security: Strip
passwordfrom plaintext redirect URL — password only travels inside AES-encryptedtrandata - Security: URL-decode
trandatabeforehex2binto handle Benefit POST encoding correctly - Security: Guard
base64_decodeandhex2binfalse returns with explicitRuntimeException - Robustness: Add
resource_keyvalidation inCompletePurchaseRequest - Robustness: Wrap decryption
RuntimeExceptionasInvalidRequestExceptionwith context - Robustness: Add empty-string guard in
pkcs5Unpadafter successful decrypt - Feature:
langidis now configurable (USA/ARA) viasetLangId()on Gateway and PurchaseRequest - Feature: Add
isCancelled()andisTimedOut()toCompletePurchaseResponse - Feature: Add
CurrencyCodeResolver::getName()and::all()methods - DX: Add
suggestsection tocomposer.json - Tests: Add
AesEncryptorTest— 9 test cases covering round-trip, key length, encoding, errors - Tests: Add
CurrencyCodeResolverTest— 12 test cases covering codes, names, case-insensitivity, duplicates - Tests: Expand
GatewayTest— addisCancelled,isTimedOut, password-not-in-URL,resource_keymissing tests - CI: Add GitHub Actions workflow for PHP 8.2 and 8.3 matrix
v2.0.0
- Require PHP
^8.2, drop PHP 7.x - Strict types and full return-type declarations
- Replace global helpers with
Crypto\AesEncryptorandCurrency\CurrencyCodeResolver - Fix duplicate currency keys in ISO 4217 map
- Add
getAuthCode(),getReferenceId(),getCode()to response - Fluent setter interface
- PHPUnit v11 config
- MIT LICENSE
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-09