Apple StoreKit API
A TypeScript/JavaScript library for Apple StoreKit API integration. Handles In-App Purchases and subscription management using the latest StoreKit 2 API.
Features
- Subscription status verification
- Purchase verification (using StoreKit 2)
- Transaction history
- Order information lookup
- Refund status checking
- Consumption information reporting
- Flexible private key handling (file path or string content)
- Auto environment detection (production/sandbox)
- Wide Node.js version support (10.24.1 and above)
Installation
npm install apple-storekit-api
Requirements
- Node.js >= 10.24.1
- App Store Connect API access
- Private key in
.p8
format (file or content)
- Issuer ID and Key ID
Usage
import { AppleStoreKit } from 'apple-storekit-api';
const configWithPath = {
issuerId: 'YOUR_ISSUER_ID',
keyId: 'YOUR_KEY_ID',
privateKey: '/path/to/private_key.p8',
bundleId: 'com.yourcompany.yourapp',
environment: 'sandbox'
};
const configWithContent = {
issuerId: 'YOUR_ISSUER_ID',
keyId: 'YOUR_KEY_ID',
privateKey: '-----BEGIN PRIVATE KEY-----\nYOUR_PRIVATE_KEY_CONTENT\n-----END PRIVATE KEY-----',
bundleId: 'com.yourcompany.yourapp',
environment: 'sandbox'
};
const configWithEnv = {
issuerId: process.env.APPLE_ISSUER_ID!,
keyId: process.env.APPLE_KEY_ID!,
privateKey: process.env.APPLE_PRIVATE_KEY!,
bundleId: process.env.APPLE_BUNDLE_ID!
};
const storeKit = new AppleStoreKit(configWithPath);
const status = await storeKit.getSubscriptionStatus('original-transaction-id');
const purchase = await storeKit.verifyPurchase('transactionId');
const history = await storeKit.getTransactionHistory('transactionId');
const order = await storeKit.lookupOrder('orderId');
const refund = await storeKit.refundLookup('transactionId');
const currentEnv = storeKit.getCurrentEnvironment();
Configuration
Generating API Credentials
Private Key Handling
The library accepts the private key in two formats:
-
File Path: Provide the path to your .p8
file
privateKey: '/absolute/path/to/private_key.p8'
privateKey: './relative/path/to/private_key.p8'
-
Key Content: Provide the private key content directly
privateKey: '-----BEGIN PRIVATE KEY-----\nYOUR_KEY_CONTENT\n-----END PRIVATE KEY-----'
Environment Detection
The library supports automatic environment detection:
API Methods
Subscription Status
const status = await storeKit.getSubscriptionStatus('original-transaction-id');
This method returns the current status of a subscription, including:
- Original transaction ID
- Status
- Expiration date
- Transaction info
- Renewal info
Purchases
verifyPurchase(transactionId: string)
: Verify a specific purchase using StoreKit 2 API
getTransactionHistory(transactionId: string)
: Get transaction history
lookupOrder(orderId: string)
: Look up order details
refundLookup(transactionId: string)
: Check refund status
setAppAccountToken(originalTransactionId: string, appAccountToken: string)
: Set or update app account token for a transaction
Consumption Information
sendConsumptionInformation(transactionId: string, consumptionRequest: ConsumptionRequest)
: Send consumption information for refund decisions
The ConsumptionRequest
interface includes required and optional fields with their corresponding enum values:
Required Fields:
{
accountTenure: AccountTenure;
appAccountToken: string;
consumptionStatus: ConsumptionStatus;
customerConsented: boolean;
deliveryStatus: DeliveryStatus;
lifetimeDollarsPurchased: LifetimeDollars;
lifetimeDollarsRefunded: LifetimeDollars;
platform: Platform;
playTime: PlayTime;
sampleContentProvided: boolean;
userStatus: UserStatus;
}
Optional Fields:
{
refundPreference?: RefundPreference;
}
Enum Values:
ConsumptionStatus
{
UNDECLARED = 0,
NOT_CONSUMED = 1,
PARTIALLY_CONSUMED = 2,
FULLY_CONSUMED = 3
}
Platform
{
UNDECLARED = 0,
APPLE = 1,
NON_APPLE = 2
}
DeliveryStatus
{
DELIVERED_WORKING = 0,
NOT_DELIVERED_QUALITY_ISSUE = 1,
DELIVERED_WRONG_ITEM = 2,
NOT_DELIVERED_SERVER_OUTAGE = 3,
NOT_DELIVERED_CURRENCY_CHANGE = 4,
NOT_DELIVERED_OTHER = 5
}
AccountTenure
{
UNDECLARED = 0,
DAYS_0_3 = 1,
DAYS_3_10 = 2,
DAYS_10_30 = 3,
DAYS_30_90 = 4,
DAYS_90_180 = 5,
DAYS_180_365 = 6,
DAYS_OVER_365 = 7
}
PlayTime
{
UNDECLARED = 0,
MINUTES_0_5 = 1,
MINUTES_5_60 = 2,
HOURS_1_6 = 3,
HOURS_6_24 = 4,
DAYS_1_4 = 5,
DAYS_4_16 = 6,
DAYS_OVER_16 = 7
}
LifetimeDollars (for both purchased and refunded)
{
UNDECLARED = 0,
USD_0 = 1,
USD_0_01_49_99 = 2,
USD_50_99_99 = 3,
USD_100_499_99 = 4,
USD_500_999_99 = 5,
USD_1000_1999_99 = 6,
USD_OVER_2000 = 7
}
UserStatus
{
UNDECLARED = 0,
ACTIVE = 1,
SUSPENDED = 2,
TERMINATED = 3,
LIMITED_ACCESS = 4
}
RefundPreference
{
UNDECLARED = 0,
GRANT = 1,
DECLINE = 2,
NO_PREFERENCE = 3
}
Example usage:
const consumptionData = {
customerConsented: true,
consumptionStatus: ConsumptionStatus.FULLY_CONSUMED,
platform: Platform.APPLE,
sampleContentProvided: true,
deliveryStatus: DeliveryStatus.DELIVERED_WORKING,
appAccountToken: 'YOUR_APP_ACCOUNT_TOKEN',
accountTenure: AccountTenure.DAYS_180_365,
playTime: PlayTime.HOURS_1_6,
lifetimeDollarsRefunded: LifetimeDollars.USD_0,
lifetimeDollarsPurchased: LifetimeDollars.USD_50_99_99,
userStatus: UserStatus.ACTIVE,
refundPreference: RefundPreference.NO_PREFERENCE
};
await storeKit.sendConsumptionInformation('transactionId', consumptionData);
Important Notes on Consumption Information
Utility
getCurrentEnvironment()
: Get the current environment being used
Security Best Practices
-
Private Key Storage:
- Never commit your
.p8
file to version control
- Store the key securely (e.g., environment variables, secure key management service)
- Consider using environment variables for all sensitive data:
const config = {
issuerId: process.env.APPLE_ISSUER_ID,
keyId: process.env.APPLE_KEY_ID,
privateKey: process.env.APPLE_PRIVATE_KEY,
bundleId: process.env.APPLE_BUNDLE_ID
};
-
Environment Management:
- Use 'sandbox' for development and testing
- Use 'production' for live apps
- Consider using different keys for sandbox and production
Compatibility
This library is compatible with:
- Node.js versions 10.24.1 and above
- TypeScript 4.9.x and above
- All major Node.js frameworks (Express, Koa, Nest.js, etc.)
- Both CommonJS and ES Modules
Set App Account Token
Sets or updates the app account token for a transaction made outside of your app:
try {
await storeKit.setAppAccountToken(
'original-transaction-id',
'user-account-uuid'
);
console.log('App account token updated successfully');
} catch (error) {
console.error('Failed to update app account token:', error.message);
}
Note: This method is available in App Store Server API 1.16+ and is useful for:
- Linking transactions to specific user accounts
- Updating account tokens for purchases made outside your app
- Improving transaction tracking and analytics
Error Handling
The library includes comprehensive error handling for API responses. All methods throw descriptive errors that include the original Apple StoreKit API error message when available.
try {
const status = await storeKit.getSubscriptionStatus('originalTransactionId');
} catch (error) {
console.error('StoreKit API Error:', error.message);
}
License
MIT
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
)
- Commit your changes (
git commit -m 'feat: amazing new feature'
)
- Push to the branch (
git push origin feature/amazing-feature
)
- Open a Pull Request
Support
For issues and feature requests, please use the GitHub issue tracker.