Git Product home page Git Product logo

app-store-server-api's Introduction

app-store-server-api

A Node.js client for the App Store Server API.

Features

  • Transaction history, subscription status and order lookup endpoints
  • Notification test and history endpoints
  • Typed responses (i.e. you get auto-complete for the fields in the response)
  • Manages authentication tokens for you
  • Helpers to decode JWS items
  • Performs certificate validation against Apple's CA.
  • Types and helpers for App Store Server Notifications V2

Requirements

Node.js 15.6.0 or newer

Installation

npm install app-store-server-api

Usage

Prerequisites

To get started, you must obtain the following:

A note on the issuer ID: Apple's documentation currently has incorrect instructions on how to obtain this. To get your issuer ID, you must create an API key for App Store Connect (not the App Store Server API). Only after creating your first API key will the issuer ID appear.

Create a client

const { AppStoreServerAPI, Environment, decodeRenewalInfo, decodeTransaction, decodeTransactions } = require("app-store-server-api")
// or
import { AppStoreServerAPI, Environment, decodeRenewalInfo, decodeTransaction, decodeTransactions } from "app-store-server-api"

const KEY = 
`-----BEGIN PRIVATE KEY-----
MHcCAQEEIPWH5lyoG7Wbzv71ntF6jNvFwwJLKYmPWN/KBD4qJfMcoAoGCCqGSM49
AwEHoUQDQgAEMOlUa/hmyAPU/RUBds6xzDO8QNrTFhFwzm8E4wxDnSAx8R9WOMnD
cVGdtnbLFIdLk8g4S7oAfV/gGILKuc+Vqw==
-----END PRIVATE KEY-----`

const KEY_ID = "ABCD123456"
const ISSUER_ID = "91fa5999-7b54-4363-a2a8-265363fa6cbe"
const APP_BUNDLE_ID = "com.yourcompany.app"

const api = new AppStoreServerAPI(
  KEY, KEY_ID, ISSUER_ID, APP_BUNDLE_ID, Environment.Production
)

History

const response = await api.getTransactionHistory(originalTransactionId)

// Decoding not only reveals the contents of the transactions but also verifies that they were signed by Apple.
const transactions = await decodeTransactions(response.signedTransactions)

for (let transaction of transactions) {
  // Do something with your transactions...
}

// The response contains at most 20 entries. You can check to see if there are more.
if (response.hasMore) {
  const nextResponse = await api.getTransactionHistory(originalTransactionId, { revision: response.revision })
  // ...
}

The library supports the filter and sort options introduced at WWDC 2022. See Get Transaction History for a list of available options.

// Import parameter types
import { ProductTypeParameter, SortParameter } from "app-store-server-api"

const response = await api.getTransactionHistory(originalTransactionId, {
  productType: ProductTypeParameter.AutoRenewable,
  sort: SortParameter.Descending,
})

Subscription status

const response = await api.getSubscriptionStatuses(originalTransactionId)

// Find the transaction you're looking for
const item = response.data[0].lastTransactions.find(item => item.originalTransactionId === originalTransactionId)

const transactionInfo = await decodeTransaction(item.signedTransactionInfo)
const renewalInfo = await decodeRenewalInfo(item.signedRenewalInfo)

Order lookup

// Import the status type
import { OrderLookupStatus } from "app-store-server-api"

const response = await api.lookupOrder(orderId)

if (response.status === OrderLookupStatus.Valid) {
    const transactions = await decodeTransactions(response.signedTransactions)
    /// ...
}

Request test notification

const response = await api.requestTestNotification()
// response.testNotificationToken identifies the notification that will be sent.

Get test notification status

const response = await api.getTestNotificationStatus("ae0e2185-a3c6-47e4-b41a-6ef4bc86314e_1656062546521")

Notification history

// Start and end date are required. 
// The earliest supported start date is June 6th (the start of WWDC 2022).
const response = await api.getNotificationHistory({
  startDate: 1654466400000, // June 6th 2022
  endDate: new Date().getTime()
})

// Check if there are more items.
if (response.hasMore) {
  // Use history.paginationToken to fetch additional items.
}

Decoding server notifications

The App Store Server API and App Store Server Notifications (version 2) are closely related and use some of the same types and encoding formats. This library includes a function to help you decode notifications (which will also verify their signature).

import { decodeNotificationPayload, isDecodedNotificationDataPayload, isDecodedNotificationSummaryPayload } from "app-store-server-api"

// signedPayload is the body sent by Apple
const payload = await decodeNotificationPayload(signedPayload)

// You might want to check that the bundle ID matches that of your app
if (payload.data.bundleId === APP_BUNDLE_ID) {
  // Handle the notification...
}

// Notifications can contain either a data field or a summary field but never both.
// Use the provided type guards to determine which is present.
if (isDecodedNotificationDataPayload(payload)) {
  // payload is of type DecodedNotificationDataPayload
}

if (isdecodedNotificationSummaryPayload(payload)) {
  // payload is of type DecodedNotificationSummaryPayload
}

Verifying transactions signed by Xcode

When using StoreKit testing in Xcode, transactions will be signed by a local certificate authority (CA) instead of Apple's. To verify these you must export the root certificate generated by Xcode and obtains its SHA256 fingerprint. This can be passed in to the various decoding functions:

import { decodeTransactions, APPLE_ROOT_CA_G3_FINGERPRINT } from "app-store-server-api"

const LOCAL_ROOT_FINGERPRINT = "AA:BB:CC:DD:..."
const fingerprint = (process.env.NODE_ENV === "production") ? APPLE_ROOT_CA_G3_FINGERPRINT : LOCAL_ROOT_FINGERPRINT
const transactions = await decodeTransactions(response.signedTransactions, fingerprint)

Resources

WWDC videos:

License

MIT

app-store-server-api's People

Contributors

agisboye avatar fariassdev avatar biancadanforth avatar levi avatar mishkhan avatar ralle avatar mitty-company avatar

Watchers

 avatar

Forkers

chadacious

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.