@onesub/server 0.11.4 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +119 -2
  2. package/dist/__tests__/cache.test.d.ts +2 -0
  3. package/dist/__tests__/cache.test.d.ts.map +1 -0
  4. package/dist/__tests__/openapi.test.d.ts +2 -0
  5. package/dist/__tests__/openapi.test.d.ts.map +1 -0
  6. package/dist/__tests__/redis-store.test.d.ts +2 -0
  7. package/dist/__tests__/redis-store.test.d.ts.map +1 -0
  8. package/dist/__tests__/webhook-apple.test.d.ts +12 -0
  9. package/dist/__tests__/webhook-apple.test.d.ts.map +1 -0
  10. package/dist/__tests__/webhook-events.test.d.ts +2 -0
  11. package/dist/__tests__/webhook-events.test.d.ts.map +1 -0
  12. package/dist/__tests__/webhook-google.test.d.ts +13 -0
  13. package/dist/__tests__/webhook-google.test.d.ts.map +1 -0
  14. package/dist/__tests__/webhook-queue.test.d.ts +2 -0
  15. package/dist/__tests__/webhook-queue.test.d.ts.map +1 -0
  16. package/dist/cache.d.ts +32 -0
  17. package/dist/cache.d.ts.map +1 -0
  18. package/dist/index.cjs +3084 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.ts +34 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +3045 -118
  23. package/dist/index.js.map +1 -1
  24. package/dist/openapi.d.ts +41 -0
  25. package/dist/openapi.d.ts.map +1 -0
  26. package/dist/providers/apple.d.ts +1 -1
  27. package/dist/providers/apple.d.ts.map +1 -1
  28. package/dist/providers/google.d.ts.map +1 -1
  29. package/dist/routes/admin.d.ts +2 -1
  30. package/dist/routes/admin.d.ts.map +1 -1
  31. package/dist/routes/webhook-apple.d.ts +6 -0
  32. package/dist/routes/webhook-apple.d.ts.map +1 -0
  33. package/dist/routes/webhook-google.d.ts +7 -0
  34. package/dist/routes/webhook-google.d.ts.map +1 -0
  35. package/dist/routes/webhook.d.ts +6 -18
  36. package/dist/routes/webhook.d.ts.map +1 -1
  37. package/dist/stores/redis.d.ts +60 -0
  38. package/dist/stores/redis.d.ts.map +1 -0
  39. package/dist/stores/schema.d.ts.map +1 -1
  40. package/dist/tracing.d.ts +32 -0
  41. package/dist/tracing.d.ts.map +1 -0
  42. package/dist/webhook-events.d.ts +58 -0
  43. package/dist/webhook-events.d.ts.map +1 -0
  44. package/dist/webhook-queue.d.ts +92 -0
  45. package/dist/webhook-queue.d.ts.map +1 -0
  46. package/package.json +33 -4
  47. package/sql/schema.sql +10 -0
  48. package/dist/__tests__/admin-customer-detail.test.js +0 -146
  49. package/dist/__tests__/admin-customer-detail.test.js.map +0 -1
  50. package/dist/__tests__/admin-list-subscriptions.test.js +0 -192
  51. package/dist/__tests__/admin-list-subscriptions.test.js.map +0 -1
  52. package/dist/__tests__/admin-subscription-detail.test.js +0 -112
  53. package/dist/__tests__/admin-subscription-detail.test.js.map +0 -1
  54. package/dist/__tests__/apple-root-ca.test.js +0 -41
  55. package/dist/__tests__/apple-root-ca.test.js.map +0 -1
  56. package/dist/__tests__/apple-status-api.test.js +0 -345
  57. package/dist/__tests__/apple-status-api.test.js.map +0 -1
  58. package/dist/__tests__/entitlements.test.js +0 -268
  59. package/dist/__tests__/entitlements.test.js.map +0 -1
  60. package/dist/__tests__/error-codes.test.js +0 -168
  61. package/dist/__tests__/error-codes.test.js.map +0 -1
  62. package/dist/__tests__/fetch-hardening.test.js +0 -192
  63. package/dist/__tests__/fetch-hardening.test.js.map +0 -1
  64. package/dist/__tests__/google-paused.test.js +0 -126
  65. package/dist/__tests__/google-paused.test.js.map +0 -1
  66. package/dist/__tests__/google-price-change.test.js +0 -186
  67. package/dist/__tests__/google-price-change.test.js.map +0 -1
  68. package/dist/__tests__/google-subscriptions-v2.test.js +0 -206
  69. package/dist/__tests__/google-subscriptions-v2.test.js.map +0 -1
  70. package/dist/__tests__/lifecycle-scenarios.test.js +0 -579
  71. package/dist/__tests__/lifecycle-scenarios.test.js.map +0 -1
  72. package/dist/__tests__/lifecycle-states.test.js +0 -423
  73. package/dist/__tests__/lifecycle-states.test.js.map +0 -1
  74. package/dist/__tests__/linked-purchase-token.test.js +0 -227
  75. package/dist/__tests__/linked-purchase-token.test.js.map +0 -1
  76. package/dist/__tests__/metrics.test.js +0 -340
  77. package/dist/__tests__/metrics.test.js.map +0 -1
  78. package/dist/__tests__/mock-provider.test.js +0 -188
  79. package/dist/__tests__/mock-provider.test.js.map +0 -1
  80. package/dist/__tests__/paused-auto-resume.test.js +0 -162
  81. package/dist/__tests__/paused-auto-resume.test.js.map +0 -1
  82. package/dist/__tests__/providers.test.js +0 -321
  83. package/dist/__tests__/providers.test.js.map +0 -1
  84. package/dist/__tests__/refund-policy.test.js +0 -317
  85. package/dist/__tests__/refund-policy.test.js.map +0 -1
  86. package/dist/__tests__/schema.test.js +0 -46
  87. package/dist/__tests__/schema.test.js.map +0 -1
  88. package/dist/__tests__/store.test.js +0 -172
  89. package/dist/__tests__/store.test.js.map +0 -1
  90. package/dist/__tests__/test-utils.js +0 -30
  91. package/dist/__tests__/test-utils.js.map +0 -1
  92. package/dist/__tests__/webhook-refund.test.js +0 -313
  93. package/dist/__tests__/webhook-refund.test.js.map +0 -1
  94. package/dist/errors.js +0 -19
  95. package/dist/errors.js.map +0 -1
  96. package/dist/http.js +0 -36
  97. package/dist/http.js.map +0 -1
  98. package/dist/logger.js +0 -20
  99. package/dist/logger.js.map +0 -1
  100. package/dist/providers/apple-root-ca.js +0 -38
  101. package/dist/providers/apple-root-ca.js.map +0 -1
  102. package/dist/providers/apple.js +0 -499
  103. package/dist/providers/apple.js.map +0 -1
  104. package/dist/providers/google.js +0 -493
  105. package/dist/providers/google.js.map +0 -1
  106. package/dist/providers/mock.js +0 -93
  107. package/dist/providers/mock.js.map +0 -1
  108. package/dist/routes/admin.js +0 -251
  109. package/dist/routes/admin.js.map +0 -1
  110. package/dist/routes/entitlements.js +0 -130
  111. package/dist/routes/entitlements.js.map +0 -1
  112. package/dist/routes/metrics.js +0 -281
  113. package/dist/routes/metrics.js.map +0 -1
  114. package/dist/routes/purchase.js +0 -187
  115. package/dist/routes/purchase.js.map +0 -1
  116. package/dist/routes/status.js +0 -55
  117. package/dist/routes/status.js.map +0 -1
  118. package/dist/routes/validate.js +0 -70
  119. package/dist/routes/validate.js.map +0 -1
  120. package/dist/routes/webhook.js +0 -441
  121. package/dist/routes/webhook.js.map +0 -1
  122. package/dist/store.js +0 -145
  123. package/dist/store.js.map +0 -1
  124. package/dist/stores/postgres.js +0 -329
  125. package/dist/stores/postgres.js.map +0 -1
  126. package/dist/stores/schema.js +0 -57
  127. package/dist/stores/schema.js.map +0 -1
