Products · Build a dot
Take payments
Take a payment in Dash's own payment sheet with dash.payments.request, choose how people can pay, confirm the payment on your server and test it.
Your dot doesn't build a checkout. It asks Dash for a payment, and Dash shows its own payment sheet. The person pays the way they already do in Dash: from a linked account, by card or with mobile money. The money goes to your business's Space, which owns the dot.
Declare payments
Add payments to dot.json's permissions, with what people pay for:
{
"permissions": { "payments": "Pay for ferry tickets" }
}Monime's review reads the reason. Dash doesn't ask the person for this permission, because they confirm every payment in the sheet.
Ask for a payment
Call this.dash.payments.request with the order. Amounts are in minor units, as in Monime's API, so SLE 75.00 is 7500:
// One of the page's actions
async pay(state) {
const result = await this.dash.payments.request({
order: {
name: 'Lungi ferry tickets',
reference: state.orderId,
lineItems: [
{ name: 'Adult ticket', unitPrice: { currency: 'SLE', value: 7500 }, quantity: state.adults },
],
},
});
if (result.status === 'completed') {
this.navigation.replace('tickets/confirmed', { orderId: state.orderId });
} else if (result.status === 'pending') {
this.setState({ note: "We're waiting for your payment to go through." });
} else {
this.setState({ note: "The payment didn't go through. Try again." });
}
},Dash adds up the total. An order holds:
- A
nameof 3 to 64 characters. - Your own
referencefor the order, up to 64 characters. Use a new one for each order. Your server's order ID works well. Asking again with the same reference gives back the first payment, and never pays twice. - 1 to 16
lineItems, all in one currency,SLEorUSD. Each has aname, aunitPriceand aquantityfrom 1 to 100,000. AnimageUrlshows a picture beside the item. It must behttps, on a host innetwork.hosts. - An optional
description. - Up to 64
metadatapairs, which stay with the payment and its webhooks. The Payments reference lists the rules for keys and values.
How a payment ends
If something goes wrong before the person picks a way to pay, request rejects with one of these codes:
| Code | What happened |
|---|---|
cancelled | The person closed the sheet |
invalid | Monime won't take the order. The message says what to change |
denied | Your dot or Space can't take payments right now |
failed | Dash couldn't reach Monime. Trying again may work |
timeout | Dash stopped waiting before the person picked a way to pay |
Monime rejects an order below its smallest amount as invalid. A dot that isn't published yet gets denied, as does a call Dash held back.
A second request while your dot's payment sheet is open also gets denied, and the open sheet carries on. To stop a double tap, set the Button's loading while you wait for the result.
Once they pick one, it resolves with the payment's status:
| Status | What it means |
|---|---|
completed | The money is paid |
pending | Not confirmed yet |
expired | The person didn't finish in time |
cancelled | The person closed the sheet after picking a way to pay |
failed | Only from get: a pending payment that failed later |
If a way to pay fails, the sheet stays open, and the person can try again or pick another.
request takes no timeout, as Dash decides how long the sheet waits. After the person picks a way to pay, cancel() only stops your dot waiting. The payment carries on.
Check a pending payment
Read a payment again with this.dash.payments.get(reference). You get undefined if your dot never asked for it, or the person never picked a way to pay. Check a pending one when the person comes back to the page:
hooks: {
async onShow() {
const payment = await this.dash.payments.get(this.state.orderId);
if (payment?.status === 'completed') {
this.setState({ paid: true, note: '' });
}
},
},Choose how people pay
Leave out methods to offer all three ways to pay. To offer fewer, or to set a method's options, list them in the order the sheet should show them:
await this.dash.payments.request({
order,
methods: [
{ type: 'momo', providers: ['m17'] },
{ type: 'link' },
],
});| Method | Pays with | Settings |
|---|---|---|
link | An account the person linked in Dash | providers |
card | A card | None |
momo | Mobile money | providers, phoneNumber |
providers lists the only providers that can pay, by Monime's IDs. Leave it out, or leave it empty, for any. Mobile money takes m17 (Orange Money) and m18 (Africell Money). A linked account is at a bank, so it takes only the banks: slb001 (Sierra Leone Commercial Bank), slb004 (Guaranty Trust Bank), slb007, slb009 and slb013.
phoneNumber is the only number that can pay with mobile money, written as +23276123456.
Where the money goes
The money goes to the Space's main account. To pay into another of the Space's accounts, give its ID:
await this.dash.payments.request({ order, financialAccountId: 'fac-k6VgVTfSmLruHpiQgMg4DUeySZx' });The account must belong to the Space that owns the dot and hold the order's currency, or the request rejects with invalid.
Confirm on your server
Anyone can change what a dot reports. Treat the result as something to show the person, not proof of payment. Deliver the ticket only once Monime confirms the payment to your server, by webhook or by looking it up with your Space's API key.
The result names what to look up:
| Paid with | Field | What it is |
|---|---|---|
| A card | checkoutSessionId | A checkout session |
| Mobile money | paymentCodeId | A payment code |
| A linked account | paymentId | The payment |
Each result also has the order's reference and total amount, and orderNumber once the payment completes, for the person's receipt. requestId is Dash's ID for the request. Monime's support asks for it if something goes wrong.
Test payments
In the simulator, Dash's sheet is a stand-in. Pick a way to pay, then choose how the payment ends: Paid, Pending, Declined or Expired. Declined keeps the sheet open. No money moves.
In a live test on a phone, payments are real, and the money goes to your Space. They only work once the dot is published and dot.json has the id Monime gave it. Until then, request and get reject with denied, and the rest of the dot runs as usual. Keep test orders small.
In a test, fake the call like any other:
const page = await testPage(tickets, {
host: {
'dash.payments.request': () => ({
method: 'momo',
paymentCodeId: 'pmc-test',
reference: 'order-1042',
requestId: 'req-test',
status: 'completed',
amount: { currency: 'SLE', value: 15000 },
}),
},
});