---
description: 当前页面用于完成Unity游戏发布安卓和ios版本的接入
---

# 接入文档

## **一、SDK接入步骤**

### **开发前准备**

广告位文档、上报埋点统计文档。@运营同学

### **导入SDK插件**

* Unity游戏：将`DN_PLUGIN_UNITY.unitypackage`插件，导入到游戏unity工程。

下载链接：https://gui.vigame.cn/CP/Unity/UnityPackage/DN\_PLUGIN\_UNITY\_2.1.9\_C.unitypackage

### **Android接入**

使用模板接入，模板工程已接入sdk所需要的配置。只需将游戏unity工程Android导出，将资源和lib等文件拷贝到对应文件中即可。

下载链接：https://gui.vigame.cn/CP/Unity/build-templates/build-templates.zip

模板工程目录结构：

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-d36e9f4b4140a3b0abdd0b8c901db4764bd8324c%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

替换`unity-classes.jar`文件：

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-2d6bf83167744d08a83ae4099396dfa54fde815c%2Fimage%20(1).png?alt=media" alt=""><figcaption></figcaption></figure>

替换`so`文件：

{% hint style="info" %}
注意：游戏工程导出后需编译生成`libil2cpp.so`再拷贝替换。
{% endhint %}

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-9f1d3f5a148af123b471548d79eefef2aac89e16%2Fimage%20(2).png?alt=media" alt=""><figcaption></figcaption></figure>

替换资源文件：

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-7e3a90e36c00f4d74e35006dc9afbe4769b3d1fc%2Fimage%20(3).png?alt=media" alt=""><figcaption></figcaption></figure>

修改游戏icon和名称

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-804bec89563fb64e28cff3146f6b8f7d056bfc74%2Fimage%20(4).png?alt=media" alt=""><figcaption></figcaption></figure>

修改启动页闪屏图

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-f5fd25ec155f854111fccfd9d92914b63cd3dda3%2Fimage%20(5).png?alt=media" alt=""><figcaption></figcaption></figure>

操作完上述步骤后即可运行工程，查看游戏内容。

**关于包名**

由动能打包时，自行更换正式包名。

**关于签名**

如无特殊要求，正式包会使用动能的签名文件。

### **iOS接入**

Unity直接选择File->Build Setting导出iOS工程，并将xcode工程提供给动能以进行iOS打包。

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-d26189e92a63677816876fcd616a2fa3feae1e01%2Fimage%20(6).png?alt=media" alt=""><figcaption></figcaption></figure>

**iOS授权和证书**

1、需要授予我们公司appid账号（appstore@bubbleteastudios.cc）app管理权限，如下图所示

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-5d8eef33f1f3497189ca1d7bb27a8020dd64fc9b%2Fimage%20(7).png?alt=media" alt=""><figcaption></figcaption></figure>

2、需提供发布证书的dev，dis类型的p12（包括密码），以及这两个发布证书对应的dev，dis描述文件

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-581f90a37f7bc717c558b0067ea368ad58004e1f%2Fimage%20(8).png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-dd4394e1979c8f2930aacfe3b6b40b3e1b8346a6%2Fimage%20(9).png?alt=media" alt=""><figcaption></figcaption></figure>

**接入iOS模拟测试模块**

