From 1aabe42be27a0f1e4d47804bb240dfe3fe01ea8a Mon Sep 17 00:00:00 2001 From: ShouWang <514504765@qq.com> Date: Wed, 13 Nov 2024 11:37:21 +0800 Subject: [PATCH 01/11] =?UTF-8?q?docs:=20=E4=BC=98=E5=8C=96=20DLC=20?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=E8=AF=B4=E6=98=8E=20(#1274)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: 优化 DLC 接入说明 * Update features.mdx * Update features.mdx --- cn/docs/sdk/copyright-verification/features.mdx | 3 ++- .../version-v3/sdk/copyright-verification/features.mdx | 3 ++- .../version-v3/sdk/copyright-verification/features.mdx | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cn/docs/sdk/copyright-verification/features.mdx b/cn/docs/sdk/copyright-verification/features.mdx index 6038eb411..3c9da65f7 100644 --- a/cn/docs/sdk/copyright-verification/features.mdx +++ b/cn/docs/sdk/copyright-verification/features.mdx @@ -22,4 +22,5 @@ TapTap 的正版验证服务适用于买断制游戏,用于检测用户开始 当您的游戏需开放新章节、新主线等付费的 DLC 内容时,您同样可使用 DLC 正版验证服务完成用户的解锁资格验证。 -在使用 DLC 正版验证服务前,请确保您的游戏存在一个用户可见的游戏详情页(可预约、可关注均可),并前往开发者中心 > 商店 > 游戏售卖创建 DLC 并提交审核。完成审核后, 请前往 [开发指南](/sdk/copyright-verification/guide/) 完成开发接入。 \ No newline at end of file +在使用 DLC 正版验证服务前,请确保您的游戏存在一个用户可见的游戏详情页(可预约、可关注均可),并确认您上传的游戏 APK 包体已通过审核。 +确认无误后,请前往开发者中心 > 商店 > 游戏售卖,创建 DLC 并提交审核。完成审核后, 请参考 [开发指南](/sdk/copyright-verification/guide/) 完成开发接入。 \ No newline at end of file diff --git a/cn/versioned_docs/version-v3/sdk/copyright-verification/features.mdx b/cn/versioned_docs/version-v3/sdk/copyright-verification/features.mdx index 81ddee738..ab3c9195c 100644 --- a/cn/versioned_docs/version-v3/sdk/copyright-verification/features.mdx +++ b/cn/versioned_docs/version-v3/sdk/copyright-verification/features.mdx @@ -22,4 +22,5 @@ TapTap 的正版验证服务适用于买断制游戏,用于检测用户开始 当您的游戏需开放新章节、新主线等付费的 DLC 内容时,您同样可使用 DLC 正版验证服务完成用户的解锁资格验证。 -在使用 DLC 正版验证服务前,请确保您的游戏存在一个用户可见的游戏详情页(可预约、可关注均可),并前往开发者中心 > 商店 > 游戏售卖创建 DLC 并提交审核。完成审核后, 请前往 [开发指南](/v3/sdk/copyright-verification/guide/) 完成开发接入。 \ No newline at end of file +在使用 DLC 正版验证服务前,请确保您的游戏存在一个用户可见的游戏详情页(可预约、可关注均可),并确认您上传的游戏 APK 包体已通过审核。 +确认无误后,请前往开发者中心 > 商店 > 游戏售卖,创建 DLC 并提交审核。完成审核后, 请参考 [开发指南](/v3/sdk/copyright-verification/guide/) 完成开发接入。 diff --git a/hk/versioned_docs/version-v3/sdk/copyright-verification/features.mdx b/hk/versioned_docs/version-v3/sdk/copyright-verification/features.mdx index 81ddee738..ab3c9195c 100644 --- a/hk/versioned_docs/version-v3/sdk/copyright-verification/features.mdx +++ b/hk/versioned_docs/version-v3/sdk/copyright-verification/features.mdx @@ -22,4 +22,5 @@ TapTap 的正版验证服务适用于买断制游戏,用于检测用户开始 当您的游戏需开放新章节、新主线等付费的 DLC 内容时,您同样可使用 DLC 正版验证服务完成用户的解锁资格验证。 -在使用 DLC 正版验证服务前,请确保您的游戏存在一个用户可见的游戏详情页(可预约、可关注均可),并前往开发者中心 > 商店 > 游戏售卖创建 DLC 并提交审核。完成审核后, 请前往 [开发指南](/v3/sdk/copyright-verification/guide/) 完成开发接入。 \ No newline at end of file +在使用 DLC 正版验证服务前,请确保您的游戏存在一个用户可见的游戏详情页(可预约、可关注均可),并确认您上传的游戏 APK 包体已通过审核。 +确认无误后,请前往开发者中心 > 商店 > 游戏售卖,创建 DLC 并提交审核。完成审核后, 请参考 [开发指南](/v3/sdk/copyright-verification/guide/) 完成开发接入。 From 8292afe0ab373fa03b0dc071d43392630a349f16 Mon Sep 17 00:00:00 2001 From: Track_Yu <31614708+yuwenjian@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:32:12 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20V4=20=E5=90=88?= =?UTF-8?q?=E8=A7=84=E8=AE=A4=E8=AF=81=E6=9C=80=E4=BD=B3=E5=AE=9E=E8=B7=B5?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=9B=BE=E7=89=87=20(#1275)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 余文建 <8997665+yu_wenjian@user.noreply.gitee.com> --- cn/docs/sdk/anti-addiction/practice.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cn/docs/sdk/anti-addiction/practice.mdx b/cn/docs/sdk/anti-addiction/practice.mdx index a1a6403a7..76c2a5ece 100644 --- a/cn/docs/sdk/anti-addiction/practice.mdx +++ b/cn/docs/sdk/anti-addiction/practice.mdx @@ -14,22 +14,22 @@ import v4SDKVersions from '/src/docComponents/v4SDKVersions'; ### 创建应用获取应用参数 在 [TapTap 开发者中心](https://developer.taptap.cn) 创建游戏应用,获取应用 Client ID、Client Token 等参数,用于初始化 SDK; -![](https://capacity-files.lcfile.com/nnQKxgJJzgErOlIOcxnbIHt8Vc1RmGYe/tap_get_ready.png) +![](https://img.tapimg.com/market/images/e9b046743f9b561b9235505d35ed6e78.png) ### 开通 TapTap 登录服务 合规认证服务依赖于 TapTap 登录服务,因此,厂商需要在 **TapTap 开发者中心 > 你的游戏 > 游戏服务 > 应用配置** 开启「TapTap 登录」; -![](https://img.tapimg.com/market/images/168f902edd3de84cf0d5eb5fa640e78d.png) +![](https://img.tapimg.com/market/images/7cbe4b738646f8e0fd214852e1a61bee.png) ### 配置应用包名和签名信息 Android 签名处填写 MD5 值,详情可参考:[如何获取 MD5 值](/sdk/access/android-md5); -![](https://img.tapimg.com/market/images/3c725fc6859363f630d90471d0c8929b.png) +![](https://img.tapimg.com/market/images/12f339345e6bd04c37ad538a0a7e688d.png) ### 开通合规认证服务 -找到 **TapTap 开发者中心 > 你的游戏 > 游戏服务 > 开发与构建 > 合规认证**,根据游戏实际情况,选择「已有版号」或「暂无版号」方案,然后点击**立即开通** +找到 **TapTap 开发者中心 > 你的游戏 > 游戏服务 > 基础服务 > 合规认证**,根据游戏实际情况,选择「已有版号」或「暂无版号」方案,然后点击**立即开通** -![](https://img.tapimg.com/market/images/90e6d759ba528aa7e9ef29077387edbb.png) +![](https://img.tapimg.com/market/images/23eb961832f75c683ca28e3d26b07c88.png) :::tip 若游戏选择的是「已有版号」方案则还需要完成中宣部实名认证系统的注册以及相应配置,具体的操作请参考 [注册中宣部实名认证系统](/sdk/anti-addiction/features/#已有版号) @@ -40,7 +40,7 @@ Android 签名处填写 MD5 值,详情可参考:[如何获取 MD5 值](/sdk/ 在后续的代码集成中,也需要处理相关的 `1100` 回调 -![](https://img.tapimg.com/market/images/e7fab2ce4099b792bd32390c04e28986.png) +![](https://img.tapimg.com/market/images/29c805cff1074f0b8bf03ba452ad3236.png) ## 代码接入 From 0c712aa236efbc9557b374c3928c4e4c1e3b8101 Mon Sep 17 00:00:00 2001 From: estelle1995 <30402318+estelle1995@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:58:01 +0800 Subject: [PATCH 03/11] =?UTF-8?q?tap=20adn=E7=89=88=E6=9C=AC=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20(#1277)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: wangping --- cn/docs/sdk/tap-adn/tds-tapad.mdx | 26 +++++-------------- cn/docs/tap-download.mdx | 4 +-- cn/src/docComponents/v3SDKVersions.ts | 4 +-- cn/src/docComponents/v4SDKVersions.ts | 4 +-- .../version-v3/sdk/tap-adn/tds-tapad.mdx | 24 +++-------------- cn/versioned_docs/version-v3/tap-download.mdx | 4 +-- hk/src/docComponents/v3SDKVersions.ts | 4 +-- hk/src/docComponents/v4SDKVersions.ts | 4 +-- 8 files changed, 22 insertions(+), 52 deletions(-) diff --git a/cn/docs/sdk/tap-adn/tds-tapad.mdx b/cn/docs/sdk/tap-adn/tds-tapad.mdx index 5f07ccdbf..d1ae5e96d 100644 --- a/cn/docs/sdk/tap-adn/tds-tapad.mdx +++ b/cn/docs/sdk/tap-adn/tds-tapad.mdx @@ -90,14 +90,6 @@ dependencies { implementation "com.android.support:support-v4:28.0.0" implementation "com.github.bumptech.glide:glide:4.9.0" implementation 'com.android.support:recyclerview-v7:28.0.0' - - // 如果引入了 oaid sdk 则不需要引入下述依赖 - // 需要新增 maven 'https://developer.huawei.com/repo' - // implementation 'com.huawei.hms:ads-identifier:3.4.62.300' - - // 如果引入了 oaid sdk 则不需要引入下述依赖 - // 需要新增 maven 'https://developer.hihonor.com/repo' - // implementation 'com.hihonor.mcs:ads-identifier:1.0.3.300' // 加入的依赖库-结束 // highlight-end // 下面这行是 Unity 的 mainTemplate.gradle 自带的,帮助定位插入位置 @@ -119,8 +111,8 @@ dependencies { :::tip **TapADN SDK 从 3.16.3.10 版本开始更新了 glide 的依赖,glide 版本从 4.0.0 更新到了 4.9.0。** ::: -```groovy -repositories{ + +{`repositories{ flatDir{ dirs 'src/main/libs' } @@ -136,17 +128,9 @@ dependencies { implementation "com.android.support:support-v4:28.0.0" implementation "com.github.bumptech.glide:glide:4.9.0" implementation 'com.android.support:recyclerview-v7:28.0.0' - - // 如果引入了 oaid sdk 则不需要引入下述依赖 - // 需要新增 maven 'https://developer.huawei.com/repo' - // implementation 'com.huawei.hms:ads-identifier:3.4.62.300' - - // 如果引入了 oaid sdk 则不需要引入下述依赖 - // 需要新增 maven 'https://developer.hihonor.com/repo' - // implementation 'com.hihonor.mcs:ads-identifier:1.0.3.300' // ... -} -``` +}`} + @@ -2015,3 +1999,5 @@ sign = fmt.Sprintf("%x", sha256.Sum256(trans_id:SecurityKey)) |**10007**| Request AdSpace Miss | | |**10008**| Request AdSpace Not Match| | |**10009**| Request Invalid DeviceId | | + + diff --git a/cn/docs/tap-download.mdx b/cn/docs/tap-download.mdx index 8867db16c..03533e229 100644 --- a/cn/docs/tap-download.mdx +++ b/cn/docs/tap-download.mdx @@ -61,8 +61,8 @@ TapSDK 为我们提供的众多服务的总称,为了方便开发者按需接 TapADN SDK 是由「易玩(上海)网络科技有限公司」开发,向媒体提供丰富的广告资源,依托高效的算法引擎,帮助开发者实现流量变现。

[接入文档](/sdk/tap-adn/tds-tapad/)    [合规指南](/sdk/tap-adn/adn-compliance/) -1. [TapADN Android SDK](https://tapad-platform.tapimg.com/sdk/TapAD_3.16.3.39.aar) 版本: 3.16.3.39 更新日期: 2024-11-06 -2. [TapADN Unity SDK](https://tapad-platform.tapimg.com/sdk/TapAD_3.16.3.39.unitypackage) 版本: 3.16.3.39 更新日期: 2024-11-06 +1. [TapADN Android SDK](https://tapad-platform.tapimg.com/sdk/TapAD_3.16.3.40.aar) 版本: 3.16.3.40 更新日期: 2024-11-13 +2. [TapADN Unity SDK](https://tapad-platform.tapimg.com/sdk/TapAD_3.16.3.40.unitypackage) 版本: 3.16.3.40 更新日期: 2024-11-13 3. [TapADN Android Demo](https://tapad-platform.tapimg.com/sdk/TapADDemo_3.16.3.37.zip) 【[Android 安装包下载](https://tapad-platform.tapimg.com/sdk/tapaddemo_external_3.16.3.37-release.apk)】 :::tip diff --git a/cn/src/docComponents/v3SDKVersions.ts b/cn/src/docComponents/v3SDKVersions.ts index 723d7d20f..8db1df320 100644 --- a/cn/src/docComponents/v3SDKVersions.ts +++ b/cn/src/docComponents/v3SDKVersions.ts @@ -27,8 +27,8 @@ const v3SDKVersions = { } }, tapadn: { - unity: "3.16.3.39", - android: "3.16.3.39", + unity: "3.16.3.40", + android: "3.16.3.40", }, tapGlobalPayments: { unity: "4.0.14", diff --git a/cn/src/docComponents/v4SDKVersions.ts b/cn/src/docComponents/v4SDKVersions.ts index 29adb99e2..54cf38b88 100644 --- a/cn/src/docComponents/v4SDKVersions.ts +++ b/cn/src/docComponents/v4SDKVersions.ts @@ -27,8 +27,8 @@ const v4SDKVersions = { } }, tapadn: { - unity: "3.16.3.39", - android: "3.16.3.39", + unity: "3.16.3.40", + android: "3.16.3.40", }, tapGlobalPayments: { unity: "4.0.14", diff --git a/cn/versioned_docs/version-v3/sdk/tap-adn/tds-tapad.mdx b/cn/versioned_docs/version-v3/sdk/tap-adn/tds-tapad.mdx index 15539c546..911a95147 100644 --- a/cn/versioned_docs/version-v3/sdk/tap-adn/tds-tapad.mdx +++ b/cn/versioned_docs/version-v3/sdk/tap-adn/tds-tapad.mdx @@ -90,14 +90,6 @@ dependencies { implementation "com.android.support:support-v4:28.0.0" implementation "com.github.bumptech.glide:glide:4.9.0" implementation 'com.android.support:recyclerview-v7:28.0.0' - - // 如果引入了 oaid sdk 则不需要引入下述依赖 - // 需要新增 maven 'https://developer.huawei.com/repo' - // implementation 'com.huawei.hms:ads-identifier:3.4.62.300' - - // 如果引入了 oaid sdk 则不需要引入下述依赖 - // 需要新增 maven 'https://developer.hihonor.com/repo' - // implementation 'com.hihonor.mcs:ads-identifier:1.0.3.300' // 加入的依赖库-结束 // highlight-end // 下面这行是 Unity 的 mainTemplate.gradle 自带的,帮助定位插入位置 @@ -119,8 +111,8 @@ dependencies { :::tip **TapADN SDK 从 3.16.3.10 版本开始更新了 glide 的依赖,glide 版本从 4.0.0 更新到了 4.9.0。** ::: -```groovy -repositories{ + +{`repositories{ flatDir{ dirs 'src/main/libs' } @@ -136,17 +128,9 @@ dependencies { implementation "com.android.support:support-v4:28.0.0" implementation "com.github.bumptech.glide:glide:4.9.0" implementation 'com.android.support:recyclerview-v7:28.0.0' - - // 如果引入了 oaid sdk 则不需要引入下述依赖 - // 需要新增 maven 'https://developer.huawei.com/repo' - // implementation 'com.huawei.hms:ads-identifier:3.4.62.300' - - // 如果引入了 oaid sdk 则不需要引入下述依赖 - // 需要新增 maven 'https://developer.hihonor.com/repo' - // implementation 'com.hihonor.mcs:ads-identifier:1.0.3.300' // ... -} -``` +}`} + diff --git a/cn/versioned_docs/version-v3/tap-download.mdx b/cn/versioned_docs/version-v3/tap-download.mdx index 25a981fbe..b2b0e37d4 100644 --- a/cn/versioned_docs/version-v3/tap-download.mdx +++ b/cn/versioned_docs/version-v3/tap-download.mdx @@ -52,8 +52,8 @@ TapSDK 为我们提供的众多服务的总称,为了方便开发者按需接 TapADN SDK 是由「易玩(上海)网络科技有限公司」开发,向媒体提供丰富的广告资源,依托高效的算法引擎,帮助开发者实现流量变现。

[接入文档](/v3/sdk/tap-adn/tds-tapad/)    [合规指南](/v3/sdk/tap-adn/adn-compliance/) -1. [TapADN Android SDK](https://tapad-platform.tapimg.com/sdk/TapAD_3.16.3.39.aar) 版本: 3.16.3.39 更新日期: 2024-11-06 -2. [TapADN Unity SDK](https://tapad-platform.tapimg.com/sdk/TapAD_3.16.3.39.unitypackage) 版本: 3.16.3.39 更新日期: 2024-11-06 +1. [TapADN Android SDK](https://tapad-platform.tapimg.com/sdk/TapAD_3.16.3.40.aar) 版本: 3.16.3.40 更新日期: 2024-11-13 +2. [TapADN Unity SDK](https://tapad-platform.tapimg.com/sdk/TapAD_3.16.3.40.unitypackage) 版本: 3.16.3.40 更新日期: 2024-11-13 3. [TapADN Android Demo](https://tapad-platform.tapimg.com/sdk/TapADDemo_3.16.3.37.zip) 【[Android 安装包下载](https://tapad-platform.tapimg.com/sdk/tapaddemo_external_3.16.3.37-release.apk)】 :::tip diff --git a/hk/src/docComponents/v3SDKVersions.ts b/hk/src/docComponents/v3SDKVersions.ts index 723d7d20f..8db1df320 100644 --- a/hk/src/docComponents/v3SDKVersions.ts +++ b/hk/src/docComponents/v3SDKVersions.ts @@ -27,8 +27,8 @@ const v3SDKVersions = { } }, tapadn: { - unity: "3.16.3.39", - android: "3.16.3.39", + unity: "3.16.3.40", + android: "3.16.3.40", }, tapGlobalPayments: { unity: "4.0.14", diff --git a/hk/src/docComponents/v4SDKVersions.ts b/hk/src/docComponents/v4SDKVersions.ts index b3474eaf5..4ec28d6b7 100644 --- a/hk/src/docComponents/v4SDKVersions.ts +++ b/hk/src/docComponents/v4SDKVersions.ts @@ -27,8 +27,8 @@ const v4SDKVersions = { } }, tapadn: { - unity: "3.16.3.39", - android: "3.16.3.39", + unity: "3.16.3.40", + android: "3.16.3.40", }, tapGlobalPayments: { unity: "4.4.0", From aaea068506a87838c0a905089a356f8ba61d675a Mon Sep 17 00:00:00 2001 From: ShouWang <514504765@qq.com> Date: Wed, 13 Nov 2024 17:57:19 +0800 Subject: [PATCH 04/11] docs: Add a description of the insufficient_scope returned by callso the OAuth Interface. (#1278) * docs: Add a description of the insufficient_scope returned by calls to the OAuth Interface. * Update taptap-oauth.mdx * Update taptap-oauth.mdx * Update taptap-oauth.mdx --- cn/docs/sdk/taptap-login/taptap-oauth.mdx | 1 + .../version-v3/sdk/taptap-login/guide/taptap-oauth.mdx | 2 ++ hk/docs/sdk/taptap-login/taptap-oauth.mdx | 2 ++ .../current/sdk/taptap-login/taptap-oauth.mdx | 1 + .../version-v3/sdk/taptap-login/guide/taptap-oauth.mdx | 2 ++ .../version-v3/sdk/taptap-login/guide/taptap-oauth.mdx | 2 ++ 6 files changed, 10 insertions(+) diff --git a/cn/docs/sdk/taptap-login/taptap-oauth.mdx b/cn/docs/sdk/taptap-login/taptap-oauth.mdx index ba35edd76..f78ec6287 100644 --- a/cn/docs/sdk/taptap-login/taptap-oauth.mdx +++ b/cn/docs/sdk/taptap-login/taptap-oauth.mdx @@ -1244,4 +1244,5 @@ curl -s -H"Authorization:${AUTHORIZATION}" "https://${REQUEST_HOST}${REQUEST_URI | forbidden | 用户没有对当前动作的权限,**引导重新身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交** | | not_found | 请求失败,请求所希望得到的资源未被在服务器上发现。**在参数相同的情况下,不应该重复请求** | | server_error | 服务器出现异常情况 **可稍等后重新尝试请求,但需有尝试上限,建议最多 3 次,如一直失败,则中断并告知用户** | +| insufficient_scope | 移动端进行 TapTap 授权使用的授权范围与服务端调用的 OAuth 接口不匹配导致,例如:移动端授权采用 basic_info 权限而服务端调用 `获取当前账户基础信息` API 时则会返回该异常 | diff --git a/cn/versioned_docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx b/cn/versioned_docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx index 2fd9dcaa5..b473b8fdc 100644 --- a/cn/versioned_docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx +++ b/cn/versioned_docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx @@ -1244,4 +1244,6 @@ curl -s -H"Authorization:${AUTHORIZATION}" "https://${REQUEST_HOST}${REQUEST_URI | forbidden | 用户没有对当前动作的权限,**引导重新身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交** | | not_found | 请求失败,请求所希望得到的资源未被在服务器上发现。**在参数相同的情况下,不应该重复请求** | | server_error | 服务器出现异常情况 **可稍等后重新尝试请求,但需有尝试上限,建议最多 3 次,如一直失败,则中断并告知用户** | +| insufficient_scope | 移动端进行 TapTap 授权使用的授权范围与服务端调用的 OAuth 接口不匹配导致,例如:移动端授权采用 basic_info 权限而服务端调用 `获取当前账户基础信息` API 时则会返回该异常 | + diff --git a/hk/docs/sdk/taptap-login/taptap-oauth.mdx b/hk/docs/sdk/taptap-login/taptap-oauth.mdx index 95661d7ee..307810a05 100644 --- a/hk/docs/sdk/taptap-login/taptap-oauth.mdx +++ b/hk/docs/sdk/taptap-login/taptap-oauth.mdx @@ -1243,4 +1243,6 @@ curl -s -H"Authorization:${AUTHORIZATION}" "https://${REQUEST_HOST}${REQUEST_URI | forbidden | 用户没有对当前动作的权限,**引导重新身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交** | | not_found | 请求失败,请求所希望得到的资源未被在服务器上发现。**在参数相同的情况下,不应该重复请求** | | server_error | 服务器出现异常情况 **可稍等后重新尝试请求,但需有尝试上限,建议最多 3 次,如一直失败,则中断并告知用户** | +| insufficient_scope | 移动端进行 TapTap 授权使用的授权与服务端调用的 OAuth 接口不匹配导致,例如:移动端授权采用 basic_info 权限而服务端调用 `获取当前账户基础信息` API 时则会返回该异常 | + diff --git a/hk/i18n/en/docusaurus-plugin-content-docs/current/sdk/taptap-login/taptap-oauth.mdx b/hk/i18n/en/docusaurus-plugin-content-docs/current/sdk/taptap-login/taptap-oauth.mdx index d1c52aec1..c2a17120a 100644 --- a/hk/i18n/en/docusaurus-plugin-content-docs/current/sdk/taptap-login/taptap-oauth.mdx +++ b/hk/i18n/en/docusaurus-plugin-content-docs/current/sdk/taptap-login/taptap-oauth.mdx @@ -1235,3 +1235,4 @@ curl -s -H"Authorization:${AUTHORIZATION}" "https://${REQUEST_HOST}${REQUEST_URI | forbidden | The user does not have permission for the current action, **guiding re-authentication will not help, and this request should not be resubmitted** | | not_found | The request failed, the requested resource was not found on the server. **Under the same parameters, the request should not be repeated** | | server_error | An exception occurred on the server **Retry the request after a while, but there should be a retry limit, recommended maximum of 3 times, if it keeps failing, interrupt and inform the user** | +| insufficient_scope | The permission used for TapTap authorisation on the mobile side does not match the OAuth interface called by the server side, e.g. if the mobile side uses the basic_info permission for authorisation and the server side calls the `Get Current Account Detailed Information' API, then this exception is returned. | diff --git a/hk/i18n/en/docusaurus-plugin-content-docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx b/hk/i18n/en/docusaurus-plugin-content-docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx index 0d96a30b5..57c93117e 100644 --- a/hk/i18n/en/docusaurus-plugin-content-docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx +++ b/hk/i18n/en/docusaurus-plugin-content-docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx @@ -596,3 +596,5 @@ public class Authorization { | forbidden        | User does not have permission to perform this action. **Reauthenticating permission will not provide any help. This request should be not repeated.** | | not_found        | Request failed. The requested resources were not found on the server. **Requests should not be repeated with the same parameters** | | server_error    | The server error has occurred.  **You may retry the request later, but there must be an upper limit (recommended: 3). If the first attempt fails, interrupt and inform the user** |  +| insufficient_scope | The permission used for TapTap authorisation on the mobile side does not match the OAuth interface called by the server side, e.g. if the mobile side uses the basic_info permission for authorisation and the server side calls the `Get Current Account Detailed Information' API, then this exception is returned. | + diff --git a/hk/versioned_docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx b/hk/versioned_docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx index 11745a1df..5d0ff6635 100644 --- a/hk/versioned_docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx +++ b/hk/versioned_docs/version-v3/sdk/taptap-login/guide/taptap-oauth.mdx @@ -1245,4 +1245,6 @@ curl -s -H"Authorization:${AUTHORIZATION}" "https://${REQUEST_HOST}${REQUEST_URI | forbidden | 用户没有对当前动作的权限,**引导重新身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交** | | not_found | 请求失败,请求所希望得到的资源未被在服务器上发现。**在参数相同的情况下,不应该重复请求** | | server_error | 服务器出现异常情况 **可稍等后重新尝试请求,但需有尝试上限,建议最多 3 次,如一直失败,则中断并告知用户** | +| insufficient_scope | 移动端进行 TapTap 授权使用的授权范围与服务端调用的 OAuth 接口不匹配导致,例如:移动端授权采用 basic_info 权限而服务端调用 `获取当前账户基础信息` API 时则会返回该异常 | + From 45b92c3000a5fbf639b8b77ddb18a8079bc12a99 Mon Sep 17 00:00:00 2001 From: ShouWang <514504765@qq.com> Date: Thu, 14 Nov 2024 11:19:29 +0800 Subject: [PATCH 05/11] docs: update store material (#1279) --- cn/docs/store/release/store-material.mdx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cn/docs/store/release/store-material.mdx b/cn/docs/store/release/store-material.mdx index 86a80dcfa..214eb75f8 100644 --- a/cn/docs/store/release/store-material.mdx +++ b/cn/docs/store/release/store-material.mdx @@ -11,7 +11,7 @@ import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; - 尺寸:512x512px - 格式:png/jpg -- 要求:请直接上传直角方图,系统会根据 TapTap 的圆角规范自动裁剪,建议保证主要内容在图示的安全区域内 +- 要求:请直接上传直角方图图标; ![图标](https://img.tapimg.com/market/images/7d9b54999437f091912d925058a3c1d6.png) @@ -55,16 +55,14 @@ import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; :::tip - 为保证用户能够快速了解游戏玩法,游戏正式上线开放下载或开放试玩版必须提供实机视频 -- 请在前 5s 内展示核心玩法,请避免使用抽卡动画 / 过场动画等类似 pv 的画面,占据视频的主要时长。且请避免仅用较短时间演示核心玩法,以掩盖游戏本身的真实水平、误导玩家 +- 请在前 5s 内展示核心玩法,请避免使用抽卡动画 / 过场动画等类似 pv 的画面,占据视频的主要时长,且请避免仅用较短时间演示核心玩法,以掩盖游戏本身的真实水平、误导玩家 - 请勿只展示角色、立绘、Loading 界面、主界面等画面,需演示游戏的核心玩法(建议占比在 90% 以上) - 请勿添加游戏本体以外的任何配音和字幕,可适当剪辑视频(如加速/减速/拼接)以提升观看体验 -- 请勿使用宣传视频替代实机录屏,实机视频的参考示例可咨询工单 - 前 30 秒内请勿在全屏画面中只展示游戏/厂商/引擎 Logo - 请勿额外使用人物立绘,请确保录屏内容占比在 95% 以上 - 请勿使用画中画,请确保录屏内容占比在 95% 以上 - 请勿拍出游玩设备,请使用游戏本身的录屏画面 - 请保持在 2 分钟以内,最长请勿超过 3 分钟 -- 请与该游戏匹配,请勿使用其他游戏 - 片尾请勿含有营销诱导性文案 - 请提供高清视频 @@ -104,6 +102,7 @@ import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; :::tip - 除了游戏名或游戏 Logo 外,请勿引用或使用其他文本 +- 请保证宣传图美观,不符合 TapTap 平台调性的宣传图将会被审核驳回 - 在某些页面会使用 4:3 比例对图片做裁剪进行展示,请误将游戏 logo、主要角色放置在裁剪线上 ::: From 49a0aa1ac9ae3238844e2a4b53f52a52fa8e7fef Mon Sep 17 00:00:00 2001 From: ShouWang <514504765@qq.com> Date: Thu, 14 Nov 2024 16:43:28 +0800 Subject: [PATCH 06/11] docs: add act album module for store (#1280) --- cn/docs/store/operations-skills/act-album.mdx | 269 ++++++++++++++++++ .../store/operations-skills/astroturfers.mdx | 2 +- .../store/operations-skills/event-center.mdx | 2 +- .../store/operations-skills/event-notice.mdx | 2 +- cn/docs/store/operations-skills/game-sign.mdx | 2 +- .../operations-skills/in-game-events.mdx | 2 +- .../information-dissemination.mdx | 2 +- cn/docs/store/operations-skills/maelstrom.mdx | 2 +- .../operations-skills/review-management.mdx | 2 +- .../operations-skills/store-gameglitch.mdx | 2 +- .../store/operations-skills/suggestions.mdx | 2 +- cn/docs/store/operations-skills/today.mdx | 2 +- 12 files changed, 280 insertions(+), 11 deletions(-) create mode 100644 cn/docs/store/operations-skills/act-album.mdx diff --git a/cn/docs/store/operations-skills/act-album.mdx b/cn/docs/store/operations-skills/act-album.mdx new file mode 100644 index 000000000..f58958559 --- /dev/null +++ b/cn/docs/store/operations-skills/act-album.mdx @@ -0,0 +1,269 @@ +--- +title: 利用图集活动,拉动玩家活跃 +sidebar_position: 1 +--- +## 「图集活动」介绍 +### 图集活动是什么? +- 图集活动是 TapTap 于 2024/11/22 推出的游戏服务功能: 活动页将展示活动相关的图文帖的合集。 +- 活动提供图文帖创作模版,鼓励用户活动期间进行模版发帖参与活动,或是参与图集投票,即为活动图文帖点赞。 + +
+ + + + + + + + + + + + + + + + + + + + + +
活动期间活动玩法活动结束
点赞互动形式我来投稿/我来评审沉淀作品集
+ + + + + + + +
+
+ +### 举行图集活动的意义? + +- 提升社区活跃度 -- 图集活动旨在鼓励高质量的图文帖投稿和点赞,所有参与行为都将在论坛内有所呈现。 +- 促进 UGC 内容创作以及优质内容传播 -- 活动将提供主题和创作模版,玩家通过分享丰富游戏内容,从而激发更多优秀创作。 +- 增加社交互动 -- 投票点赞是重要的社区社交行为,图集活动将鼓励玩家之间的创作交流与互动,构建更紧密的社区关系。 +- 沉淀作品,游戏宣传 -- 活动结束后,活动页将作为优秀作品集长期有效,建议将其视为用户自发的 UGC 作品集。 + +### 您将获得的资源位支持 + +当您在开发者后台创建的签到活动过审之后,将会获得以下系统自动配置的资源: +- 【活动与公告】:创建的签到活动过审后,系统会自动展示于游戏详情页 - 活动与公告处; + +同时,我们推荐您将图集活动配置在论坛推荐位。 + +## 「图集活动」的创建 +### 一、活动素材要求 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
素材内容说明使用场景素材示例
活动头图 +

【活动中状态头图】

+

尺寸:1080*1080

+

格式:JPG 格式,小于 300KB

+

说明:要求包含活动名称。

+

建议将简要的比赛说明及活动时间放入头图中。活动页点击头图区域将弹出详细活动说明。

+
+ + + +
+

【活动结束状态头图】

+

尺寸:984*1080

+

格式:JPG 格式,小于 300KB

+

说明:顶部 525*1080 范围为安全区域,图片底部将展示用户参赛投稿及名次,请注意安全区避免被遮挡

+
+ + + +
活动按键 +

【未投稿状态的投稿按键】

+

尺寸:540x252

+

格式:JPG 格式,小于 300KB

+

说明:按键文本为 投稿参赛

+
+ + + +
+

【已投稿状态的投稿按键】

+

尺寸:540x252

+

格式:JPG 格式,小于 300KB

+

说明:按键文本为 已参赛继续投稿

+
+ +
+

【评审按键】

+

尺寸:540x252

+

格式:JPG格式,小于300KB

+

说明:按键文本为 我来评审

+
+ +
活动按键氛围背景 +

【按键背景】

+

尺寸:1080x252

+

格式:JPG 格式,小于 300KB

+

说明:活动氛围图

+
+ + + +
活动页配色 +

请输入颜色 code,如: #F5ECE2

+

- 背景色:该色值将被用于页面背景色取值。

+

- 选中文字色:该色值将被用于文字标签被选中时的颜色取值

+

- 未选中文字色:该色值将被用于文字标签未被选中时的颜色取值

+
+ +
+
+ +### 二、活动的创建方式 + +开发者可于【开发者中心 - 游戏福利 - 图集活动 - 创建图集活动】中提交相关图片/文案进行创建与审核。 + +- 操作步骤一:点击创建图集活动后,完整提交基础信息以及活动配置信息并保存。 +- 操作步骤二:点击 奖品设置 配置活动奖品,完整提交奖品信息并保存,活动要求奖品数量不小于 50 件。 +- 操作步骤二:确认内容无误后,提交审核(请仔细检查内容,如出现错误将影响你的审核进度和结果)。 + +:::info 注意 +1.为避免用户看到的活动奖品发生变化,审核通过的活动仅支持补充库存操作,不支持添加新的奖品/删除奖品/编辑现有奖品信息。 + +2.我们支持提供游戏的平台头像框奖品,但是若需发放头像框奖品,请先与平台联络并达成合作。在获得专属头像框 ID 后进行活动头像框奖品配置,直接配置头像框活动将被审核驳回。 +::: + +**操作示例:** + + + +### 三、活动的奖品要求 + +- 奖品数量 -- 要求奖品数量不少于 50 件,少于 50 件的活动将不会通过审核。 +- 奖品类型 -- 活动支持奖品类型包括实物、兑换码和平台头像框。其中,如需发放头像框奖品,请先与平台联系并达成合作,获得专属头像框 ID 后再进行头像框奖品配置,直接配置头像框的活动将被审核驳回。 +- 发放形式 -- 奖品将根据您的库存,从您填写的 “放起始名次” 开始依次发放,直至库存发完或无用户可发。 + +例如:若“发放起始名次”填写为 2,奖品库存为 3,则奖品将发放给第 2、3、4 名用户;若 “发放起始名次” 填写为 2,奖品库存为 1000,参赛用户共 600 名,则奖品将发放给全部 600 名参赛用户,剩余库存 400 件。 + + + +- 用户领奖 -- 活动结束后,获奖用户将收到一封站内信,通知其奖品已发放,请返回活动页领取奖品。用户回到活动页后,礼包码或头像框奖品将立即发放;实物奖品则需填写地址。 + +:::info 实物奖品的发放 +如果您为活动配置了实物奖品,请在奖品过期时间到期后,通过后台导出实物发奖名单,并自行发奖。 +::: + +## 「图集活动」的管理 + +### 一、活动素材要求 + +图集活动支持您对活动页展示的投稿图文帖内容进行管理。 + +
+ + + + + + + + + + + + + +
管理入口管理页面
+ + + +
+
+ +- 图集投稿管理仅适用于取消被移除帖子的活动排名及奖励。被移除的帖子在活动页面内不会展示,但仍在论坛内可见。如帖子内容违反论坛规定,请使用管理员权限进行沉底或删除等论坛管理操作。 +- 帖子被移除/恢复时,用户将收到一封站内信通知,告知其帖子状态变动以及变动原因。 + +### 二、审核通过后的配置修改 + +- 活动首次通过审核后,将在您配置的开始时间自动上线。 +- 活动奖品 -- 为避免用户看到的活动奖品发生变化,审核通过活动的奖品模块仅支持补充库存操作,不支持删除/修改/新建奖品。 +- 活动信息 -- 活动开始前,支持您修改所有表单内容;活动开始后,仅支持修改活动名称、活动结束时间和活动素材配置;活动结束后,仅支持修改活动素材配置。如果您提交的修改审核在审核通过时已不再支持修改,则该项修改将无效。(例如:如果活动开始前您修改了活动开始时间和活动头图,但在审核通过时活动已上线,那么对活动开始时间的修改无效,而对活动头图的修改正常生效) + +:::info 注意 +审核通过后您修改的表单内容实际为草稿态,需要提交审核并通过后才会对线上活动生效。 +::: + +## Q&A + +**Q:我修改了活动内容,需要多久才能对线上活动生效?** + +**A:**您修改的活动表单内容处于草稿态,需要提交审核并通过后才能立即生效。 + +**Q:为什么审核中的活动到达活动开始时间后直接上线了?/为什么审核中的活动未到达活动开始时间后直接上线了?** + +**A:**活动将自动根据您最后一次审核通过的活动开始时间上线。如果发生您所述的这种情况,说明您在活动通过审核后,对表单进行了配置修改并再次提交审核。如果您提交的修改(如活动开始时间)审核在审核通过时已不再支持修改,则该项修改将无效。 + +**Q:如何确认是否申请成功?我为什么被拒审了?** + +**A:**审核状态请于活动创建页面审核状态处查看。 + +**Q:我想举办图集活动,需要提前多久提交活动申请以便审核?** + +**A:** 所有活动申请,自提交审核成功后 2 个工作日内处理,烦请及时查看审核状态,以便活动及时上线。未通过审核的活动不会上线。 + +**Q:活动对于游戏以及奖品有什么要求?** + +**A:** +- 活动奖品数量 < 50,不予通过 +- 素材不符合平台规范,不予通过 +- 其余无要求,但过往经验及数据显示,奖品价值越高,用户参与度越高,活动效果越好。 + +**Q:关于图集活动我还有其他问题?** + +**A:**如有任何问题请提工单选择分类「商店运营服务支持」-「TapTap 新功能申请/咨询」-「游戏签到系统问题咨询」进行咨询处理。 \ No newline at end of file diff --git a/cn/docs/store/operations-skills/astroturfers.mdx b/cn/docs/store/operations-skills/astroturfers.mdx index 5e1616197..b4e3feb4a 100644 --- a/cn/docs/store/operations-skills/astroturfers.mdx +++ b/cn/docs/store/operations-skills/astroturfers.mdx @@ -1,6 +1,6 @@ --- title: TapTap 诱导好评定义及处理规则 -sidebar_position: 10 +sidebar_position: 11 --- TapTap 致力于维护评价内容的真实性,拒绝开发者利用奖励干预玩家对游戏的真实点评。 diff --git a/cn/docs/store/operations-skills/event-center.mdx b/cn/docs/store/operations-skills/event-center.mdx index 714047152..ac99a475d 100644 --- a/cn/docs/store/operations-skills/event-center.mdx +++ b/cn/docs/store/operations-skills/event-center.mdx @@ -1,6 +1,6 @@ --- title: 申请活动中心栏目 -sidebar_position: 5 +sidebar_position: 6 --- import useBaseUrl from "@docusaurus/useBaseUrl"; diff --git a/cn/docs/store/operations-skills/event-notice.mdx b/cn/docs/store/operations-skills/event-notice.mdx index af1cf402c..9d33ef56f 100644 --- a/cn/docs/store/operations-skills/event-notice.mdx +++ b/cn/docs/store/operations-skills/event-notice.mdx @@ -1,6 +1,6 @@ --- title: 如何利用「活动与公告」板块获得曝光 -sidebar_position: 11 +sidebar_position: 12 --- import useBaseUrl from "@docusaurus/useBaseUrl"; diff --git a/cn/docs/store/operations-skills/game-sign.mdx b/cn/docs/store/operations-skills/game-sign.mdx index b435e248d..a430569b2 100644 --- a/cn/docs/store/operations-skills/game-sign.mdx +++ b/cn/docs/store/operations-skills/game-sign.mdx @@ -1,6 +1,6 @@ --- title: 利用签到活动,拉动玩家活跃 -sidebar_position: 7 +sidebar_position: 8 --- import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; diff --git a/cn/docs/store/operations-skills/in-game-events.mdx b/cn/docs/store/operations-skills/in-game-events.mdx index d3bbe5296..98d4ca698 100644 --- a/cn/docs/store/operations-skills/in-game-events.mdx +++ b/cn/docs/store/operations-skills/in-game-events.mdx @@ -1,6 +1,6 @@ --- title: 如何更好运营游戏更新和游戏内活动 -sidebar_position: 6 +sidebar_position: 7 toc_max_heading_level: 6 --- diff --git a/cn/docs/store/operations-skills/information-dissemination.mdx b/cn/docs/store/operations-skills/information-dissemination.mdx index 18d3f4720..ec52bd8c8 100644 --- a/cn/docs/store/operations-skills/information-dissemination.mdx +++ b/cn/docs/store/operations-skills/information-dissemination.mdx @@ -1,6 +1,6 @@ --- title: 如何让官方信息更好地触达到玩家 -sidebar_position: 1 +sidebar_position: 2 --- import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; diff --git a/cn/docs/store/operations-skills/maelstrom.mdx b/cn/docs/store/operations-skills/maelstrom.mdx index acdb58103..9d62539e4 100644 --- a/cn/docs/store/operations-skills/maelstrom.mdx +++ b/cn/docs/store/operations-skills/maelstrom.mdx @@ -1,6 +1,6 @@ --- title: 游戏异常事件应对 -sidebar_position: 8 +sidebar_position: 9 --- import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; diff --git a/cn/docs/store/operations-skills/review-management.mdx b/cn/docs/store/operations-skills/review-management.mdx index 6c978d466..2ee54718b 100644 --- a/cn/docs/store/operations-skills/review-management.mdx +++ b/cn/docs/store/operations-skills/review-management.mdx @@ -1,6 +1,6 @@ --- title: 如何运营游戏的评分评价? -sidebar_position: 2 +sidebar_position: 3 --- import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; diff --git a/cn/docs/store/operations-skills/store-gameglitch.mdx b/cn/docs/store/operations-skills/store-gameglitch.mdx index a05377c68..f28bc8e12 100644 --- a/cn/docs/store/operations-skills/store-gameglitch.mdx +++ b/cn/docs/store/operations-skills/store-gameglitch.mdx @@ -1,6 +1,6 @@ --- title: 游戏故障应对 -sidebar_position: 9 +sidebar_position: 10 --- import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; diff --git a/cn/docs/store/operations-skills/suggestions.mdx b/cn/docs/store/operations-skills/suggestions.mdx index f7bbae8d1..cb85b78db 100644 --- a/cn/docs/store/operations-skills/suggestions.mdx +++ b/cn/docs/store/operations-skills/suggestions.mdx @@ -1,6 +1,6 @@ --- title: 如何在不同运营节点提高运营效率 -sidebar_position: 3 +sidebar_position: 4 --- import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; diff --git a/cn/docs/store/operations-skills/today.mdx b/cn/docs/store/operations-skills/today.mdx index c9751b909..9185cad78 100644 --- a/cn/docs/store/operations-skills/today.mdx +++ b/cn/docs/store/operations-skills/today.mdx @@ -1,6 +1,6 @@ --- title: 如何获得「今日游戏」栏目的曝光 -sidebar_position: 4 +sidebar_position: 5 --- import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; From e15d5fdd852351063acaced9e69c06f506bfdd76 Mon Sep 17 00:00:00 2001 From: ShouWang <514504765@qq.com> Date: Fri, 15 Nov 2024 15:26:19 +0800 Subject: [PATCH 07/11] docs: Shell signing example for writing an interface for uploading APKs (#1281) --- cn/docs/sdk/apk-upload/guide.mdx | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/cn/docs/sdk/apk-upload/guide.mdx b/cn/docs/sdk/apk-upload/guide.mdx index 322fc0cf9..2cb54eb1e 100644 --- a/cn/docs/sdk/apk-upload/guide.mdx +++ b/cn/docs/sdk/apk-upload/guide.mdx @@ -159,6 +159,70 @@ Signature = Base64Encode(HMAC-SHA256(Server Secret, SignParts)) +
+ Shell 请求示例 + +```bash +#!/usr/bin/env bash + +# TapTap API 上传 APK 「获取上传请求参数」接口请求示例 Shell 脚本 +# 测试该脚本时需要开发者根据自己的应用参数替换如下四个参数:app_id、client_id、server_secret、file_name + +# app_id:游戏在 TapTap 商店的唯一身份标识。 例如:https://www.taptap.cn/app/187168,其中 187168 是 app_id。 +app_id="填写应用的 App ID" + +# TapTap 开放平台提供的 Client ID,应用的客户端标识 +client_id="填写应用的 Client ID" + +# TapTap 开放平台的 Server Secret,服务端对服务端的调用凭证,用来生成签名的密钥(请勿泄露) +server_secret="填写应用的 Server Secret" + +# 要上传的 APK 文件名,必须以 .apk 为扩展名,且只允许包含字母、数字、下划线和中横线 +file_name="要上传的 APK 文件名,必须以 .apk 为扩展名" + +# 生成 8 位随机字符串作为请求中的 nonce,用于防止请求重放 +nonce=$(openssl rand -hex 4) + +# 当前时间的秒级 Unix 时间戳,用于生成签名 +ts=$(date +%s) + +# 构造待签名的请求内容 +# 请求方法 +method="GET" + +# 完整请求路径及其 QueryString 参数,用于访问 API 上传参数 +url_path_and_query="/apk/v1/upload-params?app_id=${app_id}&file_name=${file_name}&client_id=${client_id}" + +# 请求头信息,包含随机数 nonce 和时间戳 ts +headers=$(printf "%s\n%s" "x-tap-nonce:${nonce}" "x-tap-ts:${ts}") + +# GET 请求不携带 Body,因此 Body 内容为空 +body="" + +# 输出待签名的请求内容(请求方法、路径、头信息、Body)用于调试 +printf "%s\n%s\n%s\n%s\n" "${method}" "${url_path_and_query}" "${headers}" "${body}" + +# 使用 HMAC-SHA256 算法对请求进行签名,并使用 Base64 编码 +# 签名生成的步骤:使用请求方法、请求路径、请求头信息和 Body,通过密钥加密生成签名 +sign=$(printf "%s\n%s\n%s\n%s\n" "${method}" "${url_path_and_query}" "${headers}" "${body}" | openssl dgst -binary -sha256 -hmac "${server_secret}" | base64) + +# 输出生成的签名值用于调试 +echo "生成的签名: $sign" + +# 构造完整的请求 URL,包括路径和查询参数 +Request_Url="https://cloud.tapapis.cn${url_path_and_query}" + +# 使用 curl 发起 GET 请求,传递时间戳 ts、nonce 和签名 sign 作为请求头 +curl -X GET \ + -H "X-Tap-Ts: ${ts}" \ + -H "X-Tap-Nonce: ${nonce}" \ + -H "X-Tap-Sign: ${sign}" \ + "${Request_Url}" +``` + +
+ + ### 响应数据 | 字段名 | 描述 | 类型 | From 9026edc79ea62a0d28913b8f0198524c316d1950 Mon Sep 17 00:00:00 2001 From: Gavin Date: Tue, 12 Nov 2024 16:41:05 +0800 Subject: [PATCH 08/11] =?UTF-8?q?feat:=20=E5=9B=BD=E5=86=85IAP=20=E5=90=88?= =?UTF-8?q?=E8=A7=84=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn/docs/sdk/start/compliance.mdx | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/cn/docs/sdk/start/compliance.mdx b/cn/docs/sdk/start/compliance.mdx index ab521f4fc..6d79cb986 100644 --- a/cn/docs/sdk/start/compliance.mdx +++ b/cn/docs/sdk/start/compliance.mdx @@ -406,6 +406,50 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in 无 +### 10. TapTap IAP + +- 功能介绍 + +提供 TapTap IAP(In App Purchase) 能力,玩家可以通过 TapTap IAP 快速购买所需要的游戏道具,最终会通过微信支付、支付宝支付等方式完成支付。 + +- 合规调用时机 + +玩家触发游戏内道具购买时进行初始化和调用。 + +- 需要权限 + +| 权限 | 使用目的 | 权限申请时机 | +| ---------------------- | ---------------------- | ---------------------- | +| 网络权限 | 用于访问网络数据 | 用户首次使用该功能时会申请权限 | +| 获取网络状态 | 用于检测当前网络连接是否有效 | 用户首次使用该功能时会申请权限 | + +- 关闭功能的配置方式 + +若要关闭,可在app目录build.gradle中移除对该功能的依赖(详见[文档](https://developer.taptap.cn/docs/sdk/update/guide/#tapsdk-%E5%88%9D%E5%A7%8B%E5%8C%96)),示例如下: + +``` +// implementation("com.taptap.android.payment:iap:latest") +// implementation("com.taptap.android.payment:base:latest") +// implementation("com.taptap.android.payment:alipaycn:latest") +// implementation("com.taptap.android.payment:wechat:latest") +``` + +- 必要个人信息 + +| 必要个人信息 | 使用目的 | 场景 | 收集频次 | +| ------ | ------ | ------ | ------ | +| 系统版本 | 为了确保设备系统兼容、定位解决问题 | 遇到服务故障时针对性进行排查和优化 | 每次应用冷启动获取一次 | +| 设备型号 | 为了确保设备系统兼容、定位解决问题 | 遇到服务故障时针对性进行排查和优化 | 每次应用冷启动获取一次 | +| 设备 CPU 信息 | 为了确保设备系统兼容、定位解决问题 | 遇到服务故障时针对性进行排查和优化 | 每次应用冷启动获取一次 | +| 网络类型 | 为了确保设备系统兼容、定位解决问题 | 遇到服务故障时针对性进行排查和优化 | 每次应用冷启动获取一次 | +| Android ID | 为了确保设备系统兼容、定位解决问题 | 遇到服务故障时针对性进行排查和优化 | 初始化及用户发起授权时获取一次 | +| 设备内存信息 | 为了确保设备系统兼容、定位解决问题 | 遇到服务故障时针对性进行排查和优化 | 每次应用冷启动获取一次 | +| 手机样式 | 为了确保设备系统兼容、定位解决问题 | 遇到服务故障时针对性进行排查和优化 | 每次应用冷启动获取一次 | + +- 可选个人信息 + +无 + ## **四、向最终用户披露 TapSDK 条款** From 644ec3b3088de896ba5a15dd69103299b20bcc6b Mon Sep 17 00:00:00 2001 From: Gavin Date: Fri, 15 Nov 2024 16:00:06 +0800 Subject: [PATCH 09/11] =?UTF-8?q?feat:=20=E5=AE=8C=E6=95=B4IAP=E6=96=87?= =?UTF-8?q?=E6=A1=A3+=E9=9A=90=E7=A7=81=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn/docs/sdk/start/agreement.mdx | 61 +- cn/docs/sdk/start/overview.mdx | 2 + cn/docs/sdk/tap-iap/_category_.json | 5 + cn/docs/sdk/tap-iap/create-merchant.mdx | 123 ++++ cn/docs/sdk/tap-iap/develop/_category_.json | 5 + cn/docs/sdk/tap-iap/develop/android.mdx | 218 ++++++ cn/docs/sdk/tap-iap/develop/sandbox.mdx | 14 + cn/docs/sdk/tap-iap/develop/server.mdx | 688 ++++++++++++++++++ cn/docs/sdk/tap-iap/develop/unity.mdx | 249 +++++++ cn/docs/sdk/tap-iap/faq.mdx | 37 + cn/docs/sdk/tap-iap/operating-manual.mdx | 113 +++ cn/docs/sdk/tap-iap/overview.mdx | 43 ++ hk/docs/sdk/TapPayments/develop/unity.mdx | 6 +- .../current/sdk/TapPayments/develop/unity.mdx | 6 +- 14 files changed, 1553 insertions(+), 17 deletions(-) create mode 100644 cn/docs/sdk/tap-iap/_category_.json create mode 100644 cn/docs/sdk/tap-iap/create-merchant.mdx create mode 100644 cn/docs/sdk/tap-iap/develop/_category_.json create mode 100644 cn/docs/sdk/tap-iap/develop/android.mdx create mode 100644 cn/docs/sdk/tap-iap/develop/sandbox.mdx create mode 100644 cn/docs/sdk/tap-iap/develop/server.mdx create mode 100644 cn/docs/sdk/tap-iap/develop/unity.mdx create mode 100644 cn/docs/sdk/tap-iap/faq.mdx create mode 100644 cn/docs/sdk/tap-iap/operating-manual.mdx create mode 100644 cn/docs/sdk/tap-iap/overview.mdx diff --git a/cn/docs/sdk/start/agreement.mdx b/cn/docs/sdk/start/agreement.mdx index 8a34a0d51..05a43ea7f 100644 --- a/cn/docs/sdk/start/agreement.mdx +++ b/cn/docs/sdk/start/agreement.mdx @@ -2,9 +2,8 @@ title: TapSDK 隐私政策 sidebar_position: 8 --- - -更新日期:2024 年 9 月 30 日 -生效日期:2024 年 9 月 30 日 +更新日期:2024 年 11 月 15 日 +生效日期:2024 年 11 月 15 日 易玩(上海)网络科技有限公司(以下简称“TapTap”或“我们”)通过 TapSDK 向开发者提供多种服务,开发者可以根据自身需求在其应用中接入其中任意一项或多项服务。本文档将向开发者和其用户(以下或称“玩家”)说明 TapSDK 的隐私安全信息,包括 TapSDK 各项服务处理的个人信息范围、处理目的、权限使用情况等。 @@ -381,7 +380,7 @@ sidebar_position: 8 个人信息/权限类型 个人信息/权限名称 - 使用目的 + 使用目的 必要个人信息/权限 @@ -425,7 +424,7 @@ sidebar_position: 8 个人信息/权限类型 个人信息/权限名称 - 使用目的 + 使用目的 必要个人信息/权限 @@ -460,6 +459,48 @@ sidebar_position: 8 +**1.2.10 TapTap IAP** + +1)功能介绍:提供 TapTap IAP(In App Purchase)能力,玩家可以通过 TapTap IAP 快速购买所需要的游戏道具,最终会通过微信支付、支付宝支付等方式完成支付。 + +2)收集信息/获取权限 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
个人信息/权限类型个人信息/权限名称使用目的
必要个人信息/权限系统版本为了确保设备系统兼容、定位解决问题
设备型号
设备 CPU 信息
网络类型
AndroidID
设备内存信息
手机样式
可选个人信息/权限/
+ + 1.3 我们仅为实现 TapSDK 产品和/或服务功能,对所收集的用户个人信息进行处理。若需要将收集的个人信息用于其他目的,我们会以合理方式告知用户,并在获得用户的同意后进行使用。 @@ -503,7 +544,7 @@ sidebar_position: 8 3.2 转让 -通常情况下,除非获得用户的明确同意,我们不会将用户的个人信息转让给任何公司、组织和个人,但以下情况除外: +通常情况下,除非获得用户的明确同意,我们不会将用户的个人信息转让给任何公司、组织和个人,但以下情况除外: 在涉及合并、收购、资产转让或类似的交易时,如涉及到个人信息转让,我们会要求新的持有用户个人信息的公司、组织以不低于本隐私政策所要求的标准继续保护用户的个人信息,否则,我们将要求该公司、组织重新向用户征求授权同意。 3.3 披露 @@ -602,4 +643,10 @@ TapSDK 个人信息保护负责人邮箱:`privacy@taptap.com` 我们将在 15 天内予以回复。 -本页面内容具有多种语言版本,若其他语言版本与简体中文版本发生冲突,应以简体中文版本为准。 \ No newline at end of file +本页面内容具有多种语言版本,若其他语言版本与简体中文版本发生冲突,应以简体中文版本为准。 + + + + + + diff --git a/cn/docs/sdk/start/overview.mdx b/cn/docs/sdk/start/overview.mdx index 537879eee..cb2ba4f8b 100644 --- a/cn/docs/sdk/start/overview.mdx +++ b/cn/docs/sdk/start/overview.mdx @@ -52,6 +52,8 @@ TDS 提供以下技术服务,开发者可以通过在游戏中集成 TapSDK - **APK 加固**:避免游戏包体被破解篡改,保障游戏安全。 +- **内购服务**:TapTap 游戏内购服务为开发者提供了便捷高效的解决方案。接入该服务后,开发者可轻松开放游戏内购,无论是消耗型道具还是非消耗型道具,都能方便地上架售卖。同时,订单查看功能,让开发者对销售情况一目了然。 + 使用对应的服务请先完成[开发者注册](https://developer.taptap.cn/)[开发者注册](https://developer.taptap.io/),之后登录开发者中心开启「游戏服务」。 diff --git a/cn/docs/sdk/tap-iap/_category_.json b/cn/docs/sdk/tap-iap/_category_.json new file mode 100644 index 000000000..9eb851869 --- /dev/null +++ b/cn/docs/sdk/tap-iap/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "内购服务", + "collapsed": true, + "position": 16 +} diff --git a/cn/docs/sdk/tap-iap/create-merchant.mdx b/cn/docs/sdk/tap-iap/create-merchant.mdx new file mode 100644 index 000000000..657cfe975 --- /dev/null +++ b/cn/docs/sdk/tap-iap/create-merchant.mdx @@ -0,0 +1,123 @@ +--- +title: 创建商户 +sidebar_position: 2 +--- + +import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; + +# 创建商户 + +## 准备材料 + +### 1. 营业执照 必填* + +* 内容要求:请提供彩色照片 or 彩色扫描件 or 加盖公章鲜章的复印件,要求正面拍摄,露出证件四角且清晰、完整,所有字符清晰可识别,不得反光或遮挡。不得翻拍、截图、镜像、PS。 +* 格式要求:只支持 JPG、BMP、PNG格式。 +* 大小要求:文件大小不能超过 2 M。 + +### 2. 法定代表人证件 必填* + +法定代表人证件可使用居民身份证或护照。 + +#### 居民身份证 + +* 内容要求:请提供身份证人像面照片及国徽面照片。请提供彩色照片 or 彩色扫描件 or 加盖公章鲜章的复印件,要求正面拍摄,露出证件四角且清晰、完整,所有字符清晰可识别,不得反光或遮挡。不得翻拍、截图、镜像、PS。 +* 格式要求:只支持 JPG、BMP、PNG格式。 +* 大小要求:文件大小不能超过 2 M。 + +#### 护照(可选) + +* 内容要求:请提供护照人像面照片。请提供彩色照片 or 彩色扫描件 or 加盖公章鲜章的复印件,要求正面拍摄,露出证件四角且清晰、完整,所有字符清晰可识别,不得反光或遮挡。不得翻拍、截图、镜像、PS。 +* 格式要求:只支持 JPG、BMP、PNG格式。 +* 大小要求:文件大小不能超过 2 M。 + +### 3. 受益人证件 + +如果公司法定代表人**并非最终受益人(UBO)**,请提供最终受益人证件信息。受益人证件要求同法定代表人证件,此处不赘述。 + +### 4. 网络游戏电子出版物审批(版号)必填* + +* 内容要求:请提供有效期内的游戏版号。请提供彩色照片 or 彩色扫描件 or 加盖公章鲜章的复印件,要求正面拍摄,露出证件四角且清晰、完整,所有字符清晰可识别,不得反光或遮挡。不得翻拍、截图、镜像、PS。 +* 格式要求:只支持 JPG、BMP、PNG格式。 +* 大小要求:文件大小不能超过 2 M。 +* 特殊说明:如果营业执照主体不是版号的运营单位,请提供授权书。 + +### 5. 计算机软件著作权登记证书(软著)必填* + +* 内容要求:请提供彩色照片 or 彩色扫描件 or 加盖公章鲜章的复印件,要求正面拍摄,露出证件四角且清晰、完整,所有字符清晰可识别,不得反光或遮挡。不得翻拍、截图、镜像、PS。 +* 格式要求:只支持 JPG、BMP、PNG格式。 +* 大小要求:文件大小不能超过 2 M。 +* 特殊说明:如果营业执照主体不是软著主体,请提供授权书。 + +### 6. IP 授权书 + +若游戏涉及 IP 合作,请确保已获得合法有效授权,并提供授权书。 + +### 7. 微信开放平台 AppID + +如需开通微信支付,必须提供[微信开放平台的 AppID](https://kf.qq.com/faq/181105JJNbmm181105eUZfee.html)。 + +* 提供应用的 AppID,将开通微信的 App 支付。 +* 提供公众号或小程序的 AppID,将开通微信的 JSAPI 支付。*目前 TapTap 游戏内购服务的 JSAPI 支付能力正在开发中,敬请期待!* + +### 8. App 截图 + +如需开通微信的 App 支付,必须提供以下所有的 App 截图: + +* 游戏商店页截图:游戏上架苹果、华为、小米等主流应用市场的游戏详情页截图,游戏需开放下载,截图需包括商店 Logo、游戏主体信息。TapTap 独家游戏提供 TapTap 游戏详情页截图即可。 +* 游戏首页。 +* 游戏尾页:尾页需包含版号、版号主体、软著等信息。 +* 游戏内截图。 +* 游戏支付页面:需含微信支付。 + +![](https://img.tapimg.com/market/images/59271c9195b3dbec8b9d5a5267804f91.jpg) + +### 9. 联系方式 必填* + +* 客服电话:请填写真实有效的客服电话,将在交易记录中向买家展示,提供咨询服务。请确保电话畅通,以便入驻后微信、支付宝平台将回拨确认。 +* 超级管理员证件:证件要求同法人证件。 + * 如超级管理员即法人,则无需二次提供超管证件。 + * 如超级管理员并非法人,则需额外提供《[业务办理授权函](https://kf.qq.com/faq/220509Y3Yvym220509fQvYR7.html)》。 +* 联系电话:用于接收重要管理信息及日常操作验证码。 +* 邮箱:用于接收日常业务邮件。 + +### 10. 结算方式 必填* + +支付宝支持选择结算至**企业**支付宝账户或银行卡(推荐结算至企业支付宝账户)。微信仅支持选择结算至银行卡。结算至银行卡请提供以下信息: + +* 开户银行 +* 开户名称:需与营业主体相同 +* 银行账号 + +## 发送邮件 + +请将材料整理发送邮件至 [PaymentSupport@taptap.com](mailto:PaymentSupport@taptap.com) 申请创建商户,邮件主题请说明您希望开通内购服务的游戏以及支付方式。 + +## 创建支付宝商户 + +支付宝商户支持通过链接自助创建。 + +在材料审核通过后,TapTap 工作人员将通过邮件回复自助创建商户链接,根据指引操作即可完成。 + +## 创建微信支付商户 + +微信支付商户需 TapTap 工作人员协助开通,创建微信支付商户需要完成以下步骤: + +1. TapTap 工作人员录入材料,向微信提交审核。 +2. 提交审核后,超级管理员需扫描二维码(二维码由 TapTap 工作人员通过邮件回复)确认本次提交材料。 +3. 审核通过后,超级管理员需扫描二维码(二维码由 TapTap 工作人员通过邮件回复)完成账户验证及创建商户签约。账户验证支持以下方式二选一: + * 对公转账确认转账金额; + * 法人使用微信号扫一扫。 +4. 完成签约后,超级管理员需在微信中查看微信消息,开通分账能力。邀请开通分账能力的微信消息由 TapTap 工作人员通过系统发送。 + +## 常见问题 + +### Q:游戏没上线可以申请开通微信 App 支付吗? + +游戏上线后才可以申请开通微信 App 支付。 +但请放心,游戏未上线可以开通支付宝支付并完整使用游戏内购服务。游戏上线提交材料创建微信支付商户后,TapTap 工作人员在后台配置即可开通微信支付,您无需更新游戏。 + +### Q:创建支付宝商户时,结算信息提示“开户名称和商户名称不一致,请补充上传授权函”怎么办? + +您填写的「签约支付宝账号」需和营业执照为同一企业主体。 +如果您无法确认填写的签约支付宝账号的主体,您可以使用其他支付宝账号对其转账,转账页面会显示其账号的主体信息。 \ No newline at end of file diff --git a/cn/docs/sdk/tap-iap/develop/_category_.json b/cn/docs/sdk/tap-iap/develop/_category_.json new file mode 100644 index 000000000..3446da847 --- /dev/null +++ b/cn/docs/sdk/tap-iap/develop/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "开发指南", + "collapsed": true, + "position": 2 +} diff --git a/cn/docs/sdk/tap-iap/develop/android.mdx b/cn/docs/sdk/tap-iap/develop/android.mdx new file mode 100644 index 000000000..1792b6560 --- /dev/null +++ b/cn/docs/sdk/tap-iap/develop/android.mdx @@ -0,0 +1,218 @@ +--- +title: Android 集成指南 +sidebar_position: 2 +--- + +import MultiLang from "/src/docComponents/MultiLang"; +import { Conditional } from "/src/docComponents/conditional"; +import v4SDKVersions from '/src/docComponents/v4SDKVersions'; +import CodeBlock from '@theme/CodeBlock'; + + +## **环境要求** + +- Gradle 版本不低于 6.1.1,Android AGP 插件版本不低于 4.0.1; + +## **准备** + +- 参照 [准备工作](/sdk/access/get-ready/) 所述创建 app,配置 app 参数并且绑定 API 域名 +- 参照 [TapSDK 快速开始](/sdk/access/quickstart/) 配置包名和签名 + +## **SDK 指南** + +### **SDK 集成** + +打开项目的 `project/app/build.gradle` 文件,添加 gradle 配置如下: + + + {`dependencies { + ... + // TapTapIAP dependency + implementation 'com.taptap.android.payment:iap:${v4SDKVersions.taptap.android}' + implementation 'com.taptap.android.payment:base:${v4SDKVersions.taptap.android}' + implementation 'com.taptap.android.payment:wechat:${v4SDKVersions.taptap.android}' + implementation 'com.taptap.android.payment:alipaycn:${v4SDKVersions.taptap.android}' +} +`} + + + + + +### **SDK 初始化** + +添加 TapTapIAP 的依赖项后,您需要初始化 `TapTapIAP` 实例。`TapTapIAP` 是 SDK 与应用的其余部分之间进行通信。`TapTapIAP` 为许多常见的操作提供了方法。 + +首先 在应用启动时需要进行 SDK 初始化, 通过设置 `TapTapSdkOptions`, 完成 SDK 初始化, `TapTapSdk.init` 。 + +这里需要设置对应在开发者后台申请的 `ClientID` 和 `ClientToken`,用于校验是否有权限使用 `TapTapIAP`。 + +```java +TapTapSdkOptions sdkOptions = new TapTapSdkOptions( + "应用的 ClientID", // clientId 开发者平台申请 + "应用的 ClientToken", // clientToken 开发者平台申请 + TapTapRegion.GLOBAL, // 地区 + "", // 分包渠道名称 + "", // 游戏版本, 为空为null会取AppVersion + false, // 是否自动上报GooglePlay内购支付成功事件 仅 [TapTapRegion.GLOBAL] 生效 + false, // 自定义字段是否能覆盖内置字段 + null, // 自定义属性,启动首个预置事件(device_login)会带上这些属性 + null, // OAID证书, 用于上报 OAID 仅 [TapTapRegion.CN] 生效 + false // 是否开启 log,建议 Debug 开启,Release 关闭 +); + +TapTapSdk.init(context, sdkOptions); +``` + +创建 `TapTapIAP`,请使用 `newBuilder()`这里会根据SDK.init所设置的 `ClientID` 和 `ClientToken`校验是否有权限使用 `TapTapIAP`。 + +```java +// 创建 TapTapIAP 实例 + TapTapIAP tapTapIAP = TapTapIAP.newBuilder().build(); + ``` + +### **展示可供购买的商品** + +初始化完成 `TapTapIAP` 后,您就可以查询可售的商品并将其展示给用户了。 + +查询应用内商品详情,请调用 `queryProductDetailsAsync()`。为了处理该异步操作的结果,您还必须指定实现 ` ProductDetailsResponseListener` 接口的监听器。然后,您可以替换 `onProductDetailsResponse()`,该方法会在查询完成时通知监听器,如以下示例所示: + +```java +List queryProductList = new ArrayList<>(); +// 支持批量查询 Product, 设置好对应的 ProductID、ProductType +// ProductType 目前仅支持 ProductType.INAPP +for (int i = 0; i < products.length; i++) { + + String productId = products[i]; + Product product = Product.newBuilder() + .setProductId(productId) + .setProductType(ProductType.INAPP) + .build(); + queryProductList.add(product); +} +QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder() + .setProductList(queryProductList).build(); +tapTapIAP.queryProductDetailsAsync(params, new ProductDetailsResponseListener() { + @Override + public void onProductDetailsResponse(TapPaymentResult result, + List productDetails, List unavailableProductIds) { + ... + + // check TapPaymentResult + // process returned productDetails + } +}); +``` + +### **启动购买流程** + +如需从应用发起购买请求,请从应用的主线程调用 `launchBillingFlow()` 方法。此方法接受对 `BillingFlowParams` 对象的引用,该对象包含通过调用 `queryProductDetailsAsync()` 获取的相关 `ProductDetails` 对象。如需创建 `BillingFlowParams` 对象,请使用 `BillingFlowParams.Builder` 类。 + +```java +// An activity reference from which the billing flow will be launched. +Activity activity = ...; +ProductDetailsParams productDetailsParams = + ProductDetailsParams.newBuilder() + // retrieve a value for "productDetails" by calling queryProductDetailsAsync() + .setProductDetails(productDetails) + .build(); + +BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() + .setProductDetailsParams(productDetailsParams) + .setObfuscatedAccountId("xxx") //Specifies an optional obfuscated string that is uniquely associated with the order(or another information) in your app. + .build(); +// Launch the billing flow +TapPaymentResult result = tapTapIAP.launchBillingFlow(activity, + billingFlowParams, + new PurchaseUpdatedListener() { + @Override + public void onPurchaseUpdated(TapPaymentResult result, Purchase purchases) { + // To be implemented in a later section. + } + } +); +``` + +`launchBillingFlow()` 方法会返回 `TapPaymentResponseCode` 中列出的几个响应代码之一。请务必检查此结果,以确保在启动购买流程时没有错误。`TapPaymentResponseCode` 为 `OK` 表示成功启动。成功调用 `launchBillingFlow()` 后,会向用户展示收银台。 + +### **购买流程中订单状态监听** + +在购买流程中, `TapTapIAP` 会调用 `onPurchasesUpdated()`,以将购买的订单状态变更实时传给实现 PurchasesUpdatedListener 接口的监听器。您可以在初始化时使用 `setListener()` 方法指定监听器。您必须实现 `onPurchasesUpdated()` 来处理可能的响应代码。以下提供了一个 `onPurchasesUpdated()` 示例 : + +```java +@Override +public void onPurchaseUpdated(TapPaymentResult result, Purchase purchase) { + if (result.getResponseCode() == TapPaymentResponseCode.OK + && purchases != null) { + handlePurchase(purchase); + } else if (result.getResponseCode() == TapPaymentResponseCode.USER_CANCELED) { + // Handle an error caused by a user cancelling the purchase flow. + } else { + // Handle any other error codes. + } +} +``` +### **进行商品的发放,且完成订单** + +在用户进行完了任意商品的购买, 请确认为该用户发放对应的商品或者解锁对应的关卡。在确定商品发放之后需要调用 `finishPurchaseAsync` 告知 `TapTapIAP` 已完成商品的发放。以下是个代码实例: + +```java +Purchase purchase = ...; +FinishPurchaseParams params = FinishPurchaseParams.newBuilder() + .setId(purchase.getOrderId()) // Required + .setOrderToken(purchase.getOrderToken()) // Required + .setPurchaseToken(purchase.getPurchaseToken()) // Required + .build(); +tapTapIAP.finishPurchaseAsync(params, new FinishPurchaseResponseListener() { + @Override + public void onFinishPurchaseResponse(TapPaymentResult result, Purchase purchase) { + } +}); +``` +:::tip +确认发放商品非常重要, 如果您没有调用 `finishPurchaseAsync` 来完成订单, 用户将无法再次购买该商品,且该订单将会在 3天后自动退款。 +::: + +### **获取未完成的订单列表** + +使用 `PurchasesUpdatedListener` 监听购买交易变更,无法完全确保您的应用会处理所有购买交易。有时您的应用可能不知道用户进行了部分购买交易。在下面这几种情况下,您的应用可能会跟踪不到或不知道购买交易的发生: + +- **在购买过程中出现网络问题**:用户成功购买了商品并收到了对应渠道的确认消息,但用户设备在通过 `PurchasesUpdatedListener` 收到购买交易的通知之前失去了网络连接。 +- **多部设备**:用户在一部设备上购买了一件商品,然后在切换设备时期望看到该商品。 +- **异常崩溃**:用户在外部购买成功时,应用出现了崩溃的情况。 + +为了处理这些情况,请确保您的应用在 `onResume()` 方法中调用 `tapTapIAP.queryUnfinishedPurchaseAsync()`,以确保所有购买交易都得到正确处理。 + +以下示例展示了如何提取用户的未完成订单列表: + +```java +tapTapIAP.queryUnfinishedPurchaseAsync(new PurchasesResponseListener() { + @Override + public void onQueryPurchasesResponse(TapPaymentResult result, List purchases) { + if (purchases != null) { + // Process Purchases. + ... + ... + } + } + }); +``` + +### **处理 TapPaymentResult 响应代码** + +当使用 `TapTapIAP` 结算库调用触发操作时,该库会返回 `TapPaymentResult` 响应,并将结果告知开发者。例如,如果您使用 `queryProductDetailsAsync` 且返回 `OK` ,并提供正确的 `ProductDetails` 对象;或者返回了其他类型,代表了无法提供 `ProductDetails` 对象的原因。 + +并非所有类型都是错误。下面列举了一些 `TapPaymentResponseCode` 不是错误的: + +- `TapPaymentResponseCode.OK`:代表业务已成功执行。 +- `TapPaymentResponseCode.USER_CANCELED`:代表用户没有完成流程,就离开了页面 + +其他的一些错误类型可以用于调试和上报使用: + +| **可重试的 CODE** | **问题** | **可以尝试的解决方案** | +| ------------------ | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| NETWORK_ERROR | 此错误代表设备和 TapTapIAP 系统之间的网络连接出现问题 | 可以使用简单的重试策略或指数退避算法 | +| ITEM_ALREADY_OWNED | 这个类型表明用户已经购买过 非消耗品 商品, 再次购买时会返回该错误 | 为了避免出现这个问题, 在展示商品界面就提示用户已经购买该商品, 且无法点进进行购买流程. | +| USER_CANCELED | 用户已退出结算流程 | | +| ITEM_UNAVAILABLE | 商品无效, 有可能是商品已经过期或者商品已经被下架 | 确保您通过 `queryProductDetailsAsync` 刷新商品详情。如果商品无效则不在界面上展示给用户 | +| DEVELOPER_ERROR | 这是一个严重错误,表明您未正确使用 API。例如,向 launchBillingFlow 提供不正确的参数可能会导致此错误 | | diff --git a/cn/docs/sdk/tap-iap/develop/sandbox.mdx b/cn/docs/sdk/tap-iap/develop/sandbox.mdx new file mode 100644 index 000000000..a449c9a53 --- /dev/null +++ b/cn/docs/sdk/tap-iap/develop/sandbox.mdx @@ -0,0 +1,14 @@ +--- +title: 沙盒环境 +sidebar_position: 4 +--- + +# 沙盒环境 + +TapTap IAP 沙盒环境进行支付测试, 如果使用沙盒账号发起 IAP, 那么对应所有渠道将按照最低标准进行支付, 以便开发者进行支付测试。 + +## 沙盒账号设置 +进入开发者中心后台, 按照如下步骤设置和添加对应沙盒账号: + +![](https://img.tapimg.com/market/images/7309efbf7c1971d44c73a53494193bb4.png) + diff --git a/cn/docs/sdk/tap-iap/develop/server.mdx b/cn/docs/sdk/tap-iap/develop/server.mdx new file mode 100644 index 000000000..c8b289e22 --- /dev/null +++ b/cn/docs/sdk/tap-iap/develop/server.mdx @@ -0,0 +1,688 @@ +--- +title: 服务端开发指南 +sidebar_position: 3 +--- + +import MultiLang from "/src/docComponents/MultiLang"; + +# 服务端开发指南 + +:::tip +服务通用规则请参考 [请求规则和签算](/sdk/tap-iap/develop/server/#请求规则和签算) +::: + +## 主查服务 + +#### 请求域名: +- `https://cloud-payment.tapapis.com` + + +| ** 接口地址 ** | **Method** | **描述** | +| ----------------------------- | ---------- | -------------------- | +| `/order/v1/info?client_id={{client_id}}&order_id={{order_id}}` | `GET` | 查询订单信息 | +| `/order/v1/unconfirmed?client_id={{client_id}}` | `GET` | 查询未核销的订单列表 | +| `/order/v1/verify?client_id={{client_id}}` | `POST` | 核销订单 | + +### 查询订单信息 + +#### 服务 URL +- https://{{domain}}/order/v1/info?client_id={{client_id}}&order_id={{order_id}} + +#### 请求方式 +- GET + +#### 请求签算 +- 详见 [请求规则和签算](/sdk/tap-iap/develop/server/#请求规则和签算) + +通过订单 ID 查询订单详细信息和支付状态 + +``` +curl -X GET \ + -H 'X-Tap-Sign: {{signature}}' \ + -H 'X-Tap-Ts: {{unix timestamp}}' \ + -H 'X-Tap-Nonce: {{random nonce}}' \ + https://{{domain}}/order/v1/info?client_id={{client_id}}&order_id={{order_id}} +``` + +`data.order` 对象结构见 [订单信息](/sdk/tap-iap/develop/server/#订单信息) + +``` +{ + "data": { + "order": {} + }, + "success": true +} +``` + +### 查询未核销的订单列表 + +#### 服务 URL +- https://{{domain}}/order/v1/unconfirmed?client_id={{client_id}} + +#### 请求方式 +- GET + +#### 请求签算 +- 详见 [请求规则和签算](/sdk/tap-iap/develop/server/#请求规则和签算) + +查询当前未核销的订单列表,正常情况下在用户支付成功后,应通过 verify 接口核销订单并同时保证对用户发货成功。如果因异常原因没有完成核销,可以通过此接口查询,重新 verify 并完成发货。 + +``` +curl -X GET \ + -H 'X-Tap-Sign: {{signature}}' \ + -H 'X-Tap-Ts: {{unix timestamp}}' \ + -H 'X-Tap-Nonce: {{random nonce}}' \ + https://{{domain}}/order/v1/unconfirmed?client_id={{client_id}} +``` + +`data.list` 数组内对象结构见 [订单信息](/sdk/tap-iap/develop/server/#订单信息) + +``` +{ + "data": { + "list": [ + {} + ] + }, + "success": true +} +``` + +### 核销订单 + +#### 服务 URL +- https://{{domain}}/order/v1/verify?client_id={{client_id}} + +#### 请求方式 +- POST[application/json; charset=utf-8] + +#### 请求正文信息 + +| ** 参数名称 ** | ** 必填 ** | ** 格式 ** | ** 描述 ** | +| --------------| --------------| --------------| --------------| +| `order_id` | Y | string | 订单唯一 ID | +| `purchase_token` | Y | string | 用于订单核销的 token | + +#### 请求签算 +- 详见 [请求规则和签算](/sdk/tap-iap/develop/server/#请求规则和签算) + +当支付成功后,核销订单表示已经确认支付结果并已对买家完成发货,订单状态也会从 `charge.succeeded` 变为 `charge.confirmed` + +``` +curl -X POST \ + -H 'X-Tap-Sign: {{signature}}' \ + -H 'X-Tap-Ts: {{unix timestamp}}' \ + -H 'X-Tap-Nonce: {{random nonce}}' \ + -H 'Content-Type: application/json; charset=utf-8' + -d '{"order_id":"{{order_id}}","purchase_token":"{{purchase_token}}"}' + https://{{domain}}/order/v1/verify?client_id={{client_id}} +``` + +`data.order` 对象结构见 [订单信息](/sdk/tap-iap/develop/server/#订单信息) + +``` +{ + "data": { + "order": {} + }, + "success": true +} +``` + +## Webhook 回调 + +:::tip +同样的通知可能会多次发送,商户系统必须正确处理重复通知。 + +推荐做法是:当商户系统收到通知时,首先进行签名验证,然后检查对应业务数据的状态,如未处理,则进行处理;如已处理,则直接返回成功。 + +在处理业务数据时建议采用数据锁进行并发控制,以避免可能出现的数据异常。 +::: + +### Webhook 说明 + +目前 Webhook 支持监听「充值成功」「退款成功」「退款失败」事件。对于「充值成功」建议采取主动核销订单,根据订单状态完成发货。 + +1. 需要依次进入 **TapTap 开发者中心 > 你的游戏 > 游戏服务 > TapPayment > 商品与订单 > API 密钥**,检查是否有已生效的密钥,没有则需要 **添加新的密钥** +2. 需要依次进入 **TapTap 开发者中心 > 你的游戏 > 游戏服务 > TapPayment > 商品与订单 > Webhooks 设置 > 添加**,添加有效的 **充值成功** URL。 + +### Webhook 请求 + +#### 服务 URL +- 由开发者提供,在 Webhooks 设置中添加 + +#### 请求方式 +- POST[application/json; charset=utf-8] + +#### 请求正文信息 + +| ** 参数名称 ** | ** 必填 ** | ** 格式 ** | ** 描述 ** | +| --------------| --------------| --------------| --------------| +| `order` | Y | object | 对象结构见 [订单信息](/sdk/tap-iap/develop/server/#订单信息) | +| `event_type` | Y | string | 事件枚举见 [Webhook的事件枚举](/sdk/tap-iap/develop/server/#webhook的事件枚举) | + +#### 请求签算 +- 详见 [请求规则和签算](/sdk/tap-iap/develop/server/#请求规则和签算) + +``` +curl -X POST \ + -H 'X-Tap-Sign: {{signature}}' \ + -H 'X-Tap-Ts: {{unix timestamp}}' \ + -H 'X-Tap-Nonce: {{random nonce}}' \ + -H 'Content-Type: application/json; charset=utf-8' + -d '{"order":{},"event_type":"charge.succeeded"}' + {{your webhook url}} + +``` + +### Webhook 响应 + +``` +{ + "code": "SUCCESS", + "msg": "" +} +``` + +#### 字段描述 + +| **字段** | **类型** | **是否必须** | **描述** | +| -------- | -------- | ------------ | ---------------------------------------- | +| code | string | Y | 状态码,`SUCCESS` 为接收成功,`FAIL` 或其他均认为失败 | +| msg | string | N | 当接收失败时需返回失败原因 | + +## 请求规则和签算 + +### 请求 Headers + +| **Header** | **是否必须** | **描述** | +| ----------- | ------------ | ------------------------------------------------------------ | +| `X-Tap-Sign` | Y | 接口签算,详见 [签算](/sdk/tap-iap/develop/server/#签算) | +| `X-Tap-Ts` | Y | 请求方当前时间 unix timestamp | +| `X-Tap-Nonce` | Y | 随机数,需要大于等于 6 字节,小于等于 60 字节,每次请求需重新生成 | + +### 请求 Request + +#### 保留参数 + +所有 HTTP METHOD 必传,需要作为查询参数的一部分 + +| **Key** | **描述** | +| --------- | --------------- | +| client_id | 开发平台应用 ID | + +``` +https://{{domain}}/order/v1/info?client_id={{client_id}}&order_id={{order_id}} +``` + +#### 当请求方法是 POST + +HTTP body 需使用 JSON 编码格式传输参数,即请求 headers 中应该携带 `Content-Type: application/json; charset=utf-8` + +``` +curl -X POST \ + -H 'X-Tap-Sign: {{signature}}' \ + -H 'X-Tap-Ts: {{unix timestamp}}' \ + -H 'X-Tap-Nonce: {{random nonce}}' \ + -H 'Content-Type: application/json; charset=utf-8' + -d '{"order_id":{{order_id}},"purchase_token":"{{purchase_token}}"}' + https://{{domain}}/order/v1/verify?client_id={{client_id}} +``` + +### 请求 Response + +#### 请求成功响应 + +``` +{ + "data": {}, + "now": 1640966400, + "success": true +} +``` + +#### 请求异常响应 + +``` +{ + "data": { + "code": 100004, + "msg": "NotFound: Unknown Error", + "error_description": "order not found" + }, + "now": 1640966400, + "success": false +} +``` + +#### 字段描述 + +| **字段** | **类型** | **是否必须** | **描述** | +| -------- | -------- | ------------ | --------------------------- | +| data | object | Y | 业务数据,或异常信息描述 | +| now | int | Y | 服务端时间 (unix timestamp) | +| success | bool | Y | 响应状态,`true` 为成功 | + +异常响应 `data` 字段描述 + +| **字段** | **类型** | **是否必须** | **描述** | +| ----------------- | -------- | ------------ |------------------------------------------------------------| +| code | int | Y | [错误码](/sdk/tap-iap/develop/server/#错误码) | +| msg | string | Y | 通用错误描述 | +| error_description | string | Y | 详细错误描述,辅助理解和解决发生的错误 | + + +### 签算 + +签算采用 HMAC-SHA256 算法 + +#### 密钥获取 +- 可在 **TapTap 开发者中心 > 你的游戏 > 游戏服务 > TapPayment > 商品与订单 > API 密钥** 查看。 + +#### 签算说明 + +sign = HMAC.New(Sha256, "{{Server Secret}}").Hash(message) + +以下为 `message` 组成 + +``` +{method}\n +{url_path_and_query}\n +{headers}\n +{body}\n +``` + +**method:** 请求 HTTP 方法,如 GET、POST。 + +**url_path_and_query:** 完整请求路径及参数,如 /service/v1/method?client_id={{client_id}}&foo={{foo}}&bar={{bar}}&foo_bar={{foo_bar}} + +**headers:** 所有 `X-Tap-` 前缀的 headers 组合,将 keys 按 ASCII-code order 排序后以换行符 \n 为分隔符拼接。如 {key1}:{value1}\n{key2}:{value2}\n{key3}:{value3}。**为避免不同网络框架导致 keys 的排序结果不一致,签算时需要执行 key 转小写操作 key = tolower(key)** + +**body:** 请求体,如果请求体为空,则最后一行仅为一个 \n + +以下为请求体为空时的 `message` 组成 + +``` +{method}\n +{url_path_and_query}\n +{headers}\n +\n +``` + +:::tip +请求体 body,无需处理请求参数的顺序。建议用 String 接收 Webhook 请求的 RequestBody,验证请求签算后,再完成数据的反序列化 +::: + + + + +<> + +```java +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpClient; +import java.net.http.HttpResponse; +import java.util.*; +import java.util.stream.Collectors; +public class SignatureExample { + + public static String signRequest(String method, URI uri, String body, Map> headers, String secret) throws Exception { + String urlPathAndQueryPart = uri.getRawPath() + (uri.getRawQuery() != null ? "?" + uri.getRawQuery() : ""); + String headersPart = getHeadersPart(headers); + + // 包含请求体的签名字符串部分 + String signParts = method.toUpperCase() + "\n" + urlPathAndQueryPart + "\n" + headersPart + "\n" + body + "\n"; + + System.out.println("Sign Parts:\n" + signParts); + + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); + sha256_HMAC.init(secretKey); + + byte[] hash = sha256_HMAC.doFinal(signParts.getBytes()); + return Base64.getEncoder().encodeToString(hash); + } + + private static String getHeadersPart(Map> headers) throws Exception { + TreeMap sortedHeaders = new TreeMap<>(); + headers.forEach((key, value) -> { + String lowerKey = key.toLowerCase(); + if (lowerKey.equals("x-tap-sign")) { + return; + } + if (lowerKey.startsWith("x-tap-")) { + if (value.size() > 1) { + throw new RuntimeException("Invalid header, " + lowerKey + " has multiple values"); + } + sortedHeaders.put(lowerKey, value.get(0)); + } + }); + + return sortedHeaders.entrySet().stream() + .map(entry -> entry.getKey() + ":" + entry.getValue()) + .collect(Collectors.joining("\n")); + } + + public static void main(String[] args) { + try { + String secret = "VRy8aS2xbwImQUwtxc6vs4v51DaJWdlO"; + String body = "{\"event_type\":\"charge.succeeded\",\"order\":{\"order_id\":\"1790288650833465345\",\"purchase_token\":\"rT2Et9p0cfzq4fwjrTsGSacq0jQExFDqf5gTy1alp+Y=\",\"client_id\":\"o6nD4iNavjQj75zPQk\",\"open_id\":\"4+Axcl2RFgXbt6MZwdh++w==\",\"user_region\":\"US\",\"goods_open_id\":\"com.goods.open_id\",\"goods_name\":\"TestGoodsName\",\"status\":\"charge.succeeded\",\"amount\":\"19000000000\",\"currency\":\"USD\",\"create_time\":\"1716168000\",\"pay_time\":\"1716168000\",\"extra\":\"1111111111111111111\"}}"; + URI uri = new URI("https://example.com/my-service/v1/my-method"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() + .uri(uri) + .header("Content-Type", "Content-Type: application/json; charset=utf-8") + .header("X-Tap-Ts", "1716168000") + .header("X-Tap-Nonce", "V7v7zJ"); + + // Considering body to be added for a POST request + HttpRequest request = requestBuilder + .POST(HttpRequest.BodyPublishers.ofString(body)) + .build(); + + String method = "POST"; // Since we are using the POST method in this example + String signature = signRequest(method, uri, body, request.headers().map(), secret); + System.out.println("Signature: " + signature); + } catch (Exception e) { + e.printStackTrace(); + } + } +} +``` + + +<> + +```go +package main + +import ( + "bytes" + "context" + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "fmt" + "io" + "net/http" + "sort" + "strings" +) + +func main() { + //nolint:gosec + secret := "VRy8aS2xbwImQUwtxc6vs4v51DaJWdlO" + body := []byte(`{"event_type":"charge.succeeded","order":{"order_id":"1790288650833465345","purchase_token":"rT2Et9p0cfzq4fwjrTsGSacq0jQExFDqf5gTy1alp+Y=","client_id":"o6nD4iNavjQj75zPQk","open_id":"4+Axcl2RFgXbt6MZwdh++w==","user_region":"US","goods_open_id":"com.goods.open_id","goods_name":"TestGoodsName","status":"charge.succeeded","amount":"19000000000","currency":"USD","create_time":"1716168000","pay_time":"1716168000","extra":"1111111111111111111"}}`) + url := "https://example.com/my-service/v1/my-method" + method := "POST" + header := http.Header{ + "Content-Type": {"Content-Type: application/json; charset=utf-8"}, + "X-Tap-Ts": {"1716168000"}, + "X-Tap-Nonce": {"V7v7zJ"}, + } + ctx := context.Background() + req, _ := http.NewRequestWithContext(ctx, method, url, bytes.NewBuffer(body)) + req.Header = header + sign, err := Sign(req, secret) + if err != nil { + panic(err) + } + req.Header.Set("X-Tap-Sign", sign) + fmt.Println(sign) +} + +// Sign signs the request. +func Sign(req *http.Request, secret string) (string, error) { + methodPart := req.Method + urlPathAndQueryPart := req.URL.RequestURI() + headersPart, err := getHeadersPart(req.Header) + if err != nil { + return "", err + } + bodyPart, err := io.ReadAll(req.Body) + if err != nil { + return "", err + } + signParts := methodPart + "\n" + urlPathAndQueryPart + "\n" + headersPart + "\n" + string(bodyPart) + "\n" + fmt.Println(signParts) + h := hmac.New(sha256.New, []byte(secret)) + h.Write([]byte(signParts)) + rawSign := h.Sum(nil) + sign := base64.StdEncoding.EncodeToString(rawSign) + return sign, nil +} + +// getHeadersPart returns the headers part of the request. +func getHeadersPart(header http.Header) (string, error) { + var headerKeys []string + for k, v := range header { + k = strings.ToLower(k) + if !strings.HasPrefix(k, "x-tap-") { + continue + } + if k == "x-tap-sign" { + continue + } + if len(v) > 1 { + return "", fmt.Errorf("invalid header, %q has multiple values", k) + } + headerKeys = append(headerKeys, k) + } + sort.Strings(headerKeys) + headers := make([]string, 0, len(headerKeys)) + for _, k := range headerKeys { + headers = append(headers, fmt.Sprintf("%s:%s", k, header.Get(k))) + } + return strings.Join(headers, "\n"), nil +} +``` + + + +<> + +```python +import base64 +import hashlib +import hmac +from typing import Dict, List +from urllib.parse import urlparse + +def sign_request(method: str, url: str, body: str, headers: Dict[str, List[str]], secret: str) -> str: + # 提取URL路径和查询字符串部分 + parsed_url = urlparse(url) + url_path_and_query = parsed_url.path + ('?' + parsed_url.query if parsed_url.query else '') + + # 获取符合条件的头部信息并排序 + headers_part = get_headers_part(headers) + + # 拼接签名字符串 + sign_parts = f"{method}\n{url_path_and_query}\n{headers_part}\n{body}\n" + + print("Sign Parts:\n", sign_parts) + + # 使用HMAC SHA256算法生成签名 + raw_sign = hmac.new(secret.encode(), sign_parts.encode(), hashlib.sha256).digest() + + # 对签名进行Base64编码 + sign = base64.b64encode(raw_sign).decode() + + return sign + +def get_headers_part(headers: Dict[str, List[str]]) -> str: + # 筛选和排序头部 + headers = {k.lower(): v for k, v in headers.items() if k.lower().startswith('x-tap-') and k.lower() != "x-tap-sign"} + header_keys = sorted(headers.keys()) + + # 组装头部字符串 + headers_str = '\n'.join(f"{k}:{headers[k][0]}" for k in header_keys if len(headers[k]) == 1) + + if any(len(headers[k]) > 1 for k in header_keys): + raise ValueError("Invalid header: has multiple values") + + return headers_str + +# 示例使用 +secret = "VRy8aS2xbwImQUwtxc6vs4v51DaJWdlO" +url = "https://example.com/my-service/v1/my-method" +method = "POST" +body = '{"event_type":"charge.succeeded","order":{"order_id":"1790288650833465345",' \ + '"purchase_token":"rT2Et9p0cfzq4fwjrTsGSacq0jQExFDqf5gTy1alp+Y=","client_id":"o6nD4iNavjQj75zPQk",' \ + '"open_id":"4+Axcl2RFgXbt6MZwdh++w==","user_region":"US","goods_open_id":"com.goods.open_id",' \ + '"goods_name":"TestGoodsName","status":"charge.succeeded","amount":"19000000000","currency":"USD",' \ + '"create_time":"1716168000","pay_time":"1716168000","extra":"1111111111111111111"}}' +headers = { + "Content-Type": ["Content-Type: application/json; charset=utf-8"], + "X-Tap-Ts": ["1716168000"], + "X-Tap-Nonce": ["V7v7zJ"], +} + +try: + sign = sign_request(method, url, body, headers, secret) + print("Signature: ", sign) +except Exception as e: + print("Error: ", str(e)) + +``` + + + +<> + +```php + $value) { + $key = strtolower($key); + if (count($value) > 1) { + throw new Exception("Multiple values for header: " . $key); + } + if ($key === "x-tap-sign") { + continue; + } + if (strpos($key, 'x-tap-') === 0) { + $signHeaders[$key] = $value; // Assuming each header has a single value + } + } + $headerKeys = []; + foreach ($signHeaders as $key => $value) { + if (!(strpos($key, 'x-tap-') === 0)) { + continue; + } + $headerKeys[] = $key; + } + sort($headerKeys); + $headerParts = []; + foreach ($headerKeys as $key) { + $headerParts[] = $key . ':' . $signHeaders[$key][0]; + } + return implode("\n", $headerParts); +} + +// 示例使用 +$secret = "VRy8aS2xbwImQUwtxc6vs4v51DaJWdlO"; +$url = "https://example.com/my-service/v1/my-method"; +$method = "POST"; +$body = '{"event_type":"charge.succeeded","order":{"order_id":"1790288650833465345","purchase_token":"rT2Et9p0cfzq4fwjrTsGSacq0jQExFDqf5gTy1alp+Y=","client_id":"o6nD4iNavjQj75zPQk","open_id":"4+Axcl2RFgXbt6MZwdh++w==","user_region":"US","goods_open_id":"com.goods.open_id","goods_name":"TestGoodsName","status":"charge.succeeded","amount":"19000000000","currency":"USD","create_time":"1716168000","pay_time":"1716168000","extra":"1111111111111111111"}}'; +$headers = [ + "Content-Type" => ["Content-Type: application/json; charset=utf-8"], + "X-Tap-Ts" => ["1716168000"], + "X-Tap-Nonce" => ["V7v7zJ"] +]; +try { + $sign = signRequest($method, $url, $body, $headers, $secret); + echo "Signature: " . $sign . "\n"; +} catch (Exception $e) { + echo "Error: " . $e->getMessage() . "\n"; +} + +``` + + + + + +上述示例签算结果 + +``` +# 参与签算部分 +POST\n +/my-service/v1/my-method\n +x-tap-nonce:V7v7zJ\n +x-tap-ts:1716168000\n +{"event_type":"charge.succeeded","order":{"order_id":"1790288650833465345","purchase_token":"rT2Et9p0cfzq4fwjrTsGSacq0jQExFDqf5gTy1alp+Y=","client_id":"o6nD4iNavjQj75zPQk","open_id":"4+Axcl2RFgXbt6MZwdh++w==","user_region":"US","goods_open_id":"com.goods.open_id","goods_name":"TestGoodsName","status":"charge.succeeded","amount":"19000000000","currency":"USD","create_time":"1716168000","pay_time":"1716168000","extra":"1111111111111111111"}}\n + +# 签算结果 (X-Tap-Sign) +PyKQzlI65e0I9noVxcQc7FPU3nEyEFHKfRde65F6vhI= +``` + +## 通用对象结构描述 + +### 订单信息 + +| **参数** | **类型** | **是否必须** | **描述** | +| -------------- | -------- | ------------ | ------------------------------------------------------------ | +| order_id | string | Y | 订单唯一 ID | +| purchase_token | string | Y | 用于订单核销的 token | +| client_id | string | Y | 应用的 Client ID | +| open_id | string | Y | 用户的开放平台 ID | +| user_region | string | Y | [用户地区] | +| goods_open_id | string | Y | 商品唯一 ID | +| goods_name | string | Y | 商品名称 | +| status | string | Y | [订单状态](/sdk/tap-iap/develop/server/#订单状态) | +| amount | string | Y | 金额(本币金额 x 1,000,000) | +| currency | string | Y | [币种] | +| create_time | string | Y | 创建时间 | +| pay_time | string | Y | 支付时间 | +| extra | string | Y | 商户自定义数据,如角色信息等,长度不超过 255 UTF-8 字符 | + +#### 订单状态 + +| **订单状态** | **描述** | +| ---------------- | ------------ | +| `charge.pending` | 待支付 | +| `charge.succeeded` | 支付成功 | +| `charge.confirmed` | 已核销 | +| `charge.overdue` | 支付超时关闭 | +| `refund.pending` | 退款中 | +| `refund.succeeded` | 退款成功 | +| `refund.failed` | 退款失败 | +| `refund.rejected` | 退款被拒绝 | + +### Webhook的事件枚举 + +| **event_type** | **描述** | +| ---------------- | -------- | +| `charge.succeeded` | 充值成功 | +| `refund.succeeded` | 退款成功 | +| `refund.failed` | 退款失败 | + +## 错误码 + +| **code** | **描述** | +| -------- | ------------ | +| `-1` | 非法请求 | +| `100000` | 支付服务异常 | +| `100004` | 订单不存在 | +| `100018` | 订单验证错误 | diff --git a/cn/docs/sdk/tap-iap/develop/unity.mdx b/cn/docs/sdk/tap-iap/develop/unity.mdx new file mode 100644 index 000000000..120b92ce2 --- /dev/null +++ b/cn/docs/sdk/tap-iap/develop/unity.mdx @@ -0,0 +1,249 @@ +--- +title: Unity 集成指南 +sidebar_position: 1 +--- + + +import MultiLang from "/src/docComponents/MultiLang"; +import v4SDKVersions from '/src/docComponents/v4SDKVersions'; +import CodeBlock from '@theme/CodeBlock'; + + +## 环境要求 + +- 支持 Unity 2019.4 及以上版本 + +## 准备 + +- 参照 [准备工作](/sdk/access/get-ready/) 所述创建 app,配置 app 参数并且绑定 API 域名 +- 参照 [TapSDK 快速开始](/sdk/access/quickstart/) 配置包名和签名 + +## 获取 SDK + +:::tip +Unity 2020.3.15 之前的版本为了避免后面构建报错建议升级 Gradle 版本,可参考该 [Gradle 升级步骤文档](/sdk/tap-iap/faq/#1unity-2020315-之前的版本升级-gradle-版本的操作步骤)。 +::: + +以下介绍了**通过 Unity Package Manager 导入**或者**修改 Packages/manifest.json 配置文件引入**两种方式,根据项目需要,任选其一即可: + +### 1、通过 Package Manager 可视化界面引入 + +因为 TapTap IAP 依赖 **EDM4U(External Dependency Manager for Unity)** 来处理 Android 相关的依赖,因此引入依赖的步骤是**先安装 EDM4U 库,然后安装 TapTap IAP**。 + +#### 安装 EDM4U + +下面介绍了两种方式安装 EDM4U,分别是通过 **OpenUPM 安装**以及**手动下载安装**; + +- **方法一:通过 OpenUPM 安装 EDM4U** + +EDM4U 可以通过 OpenUPM 进行下载,开发者可以通过 **Edit > Project Settings > Package Manager** 来注册使用 OpenUPM。 + +![](https://capacity-files.lcfile.com/gpS8BcTVJIdSpMxyDipIWORX4Gb2filA/NdoQbmRRvovet4x3LGUcsTXWnjb.png) + +- **方法二:手动下载安装** + +开发者可以通过 [Google APIs for Unity](https://developers.google.com/unity/archive#external_dependency_manager_for_unity) 下载 UPM 安装包. 并且通过[从本地磁盘安装](https://docs.unity3d.com/Manual/upm-ui-local.html)的方式进行安装。 + +#### 安装 TapTap IAP + +TapTap IAP 可以通过 NPMJS 进行安装, 开发者可以通过 **Edit > Project Settings > Package Manager** 来注册使用 NPMJS。 + +![](https://capacity-files.lcfile.com/sJDhXK4vAwAYX7BpQFh1SrQzeUmXk165/taptap.png) + +<> + 配置完成以后就可以在 Window > Package Manager > My Registries 中安装 TapTapSDK IAP {v4SDKVersions.taptap.unity}。 + 如果安装目录中没有 TapTapSDK IAP, 请尝试在 Edit > Project Settings > Package Manager 中重新注册 NPMJS。 + + +![](https://img.tapimg.com/market/images/cda0911e47723fba9bee9a29ef62260f.png) + + +### 2、修改 Packages/manifest.json 文件 + + + {` "dependencies": { + "com.taptap.sdk.iap": "${v4SDKVersions.taptap.unity}", //添加 TapTap IAP + "com.unity.purchasing": "3.1.0", //TapTap IAP 所须依赖 + "com.google.external-dependency-manager": "1.2.179", //TapTap IAP 所须依赖 + "com.taptap.sdk.core": "${v4SDKVersions.taptap.unity}", + ... + ... + }, + + // 添加 Registries + "scopedRegistries": [ + { + "name": "taptap", + "url": "https://registry.npmjs.org", + "scopes": ["com.tapsdk", "com.taptap", "com.leancloud"] + }, + { + "name": "openupm", + "url": "https://package.openupm.com", + "scopes": [ + "com.google" + ] + } + ]`} + + + +:::tip + +**处理安卓依赖失败** + +EDM4U 会自动监控 TapTap IAP 引入的 Android 依赖,但是在某些特殊情况下自动依赖解析可能失败,开发者可以通过 **Assets > External Dependency Manager > Android Resolver > Force Resolve** 来强制依赖解析。在测试之前请确认对于 `com.taptap.android.payment:unity` 的依赖被加到了 mainTemplate.gradle 文件中,如果 EDM4U 没有自动添加这个依赖,开发者也可以通过手动添加的方式处理依赖。 +::: + +## SDK 指南 + +我们在 [Unity IAP](https://unity.com/products/iap) 的框架下实现了一个新的商店实现,通过这种方式降低已经有 Google Play 或者 App Store 内购的 app 的接入成本。如果开发者是第一次接触到内购的流程,我们会在接下来简要说明 Unity 的内购流程,开发者也可以在 Unity 的[官方文档](https://docs.unity3d.com/Packages/com.unity.purchasing@4.8/manual/Overview.html) 中了解有关内购的详细内容。 + +### 初始化 Unity Gaming Services + +调用 `UnityServices.InitializeAsync()` 来一次性初始化 Unity Gaming Services。 这个方法会返回一个 `Task` 对象,开发者可以通过这个对象来获取初始化的状态信息。 + +```cs +using System; +using Unity.Services.Core; +using Unity.Services.Core.Environments; +using UnityEngine; + +public class InitializeUnityServices : MonoBehaviour +{ + public string environment = "production"; + + async void Start() + { + try + { + var options = new InitializationOptions() + .SetEnvironmentName(environment); + + await UnityServices.InitializeAsync(options); + } + catch (Exception exception) + { + // An error occurred during services initialization. + } + } +} +``` + +### 初始化 IAP + +确保你在初始化 IAP 的时候添加 `TapPurchasingModule`,并且设置正确的 `clientId` 和 `clientToken`。 + +```cs +using UnityEngine; +using UnityEngine.Purchasing; +using UnityEngine.Purchasing.Extension; +using TapSDK.IAP; + +public class MyIAPManager : IStoreListener { + + private IStoreController controller; + private IExtensionProvider extensions; + + public MyIAPManager () { + var builder = ConfigurationBuilder.Instance(TapPurchasingModule.Instance); + builder.Configure().SetClientId("Your Client ID Here"); + builder.Configure().SetClientToken("Your Client Token Here"); + builder.Configure().SetRegionCode(1); // 0: CN, 1: GLOBAL + builder.AddProduct("100_gold_coins", ProductType.Consumable); + + UnityPurchasing.Initialize (this, builder); + } + + /// + /// Called when Unity IAP is ready to make purchases. + /// + public void OnInitialized (IStoreController controller, IExtensionProvider extensions) + { + this.controller = controller; + this.extensions = extensions; + } + + /// + /// Called when Unity IAP encounters an unrecoverable initialization error. + /// + /// Note that this will not be called if Internet is unavailable; Unity IAP + /// will attempt initialization until it becomes available. + /// + public void OnInitializeFailed (InitializationFailureReason error) + { + } + + public void OnInitializeFailed(InitializationFailureReason error, string str) + { + } + + + /// + /// Called when a purchase completes. + /// + /// May be called at any time after OnInitialized(). + /// + public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs e) + { + return PurchaseProcessingResult.Complete; + } + + /// + /// Called when a purchase fails. + /// + public void OnPurchaseFailed (Product i, PurchaseFailureReason p) + { + } +} +``` + +### 发起内购流程 + +在 IAP 被成功初始化以后,你可以通过调用 `IStoreController.InitiatePurchase` 来发起内购流程。 + +```cs +// Example method called when the user taps a 'buy' button +// to start the purchase process. +public void OnPurchaseClicked(string productId) { + controller.InitiatePurchase(productId, "developerPayload, e.g. user_id or order_id"); +} +``` + +### 处理购买结果 + +购买完成时会调用商店监听器的 ProcessPurchase 函数。无论用户购买任何物品,您的应用程序都应该履单;例如,解锁本地内容或将购买收据发送给服务器以更新服务器端游戏模型。 + +此过程会返回结果以指出应用程序是否已完成对购买的处理: + +| 结果 | 描述 | +| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| PurchaseProcessingResult.Complete | 应用程序已完成对购买的处理,不应再次向应用程序通知此事。 | +| PurchaseProcessingResult.Pending | 应用程序仍在处理购买,除非调用 `IStoreController` 的 `ConfirmPendingPurchase` 函数,否则将在下一次应用程序启动时再次调用 `ProcessPurchase`。 | + +请注意,在初始化成功后,随时可能调用 `ProcessPurchase`。如果应用程序在 `ProcessPurchase` 处理程序执行过程中崩溃,那么在 Unity IAP 下次初始化时会再次调用它,因此您可能希望实现自己的额外重复数据删除功能。 + +#### 可靠性 + +Unity IAP 要求明确确认购买以确保在网络中断或应用程序崩溃的情况下可靠地完成购买。在应用程序离线时完成的任何购买都将在下次初始化时发送给应用程序。 + +#### 立即完成购买 + +返回 `PurchaseProcessingResult.Complete` 时,Unity IAP 立即完成交易(如下图所示)。 + +如果您正在销售可消耗商品并从服务器履行订单(例如,在网络游戏中提供游戏币),那么您不得返回 `PurchaseProcessingResult.Complete`。 + +否则,如果在保存到云端之前卸载应用程序,则购买的消耗品将面临丢失的风险。 + +![](https://capacity-files.lcfile.com/PYPIumvCKtaAwhJOPAf1qaApNMOdQ9nF/VrHVbfdKUoCHgXxmOYkccZLMn8e.png) + +#### 将购买保存到云端 + +如果要将消耗品购买交易保存到云端,您必须返回 `PurchaseProcessingResult.Pending`,并且仅在成功保存购买时才调用 `ConfirmPendingPurchase`。 + +返回 `Pending` 时,Unity IAP 会在底层商店中保持交易为未结 (open) 状态,直至确认为已处理为止,因此确保了即使在消耗品处于此待处理状态时用户重新安装您的应用程序,消耗品购买交易也不会丢失。 + +![](https://capacity-files.lcfile.com/zDX7oMjWBju6ME0K9i4zym9OOuIgCvrx/TFgMbu4JhohID1xHBnhcet7nnth.png) + +## 调试 +**我们当前只提供了 Android 的库实现, 请在 Android 环境下进行各功能调试**(其他平台会逐步补充完善)。 \ No newline at end of file diff --git a/cn/docs/sdk/tap-iap/faq.mdx b/cn/docs/sdk/tap-iap/faq.mdx new file mode 100644 index 000000000..0b34bd68a --- /dev/null +++ b/cn/docs/sdk/tap-iap/faq.mdx @@ -0,0 +1,37 @@ +--- +title: 常见问题 +sidebar_position: 5 +--- + +### 1、Unity 2020.3.15 之前的版本升级 Gradle 版本的操作步骤 + +在 `Player Settings` -> `Player` -> `Android Tab` -> `Publish Settings` -> `Build`,然后勾选 **Custom Base Gradle Template**、**Custom Launcher Gradle Template**、**Custom Main Gradle Template**。 + +![](https://capacity-files.lcfile.com/5nSUEX6IWVRkwu4Nep1pXo6vUnl9VppH/%E5%8D%87%E7%BA%A7gradle_1.png) + +以下更改应用于 `Assets/Plugins/Android/` 该文件夹下生成的三个文件 `mainTemplate.gradle`、`launcherTemplate.gradle`、`baseProjectTemplate.gradle`。 + +打开 `baseProjectTemplate.gradle` 修改文件内容: + +```groovy +dependencies { + ... + // 将 3.x.0 版本修改为 4.0.0 + //classpath 'com.android.tools.build:gradle:3.x.0' + classpath 'com.android.tools.build:gradle:4.0.0' +} +``` + +分别打开 `mainTemplate.gradle` 和 `launcherTemplate.gradle` 文件,找到 `lintOptions` 标签, 分别添加 **checkReleaseBuilds false** 配置: + +```groovy +lintOptions { + abortOnError false + checkReleaseBuilds false +} +``` + + +同时,为了将 [Gradle 版本和 Android Gradle Plugin 版本对应](https://developer.android.com/studio/releases/gradle-plugin#expandable-1),需要更新 Gradle 版本,下载 [6.5.0 版本的 Gradle](https://services.gradle.org/distributions/gradle-6.5-all.zip),解压后放到自定义的文件夹中,同时**不**勾选 Unity 中的 `Preferences` -> `External Tools`-> `Android` -> `Gradle Installed with Unity(recommend)`,改为选择解压后 Gradle 文件夹的位置,如 `/gradle-6.5.0`。 + +![](https://capacity-files.lcfile.com/hrkFCRy9VuLapvsanFm6nhpkHEEz0qVE/%E5%8D%87%E7%BA%A7gradle_2.png) \ No newline at end of file diff --git a/cn/docs/sdk/tap-iap/operating-manual.mdx b/cn/docs/sdk/tap-iap/operating-manual.mdx new file mode 100644 index 000000000..e7e477e51 --- /dev/null +++ b/cn/docs/sdk/tap-iap/operating-manual.mdx @@ -0,0 +1,113 @@ +--- +title: 系统操作手册 +sidebar_position: 4 +--- + +# 一、商品管理 + +若要在游戏中提供内购商品,必须在 TapTap 开发者服务中心录入内购商品信息,并添加到你的游戏内。每个商品须关联一个游戏应用(Client),并且只能用于该游戏。在使用过程中,你可以创建或删除商品,也可以修改完善现有商品的信息。 + +## 创建游戏内商品 + +在创建商品之前,请务必仔细规划您的产品 ID。商品 ID 对于您的游戏来说必须是唯一的,并且在创建后不能更改或重复使用。 + +- 商品 ID 必须以数字或字母开头,长度不超过 30 个字符,可以包含数字 (0-9)、英文字母 (a-z/A-Z)、下划线 (_) 和句点 (.) +- 创建商品后,您无法更改或重复使用商品 ID + +### 创建单个商品 + +1. 前往 TapTap 开发者服务中心,选择「游戏服务」-「内购服务」; + +2. 点击「添加商品」,在弹出的表单中填写您的商品详细信息; + + - 商品类型:消耗型和非消耗型商品,详情请参见[商品类型](/sdk/tap-iap/overview) + - 商品 ID:商品的唯一标识,创建后不可更改和重复使用; + - 商品名称:商品的短名称,用户可见。建议保持在 80 个字符以内; + - 商品描述:对商品内容的细节描述,建议保持在 100 个字符以内; + - 商品定价:期望售卖的价格,默认以美元定价,开发者可下载所有定价等级查看不同国家的价格; + +3. 完成信息填写后,点击「提交审核」并等待审核结果; + +4. 审核通过后,如需商品生效,可点击商品对应操作列的「上架」按钮即可; + + +> 注意同一个游戏内商品 ID 不能重复,提交后将不可更改,删除后也无法重复使用,请仔细规划。商品在未上架状态时均可修改名称、描述、价格等信息,上架后的商品不可修改信息。具体见「编辑/修改商品」。 + + +![mahua](https://capacity-files.lcfile.com/GSpWNUzJ025ypkp42jD180Ko7u9wDiUA/add_sku.png) + +## 批量创建多个商品 + +1. 如需同时创建多个游戏内购商品,您可以选择使用「批量导入」功能,上传包含每个商品详细信息的 CSV 文件; + +2. 前往 TapTap 开发者服务中心,选择「游戏服务」-「内购服务」; + +3. 点击「批量导入」: + + - 下载模版; + - 上传商品详细信息 CSV 文件; + - 请确保每个商品都为单独一行,单次上传不得超过 100 个商品,下载模板; + - 当商品详细信息 CSV 中的商品 ID 与后台列表中现有商品 ID 匹配时,此次商品详细信息 CSV 中的商品不被上传; + +> 商品详细信息 CSV 文件上传成功后,系统将直接提交审核,若上传了系统不支持的语言,则会忽略该语言内容并由默认语言替代。 + +![tappay](https://capacity-files.lcfile.com/6GwDJdk5zVDaVp1znwrPRUEx1TcmjQC5/add_sku_batch.png) + +## 编辑/修改商品 + +| 商品状态 | 编辑与操作 | +| ---- | ---- | +| 审核通过,待上架 | 可修改商品名称、商品说明 / 可上架 / 可删除 | +| 审核失败 | 可修改商品名称、商品说明 / 可删除 | +| 已上架 | 可修改商品名称、商品说明 / 可下架 | +| 已下架 | 可删除 | + +## 商品状态说明 + +* __审核中__:商品在发布之前需要提交审核,审核通过则进入待上架状态,审核失败会给出失败原因,需要根据失败原因进行修改后重新提交; + +* __审核通过__:审核通过的商品,处于待上架状态,可随时发布上架,上架的商品才会在生产环境生效; + +* __已上架__:上架后的商品,会在生产环境生效; + +* __已下架__:下架的商品,无法在生产环境使用。如用户点击该商品后提示“该商品已下架”; + +* __已删除__:开发者可以删除商品,删除的商品不可再复用; + +## 语言和本地化 + +如果你的游戏会在不同的国家/地区发布,那么也建议为你的商品添加本地化信息。通过添加不同地区的语言完成本地化信息的录入。 + +![tappay](https://capacity-files.lcfile.com/RuxW5n9niJRDFIVVAa2uOURPHbnpgx4F/product-multilingual.png) + +# 二、管理订单 + +你可以通过 TapTap 开发者服务中心的「游戏服务」-「内购服务」-「交易列表」来查看游戏内购买商品(IAP)的销售订单 + +![tappay](https://capacity-files.lcfile.com/8WMyxhKLhNA1SniirMSVSOt56kS2z2wb/tappay-orders.png) + +## 查找订单 + +TapTap IAP 支持多种查询方式: + +* __按用户标识查询__:输入用户的 TapTap ID,即可查询到当前用户购买的所有订单; + +* __按订单号查询__:用户在游戏内购买时创建的 TapTap 订单号; + +* __按交易流水号查询__:开发者自定义的订单 ID; + +* __按订单状态查询__:根据订单交易状态查询,包括“支付中”、“已支付”、“已验证”、“已过期”、“已退款”等; + +* __按订单时间查询__:筛选用户订单发生的日期查询; + +## 订单状态 + +订单页面会显示每一笔用户购买的状态,如下: + +| 订单支付状态 | 说明 | +| ---- | ---- | +| 支付中 | 用户还未完成付款,或系统正在处理订单 | +| 订单已支付 | 用户完成付款,系统已成功向用户收款 | +| 订单已过期 | 订单长时间未进行付款,或付款已取消 | + + diff --git a/cn/docs/sdk/tap-iap/overview.mdx b/cn/docs/sdk/tap-iap/overview.mdx new file mode 100644 index 000000000..903eeeb1e --- /dev/null +++ b/cn/docs/sdk/tap-iap/overview.mdx @@ -0,0 +1,43 @@ +--- +title: 功能介绍 +sidebar_position: 1 +--- + +# 游戏内购服务功能介绍 + +TapTap 游戏内购服务为开发者提供了便捷高效的解决方案。接入该服务后,开发者可轻松开放游戏内购,无论是消耗型道具还是非消耗型道具,都能方便地上架售卖。同时,订单查看功能,让开发者对销售情况一目了然。 + +## 业务介绍 + +TapTap 游戏内购服务为开发者提供便捷高效的支付解决方案,其特点如下: + +* **多种支付渠道** :接入 SDK 即可支持微信支付和支付宝支付。 +* **灵活配置** :可在开发者后台配置商品及其价格,并且支持通过后台调整。 +* **商品类型多样** :支持消耗型(如金币、钻石)商品和非消耗型(如皮肤)商品。 +* **零分成** :TapTap 对游戏内购服务实行零分成。*但请注意,交易依旧需向微信和支付宝支付 1% 的手续费。* + +## 如何接入和使用 + +### 创建商户 + +开通游戏内购服务需提交材料,入驻成为 TapTap 服务商下的二级商户。请按照《[创建商户](/sdk/tap-iap/create-merchant)》文档的要求准备材料,并将材料发送至邮箱:[PaymentSupport@taptap.com](mailto:PaymentSupport@taptap.com) 完成商户创建。 + +创建商户大约需要 1~2 周,建议您提前完成准备工作。 + +### 接入 SDK + +将 TapTap IAP SDK 集成到您的游戏中,我们提供了 Unity 和 Android 的集成选项: + +- [Unity 集成指南](/sdk/tap-iap/develop/unity) +- [Android 集成指南](/sdk/tap-iap/develop/android) + + +### 上架商品 + +在 [TapTap 开发者中心](https://developer.taptap.io/)添加商品并注册相关信息:项目 ID、项目标题、项目类型、价格等。进一步了解请查阅《[系统操作手册](/sdk/tap-iap/operating-manual)》。 + +### 订单结算 + +系统将自动在订单交易成功后 7 个自然日完成结算,结算后资金将自动转入您的微信和支付宝商户账户,您可以登录微信和支付宝的商户后台查看账单、操作提现等。 + +您也可以设置自动提现,详细可查阅微信和支付宝的商户操作手册。 \ No newline at end of file diff --git a/hk/docs/sdk/TapPayments/develop/unity.mdx b/hk/docs/sdk/TapPayments/develop/unity.mdx index 34edbfe7d..05120d66f 100644 --- a/hk/docs/sdk/TapPayments/develop/unity.mdx +++ b/hk/docs/sdk/TapPayments/develop/unity.mdx @@ -150,11 +150,7 @@ public class MyIAPManager : IStoreListener { builder.Configure().SetClientId("Your Client ID Here"); builder.Configure().SetClientToken("Your Client Token Here"); builder.Configure().SetRegionCode(1); // 0: CN, 1: GLOBAL - builder.AddProduct("100_gold_coins", ProductType.Consumable, new IDs - { - {"100_gold_coins_google", GooglePlay.Name}, - {"100_gold_coins_mac", MacAppStore.Name} - }); + builder.AddProduct("100_gold_coins", ProductType.Consumable); UnityPurchasing.Initialize (this, builder); } diff --git a/hk/i18n/en/docusaurus-plugin-content-docs/current/sdk/TapPayments/develop/unity.mdx b/hk/i18n/en/docusaurus-plugin-content-docs/current/sdk/TapPayments/develop/unity.mdx index 4f4045e81..54ede3caa 100644 --- a/hk/i18n/en/docusaurus-plugin-content-docs/current/sdk/TapPayments/develop/unity.mdx +++ b/hk/i18n/en/docusaurus-plugin-content-docs/current/sdk/TapPayments/develop/unity.mdx @@ -145,11 +145,7 @@ public class MyIAPManager : IStoreListener { builder.Configure().SetClientId("Your Client ID Here"); builder.Configure().SetClientToken("Your Client Token Here"); builder.Configure().SetRegionCode(1); // 0: CN, 1: GLOBAL - builder.AddProduct("100_gold_coins", ProductType.Consumable, new IDs - { - {"100_gold_coins_google", GooglePlay.Name}, - {"100_gold_coins_mac", MacAppStore.Name} - }); + builder.AddProduct("100_gold_coins", ProductType.Consumable); UnityPurchasing.Initialize (this, builder); } From 4e0d12cc08c714ba3adab99c935ccf93e37bdaf6 Mon Sep 17 00:00:00 2001 From: Gavin Date: Fri, 15 Nov 2024 16:16:08 +0800 Subject: [PATCH 10/11] =?UTF-8?q?feat:=20=E6=A0=BC=E5=BC=8F=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn/docs/sdk/tap-iap/operating-manual.mdx | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/cn/docs/sdk/tap-iap/operating-manual.mdx b/cn/docs/sdk/tap-iap/operating-manual.mdx index e7e477e51..4d50af52d 100644 --- a/cn/docs/sdk/tap-iap/operating-manual.mdx +++ b/cn/docs/sdk/tap-iap/operating-manual.mdx @@ -3,18 +3,18 @@ title: 系统操作手册 sidebar_position: 4 --- -# 一、商品管理 +## 一、商品管理 若要在游戏中提供内购商品,必须在 TapTap 开发者服务中心录入内购商品信息,并添加到你的游戏内。每个商品须关联一个游戏应用(Client),并且只能用于该游戏。在使用过程中,你可以创建或删除商品,也可以修改完善现有商品的信息。 -## 创建游戏内商品 +### 创建游戏内商品 在创建商品之前,请务必仔细规划您的产品 ID。商品 ID 对于您的游戏来说必须是唯一的,并且在创建后不能更改或重复使用。 - 商品 ID 必须以数字或字母开头,长度不超过 30 个字符,可以包含数字 (0-9)、英文字母 (a-z/A-Z)、下划线 (_) 和句点 (.) - 创建商品后,您无法更改或重复使用商品 ID -### 创建单个商品 +#### 创建单个商品 1. 前往 TapTap 开发者服务中心,选择「游戏服务」-「内购服务」; @@ -36,7 +36,7 @@ sidebar_position: 4 ![mahua](https://capacity-files.lcfile.com/GSpWNUzJ025ypkp42jD180Ko7u9wDiUA/add_sku.png) -## 批量创建多个商品 +### 批量创建多个商品 1. 如需同时创建多个游戏内购商品,您可以选择使用「批量导入」功能,上传包含每个商品详细信息的 CSV 文件; @@ -53,7 +53,7 @@ sidebar_position: 4 ![tappay](https://capacity-files.lcfile.com/6GwDJdk5zVDaVp1znwrPRUEx1TcmjQC5/add_sku_batch.png) -## 编辑/修改商品 +### 编辑/修改商品 | 商品状态 | 编辑与操作 | | ---- | ---- | @@ -62,7 +62,7 @@ sidebar_position: 4 | 已上架 | 可修改商品名称、商品说明 / 可下架 | | 已下架 | 可删除 | -## 商品状态说明 +### 商品状态说明 * __审核中__:商品在发布之前需要提交审核,审核通过则进入待上架状态,审核失败会给出失败原因,需要根据失败原因进行修改后重新提交; @@ -74,19 +74,14 @@ sidebar_position: 4 * __已删除__:开发者可以删除商品,删除的商品不可再复用; -## 语言和本地化 -如果你的游戏会在不同的国家/地区发布,那么也建议为你的商品添加本地化信息。通过添加不同地区的语言完成本地化信息的录入。 - -![tappay](https://capacity-files.lcfile.com/RuxW5n9niJRDFIVVAa2uOURPHbnpgx4F/product-multilingual.png) - -# 二、管理订单 +## 二、管理订单 你可以通过 TapTap 开发者服务中心的「游戏服务」-「内购服务」-「交易列表」来查看游戏内购买商品(IAP)的销售订单 ![tappay](https://capacity-files.lcfile.com/8WMyxhKLhNA1SniirMSVSOt56kS2z2wb/tappay-orders.png) -## 查找订单 +### 查找订单 TapTap IAP 支持多种查询方式: @@ -100,7 +95,7 @@ TapTap IAP 支持多种查询方式: * __按订单时间查询__:筛选用户订单发生的日期查询; -## 订单状态 +### 订单状态 订单页面会显示每一笔用户购买的状态,如下: From bc1e2caa162c173c0a48b9d5ce7bb2f4f0c65b28 Mon Sep 17 00:00:00 2001 From: Gavin Date: Fri, 15 Nov 2024 16:22:37 +0800 Subject: [PATCH 11/11] =?UTF-8?q?feat:=20=E6=A0=BC=E5=BC=8F=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cn/docs/sdk/tap-iap/create-merchant.mdx | 2 -- cn/docs/sdk/tap-iap/develop/sandbox.mdx | 2 -- cn/docs/sdk/tap-iap/develop/server.mdx | 2 -- cn/docs/sdk/tap-iap/overview.mdx | 5 ++--- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/cn/docs/sdk/tap-iap/create-merchant.mdx b/cn/docs/sdk/tap-iap/create-merchant.mdx index 657cfe975..60b19410b 100644 --- a/cn/docs/sdk/tap-iap/create-merchant.mdx +++ b/cn/docs/sdk/tap-iap/create-merchant.mdx @@ -5,8 +5,6 @@ sidebar_position: 2 import {Red, Blue, Black, Gray} from '/src/docComponents/doc'; -# 创建商户 - ## 准备材料 ### 1. 营业执照 必填* diff --git a/cn/docs/sdk/tap-iap/develop/sandbox.mdx b/cn/docs/sdk/tap-iap/develop/sandbox.mdx index a449c9a53..cd50341ec 100644 --- a/cn/docs/sdk/tap-iap/develop/sandbox.mdx +++ b/cn/docs/sdk/tap-iap/develop/sandbox.mdx @@ -3,8 +3,6 @@ title: 沙盒环境 sidebar_position: 4 --- -# 沙盒环境 - TapTap IAP 沙盒环境进行支付测试, 如果使用沙盒账号发起 IAP, 那么对应所有渠道将按照最低标准进行支付, 以便开发者进行支付测试。 ## 沙盒账号设置 diff --git a/cn/docs/sdk/tap-iap/develop/server.mdx b/cn/docs/sdk/tap-iap/develop/server.mdx index c8b289e22..efb9470d1 100644 --- a/cn/docs/sdk/tap-iap/develop/server.mdx +++ b/cn/docs/sdk/tap-iap/develop/server.mdx @@ -5,8 +5,6 @@ sidebar_position: 3 import MultiLang from "/src/docComponents/MultiLang"; -# 服务端开发指南 - :::tip 服务通用规则请参考 [请求规则和签算](/sdk/tap-iap/develop/server/#请求规则和签算) ::: diff --git a/cn/docs/sdk/tap-iap/overview.mdx b/cn/docs/sdk/tap-iap/overview.mdx index 903eeeb1e..4575ed715 100644 --- a/cn/docs/sdk/tap-iap/overview.mdx +++ b/cn/docs/sdk/tap-iap/overview.mdx @@ -1,10 +1,9 @@ --- -title: 功能介绍 +title: 游戏内购服务功能介绍 +sidebar_label: 功能介绍 sidebar_position: 1 --- -# 游戏内购服务功能介绍 - TapTap 游戏内购服务为开发者提供了便捷高效的解决方案。接入该服务后,开发者可轻松开放游戏内购,无论是消耗型道具还是非消耗型道具,都能方便地上架售卖。同时,订单查看功能,让开发者对销售情况一目了然。 ## 业务介绍