Skip to content

Configuration ​

Each gateway has a config class (KbzPayConfig, WaveMoneyConfig, AyaPayConfig, YomaMmqrConfig, CyberSourceConfig) that takes named arguments. Gateways take the config object or an array of its snake_case keys. Every setting is required except the URL overrides and Yoma's webhook secret: there are no defaults, and a missing or blank setting throws a ConfigurationException naming it:

php
use Laranex\PhpMyanmarPayments\Exceptions\ConfigurationException;
use Laranex\PhpMyanmarPayments\KbzPay\KbzPay;
use Laranex\PhpMyanmarPayments\KbzPay\KbzPayConfig;

try {
    $config = new KbzPayConfig(
        appId: '...',
        appKey: '',
        merchantCode: '...',
        timeoutSeconds: 30,
    );
} catch (ConfigurationException $e) {
    // e.g. kbz_pay "app_key"
    error_log("missing {$e->gateway} setting \"{$e->key}\"");
    throw $e;
}

$kbz = new KbzPay($config);

$e->getMessage() reads The kbz_pay configuration is missing [app_key].

The time settings (timeoutSeconds, and Wave Money's timeToLiveSeconds) must be whole numbers greater than 0. Any other value throws the same exception with the message The kbz_pay configuration [timeout_in_seconds] must be a whole number greater than 0.

Endpoints ​

Every gateway uses its production endpoints. There is no switch between test and production: to test against a gateway's UAT environment, or to go through a proxy, set the URL overrides (see Testing Against UAT). A blank override means unset. Each config object exposes the URL actually used as a read-only property ($config->apiUrl, $config->baseUrl, …).

Config Options ​

KbzPayConfig ​

ParameterTypeRequiredDescription
appIdstringYesappid issued by KBZ
appKeystringYesSecret key used to sign requests
merchantCodestringYesmerch_code issued by KBZ
timeoutSecondsintYesSeconds before the default HTTP client gives up. A missing one is reported as timeout_in_seconds
apiUrl?stringNoOverride the API base URL
pwaUrl?stringNoOverride the PWA checkout URL. Normalized to end with /, e.g. …/pwa/#/

WaveMoneyConfig ​

ParameterTypeRequiredDescription
merchantIdstringYesMerchant ID issued by Wave
secretKeystringYesHash secret key issued by Wave
merchantNamestringYesShown on Wave's payment page
timeToLiveSecondsintYesSeconds the customer has to pay. A missing one is reported as time_to_live_in_seconds
timeoutSecondsintYesSeconds before the default HTTP client gives up. A missing one is reported as timeout_in_seconds
baseUrl?stringNoOverride the API base URL
authenticateUrl?stringNoOverride the host the customer is redirected to

AyaPayConfig ​

ParameterTypeRequiredDescription
appKeystringYesPublic application key
appSecretstringYesSecret used for checksums
timeoutSecondsintYesSeconds before the default HTTP client gives up. A missing one is reported as timeout_in_seconds
baseUrl?stringNoOverride the gateway base URL

YomaMmqrConfig ​

ParameterTypeRequiredDescription
merchantIdstringYesMerchant ID issued by Yoma
clientIdstringYesOAuth client ID
clientSecretstringYesOAuth client secret
webhookHashKeystringYesHash key issued by Yoma for verifying callbacks. A missing one is reported as webhook_hashkey
apiVersionstringYesThe {version} segment of Yoma's API paths, e.g. v1rc
timeoutSecondsintYesSeconds before the default HTTP client gives up. A missing one is reported as timeout_in_seconds
webhookSecret?stringNoWhen set, callbacks must carry it in X-Webhook-Secret
baseUrl?stringNoOverride the API base URL

CyberSourceConfig ​

ParameterTypeRequiredDescription
profileIdstringYesSecure Acceptance profile ID
accessKeystringYesProfile access key
secretKeystringYesProfile secret key used to sign fields
baseUrl?stringNoOverride the Secure Acceptance base URL

Production Endpoints ​

GatewayURL
KBZ Pay APIhttps://api.kbzpay.com/payment/gateway
KBZ Pay PWAhttps://wap.kbzpay.com/pgw/pwa/#/
Wave Money APIhttps://payments.wavemoney.io
Wave Money authenticate redirecthttps://payments.wavemoney.io
AYA Payment Gatewayhttps://pgw.ayainnovation.com
Yoma MMQRhttps://paymenthubapi.yomabank.com
CyberSourcehttps://secureacceptance.cybersource.com

The URLs are class constants on the config classes: KbzPayConfig::PRODUCTION_API_URL, KbzPayConfig::PRODUCTION_PWA_URL, WaveMoneyConfig::PRODUCTION_URL, WaveMoneyConfig::PRODUCTION_AUTHENTICATE_URL, and PRODUCTION_URL on AyaPayConfig, YomaMmqrConfig and CyberSourceConfig.

Testing Against UAT ​

Each gateway issues separate UAT credentials. To use them, set the URL overrides to the gateway's UAT endpoints together with the UAT credentials:

GatewayVariableConfig argumentUAT value
KBZ PayKBZ_PAY_BASE_URLapiUrlhttp://api-uat.kbzpay.com/payment/gateway/uat
KBZ PayKBZ_PAY_PWA_BASE_REDIRECT_URLpwaUrlhttps://static.kbzpay.com/pgw/uat/pwa/#/
Wave MoneyWAVE_MONEY_BASE_URLbaseUrlhttps://preprodpayments.wavemoney.io:8107
Wave MoneyWAVE_MONEY_AUTHENTICATE_URLauthenticateUrlhttps://preprodpayments.wavemoney.io
AYA Payment GatewayAYA_PAY_BASE_URLbaseUrlhttps://uat-pgw.ayainnovation.com
Yoma MMQRYOMA_MMQR_BASE_URLbaseUrlhttps://devapi.yomabank.net
CyberSourceCYBER_SOURCE_BASE_URLbaseUrlhttps://testsecureacceptance.cybersource.com

Wave serves its API on port 8107 and the page the customer is redirected to on the same host without the port. Remove the overrides, and switch to the production credentials, when you go live.

From Environment Variables ​

Every config class and gateway has fromEnv($env = null), which reads getenv() merged with $_ENV by default and takes any array instead, such as one in tests. The variable names match the Laravel package, so one .env file works for both.

php
use Laranex\PhpMyanmarPayments\KbzPay\KbzPay;
use Laranex\PhpMyanmarPayments\KbzPay\KbzPayConfig;

$kbz = KbzPay::fromEnv();
// or
$config = KbzPayConfig::fromEnv();
$kbz = new KbzPay($config);

Every variable is required unless it is marked optional. The values after = are examples:

env
# Every gateway that calls an API
MYANMAR_PAYMENTS_HTTP_TIMEOUT=30

# KBZ Pay
KBZ_PAY_APP_ID=
KBZ_PAY_APP_KEY=
KBZ_PAY_MERCHANT_CODE=
KBZ_PAY_BASE_URL=                     # optional override
KBZ_PAY_PWA_BASE_REDIRECT_URL=        # optional override

# Wave Money
WAVE_MONEY_MERCHANT_ID=
WAVE_MONEY_SECRET_KEY=
WAVE_MONEY_MERCHANT_NAME=
WAVE_MONEY_TIME_TO_LIVE_IN_SECONDS=300
WAVE_MONEY_BASE_URL=                  # optional override
WAVE_MONEY_AUTHENTICATE_URL=          # optional override

# AYA Payment Gateway (AYA_PGW_* names are read too)
AYA_PAY_APP_KEY=
AYA_PAY_APP_SECRET=
AYA_PAY_BASE_URL=                     # optional override

# Yoma MMQR
YOMA_MMQR_MERCHANT_ID=
YOMA_MMQR_CLIENT_ID=
YOMA_MMQR_CLIENT_SECRET=
YOMA_MMQR_WEBHOOK_HASHKEY=
YOMA_MMQR_API_VERSION=v1rc
YOMA_MMQR_WEBHOOK_SECRET=             # optional
YOMA_MMQR_BASE_URL=                   # optional override

# CyberSource
CYBER_SOURCE_PROFILE_ID=
CYBER_SOURCE_ACCESS_KEY=
CYBER_SOURCE_SECRET_KEY=
CYBER_SOURCE_BASE_URL=                # optional override

MYANMAR_PAYMENTS_HTTP_TIMEOUT sets timeout_in_seconds for KBZ Pay, Wave Money, AYA and Yoma MMQR. The package never reads files itself: load the .env file with your framework or with vlucas/phpdotenv before calling fromEnv().

Credentials from a config file go through fromArray(), which reads the same settings as snake_case keys:

Config classKeys
KbzPayConfigapp_id, app_key, merchant_code, timeout_in_seconds, api_url, pwa_url
WaveMoneyConfigmerchant_id, secret_key, merchant_name, time_to_live_in_seconds, timeout_in_seconds, base_url, authenticate_url
AyaPayConfigapp_key, app_secret, timeout_in_seconds, base_url
YomaMmqrConfigmerchant_id, client_id, client_secret, webhook_hashkey, api_version, timeout_in_seconds, webhook_secret, base_url
CyberSourceConfigprofile_id, access_key, secret_key, base_url

time_to_live_in_seconds and timeout_in_seconds take an int or integer text such as '30'.

One Object for Every Gateway ​

MyanmarPayments builds each gateway from its config, on first use, and reuses it. Only the gateways you call need to be configured:

php
use Laranex\PhpMyanmarPayments\KbzPay\KbzPayConfig;
use Laranex\PhpMyanmarPayments\MyanmarPayments;

$payments = new MyanmarPayments([
    'kbz_pay' => new KbzPayConfig(
        appId: '...',
        appKey: '...',
        merchantCode: '...',
        timeoutSeconds: 30,
    ),
    'yoma_mmqr' => [
        'merchant_id' => '...',
        'client_id' => '...',
        'client_secret' => '...',
        'webhook_hashkey' => '...',
        'api_version' => 'v1rc',
        'timeout_in_seconds' => 30,
    ],
]);

$payments->kbzPay(); // KbzPay, the same instance on every call
// throws ConfigurationException:
// The wave_money configuration is missing [merchant_id].
$payments->waveMoney();

// reads each gateway's variables on first use
$fromEnv = MyanmarPayments::fromEnv();

The keys kbz_pay, wave_money, aya_pay, yoma_mmqr and cyber_source take a config object or the array fromArray() reads, and the facade also takes the httpClient and cache arguments below, shared by every gateway it builds. $payments->cyberSource() returns the one CyberSource class.

HTTP Client ​

Gateways that call an API take any PSR-18 client as their second argument:

ArgumentTypeDescription
httpClient?Psr\Http\Client\ClientInterfaceSends every request. Use it for proxies, tracing, retries or test doubles. Without one, the gateway uses Guzzle with the config's timeoutSeconds when Guzzle is installed, and otherwise discovers an installed PSR-18 client
php
use GuzzleHttp\Client;
use Laranex\PhpMyanmarPayments\KbzPay\KbzPay;
use Laranex\PhpMyanmarPayments\KbzPay\KbzPayConfig;

$client = new Client([
    'timeout' => 10,
    'proxy' => 'http://proxy.internal:3128',
]);

$kbz = new KbzPay(KbzPayConfig::fromEnv(), $client);

fromEnv() takes the same client: KbzPay::fromEnv(null, $client).

A client you pass keeps its own timeout; timeoutSeconds is still required. A discovered client keeps its own timeout too. Request and stream objects are created with discovered PSR-17 factories, so a PSR-7 implementation such as guzzlehttp/psr7 or nyholm/psr7 must be installed. Guzzle ships one.

A failed request (connection error, timeout) throws an ApiException whose getPrevious() is the client's original exception.

CyberSource takes only its config: it only signs fields and makes no HTTP calls.

Token Cache ​

Yoma MMQR authenticates with an OAuth access token that lasts hours. YomaMmqr keeps it in a PSR-16 cache, its third argument:

php
use Laranex\PhpMyanmarPayments\YomaMmqr\YomaMmqr;
use Laranex\PhpMyanmarPayments\YomaMmqr\YomaMmqrConfig;
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\Cache\Psr16Cache;

$cache = new Psr16Cache(new RedisAdapter(
    RedisAdapter::createConnection('redis://localhost'),
));

$yoma = new YomaMmqr(YomaMmqrConfig::fromEnv(), null, $cache);

The default is an in-memory ArrayCache that only lives for the current PHP process, so with PHP-FPM every request fetches a new token. Pass a shared cache (Redis, APCu, filesystem) in production. Pass cache to MyanmarPayments to share one cache with the Yoma gateway it builds. The token is stored under myanmar-payments.yoma-mmqr.token.<sha256(baseUrl|clientId)>, the same key in every Laranex SDK, so services in different languages can share one cache. $yoma->forgetToken() drops a cached token, e.g. after rotating the client secret.

Released under the MIT License, except where a package says otherwise.