Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ This monorepo contains all OpenIAP packages:

- **[docs](packages/docs)** - Documentation site at [openiap.dev](https://openiap.dev)
- **[spec](packages/gql)** - OpenIAP specification and type generation [![Spec Release](https://img.shields.io/github/v/tag/hyodotdev/openiap?filter=gql-*&label=version&logo=graphql&color=purple)](https://github.com/hyodotdev/openiap/releases?q=gql&expanded=true)
- **[google](packages/google)** - Android library [![Maven Central (Play)](https://img.shields.io/maven-central/v/io.github.hyochan.openiap/openiap-google?label=Play%20Store)](https://central.sonatype.com/artifact/io.github.hyochan.openiap/openiap-google) [![Maven Central (Horizon)](https://img.shields.io/maven-central/v/io.github.hyochan.openiap/openiap-google-horizon?label=Meta%20Horizon)](https://central.sonatype.com/artifact/io.github.hyochan.openiap/openiap-google-horizon) [![CI](https://github.com/hyodotdev/openiap/actions/workflows/ci.yml/badge.svg)](https://github.com/hyodotdev/openiap/actions/workflows/ci.yml)
- **[apple](packages/apple)** - iOS/macOS library [![Swift Package](https://img.shields.io/github/v/tag/hyodotdev/openiap?filter=2.*&label=version&logo=swift&color=orange)](https://github.com/hyodotdev/openiap/releases?q=Apple&expanded=true) [![CocoaPods](https://img.shields.io/cocoapods/v/openiap?color=E35A5F&logo=cocoapods)](https://cocoapods.org/pods/openiap) [![CI](https://github.com/hyodotdev/openiap/actions/workflows/ci.yml/badge.svg)](https://github.com/hyodotdev/openiap/actions/workflows/ci.yml)
- **[google](packages/google)** - Android library [![Maven Central (Play)](https://img.shields.io/maven-central/v/io.github.hyochan.openiap/openiap-google?label=Play%20Store)](https://central.sonatype.com/artifact/io.github.hyochan.openiap/openiap-google) [![Maven Central (Horizon)](https://img.shields.io/maven-central/v/io.github.hyochan.openiap/openiap-google-horizon?label=Meta%20Horizon)](https://central.sonatype.com/artifact/io.github.hyochan.openiap/openiap-google-horizon) [![CI](https://github.com/hyodotdev/openiap/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/hyodotdev/openiap/actions/workflows/ci.yml?query=branch%3Amain)
- **[apple](packages/apple)** - iOS/macOS library [![Swift Package](https://img.shields.io/github/v/tag/hyodotdev/openiap?filter=2.*&label=version&logo=swift&color=orange)](https://github.com/hyodotdev/openiap/releases?q=Apple&expanded=true) [![CocoaPods](https://img.shields.io/cocoapods/v/openiap?color=E35A5F&logo=cocoapods)](https://cocoapods.org/pods/openiap) [![CI](https://github.com/hyodotdev/openiap/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/hyodotdev/openiap/actions/workflows/ci.yml?query=branch%3Amain)

## Libraries

Expand Down
2 changes: 1 addition & 1 deletion knowledge/_claude-context/context.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# OpenIAP Project Context

> **Auto-generated for Claude Code**
> Last updated: 2026-04-16T13:24:54.898Z
> Last updated: 2026-04-16T13:44:54.257Z
>
> Usage: `claude --context knowledge/_claude-context/context.md`

Expand Down
64 changes: 64 additions & 0 deletions libraries/expo-iap/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,56 @@ export interface ActiveSubscription {
willExpireSoon?: (boolean | null);
}

/**
* Advanced Commerce metadata from a transaction (iOS 18.4+).
* Contains item details, tax information, and refund data for purchases
* made through the Advanced Commerce API using generic SKUs.
* Only present for transactions that use the Advanced Commerce API.
*/
export interface AdvancedCommerceInfoIOS {
/** Optional description */
description?: (string | null);
/** Optional display name */
displayName?: (string | null);
/** Estimated tax amount (decimal string) */
estimatedTax?: (string | null);
/** The items purchased as part of this transaction */
items: AdvancedCommerceItemIOS[];
/** Request reference identifier for tracking */
requestReferenceId?: (string | null);
/** Tax code for the transaction */
taxCode?: (string | null);
/** Price excluding tax (decimal string) */
taxExclusivePrice?: (string | null);
/** Tax rate applied (decimal string) */
taxRate?: (string | null);
}

/** Details of an Advanced Commerce item (iOS 18.4+). */
export interface AdvancedCommerceItemDetailsIOS {
/** JSON representation of the item details */
jsonRepresentation?: (string | null);
}

/**
* An item purchased through the Advanced Commerce API (iOS 18.4+).
* Represents a developer-defined product within a generic SKU transaction.
*/
export interface AdvancedCommerceItemIOS {
/** The item's detail information */
details?: (AdvancedCommerceItemDetailsIOS | null);
/** Refunds issued for this item, if any */
refunds?: (AdvancedCommerceRefundIOS[] | null);
/** Date access to this item was revoked (milliseconds since epoch) */
revocationDate?: (number | null);
}

/** Refund information for an Advanced Commerce item (iOS 18.4+). */
export interface AdvancedCommerceRefundIOS {
/** JSON representation of the refund details */
jsonRepresentation?: (string | null);
}

/**
* Alternative billing mode for Android
* Controls which billing system is used
Expand Down Expand Up @@ -1112,6 +1162,12 @@ export interface PurchaseError {
}

export interface PurchaseIOS extends PurchaseCommon {
/**
* Advanced Commerce API metadata (iOS 18.4+).
* Present only for transactions that use the Advanced Commerce API.
* Contains item details, tax information, and refund data for generic SKU purchases.
*/
advancedCommerceInfoIOS?: (AdvancedCommerceInfoIOS | null);
appAccountToken?: (string | null);
appBundleIdIOS?: (string | null);
countryCodeIOS?: (string | null);
Expand Down Expand Up @@ -1188,6 +1244,13 @@ export interface Query {
fetchProducts: Promise<(ProductOrSubscription[] | Product[] | ProductSubscription[] | null)>;
/** Get active subscriptions (filters by subscriptionIds when provided) */
getActiveSubscriptions: Promise<ActiveSubscription[]>;
/**
* Get the full StoreKit 2 transaction history as PurchaseIOS values.
* Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
* for finished consumables to be included (iOS 18+).
* Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
*/
getAllTransactionsIOS: Promise<PurchaseIOS[]>;
/** Fetch the current app transaction (iOS 16+) */
getAppTransactionIOS?: Promise<(AppTransaction | null)>;
/** Get all available purchases for the current user */
Expand Down Expand Up @@ -1901,6 +1964,7 @@ export type QueryArgsMap = {
currentEntitlementIOS: QueryCurrentEntitlementIosArgs;
fetchProducts: QueryFetchProductsArgs;
getActiveSubscriptions: QueryGetActiveSubscriptionsArgs;
getAllTransactionsIOS: never;
getAppTransactionIOS: never;
getAvailablePurchases: QueryGetAvailablePurchasesArgs;
getExternalPurchaseCustomLinkTokenIOS: QueryGetExternalPurchaseCustomLinkTokenIosArgs;
Expand Down
156 changes: 156 additions & 0 deletions libraries/flutter_inapp_purchase/lib/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,147 @@ class ActiveSubscription {
}
}

/// Advanced Commerce metadata from a transaction (iOS 18.4+).
/// Contains item details, tax information, and refund data for purchases
/// made through the Advanced Commerce API using generic SKUs.
/// Only present for transactions that use the Advanced Commerce API.
class AdvancedCommerceInfoIOS {
const AdvancedCommerceInfoIOS({
this.description,
this.displayName,
this.estimatedTax,
required this.items,
this.requestReferenceId,
this.taxCode,
this.taxExclusivePrice,
this.taxRate,
});

/// Optional description
final String? description;
/// Optional display name
final String? displayName;
/// Estimated tax amount (decimal string)
final String? estimatedTax;
/// The items purchased as part of this transaction
final List<AdvancedCommerceItemIOS> items;
/// Request reference identifier for tracking
final String? requestReferenceId;
/// Tax code for the transaction
final String? taxCode;
/// Price excluding tax (decimal string)
final String? taxExclusivePrice;
/// Tax rate applied (decimal string)
final String? taxRate;

factory AdvancedCommerceInfoIOS.fromJson(Map<String, dynamic> json) {
return AdvancedCommerceInfoIOS(
description: json['description'] as String?,
displayName: json['displayName'] as String?,
estimatedTax: json['estimatedTax'] as String?,
items: (json['items'] as List<dynamic>).map((e) => AdvancedCommerceItemIOS.fromJson(e as Map<String, dynamic>)).toList(),
requestReferenceId: json['requestReferenceId'] as String?,
taxCode: json['taxCode'] as String?,
taxExclusivePrice: json['taxExclusivePrice'] as String?,
taxRate: json['taxRate'] as String?,
);
}

Map<String, dynamic> toJson() {
return {
'__typename': 'AdvancedCommerceInfoIOS',
'description': description,
'displayName': displayName,
'estimatedTax': estimatedTax,
'items': items.map((e) => e.toJson()).toList(),
'requestReferenceId': requestReferenceId,
'taxCode': taxCode,
'taxExclusivePrice': taxExclusivePrice,
'taxRate': taxRate,
};
}
}

/// Details of an Advanced Commerce item (iOS 18.4+).
class AdvancedCommerceItemDetailsIOS {
const AdvancedCommerceItemDetailsIOS({
this.jsonRepresentation,
});

/// JSON representation of the item details
final String? jsonRepresentation;

factory AdvancedCommerceItemDetailsIOS.fromJson(Map<String, dynamic> json) {
return AdvancedCommerceItemDetailsIOS(
jsonRepresentation: json['jsonRepresentation'] as String?,
);
}

Map<String, dynamic> toJson() {
return {
'__typename': 'AdvancedCommerceItemDetailsIOS',
'jsonRepresentation': jsonRepresentation,
};
}
}

/// An item purchased through the Advanced Commerce API (iOS 18.4+).
/// Represents a developer-defined product within a generic SKU transaction.
class AdvancedCommerceItemIOS {
const AdvancedCommerceItemIOS({
this.details,
this.refunds,
this.revocationDate,
});

/// The item's detail information
final AdvancedCommerceItemDetailsIOS? details;
/// Refunds issued for this item, if any
final List<AdvancedCommerceRefundIOS>? refunds;
/// Date access to this item was revoked (milliseconds since epoch)
final double? revocationDate;

factory AdvancedCommerceItemIOS.fromJson(Map<String, dynamic> json) {
return AdvancedCommerceItemIOS(
details: json['details'] != null ? AdvancedCommerceItemDetailsIOS.fromJson(json['details'] as Map<String, dynamic>) : null,
refunds: (json['refunds'] as List<dynamic>?) == null ? null : (json['refunds'] as List<dynamic>?)!.map((e) => AdvancedCommerceRefundIOS.fromJson(e as Map<String, dynamic>)).toList(),
revocationDate: (json['revocationDate'] as num?)?.toDouble(),
);
}

Map<String, dynamic> toJson() {
return {
'__typename': 'AdvancedCommerceItemIOS',
'details': details?.toJson(),
'refunds': refunds == null ? null : refunds!.map((e) => e.toJson()).toList(),
'revocationDate': revocationDate,
};
}
}

/// Refund information for an Advanced Commerce item (iOS 18.4+).
class AdvancedCommerceRefundIOS {
const AdvancedCommerceRefundIOS({
this.jsonRepresentation,
});

/// JSON representation of the refund details
final String? jsonRepresentation;

factory AdvancedCommerceRefundIOS.fromJson(Map<String, dynamic> json) {
return AdvancedCommerceRefundIOS(
jsonRepresentation: json['jsonRepresentation'] as String?,
);
}

Map<String, dynamic> toJson() {
return {
'__typename': 'AdvancedCommerceRefundIOS',
'jsonRepresentation': jsonRepresentation,
};
}
}

class AppTransaction {
const AppTransaction({
required this.appId,
Expand Down Expand Up @@ -2612,6 +2753,7 @@ class PurchaseError {

class PurchaseIOS extends Purchase implements PurchaseCommon {
const PurchaseIOS({
this.advancedCommerceInfoIOS,
this.appAccountToken,
this.appBundleIdIOS,
this.countryCodeIOS,
Expand Down Expand Up @@ -2649,6 +2791,10 @@ class PurchaseIOS extends Purchase implements PurchaseCommon {
this.isAlternativeBilling,
});

/// Advanced Commerce API metadata (iOS 18.4+).
/// Present only for transactions that use the Advanced Commerce API.
/// Contains item details, tax information, and refund data for generic SKU purchases.
final AdvancedCommerceInfoIOS? advancedCommerceInfoIOS;
final String? appAccountToken;
final String? appBundleIdIOS;
final String? countryCodeIOS;
Expand Down Expand Up @@ -2688,6 +2834,7 @@ class PurchaseIOS extends Purchase implements PurchaseCommon {

factory PurchaseIOS.fromJson(Map<String, dynamic> json) {
return PurchaseIOS(
advancedCommerceInfoIOS: json['advancedCommerceInfoIOS'] != null ? AdvancedCommerceInfoIOS.fromJson(json['advancedCommerceInfoIOS'] as Map<String, dynamic>) : null,
appAccountToken: json['appAccountToken'] as String?,
appBundleIdIOS: json['appBundleIdIOS'] as String?,
countryCodeIOS: json['countryCodeIOS'] as String?,
Expand Down Expand Up @@ -2730,6 +2877,7 @@ class PurchaseIOS extends Purchase implements PurchaseCommon {
Map<String, dynamic> toJson() {
return {
'__typename': 'PurchaseIOS',
'advancedCommerceInfoIOS': advancedCommerceInfoIOS?.toJson(),
'appAccountToken': appAccountToken,
'appBundleIdIOS': appBundleIdIOS,
'countryCodeIOS': countryCodeIOS,
Expand Down Expand Up @@ -4830,6 +4978,11 @@ abstract class QueryResolver {
});
/// Get active subscriptions (filters by subscriptionIds when provided)
Future<List<ActiveSubscription>> getActiveSubscriptions([List<String>? subscriptionIds]);
/// Get the full StoreKit 2 transaction history as PurchaseIOS values.
/// Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
/// for finished consumables to be included (iOS 18+).
/// Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
Future<List<PurchaseIOS>> getAllTransactionsIOS();
/// Fetch the current app transaction (iOS 16+)
Future<AppTransaction?> getAppTransactionIOS();
/// Get all available purchases for the current user
Expand Down Expand Up @@ -5030,6 +5183,7 @@ typedef QueryFetchProductsHandler = Future<FetchProductsResult> Function({
ProductQueryType? type,
});
typedef QueryGetActiveSubscriptionsHandler = Future<List<ActiveSubscription>> Function([List<String>? subscriptionIds]);
typedef QueryGetAllTransactionsIOSHandler = Future<List<PurchaseIOS>> Function();
typedef QueryGetAppTransactionIOSHandler = Future<AppTransaction?> Function();
typedef QueryGetAvailablePurchasesHandler = Future<List<Purchase>> Function({
bool? alsoPublishToEventListenerIOS,
Expand Down Expand Up @@ -5061,6 +5215,7 @@ class QueryHandlers {
this.currentEntitlementIOS,
this.fetchProducts,
this.getActiveSubscriptions,
this.getAllTransactionsIOS,
this.getAppTransactionIOS,
this.getAvailablePurchases,
this.getExternalPurchaseCustomLinkTokenIOS,
Expand All @@ -5083,6 +5238,7 @@ class QueryHandlers {
final QueryCurrentEntitlementIOSHandler? currentEntitlementIOS;
final QueryFetchProductsHandler? fetchProducts;
final QueryGetActiveSubscriptionsHandler? getActiveSubscriptions;
final QueryGetAllTransactionsIOSHandler? getAllTransactionsIOS;
final QueryGetAppTransactionIOSHandler? getAppTransactionIOS;
final QueryGetAvailablePurchasesHandler? getAvailablePurchases;
final QueryGetExternalPurchaseCustomLinkTokenIOSHandler? getExternalPurchaseCustomLinkTokenIOS;
Expand Down
Loading
Loading