# W1遊戲接入
### 1. W1部分
:green_book: 參考 \Model\Game\RTG\
1. 將遊戲館加入OpenGame(appsettings.DEV.json)
```json
"OpenGame": "SABA,RCG,JDB,DS,PG,AE,STREAMER,RSG,RLG,TP,RTG,JILI,JOKER"
"RTG_URL": "https://api.rbgamerp2.com/",
"RTG_Client_ID": "Tp2fTILl2Q2RpIzC",
"RTG_Secret": "I%9FJ*O$vDDcEO1g24",
"RTG_Key": "G6scW9lq",
"RTG_IV": "qbZogH8s",
"RTG_SystemCode": "h1sys",
"RTG_WebID": "webdev"
```
2. 註冊Service (Startup.cs)
```csharp
services.AddScoped<IRTGApiService, RTGApiService>();
services.AddSingleton<RtgRecordSchedule>();
services.AddSingleton<RtgReportSchedule>();
services.AddSingleton<RtgAuditSchedule>();
```
3. 設定Schedule (Startup.cs)
```csharp
scheduler.Schedule<RtgRecordSchedule>().EverySeconds(20).Zoned(TimeZoneInfo.Local).PreventOverlapping("RtgRecordScheduleLock");
scheduler.Schedule<RtgReportSchedule>().Cron("10 01 * * *").Zoned(TimeZoneInfo.Local).PreventOverlapping("RtgReportScheduleLock");
scheduler.Schedule<RtgAuditSchedule>().Cron("20 01 * * *").Zoned(TimeZoneInfo.Local).PreventOverlapping("RtgAuditSchedule");
```
### 2. 建立遊戲館API Request/Response Modle
:green_book: 參考 \Model\Game\RTG\
### 3. 遊戲API HTTP Service
:pencil2: 實作與遊戲館http requset 模型包含加解密與資料驗證
**reponse 需紀錄**
* GCP log request/response參數
```csharp!
var dics = new Dictionary<string, object>
{
{ "request", reqJson },
{ "response", responselog }
};
using (var scope = _logger.BeginScope(dics))
{
_logger.LogInformation("Get RequestPath: {RequestPath} | ResponseHttpStatus:{Status} | exeTime:{exeTime} ms", url, response.StatusCode, sw.Elapsed.TotalMilliseconds);
}
```
* 遊戲館health參數
```csharp!
apiResInfo.ElapsedMilliseconds = sw.ElapsedMilliseconds;
_ = _apiHealthCheckService.SetResponseData(Platform.RTG, apiResInfo);
```
:green_book: 參考 \Service\Game\RTG\RTGApiService.cs (ApiHandle)
### 4. 建立遊戲館 API Service
:pencil2:實作必要與遊戲館溝通API
:green_book: 參考 \Service\Game\RTG\RTGApiService.cs
### 5. 實作遊戲IGameInterfaceService
:green_book: 參考 \Service\Game\RTG\RTG_InterfaceService.cs
#### 5.1 建立使用者 CreateGameUser
:::info
新接遊戲館請固定加上3個字元prefix key(定義在appsettings)
```json
"WalletMode": "TransferWallet",
"RCGMode": "H1",
"Prefix_Key": "dev",
"OpenGame": "SABA,RCG,JDB,DS,PG,AE,STREAMER,RSG,RLG,TP,RTG,JILI,JOKER"
```
:::
#### 5.2 登出使用者 KickUser
#### 5.3 登出所有使用者 KickAllUser
#### 5.4 轉入餘額 Deposit
:::info
交易結果要回傳3個狀態
1. success : 遊戲回傳成功
2. fail : 遊戲回傳交易失敗(需要是遊戲定義error code 保證失敗無異動金額)
3. pending : 遊戲回傳狀態不明/延遲, 或是request time out
:::
#### 5.5 轉出餘額 WithDraw
同5.4
#### 5.6 取得登入連結 Login
幣別/語系等相關參數 資料轉換請定義在\Model\Game\遊戲館ID\遊戲館ID.cs
:green_book: 參考 \Model\Game\RTG\RTG.cs
#### 5.7 查詢交易結果 CheckTransferRecord
實作交易pending重新查詢
:::warning
遊戲館若回傳不明確不可變更狀態
測試此功能可先將遊戲館轉帳timeout時間改成10-50ms
:::
#### 5.8 取得遊戲調閱URL GameDetailURL
若遊戲舘不支援須提出討論
#### 5.9 設定遊戲館線上清單 SetOnlineUser
:::info
遊戲館若不支援改使用last_platform 判斷是否在線
要回傳club_id 非遊戲中id (去除前/後綴)
club_ename與frachiser_id 保持null即可
:::
#### 5.10 取得遊戲館線上清單 getOnlineUser
#### 5.11 取得遊戲明細 getGameRecordList
:::danger
請等W1核心部分(BetRecordService)新增介面
:::
### 6. 實作遊戲注單相關
:::info
目前介面尚未統一, 分每個遊戲館自訂介面與實作
:::
#### 6.1 寫入遊戲注單 PostRtgRecord
包含遊戲注單明細(t_rtg_bet_record), 5分鐘匯總帳(t_bet_record_summary)
注單明細player id 使用遊戲館內id
5分鐘匯總帳player 使用H1 club_id (注意要去除前/後綴)
:question: 匯總帳需確認是否要區分遊戲類型
#### 6.2 W1報表 SummaryW1Report
#### 6.3 遊戲館報表 SummaryGameProviderReport
若遊戲館沒提供報表API先忽略
### 7. 注單重拉
需要將輸入時間分段拉取(建議10分鐘1段)
```csharp
var RepairCount = 0;
while (RepairReq.EndTime.Subtract(startTime).TotalMinutes > 10)
{
endTime = startTime.AddMinutes(10);
_logger.LogDebug("Repair RTG record start Time : {startTime} end Time : {endTime}", startTime, endTime);
RepairCount += await RepairRtg(startTime, endTime);
startTime = endTime;
await Task.Delay(1000);
}
_logger.LogDebug("Repair RTG record start Time : {startTime} end Time : {endTime}", startTime, RepairReq.EndTime);
RepairCount += await RepairRtg(startTime, RepairReq.EndTime);
```
* 要確認起始與結束時間的格式與遊戲館拉取是否包含該段時間
* 重補注單需要取得W1明細先排除重複的再寫入
* 注單重拉之後要重新產出報表
* 要回傳新增注單筆數
### 8. 建立排程
排程需要將執行參數自動建立並寫入DB
排程需要可重工具平台設定參數關閉
```csharp
t_system_parameter parameter = null;
// 取得當前時間,計算下一個帳務比對的時間
var now = DateTime.Now.ToLocalTime();
now = now.AddDays(-1);
var nextTime = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0);
var key = "RtgAuditSchedule";
// 取得帳務比對的時間基準
parameter = await _commonService._serviceDB.GetSystemParameter(key);
// 檢查有無資料,沒資料的話新增預設值
if (parameter == null)
{
var model = new t_system_parameter()
{
key = key,
value = nextTime.ToString("yyyy-MM-dd HH:mm:ss"),
min_value = string.Format("{0}", 1),
name = "RTG 每小時遊戲帳務比對排程",
description = "RTG 紀錄帳務比對排程時間基準點"
};
var postSystemParameter = await _commonService._serviceDB.PostSystemParameter(model);
if (postSystemParameter)
{
parameter = model;
}
else
{
return; // 新增失敗就結束排程
}
}
```
#### 8.1 注單排程 DsRecordSchedule
若是使用Max Id可參考 PgRecordSchedule
若是使用時間區間拉單可參考 DsRecordSchedule
排程執行時間請先參考DS遊戲
```csharp
scheduler.Schedule<DsRecordSchedule>().EverySeconds(20).Zoned(TimeZoneInfo.Local).PreventOverlapping("DsRecordScheduleLock").RunOnceAtStart();
scheduler.Schedule<DsReportSchedule>().Cron("0,20,40 * * * *").PreventOverlapping("DsReportScheduleLock").Zoned(TimeZoneInfo.Local);
scheduler.Schedule<DsAuditSchedule>().Cron("10,30,50 * * * *").PreventOverlapping("DsAuditScheduleLock").Zoned(TimeZoneInfo.Local);
```
:rotating_light:請注意遊戲商拉回是否會有重複資料
:rotating_light:請注意注單拉取時間是否有包含起始與結束時間
#### 8.2 遊戲注單報表排程 DsReportSchedule
每個遊戲商產生報表時間不盡相同, 目前預設2小時後執行
需確認時間後再決定執行排程時間
#### 8.3 遊戲注單檢查排程 DsAuditSchedule
遊戲注單報表產生後10分執行