Skip to content

Wave Pay ​

Wave Pay (Pay with Wave API v1.3) sends the customer to Wave's payment page to pay with their WavePay wallet.

CallWhat it doesReturns
await wave.initiate(data)Redirect to Wave's payment pageRedirectPayment
wave.handleCallback(request)Verify the callbackPaymentCallback

Wave Pay has no status API in this package: the callback is the only payment result.

How it works ​

Wave sends the customer back to your return URL and posts the result to your callback URL separately.

Wave Pay: payment request, authenticate, resultCustomerYour appWave PayCheck outPayment request with hashawait wave.initiate(data)transaction_idRedirect to authenticate/authenticate?transaction_id=…Pay with WavePayBack to the frontend URLreturnUrl: not proof of paymentBackend result URL callbackPOST to callbackUrl, hashValueVerified callback is proofwave.handleCallback(request)
Wave Pay: payment request, authenticate, result

Initiating a Payment ​

ts
import {
  WavePay,
  WavePayConfig,
  type WavePayPaymentData,
} from '@laranex/myanmar-payments/wave-pay';

const wave = new WavePay({
  merchantId: '...',
  secretKey: '...',
  merchantName: 'My Shop',
  baseUrl: WavePayConfig.PRODUCTION_URL,
  baseRedirectUrl: WavePayConfig.PRODUCTION_URL,
  timeToLiveSeconds: 300,
});

const data: WavePayPaymentData = {
  orderId: `ORDER_${order.id}`,
  callbackUrl: 'https://shop.test/payments/wave/callback',
  returnUrl: `https://shop.test/orders/${order.id}`,
  description: `Order #${order.id}`,
  items: [
    { name: 'Product A', amount: 6000 },
    { name: 'Product B', amount: 4000 },
  ],
};

const payment = await wave.initiate(data);

// Store data.merchantReferenceId with the order: initiate() filled it in.

res.writeHead(302, { Location: payment.url }).end();

Payments are posted as JSON, in MMK, to {baseUrl}/payment; the customer is sent to {baseRedirectUrl}/authenticate?transaction_id=….

WavePayPaymentData ​

FieldTypeRequiredRules
orderIdstringYesYour order ID, at most 100 characters: letters, digits, _ and - only. One order can have several payment attempts
callbackUrlstringYesAbsolute http or https URL that Wave posts the result to, at most 255 characters
returnUrlstringYesAbsolute http or https URL Wave sends the customer back to, at most 255 characters. Not proof of payment
descriptionstringYesShown to the customer, at most 255 characters
itemsWavePayItem[]YesAt least one item
amountAmount | number | bigintNoWhole kyat, greater than 0 (Wave doesn't accept decimals). Unset charges the sum of the items. Wave only accepts MMK
merchantReferenceIdstringNoUnique ID of this attempt, at most 100 characters: letters, digits, _ and - only. Unset or empty means a random ID
merchantNamestringNoBusiness name shown on Wave's page for this payment. Unset or null uses the configured merchantName; a blank one is rejected
timeToLiveSecondsnumberNoSeconds the customer has to pay this payment, a whole number greater than 0. Unset or null uses the configured timeToLiveSeconds
additionalField3, additionalField4, additionalField5stringNoExtra information, at most 50 characters each, sent as additional_field_3–5 and echoed in the callback's additionalField3–5. Unset, null or empty is not sent

Length limits count UTF-8 bytes. WavePayItem has a name and an amount in whole kyat, greater than 0. The items are summed with exact bigint arithmetic, never floats; WavePay.resolvedAmount(data) returns the total that will be charged.

Merchant Reference ID ​

Wave rejects a reused merchant_reference_id (409). Leave it empty to get a random one, and store data.merchantReferenceId after initiate(): Wave's callback may omit orderId.

Handling Callbacks ​

ts
import { CallbackRequest } from '@laranex/myanmar-payments';

// POST /payments/wave/callback
try {
  const request = await CallbackRequest.fromNodeRequest(req);
  const callback = wave.handleCallback(request);

  if (callback.isSuccessful()) {
    // callback.orderId is your orderId
    // callback.raw.merchantReferenceId is the attempt's reference
    // callback.gatewayReference is Wave's transactionId
  }

  callback.acknowledgement.send(res);
} catch {
  res.writeHead(400).end('invalid callback');
}

Responses ​

See Results and PaymentCallback & Status for the full classes.

initiate() → RedirectPayment ​

FieldWave Pay value
flow'redirect'
orderIdYour data.orderId
url{baseRedirectUrl}/authenticate?transaction_id=… (URL-encoded), e.g. https://payments.wavemoney.io/authenticate?transaction_id=…
gatewayReferenceWave transaction_id. Always set
rawWave's /payment response: message (success), transaction_id

handleCallback() → PaymentCallback ​

FieldWave Pay value
orderIdWave orderId, falling back to merchantReferenceId when it is missing, null or empty
statusstatus mapped, see Statuses
gatewayStatusWave status, trimmed, e.g. PAYMENT_CONFIRMED
gatewayReferenceWave transactionId
amountWave amount, e.g. 10000
rawThe verified body: status, merchantId, orderId, merchantReferenceId, frontendResultUrl, backendResultUrl, initiatorMsisdn, amount, timeToLiveSeconds, paymentDescription, currency, additionalField1–5, transactionId, paymentRequestId, requestTime, hashValue
acknowledgementHTTP 200, empty body, Content-Type: text/plain

Statuses ​

Only PAYMENT_CONFIRMED means the customer paid.

Wave statusPaymentStatus
PAYMENT_CONFIRMEDsuccessful
BILL_COLLECTION_FAILED, INSUFFICIENT_BALANCE, ACCOUNT_LOCKEDfailed
PAYMENT_REQUEST_CANCELLEDcanceled
TRANSACTION_TIMED_OUT, SCHEDULER_TRANSACTION_TIMED_OUTexpired
anything elseunknown

SCHEDULER_TRANSACTION_TIMED_OUT arrives up to 15 minutes after the time-to-live ends.

Errors ​

CallThrowsWhen
initiate()InvalidPaymentDataErrorWavePay.validate(data) fails. Nothing is sent and data is left untouched. Item errors use items.0.amount keys
initiate()ApiErrorWave answers with an HTTP error, a message other than success, or no transaction_id
handleCallback()SignatureVerificationErrorhashValue doesn't match, a hashed field holds an object or array, amount isn't a decimal, both orderId and merchantReferenceId are empty, or either holds anything but letters, digits, _ and -

httpStatus tells Wave's rejections apart: 400 invalid hash, 404 unknown merchant, 409 reused reference, 422 validation (gatewayCode is VALIDATION_ERROR).