Skip to content

Configuration ​

Environment Variables ​

Add the keys of the gateways you use. Every setting of those gateways is required except the URL overrides and Yoma's webhook secret: there are no defaults. A gateway is configured the first time you request it, and a missing or blank setting returns a *myanmarpayments.ConfigurationError naming it, e.g. myanmarpayments: The kbz_pay configuration is missing [app_key]. The time settings must be whole numbers greater than 0; any other value returns the same error with Invalid set and the message myanmarpayments: The kbz_pay configuration [timeout_in_seconds] must be a whole number greater than 0.

The variable names are the ones the Go SDK reads and the same as Laravel Myanmar Payments, so one .env works for both. The values after = are examples:

env
# Every gateway that calls an API (all but CyberSource)
MYANMAR_PAYMENTS_HTTP_TIMEOUT=30
# AYA Pay and CyberSource, while the form route is enabled
MYANMAR_PAYMENTS_FORM_TTL_MINUTES=30
# optional, an http.clients entry, empty = default client
MYANMAR_PAYMENTS_HTTP_CLIENT=
# optional, store for Yoma access tokens, empty = default store
MYANMAR_PAYMENTS_CACHE_STORE=

# 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 Secure Acceptance
CYBER_SOURCE_PROFILE_ID=
CYBER_SOURCE_ACCESS_KEY=
CYBER_SOURCE_SECRET_KEY=
CYBER_SOURCE_BASE_URL=                # optional override

Settings ​

VariableConfig keyRequiredDescription
MYANMAR_PAYMENTS_HTTP_TIMEOUThttp.timeoutYesSeconds before a gateway call gives up. Given to every gateway except CyberSource as its timeout_in_seconds
MYANMAR_PAYMENTS_FORM_TTL_MINUTESform_route.ttl_minutesYesMinutes an auto-submit form link stays valid. Needed by AYA Pay and CyberSource while the form route is enabled
MYANMAR_PAYMENTS_HTTP_CLIENThttp.clientNoAn entry of http.clients in config/http.go; empty means the default client
MYANMAR_PAYMENTS_CACHE_STOREcache_storeNoCache store for Yoma MMQR access tokens; empty means the default store
KBZ_PAY_APP_IDkbz_pay.app_idYesappid issued by KBZ
KBZ_PAY_APP_KEYkbz_pay.app_keyYesSecret key used to sign requests
KBZ_PAY_MERCHANT_CODEkbz_pay.merchant_codeYesmerch_code issued by KBZ
KBZ_PAY_BASE_URLkbz_pay.api_urlNoOverride the API base URL
KBZ_PAY_PWA_BASE_REDIRECT_URLkbz_pay.pwa_urlNoOverride the PWA checkout URL
WAVE_MONEY_MERCHANT_IDwave_money.merchant_idYesMerchant ID issued by Wave
WAVE_MONEY_SECRET_KEYwave_money.secret_keyYesHash secret key issued by Wave
WAVE_MONEY_MERCHANT_NAMEwave_money.merchant_nameYesShown on Wave's payment page
WAVE_MONEY_TIME_TO_LIVE_IN_SECONDSwave_money.time_to_live_in_secondsYesSeconds the customer has to pay
WAVE_MONEY_BASE_URLwave_money.base_urlNoOverride the API base URL
WAVE_MONEY_AUTHENTICATE_URLwave_money.authenticate_urlNoOverride the host the customer is redirected to
AYA_PAY_APP_KEYaya_pay.app_keyYesPublic application key
AYA_PAY_APP_SECRETaya_pay.app_secretYesSecret used for checksums
AYA_PAY_BASE_URLaya_pay.base_urlNoOverride the gateway base URL
YOMA_MMQR_MERCHANT_IDyoma_mmqr.merchant_idYesMerchant ID issued by Yoma
YOMA_MMQR_CLIENT_IDyoma_mmqr.client_idYesOAuth client ID
YOMA_MMQR_CLIENT_SECRETyoma_mmqr.client_secretYesOAuth client secret
YOMA_MMQR_WEBHOOK_HASHKEYyoma_mmqr.webhook_hashkeyYesHash key issued by Yoma for verifying callbacks
YOMA_MMQR_API_VERSIONyoma_mmqr.api_versionYesThe {version} segment of Yoma's API paths, e.g. v1rc
YOMA_MMQR_WEBHOOK_SECRETyoma_mmqr.webhook_secretNoWhen set, callbacks must carry it in X-Webhook-Secret
YOMA_MMQR_BASE_URLyoma_mmqr.base_urlNoOverride the API base URL
CYBER_SOURCE_PROFILE_IDcyber_source.profile_idYesSecure Acceptance profile ID
CYBER_SOURCE_ACCESS_KEYcyber_source.access_keyYesProfile access key
CYBER_SOURCE_SECRET_KEYcyber_source.secret_keyYesProfile secret key used to sign fields
CYBER_SOURCE_BASE_URLcyber_source.base_urlNoOverride the Secure Acceptance base URL

