Use a dedicated Merchi environment with a test store, a test client and a product that can be ordered. The examples use Bash, curl and jq. Set MERCHI_SANDBOX_API to the sandbox HTTPS origin, and use a session for that environment. Keep tokens and any checkout links in the test session.
Use the API quickstart to create a session and the workflow guide for request fields and response contracts.
The following path exercises Merchi’s simulated payment for a test cart when Stripe test keys are unavailable. Set MERCHI_DOMAIN_ID, MERCHI_CLIENT_ID and MERCHI_PRODUCT_ID to sandbox fixture IDs. Choose a product with a positive total and no mandatory variation fields, or include its required variation values.
set -euo pipefail
cart=$(curl --silent --show-error --fail-with-body \
"$MERCHI_SANDBOX_API/v6/carts/" \
--cookie "session_token=$MERCHI_SESSION_TOKEN" \
--data-urlencode 'isTest=true' \
--data-urlencode 'domain-count=1' \
--data-urlencode "domain-0-id=$MERCHI_DOMAIN_ID" \
--data-urlencode 'client-count=1' \
--data-urlencode "client-0-id=$MERCHI_CLIENT_ID")
cart_id=$(jq -er '.cart.id' <<<"$cart")
cart_token=$(jq -er '.cart.token' <<<"$cart")
jq -e '.cart.isTest == true' <<<"$cart" >/dev/null
item=$(curl --silent --show-error --fail-with-body \
"$MERCHI_SANDBOX_API/v6/cart_items/" \
--data-urlencode "cart_token=$cart_token" \
--data-urlencode 'cart-count=1' \
--data-urlencode "cart-0-id=$cart_id" \
--data-urlencode 'product-count=1' \
--data-urlencode "product-0-id=$MERCHI_PRODUCT_ID" \
--data-urlencode 'quantity=25')
jq -e '.cartItem.id' <<<"$item" >/dev/null
If the store requires shipping, add the receiver address and generate the cart’s shipment quotes before completing checkout. Check the selected quotes and final invoice amount against the configured shipment method.
checkout=$(curl --silent --show-error --fail-with-body \
"$MERCHI_SANDBOX_API/v6/carts/$cart_id/complete_test_payment/" \
--data-urlencode "cart_token=$cart_token")
invoice_id=$(jq -er '.invoice.id' <<<"$checkout")
jq -e '.invoice.isTest == true and .invoice.unpaid == false' \
<<<"$checkout" >/dev/null
curl --silent --show-error --fail-with-body --get \
"$MERCHI_SANDBOX_API/v6/invoices/$invoice_id/" \
--cookie "session_token=$MERCHI_SESSION_TOKEN" \
--data-urlencode 'embed={"owedMoney":{},"isCompletelyPaid":{}}' |
jq -e '.invoice.isCompletelyPaid == true and (.invoice.owedMoney | tonumber) == 0'
Use a session that can read the returned invoice for the final request. A repeat completion attempt returns an already-paid error. If the original request timed out, reload the cart or invoice and check its state before acting. If Stripe test keys are configured, the simulation endpoint returns 400. Follow the test-card flow for that environment instead.
Checkout fixture and paid invoice assertions · Simulation endpoint guards
Use separate fixtures for these scenarios. When using the API’s test suite, Stripe and carrier responses come from test doubles. Run provider-backed checks separately in the corresponding test environments.
| Scenario | Check |
|---|---|
| Quote approval | Create a quote for a test job and approve it with the invoice token. Re-read the invoice and check that the quote flag cleared. A decline keeps the quote state and saves the reason. |
| Repeated Stripe attempt | Start a wallet attempt, retry the same payment, and compare attempt IDs. Refresh a succeeded attempt twice and check for one payment record. A partial payment should leave the remaining balance open. |
| Duplicate signed webhook | Deliver the same signed event twice. Check the acknowledgement, then confirm that a single event is recorded and reconciliation creates one payment. An invalid signature should return 400. |
| Pending partial refund | Request a partial refund and keep its request key for retries. While pending, the recorded refunded amount stays unchanged. After success, re-read the invoice and compare the balance with the original payment minus the refund. |
| Draft change request | Upload a draft for a test job, then post a change-request comment as the client. Read the job and confirm its design state reflects the open request. Resolve the request, approve the current draft with an authorized session and verify its acceptance timestamp. |
| Carrier booking | Use an editable shipment with valid Australian addresses and test parcel dimensions. Verify that booking yields a carrier shipment ID and tracking number. Lodge it and check the carrier order ID. For a separate booking, void it before lodging and confirm that its booking identifiers are cleared. |
Stripe recovery fixtures · Draft change-request assertions · Carrier booking assertions
From an API checkout at the documented revision with its pinned SDK submodule and a disposable local test configuration, use the repository’s test helper.
./helpi test CartTestCheckoutSuite StripeWalletPaymentsSuite InvoiceQuoteSuite DraftingSuite EstimatesSuite AusPostShippingSuite
The suites exercise the API handlers and service behavior against fixture data. Their coverage includes paid test-cart invoices, quote permissions, repeated Stripe events, partial refund accounting, draft state transitions and carrier booking state. They do not simulate a real card entry or a carrier pickup.