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 a failure and it uses the failure suffix instead.

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 triggerYour endpoint receives, in order
payment.createdpayment.created
payment.failedpayment.created, payment.processing, payment.failed
payment.succeededpayment.created, payment.processing, payment.succeeded, balance.updated, fee.charged
refund.succeededThe five above, then refund.created, refund.succeeded, balance.updated

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
--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=contact@example.com
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, then send or mark-paid
link.*wajub links create
account.*wajub accounts create, for Sync platforms
payment.expiredLet a pending payment reach the end of its window
payment.split.*Pass split_count on a sandbox payment

Use it against sandbox, deliberately

wajub trigger writes through the API using whichever profile is active. Point it at the wrong one and you have created a real customer on a real account.

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?