{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"cb1dd19a-18ee-470c-914c-f52ad856e7f7","name":"MICROESIM OPEN API V1","description":"## MicroDrive Tech Co., Ltd **API V1.0**\n\n## 1、Interface descriptions\n\n- This document is provided by Microdrive Tech Co., Ltd and is only used for the technical connection of the partner.\n    \n- Please setup request header : Content-Type:application/json\n    \n- The interface uses UTF-8 encoding\n    \n- System time zone: UTC/GMT+08:00\n    \n- **Environment URLs:**\n    \n    - **Test Environment :**[<code>https://test.microesim.com</code>](https://test.microesim.com)\n        \n    - **Production Environment :** `https://www.microesim.top`\n        \n\n## 2、 Public request header\n\n- MICROESIM-ACCOUNT：Provided by Microesim\n    \n- MICROESIM-NONCE：Radom strings ,length 6-32 digits\n    \n- MICROESIM-TIMESTAMP：Timestamp (seconds), 13 digits long\n    \n- MICROESIM-SIGN：A signature generated using HMAC-SHA256 with the hashed password derived from the original secret and salt. Signature Content：`MICROESIM-ACCOUNT`, `MICROESIM-NONCE`, and `MICROESIM-TIMESTAMP`.\n    \n\n## 3、Authentication Process\n\n- Generate a random nonce string of 6-32 characters.\n    \n- Get the current timestamp in milliseconds.\n    \n- Use the provided secret key and salt to generate a hashed password using the PBKDF2 algorithm with SHA256.\n    \n- Concatenate `MICROESIM-ACCOUNT`, `MICROESIM-NONCE`, and `MICROESIM-TIMESTAMP` to form a string to be signed.\n    \n- Use the hashed password to generate the `MICROESIM-SIGN` signature using HMAC-SHA256.\n    \n- Include the generated `MICROESIM-ACCOUNT`, `MICROESIM-NONCE`, `MICROESIM-TIMESTAMP`, and `MICROESIM-SIGN` in the request headers.\n    \n\n## 4、Signature Generation Method\n\n``` javascript\nimport crypto from \"crypto\";\nimport fetch from \"node-fetch\";\nfunction toHex(buffer) {\n  return buffer.toString(\"hex\");\n}\nfunction pbkdf2ToHex(secret, saltHex, iterations, keyLen) {\n  const salt = Buffer.from(saltHex, \"hex\");\n  const derivedKey = crypto.pbkdf2Sync(secret, salt, iterations, keyLen, \"sha256\");\n  return toHex(derivedKey);\n}\nfunction hmacWithHexKey(data, hexKey) {\n  return crypto\n    .createHmac(\"sha256\", Buffer.from(hexKey, \"utf-8\"))\n    .update(data)\n    .digest(\"hex\");\n}\nasync function sendRequest() {\n  const account = \"your_account_here\";\n  const secret = \"your_secret_here\";\n  const saltHex = \"your_salt_hex_here\";\n  const nonce = Math.random().toString(36).substring(2, 18);\n  const timestamp = Date.now().toString();\n  const hexKey = pbkdf2ToHex(secret, saltHex, 1024, 32);\n  const data = account + nonce + timestamp;\n  const signature = hmacWithHexKey(data, hexKey);\n  const url = \"https://microesim.cn/allesim/v1/esimDataplanList\";\n  const headers = {\n    \"Content-Type\": \"application/json\",\n    \"MICROESIM-ACCOUNT\": account,\n    \"MICROESIM-NONCE\": nonce,\n    \"MICROESIM-TIMESTAMP\": timestamp,\n    \"MICROESIM-SIGN\": signature,\n  };\n  try {\n    const response = await fetch(url, { method: \"GET\", headers });\n    const result = await response.json();\n    console.log(\"Response status:\", response.status);\n    console.log(\"Response data:\", result);\n  } catch (error) {\n    console.error(\"Request failed:\", error);\n  }\n}\nsendRequest();\n\n ```\n\n``` python\nimport requests\nimport secrets\nimport time\nimport hmac\nimport hashlib\nimport binascii\nACCOUNT = \"your_account_here\"\nSECRET = \"your_secret_here\"\nSALT_HEX = \"your_salt_hex_here\"\nSALT = binascii.unhexlify(SALT_HEX)\nITERATIONS = 1024\nKEY_LENGTH = 32 \nnonce = secrets.token_hex(10)\ntimestamp = str(int(time.time() * 1000))\nhash_password = hashlib.pbkdf2_hmac(\n    'sha256',\n    SECRET.encode('utf-8'),\n    SALT,\n    ITERATIONS,\n    dklen=KEY_LENGTH\n)\ndata_to_sign = ACCOUNT + nonce + timestamp\nhash_password_hex = hash_password.hex()\nsignature = hmac.new(\n    hash_password_hex.encode('utf-8'),\n    data_to_sign.encode('utf-8'),\n    hashlib.sha256\n).hexdigest()\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"MICROESIM-ACCOUNT\": ACCOUNT,\n    \"MICROESIM-NONCE\": nonce,\n    \"MICROESIM-TIMESTAMP\": timestamp,\n    \"MICROESIM-SIGN\": signature\n}\nurl = \"https://microesim.cn/allesim/v1/esimDataplanList\"\nresponse = requests.get(url, headers=headers, timeout=10)\nprint(\"Signature:\", signature)\nprint(\"Response status:\", response.status_code)\nprint(\"Response text:\", response.text)\n\n ```\n\n``` java\nimport javax.crypto.Mac;\nimport javax.crypto.SecretKeyFactory;\nimport javax.crypto.spec.PBEKeySpec;\nimport javax.crypto.spec.SecretKeySpec;\nimport java.io.BufferedReader;\nimport java.io.InputStreamReader;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport java.nio.charset.StandardCharsets;\nimport java.security.spec.KeySpec;\nimport java.util.Random;\npublic class MicroEsimApiClient {\n    public static String pbkdf2Hex(String secret, byte[] salt, int iterations, int keyLength) throws Exception {\n        KeySpec spec = new PBEKeySpec(secret.toCharArray(), salt, iterations, keyLength * 8);\n        SecretKeyFactory factory = SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA256\");\n        byte[] key = factory.generateSecret(spec).getEncoded();\n        return bytesToHex(key);\n    }\n    public static String hmacSha256Hex(String data, String hexKey) throws Exception {\n        byte[] keyBytes = hexKey.getBytes(StandardCharsets.UTF_8);\n        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, \"HmacSHA256\");\n        Mac mac = Mac.getInstance(\"HmacSHA256\");\n        mac.init(secretKey);\n        byte[] hmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));\n        return bytesToHex(hmac);\n    }\n    public static String bytesToHex(byte[] bytes) {\n        StringBuilder sb = new StringBuilder();\n        for (byte b : bytes) {\n            sb.append(String.format(\"\u0002x\", b)); \n        }\n        return sb.toString();\n    }\n    public static String generateNonce(int length) {\n        String chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n        StringBuilder nonce = new StringBuilder();\n        Random random = new Random();\n        for (int i = 0; i < length; i++) {\n            nonce.append(chars.charAt(random.nextInt(chars.length())));\n        }\n        return nonce.toString();\n    }\n    private static byte[] hexStringToByteArray(String s) {\n        int len = s.length();\n        byte[] data = new byte[len / 2];\n        for (int i = 0; i < len; i += 2) {\n            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)\n                    + Character.digit(s.charAt(i + 1), 16));\n        }\n        return data;\n    }\n    public static void main(String[] args) throws Exception {\n        // 请替换成你自己的参数👇\n        String account = \"your_account_here\";\n        String secret = \"your_secret_here\";\n        String saltHex = \"your_salt_hex_here\";\n        byte[] salt = hexStringToByteArray(saltHex);\n        int iterations = 1024;\n        int keyLength = 32;\n        String nonce = generateNonce(16);\n        String timestamp = String.valueOf(System.currentTimeMillis());\n        String hexKey = pbkdf2Hex(secret, salt, iterations, keyLength);\n        String dataToSign = account + nonce + timestamp;\n        String signature = hmacSha256Hex(dataToSign, hexKey);\n        String urlStr = \"https://microesim.cn/allesim/v1/esimDataplanList\";\n        URL url = new URL(urlStr);\n        HttpURLConnection conn = (HttpURLConnection) url.openConnection();\n        conn.setRequestMethod(\"GET\");\n        conn.setRequestProperty(\"Content-Type\", \"application/json\");\n        conn.setRequestProperty(\"MICROESIM-ACCOUNT\", account);\n        conn.setRequestProperty(\"MICROESIM-NONCE\", nonce);\n        conn.setRequestProperty(\"MICROESIM-TIMESTAMP\", timestamp);\n        conn.setRequestProperty(\"MICROESIM-SIGN\", signature);\n        int responseCode = conn.getResponseCode();\n        System.out.println(\"Response Code: \" + responseCode);\n        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));\n        String inputLine;\n        StringBuilder response = new StringBuilder();\n        while ((inputLine = in.readLine()) != null) {\n            response.append(inputLine);\n        }\n        in.close();\n        System.out.println(\"Response Body: \" + response.toString());\n    }\n}\n\n ```\n\n``` php\n$account = \"your_account_here\";\n$secret = \"your_secret_here\";\n$saltHex = \"your_salt_hex_here\";\n$nonce = bin2hex(random_bytes(8));\n$timestamp = (string)round(microtime(true) * 1000);\n$key_bin = hash_pbkdf2(\"sha256\", $secret, hex2bin($saltHex), 1024, 32, true);\n$key_hex = bin2hex($key_bin);\n$dataToSign = $account . $nonce . $timestamp;\n$signature = hash_hmac(\"sha256\", $dataToSign, $key_hex);\n$url = \"https://microesim.cn/allesim/v1/esimDataplanList\";\n$headers = [\n    \"Content-Type: application/json\",\n    \"MICROESIM-ACCOUNT: $account\",\n    \"MICROESIM-NONCE: $nonce\",\n    \"MICROESIM-TIMESTAMP: $timestamp\",\n    \"MICROESIM-SIGN: $signature\"\n];\n$ch = curl_init();\ncurl_setopt($ch, CURLOPT_URL, $url);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, $headers);\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n$response = curl_exec($ch);\nif (curl_errno($ch)) {\n    echo \"Curl error: \" . curl_error($ch);\n} else {\n    echo \"Response:\\n$response\\n\";\n}\ncurl_close($ch);\n\n ```\n\n``` typescript\n// Postman Request Script\nconst CryptoJS = require('crypto-js');\nconst account = 'account';\nconst nonce = CryptoJS.lib.WordArray.random(10).toString(CryptoJS.enc.Hex);\nconst timestamp = new Date().getTime().toString();\nconst secret = 'secret';\nconst salt = CryptoJS.enc.Hex.parse('salt');\nconst iterations = 1024;\nconst keyLength = 256 / 32; \nlet hashPassword = CryptoJS.PBKDF2(secret, salt, {keySize: keyLength,iterations: iterations,hasher: CryptoJS.algo.SHA256}).toString(CryptoJS.enc.Hex);\nconst dataToHash = account + nonce + timestamp;\nconst signature = CryptoJS.HmacSHA256(dataToHash,hashPassword).toString(CryptoJS.enc.Hex);\nconsole.log(\"Generated Signature (Client): \" + signature); \npm.environment.set(\"MICROESIM-ACCOUNT\", account);\npm.environment.set(\"MICROESIM-SIGN\", signature);\npm.environment.set(\"MICROESIM-TIMESTAMP\", timestamp);\npm.environment.set(\"MICROESIM-NONCE\", nonce); \n\n ```\n\n## 5、 Interface summary\n\n- eSIM Data Plan List interface（/allesim/v1/esimDataplanList）\n    \n- eSIM New Order interface（/allesim/v1/esimSubscribe）\n    \n- Enquiry Topup Details interface （/allesim/v1/topupDetail）\n    \n- Enquiry Data Plan Details interface （/allesim/v1/deviceDetail）\n    \n- Enquiry Event Detail interface （/allesim/v1/eventDetail）\n    \n- Terminate interface （/allesim/v1/terminate）\n    \n\n## 6、 Flow Overview\n\n##### 1\\. Get eSIM Data Plan List\n\n- `GET /allesim/v1/esimDataplanList`\n    \n- or `GET /allesim/v1/esimDataplanListPage` (Recommended for large data)\n    \n\n##### 2\\. Subscribe eSIM\n\n- `POST /allesim/v1/esimSubscribe`\n    \n- Use `channel_dataplan_id` from Step 1\n    \n- Response returns `topup_id`\n    \n\n##### 3\\. Get Order Detail (Sync / Async)\n\n###### Option A: **Synchronous Query**\n\n- `POST /allesim/v1/topupDetail`\n    \n- Query order status by `topup_id`\n    \n- Client actively polls the order detail\n    \n\n###### Option B: **Asynchronous Callback**\n\n- `POST /allesim/v1/topupDetail-async`\n    \n- Client provides a callback URL in the request\n    \n- Server will **push order details** to the provided callback URL once the order status is updated\n    \n- In async mode, the client does not need to poll the order status; order details will be delivered via server callback.","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":true,"owner":"18073709","team":2691836,"collectionId":"cb1dd19a-18ee-470c-914c-f52ad856e7f7","publishedId":"2sAYBPkZmf","public":true,"publicUrl":"https://documenter-api.postman.tech/view/18073709/2sAYBPkZmf","privateUrl":"https://go.postman.co/documentation/18073709-cb1dd19a-18ee-470c-914c-f52ad856e7f7","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"documentationLayout":"classic-single-column","customisation":{"metaTags":[{"name":"description","value":""},{"name":"title","value":""}],"appearance":{"default":"system_default","themes":[{"name":"dark","logo":null,"colors":{"top-bar":"212121","right-sidebar":"303030","highlight":"FF6C37"}},{"name":"light","logo":null,"colors":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"}}]}},"version":"8.11.6","publishDate":"2024-11-16T02:46:08.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{"title":"","description":""},"logos":{"logoLight":null,"logoDark":null}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/d1fe7cc6e6bc2f0d4ad0962390b8012e6fd1d0d5d36b5b4cb0ef085f9b2dabfc","favicon":""},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://documenter.gw.postman.com/view/metadata/2sAYBPkZmf"}