# 云游戏支持

本文档说明运营 SDK（下面称 SDK）对游戏盒云游戏的优惠券、充值等功能的支持

## 云游戏、游戏盒、SDK关系简介
下图示意了云游戏过程中各个实体的包含关系和通信流程

![pay_flow_cloud](https://4399public.oss-cn-beijing.aliyuncs.com/ope/cloud_game_and_sdk.png)  

在游戏盒内进行云游戏，硬件部署结构有以下包含关系：
- 云端设备安装或部署了
    - 游戏，游戏集成了运营 SDK
    - 云游戏服务，云游戏通信模块，可与云端设备直接交互
    - 游戏盒（可选，看配置），作为游戏关联应用，但版本通常比较低
- 用户设备安装游戏盒，此游戏盒包含了
    - 云游戏插件，集成了
      - 云游戏 SDK，支持云游戏的基本功能，如接受播放画面和用户事件同步
      - 运营 SDK，支持云游戏本地充值
    - 游戏盒本身的一些模块，比如登录等

*注意：上述包含关系中出现了两个游戏盒、两个运营SDK，它们完全可以是不同的*

一些典型的通信流程
- 游戏画面：云游戏服务采集游戏画面，并实时传输给游戏盒内的云游戏 SDK，进而在播放器内展示
- 用户事件：用户在自己设备上的事件，通过云游戏 SDK 传输给云游戏服务，服务通过系统机制发送给真正的游戏画面
- 登录调用：云游戏登录调用被云游戏服务拦截，此调用转发给云游戏 SDK，云游戏 SDK 调用游戏登录模块完成登录；  
登录结果又反向传递，直到游戏收到授权登录结果，此过程中游戏无感知
- 充值调用：游戏调用运营 SDK 充值，充值调用发送给云游戏服务-云游戏 SDK，云游戏 SDK 间接调用本地运营 SDK功能完成充值；  
SDK 服务端将充值结果发送给游戏服务端，游戏服务端通知其客户端发放物品

## 接入准备
- **云游戏注册**：云游戏已经按规范完成注册，注册后得到 SDK 的游戏标识 `game key`
- **game key 同步**：SDK 的游戏标识，已经同步到云游戏后台，且游戏盒客户端可以获取此参数

对于具体功能，还需要额外配置，将在下文说明

## 初始化
游戏盒调用充值前需要以特定参数初始化，以告知 SDK 的初始化方式
```
mOpeCenter = OperateCenter.getInstance();
OperateConfig opeConfig = new OperateConfig.Builder(requireContext())
        .setGameKey(mGame.key()) // game key，从云端获取
        .setOrientation(SettingProvider.screenOrientation()) // SDK 页面方向，跟随游戏
        .setForCloud(true) // 是否为云游戏充值初始化
        .build();
mOpeCenter.setConfig(opeConfig);
mOpeCenter.init(MainActivity.this, new OperateCenter.OnInitGlobalListener() {
        @Override
        public void onInitFinished(boolean isLogin, User userInfo) {
            // 初始化后处理
        }

        @Override
        public void onUserAccountLogout(boolean fromUserCenter) {
            // 用户登出，游戏应回到自身登录页面
        }
        @Override
        public void onSwitchUserAccountFinished(boolean fromUserCenter, User userInfo) {
            // 用户切换，游戏应回到选服页面
        }
});
```

## 悬浮窗优惠券页
```java
/*
* 获取云游戏优惠券View
*
* @param activity 游戏Activity
* @param args 游戏盒向服务端临时请求获取到的accessToken
* @param listener1 踢出回调对象；其中code：607、608为踢出标识；message：为踢出说明文案
* @param listener2 需要手机认证时的回调对象；
* @return 优惠券view；在未初始化 || activity == null || gameBoxToken == null || listener1 == null || listener2 == null时该view可能为空
 */
mOpeCenter.getCouponView(activity,args,
    new OpeResultListener() {
    @Override
    public void onResult(int code, @Nullable String message) {

    }},
    new OpeResultListener() {
    @Override
    public void onResult(int code, @Nullable String message) {

    }
});
```
```java
/**
 * 云游戏优惠券页面，刷新优惠券列表
 */
 mOpeCenter.refreshCouponView();
```

## 云游戏充值

### 基本原理
运营 SDK 支持云游戏充值方案，是将云端充值请求转发到用户环境来完成。方案如图所示：

![pay_flow_cloud](https://4399public.oss-cn-beijing.aliyuncs.com/ope/pay_flow_cloud.png)  

整个流程围绕订单及其结果的传递而展开（略去不必要的细节），简要说明如下： 

- **1、Pay(order)**：游戏调用 SDK 充值接口
- <font color='red'>**2、Intent(PAY, order)**</font>：SDK 在充值接口内识别到云游戏环境，则将充值调用转发给云游戏运行时
- <font color='red'>**3、Forward(PAY, order)**</font>：云游戏 Runtime 提取充值调用，转发给指定云游戏 SDK 实例
- <font color='red'>**4、SendEvent(PAY, order)**</font>：云游戏 SDK 发送“充值事件”给游戏盒客户端
- **5、Pay(3rd_order)**：游戏盒客户端集成4399 SDK，与充值渠道 App 交互完成充值
- **6、Callback(3rd_order_result)**：充值渠道将外部订单结果回调给充值服务端
- **7、Callback(order_result)**：充值服务端将游戏订单结果回调给游戏服务端
- **8、Notify**：游戏服务端通知其客户端充值结果，客户端对账号发放商品

至此，完成整个充值流程，但是需要注意，此方案**不支持单机游戏**


### 相关配置
- **充值参数**：游戏已经申请了充值参数
- **云设备注册**：云游戏设备需要将机型特征提交给 SDK 后台，后台标记云设备，并通知客户端转发充值请求

### 接口调用

游戏盒需要调用 SDK 内的充值接口，此接口会与游戏所用充值接口不一样
```java
/*
 * 云游戏充值.
 *
 * @param activity Activity对象
 * @param args     Map，包装充值参数，包括用户、订单、设备参数
 * @param listener 充值回调对象
 */
mOpeCenter.recharge(activity, args, new OperateCenter.OnRechargeFinishedListener() {
    @Override
    public void onRechargeFinished(boolean success, int resultCode, String msg) {
        // 一般回调处理中
    }
});
```