1、clone[自动化脚本](https://gitee.com/vigamedev/vigame.git)到工程目录

2、安装插件

```shell
gem install plist
gem install xcodeproj
```

2、执行脚本

```
sh ./vigame/auto.sh  b3e75b912e672146
```

3、出包测试

## 二、常用接口

### 基础（必接）

#### **日志打印**

调用该接口后会开启日志输出

```C#
/// <summary>
/// 日志打印开关
/// </summary>
/// <param name="isDebug">true是可打印日志，false否不打印日志</param>
public void SetDebug(bool isDebug)
```

#### **隐私政策和用户协议（必接）**

示例

```CSS
// 隐私政策
Wb.CoreManager.Instance.OpenPrivacyPolicy();
// 用户协议
Wb.CoreManager.Instance.OpenUserAgreement();
```

#### **签名验证 （防止盗版包必接）**

游戏开始时，需要签名验证，调用该方法验签，只有动能认可的签名信息才能通过验证。

```C#
/// <summary>
/// 签名验证
/// </summary>
/// <param name="successCall">成功回调</param>
/// <param name="failCall">失败回调</param>
public void CheckSignature(UnityAction successCall, UnityAction failCall)
```

示例

```C#
Wb.CoreManager.Instance.CheckSignature(delegate ()
{
   //验签成功，正常进入游戏
},

delegate ()
{
   //验签失败，直接闪退等
});
```

自测

```C#
过滤日志CheckSign查看验签结果
可以使用其他签名文件签名，签名apk运行后是否启动闪退。
```

### **广告（必接）**

#### **本地广告配置**

可以拷贝模板工程 build-templates\wbLibrary\src\main\assets\ADPositions.xml 中的配置添加游戏使用的广告位（广告位不可是中文等特殊字符），添加到游戏工程资源目录测试。

```
<?xml version="1.0" encoding="utf-8"?>
<appid>10001</appid><!------- 限定调试包使用，请勿修改参数 ----->
<channel>baibao</channel><!------- 限定调试包使用，请勿修改参数 ----->
<adlist>
    <ad>
        <type>splash</type> 
        <positions>splash,game_awaken</positions>
    </ad>
    <ad>
        <type>banner</type> 
        <positions>banner</positions>
    </ad>
    <ad>
        <type>plaque</type> <!------- 插屏 ----->
        <positions>pause,exit_game</positions>
    </ad>
    <ad>
        <type>video</type> <!------- 视频 ----->
        <positions>home_mfzs,level_win_mfzs</positions>
    </ad>
    <ad>
        <type>msg</type> 
        <positions>game_msg,yuans,load_msg,tx_msg</positions>
    </ad>
    <ad>
        <type>icon</type>
        <positions>mini_video,chouj</positions>
    </ad>
</adlist>
```

#### **广告是否准备好（选接）**

```C#
/// <summary>
/// 广告是否准备好
/// </summary>
/// <param name="adName">广告位</param>
public bool IsAdReady(string adName)
```

#### **关卡是否可以打开该广告（选接）**

```C#
/// <summary>
/// 关卡是否可以打开该广告
/// </summary>
/// <param name="adName">广告位</param>
/// <param name="level">关卡</param>
public bool IsAdBeOpenInLevel(string adName, int level)
```

#### **获取原生广告参数（选接）**

```C#
/// <summary>
/// 获取广告参数
/// </summary>
/// <param name="adName">广告位</param>
/// <returns></returns>
public string GetNativeData(string adName)
```

#### **打开嵌入式广告（选接）**

```C#
/// <summary>
/// 打开嵌入式广告
/// </summary>
/// <param name="adName">广告位</param>
/// <param name="showRect">展示区域</param>
/// <param name="clickRect">点击区域数组</param>
/// <param name="callBackFun1">关闭广告回调</param>
/// <param name="callBackFun2">打开成功失败回调</param>
public void ShowMsgAD(string adName, RectTransform showRect, RectTransform[] clickRect, ADCallback callBackFun1 = null, ADCallback callBackFun2 = null)
```

#### **打开广告（必接）**

```C#
/// <summary>
/// 打开广告
/// </summary>
/// <param name="adName">广告位名称</param>
/// <param name="callBackFun">广告关闭回调</param>
/// <param name="adStartFun">广告播放状态回调(可不设置回调)</param>
public void OpenAd(string adName, ADCallback callBackFun = null, AdStartCallback adStartFun = null)
```

#### **打开信息流广告（选接）**

```C#
/// <summary>
/// 打开信息流广告
/// </summary>
/// <param name="rect">广告展示区域，锚点为中心</param>
/// <param name="adName">广告位</param>
public void OpenYsAd(RectTransform rect, string adName = "yuans")
```

示例

```C#
    //打开视频广告
    public void OpenVideo() 
    {
        Wb.ADManager.Instance.OpenAd("home_mfzs", (result, resultParam) =>
        {
            if (result == Wb.ADResult.NotReady)
            {
                Debug.Log("广告未准备好~");
            }
            else if (result == Wb.ADResult.Success)
            {
                Debug.Log(resultParam.ToString());
                Debug.Log("广告打开成功~");
            }
            else
            {
                Debug.Log(resultParam.ToString());
                Debug.Log("广告打开失败~");
            }
        });
    }
    
    //打开插屏广告
    public void OpenPlaque() 
    {
        Wb.ADManager.Instance.OpenAd("pause", (result, resultParam) =>
        {
            if (result == Wb.ADResult.NotReady)
            {
                Debug.Log("广告未准备好~");
            }
            else if (result == Wb.ADResult.Success)
            {
                Debug.Log(resultParam.ToString());
                Debug.Log("广告打开成功~");
            }
            else
            {
                Debug.Log(resultParam.ToString());
                Debug.Log("广告打开失败~");
            }
        });
    }
    
    //打开banner广告
    public void OpenBanner() 
    {
        Wb.ADManager.Instance.OpenAd("banner");
    }
```

### **统计（必接）**

列举的接口根据游戏实际情况使用，事件id参数使用上报文档中的参数填写。游戏自定义事件通过自定义上报接口进行上报。

#### **自定义事件（选接）**

**单独事件**

```C#
/// <summary>
/// 单独事件上报
/// </summary>
/// <param name="eventId">事件id，可根据统计文档填写</param>
public void TJCustomEvent(string eventId)
```

**app\_loading\_show和app\_home\_show推荐接入，以便于分析启动漏斗转化。**

| **事件名称**    | **事件ID**           | **触发时机**      | **附加参数** |
| ----------- | ------------------ | ------------- | -------- |
| 游戏loading页面 | app\_loading\_show | 游戏引擎初始化后就触发上报 | 无        |
| 游戏内首页       | app\_home\_show    | 主页展示时         | 无        |

示例

```C#
//进入冷启动Loading页面时
Wb.TjManager.Instance.TJCustomEvent("app_loading_show");
//进入游戏首页时
Wb.TjManager.Instance.TJCustomEvent("app_home_show");
```

**携带标签上报**

```C#
/// <summary>
/// 上报
/// </summary>
/// <param name="eventId">事件id，可根据统计文档填写</param>
/// <param name="label">label内容</param>
public void TJCustomEvent(string eventId, string label)
```

示例

```C#
Wb.TjManager.Instance.TJCustomEvent("事件id"，"label内容");
```

**多属性上报**

```C#
/// <summary>
/// 多属性上报
/// </summary>
/// <param name="eventId">事件id，可根据统计文档填写</param>
/// <param name="attributes">attributes</param>
public void TJCustomEvent(string eventId, Dictionary<string, string> attributes)
```

示例

```C#
//关卡触发的自定义事件
Dictionary<string, string> ps = new Dictionary<string, string>();
ps["level"] = level.ToString();
ps["skinID"] = skinID.ToString();
ps["boost"] = boost ? "1" : "0";
Wb.TjManager.Instance.TJCustomEvent("事件id", ps);

//视频广告奖励按钮显示时，检查广告是否已准备好。如没有准备好，则需要隐藏视频按钮；如果准备好，则显示按钮，并调用此方法统计。
Dictionary<string, string> ps = new Dictionary<string, string>();
ps["ad_pos"] = adName;
Wb.TjManager.Instance.TJCustomEvent("ad_video_ready", ps);
```

#### **关卡开始（必接）**

```C#
/// <summary>
/// 关卡开始
/// </summary>
/// <param name="level">关卡id</param>
public void StartLevel(string level)
```

示例

```C#
Wb.TjManager.Instance.StartLevel("1");
```

#### **关卡获胜（必接）**

```C#
/// <summary>
/// 关卡获胜
/// </summary>
/// <param name="level">关卡id</param>
/// <param name="score">得分</param>
public void FinishLevel(string level, string score)
```

示例

```C#
Wb.TjManager.Instance.FinishLevel("1", "100");
```

#### **关卡失败（必接）**

```C#
/// <summary>
/// 关卡失败
/// </summary>
/// <param name="level">关卡id</param>
/// <param name="score">得分</param>
public void FailLevel(string level, string score)
```

示例

```C#
Wb.TjManager.Instance.FailLevel("1", "10");
```

### 商店联运

> 如您的游戏不需要在商店进行上线，可直接跳过。

#### **游戏退出（必接）**

游戏退出时先判断是否支持第三方退出，支持则调用SDK接口，不支持则调用游戏本身的退出逻辑。[用例参考](https://blog.csdn.net/Czhenya/article/details/78237374)

```C#
void Update()
{
    if (Input.GetKeyDown(KeyCode.Escape))
    {
        if (Wb.PayManager.Instance.IsSupportExit())
        {
            //如果支持退出，则调用openExitGame接口
            Wb.PayManager.Instance.OpenExitGame();
        } else {
            //否则展示游戏的退出窗口
        }  
    }
}
```

#### **反馈邮箱（必接）**

在设置界面显示邮箱信息，获取到数据就显示，没有就不显示。

> 安卓：读取assets/ConfigVigame.xml中的Email字段。
>
> iOS：读取VigameLibrary.plist中的Email字段。

```CSS
//get email config from ConfigVigame.xml
string str = Wb.CoreManager.Instance.getConfigVigameValue("Email");
if (str.Length == 0)
{
   //not have the Email config
}
else
{
    // have the Email config show the config on Setting.

}
```

#### **更多精彩（必接）**

> 先判断是否显示更多精彩按钮结果返回true才显示

否显示更多精彩按钮

```C#
/// <summary>
/// 否显示更多精彩按钮
/// </summary>
public bool IsMoreGameBtn() 
```

打开更多精彩

```C#
/// <summary>
/// 打开更多精彩
/// </summary>
public void OpenMoreGame() 
```

示例

```C#
//否显示更多精彩按钮
Wb.PayManager.Instance.IsMoreGameBtn();
//打开更多精彩
Wb.PayManager.Instance.OpenMoreGame();
```

按钮资源

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-fb9dc0877986be0c0abe1935288f7514855c3408%2Fimage%20(10).png?alt=media" alt=""><figcaption></figcaption></figure>

### 增值功能（选接）

#### **客服中心**

```C#
/// <summary>
/// 打开客服中心
/// </summary>
/// <param name="title">网页标题</param>
/// <param name="loginId">用户id</param>  
public void OpenClientCenter(string title, string loginId) 
```

#### 支付和补单

> 如您的游戏不需要支付功能，可直接跳过。

{% hint style="info" %}
注意：Android Studio 工程 assets\bin\version.txt 为 2.0.5 或高于该版本 sdk 支持升级版补单。
{% endhint %}

**支付流程**

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-a7c1b1bdb332af84ae03396576c82927b961cb34%2Fpay01.png?alt=media" alt=""><figcaption></figcaption></figure>

**客户端补单流程**

{% hint style="info" %}
注意：服务器发奖可跳过该流程。
{% endhint %}

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-1799e78382ab7af89ecc6439c9d2996b76d545e7%2Fpay02.png?alt=media" alt=""><figcaption></figcaption></figure>

**1. 支付**

**1.1 支付接口**

* 有两种方式创建 PayParam 对象，根据使用的构造函数不同区分是否使用 sdk 计费配置。
* 调用支付接口 sdk 会自动上报内购统计 pay\_purchase 事件。
* userdata 为用户自定义数据，由于支付平台的限制，该数据长度限制在16个字符内，超过长度限制数据会被截取（已使用 custom 字段代替）。
* custom 为用户自定义数据，只在 sdk 服务器生效不会向支付平台传递，长度限制在128个字符内，超过长度限制数据会被截取（服务端回传数据时可使用该字段传入自定义数据）。

{% hint style="info" %}
注意：APP有用户id参数可以调用SetLoginId进行设置，调用支付接口创建订单时会上传该数据。
{% endhint %}

```C#
/// <summary>
/// 通用-内购统计支付
/// </summary>
/// <param name="payParam">支付参数</param>
/// <param name="callFun">支付回调</param>
public void OrderPay(PayParam payParam, OrderPayCallbackHandler callFun)
```

参数说明：

{% hint style="info" %}
注意：custom 服务端回传数据时可使用该字段传入自定义数据。
{% endhint %}

```C#
payId 计费点id
price 金额（单位分）
payDesc 商品描述
payCode 支付code，没有填写计费点payId
giftId 礼包id，没有的话写计费点payId
giftType 礼包类型，没有填写空 非必传
giftNum 礼包数量，一次购买了几份，最小值为1
giftPrice 礼包价值，没有可填写price金额值（单位分）
levelId 有用户等级的传用户等级，没有用户等级的游戏传关卡id
tokenType 代币类型（当礼包类型为代币礼包时，传参。否则传空串）非必传
custom 用户自定义数据，最长128个字符(不会上传给平台) 非必传
userdata 用户自定义数据，由于支付平台的限制，最长16个字符（微信支付有效） 非必传
payPush 礼包推送：1主动点击；0被动推送 非必传
userId 户的账号ID，无账号游戏为空。最长128个字符 非必传
extParams 额外参数，传参后支付事件上报时携带该数据 非必传
```

> Unity使用计费点配置示例

```C#
var payParam = new Wb.PayParam(payId, giftId, giftType, giftNum, giftPrice, levelId, tokenType, custom, payPush, userId);
payParam.extraParam.Add("k1", "自定义参数1");
payParam.extraParam.Add("k2", "自定义参数2");
Wb.PayManager.Instance.OrderPay(payParam, (result, id, userData, orderInfo) =>
{
    if (result == Wb.PayStatus.PaySuccess)
    {
        Debug.Log("支付成功 orderInfo = " + orderInfo);
    }
    else if (result == Wb.PayStatus.PayFail)
    {
        Debug.Log("支付失败 orderInfo = " + orderInfo);
    }
    else if (result == Wb.PayStatus.PayCancel)
    {
        Debug.Log("支付取消 orderInfo = " + orderInfo);
    }
});
```

> Unity不使用计费点配置示例

```C#
var payParam = new Wb.PayParam(payId, price, payDesc, payCode, giftId, giftType, giftNum, giftPrice, levelId, tokenType, custom, payPush, userId);
payParam.extraParam.Add("k1", "自定义参数1");
payParam.extraParam.Add("k2", "自定义参数2");
Wb.PayManager.Instance.OrderPay(payParam, (result, id, userData, orderInfo) =>
{
    if (result == Wb.PayStatus.PaySuccess)
    {
        Debug.Log("支付成功 orderInfo = " + orderInfo);
    }
    else if (result == Wb.PayStatus.PayFail)
    {
        Debug.Log("支付失败 orderInfo = " + orderInfo);
    }
    else if (result == Wb.PayStatus.PayCancel)
    {
        Debug.Log("支付取消 orderInfo = " + orderInfo);
    }
});
```

**2. 游戏发奖**

**2.1 游戏发奖**

> 服务器发奖的游戏可以直接跳过该部分。

客户端发奖有可能会出现补单情况，需监听补单回调`2.1.1 设置补单回调`，然后进行`2.1.2充值到账上报`。

**2.1.1 设置补单回调**

{% hint style="info" %}
调用该接口即通知sdk开启补单逻辑，可以在游戏初始化完成后调用该接口触发补单。 建议：不要游戏启动就调用该接口，以免游戏数据还未初始化完成（手机性能不同）收到回调后无法处理发奖逻辑。
{% endhint %}

```C#
/// <summary>
/// 设置补单回调
/// 请在合适时机调用该接口开启sdk补单逻辑
/// </summary>
/// <param name="callFun">支付回调</param>
public void SetInventoryCallBack(OrderPayCallbackHandler callFun)
```

示例

```C#
//设置补单回调
Wb.PayManager.Instance.SetInventoryCallBack((status, payId, userData, orderId) => {
    Debug.Log($"pay 补单回调 status = {status}, payId = {payId}, userData = {userData}, traceId = {traceId}");
});
```

**2.1.2 充值到账上报**

{% hint style="info" %}
补单或非补单都要在发奖后调用接口上报，否则会造成后台统计掉单率升高并会重复补单。
{% endhint %}

充值成功后下发道具后进行上报（补单或非补单都要上报），需要自己调用TJPayOnAccount，接口内会自动上报pay\_on\_account事件，同时会触发消耗订单（微信米大师支付例外，因为米大师支付需要先扣币，扣币后服务器会自动消单）。 参数 tradeId 使用`1.支付`回调返回的 tradeId 。

```C#
/// <summary>
/// 充值道具到账后上报
/// </summary>
/// <param name="tradeId">订单id</param>
public void TJPayOnAccount(string tradeId)
```

**2.2 服务端发奖**

推荐的对接流程如下：

<figure><img src="https://3109237457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpGDLwHS4NGOCL3SVgTBf%2Fuploads%2Fgit-blob-a5da68e8bfffab7ded09436aa173e36b1f5542ec%2Fpay03.png?alt=media" alt=""><figcaption></figcaption></figure>

用户数值由服务器统一管理的游戏，可直接由游戏服务器接收支付结果和发奖，可从根本上解决掉单的问题。整体流程可以参考下面的校验逻辑。 客户端支付成功后，sdk服务器会将充值结果通知游戏服务器，游戏服务器根据订单支付结果进行道具下发、到账上报、消单等操作。

**3. 支付相关事件上报**

**3.1 代币变化上报**

{% hint style="info" %}
非服务端发奖游戏建议接入该事件上报，便于充值后奖励到账查询。
{% endhint %}

玩家游戏过程中虚拟货币发生变化时进行上报。内购上报统计事件为`pay_token_change`。 示例

```C#
 //以下参数仅供参考，以实际游戏为准
 Dictionary<string, string> attributes = new Dictionary<string, string>();
 attributes.Add("appid", Wb.CoreManager.Instance.GetAppid()); 
 attributes.Add("pid", Wb.CoreManager.Instance.GetPrjid());
 attributes.Add("level_id", "关卡ID(数值)");
 attributes.Add("token_type", "代币类型(1金币,2钻石,3体力)");
 attributes.Add("before_token", "变化前数量");
 attributes.Add("change_token", "变化数量");
 attributes.Add("after_token", "变化后数量");
 attributes.Add("add_reduce", "增减标志(1增加, 2减少)");
 attributes.Add("reason", "变化原因，新产品采用全新reason编号游戏内资产变化reason");
 attributes.Add("scene", "场景(eg: 1游戏结束时、2游戏过程中、3商城)");
 
 Wb.TjManager.Instance.TJCustomEvent("pay_token_change", attributes);
```

#### 在线参数

**1. 获取游戏在线参数配置**

```C#
/// <summary>
/// 获取游戏在线参数
/// </summary>
/// <param name="version">配置版本, 没有特殊指定填1</param>
/// <param name="callFun">回调</param>
public void InitGameConfig(int version, GameConfigCallback callFun)
```

**2. 根据key获取参数**

```C#
/// <summary>
/// 根据key获取参数
/// </summary>
/// <param name="key">关键字</param>
/// <returns>参数值</returns>
public string GetGameConfigValue(string key)
```

示例

```C#
//请求游戏参数配置
Wb.CoreManager.Instance.InitGameConfig(1, (result) =>
{
    if (result)
    {
        //获取成功，根据key获取参数
        string str = Wb.CoreManager.Instance.GetConfigValue(inputValue);
        Debug.Log("根据key获取参数 value = " + str);
    }
    else
    {
        //获取失败
        Debug.Log("获取失败~");
    }
});

```

#### 兑换码

**1. 兑换码开关**

> 自定义配置参数 key：dhm

{% hint style="info" %}
通过游戏在线参数配置 InitGameConfig 获取兑换码开关！！！
{% endhint %}

**2. 使用兑换码**

```C#
/// <summary>
/// 使用兑换码
/// </summary>
/// <param name="dhm">兑换码id</param>
/// <param name="callFun">回调</param>
public void UseCDKey(string dhm, Action<CDKeyState, string, string> callFun)
```

兑换码状态

```C#
// 兑换码状态
public enum CDKeyState
{
    Success = 200, // 成功
    ParamError = 401, // param is error 参数验证不通过
    UnOperate = 402, // 无效操作
    Invalid = 403, // 兑换码无效
    Used = 405, // 兑换失败，当前兑换码已经被使用过了
    UnUse = 406, // 当前兑换码已经失效
    Repeat = 407, // 不能重复使用
    UnExist = 408, // 兑换码不存在
    Busy = 505, // 系统繁忙
}
```

示例

```C#
Wb.CoreManager.Instance.UseCDKey("兑换码", (state, value, msg)=>{
   if(Wb.CDKeyState.Success == state) {
     // CDKey Success value = {"test":"11","te":"22"} msg = 兑换成功
     Debug.Log("CDKey Success value = " + value + " msg = " + msg);
   } else {
     Debug.Log("CDKey Fail value = " + value + " msg = " + msg);
   }
});
```

**3. 获取兑换码信息**

```C#
/// <summary>
/// 获取兑换码信息
/// </summary>
/// <param name="dhm">兑换码</param>
/// <param name="callFun"></param>
public void GetCDKeyInfo(string dhm, Action<CDKeyState, string, string> callFun)
```

兑换码状态

```C#
// 兑换码状态
public enum CDKeyState
{
    Success = 200, // 成功
    ParamError = 401, // param is error 参数验证不通过
    UnOperate = 402, // 无效操作
    Invalid = 403, // 兑换码无效
    Used = 405, // 兑换失败，当前兑换码已经被使用过了
    UnUse = 406, // 当前兑换码已经失效
    Repeat = 407, // 不能重复使用
    UnExist = 408, // 兑换码不存在
    Busy = 505, // 系统繁忙
}
```

示例

```C#
Wb.CoreManager.Instance.GetCDKeyInfo("兑换码", (state, value, msg) => {
    //Debug.Log("CDKey info value = " + value + " msg = " + msg);
});
```

回调value示例

> 生成兑换码时配置了如下格式的value，查询成功将下发配置的value

```TypeScript
{"rewards":[{"type":1,"name":"钞票","num":5},{"type":2,"name":"票券","num":10}]}
```

#### 三方账号登录

> 获取渠道包登录类型适用vivo，huawei，xiaomi，oppo渠道。

```C#
LoginType loginType = Wb.SocialManager.Instance.GetLoginType();
```

**1. 登录**

登录类型

```C#
// 登录类型
public enum LoginType
{
    TYPE_NULL = 0,
    TYPE_WX = 1,
    TYPE_QQ = 2,
    TYPE_FACEBOOK = 3,
    TYPE_MSDK = 4,
    TYPE_AliGame = 5,
    TYPE_Downjoy = 6,
    TYPE_Vivo = 7,
    TYPE_AliPay = 8,
    TYPE_Common = 9, // 模拟登陆
    TYPE_Huawei  = 10,
    TYPE_Xiaomi  = 11,
    TYPE_Oppo = 12,
    CopyRight = 13 //版号包登录
}
```

示例

```C#
LoginType loginType = Wb.SocialManager.Instance.GetLoginType();
Wb.SocialManager.Instance.Login(loginType, (result) =>
{
    if (result)
    {
         // 登录成功
    }
    else
    {
        // 登录失败
    }
});
```

**2. 获取用户信息**

> 获取用户信息时账号未登录会拉起登录后再获取信息

示例

```C#
LoginType loginType = Wb.SocialManager.Instance.GetLoginType();
Wb.SocialManager.Instance.GetUserInfo(loginType, (result,info) =>
{
    if (result)
    {
        // info 为返回的对象，可以使用下面方法获取具体信息
        // public string GetOpenId();
        // public string GetAccessToken();
        // public string GetNickName();
        // public string GetHeadImgUrl();
        // 获取用户信息成功
        Debug.Log("Social OpenId = " + info.GetOpenId());
        Debug.Log("Social accesstoken = " + info.GetAccessToken());
    }
    else
    {
        // 获取用户信息失败
        Debug.Log("获取用户信息失败 msg = " + info. ToString());
    }       
});
```

服务器响应示例

{% hint style="info" %}
字段有可能为空，使用时需进行判断处理
{% endhint %}

```Json
{
  "reason": "登陆成功",
  "openid": "86eb5d1f-ebf2-48a0-9e90-b7aab5210423",
  "nickname": "模拟登陆",
  "retCode": "1",
  "token": "83bf4c31-b37b-4789-aa1d-40bd1b58d04f==",
  "headimgUrl": "https://i.imgs.ovh/2023/09/27/PjNJW.jpeg",
  "playerid": "f7590e24-df9d-438a-881d-c918b99e15f5="
}
```

注意

{% hint style="info" %}
如用到第三方账号来绑定用户数据，还需要用到服务端的账号校验接口来防客户端篡改可联系获取服务端对接文档。
{% endhint %}

###
