收据验证
未给出的项目收据¶
发送物品有时会在购买后失败或被取消。为了防止这种情况,请通过调用IAPV4类的restore()
方法请求未提供的物品的收据信息。
- 如果返回
SUCCESS
并且在调用restore()
后发送ReceiptList,则需要恢复的项目存在。发送未给出的项目并完成恢复过程。 - 如果在调用
restore()
后未返回SUCCESS
,则游戏工作室不需要更多处理。 - 如果调用
restore()
方法时发生错误,请通知仅需识别的一些错误,并跳过其他错误,以便用户继续玩游戏。 - 当在Windows应用程序中使用
GOOGLE_PLAYSTORE
市场进行Google Play(Hive SDK v4 Unity Windows 23.0.0或更高版本)时,如果用于支付的Google账户的身份验证信息在调用restore()
方法时过期,Hive SDK会自动启动重新身份验证过程。
以下是请求未提供物品的收据信息的示例代码。
API 参考: hive .IAPV4.restore
using hive;
IAPV4.restore((ResultAPI result, List receiptList) => {
if (result.isSuccess()) {
if (result.errorCode = ResultAPI.ErrorCode.SUCCESS) {
// TODO: Request receipt verification using the received receiptList
} else if (result.errorCode = ResultAPI.ErrorCode.NOT_OWNED) {
// No unpaid items
}
}
}
#include "HiveIAPV4.h"
FHiveIAPV4::Restore(FHiveIAPV4OnRestoreDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TArray<FHiveIAPV4Receipt>& IAPV4ReceiptList) {
if (Result.IsSuccess()) {
if (Result.ErrorCode == FHiveResultAPI::EErrorCode::SUCCESS) {
// TODO: 使用收到的receiptList请求收据验证
} else if (Result.ErrorCode == FHiveResultAPI::EErrorCode::RESTORE_NOT_OWNED) {
// 没有未付款项
}
}
}));
API 参考: IAPV4 ::restore
#include <HIVE_SDK_Plugin/HIVE_CPP.h>
using namespace std;
using namespace hive;
IAPV4::restore([=](ResultAPI const & result, vector<reference_wrapper<IAPV4Receipt>> receiptList) {
if (result.isSuccess()) {
if (result.errorCode == ResultAPI::ErrorCode::SUCCESS) {
// TODO: 使用收到的receiptList请求收据验证
} else if (result.errorCode == ResultAPI::ErrorCode::RESTORE_NOT_OWNED) {
// 没有未支付的项目
}
}
});
API 参考: IAPV4.restore
import com.hive.IAPV4
import com.hive.ResultAPI
IAPV4.restore(object : IAPV4.IAPV4RestoreListener {
override fun onIAPV4Restore(result: ResultAPI, iapv4ReceiptList: ArrayList<IAPV4.IAPV4Receipt>?) {
if (result.isSuccess) {
if (result.errorCode == ResultAPI.SUCCESS) {
// TODO: 使用接收到的iapv4ReceiptList请求收据验证
} else if (result.errorCode == ResultAPI.RESTORE_NOT_OWNED) {
// 没有未付款项
}
}
}
})
API 参考: com.hive.IAPV4.restore
import com.hive.IAPV4;
import com.hive.ResultAPI;
IAPV4.INSTANCE.restore((result, iapv4ReceiptList) -> {
if (result.isSuccess()) {
if (result.getErrorCode() == ResultAPI.Companion.getSUCCESS()) {
// TODO: 使用收到的iapv4ReceiptList请求收据验证
} else if (result.getErrorCode() == ResultAPI.Companion.getRESTORE_NOT_OWNED()) {
// 没有未付款项
}
}
});
API 参考: IAPV4Interface .restore
API 参考: HIVEIAPV4::restore
#import <HIVEService/HIVEService-Swift.h>
[HIVEIAPV4 restore: ^(HIVEResultAPI *result, NSArray<HIVEIAPV4Receipt *> *receiptList) {
if ([result isSuccess]) {
if ([result getErrorCode] == HIVEResultAPITypeSuccess) {
// TODO: 使用收到的 receiptList 请求收据验证
} else if ([result getErrorCode] == HIVEResultAPITypeNotOwned){
// 没有未付款项
}
}
}];
Note
may differ by operating system/market. For more details, see the status of supported features.
购买恢复错误代码列表¶
错误代码 | 描述 |
---|---|
NEED_INITIALIZE | 无法初始化 |
NETWORK | 网络错误 |
NOT_SUPPORTED | 无法恢复(设备上的应用内购买被拒绝等)。用户设置了不可用的商店 |
INVALID_SESSION | 无效的恢复会话 |
IN_PROGRESS | 恢复 API 正在进行中 |
RESTORE_NOT_OWNED | 没有可恢复的项目 |
NOT_OWNED | 没有可恢复的项目 |
RESPONSE_FAIL | IAP 服务器错误 |
验证购买收据¶
在从游戏服务器发送物品之前,IAP 的验证 API 应该确认收据是否有效。 验证 API 中的 hiveiap_transaction_id
是由收据发出的唯一 ID。因此,请在游戏服务器上保存该 ID 以检查重复的收据。 如果您使用验证 API 然后发送所有来自请求参数的数据,IAP 服务器会转发游戏数据以分析销售状态。只需利用 API 在 Hive One > 搜索所有 中搜索付款。 有关更多详细信息,请参阅 IAP 收据验证 API。
完成以提供已购买或未提供的项目¶
如果游戏服务器在购买后发送物品,请确保调用IAPV4类的transactionFinish()
方法以完成购买。
Warning
如果您不调用 transactionFinish()
方法,物品将保持在未给出状态。
此原因是调用restore()
方法时返回收据。 因此,请确保在所有过程完成后调用finish API。
Note
使用 Hive SDK v4.12.0 及更高版本在 Android Google Play 商店中,如果在支付后三天内或测试状态下五分钟内,IAPV4 类中实现 TransactionFinish()
方法的结果未成功,则付款会自动退款。
以下是完成物品发送请求的示例代码。
API 参考: hive .IAPV4.transactionFinish
API 参考: IAPV4 ::transactionFinish
API 参考: IAPV4.transactionFinish
import com.hive.IAPV4
import com.hive.ResultAPI
val marketPid = "{YOUR_PRODUCT_MARKET_PID}"
IAPV4.transactionFinish(marketPid, object : IAPV4.IAPV4TransactionFinishListener {
override fun onIAPV4TransactionFinish(result: ResultAPI, marketPid: String) {
if (result.isSuccess) {
// call successful
}
}
})
API 参考: com.hive.IAPV4.transactionFinish
API 参考: IAPV4Interface.transactionFinish
以下是请求发送多个项目的示例代码。
API 参考: hive .IAPV4.transactionMultiFinish
using hive;
List marketPidList = new List();
marketPidList.Add("{YOUR_PRODUCT_MARKET_PID_01}");
marketPidList.Add("{YOUR_PRODUCT_MARKET_PID_02}");
marketPidList.Add("{YOUR_PRODUCT_MARKET_PID_03}");
IAPV4.transactionMultiFinish((List<ResultAPI> resultList, List<String> marketPidList) => {
for (ResultAPI result in resultList) {
if (result.isSuccess()) {
// call successful
}
}
});
#include "HiveIAPV4.h"
TArray<FString> MarketPidList;
MarketPidList.Add(TEXT("YOUR_PRODUCT_MARKET_PID_01"));
MarketPidList.Add(TEXT("YOUR_PRODUCT_MARKET_PID_02"));
MarketPidList.Add(TEXT("YOUR_PRODUCT_MARKET_PID_03"));
FHiveIAPV4::TransactionMultiFinish(MarketPidList, FHiveIAPV4OnTransactionMultiFinishDelegate::CreateLambda([this](const TArray<FHiveResultAPI>& ResultList, const TArray<FString>& MarketPidList) {
for (const auto& Result : ResultList) {
if (Result.IsSuccess()) {
// API 调用成功
}
}
}));
API 参考: IAPV4 ::transactionMultiFinish
#include <HIVE_SDK_Plugin/HIVE_CPP.h>
using namespace std;
using namespace hive;
vector<string> marketPidList;
marketPidList.push_back("{YOUR_PRODUCT_MARKET_PID_01}");
marketPidList.push_back("{YOUR_PRODUCT_MARKET_PID_02}");
marketPidList.push_back("{YOUR_PRODUCT_MARKET_PID_03}");
IAPV4::transactionMultiFinish(marketPidList, [=](vector<ResultAPI> const & resultList, vector<string> const & marketPidList) {
for (ResultAPI result : resultList) {
if (result.isSuccess()) {
// call successful
}
}
});
API 参考: IAPV4.transactionMultiFinish
import com.hive.IAPV4
import com.hive.ResultAPI
val marketPidList = arrayListOf(
"{YOUR_PRODUCT_MARKET_PID_01}",
"{YOUR_PRODUCT_MARKET_PID_02}",
"{YOUR_PRODUCT_MARKET_PID_03}"
)
IAPV4.transactionMultiFinish(marketPidList, object : IAPV4.IAPV4TransactionMultiFinishListener {
override fun onIAPV4TransactionMultiFinish(resultList: ArrayList<ResultAPI>, marketPidList: ArrayList<String>) {
for (i in 0 until resultList.size) {
if (resultList[i].isSuccess) {
// call successful
}
}
}
})
API 参考: com.hive.IAPV4.transactionMultiFinish
import com.hive.IAPV4;
import com.hive.ResultAPI;
ArrayList<String> marketPidList = new ArrayList<>(Arrays.asList(
"{YOUR_PRODUCT_MARKET_PID_01}",
"{YOUR_PRODUCT_MARKET_PID_02}",
"{YOUR_PRODUCT_MARKET_PID_03}"
));
IAPV4.INSTANCE.transactionMultiFinish(marketPidList, (resultList, marketPidList1) -> {
for (ResultAPI result : resultList) {
if (result.isSuccess()) {
// call successful
}
}
});
API 参考: IAPV4Interface.transactionMultiFinish
import HIVEService
var marketPidList = [String]()
marketPidList.append("{YOUR_PRODUCT_MARKET_PID_01}")
marketPidList.append("{YOUR_PRODUCT_MARKET_PID_02}")
marketPidList.append("{YOUR_PRODUCT_MARKET_PID_03}")
IAPV4Interface.transactionMultiFinish(marketPidList) { resultList, marketPidList in
for result in resultList {
if result.isSuccess() {
// call successful
}
}
}
API 参考: HIVEIAPV4::transactionMultiFinish
#import <HIVEService/HIVEService-Swift.h>
NSMutableArray<NSString *> *maketPidList = [NSMutableArray array];
[maketPidList addObject:@"{YOUR_PRODUCT_MARKET_PID_01}"];
[maketPidList addObject:@"{YOUR_PRODUCT_MARKET_PID_02}"];
[maketPidList addObject:@"{YOUR_PRODUCT_MARKET_PID_03}"];
[HIVEIAPV4 transactionMultiFinish: maketPidList handler: ^(NSArray<HIVEResultAPI *> *resultList, NSArray<NSString *> *marketPidList) {
for (HIVEResultAPI *result in resultList) {
if ([result isSuccess]) {
// call successful
}
}
}];
获取用户购买活动信息:使用 AccountUuid
¶
可能会有用户滥用支付系统,例如一个游戏账户使用多个应用商店账户进行支付。在游戏工作室方面,您可以通过比较支付用户信息(AccountUuid)来获取和分析特定用户行为。
下面的方法返回AccountUuid
,这是UUID v3格式中PlayerId的哈希值,由Hive SDK传递给应用商店。
API 参考: IAPV4.getAccountUuid
API 参考: IAPV4 ::getAccountUuid
API 参考: IAPV4.getAccountUuid
API 参考: IAPV4.INSTANCE .getAccountUuid
API 参考: IAPV4Interface.getAccountUuid
API 参考: [HIVEIAPV4 getAccountUuid ]
游戏工作室可以使用此哈希值和购买收据信息来分析用户的购买情况。下面的示例显示了在此游戏帐户中有多个游戏角色时,通过AccountUuid
分析具有特定PlayerId的游戏帐户的购买活动。此示例仅供开发参考,并不保证实际操作。
在游戏服务器中提前存储购买元信息¶
在购买请求发生之前,将购买元信息(AccountUuid
和角色信息)保存到游戏服务器。
/* The game client pass the info to the game server before the purchase occurs.
*
* @param purchaseTime: purchase time. The receipts are usually based on UTC. since the epoch (Jan 1, 1970).
* @param productId: purchase product ID.
* @param accountUuId: hashed PlayerId. It is included in the receipt and can be obtained with IAPV4.getAccountUuid().
* @param characterId: the character identifier within PlayerId.
*/
game.sendPurchaseGameData(purchaseTime, productId, accountUuid, characterId)
发送 bypassInfo
¶
当购买请求发生时,将 bypassInfo
数据发送到游戏服务器。下面的代码是供开发参考的伪代码。
收据验证请求¶
游戏服务器将 bypassInfo
数据传递给 IAP v4 服务器并请求验证收据。有关请求收据验证的详细信息,请参见 这里。 hiveiap_receipt
中包含的 AccountUuid
是在响应值中收到的应用市场/商店的原始收据。
# Apple
# Purchase time: purchase_date_ms
# Purchased products: product_id
# AccountUuid: app_account_token
# Google
# Purchase time: purchaseTime
# Purchased products: productId
# AccountUuid: obfuscatedAccountId
通过将购买元信息的 AccountUuid
与 hiveiap_receipt
的 AccountUuid
进行匹配进行分析¶
通过将之前存储在购买元信息中的AccountUuid
与收据验证结果中获得的AccountUuid
进行匹配,找到进行分析所需的用户信息,例如游戏角色信息。您可以通过将购买元信息与收据信息进行匹配来分析相应游戏账户的购买活动。
如果用户购买了多个商品,可以通过将购买元信息与hiveiap_receipt
的purchaseTime
进行匹配来识别每个购买。有关hiveiap_receipt
的详细信息,请参见验证收据,并按市场检查API响应。
获取用户购买活动信息:使用 iadPayload
¶
当请求购买时,如果您的游戏公司还提供预定义的数据来分析用户购买活动,使用 Purchase(),iapPayload
,Hive 服务器会匹配与 iapPayload
相对应的购买收据,并将其发送到游戏服务器。游戏公司可以将收据中的信息与 iadPayload
中的信息结合起来,以分析用户购买活动。
Note
通过这种方式,因为 Hive 服务器将每个购买的元信息与每个收据匹配并发送到您的游戏服务器,您无需像上面所示那样自己通过 AccountUuid
匹配购买元信息和收据。
定义 iapPayload
并执行 Purchase()
¶
在执行每个 产品购买请求 时,定义所需的字段和值在 iapPayload
中,并将其作为参数使用。该过程类似于定义 购买元数据。
请求收据验证,并接收 iapPayload
及相应的收据。¶
当付款完成并请求收据验证时,Hive 服务器通过购买将 iapPayload
与其相应的收据匹配,并将其交付给游戏服务器。游戏工作室可以使用 iapPayload
和收据中的信息来分析用户购买活动。