Crate iap

source · []
Expand description

iap is a rust library for verifying receipt information for purchases made through the Google Play Store or the Apple App Store.

Current Features

  • Validating receipt data received from Unity’s IAP plugin to verify subscriptions and if they are valid and not expired
  • Helper functions to receive response data from Google/Apple for more granular error handling or validation

Supported Transaction Types

  • Subscriptions

Coming Features

  • Non-subscription purchase types
  • Manual input of data for verification not received through Unity IAP

Usage

For simple validation of Unity IAP receipts

You can receive a PurchaseResponse which will simply tell you if a purchase is valid (and not expired if a subscription) by creating a UnityPurchaseValidator.

use iap::*;

const APPLE_SECRET: &str = "<APPLE SECRET>";
const GOOGLE_KEY: &str = "<GOOGLE KEY JSON>";

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let validator = UnityPurchaseValidator::default()
        .set_apple_secret(APPLE_SECRET.to_string())
        .set_google_service_account_key(GOOGLE_KEY.to_string())?;

    // RECEIPT_INPUT would be the Json string containing the store, transaction id, and payload
    // from Unity IAP. ie:
    // "{ \"Store\": \"GooglePlay\", \"TransactionID\": \"<Txn ID>\", \"Payload\": \"<Payload>\" }"
    let unity_receipt = UnityPurchaseReceipt::from(&std::env::var("RECEIPT_INPUT")?)?;

    let response = validator.validate(&unity_receipt).await?;

    println!("PurchaseResponse is valid: {}", response.valid);

    Ok(())
}

If you wanted more granular control and access to the response from the store’s endpoint, we provide helper functions to do so.

For the Play Store:

pub async fn validate(receipt: &UnityPurchaseReceipt) -> error::Result<PurchaseResponse> {
    let response = fetch_google_receipt_data(receipt, "<GOOGLE_KEY>").await?;

    // debug or validate on your own with the data in the response
    println!("Expiry data: {:?}", response.expiry_time);

    // or just simply validate the response
    validate_google_subscription(&response, chrono::Utc::now())
}

For the App Store:

pub async fn validate(receipt: &UnityPurchaseReceipt) -> error::Result<PurchaseResponse> {
    let response = fetch_apple_receipt_data(receipt, "<APPLE_SECRET>").await?;

    // was this purchase made in the production or sandbox environment
    println!("Environment: {}", response.environment.clone().unwrap());

    Ok(validate_apple_subscription(&response, &receipt.transaction_id, chrono::Utc::now()))
}

Modules

Convenience types for lib specific error handling

Structs

Convenience struct for storing our production and sandbox URLs. Best practice is to attempt to verify against production, and if that fails, to then request verification from the sandbox. See: https://developer.apple.com/documentation/appstorereceipts/verifyreceipt

A simple validation response returned by any of the validate methods which tells us if the receipt represents a valid purchase and/or active subscription.

Represents the deserialized contents of the Json string delivered by Unity IAP.

Validator which stores our needed secrets for being able to authenticate against the stores’ endpoints, and performs our validation.

Enums

This is the platform on which the purchase that created the unity receipt was made.

enum for differentiating between product purchases and subscriptions

Traits

Trait which allows us to retrieve receipt data from an object’s own secrets.

Convenience trait which combines ReceiptDataFetcher and Validator traits.

The base trait for implementing a validator. Mock Validators can be made for running local tests by implementing this trait.

Functions

Retrieves the responseBody data from Apple

Response call with AppleUrls parameter for tests

Retrieves the response body from google

Retrieves the google response with a specific uri, useful for running tests.

Validates that a package status is valid

Simply validates based on whether or not the subscription’s expiration has passed.

Simply validates product purchase

Simply validates based on whether or not the subscription’s expiration has passed.