文檔簡介
本文檔為 Pocker Mars Web API 接口使用說明,包括建立、登入、查詢玩家帳戶、跳轉遊戲、上分、下分的功能。
文檔版本歷史
| 版本 | 描述 | 日期 |
| 1.1.1 | 初版 | 2025.03.24 |
| 1.1.2 | 取得玩家投注記錄 api 新增總抽水比例、總抽水金額欄位 | 2025.05.27 |
重要說明
API
- 聯絡我們取得代理商的安全密鑰 ( Secret_key )
- 所有接口使用 POST 協議進行請求
- 傳輸內容, 一律使用 utf8 編碼
- 傳入與傳出皆為 Json 格式
- 發送命令需用 AES-256-CBC 加密處理
- 貨幣單位皆為 0.0001 ( 萬分之一 ),請參考 貨幣處理
發送命令時需將命令打包成如下的 Json 格式
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Code | string | 使用 base64 處理過的 iv + AES-256-CBC 密文, Secret_key = 代理商的安全密鑰 |
範例
{
"Agent_name": "DD00001",// 代理商別名
"Code": "qu90XJg6U8Te9kKikdPGnQFlL9YT90vssu9I5KpyXNWCLZN3/c4SQwJVUWMLrfJZQlpNiGaKpaQI7oLhXhIAW/eGMvbo7hsrikga/foE9cuFJGf6KeA9jAiDgJb1q9KSxtPXsSAgwIE0fdek8s8kJVamzw8MDIjJYMfAz8dTgOoAV9NerF3sP4vqPLQcfBw1" // 使用 base64 處理過的 iv + AES-256-CBC 密文, Secret_key = 代理商的安全密鑰
}
API 列表
請諮詢我們取得API網址
| url | 功能說明 | 更新日期 |
|---|---|---|
| /v2/agent/player_login | 玩家帳號登入(如果無此帳號,會新建立一個) | 2025/02/18 |
| /v2/agent/player_create | 建立玩家帳號 | 2025/02/18 |
| /v2/agent/player_transfer_in | 玩家錢包額度 轉入(上分) | 2025/02/18 |
| /v2/agent/player_transfer_out | 玩家錢包額度 轉出(下分) | 2025/02/18 |
| /v2/agent/get_game_url | 取得遊戲進入網址 | 2025/02/18 |
| /v2/agent/get_player_info | 取得玩家資訊 | 2025/02/18 |
| /v2/agent/get_bet_log | 取得玩家投注記錄 | 2025/02/18 |
| /v2/agent/get_profit_log | 取得其他營收記錄 | 2025/02/18 |
| /v2/agent/get_player_records | 查詢單一玩家上下分紀錄 | 2025/09/16 |
| /v2/agent/get_player_ledger_entries | 查詢單一玩家交易紀錄 | 2025/09/16 |
貨幣處理
調用 API 的參數中代表金額的欄位,單位皆為 0.0001 ( 萬分之一 ),例如轉入 1 元時 Amount 參數為 10000 。
加密
加密要求
所有的 API 服務在傳輸前都要求用 AES-256-CBC 加密和 MD5 Hash 進行數位簽名,以保證內容在傳輸過程中不會被修改。 請諮詢我們以下資訊:
- 安全密鑰 Secret_key
- 代理商別名 Agent_name
- API url
ASP.NET C# AES-256-CBC 加密函數範例
public static string EncryptAES256CBCByText(string data, string secretKey)
{
byte[] key = Encoding.UTF8.GetBytes(secretKey);
byte[] iv = new byte[16];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(iv);
}
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (var msEncrypt = new System.IO.MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(data);
}
byte[] encrypted = msEncrypt.ToArray();
string code = Convert.ToBase64String(iv.Concat(encrypted).ToArray());
return code;
}
}
}
}
PHP AES-256-CBC 加密函數範例
public static function encryptAES256CBCByText($data, $secretKey)
{
$key = $secretKey;
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
$encrypted = base64_encode($iv . $ciphertext);
return $encrypted;
}
Node.js AES-256-CBC 加密函數範例
function encryptAES256CBCByText(data, secretKey) {
const key = Buffer.from(secretKey, 'utf8');
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(data, 'utf8', 'base64');
encrypted += cipher.final('base64');
return Buffer.concat([iv, Buffer.from(encrypted, 'base64')]).toString('base64');
}
ASP.NET C# MD5 hash 函數範例
public static string GetMd5Hash(this string input)
{
using (MD5 md5 = MD5.Create())
{
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("x2"));
}
return sb.ToString();
}
}
PHP MD5 hash 函數範例
function getMd5Hash($input)
{
return md5($input);
}
Node.js MD5 hash 函數範例
function getMd5Hash(input) {
return crypto.createHash('md5').update(input).digest('hex');
}
加密流程
呼叫API舉例
以玩家帳號登入舉例
假設資料如下
- Agent_name : PM0122222
- Account : acc0001
- Timestamp : 1722913476
簽名為 Signature = Secret_key+Agent_name+Account+Timestamp 再轉 MD5 雜湊字串
假設 Secret_key 是 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Signature 為 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxPM0122222acc00011722912445 再轉 MD5 雜湊字串
組成傳入參數的 JSON 如下
{
"Agent_name": "PM0122222", // 代理商別名
"Account": "acc0001", // 玩家帳號(3~50碼全小寫英文字+數字)
"Timestamp": 1722913476, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "fcf9dc4001a3c35605cff438ea6f8562" // 簽名
}
input 字串再用 Secret_key 以 AES-256-CBC 加密後得到 code 的值,組合成最終的 http request body
{
"Agent_name": "PM0122222", // 代理商別名
"Code": "6/fvX2EdsA5pxLppI5q\u002BCEDZWWSrlplxHq9Idt\u002BuwXRADBOMUGCc28p9jiJUnRTP7y10pm0BohB5D2sY8pj2F8f7/M/Oj1100D9XlnKH1zO4oVQPDGFf3x0pJfO9h65xvjPUEFf1TU9Ac0gzB4jm6fsH98aYbTxaWH4BVOvxji09/wYnYd\u002BOm/hRHZkiVFJZ" // 使用 base64 處理過的 iv + AES-256-CBC 密文, Secret_key = 代理商的安全密鑰
}
POST 到 https://game.pokermars.com/api/v1/agent/player_login ( 請求內文必須使用 "Content-Type: application/json" 格式 )
得到返回結果
{
"Error_code": 1, // 錯誤碼
"Msg": "成功", // 訊息
"Token": "7057049464837" // 玩家登入遊戲專用的Token
}
錯誤處理
當解密、簽名不正確時,返回結果會輸出以下錯誤回應。
Error_code -10 解密失敗
Error_code -105 Json 解碼失敗
Error_code -125 簽名驗證失敗
解密(單一錢包API用)
解密要求
安全起見, 單一錢包 API 的內文經過加密,因此收到需求後須進行解密才得到真實內容。 解密與加密邏輯一致,使用一樣的安全密鑰與代理商別名。API url 則由代理商提供。
- 安全密鑰 Secret_key
- 代理商別名 Agent_name
- API url 由代理商提供
ASP.NET C# AES-256-CBC 解密函數範例
public static string DecryptAES256CBC(string encryptContent, string secretKey)
{
byte[] fullCipher = Convert.FromBase64String(encryptContent);
byte[] key = Encoding.UTF8.GetBytes(secretKey);
byte[] iv = fullCipher.Take(16).ToArray();
byte[] cipherText = fullCipher.Skip(16).ToArray();
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (var msDecrypt = new System.IO.MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
return srDecrypt.ReadToEnd();
}
}
}
}
}
PHP AES-256-CBC 解密函數範例
public static function decryptAES256CBCByText($encryptedData, $secretKey)
{
$key = $secretKey;
$decoded = base64_decode($encryptedData);
$iv = substr($decoded, 0, 16);
$ciphertext = substr($decoded, 16);
$decrypted = openssl_decrypt($ciphertext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
return $decrypted;
}
Node.js AES-256-CBC 解密函數範例
const crypto = require('crypto');
function decryptAES256CBCByText(encryptedData, secretKey) {
const key = Buffer.from(secretKey, 'utf8');
const decodedData = Buffer.from(encryptedData, 'base64');
const iv = decodedData.subarray(0, 16);
const encryptedText = decodedData.subarray(16);
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(encryptedText, 'base64', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
解密流程
API 請求流程範例
取得玩家餘額範例
假設收到的 API request body 如下
{
"Agent_name": "PM0120001", // 代理商別名
"Code": "RVZ5abDsWReqa1FDypByadrHPFzSXmEevM0fdWWiYtCxL5ZdWwKcygfo\u002BWPzSfe0Xm2xylaWn7CgeXTeU3EspL
bQM/pXENHWrxZxXD9Tcveaszmhhk88ZwkIb3egBm7/3Obh3eHdpDiZSfbeTq91VQ==" // 使用 base64 處理過的 iv + AES-256-CBC 密文, Secret_key = 代理商的安全密鑰
}
對參數 code 字串進行解密, 得到內文參數物件
{
"Account": "singleaccount001",
"Timestamp": 1741758634,
"Signature": "a11f0141bf5f28869b02d60d540947b2"
}
檢查其簽名 ( Signature ) 欄位,是否符合約定的簽名邏輯
簽名驗證成功則返回玩家餘額 API response
{
"Data": {
"account": "singleaccount001",
"balance": 10000000,
"currency": 1
},
"Error_code": 1,
"Msg": ""
}
錯誤處理
當解密、簽名不正確時,返回結果會輸出以下錯誤回應。
Error_code -10 解密失敗
Error_code -105 Json 解碼失敗
Error_code -125 簽名驗證失敗
遊戲 API
玩家登入遊戲流程
建立玩家帳號
- API 名稱 /v2/agent/player_create
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Account | string(50) | 玩家帳號(3~50碼全小寫英文字+數字) |
| Nickname | string(40) | 暱稱 |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+agent_name+account+nickname+timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Token | string | 玩家登入遊戲專用的Token |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Account": "account001", // 玩家帳號(3~50碼全小寫英文字+數字)
"Nickname": "account001", // 暱稱
"Timestamp": 1722918019, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "7a6d69a4bcb732506b36fc0231fa15a1" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Token": "7057049464837" // 玩家登入遊戲專用的Token
}
玩家帳號登入
- API 名稱 /v2/agent/player_login
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Account | string(50) | 玩家帳號(3~50碼全小寫英文字+數字) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Account+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Token | string | 玩家登入遊戲專用的Token |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Account": "account001", // 玩家帳號(3~50碼全小寫英文字+數字)
"Timestamp": 1722918019, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "7a6d69a4bcb732506b36fc0231fa15a1" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Token": "7057049464837" // 玩家登入遊戲專用的Token
}
取得遊戲進入網址
- API 名稱 /v2/agent/get_game_url
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Account | string(50) | 玩家帳號(3~50碼全小寫英文字+數字) |
| Lang | string(10) |
語言設定
en 英文
zh 簡體中文
zh-TW 繁體中文
tl 菲律賓語
th 泰文
vi 越南文
id 印尼文
pt 葡萄牙文 (巴西)
es 西班牙文
|
| Return_url | string | 遊戲退出轉跳網址(例:https://www.abc.com)(使用base64url編碼) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Account+Return_url+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Game_url | string | 遊戲進入網址 |
傳入參數 範例
{
"Agent_name": "PM0122222", // 代理商別名
"Account": "acc0001", // 玩家帳號(3~50碼全小寫英文字+數字)
"Lang":"en", // 語言設定
"Return_url": "aHR0cDovLzE5Mi4xNjguMS4yMDI6ODA4MA", // 遊戲退出轉跳網址(例:https://www.abc.com)(使用base64url編碼)
"Timestamp": 1722929138, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "9aa963d0a21907eaa25f5daddb1dcfe7" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Game_url": "60.251.230.110/PokerDream/?token=7061713551368&return_url=aHR0cDovLzE5Mi4xNjguMS4yMDI6ODA4MA" // 遊戲進入網址
}
取得玩家資訊
- API 名稱 /v2/agent/get_player_info
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Account | string(50) | 玩家帳號(3~50碼全小寫英文字+數字) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Account+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Player_info | any |
玩家資訊結構, 下面僅列出對代理商有用的資訊
CLIENT_UID=玩家在Client端看到的UID
TOKEN_p=玩家登入專用的口令
ACCOUNT_p=玩家帳號
NICKNAME_p=玩家暱稱
GOLD_p[0]=測試幣
GOLD_p[1]=正式幣
GOLD_p[2]=泥碼
GOLD_p[3]=鑽石
PHOTO_URL_p=頭像的url
COUNTRY_CODE_p=國碼(例如TW)
|
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Account": "account001", // 玩家帳號(3~50碼全小寫英文字+數字)
"Timestamp": 1722918019, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "7a6d69a4bcb732506b36fc0231fa15a1" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "成功", // 訊息
"Player_info": { // 玩家資訊結構, 下面僅列出對代理商有用的資訊
"GOLD_p": [
20000000, // GOLD_p[0]=測試幣
60000, // GOLD_p[1]=正式幣
0, // GOLD_p[2]=泥碼
0 // GOLD_p[3]=鑽石
]
}
}
取得玩家投注記錄
- API 名稱 /v2/agent/get_bet_log
- 請求協議 POST
-
注意事項
- 1.每個小時不能超過60次請求
- 3.開始時間必須小於結束時間
- 4.開始時間和結束時間間隔不能超過12個小時
- 5.最多獲取距離今天往前推十天內的數據(以日為單位)
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Start_timestamp | int64 | 查詢的起始點戳記(UTC秒數) |
| End_timestamp | int64 | 查詢的結束點戳記(UTC秒數) |
| Search_page | int32 | 查詢的頁數 預設 第0頁 |
| Search_count | int32 | 查詢的數量(單次上限最多1000筆) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Start_timestamp+End_timestamp+Search_page+Search_count+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Total_count | int32 | 總筆數 |
| Page_no | int32 | 查詢頁碼 |
| Page_size | int32 | 該頁數量 |
| Bet_log | array | 投注記錄 |
Bet_log
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Bet_id | string | 注單號 |
| Account | string | 玩家帳號 |
| Date_time | int64 | 牌局結束時間 時間戳記 (UTC秒數) |
| Round_id | string | 牌局ID |
| Game_name | string | 玩法 |
| Gold_add | int64 | 玩家輸贏 |
| Pots | int64 | 底池總金額(單位0.0001) |
| Bets | int64 | 壓注總金額(單位0.0001) |
| Hands_card | string | 手牌 |
| Board_card_0 | string | 公牌 0 |
| Board_card_1 | string | 公牌 1 |
| Board_card_2 | string | 公牌 2 |
| EV_revenue | int64 | EV 盈虧 |
| EV_split | int64 | EV分成比例 |
| Rake_gold | int64 | 玩家該局抽水 |
| Rake_split | int64 | 抽水分成比例 |
| Start_Date_time | int64 | 牌局開始時間 |
| Rake | int64 | 總抽水比例(玩家該局抽水比例) |
| Rake_amount | int64 | 總抽水金額(玩家該局實際被抽的總金額) |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Start_timestamp": 1729440000, // 查詢的起始點戳記(UTC秒數)
"End_timestamp": 1729461600, // 查詢的結束點戳記(UTC秒數)
"Search_page": 0, // 查詢的頁數 預設 第0頁
"Search_count": 1, // 查詢的數量(單次上限最多1000筆)
"Timestamp": 1729569008, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "cf0d2ed789096f9f8abd25de34a249a6" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Total_count": 52372, // 總筆數
"Page_no": 0, // 查詢頁碼
"Page_size": 1, // 該頁數量
"Bet_log": [ // 投注記錄
{
"Bet_id": "169872366254559232", // 注單號
"Account": "aubree85", // 玩家帳號
"Date_time": 1748301365, // 牌局結束時間
"Round_id": "4_1790260575989", // 牌局ID
"Game_name": "AoF-NLH", // 玩法
"Gold_add": -15869575, // 玩家輸贏
"Pots": 33069150, // 底池總金額(單位0.0001)
"Bets": 15869575, // 壓注總金額(單位0.0001)
"Hands_card": "10,61", // 手牌
"Board_card_0": "26,24,51,67,64", // 公牌-1
"Board_card_1": "", // 公牌-2
"Board_card_2": "", // 公牌-3
"EV_revenue": 0, // EV 盈虧
"EV_split": 10000, // EV分成比例
"Rake_gold": 793478, // 玩家該局抽水
"Rake_split": 10000 // 抽水分成比例
"Start_Date_time": 1748301343, // 牌局開始時間
"Rake": 500, // 總抽水比例(玩家該局抽水比例)
"Rake_amount": 793478 // 總抽水金額(玩家該局實際被抽的總金額)
}
]
}
取得其他營收記錄
- API 名稱 /v2/agent/get_profit_log
- 請求協議 POST
-
注意事項
- 1.每個小時不能超過60次請求
- 3.開始時間必須小於結束時間
- 4.開始時間和結束時間間隔不能超過12個小時
- 5.最多獲取距離今天往前推十天內的數據(以日為單位)
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Start_timestamp | int64 | 查詢的起始點戳記(UTC秒數) |
| End_timestamp | int64 | 查詢的結束點戳記(UTC秒數) |
| Search_page | int32 | 查詢的頁數 預設 第0頁 |
| Search_count | int32 | 查詢的數量(單次上限最多1000筆) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Start_timestamp+End_timestamp+Search_page+Search_count+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Total_count | int32 | 總筆數 |
| Page_no | int32 | 查詢頁碼 |
| Page_size | int32 | 該頁數量 |
| Profit_log | array | 其他營收記錄 |
Profit_log
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Order_id | string | 訂單號碼 |
| Account | string | 玩家帳號 |
| Cause | int32 | 牌局ID |
| Shop_revenue | int64 | 商城收益 |
| Shop_split | int64 | 商城分成比例 |
| Host_withdrawal | int64 | 房主提領 |
| Deposit | int64 | 上分 |
| Withdrawal | int64 | 下分 |
| Date_time | int64 | 交易時間 |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Start_timestamp": 1729440000, // 查詢的起始點戳記(UTC秒數)
"End_timestamp": 1729461600, // 查詢的結束點戳記(UTC秒數)
"Search_page": 0, // 查詢的頁數 預設 第0頁
"Search_count": 1, // 查詢的數量(單次上限最多1000筆)
"Timestamp": 1729569008, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "cf0d2ed789096f9f8abd25de34a249a6" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Total_count": 52372, // 總筆數
"Page_no": 0, // 查詢頁碼
"Page_size": 1, // 該頁數量
"Profit_log": [ // 其他營收記錄
{
"Order_id": "s134758880470241280", // 訂單號碼
"Account": "skyray17", // 玩家帳號
"Cause": 5, // 交易類型
"Shop_revenue": 39920, // 商城收益
"Shop_split": 5000, // 商城分成比例
"Host_withdrawal": 0, // 房主提領
"Deposit": 0, // 上分
"Withdrawal": 0, // withdrawal
"Date_time": 1739929539 // 交易時間
}
]
}
查詢單一玩家上下分紀錄
- API 名稱 /v2/agent/get_player_records
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Order_id | string | 訂單號碼 |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Order_id+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Account | string | 玩家帳號 |
| Order_id | string | 訂單號碼 |
| Cause | int32 | 交易類型 |
| Gold_add | int64 | 交易金額(單位0.0001) |
| Date_time | int32 | 交易時間 |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Order_id": "202508221626370001", // 訂單號碼
"Timestamp": 1729569008, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "cf0d2ed789096f9f8abd25de34a249a6" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Account": "skyray17", // 玩家帳號
"Order_id": "202508221626370001", // 訂單號碼
"Cause": 1, // 交易類型
"Gold_add": 500000, // 交易金額(單位0.0001)
"Date_time": 1739929539 // 交易時間
}
查詢單一玩家交易紀錄
- API 名稱 /v2/agent/get_player_ledger_entries
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Account | string | 玩家帳號 |
| Start_timestamp | int64 | 查詢的起始點戳記(UTC秒數) |
| End_timestamp | int64 | 查詢的結束點戳記(UTC秒數) |
| Search_page | int32 | 查詢的頁數 預設 第0頁 |
| Search_count | int32 | 查詢的數量(單次上限最多1000筆) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Start_timestamp+End_timestamp+Search_Page+Search_Count+Timestamp+Account
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Account | string | 玩家帳號 |
| Total_count | int32 | 總筆數 |
| Page_no | int32 | 查詢頁碼 |
| Page_size | int32 | 該頁數量 |
| Ledger_entries_log | array | 單一玩家交易紀錄 |
Ledger_entries_log
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Cause | int32 | 交易類型 |
| Gold_old | int64 | 交易前餘額(單位0.0001) |
| Gold_add | int64 | 交易金額(單位0.0001) |
| Gold_new | int64 | 交易後餘額(單位0.0001) |
| Gold_type | int64 | 幣種 |
| Order_id | string | 訂單號碼 |
| Date_time | int64 | 交易時間 |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Account": "skyray17", // 玩家帳號
"Start_timestamp": 1729569008, // 查詢的起始點戳記(UTC秒數)
"End_timestamp": 1729569008, // 查詢的結束點戳記(UTC秒數)
"Search_page": 0, // 查詢的頁數 預設 第0頁
"Search_count": 1, // 查詢的數量(單次上限最多1000筆)
"Timestamp": 1729569008, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "cf0d2ed789096f9f8abd25de34a249a6" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Account": "skyray17", // 玩家帳號
"Total_count": 2, // 總筆數
"Page_no": 0, // 查詢頁碼
"Page_size": 1000, // 該頁數量
"Ledger_entries_log": [ // 單一玩家交易紀錄
{
"Cause": 1, // 交易類型
"Gold_old": 0, // 交易前餘額(單位0.0001)
"Gold_add": 5000, // 交易金額(單位0.0001)
"Gold_new": 5000, // 交易後餘額(單位0.0001)
"Gold_type": 1, // 幣種
"Order_id": "202508221626370001", // 訂單號碼
"Date_time": 1739929539 // 交易時間
},
{
"Cause": 1, // 交易類型
"Gold_old": 5000, // 交易前餘額(單位0.0001)
"Gold_add": 5000, // 交易金額(單位0.0001)
"Gold_new": 10000, // 交易後餘額(單位0.0001)
"Gold_type": 1, // 幣種
"Order_id": "202508221626370001", // 訂單號碼
"Date_time": 1755851203 // 交易時間
}
]
}
查詢錦標賽賽事盈虧紀錄
- API 名稱 /v2/agent/get_cup_agent_profit_log
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Start_timestamp | int64 | 查詢的起始點戳記(UTC秒數) |
| End_timestamp | int64 | 查詢的結束點戳記(UTC秒數) |
| Search_page | int32 | 查詢的頁數 預設 第0頁 |
| Search_count | int32 | 查詢的數量(單次上限最多1000筆) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Start_timestamp+End_timestamp+Search_Page+Search_Count+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Total_count | int32 | 總筆數 |
| Page_no | int32 | 查詢頁碼 |
| Page_size | int32 | 該頁數量 |
| Cup_list | array | 賽事盈虧紀錄 |
Cup_list
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Cup_id | int32 | 賽事編號 |
| Cup_name | string | 錦標賽名稱 |
| Start_time | int64 | 錦標賽上線時間(UTC秒數) |
| End_time | int64 | 錦標賽結束時間(UTC秒數) |
| Cup_type_name | string | 賽事類別名稱 |
| Server_name | string | 遊戲名稱:NLH, 6+, PLO, AoF-NLH, AoF-PLO |
| Max_seat | int32 | 牌桌人數 |
| Register_gold | int64 | 報名費 |
| Join_ppl | int32 | 代理玩家報名人數 |
| All_player | int32 | 總報名人數 |
| Buy_in_ppl | int32 | 代理玩家報名次數 |
| Total_buy_in_ppl | int32 | 所有玩家報名次數 |
| Rebuy_in_ppl | int32 | 代理玩家重複報名次數 |
| Contribution | int32 | 貢獻度 |
| Total_gold | int64 | 總報名費(單位0.0001) |
| Total_bonus | int64 | 總獎金(單位0.0001) |
| Total_actual_bonus | int64 | 總獎金實收(單位0.0001) |
| Min_bonus | int64 | 保底獎金(單位0.0001) |
| Prize_pool_rake | int32 | 獎金池比例 |
| Rake | int32 | 錦標賽代理抽水比例 |
| Cup_service_rake | int32 | 盤口費比例 |
| Cup_service_fee | int64 | 盤口費(單位0.0001) |
| Promo_rake | int32 | 促銷費比例 |
| Promo_fee | int64 | 促銷費(單位0.0001) |
| Game_provider_rake | int32 | 遊戲商分成比例 |
| Game_provider_amount | int64 | 遊戲商分成收益(單位0.0001) |
| Master_split_rake | int32 | 總代理拆帳比例 |
| Master_agent_income | int64 | 總代理收益(單位0.0001) |
| Gold_split | int32 | 代理拆帳比例 |
| Agent_income | int64 | 代理收益(單位0.0001) |
| Agent_payout | int64 | 代理支出(單位0.0001) |
| Agent_actual_bonus | int64 | 代理盈虧金額(單位0.0001) |
| Game_dev_income | int64 | 遊戲商收益 |
| Is_overlay | bool | 是否破保 |
| Overlay_amount | int64 | 破保金額 |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Start_timestamp": 1729569008, // 查詢的起始點戳記(UTC秒數)
"End_timestamp": 1729569008, // 查詢的結束點戳記(UTC秒數)
"Search_page": 0, // 查詢的頁數 預設 第0頁
"Search_count": 1, // 查詢的數量(單次上限最多1000筆)
"Timestamp": 1729569008, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "cf0d2ed789096f9f8abd25de34a249a6" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Total_count": 1, // 總筆數
"Page_no": 0, // 查詢頁碼
"Page_size": 1000, // 該頁數量
"Cup_list": [ // 賽事盈虧紀錄
{
"Cup_id": 213133117, // 賽事編號
"Cup_name": NLH TEST10, // 錦標賽名稱
"Start_time": 1739929539, // 錦標賽上線時間(UTC秒數)
"End_time": 1739929539, // 錦標賽結束時間(UTC秒數)
"Cup_type_name": 常規賽, // 賽事類別名稱
"Server_name": "NLH", // 遊戲名稱:NLH, 6+, PLO, AoF-NLH, AoF-PLO
"Max_seat": 6, // 牌桌人數
"Register_gold": 1000000, // 報名費
"Join_ppl": 25, // 代理玩家報名人數
"All_player": 33, // 總報名人數
"Buy_in_ppl": 25, // 代理玩家報名次數
"Total_buy_in_ppl": 33, // 所有玩家報名次數
"Rebuy_in_ppl": 0, // 代理玩家重複報名次數
"Contribution": 75, // 貢獻度
"Total_gold": 25000000, // 總報名費(單位0.0001)
"Total_bonus": 23000000, // 總獎金(單位0.0001)
"Total_actual_bonus": 22655000, // 總獎金實收(單位0.0001)
"Min_bonus": 50000000, // 保底獎金(單位0.0001)
"Prize_pool_rake": 92, // 獎金池比例
"Rake": 6, // 錦標賽代理抽水比例
"Cup_service_rake": 2, // 盤口費比例
"Cup_service_fee": 2, // 盤口費(單位0.0001)
"Promo_rake": 1.5, // 促銷費比例
"Promo_fee": 2, // 促銷費(單位0.0001)
"Game_provider_rake": 2, // 遊戲商分成比例
"Game_provider_amount": 2, // 遊戲商分成收益(單位0.0001)
"Master_split_rake": 3, // 總代理拆帳比例
"Master_agent_income": 45000, // 總代理收益(單位0.0001)
"Gold_split": 97, // 代理拆帳比例
"Agent_income": 1455000, // 代理收益(單位0.0001)
"Agent_payout": 0, // 代理支出(單位0.0001)
"Agent_actual_bonus": 1455000, // 代理盈虧金額(單位0.0001)
"Game_dev_income": 8450000, // 遊戲商收益
"Is_overlay": false, // 是否破保
"Overlay_amount": 25000000, // 破保金額
}
]
}
查詢錦標賽賽事個人盈虧
- API 名稱 /v2/agent/get_cup_player_profit_log
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Cup_id | int32 | 賽事編號 |
| Search_page | int32 | 查詢的頁數 預設 第0頁 |
| Search_count | int32 | 查詢的數量(單次上限最多1000筆) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Cup_id+Search_Page+Search_Count+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Cup_id | int32 | 賽事編號 |
| Total_count | int32 | 總筆數 |
| Page_no | int32 | 查詢頁碼 |
| Page_size | int32 | 該頁數量 |
| Cup_player_list | array | 玩家賽事盈虧紀錄 |
Cup_player_list
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Cup_id | int32 | 賽事編號 |
| Cup_name | string | 錦標賽名稱 |
| Type_name | string | 賽事類別名稱 |
| Start_time | int64 | 錦標賽上線時間(UTC秒數) |
| End_time | int64 | 錦標賽結束時間(UTC秒數) |
| Server_name | string | 遊戲名稱:NLH, 6+, PLO, AoF-NLH, AoF-PLO |
| Max_seat | int32 | 牌桌人數 |
| Client_uid | int64 | 玩家uid |
| Client_nickname | string | 暱稱 |
| Ticket_id | int32 | 門票ID |
| Ticket_num | int32 | 門票張數 |
| Register_gold | int64 | 報名費 |
| Buy_time | int32 | 買入次數 |
| Buy_gold | int64 | 總報名費(單位0.0001) |
| All_round | int32 | 手牌數 |
| Bonus_gold | int64 | 獎金(單位0.0001) |
| Profit_gold | int64 | 盈虧(單位0.0001) |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Cup_id": "213133117", // 賽事編號
"Search_page": 0, // 查詢的頁數 預設 第0頁
"Search_count": 1, // 查詢的數量(單次上限最多1000筆)
"Timestamp": 1729569008, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "cf0d2ed789096f9f8abd25de34a249a6" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Cup_id": 213133117, // 賽事編號
"Total_count": 1, // 總筆數
"Page_no": 0, // 查詢頁碼
"Page_size": 1000, // 該頁數量
"Cup_player_list": [ // 玩家賽事盈虧紀錄
{
"Cup_id": 213133117, // 賽事編號
"Cup_name": NLH TEST10, // 錦標賽名稱
"Type_name": 常規賽, // 賽事類別名稱
"Start_time": 1739929539, // 錦標賽上線時間(UTC秒數)
"End_time": 1739929539, // 錦標賽結束時間(UTC秒數)
"Server_name": "NLH", // 遊戲名稱:NLH, 6+, PLO, AoF-NLH, AoF-PLO
"Max_seat": 6, // 牌桌人數
"Client_uid": 1358, // 玩家uid
"Client_nickname": "sydney89906", // 暱稱
"Ticket_id": 0, // 門票ID
"Ticket_num": 0, // 門票張數
"Register_gold": 1000000, // 報名費
"Buy_time": 1, // 買入次數
"Buy_gold": 1000000, // 總報名費(單位0.0001)
"All_round": 2, // 手牌數
"Bonus_gold": 0, // 獎金(單位0.0001)
"Profit_gold": -1000000 // 盈虧(單位0.0001)
}
]
}
查詢賽事列表
- API 名稱 /v2/agent/get_tournament
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Start_timestamp | int64 | 查詢的起始點戳記(UTC秒數) |
| End_timestamp | int64 | 查詢的結束點戳記(UTC秒數) |
| Lang_key | int32 | 語系對應參數 1:英文 2:繁體中文 |
| Search_page | int32 | 查詢的頁數 預設 第0頁 |
| Search_count | int32 | 查詢的數量(單次上限最多1000筆) |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Start_timestamp+End_timestamp+Search_Page+Search_Count+Timestamp+Lang_key
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Total_count | int32 | 總筆數 |
| Page_no | int32 | 查詢頁碼 |
| Page_size | int32 | 該頁數量 |
| Tournament_log | array | 賽事列表 |
Tournament_log
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Cup_id | int32 | 賽事編號 |
| Cup_rule | Cup_rule_lang_struct | 錦標賽語言結構 |
| Ticket_gold | int64 | 報名費(單位0.0001) |
| Total_bonus | int64 | 總獎金(單位0.0001) |
| All_player | int32 | 總報名人數 |
| All_play_sec | int32 | 錦標賽已進行了多久(秒數) |
| Event_time | int64 | 本屆錦標賽的開賽時間(UTC秒數) |
| End_time | int64 | 本屆錦標賽的結束時間(UTC秒數) |
Cup_rule_lang_struct
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Lang_key | string | 語系代碼,例如 zh-TW |
| Name_p | string | 錦標賽名稱 |
| Note_p | string | 錦標賽說明 |
| Tag_p | Object<string, number> | 賽事標籤 |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Start_timestamp": 1729569008, // 查詢的起始點戳記(UTC秒數)
"End_timestamp": 1729569008, // 查詢的結束點戳記(UTC秒數)
"Lang_key": 2, // 語系對應參數 1:英文 2:繁體中文
"Search_page": 0, // 查詢的頁數 預設 第0頁
"Search_count": 1, // 查詢的數量(單次上限最多1000筆)
"Timestamp": 1729569008, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "cf0d2ed789096f9f8abd25de34a249a6" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Total_count": 1, // 總筆數
"Page_no": 0, // 查詢頁碼
"Page_size": 1000, // 該頁數量
"Tournament_log": [ // 賽事列表
{
"Cup_id": 213638245, // 賽事編號
"Cup_rule": { // 錦標賽語言結構
"Lang_key": "zh-TW", // 語系代碼,例如 zh-TW
"Name_p": "NLH TEST34", // 錦標賽名稱
"Note_p": 常規賽, // 錦標賽說明
"Tag_p": {"Test":1,"Free":1} // 賽事標籤
},
"Ticket_gold": 100000, // 報名費(單位0.0001)
"Total_bonus": 50000000, // 總獎金(單位0.0001)
"All_player": 98, // 總報名人數
"All_play_sec": 600, // 錦標賽已進行了多久(秒數)
"Event_time": 1729569008, // 本屆錦標賽的開賽時間(UTC秒數)
"End_time": 1729569008 // 本屆錦標賽的結束時間(UTC秒數)
}
]
}
查詢賽事排行榜
- API 名稱 /v2/agent/get_tournament_rankings
- 請求協議 POST
傳入參數
| 傳入參數 | 資料形態 | 說明 |
|---|---|---|
| Agent_name | string | 代理商別名 |
| Cup_id | int32 | 賽事編號 |
| Timestamp | int64 | 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒) |
| Signature | string |
簽名
Secret_key+Agent_name+Cup_id+Timestamp
最後再轉成MD5字串
|
返回結果
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Error_code | int32 | 錯誤碼 |
| Msg | string | 訊息 |
| Total_count | int32 | 總筆數(總共有多少玩家參賽) |
| Cup_id | int32 | 賽事編號 |
| Player_rankings | array | 排行榜 |
| Cup_message | Cup_message | 錦標賽資訊列表 |
Player_rankings
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Rank | int64 | 排名 |
| Uid | int64 | 玩家uid |
| Nickname | string | 暱稱 |
| Country_code | string | 國碼 |
| Bonus_gold | int64 | 獎金(單位0.0001) |
Cup_message
| 回傳值 | 資料形態 | 說明 |
|---|---|---|
| Server_name | string | 遊戲名稱:NLH, 6+, PLO, AoF-NLH, AoF-PLO |
| Register_gold | int64 | 報名費 |
| Start_gold | int64 | 初始籌碼(單位0.0001) |
| Purchase_count | int32 | 重購次數上限 |
| Max_seat | int32 | 牌桌人數 |
| Play_sec | int32 | 錦標賽已進行了多久(秒數) |
| Rest_sec | int32 | 休息時間(單位秒) |
| Register_min_player | int32 | 報名最低人數 |
| Register_max_player | int32 | 報名上限人數 |
| Register_delay_lv | int32 | 可報名盲注上限 |
傳入參數 範例
{
"Agent_name": "PM0100001", // 代理商別名
"Cup_id": 213133117, // 賽事編號
"Timestamp": 1729569008, // 時間戳(是一個UTC秒數, 與Server之間的誤差不得超過60秒)
"Signature": "cf0d2ed789096f9f8abd25de34a249a6" // 簽名
}
返回結果 範例
{
"Error_code": 1, // 錯誤碼
"Msg": "Success", // 訊息
"Total_count": 2, // 總筆數
"Cup_id": 213133117, // 賽事編號
"Cup_message": { // 錦標賽資訊列表
"Server_name": 1, // 遊戲名稱:NLH, 6+, PLO, AoF-NLH, AoF-PLO
"Register_gold": 2516, // 報名費
"Start_gold": "frances86005", // 初始籌碼(單位0.0001)
"Purchase_count": "MX", // 重購次數上限
"Max_seat": 198850000, // 牌桌人數
"Play_sec": 1, // Play_sec
"Rest_sec": 2516, // 休息時間(單位秒)
"Register_min_player": "frances86005", // 報名最低人數
"Register_max_player": "MX", // 報名上限人數
"Register_delay_lv": 198850000, // 可報名盲注上限
},
"Player_rankings": [ // 排行榜
{
"Rank": 1, // 排名
"Uid": 2516, // 玩家uid
"Nickname": "frances86005", // 暱稱
"Country_code": "MX", // 國碼
"Bonus_gold": 198850000 // 獎金(單位0.0001)
},
{
"Rank": 2, // 排名
"Uid": 3670, // 玩家uid
"Nickname": "grant42200", // 暱稱
"Country_code": "US", // 國碼
"Bonus_gold": 97900000 // 獎金(單位0.0001)
}
]
}
串接程式範例
以下範例實作串接玩家登入,其他 API 也是相同的作法
ASP.NET (C#)
using System.Net;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
namespace Sample
{
internal class Program
{
private static async Task Main(string[] args)
{
var url = "http://172.31.34.66:9004/v2/agent/player_login";
var agentName = "代理商別名";
var secretKey = "聯絡我們取得代理商的安全密鑰";
var account = "玩家帳號";
var timeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var playerLoginApiEntity = new
{
Agent_name = agentName,
Account = account,
Timestamp = timeStamp,
Signature = $"{secretKey}{agentName}{account}{timeStamp}".GetMd5Hash()
};
var jsonPayload = JsonSerializer.Serialize(playerLoginApiEntity);
var code = AES256CBCEncryptor.EncryptAES256CBCByText(agentName, jsonPayload, secretKey);
var entity = new
{
Agent_name = agentName,
Code = code
};
var requestContent = JsonSerializer.Serialize(entity);
var content = new StringContent(requestContent, Encoding.UTF8, "application/json");
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
Content = content,
RequestUri = new Uri($"{url}")
};
var response = await new HttpClient().SendAsync(request);
var responseContent = await response.Content.ReadFromJsonAsync<PlayerLoginResponseEntity>();
if (response.StatusCode == HttpStatusCode.OK)
{
if (responseContent.Error_code == 1)
{
}
}
else
{
}
}
private class PlayerLoginResponseEntity
{
public int Error_code { get; set; }
public string Msg { get; set; } = string.Empty;
public string Token { get; set; } = string.Empty;
}
}
public static class MD5Extension
{
public static string GetMd5Hash(this string input)
{
using (MD5 md5 = MD5.Create())
{
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("x2"));
}
return sb.ToString();
}
}
}
public static class AES256CBCEncryptor
{
public static string EncryptAES256CBCByText(string uid, string data, string secretKey)
{
byte[] key = Encoding.UTF8.GetBytes(secretKey);
byte[] iv = new byte[16];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(iv);
}
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (var msEncrypt = new System.IO.MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(data);
}
byte[] encrypted = msEncrypt.ToArray();
string code = Convert.ToBase64String(iv.Concat(encrypted).ToArray());
return code;
}
}
}
}
}
}
PHP
class AES256CBCEncryptor
{
public static function convertUnicodeToUtf8($data)
{
return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($matches) {
return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UCS-2BE');
}, $data);
}
public static function encryptAES256CBCByText($data, $secretKey)
{
$key = $secretKey;
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
$encrypted = base64_encode($iv . $ciphertext);
return $encrypted;
}
}
function getMd5Hash($input)
{
return md5($input);
}
$url = "http://172.31.34.66:9004/api/v2/agent/player_login";
$agentName = "代理商別名";
$secretKey = "聯絡我們取得代理商的安全密鑰";
$account = "玩家帳號";
$timeStamp = time();
$playerLoginApiEntity = [
"Agent_name" => $agentName,
"Account" => $account,
"Timestamp" => $timeStamp,
"Signature" => getMd5Hash($secretKey . $agentName . $account . $timeStamp)
];
$jsonPayload = json_encode($playerLoginApiEntity);
$code = AES256CBCEncryptor::encryptAES256CBCByText($jsonPayload, $secretKey);
$entity = [
"Agent_name" => $agentName,
"Code" => $code
];
$options = [
'http' => [
'header' => "Content-type: application/json\r\n",
'method' => 'POST',
'content' => json_encode($entity)
]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
$applyResponse = json_decode($response);
if ($http_response_header[0] === 'HTTP/1.1 200 OK') {
if ($applyResponse->Error_code == 1) {
}
} else {
}
Node.js
const crypto = require('crypto');
const axios = require('axios');
const agentName = '代理商別名';
const secretKey = '聯絡我們取得代理商的安全密鑰';
const account = '玩家帳號';
const url = 'http://172.31.34.66:9004/api/v2/agent/player_login';
const timeStamp = Math.floor(Date.now() / 1000);
function getMd5Hash(input) {
return crypto.createHash('md5').update(input).digest('hex');
}
function encryptAES256CBCByText(data, secretKey) {
const key = Buffer.from(secretKey, 'utf8');
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(data, 'utf8', 'base64');
encrypted += cipher.final('base64');
return Buffer.concat([iv, Buffer.from(encrypted, 'base64')]).toString('base64');
}
(async () => {
const playerLoginApiEntity = {
Agent_name: agentName,
Account: account,
Timestamp: timeStamp,
Signature: getMd5Hash(`${secretKey}${agentName}${account}${timeStamp}`)
};
const jsonPayload = JSON.stringify(playerLoginApiEntity);
const code = encryptAES256CBCByText(jsonPayload, secretKey);
const entity = {
Agent_name: agentName,
Code: code
};
const response = await axios.post(url, entity, {
headers: {
'Content-Type': 'application/json'
}
});
const applyResponse = response.data;
if (response.status === 200) {
if (applyResponse.Error_code === 1) {
console.log('Success:', applyResponse);
}
} else {
console.log('Failed:', applyResponse);
}
})();
附錄 - 錯誤訊息代碼
| 錯誤碼 (Error_cod) | 訊息 (Msg) |
|---|---|
| 1 | Success |
| -1 | Failed but it's okay |
| -2 | Failed |
| -3 | Timeout or does not exist |
| -4 | Disconnected |
| -5 | WebSocket send buffer is full |
| -6 | Contains unsafe characters |
| -7 | Invalid command |
| -8 | Server not ready |
| -9 | Server lacks permission |
| -10 | Decryption failed |
| -11 | DBA result set is empty |
| -12 | Parameter error |
| -13 | Account is too short |
| -14 | Account is too long |
| -21 | This API has reached the query limit |
| -22 | Each query request must be spaced at least 30 seconds apart |
| -100 | Duplicate login |
| -101 | Duplicate account |
| -102 | Job is full |
| -103 | Account does not exist |
| -104 | Incorrect password |
| -105 | JSON decoding failed |
| -106 | Invalid token |
| -107 | Token expired |
| -108 | Server disconnected |
| -109 | This account is logged into another game |
| -110 | Invalid coin type |
| -111 | Insufficient coins |
| -112 | Too many coins |
| -113 | Coin limit exceeded |
| -114 | Failed to add coins |
| -115 | This account has an unfinished game |
| -116 | Unable to retrieve game data |
| -117 | Duplicate click |
| -118 | Account cache does not exist |
| -119 | Failed to modify coins |
| -120 | System is busy |
| -121 | String contains unsafe characters |
| -122 | Incorrect time |
| -123 | Time range is too large |
| -124 | Time verification failed |
| -125 | Signature verification failed |
| -126 | Agent not found |
| -127 | Account has been deleted |
| -128 | Account has been frozen |
| -129 | Account already exists |
| -130 | Nickname already exists |
| -131 | Insufficient deposit |
| -132 | Too much deposit |
| -133 | Invalid deposit amount |
| -134 | Nickname is too short |
| -135 | Nickname is too long |
| -136 | Password is too short |
| -137 | Account cache is not ready |
| -138 | Creating a private table is not allowed |
| -139 | Insufficient diamonds |
| -140 | Main agent not found |
| -141 | Main agent has been deleted |
| -142 | Main agent has been frozen |
| -143 | Agent has been deleted |
| -144 | Agent has been frozen |
| -145 | Invalid product category |
| -146 | Invalid product ID |
| -147 | Invalid avatar image ID |
| -148 | This agent cannot join the public domain |
| -149 | Agent mismatch |
| -150 | Incomplete account cache data |
| -151 | Language is too short |
| -152 | Language is too long |
附錄 - 撲克牌編號
| 卡牌編號 | 卡牌 |
|---|---|
| 0 | 無或背面 |
| 1 | 梅花 A |
| 2 | 梅花 2 |
| 3 | 梅花 3 |
| 4 | 梅花 4 |
| 5 | 梅花 5 |
| 6 | 梅花 6 |
| 7 | 梅花 7 |
| 8 | 梅花 8 |
| 9 | 梅花 9 |
| 10 | 梅花 10 |
| 11 | 梅花 J |
| 12 | 梅花 Q |
| 13 | 梅花 K |
| 21 | 鑽石 A |
| 22 | 鑽石 2 |
| 23 | 鑽石 3 |
| 24 | 鑽石 4 |
| 25 | 鑽石 5 |
| 26 | 鑽石 6 |
| 27 | 鑽石 7 |
| 28 | 鑽石 8 |
| 29 | 鑽石 9 |
| 30 | 鑽石 10 |
| 31 | 鑽石 J |
| 32 | 鑽石 Q |
| 33 | 鑽石 K |
| 41 | 紅心 A |
| 42 | 紅心 2 |
| 43 | 紅心 3 |
| 44 | 紅心 4 |
| 45 | 紅心 5 |
| 46 | 紅心 6 |
| 47 | 紅心 7 |
| 48 | 紅心 8 |
| 49 | 紅心 9 |
| 50 | 紅心 10 |
| 51 | 紅心 J |
| 52 | 紅心 Q |
| 53 | 紅心 K |
| 61 | 黑桃 A |
| 62 | 黑桃 2 |
| 63 | 黑桃 3 |
| 64 | 黑桃 4 |
| 65 | 黑桃 5 |
| 66 | 黑桃 6 |
| 67 | 黑桃 7 |
| 68 | 黑桃 8 |
| 69 | 黑桃 9 |
| 70 | 黑桃 10 |
| 71 | 黑桃 J |
| 72 | 黑桃 Q |
| 73 | 黑桃 K |
| 81 | 鬼牌(黑) |
| 82 | 鬼牌(紅) |