Step 2: Create Order
Register your transaction with Telebirr and receive a prepay_id. You’ll need that ID to build the checkout URL in Step 3.
Library users: createCheckoutUrl() calls this internally — you never see the prepay_id unless you read it from the returned CheckoutResult ($result->getPrepayId() in PHP, result.prepayId in JS/TS). You can also call createOrder() directly if you need lower-level control.
The library way
High-level — one call does everything
$result = (new Telebirr($config))->createCheckoutUrl('Coffee x2', '45.00');
// $result->getMerchOrderId() — persist this against your order record
// $result->getPrepayId() — the prepay_id from Telebirr
// $result->getCheckoutUrl() — the URL to redirect the customer toLower-level — call createOrder directly
use Melaku\Telebirr\Telebirr;
use Melaku\Telebirr\Exceptions\ApiException;
use Melaku\Telebirr\Exceptions\InvalidParameterException;
$client = new Telebirr($config);
try {
$tokenInfo = $client->applyFabricToken();
$fabricToken = $tokenInfo['token'];
$order = $client->createOrder($fabricToken, 'Coffee x2', '45.00', null);
$prepayId = $order['biz_content']['prepay_id'];
$checkoutUrl = $client->buildCheckoutUrl($prepayId);
} catch (InvalidParameterException $e) {
error_log($e->getMessage());
} catch (ApiException $e) {
error_log("HTTP {$e->getHttpStatus()}, code {$e->getErrorCode()}: {$e->getMessage()}");
}⚠️
Merchant order ID rules: must be alphanumeric only — ^[A-Za-z0-9]+$. No underscores, hyphens, or dots. The library validates this and throws InvalidParameterException on invalid input rather than letting Telebirr return a cryptic error.
Raw API (all languages)
// You need: $fabricToken from Step 1, $config with your credentials
// You need: a Signer that does SHA256WithRSA — see Request Signature guide
$timestamp = (string) time();
$nonceStr = bin2hex(random_bytes(16));
$merchOrderId = time() . ''; // alphanumeric only!
$biz = [
'notify_url' => 'https://your-site.com/pay/notify',
'appid' => $merchantAppId,
'merch_code' => $merchantCode,
'merch_order_id' => $merchOrderId,
'trade_type' => 'Checkout',
'title' => 'Coffee x2',
'total_amount' => '45.00',
'trans_currency' => 'ETB',
'timeout_express' => '120m',
'redirect_url' => 'https://your-site.com/pay/return',
];
$req = [
'timestamp' => $timestamp,
'nonce_str' => $nonceStr,
'method' => 'payment.preorder',
'version' => '1.0',
'biz_content' => $biz,
];
// Sign ALL fields (including biz_content sub-fields) sorted by ASCII key order
$req['sign'] = signRequestObject($req);
$req['sign_type'] = 'SHA256WithRSA';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $baseUrl . '/payment/v1/merchant/preOrder',
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-APP-Key: ' . $fabricAppId,
'Authorization: ' . $fabricToken,
],
CURLOPT_POSTFIELDS => json_encode($req),
]);
$response = json_decode(curl_exec($ch), true);
$prepayId = $response['biz_content']['prepay_id'];Request parameters
Top-level
| Field | Type | Required | Description |
|---|---|---|---|
timestamp | string(13) | ✅ | UTC timestamp in seconds |
nonce_str | string(32) | ✅ | Random alphanumeric string, max 32 chars |
method | string | ✅ | Always "payment.preorder" |
version | string | ✅ | Always "1.0" |
sign_type | string | ✅ | Always "SHA256WithRSA" |
sign | string | ✅ | See Request Signature |
biz_content | object | ✅ | Order details (below) |
biz_content fields
| Field | Type | Required | Description |
|---|---|---|---|
notify_url | string | ✅ | Where Telebirr POSTs the payment result |
appid | string | ✅ | Merchant App ID |
merch_code | string | ✅ | Merchant short code (6 digits) |
merch_order_id | string | ✅ | Your order ID — ^[A-Za-z0-9]+$ only |
trade_type | string | ✅ | "Checkout" for web payments |
title | string | ✅ | Order description (no ~!#$%^* etc.) |
total_amount | string | ✅ | Amount in ETB, up to 2 decimal places |
trans_currency | string | ✅ | Always "ETB" |
timeout_express | string | ✅ | Payment window, e.g. "120m" (1–120 min) |
redirect_url | string | ○ | Where to send customer after payment |
callback_info | string | ○ | Passed back verbatim in the notification |
Response
{
"result": "SUCCESS",
"code": "0",
"msg": "Success",
"biz_content": {
"merch_order_id": "1684481138534",
"prepay_id": "007a6bd3175cdb3c658545a4f3f85fac23143239021"
}
}