Only the gateways you call need their settings: an app that only uses KBZ Pay never reads the Wave Money keys.

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.

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

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 keyUAT value
KBZ PayKBZ_PAY_BASE_URLkbz_pay.api_urlhttp://api-uat.kbzpay.com/payment/gateway/uat
KBZ PayKBZ_PAY_PWA_BASE_REDIRECT_URLkbz_pay.pwa_urlhttps://static.kbzpay.com/pgw/uat/pwa/#/
Wave MoneyWAVE_MONEY_BASE_URLwave_money.base_urlhttps://preprodpayments.wavemoney.io:8107
Wave MoneyWAVE_MONEY_AUTHENTICATE_URLwave_money.authenticate_urlhttps://preprodpayments.wavemoney.io
AYA Payment GatewayAYA_PAY_BASE_URLaya_pay.base_urlhttps://uat-pgw.ayainnovation.com
Yoma MMQRYOMA_MMQR_BASE_URLyoma_mmqr.base_urlhttps://devapi.yomabank.net
CyberSourceCYBER_SOURCE_BASE_URLcyber_source.base_urlhttps://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. Quote the KBZ PWA URL in .env, because of its #:

env
# UAT
KBZ_PAY_BASE_URL=http://api-uat.kbzpay.com/payment/gateway/uat
KBZ_PAY_PWA_BASE_REDIRECT_URL="https://static.kbzpay.com/pgw/uat/pwa/#/"
WAVE_MONEY_BASE_URL=https://preprodpayments.wavemoney.io:8107
WAVE_MONEY_AUTHENTICATE_URL=https://preprodpayments.wavemoney.io
AYA_PAY_BASE_URL=https://uat-pgw.ayainnovation.com
YOMA_MMQR_BASE_URL=https://devapi.yomabank.net
CYBER_SOURCE_BASE_URL=https://testsecureacceptance.cybersource.com

Config Structure ​

config/myanmar_payments.go maps the environment variables onto the myanmar_payments config. A published value wins; when a value is empty or the file is not published, the package falls back to the SDK's environment variable.

go
package config

import (
	contractshttp "github.com/goravel/framework/contracts/http"

	"yourapp/app/facades"
)

func init() {
	config := facades.Config()
	config.Add("myanmar_payments", map[string]any{
		"kbz_pay": map[string]any{
			"app_id":        config.Env("KBZ_PAY_APP_ID", ""),
			"app_key":       config.Env("KBZ_PAY_APP_KEY", ""),
			"merchant_code": config.Env("KBZ_PAY_MERCHANT_CODE", ""),
			"api_url":       config.Env("KBZ_PAY_BASE_URL", ""),
			"pwa_url": config.Env(
				"KBZ_PAY_PWA_BASE_REDIRECT_URL", "",
			),
		},

		"wave_money": map[string]any{
			"merchant_id": config.Env("WAVE_MONEY_MERCHANT_ID", ""),
			"secret_key":  config.Env("WAVE_MONEY_SECRET_KEY", ""),
			"merchant_name": config.Env(
				"WAVE_MONEY_MERCHANT_NAME", "",
			),
			"time_to_live_in_seconds": config.Env(
				"WAVE_MONEY_TIME_TO_LIVE_IN_SECONDS", "",
			),
			"base_url": config.Env("WAVE_MONEY_BASE_URL", ""),
			"authenticate_url": config.Env(
				"WAVE_MONEY_AUTHENTICATE_URL", "",
			),
		},

		"aya_pay": map[string]any{
			"app_key": config.Env(
				"AYA_PAY_APP_KEY", config.Env("AYA_PGW_APP_KEY", ""),
			),
			"app_secret": config.Env(
				"AYA_PAY_APP_SECRET", config.Env("AYA_PGW_APP_SECRET", ""),
			),
			"base_url": config.Env(
				"AYA_PAY_BASE_URL", config.Env("AYA_PGW_BASE_URL", ""),
			),
		},

		"yoma_mmqr": map[string]any{
			"merchant_id":   config.Env("YOMA_MMQR_MERCHANT_ID", ""),
			"client_id":     config.Env("YOMA_MMQR_CLIENT_ID", ""),
			"client_secret": config.Env("YOMA_MMQR_CLIENT_SECRET", ""),
			"webhook_hashkey": config.Env(
				"YOMA_MMQR_WEBHOOK_HASHKEY", "",
			),
			"webhook_secret": config.Env("YOMA_MMQR_WEBHOOK_SECRET", ""),
			"base_url":       config.Env("YOMA_MMQR_BASE_URL", ""),
			"api_version":    config.Env("YOMA_MMQR_API_VERSION", ""),
		},

		"cyber_source": map[string]any{
			"profile_id": config.Env("CYBER_SOURCE_PROFILE_ID", ""),
			"access_key": config.Env("CYBER_SOURCE_ACCESS_KEY", ""),
			"secret_key": config.Env("CYBER_SOURCE_SECRET_KEY", ""),
			"base_url":   config.Env("CYBER_SOURCE_BASE_URL", ""),
		},

		"http": map[string]any{
			"client":  config.Env("MYANMAR_PAYMENTS_HTTP_CLIENT", ""),
			"timeout": config.Env("MYANMAR_PAYMENTS_HTTP_TIMEOUT", ""),
		},

		"cache_store": config.Env("MYANMAR_PAYMENTS_CACHE_STORE", ""),

		"form_route": map[string]any{
			"enabled":     true,
			"path":        "myanmar-payments/form",
			"middleware":  []contractshttp.Middleware{},
			"ttl_minutes": config.Env(
				"MYANMAR_PAYMENTS_FORM_TTL_MINUTES", "",
			),
			"base_url":    config.Env("APP_URL", "http://localhost"),
		},
	})
}

