Skip to main content
This guide shows you how to compute the request signature, log in to obtain a session token, and make authenticated API calls — all in PHP with no external dependencies.

Computing the signature

Every request to the MIOeSIM API requires a sign parameter. Use the bpm_sign function below to compute it.
sign.php
<?php

function bpm_sign($data_ary) {
    if (!is_array($data_ary)) {
        return '';
    }

    $Sign_key = "1234567890qwertyuiopasdfghjklzxc";

    // Remove "sign" if already present — it must not be part of the input
    if (isset($data_ary['sign'])) {
        unset($data_ary['sign']);
    }

    // Format each parameter as "key=value"
    $ArrayList = [];
    foreach ($data_ary as $k => $v) {
        $ArrayList[] = $k . "=" . $v;
    }

    // Sort alphabetically and concatenate
    sort($ArrayList);
    $Buffer = implode('', $ArrayList);

    // URL-encode the concatenated string plus secret key, then MD5-hash it
    $encodeStr = customURLEncode($Buffer . $Sign_key);
    return strtoupper(hash('md5', $encodeStr));
}

function customURLEncode($string) {
    return str_replace(
        ['+',   '*',    '%7E'],
        ['%20', '%2A',  '~'],
        rawurlencode($string)
    );
}
The function:
  1. Removes sign from the array so it is never part of the input.
  2. Formats each remaining parameter as key=value and sorts them alphabetically.
  3. Concatenates the sorted strings, appends your secret key, and URL-encodes the result with customURLEncode.
  4. Returns the uppercase MD5 hex digest of the encoded string.

Why customURLEncode is needed

PHP’s rawurlencode encodes the string according to RFC 3986, but produces output that differs slightly from the encoding expected by the MIOeSIM signing algorithm:
Characterrawurlencode outputcustomURLEncode output
space+%20
**%2A
~%7E~
Always pass the pre-signature string through customURLEncode before hashing. Skipping this step produces an incorrect signature.
Never include your secret key in client-side code, public repositories, or logs. Treat it like a password.

Logging in

Call POST /api_order/login to exchange your phone number and password for a session token. The login request itself must include a valid sign.
login.php
<?php

function login($phonenumber, $password) {
    $params = [
        'phonenumber' => $phonenumber,
        'password'    => $password,
    ];
    $params['sign'] = bpm_sign($params);

    $ch = curl_init('https://bpm.mioesim.com/api_order/login');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));

    $response = curl_exec($ch);
    curl_close($ch);

    $data = json_decode($response, true);
    if ($data['code'] === 1) {
        return $data['data']['token'];
    }

    throw new RuntimeException('Login failed: ' . $data['message']);
}

$token = login('YOUR_PHONE_NUMBER', 'YOUR_PASSWORD');
echo "Token: " . $token . PHP_EOL;
A successful response returns a token in the data field:
{
  "code": 1,
  "message": "Successful",
  "data": {
    "token": "29281-9EFE5E410BEF5300DD15E3830BD65601"
  }
}
Pass the returned token to every subsequent API call.

Making authenticated API calls

After login, include both token and sign on every request. The example below calls GET /api_esim/getSkus to retrieve available eSIM packages.
get-skus.php
<?php

function getSkus($token) {
    $params = [
        'token' => $token,
    ];
    $params['sign'] = bpm_sign($params);

    $url = 'https://bpm.mioesim.com/api_esim/getSkus?' . http_build_query($params);

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

$skus = getSkus($token);
print_r($skus);
Build the parameter array with token first, compute sign from that array, then add sign to the array before appending it to the request URL.
Tokens are valid for 2 hours. Store the token and its issue time, then re-authenticate before the token expires rather than calling login on every request.
Replace 'YOUR_PHONE_NUMBER' and 'YOUR_PASSWORD' with your actual MIOeSIM account credentials before running the code.