Skip to content
/ Mercato Public

Mercato is a lightweight StoreKit 2 wrapper that makes it easy to add in-app purchases and subscriptions to your iOS, macOS, tvOS, watchOS, and visionOS apps.

License

Notifications You must be signed in to change notification settings

tikhop/Mercato

Repository files navigation

Mercato

License Platform Swift

StoreKit 2 wrapper for In-App Purchases.

Installation

Swift Package Manager

.package(url: "https://github.com/tikhop/Mercato.git", .upToNextMajor(from: "1.1.0"))

Requirements

  • Swift 5.10+
  • iOS 15.4+ / macOS 12.3+ / tvOS 17.0+ / watchOS 10.0+ / visionOS 1.0+

Usage

Basic Purchase

import Mercato

// Fetch products
let products = try await Mercato.retrieveProducts(
    productIds: ["com.app.premium", "com.app.subscription"]
)

// Purchase
let purchase = try await Mercato.purchase(
    product: product,
    finishAutomatically: false
)

// Deliver content and finish
grantAccess(for: purchase.productId)
await purchase.finish()

Transaction Monitoring

// Current entitlements
for await result in Mercato.currentEntitlements {
    let transaction = try result.payload
    // Active subscriptions and non-consumables
}

// Live updates
for await result in Mercato.updates {
    let transaction = try result.payload
    await processTransaction(transaction)
    await transaction.finish()
}

Subscription Features

// Check eligibility
if await product.isEligibleForIntroOffer {
    // Show intro pricing
}

// Product info
product.localizedPrice        // "$9.99"
product.localizedPeriod      // "1 month"
product.hasTrial             // true/false
product.priceInDay           // 0.33

Purchase Options

let options = Mercato.PurchaseOptionsBuilder()
    .setQuantity(3)
    .setPromotionalOffer(offer)
    .setAppAccountToken(token)
    .build()

let purchase = try await Mercato.purchase(
    product: product,
    options: options,
    finishAutomatically: false
)

Error Handling

do {
    let purchase = try await Mercato.purchase(product: product)
} catch MercatoError.canceledByUser {
    // User canceled
} catch MercatoError.purchaseIsPending {
    // Ask to Buy
} catch MercatoError.productUnavailable {
    // Product not found
}

Utilities

// Check purchase status
let isPurchased = try await Mercato.isPurchased("com.app.premium")

// Get latest transaction
if let result = await Mercato.latest(for: productId) {
    let transaction = try result.payload
}

// Sync purchases (rarely needed)
try await Mercato.syncPurchases()

Advanced Commerce (iOS 18.4+)

Mercato includes support for Advanced Commerce API.

This feature requires iOS 18.4+, macOS 15.4+, tvOS 18.4+, watchOS 11.4+, or visionOS 2.4+.

Purchase with Compact JWS

import AdvancedCommerceMercato

// iOS/macOS/tvOS/visionOS - requires UI context
let purchase = try await AdvancedCommerceMercato.purchase(
    productId: "com.app.premium",
    compactJWS: signedJWS,
    confirmIn: viewController  // UIViewController on iOS, NSWindow on macOS
)

// watchOS - no UI context needed
let purchase = try await AdvancedCommerceMercato.purchase(
    productId: "com.app.premium",
    compactJWS: signedJWS
)

Purchase with Advanced Commerce Data

// Direct purchase with raw Advanced Commerce data
let result = try await AdvancedCommerceMercato.purchase(
    productId: "com.app.premium",
    advancedCommerceData: dataFromServer
)

Request Validation

All Advanced Commerce request models include built-in validation to ensure data integrity before sending to your server:

import AdvancedCommerceMercato

// Create a request
let request = OneTimeChargeCreateRequest(
    currency: "USD",
    item: OneTimeChargeItem(
        sku: "BOOK_001",
        displayName: "Digital Book",
        description: "Premium content",
        price: 999
    ),
    requestInfo: RequestInfo(requestReferenceId: UUID().uuidString),
    taxCode: "C003-00-2"
)

// Validate before sending to server
do {
    try request.validate()
    // Request is valid, proceed with encoding and sending
} catch {
    print("Validation error: \(error)")
}

Validation checks include currency codes, tax codes, storefronts, transaction IDs, and required fields.

Transaction Management

// Get latest transaction for a product
if let result = await AdvancedCommerceMercato.latestTransaction(for: productId) {
    let transaction = try result.payload
}

// Current entitlements
if let entitlements = await AdvancedCommerceMercato.currentEntitlements(for: productId) {
    for await result in entitlements {
        // Process active subscriptions
    }
}

// All transactions
if let transactions = await AdvancedCommerceMercato.allTransactions(for: productId) {
    for await result in transactions {
        // Process transaction history
    }
}

For detailed information about implementing Advanced Commerce, including request signing and supported operations, see AdvancedCommerce.md.

Documentation

See Usage.md for complete documentation.

Contributing

Contributions are welcome. Please feel free to submit a Pull Request.

License

MIT. See LICENSE for details.

About

Mercato is a lightweight StoreKit 2 wrapper that makes it easy to add in-app purchases and subscriptions to your iOS, macOS, tvOS, watchOS, and visionOS apps.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Languages