收据验证
未給予的項目收據¶
發送項目有時會在購買後失敗或被取消。為了防止這種情況,請通過調用IAPV4類的restore()
方法請求未提供的項目的收據信息。
- 如果在调用
restore()
后返回SUCCESS
并且发送了 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: Request receipt verification using the received receiptList
} else if (Result.ErrorCode == FHiveResultAPI::EErrorCode::RESTORE_NOT_OWNED) {
// No unpaid items
}
}
}));
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: Request receipt verification using the received receiptList
} else if (result.errorCode == ResultAPI::ErrorCode::RESTORE_NOT_OWNED) {
// No unpaid items
}
}
});
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 商店上,如果在付款後三天內或測試狀態下五分鐘內,TransactionFinish()
方法在 IAPV4 類中的實現結果不成功,則付款將自動退款。
以下是完成物品發送請求的範例代碼。
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 Reference: 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
和收據中的信息來分析用戶的購買活動。
以下是使用iapPayload的情況示例。
- 市場帳戶: A, Hive 玩家ID: a, 應用角色: 1 登入
- 購買(marketPid, "玩家ID a - 角色 1")
- 切換帳戶至 Hive 玩家ID: b, 應用角色 2
- 還原()
- 收到包含 iapPayload "玩家ID a - 角色 1" 的收據