Skip to content

Trigger events

Produce a real sandbox payment, and the events that follow it.

wajub trigger does not fabricate a payload. It calls the sandbox API the way your code would, with the test number that produces the outcome you asked for, and lets the platform emit the events on its own. What reaches your handler is therefore identical to what a real payer would have produced.

One command, a whole payment
$ wajub trigger payment.succeeded

Triggering payment.succeeded …
✓ created payment trx_test_VPRKcDWn0pi29ScaQL9B
✓ dispatched cm.mtn charge (+237670000000)
✓ payment trx_test_VPRKcDWn0pi29ScaQL9B is succeeded

The number it dialled is the giveaway: +237670000000 is the sandbox MTN Cameroon prefix followed by the success suffix. Ask for another outcome and it dials another suffix.

The same command, the other outcome
$ wajub trigger payment.failed --amount 2500

Triggering payment.failed …
✓ created payment trx_test_PR8mmBq5bfkxqGcJRtP5
✓ dispatched cm.mtn charge (+237670000002)
✓ payment trx_test_PR8mmBq5bfkxqGcJRtP5 is failed

The eight events

wajub trigger --list
Triggerable events:
  customer.created     Create a customer
  customer.updated     Create then update a customer
  payment.cancelled    Create and cancel a payment (mobile money canceled)
  payment.created      Create a payment and leave it unpaid
  payment.failed       Create and fail a payment (mobile money failure)
  payment.succeeded    Create and complete a payment (mobile money success)
  refund.failed        Complete a payment whose refund deterministically fails
  refund.succeeded     Complete a payment then refund it (refund succeeds)

Eight arguments, but far more than eight events, because each one drives a real flow.

You triggerNumber dialledYour endpoint receives, in order
payment.createdNonepayment.created
payment.failed+237670000002payment.created, payment.processing, payment.failed
payment.cancelled+237670000004payment.created, payment.processing, payment.cancelled
payment.succeeded+237670000000payment.created, payment.processing, payment.succeeded, balance.updated, fee.charged
refund.succeeded+237670000000The five above, then refund.created, refund.succeeded, balance.updated
refund.failed+237670000009The five payment events, then refund.created, refund.failed

The very first trigger on an account also emits customer.created, because the CLI creates the CLI Trigger customer it reuses afterwards.

The chain is the lesson, not a side effect

A real payment behaves the same way. If your handler only implements payment.succeeded, this is where you find out that four other types are already arriving and being ignored, and that fee.charged is the one your ledger was missing.

Shaping what gets created

FlagDefaultEffect
--amount5000Amount on the created resource
--currencyXAFCurrency
--channelcm.mtnWhich rail to charge. The number dialled takes that operator's sandbox prefix and keeps its suffix, from CLI 1.7.2
--phoneDerivedOverride the payer number. Advanced, it decides the outcome
-d, --dataExtra key=value on the created resource, repeatable
--listPrint the list above and exit
Closer to your own traffic
wajub trigger payment.succeeded --amount 250000 --currency XOF --channel ci.orange
wajub trigger customer.created -d name="Boutique Akwa" -d [email protected]
wajub trigger payment.succeeded -d reference=order-4172 -d description="Order #4172"

Passing -d reference=order-4172 is the trick that makes the test realistic: your handler can then look the order up exactly as it would in production, instead of special casing the fake payment.

What it cannot trigger

The list is short on purpose: an event only appears there when the CLI can produce it without extra setup. Everything else you produce the same way you would in your own code.

EventHow to produce it
transfer.*wajub beneficiaries create, then wajub transfers create
dispute.*Disputes are opened by the acquirer, not by you
invoice.*wajub invoices create with a live key, since invoices do not exist in sandbox
link.*wajub links create with a live key, for the same reason
account.*wajub accounts create, then the merchant's onboarding, for Sync platforms
payment.expiredLet a pending payment reach the end of its window
payment.split.*wajub post /payments/{id}/splits on a sandbox payment

Sandbox keys only

wajub trigger refuses any key that is not a sandbox one, before sending a single request. With a live profile active, or a live WAJUB_API_KEY exported, it stops there:

With a live key
$ wajub trigger payment.succeeded

 ›   Error: `wajub trigger` only works with a sandbox API key (sk_test…).

Pick the sandbox profile for the command, and check that no live key is exported, since WAJUB_API_KEY wins over --profile.

Be explicit when it matters
wajub config                                  # which profile is default?
wajub trigger payment.succeeded --profile sandbox

The loop

Two terminals
# 1
wajub listen --forward-to localhost:3000/webhooks/wajub

# 2
wajub trigger payment.succeeded
wajub trigger payment.failed
wajub trigger refund.succeeded

Three commands cover the branches most handlers get wrong: the happy path, the failure that must release the reservation, and the refund that must not be mistaken for a new payment.

What did you think of this content?