H5 C2B IntegrationStep 2: Create Order

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 to

Lower-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

FieldTypeRequiredDescription
timestampstring(13)UTC timestamp in seconds
nonce_strstring(32)Random alphanumeric string, max 32 chars
methodstringAlways "payment.preorder"
versionstringAlways "1.0"
sign_typestringAlways "SHA256WithRSA"
signstringSee Request Signature
biz_contentobjectOrder details (below)

biz_content fields

FieldTypeRequiredDescription
notify_urlstringWhere Telebirr POSTs the payment result
appidstringMerchant App ID
merch_codestringMerchant short code (6 digits)
merch_order_idstringYour order ID — ^[A-Za-z0-9]+$ only
trade_typestring"Checkout" for web payments
titlestringOrder description (no ~!#$%^* etc.)
total_amountstringAmount in ETB, up to 2 decimal places
trans_currencystringAlways "ETB"
timeout_expressstringPayment window, e.g. "120m" (1–120 min)
redirect_urlstringWhere to send customer after payment
callback_infostringPassed back verbatim in the notification

Response

{
  "result": "SUCCESS",
  "code": "0",
  "msg": "Success",
  "biz_content": {
    "merch_order_id": "1684481138534",
    "prepay_id": "007a6bd3175cdb3c658545a4f3f85fac23143239021"
  }
}