Products · Templates
collect_payment
Take a mobile money payment during a USSD session. The subscriber approves it with their PIN.
The collect_payment template takes a mobile money payment inside the flow. The subscriber sees your PIN prompt, enters their mobile money PIN, and the flow continues once the payment goes through.
You don't need your own payment integration. Point the page at a Payment Code or UVAN in your Monime space. Payments work on Orange Money and Afrimoney.
Fields
| Property | Type | Required | Description |
|---|---|---|---|
payment_target_ref | string | Yes | The Payment Code or UVAN that receives the money. Not the amount, and not the subscriber's number. |
amount | number or string | No | The amount in SLE, at least 1 after the multiplier. Leave it out to let the subscriber type it. See the amount rule. |
multiplier | integer or string | No | Multiplies the amount, for example a ticket count. Default 1. A literal must be 1 to 1000. A reference outside that range is clamped to it. |
reference | string | No | Your reference for reconciliation. Cut off at 100 characters. |
receipt_name | string | No | Title on the receipt. Cut off at 100 characters. See Receipt name. |
metadata | object | No | Up to 8 string pairs. Keys up to 21 characters, values up to 40. Values can use $(...). |
reference, receipt_name and metadata values can use $(...) variables and expressions.
The Amount Rule
amount and multiplier take either a number or a single variable reference, and nothing else. These are allowed:
100"$(page.enter_amount.value)""$(data.amount)""$(rc.usual_amount)""$(sc.gift_amount)"
Expressions such as $(rc.usual_amount ?? 50) or $(page.qty.value * 2) are rejected when you save the flow. To charge a computed amount, write it to sc.* on an earlier page (a side-effect page works well), then reference that key here.
When there is no amount, the subscriber is asked to enter one before the PIN prompt.
The PIN Prompt
The label is the PIN prompt: the text the subscriber reads just before entering their PIN. Say which network, what the payment is for, and how much:
Enter your $(session.network_provider_name) PIN to pay {{amount}} for registration.{{amount}} (double curly braces, not $(...)) is replaced with the amount being charged, after the multiplier. It works only in this label. If the label has no {{amount}}, Monime adds the amount at the end.
Don't put a currency before {{amount}}. Write pay {{amount}}, not pay SLE {{amount}}.
Receipt Name
Monime adds the multiplier to the end of the receipt name, for example Registration fee (X 1). This happens even when the multiplier is 1. To place it yourself, put {{multiplier}} in the text:
{ "receipt_name": "{{multiplier}} tickets to Freetown Live" }What It Returns
When the payment succeeds, the page value is the transaction ID. Read it with $(page.PAGE_ID.value). The flow then moves to the next page.
If the payment fails, the subscriber sees the network's message and the session ends. The flow does not continue, so you can't branch on a failed payment.
Examples
Fixed amount:
{
"id": "make_payment",
"component": {
"type": "template",
"label": "Enter your $(session.network_provider_name) PIN to pay {{amount}} for registration.",
"template_name": "collect_payment",
"template_data": {
"payment_target_ref": "7150001234",
"amount": 100,
"reference": "REG-FEE",
"receipt_name": "Registration fee"
}
}
}Amount from an earlier page:
{
"id": "make_payment",
"component": {
"type": "template",
"label": "Enter your $(session.network_provider_name) PIN to pay {{amount}} for $(page.select_package.label).",
"template_name": "collect_payment",
"template_data": {
"payment_target_ref": "9020056",
"amount": "$(page.enter_amount.value)"
}
}
}Saved amount for a returning subscriber:
{
"id": "make_payment",
"component": {
"type": "template",
"label": "Enter your $(session.network_provider_name) PIN to give {{amount}}.",
"template_name": "collect_payment",
"template_data": {
"payment_target_ref": "7150004521",
"amount": "$(rc.usual_amount)",
"reference": "$(rc.display_name)"
}
}
}An earlier visit saved rc.usual_amount with on_done.recurring_context.mutations. Use sc.* instead if the amount should last only for this session.
Subscriber types the amount:
{
"id": "make_payment",
"component": {
"type": "template",
"label": "Enter your $(session.network_provider_name) PIN to top up {{amount}} with Makeni Airtime.",
"template_name": "collect_payment",
"template_data": {
"payment_target_ref": "7150009876"
}
}
}Multiplier for several units:
{
"id": "pay_subscription",
"component": {
"type": "template",
"label": "Enter your $(session.network_provider_name) PIN to pay {{amount}} for 3 months.",
"template_name": "collect_payment",
"template_data": {
"payment_target_ref": "7150004521",
"amount": 50,
"multiplier": 3,
"reference": "SUB-3M",
"receipt_name": "Premium plan, {{multiplier}} months",
"metadata": {
"plan": "premium"
}
}
}
}Monime charges 50 × 3 = SLE 150.
Errors
| The subscriber sees | Cause | Fix |
|---|---|---|
| "Flow error: The minimum amount is …" | The amount after the multiplier is below SLE 1 | Raise min_value on the amount prompt |
| "Flow error: 'collect_payment' amount must be a number" | The referenced value isn't a number | Collect it with an integer or double prompt |
| "… is having issues. You may be debited…" | The network's mobile money service is down | Nothing to fix in the flow. The subscriber can try later |
| "Unable to process payment: …" | The payment was declined, for example for low balance | Nothing to fix in the flow |