Fork of @apple/app-store-server-library-node (v3.0.0), rewritten to run natively on Cloudflare Workers and any WebCrypto-compatible runtime.
Covers the App Store Server API, App Store Server Notifications V2, and Retention Messaging API.
| Upstream (Node.js) | This fork (Workers) |
|---|---|
jsonwebtoken |
jose |
jsrsasign (X509, ASN1HEX, OCSP) |
@peculiar/x509 + manual DER parser |
crypto (X509Certificate, KeyObject, createHash, verify) |
@peculiar/x509 + crypto.subtle |
node-fetch |
native fetch |
Buffer |
Uint8Array / atob / btoa |
base64url |
manual base64url |
OCSP revocation checking is fully implemented using manual DER encoding/decoding and crypto.subtle for signature verification — no Node.js crypto dependencies.
jose ^5.9.0
@peculiar/x509 ^1.12.0
Zero Node.js-specific dependencies. Both packages work on Workers, Deno, Bun, and browsers.
# npm
npm install @studium-ignotum/app-store-server-library
# yarn
yarn add @studium-ignotum/app-store-server-library
# pnpm
pnpm add @studium-ignotum/app-store-server-libraryOr install directly from GitHub:
# npm
npm install github:studium-ignotum/app-store-server-library-node
# yarn
yarn add studium-ignotum/app-store-server-library-node
# pnpm
pnpm add github:studium-ignotum/app-store-server-library-nodeRequires a runtime with Web Crypto API (crypto.subtle) and native fetch.
import { AppStoreServerAPIClient, Environment } from "@studium-ignotum/app-store-server-library"
const client = new AppStoreServerAPIClient(
encodedKey, keyId, issuerId, bundleId, Environment.SANDBOX
)
const response = await client.requestTestNotification()import { SignedDataVerifier, Environment } from "@studium-ignotum/app-store-server-library"
const rootCAs: Uint8Array[] = [appleRootG3DER] // DER-encoded Apple root certificates
const verifier = new SignedDataVerifier(rootCAs, true, Environment.PRODUCTION, bundleId, appAppleId)
const notification = await verifier.verifyAndDecodeNotification(signedPayload)Constructor accepts
Uint8Array[](notBuffer[]).Bufferstill works at runtime since it extendsUint8Array.
import { ReceiptUtility } from "@studium-ignotum/app-store-server-library"
const receiptUtil = new ReceiptUtility()
const transactionId = receiptUtil.extractTransactionIdFromAppReceipt(appReceipt)import { PromotionalOfferSignatureCreator } from "@studium-ignotum/app-store-server-library"
const creator = new PromotionalOfferSignatureCreator(encodedKey, keyId, bundleId)
const signature = await creator.createSignature(productId, offerId, appAccountToken, nonce, timestamp)
createSignatureis now async (returnsPromise<string>).
import { AppStoreServerAPIClient, SignedDataVerifier, Environment } from "@studium-ignotum/app-store-server-library"
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const verifier = new SignedDataVerifier(
[base64ToUint8Array(env.APPLE_ROOT_CA_G3)],
true,
Environment.PRODUCTION,
env.BUNDLE_ID,
Number(env.APP_APPLE_ID)
)
const { signedPayload } = await request.json<{ signedPayload: string }>()
const notification = await verifier.verifyAndDecodeNotification(signedPayload)
return Response.json({ type: notification.notificationType })
}
}| Method / Constructor | Change |
|---|---|
new SignedDataVerifier(certs, ...) |
certs type: Buffer[] → Uint8Array[] |
verifyCertificateChain(...) |
Returns Promise<CryptoKey> instead of Promise<KeyObject> |
PromotionalOfferSignatureCreator.createSignature(...) |
Now async — returns Promise<string> |
PromotionalOfferV2SignatureCreator.createSignature(...) |
Now async — returns Promise<string> |
IntroductoryOfferEligibilitySignatureCreator.createSignature(...) |
Now async — returns Promise<string> |
AdvancedCommerceInAppSignatureCreator.createSignature(...) |
Now async — returns Promise<string> |
AppStoreServerAPIClient.uploadImage(id, image) |
image type: Buffer → Uint8Array |
All other public APIs remain unchanged.
Download the root certificates from the Apple PKI site (Apple Root Certificates section). Store them as DER-encoded Uint8Array values and pass to SignedDataVerifier.
MIT — see LICENSE.txt. Original library by Apple Inc.