Socket
Book a DemoInstallSign in
Socket

apple-storekit-api

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

apple-storekit-api

Apple StoreKit API integration for In-App Purchases and Subscriptions

1.0.16
latest
Source
npmnpm
Version published
Weekly downloads
53
-53.1%
Maintainers
1
Weekly downloads
 
Created
Source

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';

// Example with file path
const configWithPath = {
  issuerId: 'YOUR_ISSUER_ID',
  keyId: 'YOUR_KEY_ID',
  privateKey: '/path/to/private_key.p8',
  bundleId: 'com.yourcompany.yourapp',
  environment: 'sandbox' // or 'production'
};

// Example with key content
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' // or 'production'
};

// Example with environment variables (recommended for production)
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!
  // environment is optional, will try production first, then sandbox if fails
};

const storeKit = new AppleStoreKit(configWithPath); // or configWithContent or configWithEnv

// Check subscription status
const status = await storeKit.getSubscriptionStatus('original-transaction-id');


// Verify purchase
const purchase = await storeKit.verifyPurchase('transactionId');

// Get transaction history
const history = await storeKit.getTransactionHistory('transactionId');

// Look up order information
const order = await storeKit.lookupOrder('orderId');

// Check refund status
const refund = await storeKit.refundLookup('transactionId');

// Get current environment
const currentEnv = storeKit.getCurrentEnvironment(); // 'production' or 'sandbox'

Configuration

Generating API Credentials

  • Go to App Store Connect:

    • Visit App Store Connect
    • Navigate to "Users and Access" > "Keys"
  • Create API Key:

    • Click the "+" button to create a new key
    • Enter a name for your key
    • Select "App Store Connect API" access
    • For In-App Purchases, ensure you have the following access rights:
      • App Access
      • Sales and Finance
      • In-App Purchase Management
  • Generate and Download Key:

    • Click "Generate" to create the key
    • Your browser will download a .p8 file
    • Important: Save this file securely. You can only download it once!
    • Note the Key ID (visible in the keys list)
  • Get Issuer ID:

    • The Issuer ID is shown at the top of the Keys page
    • It's the same for all keys in your organization
  • Bundle ID:

    • This is your app's bundle identifier
    • Found in Xcode or App Store Connect under app settings
    • Format: com.yourcompany.yourapp

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'
    // or
    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:

  • Auto Detection (recommended for development):

    const config = {
      // ... other config
      // environment not specified
    };
    
    • First tries production environment
    • If request fails, automatically retries with sandbox
    • Useful during development and testing
  • Manual Setting:

    const config = {
      // ... other config
      environment: 'production' // or 'sandbox'
    };
    
    • Explicitly sets the environment
    • No automatic switching
    • Recommended for production use

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;           // Age of customer's account
  appAccountToken: string;                // UUID of user account
  consumptionStatus: ConsumptionStatus;   // Extent of consumption
  customerConsented: boolean;             // User consent (must be true)
  deliveryStatus: DeliveryStatus;         // Delivery success status
  lifetimeDollarsPurchased: LifetimeDollars; // Total purchases (USD)
  lifetimeDollarsRefunded: LifetimeDollars;  // Total refunds (USD)
  platform: Platform;                     // Purchase platform
  playTime: PlayTime;                     // App usage time
  sampleContentProvided: boolean;         // Free sample provided
  userStatus: UserStatus;                 // Customer account status
}

Optional Fields:

{
  refundPreference?: RefundPreference;    // Your refund preference
}

Enum Values:

ConsumptionStatus

{
  UNDECLARED = 0,        // Use to avoid providing information
  NOT_CONSUMED = 1,      // Not consumed at all
  PARTIALLY_CONSUMED = 2, // Partially consumed
  FULLY_CONSUMED = 3     // Fully consumed
}

Platform

{
  UNDECLARED = 0,  // Use to avoid providing information
  APPLE = 1,       // Apple platform
  NON_APPLE = 2    // Non-Apple platform
}

DeliveryStatus

{
  DELIVERED_WORKING = 0,              // Delivered and working properly
  NOT_DELIVERED_QUALITY_ISSUE = 1,    // Not delivered due to quality issue
  DELIVERED_WRONG_ITEM = 2,           // Wrong item delivered
  NOT_DELIVERED_SERVER_OUTAGE = 3,    // Not delivered due to server outage
  NOT_DELIVERED_CURRENCY_CHANGE = 4,  // Not delivered due to currency change
  NOT_DELIVERED_OTHER = 5             // Not delivered for other reasons
}

AccountTenure

{
  UNDECLARED = 0,     // Use to avoid providing information
  DAYS_0_3 = 1,       // 0-3 days
  DAYS_3_10 = 2,      // 3-10 days
  DAYS_10_30 = 3,     // 10-30 days
  DAYS_30_90 = 4,     // 30-90 days
  DAYS_90_180 = 5,    // 90-180 days
  DAYS_180_365 = 6,   // 180-365 days
  DAYS_OVER_365 = 7   // Over 365 days
}

PlayTime

{
  UNDECLARED = 0,    // Use to avoid providing information
  MINUTES_0_5 = 1,   // 0-5 minutes
  MINUTES_5_60 = 2,  // 5-60 minutes
  HOURS_1_6 = 3,     // 1-6 hours
  HOURS_6_24 = 4,    // 6-24 hours
  DAYS_1_4 = 5,      // 1-4 days
  DAYS_4_16 = 6,     // 4-16 days
  DAYS_OVER_16 = 7   // Over 16 days
}

LifetimeDollars (for both purchased and refunded)

{
  UNDECLARED = 0,        // Use to avoid providing information
  USD_0 = 1,            // $0
  USD_0_01_49_99 = 2,   // $0.01-$49.99
  USD_50_99_99 = 3,     // $50-$99.99
  USD_100_499_99 = 4,   // $100-$499.99
  USD_500_999_99 = 5,   // $500-$999.99
  USD_1000_1999_99 = 6, // $1000-$1999.99
  USD_OVER_2000 = 7     // Over $2000
}

UserStatus

{
  UNDECLARED = 0,      // Use to avoid providing information
  ACTIVE = 1,          // Account is active
  SUSPENDED = 2,       // Account is suspended
  TERMINATED = 3,      // Account is terminated
  LIMITED_ACCESS = 4   // Account has limited access
}

RefundPreference

{
  UNDECLARED = 0,     // Use to avoid providing information
  GRANT = 1,          // Prefer to grant the refund
  DECLINE = 2,        // Prefer to decline the refund
  NO_PREFERENCE = 3   // No preference
}

Example usage:

const consumptionData = {
  customerConsented: true,  // Make sure you have obtained valid consent
  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

  • User Consent Required

    • You MUST obtain valid consent before sharing consumption data
    • Consent must be freely given, specific, informed, and unambiguous
    • Users should be able to withdraw consent at any time
    • Do NOT use App Tracking Transparency prompt for this consent
    • The API will return HTTP 400 with InvalidCustomerConsentError if customerConsented is not true
  • Response to Refund Requests

    • Send consumption information when you receive a CONSUMPTION_REQUEST notification
    • Respond within 12 hours of receiving the notification
    • Only send data if user has provided consent
  • Privacy Considerations

    • Never store sensitive user data unencrypted
    • Update your app's privacy labels to reflect data usage
    • Implement user data access and deletion requests
    • Follow Apple's privacy guidelines
  • Best Practices

    • Use UNDECLARED (0) for any field where you don't want to provide information
    • Always validate the data ranges before sending
    • Keep track of user consent status
    • Implement proper error handling for API responses

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.

Keywords

apple

FAQs

Package last updated on 26 Aug 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.