api * 必要物品 1. signkey 2. encryptKey 3. encryptIV 4. APIURL --- * 加密範例(php版)(以取得遊戲連結為範例) ```php $signKey = '{signkey}'; $encryptKey = base64_decode('{encryptKey}'); $encryptIV = base64_decode('{encryptIV}'); // 代理識別碼 $agentCode = 1234; // GAME API 請求網址 $apiurl = 'http://{APIURL}/api/game'; $requestData = [ 'ns' => 'player', 'work' => 'forwardRecreation', 'version' => '0.0.1', 'data' => [ 'playerAccount' => 'test5566player', 'homeUrl' => 'www.nba.com', 'gameRuleUrl' => 'www.nba.com' ] ]; $content = json_encode($requestData); // 開始加密 $dataLen = strlen($content); $remainder = $dataLen % 16; if ($remainder != 0) { $content .= str_repeat(chr(0), 16 - $remainder); } $rawData = openssl_encrypt($content, 'AES-256-CBC', $encryptKey, OPENSSL_ZERO_PADDING, $encryptIV); // 製作簽名資料 $sign = openssl_digest($rawData . $signKey, 'sha512'); // 送出請求 header 需包含 Agent-Code 及 Sign $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $apiurl, CURLOPT_HEADER => false, CURLOPT_BINARYTRANSFER => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Agent-Code: ' . $agentCode, 'Sign: '. $sign, ], CURLOPT_POST => true, CURLOPT_POSTFIELDS => $rawData ]); $rawData = curl_exec($ch); curl_close($ch); ``` * 解密範例(php版) - api回應的資料作解密 ```php $signKey = '{signkey}'; $encryptKey = base64_decode('{encryptKey}'); $encryptIV = base64_decode('{encryptIV}'); // 從 response header 中取得簽名檔 $originSign = '我是簽名檔'; //API回傳header中的Sign $rawData = '我是加密後的資料';//API回傳的已加密資料 // 驗證簽名檔是否正確 $sign = openssl_digest($rawData . $signKey, 'sha512'); if ($sign != $originSign) { throw new Exceptin('簽名檔驗證錯誤'); } // 執行解密 $decryptData = trim(openssl_decrypt($rawData, 'AES-256-CBC', $encryptKey, OPENSSL_ZERO_PADDING, $encryptIV)); $responseData = json_decode($decryptData, true); ``` * 解密後結果 ``` ================== 最後結果 ================== 最後 $responseData 的值應如下 [ 'errorCode' => 0, 'message' => 'OK', 'url' => 'http://play.url?authToken=xxxxxxxxxxxxxxxxxxxx' ] ``` --- * 更多 歡迎提供其他版本的範例 : java / C# / golang / node-js 版 --- * 錯誤代碼 | errorCode| message | description | need you | | -------- | --------| -------- | -------- | | 0 | OK | nothing wrong | nothing | | 1001 | | 簽名驗證失敗 | 確認Sign簽名是否正確 | | 1002 | | server解密失敗 | 確認加密金鑰是否正確加密 | | 1004 | | agent key disabled | 請聯絡custom support| | 2001 | | ns field wrong format | 檢查ns欄位是否合法 | | 2002 | | work field | 檢查欄位的值內容是否合法 | | 2003 | | version field | 檢查欄位的值內容是否為0.0.1 | | 2004 | | playerAccount field | 檢查欄位的值內容是否合法 &長度是否合法 | | 2005 | | url format | 檢查欄位的值內容是否合法 | | 2006 | | nickname format | 檢查欄位的值內容是否合法 | | 2007 | | email format | 檢查欄位的值內容是否合法(RFC2822) | | 2008 | | billnumber format | 檢查欄位的值內容是否合法 , prefix is agentCode | | 2009 | | amount format | 檢查欄位的值內容是否合法, deposit only allow integer / withdraw allow integer & double | | 2010 | | time format | 檢查欄位的值內容是否合法, Y-m-d H:i:s | | 3001 | | not exist account | create first and then use it | | 3002 | | account already exist | duplicate create | | 3003 | | logout player failed | | | 3004 | | trial account over limit | | | 4001 | | transfer type not valid || | 4002 | | transfer balance should not equal zero. | check transfer balance | | 4003 | | lookup transfer record failed | check again or contact customer support | | 4004 | | player balance insufficient | check player balance | | 4005 | | transfer failed | try again or contact customer support | | 5001 | | start page | vaild : integer and >0 | | 5002 | | items each page | vaild: 100~2000 | | 6001 | | starttime not over or equal endtime | check starttime | | 6002 | | date only allow today - 30 days | check date| | 6003 | | time format range limit 24 hours | valid time format & range | | 8001 | | unknow service | check ns / work / version valid & work | | 8004 | | token expired | create new token | | 8009 | |game url not set | set game url | | 9999 | | others error | contact customer support | --- * FAQ 1. 若 Header中沒有傳入 名為Agent-Code, Sign 任一項的Header,則 Http 狀態碼回傳 401,錯誤訊息會放在 Header Message 裡 2. 利用 Header Agent-Code 取得系統中 Agent-Code 的相關資訊,若無法取得,則 Http 狀態碼回傳 401,錯誤訊息會放在 Header Message 裡簽名無效狀況 3. 確認1,2點皆無問題後,進行簽名驗證,若驗證失敗則回傳加密後的資料 errorCode=1001 => 解密失敗 4. 確認1,2,3點皆無問題後,進行資料解密,若失敗回傳加密後的資料 errorCode=1002 5. 請確認傳入的參數和值沒有多餘的空白 --- * JAVA版 ``` import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.Cipher import groovy.json.JsonBuilder JsonBuilder builder = new JsonBuilder() builder( { "ns" "player" "work" "createPlayer" "version" "0.0.1" "data" { "account" "abc1234567890" "nickname" "haabc1234567890" "email" "abc@test.com" } } ) def plainText = builder.toString() def encryptKey = encryptKey.decodeBase64() def ivSpec = encryptIV.decodeBase64() def cipher = Cipher.getInstance("AES/CBC/NoPadding") int blockSize = cipher.getBlockSize() byte[] dataBytes = plainText.getBytes() int length = dataBytes.length if (length % blockSize != 0) { length = length + (blockSize - (length % blockSize)); } byte[] newPlainText = new byte[length] System.arraycopy(dataBytes, 0, newPlainText, 0, dataBytes.length) SecretKeySpec key = new SecretKeySpec(encryptKey, "AES") cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivSpec)) def encryptedStr = cipher.doFinal(newPlainText).encodeBase64().toString() ```