public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] Receipt receipt, HttpRequest req, ILogger log, CancellationToken cancellationToken) { var result = default(ValidationResult); if (!string.IsNullOrEmpty(receipt?.BundleId) && !string.IsNullOrEmpty(receipt?.ProductId) && !string.IsNullOrEmpty(receipt?.TransactionId) && !string.IsNullOrEmpty(receipt?.Token)) { var appleResponse = await PostAppleReceiptAsync(AppleProductionUrl, receipt, log, cancellationToken); // Apple recommends calling production, then falling back to sandbox on an error code if (appleResponse?.WrongEnvironment == true) { log.LogInformation("Sandbox purchase, calling test environment..."); appleResponse = await PostAppleReceiptAsync(AppleTestUrl, receipt, log, cancellationToken); } if (appleResponse?.IsValid == true) { result = ValidateProduct(receipt, appleResponse, log); } else if (!string.IsNullOrEmpty(appleResponse?.Error)) { result = new ValidationResult(false, appleResponse.Error); } else { result = new ValidationResult(false, $"Invalid {nameof(Receipt)}"); } } else { result = new ValidationResult(false, $"Invalid {nameof(Receipt)}"); } await _verificationRepository.SaveLogAsync(nameof(Apple), receipt, result, cancellationToken); if (result.IsValid && result.ValidatedReceipt != null) { log.LogInformation($"Validated IAP '{receipt.BundleId}':'{receipt.ProductId}'"); return(new JsonResult(result.ValidatedReceipt)); } if (!string.IsNullOrEmpty(receipt?.BundleId) && !string.IsNullOrEmpty(receipt?.ProductId)) { log.LogInformation($"Failed to validate IAP '{receipt.BundleId}':'{receipt.ProductId}', reason '{result?.Message ?? string.Empty}'"); } else { log.LogInformation($"Failed to validate IAP, reason '{result?.Message ?? string.Empty}'"); } return(new BadRequestResult()); }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] Receipt receipt, HttpRequest req, ILogger log, CancellationToken cancellationToken) { var result = default(ValidationResult); if (!string.IsNullOrEmpty(receipt?.BundleId) && !string.IsNullOrEmpty(receipt?.ProductId) && !string.IsNullOrEmpty(receipt?.TransactionId) && !string.IsNullOrEmpty(receipt?.DeveloperPayload) && !string.IsNullOrEmpty(receipt?.Token)) { try { var product = await _googleService.Inappproducts.Get(receipt.BundleId, receipt.ProductId) .ExecuteAsync(cancellationToken); if (product != null) { result = product.PurchaseType == "subscription" ? await ValidateSubscriptionAsync(receipt, log, cancellationToken) : await ValidateProductAsync(receipt, log, cancellationToken); } else { result = new ValidationResult(false, $"IAP '{receipt.BundleId}':'{receipt.ProductId}' not found"); } } catch (Exception ex) { log.LogError($"Failed to validate IAP: {ex.Message}", ex); result = new ValidationResult(false, ex.Message); } } else { result = new ValidationResult(false, $"Invalid {nameof(Receipt)}"); } await _verificationRepository.SaveLogAsync(nameof(Google), receipt, result, cancellationToken); if (result.IsValid && result.ValidatedReceipt != null) { log.LogInformation($"Validated IAP '{receipt.BundleId}':'{receipt.ProductId}'"); return(new JsonResult(result.ValidatedReceipt)); } if (!string.IsNullOrEmpty(receipt?.BundleId) && !string.IsNullOrEmpty(receipt?.ProductId)) { log.LogInformation($"Failed to validate IAP '{receipt.BundleId}':'{receipt.ProductId}', reason '{result?.Message ?? string.Empty}'"); } else { log.LogInformation($"Failed to validate IAP, reason '{result?.Message ?? string.Empty}'"); } return(new BadRequestResult()); }