Collect a contract's arrears now
Takes a payment against an existing contract now, outside its schedule, for some or all of what is outstanding. Merchant View opens a hosted checkout for the contract (source MOTO, amount defaulted to the arrears) and the payment is taken when the hosted checkout submits; an integrator can call the contract's pay-now endpoint directly with a saved payment method or card details. The money is attributed to the contract's open charges, the contract's next automated attempt is recalculated, and a card entered during the checkout can be saved and made the contract's payment method.
Where you can do this
- Merchant View: Contract (Make Payment)
- Merchant View: Arrears (Make Payment)
- The hosted checkout: Payment form (Process Payment (checkout request names an existing contract))
- API: Create a checkout (
POST /checkouts) — body carries contract; Merchant View sends source MOTO and default_amount equal to the arrears - The hosted checkout: the hosted checkout submits and its checkout request names a contract
- API: Create a payment (
POST /contracts/{contract_id}/payment) — amount, with an optional payment_method (saved id or card details) - API: Create a payment (
POST /payments) — body carries contract
Before you start
- The contract exists and has an amount outstanding: at least one charge still in progress with an unpaid part for the paying account. Server-side this is the only status check; see Rules for what Merchant View additionally refuses.
- The contract is not holding an unattributed payment (money received but not yet allocated to charges); if it is, no new transaction is created.
- No other payment is being processed on the contract at the same moment (one contract lock per payment).
- Admin app: the user holds
payment_contractand the instance has therecurring_editfeature option; the contract shows an arrears amount; its status is not SETUP, UNRESOLVED, UNATTRIBUTED, CANCELLED or PENDING; and no automated attempt is due within the next five minutes or ran within the last hour.
Inputs
| Input | Required | Meaning and constraints |
|---|---|---|
| contract | yes | The contract to collect against; in the checkout it is carried in the checkout request, on the direct endpoints in the path or the contract field |
| amount | conditional | Amount to collect. Required and above zero on a single-legal-entity contract; not accepted on a split-payment contract (each leg is collected in full). Cannot exceed the contract's total outstanding, which counts every in-progress charge including those not yet due, net of any unresolved payment |
| payment_method | no (direct API) / yes (checkout) | A saved payment method id, or card details (card_number, card_expiry as MMYY, MM/YY or YYYY-MM, card_cvc); the direct endpoint defaults to the contract's own payment method when omitted. the hosted checkout sends the selected saved method or the card fields it collected |
| save_card | no | Store a newly entered card and make it the contract's payment method (checkout form: the "save card" choice) |
| success_url | no | Where the customer returns after a successful 3DS or hosted step |
| cancel_url | no | Where the customer returns after abandoning a 3DS or hosted step |
| default_amount | checkout only | The amount pre-filled in the form; the operator can change it |
| source | checkout only | MOTO for a payment taken over the phone by an operator |
| currency | checkout only | The contract's currency |
| account | checkout only | The contract's account |
Rules
Checked by the API means Shuttle refuses the request however it is sent; a screen name means only that screen refuses it, and a direct API call would be accepted.
| Rule | Checked by | What you see |
|---|---|---|
| The contract must exist | The API | NOT_FOUND: "Contract not found"; Shuttle: VALIDATION_ERROR "apiValidation.error.not.found" on PAYMENT_CONTRACT |
| A single-legal-entity contract must carry an amount above zero | The API | VALIDATION_ERROR: "Amount required"; Shuttle: "apiValidation.error.mandatory" |
| The amount cannot exceed the total outstanding (all in-progress charges, due or not, net of unresolved payments); a contract with nothing outstanding cannot be paid | The API | INVALID: "Invalid value for field amountToPay."; the hosted checkout shows the same message |
| The amount is re-read inside the contract lock; anything above what is then outstanding is refused before any record is written | The API | INVALID_AMOUNT (BOLT-1168) |
| Before the gateway is called, the amount is validated against the charges attributable to the transaction's legal entity and account; a failure abandons the transaction as not attempted ("Contract no longer owes this amount") | The API | INVALID_AMOUNT_NOTHING_DUE (BOLT-1169); the direct API surfaces it as code INVALID |
| On a split-payment contract each legal entity's leg is compared with what that entity is currently owed inside the lock, and every leg is an authorisation followed by a capture, so every gateway involved must support authorisation | The API | INVALID_AMOUNT_NOTHING_DUE (BOLT-1169); CANNOT_AUTHORISE_TRANSACTION (BOLT-7094) |
| A payment method is required: a saved method id or card details. The direct endpoint fills in the contract's own method when none is sent; the hosted checkout always sends one | The API | INVALID: "Invalid value for field paymentMethodValues." |
| A new card is routed against the contract's legal entity and currency and the account's domicile; a card type with no route there has no gateway | The API | CANNOT_ROUTE_TRANSACTION (BOLT-7085) |
| The payment method must be usable for the contract (initiative, legal entity, currency, domicile, gateway) and not failed, expired or archived | The API | not attempted: "Payment method no longer available (failed / expired / archived)", PAYMENT_METHOD_UNAVAILABLE (BOLT-1192) |
| The gateway must not be archived and a route must exist for the contract's designation and the account's country | The API | declined: "Payment method no longer available (gateway archived)" / "Gateway unavailable for this payment"; the contract is marked unroutable |
| A declined, errored, not-attempted or rolled-back payment is reported as an error carrying the gateway's message | The API | status ERROR with BOLT-1176 (declined), BOLT-1177 (declined, retry), BOLT-1178 / BOLT-1278 (declined error, MOTO variant) or BOLT-1192; the direct API maps 1192 to INVALID_REQUEST and the rest to INVALID |
| Only one payment runs on a contract at a time; a second waits up to 30 seconds for the lock, then fails. A lock that is taken is held for at most 120 seconds | The API | LOCK_EXCEPTION (BOLT-7059); the hosted checkout shows "duplicate in progress" and retries for up to five minutes; the direct API surfaces code INVALID |
the hosted checkout's submission must match the cached checkout request: see Take a one-off payment. Merchant View's checkout pins the contract, account and currency but not the amount (it sends default_amount), so the operator may change the amount in the form up to the total outstanding | The API and Merchant View screen | INVALID_REQUEST: "Request tampered" |
Merchant View offers the control only when an arrears amount is showing (overdue_amount, or the statement balance as at today); the server accepts any amount up to the total outstanding, including charges not yet due | Merchant View screen | control hidden |
| The checkout's duplicate-nonce protection applies to the checkout call: see Take a one-off payment | The API | PROCESSING or DUPLICATE |
What happens
- A PAYMENT transaction is created against the contract for the amount requested (on a split-payment contract, one leg per legal entity for that entity's full due amount) and sent to the gateway. The response carries the transaction; a declined, not-attempted or rolled-back payment comes back with status ERROR and the gateway's message.
- On success the money is allocated to the contract's open charges, each charge it completes raises CHARGE.COMPLETE, the contract's failure count is cleared, and PAYMENT.SUCCESS (PAYMENT.PENDING when the gateway's answer is pending), CONTRACT.UPDATE and ACCOUNT.UPDATE are raised.
- No receipt is emailed or texted to the payer automatically. The hosted checkout shows a receipt page at the end (unless
skip_receiptis set), and the checkout'ssuccess_emailemails the addresses the checkout request names, but sending the payer a receipt of their own is the integrator's to do. - On failure the contract moves to FAILING,
last_transactionrecords the attempt, the payment method moves to FAILING on a decline, and PAYMENT.FAILED, CONTRACT.UPDATE and ACCOUNT.UPDATE are raised. - The contract's
next_paymentis recalculated: the next retry date after a failure (cleared, withretry_completeset, once retries are exhausted), otherwise the due date of the next charge still in the future. The regular collection acts on that date next. - With
save_card, the card entered becomes a saved payment method on the account and the contract's payment method from now on (CONTRACT.UPDATE). - If the gateway requires 3DS or a hosted step the response carries a redirect URL and the payment completes when the customer returns from it; a gateway timeout leaves the transaction UNRESOLVED and it is settled one way or the other about ten minutes later.
Who can do this
- Roles: Admin only today; intended for Support as well, and being aligned. From the hosted checkout, no operator role applies.
- Admin app: permission
payment_contractand feature optionrecurring_editgate the control. - Permission keys (for clients managing permissions directly):
agreement,payment_contractor*on the client, or failing that on the contract's division, checked at the API before the request goes any further. - Checkout paths (
POST /c/api/checkoutthen the hosted checkout): the checkout's account session only; the checkout call itself needs whatever the caller's API session grants.
Related
Updated 33 minutes ago