การตรวจสอบใบเสร็จ
ใบเสร็จสินค้าที่ไม่ได้รับ¶
การส่งรายการอาจล้มเหลวหรือถูกยกเลิกหลังจากการซื้อ เพื่อป้องกันสถานการณ์นี้ ให้ขอข้อมูลใบเสร็จของรายการที่ไม่ได้รับโดยการเรียกใช้วิธี restore() ของคลาส IAPV4 
- หากส่งคืน SUCCESSและ ReceiptList ถูกส่งหลังจากเรียกใช้restore()หมายความว่ามีรายการที่ต้องการการกู้คืน ส่งรายการที่ยังไม่ได้ให้และทำให้กระบวนการกู้คืนเสร็จสมบูรณ์
- หากไม่ส่งคืน SUCCESSหลังจากเรียกใช้restore()จะไม่มีการดำเนินการเพิ่มเติมที่จำเป็นสำหรับสตูดิโอเกม
- หากเกิดข้อผิดพลาดขณะเรียกใช้วิธี restore()แจ้งเตือน เฉพาะข้อผิดพลาดบางอย่างที่จำเป็นต้องรู้ และข้ามข้อผิดพลาดอื่น ๆ เพื่อให้ผู้ใช้สามารถเล่นเกมของคุณต่อไป
- เมื่อใช้ตลาด GOOGLE_PLAYSTOREในแอป Windows สำหรับ Google Play (Hive SDK v4 Unity Windows 23.0.0 หรือสูงกว่า) หากข้อมูลการรับรองสำหรับบัญชี Google ที่ใช้ในการชำระเงินหมดอายุในขณะเรียกใช้วิธีrestore()Hive SDK จะเริ่มกระบวนการรับรองความถูกต้องใหม่โดยอัตโนมัติ
ต่อไปนี้คือตัวอย่างโค้ดเพื่อขอข้อมูลใบเสร็จของรายการที่ไม่ได้ให้
API Reference: 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) {
                        //  ไม่มีรายการที่ยังไม่ได้ชำระ
                }
        }
}));
API Reference: 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: Request receipt verification using the received iapv4ReceiptList    
                 } else if (result.errorCode == ResultAPI.RESTORE_NOT_OWNED) {    
                     // No unpaid items    
                 }    
             }    
         }    
})
API Reference: 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: Request receipt verification using the received iapv4ReceiptList    
             } else if (result.getErrorCode() == ResultAPI.Companion.getRESTORE_NOT_OWNED()) {    
                 // No unpaid items    
             }    
         }    
});
API Reference: IAPV4Interface .restore
API Reference: HIVEIAPV4::restore
#import <HIVEService/HIVEService-Swift.h>    
    [HIVEIAPV4 restore: ^(HIVEResultAPI *result, NSArray<HIVEIAPV4Receipt *> *receiptList) {    
         if ([result isSuccess]) {    
            if ([result getErrorCode] == HIVEResultAPITypeSuccess) {    
            // TODO: Request receipt verification using the received receiptList    
            } else if ([result getErrorCode] == HIVEResultAPITypeNotOwned){    
        // No unpaid items    
            }    
         }    
}];
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 | 
การตรวจสอบใบเสร็จการซื้อ¶
ก่อนที่จะส่งรายการจากเซิร์ฟเวอร์เกม API การตรวจสอบจาก IAP ควรยืนยันว่าบัตรกำนัลนั้นถูกต้อง hiveiap_transaction_id ใน API การตรวจสอบคือ ID ที่ไม่ซ้ำกันที่ออกโดยบัตรกำนัล ดังนั้นให้บันทึก ID บนเซิร์ฟเวอร์เกมเพื่อตรวจสอบบัตรกำนัลที่ซ้ำกัน หากคุณใช้ API การตรวจสอบและส่งข้อมูลทั้งหมดจากพารามิเตอร์ Request เซิร์ฟเวอร์ IAP จะส่งต่อข้อมูลเกมเพื่อวิเคราะห์สถานะการขาย เพียงใช้ API เพื่อค้นหาการชำระเงินใน Hive One > ค้นหาทั้งหมด ด้วย สำหรับรายละเอียดเพิ่มเติม โปรดดูที่ IAP Receipt Verification API.
การทำให้เสร็จสิ้นเพื่อให้รายการที่ซื้อหรือยังไม่ได้ให้¶
หากเซิร์ฟเวอร์เกมส่งไอเทมหลังจากการซื้อ ให้แน่ใจว่าได้เรียกใช้วิธี transactionFinish() ของคลาส IAPV4 เพื่อทำให้การซื้อเสร็จสมบูรณ์
Warning
หากคุณไม่เรียกใช้เมธอด transactionFinish() รายการจะยังคงอยู่ในสถานะที่ไม่ได้ให้ 
สาเหตุนี้ทำให้การคืนใบเสร็จเกิดขึ้นภายใต้การเรียกใช้วิธี restore() ดังนั้นโปรดตรวจสอบให้แน่ใจว่าได้เรียกใช้ API เสร็จสิ้นหลังจากกระบวนการทั้งหมดเสร็จสิ้น
Note
ด้วย Hive SDK v4.12.0 และเวอร์ชันที่ใหม่กว่านั้นใน Android Google Play Store การชำระเงินจะถูกคืนเงินโดยอัตโนมัติหากผลลัพธ์ของการเรียกใช้ TransactionFinish() ในคลาส IAPV4 ไม่สำเร็จภายในสามวันหรือห้านาทีในสถานะทดสอบหลังจากการชำระเงิน.
ต่อไปนี้คือตัวอย่างโค้ดที่ทำการส่งคำขอสำหรับการส่งสินค้า
API Reference: hive .IAPV4.transactionFinish
API Reference: IAPV4 ::transactionFinish
API Reference: 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 Reference: com.hive.IAPV4.transactionFinish
API Reference: IAPV4Interface.transactionFinish
API Reference: HIVEIAPV4::transactionFinish:handler:
ต่อไปนี้คือตัวอย่างโค้ดเพื่อขอส่งหลายรายการ
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 call successful
                }
        }
}));
API Reference: 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 Reference: 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 Reference: 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 Reference: 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 Reference: 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 ซึ่งเป็นค่าแฮชของ PlayerId ในรูปแบบ UUID v3 ที่ Hive SDK ส่งไปยังร้านค้าแอป
เอกสารอ้างอิง API: IAPV4.getAccountUuid
API Reference: IAPV4 ::getAccountUuid
API Reference: IAPV4.getAccountUuid
API Reference: IAPV4.INSTANCE .getAccountUuid
API Reference: IAPV4Interface.getAccountUuid
API Reference: [HIVEIAPV4 getAccountUuid ]
สตูดิโอเกมสามารถใช้ค่าแฮชนี้ร่วมกับข้อมูลใบเสร็จการซื้อเพื่อวิเคราะห์การซื้อของผู้ใช้
ตัวอย่างด้านล่างแสดงการวิเคราะห์กิจกรรมการซื้อของบัญชีเกมที่มี PlayerId เฉพาะผ่าน AccountUuid เมื่อมีตัวละครในเกมหลายตัวในบัญชีเกมนี้ ตัวอย่างนี้ใช้เพื่อการพัฒนาเท่านั้นและไม่รับประกันการทำงานจริง 
เก็บข้อมูลเมตาของการซื้อในเซิร์ฟเวอร์เกมล่วงหน้า¶
ก่อนที่จะมีการขอซื้อเกิดขึ้น ให้บันทึกข้อมูลเมตาของการซื้อ (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 และขอให้ตรวจสอบความถูกต้องของใบเสร็จ สำหรับรายละเอียดเกี่ยวกับการขอการตรวจสอบใบเสร็จ โปรดดูที่ ที่นี่. AccountUuid ที่รวมอยู่ใน hiveiap_receipt ซึ่งเป็นใบเสร็จต้นฉบับจากตลาด/ร้านแอปที่ได้รับภายในค่าการตอบกลับ.
# Apple
# Purchase time: purchase_date_ms
# Purchased products: product_id
# AccountUuid: app_account_token   
# Google
# Purchase time: purchaseTime
# Purchased products: productId
# AccountUuid: obfuscatedAccountId
วิเคราะห์โดยการจับคู่ AccountUuid ของข้อมูลเมตาของการซื้อกับ AccountUuid ของ hiveiap_receipt¶
 ค้นหาข้อมูลผู้ใช้ที่จำเป็นสำหรับการวิเคราะห์ เช่น ข้อมูลตัวละครเกม โดยการจับคู่ AccountUuid ที่เก็บไว้ก่อนหน้านี้ในข้อมูลเมตาของการซื้อกับ AccountUuid ที่ได้รับจากผลลัพธ์ของการตรวจสอบใบเสร็จ คุณสามารถวิเคราะห์กิจกรรมการซื้อของบัญชีเกมที่เกี่ยวข้องโดยการจับคู่ข้อมูลเมตาของการซื้อกับข้อมูลใบเสร็จ
หากผู้ใช้ได้ทำการซื้อสินค้าหลายรายการ การซื้อแต่ละครั้งสามารถระบุได้โดยการจับคู่ข้อมูลเมตาของการซื้อกับ purchaseTime ของ hiveiap_receipt สำหรับรายละเอียดเกี่ยวกับ hiveiap_receipt โปรดดูที่ ตรวจสอบใบเสร็จ และตรวจสอบการตอบสนองของ API ตามตลาด
รับข้อมูลกิจกรรมการซื้อของผู้ใช้: ใช้ iadPayload¶
 เมื่อขอซื้อด้วย Purchase() หากบริษัทเกมของคุณยังให้ข้อมูลที่กำหนดไว้ล่วงหน้าเพื่อวิเคราะห์กิจกรรมการซื้อของผู้ใช้ iapPayload เซิร์ฟเวอร์ Hive จะตรงกับใบเสร็จการซื้อที่ Corresponding กับ iapPayload และส่งสิ่งนี้ไปยังเซิร์ฟเวอร์เกม บริษัทเกมสามารถใช้ข้อมูลในใบเสร็จและข้อมูลใน iadPayload ร่วมกันเพื่อวิเคราะห์กิจกรรมการซื้อของผู้ใช้
Note
ด้วยวิธีนี้ เนื่องจาก Hive Server จะจับคู่ข้อมูลเมตาของการซื้อแต่ละรายการกับใบเสร็จและส่งไปยังเซิร์ฟเวอร์เกมของคุณ คุณจึงไม่จำเป็นต้องจับคู่ข้อมูลเมตาของการซื้อและใบเสร็จด้วย AccountUuid ด้วยตัวเองตามที่แสดงข้างต้น
กำหนด iapPayload และดำเนินการ Purchase()¶
 เมื่อดำเนินการแต่ละ คำขอซื้อผลิตภัณฑ์ ให้กำหนดฟิลด์และค่าที่ต้องการใน iapPayload และใช้เป็นอาร์กิวเมนต์ กระบวนการนี้คล้ายกับการกำหนด ข้อมูลเมตาของการซื้อ.
ขอการตรวจสอบใบเสร็จและรับ iapPayload และใบเสร็จที่เกี่ยวข้อง¶
 เมื่อการชำระเงินเสร็จสมบูรณ์และมีการขอการตรวจสอบใบเสร็จ ใบเสร็จการตรวจสอบ, เซิร์ฟเวอร์ Hive จะจับคู่ iapPayload กับใบเสร็จที่เกี่ยวข้องตามการซื้อและส่งมอบไปยังเซิร์ฟเวอร์เกม สตูดิโอเกมสามารถใช้ข้อมูลใน iapPayload และใบเสร็จเพื่อตรวจสอบกิจกรรมการซื้อของผู้ใช้
ด้านล่างเป็นตัวอย่างของสถานการณ์ที่ใช้ iapPayload.
- บัญชีตลาด: A, Hive PlayerId: a, ตัวละครแอป: 1 เข้าสู่ระบบ
- ซื้อ(marketPid, "playerId a - character 1")
- เปลี่ยนบัญชีเป็น Hive PlayerId: b, ตัวละครแอป 2
- กู้คืน()
- ได้รับใบเสร็จที่มี iapPayload "playerId a - character 1"