yourapp/app/facades is the facades package Goravel generates in your app; package:install fills in the right import.

HTTP Client ​

go
"http": map[string]any{
	"client":  config.Env("MYANMAR_PAYMENTS_HTTP_CLIENT", ""),
	"timeout": config.Env("MYANMAR_PAYMENTS_HTTP_TIMEOUT", ""),
},

Gateway calls go through Goravel's HTTP client, so Fake() intercepts them in tests; see Testing. client names an entry of http.clients in config/http.go (empty means the default client), so its transport settings (connection pool, telemetry) apply. timeout is in seconds, applies to gateway calls only and is required: the package passes it to KBZ Pay, Wave Money, AYA and Yoma MMQR as their TimeoutSeconds, so a missing one returns myanmarpayments: The kbz_pay configuration is missing [timeout_in_seconds]. when you first request KBZ Pay. When a gateway can't be reached, the call returns an *APIError with HTTPStatus 0.

Auto-submit Form Route ​

go
"form_route": map[string]any{
	"enabled":     true,
	"path":        "myanmar-payments/form",
	"middleware":  []contractshttp.Middleware{},
	"ttl_minutes": config.Env("MYANMAR_PAYMENTS_FORM_TTL_MINUTES", ""),
	"base_url":    config.Env("APP_URL", "http://localhost"),
},

AYA Pay and CyberSource need the customer's browser to POST a signed form. The package registers a GET /myanmar-payments/form route (named myanmar-payments.form) that renders that form and submits it, and payments.AutoSubmitURL(form) returns an encrypted link to it. Links expire after ttl_minutes; an invalid or expired link answers 410 Gone. The page is sent with Cache-Control: no-store.

KeyMeaning
enabledRegister the route. When false, AutoSubmitURL returns payments.ErrFormRouteDisabled; build the form yourself, see Form Payments
pathThe route path
middlewareMiddleware for the route, e.g. rate limiting. Don't add authentication: the customer may arrive from a gateway or another device
ttl_minutesMinutes a link stays valid. Required to create a link: without it AutoSubmitURL returns a *myanmarpayments.ConfigurationError with form_route and ttl_minutes (The form_route configuration is missing [ttl_minutes].), with Invalid set for a value that is not a whole number greater than 0
base_urlThe scheme and host links start with. Falls back to http.url, then APP_URL

Links are encrypted with Goravel's crypt facade (APP_KEY); without it, AutoSubmitURL returns payments.ErrCryptNotAvailable.

Cache ​

Yoma MMQR access tokens last several hours and are reused until they expire. They are kept in your default cache store, or in cache_store when set. Use a shared store (Redis, database) when you run more than one server. The token is stored under myanmar-payments.yoma-mmqr.token.<sha256(baseURL|clientID)>, the same key in every Laranex SDK, so services written in different languages can share one store. Without the cache facade, each process keeps its own token in memory.

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