Your first payment
Do this once by hand with cURL before writing any code. You’ll charge a test number, approve it on the phone, check the result and refund it.
Set these first. Use a verified test number from step 2.5:
export EIP=https://developers.ecocash.co.zw/sandbox/payment/v1
export EIP_AUTH="sbx_yourusername:yourpassword"
export MSISDN=263771234567 # your verified test number
export CORR=$(date +%s) # a unique clientCorrelator
4.1 Step 1: Charge the customer
curl -sS -X POST "$EIP/transactions/amount/" \
-u "$EIP_AUTH" \
-H 'Content-Type: application/json' \
-d '{
"clientCorrelator": "'"$CORR"'",
"notifyUrl": "",
"referenceCode": "ORDER-'"$CORR"'",
"tranType": "MER",
"endUserId": "'"$MSISDN"'",
"remarks": "Test payment",
"transactionOperationStatus": "Charged",
"paymentAmount": {
"charginginformation": { "amount": "2.00", "currency": "USD", "description": "Test payment" },
"chargeMetaData": { "channel": "WEB" }
},
"merchantCode": "287164",
"merchantPin": "1234",
"merchantNumber": "778503033",
"countryCode": "ZW",
"terminalID": "TERM001",
"location": "Harare",
"superMerchantName": "EcoCash Sandbox",
"merchantName": "Test Merchant"
}'
You get 200 OK with "status": "PENDING", which means the charge was accepted, not yet
paid. (The responses in this section are the portal’s documented examples, so their values
won’t match your request.)
{
"transactionId": "MP230422.1145.T0123456",
"clientCorrelator": "1774252612",
"status": "PENDING",
"statusCode": "200",
"amount": 2,
"currency": "USD",
"endUserId": "773047653",
"merchantCode": "001535",
"timestamp": "2024-04-22T11:45:30Z"
}
Save the transactionId. You need it to refund this payment.
4.2 Step 2: Approve on the phone
The test phone gets a USSD prompt. Enter a sandbox test PIN to choose the outcome:
| PIN | Outcome |
|---|---|
0000 |
✅ Successful payment |
1111 |
⚠️ Insufficient balance |
2222 |
❌ Invalid PIN |
9999 |
🚫 Transaction limit exceeded |
Use 0000 now. The merchant PIN in the request body (1234) never changes.
4.3 Step 3: Check the status
curl -sS "$EIP/$MSISDN/transactions/amount/$CORR" -u "$EIP_AUTH"
{
"transactionId": "MP230422.1145.T0123456",
"clientCorrelator": "1774252612",
"status": "SUCCESS",
"statusCode": "200",
"endUserId": "773047653",
"amount": 2,
"currency": "USD",
"merchantCode": "001535",
"merchantName": "UAT STORE 3",
"referenceCode": "TEST_1774252612",
"timestamp": "2024-04-22T11:45:30Z",
"description": "UAT STORE 3"
}
Repeat every few seconds until status is no longer PENDING. Sandbox transactions usually
resolve within 12–30 seconds. The phone also gets an SMS starting SANDBOX TEST:.
4.4 Step 4: Refund it
Refunds need a new clientCorrelator and the original EcoCash reference (the
transactionId from step 1). Only a SUCCESS payment can be refunded.
export REFUND_CORR=$(date +%s)
export ORIGINAL_REF=MP230422.1145.T0123456 # transactionId from step 1
curl -sS -X POST "$EIP/transactions/refund/" \
-u "$EIP_AUTH" \
-H 'Content-Type: application/json' \
-d '{
"clientCorrelator": "'"$REFUND_CORR"'",
"referenceCode": "REFUND-'"$REFUND_CORR"'",
"tranType": "REF",
"endUserId": "'"$MSISDN"'",
"originalEcocashReference": "'"$ORIGINAL_REF"'",
"remarks": "Customer refund",
"paymentAmount": {
"charginginformation": { "amount": "2.00", "currency": "USD", "description": "Refund" },
"chargeMetaData": { "channel": "WEB" }
},
"merchantCode": "287164",
"merchantPin": "1234",
"merchantNumber": "778503033",
"countryCode": "ZW",
"terminalID": "TERM001",
"location": "Harare",
"superMerchantName": "EcoCash Sandbox",
"merchantName": "Test Merchant"
}'
{
"transactionId": "RF230422.1200.R0123456",
"clientCorrelator": "1774252613",
"status": "SUCCESS",
"statusCode": "200",
"statusMessage": "Refund processed successfully",
"originalReference": "MP230422.1145.T0123456",
"amount": 2,
"currency": "USD",
"timestamp": "2024-04-22T12:00:15Z"
}
Done. You’ve run the full payment lifecycle. Now confirm three details, then build it into your app with the code examples.
4.5 Confirm three details in your first run
The portal’s pages disagree on three details. Your first sandbox run settles them. Keep each one as a single config value in your code (the examples in section 8 do) so you can switch it without a rewrite.
| Detail | Try first | If the sandbox rejects it |
|---|---|---|
amount format |
String with two decimals, "2.00" (what the Playground and SDK samples send) |
A JSON number, 2 (what the Documentation examples show) |
Refund tranType |
"REF" for a refund, "REV" for a reversal (the Documentation) |
"MER" plus a top-level "currencyCode" (what the Playground and SDK samples send) |
| Merchant values | Your Authentication tab’s Credential Reference set | The Documentation’s Test Data set (7.3) |
Background on each is in Known portal inconsistencies.
This page is generated from section 4 of the README in README.md. Spotted something wrong? Open an issue.