/// <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
                           ));
            }
        }