영수증 확인을 통해 사용자가 구매하지 않은 콘텐츠에 액세스하지 못하게 합니다.
중요: Unity IAP는 로컬 확인 메서드를 제공하지만 로컬 확인은 사기에 더 취약합니다. 가능한 경우 서버측에서 민감한 트랜잭션을 확인하는 것이 베스트 프랙티스로 간주됩니다. 더 자세한 내용은 사기 방지에 대한 Apple 및 Android의 기술 자료를 참조하십시오.
사용자가 구매한 콘텐츠가 기기에 이미 존재하는 경우, 애플리케이션은 콘텐츠의 해지 여부만 결정하면 됩니다.
Unity IAP는 Google Play와 Apple 스토어를 통해 콘텐츠를 숨기고 영수증을 파싱할 수 있는 툴을 제공합니다.
영수증 검증은 알려진 암호화 키를 사용해 진행됩니다. 이 키는 애플리케이션의 암호화된 Google Play 공용 키나 Apple 루트 인증서입니다.
사용자가 이 키를 교체할 수 있다면 영수증 확인 과정을 무력화할 수 있으므로, 사용자가 키를 찾아 수정하기 어렵도록 해야 합니다.
Unity IAP는 애플리케이션에서 암호화 키를 난독 처리할 수 있는 툴을 제공합니다. 이 툴은 키를 난독 처리하여 사용자가 액세스하기 어렵게 만듭니다. Unity 메뉴 바에서 Window > Unity IAP > IAP Validation Obfuscator 로 이동합니다.
이 창은 Unity IAP와 번들로 제공되는 Apple 루트 인증서와 애플리케이션의 Google Play Developer Console Services & APIs 페이지의 Google Play 공용 키를 둘 다 암호화하여 AppleTangle 및 GooglePlayTangle 이라는 두 개의 다른 C# 파일에 저장합니다. 이 파일은 프로젝트에 추가되어 다음 섹션에서 사용하게 됩니다.
Apple 스토어만 타겟하는 경우에는 Google Play 공용 키를 제공할 필요가 없으며, 그 반대도 마찬가지입니다.
CrossPlatformValidator 클래스를 사용하여 Google Play와 Apple 스토어에서 확인을 수행할 수 있습니다.
클래스에 Google Play 공용 키나 Apple 루트 인증서를 제공해야 하며, 두 플랫폼에서 확인을 수행하려면 둘 다 제공해야 합니다.
CrossPlatformValidator는 두 가지 확인을 수행합니다.
이 검증기는 Google Play와 Apple 플랫폼에서 생성된 영수증만 확인할 수 있습니다. 다른 플랫폼에서 생성한 영수증이나 에디터에서 생성한 모의 영수증을 확인하면 IAPSecurityException 오류가 발생합니다.
비밀 키를 제공하지 않은 플랫폼의 영수증을 확인하려고 시도하면 MissingStoreSecretException 오류가 발생합니다.
public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs e)
{
bool validPurchase = true; // Presume valid for platforms with no R.V.
// Unity IAP's validation logic is only included on these platforms.
#if UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_OSX
// Prepare the validator with the secrets we prepared in the Editor
// obfuscation window.
var validator = new CrossPlatformValidator(GooglePlayTangle.Data(),
AppleTangle.Data(), Application.bundleIdentifier);
try {
// On Google Play, result has a single product ID.
// On Apple stores, receipts contain multiple products.
var result = validator.Validate(e.purchasedProduct.receipt);
// For informational purposes, we list the receipt(s)
Debug.Log("Receipt is valid. Contents:");
foreach (IPurchaseReceipt productReceipt in result) {
Debug.Log(productReceipt.productID);
Debug.Log(productReceipt.purchaseDate);
Debug.Log(productReceipt.transactionID);
}
} catch (IAPSecurityException) {
Debug.Log("Invalid receipt, not unlocking content");
validPurchase = false;
}
#endif
if (validPurchase) {
// Unlock the appropriate content here.
}
return PurchaseProcessingResult.Complete;
}
영수증의 유효성뿐만 아니라 해당 내용도 검사해야 합니다. 사용자가 구매를 하지 않고 콘텐츠에 액세스하는 흔한 방법 중 하나는 다른 제품이나 애플리케이션에서 영수증을 제공하는 것입니다. 영수증은 진품이고 확인 과정을 통과하기 때문에, CrossPlatformValidator 가 제품 ID를 파싱한 결과에 따라 판단을 내리도록 해야 합니다.
스토어마다 구매 영수증을 구성하는 필드가 다릅니다. 스토어별 필드에 액세스하려면 IPurchaseReceipt를 두 개의 하위 유형인 GooglePlayReceipt 및 AppleInAppPurchaseReceipt에 적용하면 됩니다.
var result = validator.Validate(e.purchasedProduct.receipt);
Debug.Log("Receipt is valid. Contents:");
foreach (IPurchaseReceipt productReceipt in result) {
Debug.Log(productReceipt.productID);
Debug.Log(productReceipt.purchaseDate);
Debug.Log(productReceipt.transactionID);
GooglePlayReceipt google = productReceipt as GooglePlayReceipt;
if (null != google) {
// This is Google's Order ID.
// Note that it is null when testing in the sandbox
// because Google's sandbox does not provide Order IDs.
Debug.Log(google.transactionID);
Debug.Log(google.purchaseState);
Debug.Log(google.purchaseToken);
}
AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt;
if (null != apple) {
Debug.Log(apple.originalTransactionIdentifier);
Debug.Log(apple.subscriptionExpirationDate);
Debug.Log(apple.cancellationDate);
Debug.Log(apple.quantity);
}
}
AppleValidator 클래스를 사용하여 Apple 영수증에 대한 세부 정보를 추출할 수 있습니다. 이 클래스는 버전 7.0부터의 iOS 앱 영수증에만 작동하며 지원이 중단된 Apple의 트랜잭션 영수증에는 작동하지 않습니다.
#if UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_OSX
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
// Get a reference to IAppleConfiguration during IAP initialization.
var appleConfig = builder.Configure<IAppleConfiguration>();
var receiptData = System.Convert.FromBase64String(appleConfig.appReceipt);
AppleReceipt receipt = new AppleValidator(AppleTangle.Data()).Validate(receiptData);
Debug.Log(receipt.bundleID);
Debug.Log(receipt.receiptCreationDate);
foreach (AppleInAppPurchaseReceipt productReceipt in receipt.inAppPurchaseReceipts) {
Debug.Log(productReceipt.transactionIdentifier);
Debug.Log(productReceipt.productIdentifier);
}
#endif
AppleReceipt 유형은 Apple의 ASN1 영수증 형식을 모델링합니다. 필드에 대한 설명은 Apple 기술 자료를 참조하십시오.