/// <summary> /// Creates an instance of the <see cref="AppleReceiptVerificationResult"/> /// with Detailed Apple Verification Response (<param name="verificationResponse"></param>) /// and verbal result description (<param name="errorMessage"></param>) /// </summary> public AppleReceiptVerificationResult( string errorMessage, IAPVerificationResponse verificationResponse ) { Message = errorMessage; AppleVerificationResponse = verificationResponse; if (verificationResponse != null) { Status = verificationResponse.StatusCode; // Backward compatibility. Receipt = verificationResponse.Receipt; } else { Status = IAPVerificationResponseStatus.InternalVerificationFailed; } }
private async Task <AppleReceiptVerificationResult?> VerifyReceiptAsync(string receiptData, IRestService restService) { // 1. Validate incoming arguments if (string.IsNullOrEmpty(receiptData)) { _logger.LogInformation("receiptData cannot be empty"); return(new AppleReceiptVerificationResult( "receiptData cannot be empty", IAPVerificationResponseStatus.WrongArgument )); } // 2. Pre-validate Receipt (Optional) try { var data = Convert.FromBase64String(receiptData); var receipt = _receiptParserService.GetAppleReceiptFromBytes(data); // a. Validate bundle ID if (receipt != null && !_settings.Value.AllowedBundleIds.Contains(receipt.BundleId)) { _logger.LogInformation("Receipt has wrong bundle ID {bundle_id}", receipt.BundleId); return(new AppleReceiptVerificationResult( $"Receipt has wrong bundle ID {receipt.BundleId}", IAPVerificationResponseStatus.WrongArgument )); } if (_customValidation != null) { // if custom Validator implemented var validationResult = _customValidation.ValidateReceipt(receipt); if (validationResult == null || validationResult.Status != IAPVerificationResponseStatus.Ok) { // and custom validation doesn't passed - failed return(validationResult); } } } catch (Exception e) { _logger.LogError(e, "Something went wrong in receipt prevalidation. Seems to be invalid receipt data. Skip this step."); } // 3. Validate Receipt in Apple (verification in IAP) try { _logger.LogDebug("Start receipt verification in IAP..."); var request = new IAPVerificationRequest(receiptData, _settings.Value.VerifyReceiptSharedSecret); IAPVerificationResponse iapVerificationResult = await restService.ValidateAppleReceiptAsync(request).ConfigureAwait(false); if (iapVerificationResult == null) { return(new AppleReceiptVerificationResult( "IAP receipt verification failed. Apple returned empty receipt.", IAPVerificationResponseStatus.InternalVerificationFailed )); } var iapStatus = iapVerificationResult.StatusCode; // 1.If status <> 0 - failed if (iapStatus != IAPVerificationResponseStatus.Ok) { return(new AppleReceiptVerificationResult( "IAP receipt verification failed", iapVerificationResult )); } _logger.LogInformation("IAPReceipt Verification passed."); return(new AppleReceiptVerificationResult( "Everything is OK.", iapVerificationResult )); } catch (Exception e) { _logger.LogError(e, "Something went wrong in IAP receipt verification"); return(new AppleReceiptVerificationResult( "Something went wrong in IAP receipt verification", IAPVerificationResponseStatus.InternalVerificationBroken )); } }