package/dist/errors.js DELETED
@@ -1,19 +0,0 @@
1
- import { ONESUB_ERROR_CODE } from '@onesub/shared';
2
- /**
3
- * Send a structured error response. Every onesub HTTP endpoint uses this
4
- * so consumers can rely on `errorCode` being present on every 4xx/5xx body.
5
- *
6
- * `extra` lets callers inject route-specific defaults (e.g. `purchase: null`
7
- * for ValidatePurchaseResponse shape compatibility).
8
- */
9
- export function sendError(res, status, code, error, extra = {}) {
10
- res.status(status).json({ ...extra, error, errorCode: code });
11
- }
12
- /**
13
- * 400 response for a failed zod parse. The ZodError's per-issue messages
14
- * are joined for the human-readable `error` field.
15
- */
16
- export function sendZodError(res, err, extra = {}) {
17
- sendError(res, 400, ONESUB_ERROR_CODE.INVALID_INPUT, err.issues.map((e) => e.message).join(', '), extra);
18
- }
19
- //# sourceMappingURL=errors.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CACvB,GAAa,EACb,MAAc,EACd,IAAqB,EACrB,KAAa,EACb,QAAiC,EAAE;IAEnC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAa,EACb,GAAe,EACf,QAAiC,EAAE;IAEnC,SAAS,CACP,GAAG,EACH,GAAG,EACH,iBAAiB,CAAC,aAAa,EAC/B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAsB,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAChE,KAAK,CACN,CAAC;AACJ,CAAC"}
package/dist/http.js DELETED
@@ -1,36 +0,0 @@
1
- /**
2
- * Outbound HTTP helpers shared by Apple/Google providers.
3
- *
4
- * Why timeouts: Node's global fetch has no default timeout. If the upstream
5
- * (Apple App Store Server API, Google Play Developer API, Google OAuth) hangs,
6
- * webhook handlers and validate routes hang with it — Apple/Google retry on
7
- * their side, so a hung outbound call cascades into request pile-up here.
8
- */
9
- /** Default timeout for outbound API calls (10s). */
10
- export const DEFAULT_FETCH_TIMEOUT_MS = 10_000;
11
- /**
12
- * fetch with an `AbortController`-based timeout. Throws an `AbortError`-like
13
- * Error when the timer fires. Caller is expected to catch and decide
14
- * (return null, log, propagate as 5xx, etc.).
15
- */
16
- export async function fetchWithTimeout(input, init, timeoutMs = DEFAULT_FETCH_TIMEOUT_MS) {
17
- const controller = new AbortController();
18
- // Allow caller-provided signal to compose with our timeout.
19
- const callerSignal = init?.signal;
20
- if (callerSignal) {
21
- if (callerSignal.aborted)
22
- controller.abort(callerSignal.reason);
23
- else
24
- callerSignal.addEventListener('abort', () => controller.abort(callerSignal.reason), { once: true });
25
- }
26
- const timer = setTimeout(() => {
27
- controller.abort(new Error(`[onesub] fetch timed out after ${timeoutMs}ms`));
28
- }, timeoutMs);
29
- try {
30
- return await fetch(input, { ...init, signal: controller.signal });
31
- }
32
- finally {
33
- clearTimeout(timer);
34
- }
35
- }
36
- //# sourceMappingURL=http.js.map
package/dist/http.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,oDAAoD;AACpD,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAE/C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAwB,EACxB,IAAkB,EAClB,SAAS,GAAG,wBAAwB;IAEpC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,4DAA4D;IAC5D,MAAM,YAAY,GAAG,IAAI,EAAE,MAAM,CAAC;IAClC,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,YAAY,CAAC,OAAO;YAAE,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;;YAC3D,YAAY,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3G,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QAC5B,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,kCAAkC,SAAS,IAAI,CAAC,CAAC,CAAC;IAC/E,CAAC,EAAE,SAAS,CAAC,CAAC;IAEd,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
package/dist/logger.js DELETED
@@ -1,20 +0,0 @@
1
- /**
2
- * Process-wide logger used by @onesub/server's providers and routes.
3
- *
4
- * Defaults to `console`. `createOneSubMiddleware()` calls `setLogger()` once
5
- * during setup if `config.logger` is provided. All internal call sites should
6
- * import `log` from this module instead of calling `console.*` directly so
7
- * operators can redirect logs (pino / winston / bunyan) with a single config
8
- * setting.
9
- */
10
- let current = console;
11
- export function setLogger(logger) {
12
- if (logger)
13
- current = logger;
14
- }
15
- export const log = {
16
- info: (...args) => current.info(...args),
17
- warn: (...args) => current.warn(...args),
18
- error: (...args) => current.error(...args),
19
- };
20
- //# sourceMappingURL=logger.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,IAAI,OAAO,GAAiB,OAAO,CAAC;AAEpC,MAAM,UAAU,SAAS,CAAC,MAAgC;IACxD,IAAI,MAAM;QAAE,OAAO,GAAG,MAAM,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAiB;IAC/B,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;CAC3C,CAAC"}
@@ -1,38 +0,0 @@
1
- /**
2
- * Apple Root CA certificates used to verify StoreKit 2 signed transactions.
3
- *
4
- * Apple signs JWS transactions with an ECDSA key; the signing certificate
5
- * chain is embedded in the JWS `x5c` header. To trust the leaf key we must
6
- * validate the chain all the way up to one of Apple's published root CAs.
7
- *
8
- * Source: https://www.apple.com/certificateauthority/
9
- * These certificates are public and static. Update this list if Apple
10
- * publishes a new root — existing JWS signed with older roots continue to
11
- * validate against their original root.
12
- */
13
- /**
14
- * Apple Root CA - G3 (current root for StoreKit 2 / App Store Server API).
15
- * SHA-256 fingerprint: 63343ABF B89A6A03 EB994052 C5ADBBF8 A87E2C46 81F6F0FC C8A4DA48 95F0FBBF
16
- * Valid: 2014-04-30 — 2039-04-30
17
- */
18
- export const APPLE_ROOT_CA_G3_PEM = `-----BEGIN CERTIFICATE-----
19
- MIICQzCCAcmgAwIBAgIILcX8iNLFS5UwCgYIKoZIzj0EAwMwZzEbMBkGA1UEAwwS
20
- QXBwbGUgUm9vdCBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9u
21
- IEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwHhcN
22
- MTQwNDMwMTgxOTA2WhcNMzkwNDMwMTgxOTA2WjBnMRswGQYDVQQDDBJBcHBsZSBS
23
- b290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9y
24
- aXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzB2MBAGByqGSM49
25
- AgEGBSuBBAAiA2IABJjpLz1AcqTtkyJygRMc3RCV8cWjTnHcFBbZDuWmBSp3ZHtf
26
- TjjTuxxEtX/1H7YyYl3J6YRbTzBPEVoA/VhYDKX1DyxNB0cTddqXl5dvMVztK517
27
- IDvYuVTZXpmkOlEKMaNCMEAwHQYDVR0OBBYEFLuw3qFYM4iapIqZ3r6966/ayySr
28
- MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gA
29
- MGUCMQCD6cHEFl4aXTQY2e3v9GwOAEZLuN+yRhHFD/3meoyhpmvOwgPUnPWTxnS4
30
- at+qIxUCMG1mihDK1A3UT82NQz60imOlM27jbdoXt2QfyFMm+YhidDkLF1vLUagM
31
- 6BgD56KyKA==
32
- -----END CERTIFICATE-----`;
33
- /**
34
- * All Apple root CAs accepted for StoreKit 2 JWS validation.
35
- * Currently only G3; add G4 here when Apple publishes it.
36
- */
37
- export const APPLE_ROOT_CA_PEMS = [APPLE_ROOT_CA_G3_PEM];
38
- //# sourceMappingURL=apple-root-ca.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apple-root-ca.js","sourceRoot":"","sources":["../../src/providers/apple-root-ca.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;0BAcV,CAAC;AAE3B;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,oBAAoB,CAAC,CAAC"}
@@ -1,499 +0,0 @@
1
- import { decodeJwt, decodeProtectedHeader, importPKCS8, importX509, jwtVerify, SignJWT } from 'jose';
2
- import { X509Certificate } from 'node:crypto';
3
- import { SUBSCRIPTION_STATUS } from '@onesub/shared';
4
- import { APPLE_ROOT_CA_PEMS } from './apple-root-ca.js';
5
- import { log } from '../logger.js';
6
- import { fetchWithTimeout } from '../http.js';
7
- import { mockValidateAppleSubscription, mockValidateAppleProduct, } from './mock.js';
8
- /** Maximum age for consumable receipts (72 hours). Older receipts may indicate replay attacks. */
9
- const MAX_CONSUMABLE_RECEIPT_AGE_MS = 72 * 60 * 60 * 1000;
10
- function derBase64ToPem(der) {
11
- return ('-----BEGIN CERTIFICATE-----\n' +
12
- (der.match(/.{1,64}/g) ?? []).join('\n') +
13
- '\n-----END CERTIFICATE-----');
14
- }
15
- const APPLE_ROOT_CERTS = APPLE_ROOT_CA_PEMS.map((pem) => new X509Certificate(pem));
16
- /**
17
- * Validate that the x5c chain from the JWS terminates at one of Apple's
18
- * bundled root CAs. Each cert in the chain must be signed by the next (or
19
- * the bundled root), and all certs must currently be within their validity
20
- * window.
21
- *
22
- * Returns the leaf certificate PEM on success. Throws on any failure.
23
- */
24
- function verifyAppleCertChain(x5c) {
25
- if (x5c.length === 0) {
26
- throw new Error('[onesub/apple] empty x5c');
27
- }
28
- const chain = x5c.map((der) => new X509Certificate(derBase64ToPem(der)));
29
- const now = new Date();
30
- // Validity window + leaf→intermediate→... signature chain
31
- for (let i = 0; i < chain.length; i++) {
32
- const cert = chain[i];
33
- if (new Date(cert.validFrom) > now || new Date(cert.validTo) < now) {
34
- throw new Error(`[onesub/apple] cert[${i}] outside validity window`);
35
- }
36
- if (i + 1 < chain.length) {
37
- if (!cert.checkIssued(chain[i + 1]) || !cert.verify(chain[i + 1].publicKey)) {
38
- throw new Error(`[onesub/apple] cert[${i}] not signed by cert[${i + 1}]`);
39
- }
40
- }
41
- }
42
- // Final cert in chain (typically intermediate) must be signed by an Apple root.
43
- // Accept either (a) explicit signature match or (b) the cert itself being one
44
- // of our bundled Apple roots (happens when Apple embeds the full chain).
45
- const top = chain[chain.length - 1];
46
- const topDer = top.raw.toString('base64');
47
- const trustsRoot = APPLE_ROOT_CERTS.some((root) => {
48
- if (root.raw.toString('base64') === topDer)
49
- return true;
50
- if (!top.checkIssued(root))
51
- return false;
52
- try {
53
- return top.verify(root.publicKey);
54
- }
55
- catch {
56
- return false;
57
- }
58
- });
59
- if (!trustsRoot) {
60
- throw new Error('[onesub/apple] cert chain does not terminate at a trusted Apple root');
61
- }
62
- return chain[0].toString();
63
- }
64
- /**
65
- * Decode and verify a StoreKit 2 signed transaction JWS.
66
- *
67
- * 1. Extract the x5c certificate chain from the JWS header.
68
- * 2. Validate the chain terminates at a bundled Apple Root CA (G3).
69
- * 3. Use the leaf certificate's public key to verify the JWS signature.
70
- *
71
- * skipVerification=true skips all of the above and just decodes the payload
72
- * (dev/test only).
73
- */
74
- export async function decodeJws(jws, skipVerification = false) {
75
- if (skipVerification) {
76
- if (process.env['NODE_ENV'] === 'production') {
77
- log.warn('[onesub/apple] WARNING: skipJwsVerification is enabled in production. ' +
78
- 'JWS signatures are NOT being verified. This is a security risk.');
79
- }
80
- return decodeJwt(jws);
81
- }
82
- const header = decodeProtectedHeader(jws);
83
- const x5c = header.x5c;
84
- if (!x5c || x5c.length === 0) {
85
- throw new Error('[onesub/apple] JWS header missing x5c certificate chain');
86
- }
87
- const leafPem = verifyAppleCertChain(x5c);
88
- const alg = header.alg ?? 'ES256';
89
- const key = await importX509(leafPem, alg);
90
- const { payload } = await jwtVerify(jws, key);
91
- return payload;
92
- }
93
- /**
94
- * Derive a SubscriptionStatus from the transaction + renewal payloads.
95
- */
96
- function deriveStatus(tx, renewal) {
97
- if (tx.revocationDate)
98
- return SUBSCRIPTION_STATUS.CANCELED;
99
- const now = Date.now();
100
- const expires = tx.expiresDate ?? 0;
101
- if (expires > now)
102
- return SUBSCRIPTION_STATUS.ACTIVE;
103
- // Expired — check if it was voluntarily canceled
104
- if (renewal?.autoRenewStatus === 0)
105
- return SUBSCRIPTION_STATUS.CANCELED;
106
- return SUBSCRIPTION_STATUS.EXPIRED;
107
- }
108
- /**
109
- * Validate an Apple receipt string.
110
- *
111
- * StoreKit 2 receipts are JWS-encoded signed transactions (the `signedTransaction`
112
- * field from the client). For legacy base64 receipts from StoreKit 1, you would
113
- * POST to verifyReceipt — that path is left as a stub here because Apple is
114
- * deprecating it.
115
- */
116
- export async function validateAppleReceipt(receipt, config) {
117
- if (config.mockMode)
118
- return mockValidateAppleSubscription(receipt);
119
- let tx;
120
- try {
121
- tx = await decodeJws(receipt, config.skipJwsVerification);
122
- }
123
- catch (err) {
124
- const preview = receipt.slice(0, 60);
125
- const parts = receipt.split('.').length;
126
- log.warn('[onesub/apple] Failed to decode receipt as JWS:', err?.message ?? err, `| preview: "${preview}..." (len=${receipt.length}, parts=${parts})`);
127
- return null;
128
- }
129
- if (!tx.originalTransactionId || !tx.productId || !tx.expiresDate) {
130
- return null;
131
- }
132
- // Validate bundle ID — missing or mismatched both rejected
133
- if (!tx.bundleId || tx.bundleId !== config.bundleId) {
134
- log.warn('[onesub/apple] Bundle ID mismatch:', tx.bundleId, '!==', config.bundleId);
135
- return null;
136
- }
137
- // Reject Sandbox receipts in production unless explicitly allowed.
138
- // Set ONESUB_ALLOW_SANDBOX=true to permit TestFlight sandbox receipts on
139
- // production servers (useful during QA before App Store release).
140
- if (process.env['NODE_ENV'] === 'production' &&
141
- tx.environment !== 'Production' &&
142
- process.env['ONESUB_ALLOW_SANDBOX'] !== 'true') {
143
- log.warn('[onesub/apple] Sandbox receipt rejected in production:', tx.environment);
144
- return null;
145
- }
146
- const status = deriveStatus(tx, null);
147
- const purchasedAt = tx.originalPurchaseDate ?? tx.purchaseDate ?? Date.now();
148
- return {
149
- userId: '', // caller fills this in from the request body
150
- productId: tx.productId,
151
- platform: 'apple',
152
- status,
153
- expiresAt: new Date(tx.expiresDate).toISOString(),
154
- originalTransactionId: tx.originalTransactionId,
155
- purchasedAt: new Date(purchasedAt).toISOString(),
156
- willRenew: status === SUBSCRIPTION_STATUS.ACTIVE, // refined by renewal info in webhook
157
- };
158
- }
159
- /**
160
- * Validate an Apple StoreKit 2 JWS signedTransaction for a consumable or
161
- * non-consumable product.
162
- *
163
- * Differences from validateAppleReceipt (subscriptions):
164
- * - Checks tx.type is 'Consumable' or 'Non-Consumable' (not a subscription)
165
- * - Uses tx.transactionId (per-purchase unique) instead of originalTransactionId
166
- * - Enforces a 72-hour receipt age limit to block replay attacks
167
- * - Does NOT check expiresDate (one-time purchases don't expire)
168
- */
169
- export async function validateAppleConsumableReceipt(signedTransaction, config, expectedProductId) {
170
- if (config.mockMode)
171
- return mockValidateAppleProduct(signedTransaction, expectedProductId);
172
- let tx;
173
- try {
174
- tx = await decodeJws(signedTransaction, config.skipJwsVerification);
175
- }
176
- catch (err) {
177
- const preview = signedTransaction.slice(0, 60);
178
- const parts = signedTransaction.split('.').length;
179
- const looksLikeJws = parts === 3;
180
- log.warn('[onesub/apple] Failed to decode consumable JWS:', err?.message ?? err, `| receipt preview: "${preview}..." (len=${signedTransaction.length}, parts=${parts}, looksLikeJws=${looksLikeJws})`);
181
- return null;
182
- }
183
- // bundleId must be present and match
184
- if (!tx.bundleId || tx.bundleId !== config.bundleId) {
185
- log.warn('[onesub/apple] Bundle ID mismatch:', tx.bundleId, '!==', config.bundleId);
186
- return null;
187
- }
188
- // Must be a one-time purchase type (not a subscription)
189
- if (tx.type !== 'Consumable' && tx.type !== 'Non-Consumable') {
190
- log.warn('[onesub/apple] Invalid purchase type for product validation:', tx.type);
191
- return null;
192
- }
193
- // Reject Sandbox receipts in production unless explicitly allowed.
194
- // Set ONESUB_ALLOW_SANDBOX=true to permit TestFlight sandbox receipts on
195
- // production servers (useful during QA before App Store release).
196
- if (process.env['NODE_ENV'] === 'production' &&
197
- tx.environment !== 'Production' &&
198
- process.env['ONESUB_ALLOW_SANDBOX'] !== 'true') {
199
- log.warn('[onesub/apple] Sandbox receipt rejected in production:', tx.environment);
200
- return null;
201
- }
202
- if (!tx.productId) {
203
- log.warn('[onesub/apple] No productId in transaction');
204
- return null;
205
- }
206
- if (expectedProductId && tx.productId !== expectedProductId) {
207
- log.warn('[onesub/apple] Product ID mismatch:', tx.productId, '!==', expectedProductId);
208
- return null;
209
- }
210
- // Reject refunded purchases
211
- if (tx.revocationDate) {
212
- log.warn('[onesub/apple] Purchase was revoked/refunded');
213
- return null;
214
- }
215
- // Reject receipts older than 72 hours (replay attack prevention)
216
- if (tx.purchaseDate && Date.now() - tx.purchaseDate > MAX_CONSUMABLE_RECEIPT_AGE_MS) {
217
- log.warn('[onesub/apple] Consumable receipt too old (>72h)');
218
- return null;
219
- }
220
- // For consumables, transactionId is per-purchase unique.
221
- // originalTransactionId is shared across re-purchases, so it must not be used
222
- // as the deduplication key for consumables.
223
- const transactionId = tx.transactionId ?? tx.originalTransactionId;
224
- if (!transactionId) {
225
- log.warn('[onesub/apple] No transactionId in consumable transaction');
226
- return null;
227
- }
228
- return {
229
- transactionId,
230
- productId: tx.productId,
231
- purchasedAt: tx.purchaseDate
232
- ? new Date(tx.purchaseDate).toISOString()
233
- : new Date().toISOString(),
234
- };
235
- }
236
- /**
237
- * Decode an Apple Server Notification V2 payload.
238
- * Returns the derived subscription update to be merged into the store.
239
- */
240
- export async function decodeAppleNotification(payload, skipJwsVerification = false) {
241
- const { signedTransactionInfo, signedRenewalInfo } = payload.data;
242
- let tx;
243
- let renewal = null;
244
- try {
245
- tx = await decodeJws(signedTransactionInfo, skipJwsVerification);
246
- }
247
- catch {
248
- return null;
249
- }
250
- try {
251
- renewal = await decodeJws(signedRenewalInfo, skipJwsVerification);
252
- }
253
- catch {
254
- // renewal info is optional for some notification types
255
- }
256
- // expiresDate is only required for subscription notifications.
257
- // Consumable / non-consumable refund notifications (REFUND for IAP) have no expiry.
258
- if (!tx.originalTransactionId)
259
- return null;
260
- const status = deriveStatus(tx, renewal);
261
- const willRenew = renewal?.autoRenewStatus === 1;
262
- // environment is on the notification data envelope but Apple also includes
263
- // it inside the signed transaction payload. Prefer the JWS-protected one.
264
- const txEnv = tx.environment;
265
- const dataEnv = payload.data.environment;
266
- const environment = txEnv === 'Sandbox' || dataEnv === 'Sandbox' ? 'Sandbox' : 'Production';
267
- return {
268
- originalTransactionId: tx.originalTransactionId,
269
- transactionId: tx.transactionId ?? null,
270
- type: tx.type ?? null,
271
- productId: tx.productId ?? null,
272
- bundleId: tx.bundleId ?? payload.data.bundleId ?? null,
273
- environment,
274
- status,
275
- willRenew,
276
- expiresAt: tx.expiresDate ? new Date(tx.expiresDate).toISOString() : null,
277
- };
278
- }
279
- // ───────────────────────────────────────────────────────────────────────────
280
- // App Store Server API — outbound calls (consumption response, etc.)
281
- // ───────────────────────────────────────────────────────────────────────────
282
- /**
283
- * Module-level JWT cache for the App Store Server API. Apple caps token TTL
284
- * at 20 minutes; we mint with that TTL and re-use until 60 seconds before
285
- * expiry (so long-running webhook bursts don't pay the ECDSA-sign cost on
286
- * every request). Promise dedup prevents thundering-herd JWT mints when many
287
- * concurrent callers race the cache miss.
288
- *
289
- * Keyed by `${issuerId}|${keyId}` since rotating either invalidates the JWT.
290
- */
291
- let cachedAppleJwt = null;
292
- let appleJwtMintPromise = null;
293
- const APPLE_JWT_TTL_MS = 20 * 60 * 1000;
294
- const APPLE_JWT_REFRESH_BEFORE_MS = 60 * 1000;
295
- /**
296
- * Mint a JWT for the App Store Server API (audience `appstoreconnect-v1`).
297
- * Requires keyId, issuerId, and privateKey (PKCS8 ES256 from App Store Connect).
298
- * Token TTL is capped at 20 minutes per Apple's spec.
299
- */
300
- async function makeAppleApiJwt(config) {
301
- const { issuerId, keyId, privateKey, bundleId } = config;
302
- if (!issuerId || !keyId || !privateKey) {
303
- throw new Error('[onesub/apple] App Store Server API requires issuerId, keyId, and privateKey');
304
- }
305
- const cacheKey = `${issuerId}|${keyId}`;
306
- const now = Date.now();
307
- if (cachedAppleJwt &&
308
- cachedAppleJwt.key === cacheKey &&
309
- cachedAppleJwt.expiresAt - now > APPLE_JWT_REFRESH_BEFORE_MS) {
310
- return cachedAppleJwt.token;
311
- }
312
- if (!appleJwtMintPromise) {
313
- appleJwtMintPromise = (async () => {
314
- const key = await importPKCS8(privateKey, 'ES256');
315
- const issuedAt = Math.floor(Date.now() / 1000);
316
- const token = await new SignJWT({ bid: bundleId })
317
- .setProtectedHeader({ alg: 'ES256', kid: keyId, typ: 'JWT' })
318
- .setIssuer(issuerId)
319
- .setAudience('appstoreconnect-v1')
320
- .setIssuedAt(issuedAt)
321
- .setExpirationTime(issuedAt + Math.floor(APPLE_JWT_TTL_MS / 1000))
322
- .sign(key);
323
- cachedAppleJwt = { token, expiresAt: Date.now() + APPLE_JWT_TTL_MS, key: cacheKey };
324
- return token;
325
- })().finally(() => {
326
- appleJwtMintPromise = null;
327
- });
328
- }
329
- return appleJwtMintPromise;
330
- }
331
- /** Test-only: clear the module-level Apple JWT cache. Not exported. */
332
- function clearAppleJwtCacheForTests() {
333
- cachedAppleJwt = null;
334
- appleJwtMintPromise = null;
335
- }
336
- // Expose for the test suite without polluting the public API surface.
337
- export const __testing = { clearAppleJwtCacheForTests };
338
- /**
339
- * PUT a ConsumptionRequest to Apple's
340
- * /inApps/v1/transactions/consumption/{transactionId} endpoint.
341
- *
342
- * Apple sends CONSUMPTION_REQUEST notifications when a customer asks for a
343
- * refund on a consumable. Without a response Apple has no usage signal and
344
- * tends to grant the refund. This call provides the data Apple uses to weigh
345
- * the refund decision.
346
- *
347
- * Fire-and-forget: failures are logged, never thrown — the webhook should
348
- * still 200 to Apple even if our outbound call fails.
349
- */
350
- export async function sendAppleConsumptionResponse(transactionId, body, config, options) {
351
- if (config.mockMode)
352
- return;
353
- let jwt;
354
- try {
355
- jwt = await makeAppleApiJwt(config);
356
- }
357
- catch (err) {
358
- log.warn('[onesub/apple] Cannot send consumption response — JWT mint failed:', err);
359
- return;
360
- }
361
- const host = options?.sandbox
362
- ? 'api.storekit-sandbox.itunes.apple.com'
363
- : 'api.storekit.itunes.apple.com';
364
- const url = `https://${host}/inApps/v1/transactions/consumption/${encodeURIComponent(transactionId)}`;
365
- try {
366
- const resp = await fetchWithTimeout(url, {
367
- method: 'PUT',
368
- headers: {
369
- Authorization: `Bearer ${jwt}`,
370
- 'Content-Type': 'application/json',
371
- },
372
- body: JSON.stringify(body),
373
- });
374
- if (!resp.ok) {
375
- const text = await resp.text();
376
- log.warn(`[onesub/apple] Consumption response API error ${resp.status}: ${text}`);
377
- }
378
- }
379
- catch (err) {
380
- log.warn('[onesub/apple] Consumption response network error:', err);
381
- }
382
- }
383
- /**
384
- * Apple's status code in the GET /inApps/v1/subscriptions/{originalTxId} response.
385
- * https://developer.apple.com/documentation/appstoreserverapi/status
386
- */
387
- const APPLE_SUBSCRIPTION_STATUS_CODE = {
388
- ACTIVE: 1,
389
- EXPIRED: 2,
390
- BILLING_RETRY: 3,
391
- GRACE_PERIOD: 4,
392
- REVOKED: 5,
393
- };
394
- function mapAppleStatusCode(code) {
395
- switch (code) {
396
- case APPLE_SUBSCRIPTION_STATUS_CODE.ACTIVE:
397
- return SUBSCRIPTION_STATUS.ACTIVE;
398
- case APPLE_SUBSCRIPTION_STATUS_CODE.GRACE_PERIOD:
399
- return SUBSCRIPTION_STATUS.GRACE_PERIOD;
400
- case APPLE_SUBSCRIPTION_STATUS_CODE.BILLING_RETRY:
401
- return SUBSCRIPTION_STATUS.ON_HOLD;
402
- case APPLE_SUBSCRIPTION_STATUS_CODE.REVOKED:
403
- return SUBSCRIPTION_STATUS.CANCELED;
404
- case APPLE_SUBSCRIPTION_STATUS_CODE.EXPIRED:
405
- default:
406
- return SUBSCRIPTION_STATUS.EXPIRED;
407
- }
408
- }
409
- /**
410
- * Fetch the current state of a subscription directly from Apple's App Store
411
- * Server API — the canonical source of truth when webhooks have been missed,
412
- * delivered out of order, or the local store has no record at all.
413
- *
414
- * GET /inApps/v1/subscriptions/{originalTransactionId}
415
- * https://developer.apple.com/documentation/appstoreserverapi/get_all_subscription_statuses
416
- *
417
- * Returns null on:
418
- * - Missing API credentials (issuerId/keyId/privateKey)
419
- * - Network or auth failure
420
- * - Empty response (transaction not found)
421
- *
422
- * Hosts can call this directly (e.g. from a reconciliation cron) or it runs
423
- * automatically as the unknown-transaction fallback inside the Apple webhook.
424
- */
425
- export async function fetchAppleSubscriptionStatus(originalTransactionId, config, options) {
426
- if (config.mockMode)
427
- return null;
428
- let jwt;
429
- try {
430
- jwt = await makeAppleApiJwt(config);
431
- }
432
- catch (err) {
433
- log.warn('[onesub/apple] Cannot fetch subscription status — JWT mint failed:', err);
434
- return null;
435
- }
436
- const host = options?.sandbox
437
- ? 'api.storekit-sandbox.itunes.apple.com'
438
- : 'api.storekit.itunes.apple.com';
439
- const url = `https://${host}/inApps/v1/subscriptions/${encodeURIComponent(originalTransactionId)}`;
440
- let body;
441
- try {
442
- const resp = await fetchWithTimeout(url, {
443
- headers: { Authorization: `Bearer ${jwt}` },
444
- });
445
- if (!resp.ok) {
446
- const text = await resp.text();
447
- log.warn(`[onesub/apple] Status API error ${resp.status}: ${text}`);
448
- return null;
449
- }
450
- body = (await resp.json());
451
- }
452
- catch (err) {
453
- log.warn('[onesub/apple] Status API network error:', err);
454
- return null;
455
- }
456
- // Find the lastTransactions entry matching the requested originalTransactionId.
457
- // Apple groups by subscriptionGroupIdentifier; one originalTxId is in exactly one group.
458
- const entry = body.data
459
- ?.flatMap((g) => g.lastTransactions ?? [])
460
- .find((t) => t.originalTransactionId === originalTransactionId);
461
- if (!entry || entry.status == null || !entry.signedTransactionInfo) {
462
- log.warn('[onesub/apple] Status API returned no matching transaction for', originalTransactionId);
463
- return null;
464
- }
465
- let tx;
466
- try {
467
- tx = await decodeJws(entry.signedTransactionInfo, config.skipJwsVerification);
468
- }
469
- catch (err) {
470
- log.warn('[onesub/apple] Failed to decode signedTransactionInfo from Status API:', err);
471
- return null;
472
- }
473
- let renewal = null;
474
- if (entry.signedRenewalInfo) {
475
- try {
476
- renewal = await decodeJws(entry.signedRenewalInfo, config.skipJwsVerification);
477
- }
478
- catch {
479
- // renewal info is optional
480
- }
481
- }
482
- if (!tx.productId || !tx.expiresDate) {
483
- log.warn('[onesub/apple] Status API transaction missing productId or expiresDate');
484
- return null;
485
- }
486
- const status = mapAppleStatusCode(entry.status);
487
- const purchasedAt = tx.originalPurchaseDate ?? tx.purchaseDate ?? Date.now();
488
- return {
489
- userId: '', // caller fills this in
490
- productId: tx.productId,
491
- platform: 'apple',
492
- status,
493
- expiresAt: new Date(tx.expiresDate).toISOString(),
494
- originalTransactionId,
495
- purchasedAt: new Date(purchasedAt).toISOString(),
496
- willRenew: renewal?.autoRenewStatus === 1,
497
- };
498
- }
499
- //# sourceMappingURL=apple.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apple.js","sourceRoot":"","sources":["../../src/providers/apple.ts"],"names":[],"mappings":"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"}