@onesub/server 0.14.0 → 0.16.0
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.
- package/dist/__tests__/google-subscriptions-v2.test.d.ts +1 -1
- package/dist/__tests__/receipt-age.test.d.ts +7 -0
- package/dist/__tests__/receipt-age.test.d.ts.map +1 -0
- package/dist/__tests__/tracing.test.d.ts +2 -0
- package/dist/__tests__/tracing.test.d.ts.map +1 -0
- package/dist/cache.d.ts +5 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/index.cjs +178 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +178 -55
- package/dist/index.js.map +1 -1
- package/dist/providers/apple.d.ts.map +1 -1
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/mock.d.ts.map +1 -1
- package/dist/routes/admin.d.ts.map +1 -1
- package/dist/routes/purchase.d.ts.map +1 -1
- package/dist/routes/validate.d.ts.map +1 -1
- package/dist/routes/webhook-apple.d.ts.map +1 -1
- package/dist/routes/webhook-google.d.ts +1 -1
- package/dist/routes/webhook-google.d.ts.map +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/stores/postgres.d.ts.map +1 -1
- package/dist/stores/redis.d.ts +1 -0
- package/dist/stores/redis.d.ts.map +1 -1
- package/dist/tracing.d.ts.map +1 -1
- package/dist/webhook-events.d.ts +10 -0
- package/dist/webhook-events.d.ts.map +1 -1
- package/package.json +5 -3
- package/dist/__tests__/admin-customer-detail.test.js +0 -146
- package/dist/__tests__/admin-customer-detail.test.js.map +0 -1
- package/dist/__tests__/admin-list-subscriptions.test.js +0 -192
- package/dist/__tests__/admin-list-subscriptions.test.js.map +0 -1
- package/dist/__tests__/admin-subscription-detail.test.js +0 -112
- package/dist/__tests__/admin-subscription-detail.test.js.map +0 -1
- package/dist/__tests__/apple-root-ca.test.js +0 -41
- package/dist/__tests__/apple-root-ca.test.js.map +0 -1
- package/dist/__tests__/apple-status-api.test.js +0 -345
- package/dist/__tests__/apple-status-api.test.js.map +0 -1
- package/dist/__tests__/cache.test.js +0 -34
- package/dist/__tests__/cache.test.js.map +0 -1
- package/dist/__tests__/entitlements.test.js +0 -268
- package/dist/__tests__/entitlements.test.js.map +0 -1
- package/dist/__tests__/error-codes.test.js +0 -173
- package/dist/__tests__/error-codes.test.js.map +0 -1
- package/dist/__tests__/fetch-hardening.test.js +0 -192
- package/dist/__tests__/fetch-hardening.test.js.map +0 -1
- package/dist/__tests__/google-paused.test.js +0 -126
- package/dist/__tests__/google-paused.test.js.map +0 -1
- package/dist/__tests__/google-price-change.test.js +0 -186
- package/dist/__tests__/google-price-change.test.js.map +0 -1
- package/dist/__tests__/google-subscriptions-v2.test.js +0 -206
- package/dist/__tests__/google-subscriptions-v2.test.js.map +0 -1
- package/dist/__tests__/lifecycle-scenarios.test.js +0 -579
- package/dist/__tests__/lifecycle-scenarios.test.js.map +0 -1
- package/dist/__tests__/lifecycle-states.test.js +0 -423
- package/dist/__tests__/lifecycle-states.test.js.map +0 -1
- package/dist/__tests__/linked-purchase-token.test.js +0 -227
- package/dist/__tests__/linked-purchase-token.test.js.map +0 -1
- package/dist/__tests__/metrics.test.js +0 -340
- package/dist/__tests__/metrics.test.js.map +0 -1
- package/dist/__tests__/mock-provider.test.js +0 -188
- package/dist/__tests__/mock-provider.test.js.map +0 -1
- package/dist/__tests__/openapi.test.js +0 -32
- package/dist/__tests__/openapi.test.js.map +0 -1
- package/dist/__tests__/paused-auto-resume.test.js +0 -162
- package/dist/__tests__/paused-auto-resume.test.js.map +0 -1
- package/dist/__tests__/providers.test.js +0 -321
- package/dist/__tests__/providers.test.js.map +0 -1
- package/dist/__tests__/redis-store.test.js +0 -166
- package/dist/__tests__/redis-store.test.js.map +0 -1
- package/dist/__tests__/refund-policy.test.js +0 -317
- package/dist/__tests__/refund-policy.test.js.map +0 -1
- package/dist/__tests__/schema.test.js +0 -46
- package/dist/__tests__/schema.test.js.map +0 -1
- package/dist/__tests__/store.test.js +0 -172
- package/dist/__tests__/store.test.js.map +0 -1
- package/dist/__tests__/test-utils.js +0 -30
- package/dist/__tests__/test-utils.js.map +0 -1
- package/dist/__tests__/webhook-apple.test.js +0 -247
- package/dist/__tests__/webhook-apple.test.js.map +0 -1
- package/dist/__tests__/webhook-events.test.js +0 -36
- package/dist/__tests__/webhook-events.test.js.map +0 -1
- package/dist/__tests__/webhook-google.test.js +0 -255
- package/dist/__tests__/webhook-google.test.js.map +0 -1
- package/dist/__tests__/webhook-queue.test.js +0 -26
- package/dist/__tests__/webhook-queue.test.js.map +0 -1
- package/dist/__tests__/webhook-refund.test.js +0 -313
- package/dist/__tests__/webhook-refund.test.js.map +0 -1
- package/dist/cache.js +0 -39
- package/dist/cache.js.map +0 -1
- package/dist/errors.js +0 -19
- package/dist/errors.js.map +0 -1
- package/dist/http.js +0 -36
- package/dist/http.js.map +0 -1
- package/dist/logger.js +0 -20
- package/dist/logger.js.map +0 -1
- package/dist/openapi.js +0 -196
- package/dist/openapi.js.map +0 -1
- package/dist/providers/apple-root-ca.js +0 -38
- package/dist/providers/apple-root-ca.js.map +0 -1
- package/dist/providers/apple.js +0 -630
- package/dist/providers/apple.js.map +0 -1
- package/dist/providers/google.js +0 -564
- package/dist/providers/google.js.map +0 -1
- package/dist/providers/mock.js +0 -93
- package/dist/providers/mock.js.map +0 -1
- package/dist/routes/admin.js +0 -327
- package/dist/routes/admin.js.map +0 -1
- package/dist/routes/apple-offer.js +0 -72
- package/dist/routes/apple-offer.js.map +0 -1
- package/dist/routes/entitlements.js +0 -130
- package/dist/routes/entitlements.js.map +0 -1
- package/dist/routes/metrics.js +0 -281
- package/dist/routes/metrics.js.map +0 -1
- package/dist/routes/purchase.js +0 -204
- package/dist/routes/purchase.js.map +0 -1
- package/dist/routes/status.js +0 -55
- package/dist/routes/status.js.map +0 -1
- package/dist/routes/validate.js +0 -70
- package/dist/routes/validate.js.map +0 -1
- package/dist/routes/webhook-apple.js +0 -145
- package/dist/routes/webhook-apple.js.map +0 -1
- package/dist/routes/webhook-google.js +0 -204
- package/dist/routes/webhook-google.js.map +0 -1
- package/dist/routes/webhook.js +0 -19
- package/dist/routes/webhook.js.map +0 -1
- package/dist/store.js +0 -145
- package/dist/store.js.map +0 -1
- package/dist/stores/postgres.js +0 -329
- package/dist/stores/postgres.js.map +0 -1
- package/dist/stores/redis.js +0 -297
- package/dist/stores/redis.js.map +0 -1
- package/dist/stores/schema.js +0 -67
- package/dist/stores/schema.js.map +0 -1
- package/dist/tracing.js +0 -74
- package/dist/tracing.js.map +0 -1
- package/dist/webhook-events.js +0 -58
- package/dist/webhook-events.js.map +0 -1
- package/dist/webhook-queue.js +0 -108
- package/dist/webhook-queue.js.map +0 -1
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for webhook-apple.ts handler behaviors.
|
|
3
|
-
*
|
|
4
|
-
* Covers gaps not reached by lifecycle-scenarios or webhook-refund:
|
|
5
|
-
* - Input validation (missing / malformed signedPayload)
|
|
6
|
-
* - Webhook event deduplication via WebhookEventStore
|
|
7
|
-
* - DID_FAIL_TO_RENEW without GRACE_PERIOD subtype → on_hold
|
|
8
|
-
* - Notification type mappings: DID_RECOVER, OFFER_REDEEMED → active; EXPIRED → expired
|
|
9
|
-
* - Unknown notification type falls through to JWS transaction status
|
|
10
|
-
*/
|
|
11
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
12
|
-
import express from 'express';
|
|
13
|
-
import { SUBSCRIPTION_STATUS } from '@onesub/shared';
|
|
14
|
-
import { createWebhookRouter } from '../routes/webhook.js';
|
|
15
|
-
import { InMemorySubscriptionStore, InMemoryPurchaseStore } from '../store.js';
|
|
16
|
-
import { InMemoryWebhookEventStore } from '../webhook-events.js';
|
|
17
|
-
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
18
|
-
function makeJws(payload) {
|
|
19
|
-
const header = Buffer.from(JSON.stringify({ alg: 'ES256' })).toString('base64url');
|
|
20
|
-
const body = Buffer.from(JSON.stringify(payload)).toString('base64url');
|
|
21
|
-
return `${header}.${body}.fakesig`;
|
|
22
|
-
}
|
|
23
|
-
function applePayload(opts) {
|
|
24
|
-
const signedTransactionInfo = makeJws({
|
|
25
|
-
bundleId: 'com.example.app',
|
|
26
|
-
type: opts.type ?? 'Auto-Renewable Subscription',
|
|
27
|
-
productId: 'pro_monthly',
|
|
28
|
-
transactionId: opts.transactionId ?? `tx_${Date.now()}`,
|
|
29
|
-
originalTransactionId: opts.originalTransactionId,
|
|
30
|
-
purchaseDate: Date.now() - 86400000,
|
|
31
|
-
expiresDate: opts.expiresDate ?? Date.now() + 30 * 86400000,
|
|
32
|
-
environment: 'Production',
|
|
33
|
-
});
|
|
34
|
-
const signedRenewalInfo = makeJws({ autoRenewStatus: opts.autoRenewStatus ?? 1 });
|
|
35
|
-
const inner = {
|
|
36
|
-
notificationType: opts.notificationType,
|
|
37
|
-
data: { signedTransactionInfo, signedRenewalInfo },
|
|
38
|
-
};
|
|
39
|
-
if (opts.subtype)
|
|
40
|
-
inner.subtype = opts.subtype;
|
|
41
|
-
if (opts.notificationUUID)
|
|
42
|
-
inner.notificationUUID = opts.notificationUUID;
|
|
43
|
-
return { signedPayload: makeJws(inner) };
|
|
44
|
-
}
|
|
45
|
-
const baseConfig = {
|
|
46
|
-
apple: { bundleId: 'com.example.app', skipJwsVerification: true },
|
|
47
|
-
database: { url: '' },
|
|
48
|
-
};
|
|
49
|
-
const sampleSub = (overrides) => ({
|
|
50
|
-
userId: 'user_a',
|
|
51
|
-
productId: 'pro_monthly',
|
|
52
|
-
platform: 'apple',
|
|
53
|
-
status: 'active',
|
|
54
|
-
expiresAt: '2099-01-01T00:00:00.000Z',
|
|
55
|
-
originalTransactionId: 'orig_a',
|
|
56
|
-
purchasedAt: '2026-01-01T00:00:00.000Z',
|
|
57
|
-
willRenew: true,
|
|
58
|
-
...overrides,
|
|
59
|
-
});
|
|
60
|
-
function buildServer(config, store, webhookEventStore) {
|
|
61
|
-
const app = express();
|
|
62
|
-
app.use(express.json());
|
|
63
|
-
app.use(createWebhookRouter(config, store, new InMemoryPurchaseStore(), webhookEventStore));
|
|
64
|
-
return {
|
|
65
|
-
async request(body) {
|
|
66
|
-
const srv = app.listen(0);
|
|
67
|
-
const port = srv.address().port;
|
|
68
|
-
try {
|
|
69
|
-
const resp = await fetch(`http://127.0.0.1:${port}/onesub/webhook/apple`, {
|
|
70
|
-
method: 'POST',
|
|
71
|
-
headers: { 'Content-Type': 'application/json' },
|
|
72
|
-
body: JSON.stringify(body),
|
|
73
|
-
});
|
|
74
|
-
const text = await resp.text();
|
|
75
|
-
let parsed = text;
|
|
76
|
-
try {
|
|
77
|
-
parsed = JSON.parse(text);
|
|
78
|
-
}
|
|
79
|
-
catch { /* keep as text */ }
|
|
80
|
-
return { status: resp.status, body: parsed };
|
|
81
|
-
}
|
|
82
|
-
finally {
|
|
83
|
-
await new Promise((r) => srv.close(() => r()));
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
// ── Input validation ─────────────────────────────────────────────────────────
|
|
89
|
-
describe('Apple webhook — input validation', () => {
|
|
90
|
-
it('returns 400 when signedPayload is missing', async () => {
|
|
91
|
-
const store = new InMemorySubscriptionStore();
|
|
92
|
-
const server = buildServer(baseConfig, store);
|
|
93
|
-
const resp = await server.request({});
|
|
94
|
-
expect(resp.status).toBe(400);
|
|
95
|
-
expect(resp.body.errorCode).toBe('MISSING_SIGNED_PAYLOAD');
|
|
96
|
-
});
|
|
97
|
-
it('returns 400 when signedPayload is not a valid JWS', async () => {
|
|
98
|
-
const store = new InMemorySubscriptionStore();
|
|
99
|
-
const server = buildServer(baseConfig, store);
|
|
100
|
-
// Not a 3-part dot-separated JWT — decodeJwt will throw
|
|
101
|
-
const resp = await server.request({ signedPayload: 'not-a-jws-string' });
|
|
102
|
-
expect(resp.status).toBe(400);
|
|
103
|
-
expect(resp.body.errorCode).toBe('INVALID_SIGNED_PAYLOAD');
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
// ── Deduplication ────────────────────────────────────────────────────────────
|
|
107
|
-
describe('Apple webhook — deduplication', () => {
|
|
108
|
-
let store;
|
|
109
|
-
let webhookEventStore;
|
|
110
|
-
let server;
|
|
111
|
-
beforeEach(() => {
|
|
112
|
-
store = new InMemorySubscriptionStore();
|
|
113
|
-
webhookEventStore = new InMemoryWebhookEventStore();
|
|
114
|
-
server = buildServer(baseConfig, store, webhookEventStore);
|
|
115
|
-
});
|
|
116
|
-
it('processes the first delivery and returns received=true', async () => {
|
|
117
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_dedup' }));
|
|
118
|
-
const resp = await server.request(applePayload({
|
|
119
|
-
notificationType: 'DID_RENEW',
|
|
120
|
-
notificationUUID: 'uuid-apple-1',
|
|
121
|
-
originalTransactionId: 'orig_dedup',
|
|
122
|
-
}));
|
|
123
|
-
expect(resp.status).toBe(200);
|
|
124
|
-
expect(resp.body.received).toBe(true);
|
|
125
|
-
expect(resp.body.deduped).toBeUndefined();
|
|
126
|
-
});
|
|
127
|
-
it('returns deduped=true and skips store update on replay', async () => {
|
|
128
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_dedup2', status: 'active' }));
|
|
129
|
-
const payload = applePayload({
|
|
130
|
-
notificationType: 'EXPIRED',
|
|
131
|
-
notificationUUID: 'uuid-apple-2',
|
|
132
|
-
originalTransactionId: 'orig_dedup2',
|
|
133
|
-
});
|
|
134
|
-
// First delivery — processed normally (EXPIRED → expired)
|
|
135
|
-
await server.request(payload);
|
|
136
|
-
expect((await store.getByTransactionId('orig_dedup2'))?.status).toBe(SUBSCRIPTION_STATUS.EXPIRED);
|
|
137
|
-
// Restore status to simulate what a store rollback would look like
|
|
138
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_dedup2', status: 'active' }));
|
|
139
|
-
// Replayed delivery — must be skipped, store stays 'active'
|
|
140
|
-
const replay = await server.request(payload);
|
|
141
|
-
expect(replay.status).toBe(200);
|
|
142
|
-
expect(replay.body.deduped).toBe(true);
|
|
143
|
-
expect((await store.getByTransactionId('orig_dedup2'))?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
|
|
144
|
-
});
|
|
145
|
-
it('does not deduplicate when no webhookEventStore is wired', async () => {
|
|
146
|
-
// Without webhookEventStore, every delivery is processed regardless of UUID
|
|
147
|
-
const serverNoDedup = buildServer(baseConfig, store);
|
|
148
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_nodedup' }));
|
|
149
|
-
const payload = applePayload({
|
|
150
|
-
notificationType: 'EXPIRED',
|
|
151
|
-
notificationUUID: 'uuid-apple-3',
|
|
152
|
-
originalTransactionId: 'orig_nodedup',
|
|
153
|
-
});
|
|
154
|
-
await serverNoDedup.request(payload);
|
|
155
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_nodedup', status: 'active' }));
|
|
156
|
-
const second = await serverNoDedup.request(payload);
|
|
157
|
-
expect(second.status).toBe(200);
|
|
158
|
-
expect(second.body.deduped).toBeUndefined();
|
|
159
|
-
// Second delivery processed → status changed
|
|
160
|
-
expect((await store.getByTransactionId('orig_nodedup'))?.status).toBe(SUBSCRIPTION_STATUS.EXPIRED);
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
// ── Notification type → status mapping ──────────────────────────────────────
|
|
164
|
-
describe('Apple webhook — notification type mapping', () => {
|
|
165
|
-
let store;
|
|
166
|
-
let server;
|
|
167
|
-
beforeEach(() => {
|
|
168
|
-
store = new InMemorySubscriptionStore();
|
|
169
|
-
server = buildServer(baseConfig, store);
|
|
170
|
-
});
|
|
171
|
-
it('DID_FAIL_TO_RENEW without subtype → on_hold', async () => {
|
|
172
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_fail' }));
|
|
173
|
-
await server.request(applePayload({
|
|
174
|
-
notificationType: 'DID_FAIL_TO_RENEW',
|
|
175
|
-
originalTransactionId: 'orig_fail',
|
|
176
|
-
}));
|
|
177
|
-
expect((await store.getByTransactionId('orig_fail'))?.status).toBe(SUBSCRIPTION_STATUS.ON_HOLD);
|
|
178
|
-
});
|
|
179
|
-
it('DID_FAIL_TO_RENEW + GRACE_PERIOD subtype → grace_period', async () => {
|
|
180
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_grace' }));
|
|
181
|
-
await server.request(applePayload({
|
|
182
|
-
notificationType: 'DID_FAIL_TO_RENEW',
|
|
183
|
-
subtype: 'GRACE_PERIOD',
|
|
184
|
-
originalTransactionId: 'orig_grace',
|
|
185
|
-
}));
|
|
186
|
-
expect((await store.getByTransactionId('orig_grace'))?.status).toBe(SUBSCRIPTION_STATUS.GRACE_PERIOD);
|
|
187
|
-
});
|
|
188
|
-
it('DID_RECOVER → active', async () => {
|
|
189
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_recover', status: 'on_hold' }));
|
|
190
|
-
await server.request(applePayload({
|
|
191
|
-
notificationType: 'DID_RECOVER',
|
|
192
|
-
originalTransactionId: 'orig_recover',
|
|
193
|
-
expiresDate: Date.now() + 30 * 86400000,
|
|
194
|
-
}));
|
|
195
|
-
expect((await store.getByTransactionId('orig_recover'))?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
|
|
196
|
-
});
|
|
197
|
-
it('OFFER_REDEEMED → active', async () => {
|
|
198
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_offer', status: 'expired' }));
|
|
199
|
-
await server.request(applePayload({
|
|
200
|
-
notificationType: 'OFFER_REDEEMED',
|
|
201
|
-
originalTransactionId: 'orig_offer',
|
|
202
|
-
expiresDate: Date.now() + 30 * 86400000,
|
|
203
|
-
}));
|
|
204
|
-
expect((await store.getByTransactionId('orig_offer'))?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
|
|
205
|
-
});
|
|
206
|
-
it('EXPIRED → expired', async () => {
|
|
207
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_exp' }));
|
|
208
|
-
await server.request(applePayload({
|
|
209
|
-
notificationType: 'EXPIRED',
|
|
210
|
-
originalTransactionId: 'orig_exp',
|
|
211
|
-
}));
|
|
212
|
-
expect((await store.getByTransactionId('orig_exp'))?.status).toBe(SUBSCRIPTION_STATUS.EXPIRED);
|
|
213
|
-
});
|
|
214
|
-
it('GRACE_PERIOD_EXPIRED → on_hold', async () => {
|
|
215
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_gpe', status: 'grace_period' }));
|
|
216
|
-
await server.request(applePayload({
|
|
217
|
-
notificationType: 'GRACE_PERIOD_EXPIRED',
|
|
218
|
-
originalTransactionId: 'orig_gpe',
|
|
219
|
-
}));
|
|
220
|
-
expect((await store.getByTransactionId('orig_gpe'))?.status).toBe(SUBSCRIPTION_STATUS.ON_HOLD);
|
|
221
|
-
});
|
|
222
|
-
it('unknown notification type falls through to JWS transaction status', async () => {
|
|
223
|
-
// JWS has autoRenewStatus=1 and a future expiresDate → provider decodes as ACTIVE.
|
|
224
|
-
// The webhook maps unknown types to the decoded status.
|
|
225
|
-
await store.save(sampleSub({ originalTransactionId: 'orig_unk', status: 'expired' }));
|
|
226
|
-
await server.request(applePayload({
|
|
227
|
-
notificationType: 'PRICE_INCREASE_CONSENT', // not in any APPLE_*_TYPES set
|
|
228
|
-
originalTransactionId: 'orig_unk',
|
|
229
|
-
expiresDate: Date.now() + 30 * 86400000,
|
|
230
|
-
autoRenewStatus: 1,
|
|
231
|
-
}));
|
|
232
|
-
// Status comes from the decoded JWS renewal info (active/grace_period based on expiresDate)
|
|
233
|
-
// With a future expiresDate + autoRenewStatus=1, decodeAppleNotification returns active
|
|
234
|
-
expect((await store.getByTransactionId('orig_unk'))?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
|
|
235
|
-
});
|
|
236
|
-
it('returns 200 even when originalTransactionId is unknown (no record in store)', async () => {
|
|
237
|
-
// Webhook should always ack — not found means we can't recover without API creds,
|
|
238
|
-
// but we still return 200 so Apple doesn't retry indefinitely.
|
|
239
|
-
const resp = await server.request(applePayload({
|
|
240
|
-
notificationType: 'DID_RENEW',
|
|
241
|
-
originalTransactionId: 'completely_unknown',
|
|
242
|
-
}));
|
|
243
|
-
expect(resp.status).toBe(200);
|
|
244
|
-
expect(resp.body.received).toBe(true);
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
//# sourceMappingURL=webhook-apple.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-apple.test.js","sourceRoot":"","sources":["../../src/__tests__/webhook-apple.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { CacheWebhookEventStore, InMemoryWebhookEventStore } from '../webhook-events.js';
|
|
3
|
-
import { InMemoryCacheAdapter } from '../cache.js';
|
|
4
|
-
describe('InMemoryWebhookEventStore', () => {
|
|
5
|
-
it('returns true the first time, false on retry', async () => {
|
|
6
|
-
const store = new InMemoryWebhookEventStore();
|
|
7
|
-
expect(await store.markIfNew('apple', 'uuid-1')).toBe(true);
|
|
8
|
-
expect(await store.markIfNew('apple', 'uuid-1')).toBe(false);
|
|
9
|
-
});
|
|
10
|
-
it('keys by provider so apple/google ids never collide', async () => {
|
|
11
|
-
const store = new InMemoryWebhookEventStore();
|
|
12
|
-
expect(await store.markIfNew('apple', 'shared')).toBe(true);
|
|
13
|
-
expect(await store.markIfNew('google', 'shared')).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
it('expires entries after the TTL', async () => {
|
|
16
|
-
const store = new InMemoryWebhookEventStore(1); // 1-second TTL
|
|
17
|
-
expect(await store.markIfNew('apple', 'uuid-1')).toBe(true);
|
|
18
|
-
await new Promise((resolve) => setTimeout(resolve, 1100));
|
|
19
|
-
// Re-eligible after expiry — Apple/Google retries beyond the window are
|
|
20
|
-
// effectively new events, which is the intended behavior.
|
|
21
|
-
expect(await store.markIfNew('apple', 'uuid-1')).toBe(true);
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
describe('CacheWebhookEventStore', () => {
|
|
25
|
-
it('uses any CacheAdapter for cluster-shared dedupe', async () => {
|
|
26
|
-
const cache = new InMemoryCacheAdapter();
|
|
27
|
-
const store = new CacheWebhookEventStore(cache);
|
|
28
|
-
expect(await store.markIfNew('google', 'msg-1')).toBe(true);
|
|
29
|
-
expect(await store.markIfNew('google', 'msg-1')).toBe(false);
|
|
30
|
-
// A second store backed by the same cache sees the prior write — this is
|
|
31
|
-
// the multi-instance idempotency guarantee we ship.
|
|
32
|
-
const store2 = new CacheWebhookEventStore(cache);
|
|
33
|
-
expect(await store2.markIfNew('google', 'msg-1')).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
//# sourceMappingURL=webhook-events.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-events.test.js","sourceRoot":"","sources":["../../src/__tests__/webhook-events.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,KAAK,GAAG,IAAI,yBAAyB,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,KAAK,GAAG,IAAI,yBAAyB,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,KAAK,GAAG,IAAI,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe;QAC/D,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1D,wEAAwE;QACxE,0DAA0D;QAC1D,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE7D,yEAAyE;QACzE,oDAAoD;QACpD,MAAM,MAAM,GAAG,IAAI,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for webhook-google.ts handler behaviors.
|
|
3
|
-
*
|
|
4
|
-
* Covers gaps not reached by google-paused, google-price-change, or webhook-refund:
|
|
5
|
-
* - Input validation (missing message.data)
|
|
6
|
-
* - Webhook event deduplication via WebhookEventStore
|
|
7
|
-
* - pushAudience JWT authentication (missing / invalid token → 401)
|
|
8
|
-
* - Package name mismatch for subscription notifications
|
|
9
|
-
* - Notification type mappings: CANCELED, REVOKED, EXPIRED, IN_GRACE_PERIOD, unknown fallback
|
|
10
|
-
* - verifyGooglePushToken unit (no network required for invalid tokens)
|
|
11
|
-
*/
|
|
12
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
13
|
-
import express from 'express';
|
|
14
|
-
import { SUBSCRIPTION_STATUS } from '@onesub/shared';
|
|
15
|
-
import { createWebhookRouter } from '../routes/webhook.js';
|
|
16
|
-
import { InMemorySubscriptionStore, InMemoryPurchaseStore } from '../store.js';
|
|
17
|
-
import { InMemoryWebhookEventStore } from '../webhook-events.js';
|
|
18
|
-
import { verifyGooglePushToken } from '../routes/webhook-google.js';
|
|
19
|
-
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
20
|
-
function googlePushBody(notificationType, purchaseToken, opts) {
|
|
21
|
-
const json = JSON.stringify({
|
|
22
|
-
version: '1.0',
|
|
23
|
-
packageName: opts?.packageName ?? 'com.example.app',
|
|
24
|
-
eventTimeMillis: String(Date.now()),
|
|
25
|
-
subscriptionNotification: {
|
|
26
|
-
version: '1.0',
|
|
27
|
-
notificationType,
|
|
28
|
-
purchaseToken,
|
|
29
|
-
subscriptionId: 'pro_monthly',
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
return {
|
|
33
|
-
message: {
|
|
34
|
-
data: Buffer.from(json).toString('base64'),
|
|
35
|
-
messageId: opts?.messageId ?? `msg-${Date.now()}`,
|
|
36
|
-
},
|
|
37
|
-
subscription: 'projects/x/subscriptions/y',
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const baseConfig = {
|
|
41
|
-
google: { packageName: 'com.example.app' },
|
|
42
|
-
database: { url: '' },
|
|
43
|
-
};
|
|
44
|
-
const sampleSub = (overrides) => ({
|
|
45
|
-
userId: 'user_g',
|
|
46
|
-
productId: 'pro_monthly',
|
|
47
|
-
platform: 'google',
|
|
48
|
-
status: 'active',
|
|
49
|
-
expiresAt: '2099-01-01T00:00:00.000Z',
|
|
50
|
-
originalTransactionId: 'tok_g',
|
|
51
|
-
purchasedAt: '2026-01-01T00:00:00.000Z',
|
|
52
|
-
willRenew: true,
|
|
53
|
-
...overrides,
|
|
54
|
-
});
|
|
55
|
-
function buildServer(config, store, webhookEventStore) {
|
|
56
|
-
const app = express();
|
|
57
|
-
app.use(express.json());
|
|
58
|
-
app.use(createWebhookRouter(config, store, new InMemoryPurchaseStore(), webhookEventStore));
|
|
59
|
-
return {
|
|
60
|
-
async request(body, headers) {
|
|
61
|
-
const srv = app.listen(0);
|
|
62
|
-
const port = srv.address().port;
|
|
63
|
-
try {
|
|
64
|
-
const resp = await fetch(`http://127.0.0.1:${port}/onesub/webhook/google`, {
|
|
65
|
-
method: 'POST',
|
|
66
|
-
headers: { 'Content-Type': 'application/json', ...headers },
|
|
67
|
-
body: JSON.stringify(body),
|
|
68
|
-
});
|
|
69
|
-
const text = await resp.text();
|
|
70
|
-
let parsed = text;
|
|
71
|
-
try {
|
|
72
|
-
parsed = JSON.parse(text);
|
|
73
|
-
}
|
|
74
|
-
catch { /* keep as text */ }
|
|
75
|
-
return { status: resp.status, body: parsed };
|
|
76
|
-
}
|
|
77
|
-
finally {
|
|
78
|
-
await new Promise((r) => srv.close(() => r()));
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
// ── Input validation ─────────────────────────────────────────────────────────
|
|
84
|
-
describe('Google webhook — input validation', () => {
|
|
85
|
-
it('returns 400 when message.data is missing', async () => {
|
|
86
|
-
const store = new InMemorySubscriptionStore();
|
|
87
|
-
const server = buildServer(baseConfig, store);
|
|
88
|
-
const resp = await server.request({ message: { messageId: '1' }, subscription: 's' });
|
|
89
|
-
expect(resp.status).toBe(400);
|
|
90
|
-
expect(resp.body.errorCode).toBe('MISSING_MESSAGE_DATA');
|
|
91
|
-
});
|
|
92
|
-
it('returns 200 when message.data decodes to an unrecognized notification format', async () => {
|
|
93
|
-
const store = new InMemorySubscriptionStore();
|
|
94
|
-
const server = buildServer(baseConfig, store);
|
|
95
|
-
// Valid base64 but payload has no known notification field
|
|
96
|
-
const json = JSON.stringify({ version: '1.0', packageName: 'com.example.app' });
|
|
97
|
-
const resp = await server.request({
|
|
98
|
-
message: { data: Buffer.from(json).toString('base64'), messageId: '1' },
|
|
99
|
-
subscription: 's',
|
|
100
|
-
});
|
|
101
|
-
// decodeGoogleNotification returns null → ack with 200
|
|
102
|
-
expect(resp.status).toBe(200);
|
|
103
|
-
expect(resp.body.received).toBe(true);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
// ── pushAudience authentication ───────────────────────────────────────────────
|
|
107
|
-
describe('Google webhook — pushAudience authentication', () => {
|
|
108
|
-
const configWithAudience = {
|
|
109
|
-
google: { packageName: 'com.example.app', pushAudience: 'https://myapp.example.com' },
|
|
110
|
-
database: { url: '' },
|
|
111
|
-
};
|
|
112
|
-
it('returns 401 when Authorization header is absent', async () => {
|
|
113
|
-
const store = new InMemorySubscriptionStore();
|
|
114
|
-
const server = buildServer(configWithAudience, store);
|
|
115
|
-
const resp = await server.request(googlePushBody(2, 'tok_auth'));
|
|
116
|
-
expect(resp.status).toBe(401);
|
|
117
|
-
expect(resp.body.errorCode).toBe('UNAUTHORIZED');
|
|
118
|
-
});
|
|
119
|
-
it('returns 401 when Bearer token is malformed (not a valid JWT)', async () => {
|
|
120
|
-
const store = new InMemorySubscriptionStore();
|
|
121
|
-
const server = buildServer(configWithAudience, store);
|
|
122
|
-
const resp = await server.request(googlePushBody(2, 'tok_auth'), { Authorization: 'Bearer not-a-real-jwt' });
|
|
123
|
-
expect(resp.status).toBe(401);
|
|
124
|
-
expect(resp.body.errorCode).toBe('UNAUTHORIZED');
|
|
125
|
-
});
|
|
126
|
-
it('passes through (processes notification) when no pushAudience is configured', async () => {
|
|
127
|
-
const store = new InMemorySubscriptionStore();
|
|
128
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_noauth' }));
|
|
129
|
-
const server = buildServer(baseConfig, store); // no pushAudience
|
|
130
|
-
const resp = await server.request(googlePushBody(2, 'tok_noauth'));
|
|
131
|
-
expect(resp.status).toBe(200);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
// ── verifyGooglePushToken unit ────────────────────────────────────────────────
|
|
135
|
-
describe('verifyGooglePushToken', () => {
|
|
136
|
-
it('returns false when Authorization header is absent', async () => {
|
|
137
|
-
const req = { headers: {} };
|
|
138
|
-
expect(await verifyGooglePushToken(req, 'https://example.com')).toBe(false);
|
|
139
|
-
});
|
|
140
|
-
it('returns false when header is not Bearer scheme', async () => {
|
|
141
|
-
const req = { headers: { authorization: 'Basic dXNlcjpwYXNz' } };
|
|
142
|
-
expect(await verifyGooglePushToken(req, 'https://example.com')).toBe(false);
|
|
143
|
-
});
|
|
144
|
-
it('returns false for a malformed JWT that cannot be verified', async () => {
|
|
145
|
-
// jose throws on invalid JWT format; verifyGooglePushToken catches and returns false
|
|
146
|
-
const req = { headers: { authorization: 'Bearer not.valid.jwt' } };
|
|
147
|
-
expect(await verifyGooglePushToken(req, 'https://example.com')).toBe(false);
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
// ── Package name validation ───────────────────────────────────────────────────
|
|
151
|
-
describe('Google webhook — package name mismatch', () => {
|
|
152
|
-
it('returns 400 when notification packageName does not match config', async () => {
|
|
153
|
-
const store = new InMemorySubscriptionStore();
|
|
154
|
-
const server = buildServer(baseConfig, store);
|
|
155
|
-
const resp = await server.request(googlePushBody(2, 'tok_pkg', { packageName: 'com.attacker.app' }));
|
|
156
|
-
expect(resp.status).toBe(400);
|
|
157
|
-
expect(resp.body.errorCode).toBe('PACKAGE_NAME_MISMATCH');
|
|
158
|
-
});
|
|
159
|
-
it('accepts notification when no packageName is configured (open mode)', async () => {
|
|
160
|
-
const openConfig = {
|
|
161
|
-
google: {}, // no packageName restriction
|
|
162
|
-
database: { url: '' },
|
|
163
|
-
};
|
|
164
|
-
const store = new InMemorySubscriptionStore();
|
|
165
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_open' }));
|
|
166
|
-
const server = buildServer(openConfig, store);
|
|
167
|
-
const resp = await server.request(googlePushBody(2, 'tok_open', { packageName: 'any.package.name' }));
|
|
168
|
-
expect(resp.status).toBe(200);
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
// ── Deduplication ────────────────────────────────────────────────────────────
|
|
172
|
-
describe('Google webhook — deduplication', () => {
|
|
173
|
-
let store;
|
|
174
|
-
let webhookEventStore;
|
|
175
|
-
let server;
|
|
176
|
-
beforeEach(() => {
|
|
177
|
-
store = new InMemorySubscriptionStore();
|
|
178
|
-
webhookEventStore = new InMemoryWebhookEventStore();
|
|
179
|
-
server = buildServer(baseConfig, store, webhookEventStore);
|
|
180
|
-
});
|
|
181
|
-
it('processes the first delivery and returns received=true', async () => {
|
|
182
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_dedup1' }));
|
|
183
|
-
const resp = await server.request(googlePushBody(2, 'tok_dedup1', { messageId: 'msg-dedup-1' }));
|
|
184
|
-
expect(resp.status).toBe(200);
|
|
185
|
-
expect(resp.body.received).toBe(true);
|
|
186
|
-
expect(resp.body.deduped).toBeUndefined();
|
|
187
|
-
});
|
|
188
|
-
it('returns deduped=true and skips store update on replay', async () => {
|
|
189
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_dedup2', status: 'active' }));
|
|
190
|
-
const body = googlePushBody(3, 'tok_dedup2', { messageId: 'msg-dedup-2' }); // CANCELED
|
|
191
|
-
// First delivery → status becomes canceled
|
|
192
|
-
await server.request(body);
|
|
193
|
-
expect((await store.getByTransactionId('tok_dedup2'))?.status).toBe(SUBSCRIPTION_STATUS.CANCELED);
|
|
194
|
-
// Restore to simulate rollback
|
|
195
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_dedup2', status: 'active' }));
|
|
196
|
-
// Replay → must be skipped, status stays active
|
|
197
|
-
const replay = await server.request(body);
|
|
198
|
-
expect(replay.status).toBe(200);
|
|
199
|
-
expect(replay.body.deduped).toBe(true);
|
|
200
|
-
expect((await store.getByTransactionId('tok_dedup2'))?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
// ── Notification type → status mapping ──────────────────────────────────────
|
|
204
|
-
describe('Google webhook — notification type mapping', () => {
|
|
205
|
-
let store;
|
|
206
|
-
let server;
|
|
207
|
-
beforeEach(() => {
|
|
208
|
-
store = new InMemorySubscriptionStore();
|
|
209
|
-
server = buildServer(baseConfig, store);
|
|
210
|
-
});
|
|
211
|
-
it('SUBSCRIPTION_CANCELED (3) → canceled', async () => {
|
|
212
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_cancel' }));
|
|
213
|
-
await server.request(googlePushBody(3, 'tok_cancel'));
|
|
214
|
-
expect((await store.getByTransactionId('tok_cancel'))?.status).toBe(SUBSCRIPTION_STATUS.CANCELED);
|
|
215
|
-
});
|
|
216
|
-
it('SUBSCRIPTION_REVOKED (12) → canceled', async () => {
|
|
217
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_revoke' }));
|
|
218
|
-
await server.request(googlePushBody(12, 'tok_revoke'));
|
|
219
|
-
expect((await store.getByTransactionId('tok_revoke'))?.status).toBe(SUBSCRIPTION_STATUS.CANCELED);
|
|
220
|
-
});
|
|
221
|
-
it('SUBSCRIPTION_EXPIRED (13) → expired', async () => {
|
|
222
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_exp' }));
|
|
223
|
-
await server.request(googlePushBody(13, 'tok_exp'));
|
|
224
|
-
expect((await store.getByTransactionId('tok_exp'))?.status).toBe(SUBSCRIPTION_STATUS.EXPIRED);
|
|
225
|
-
});
|
|
226
|
-
it('SUBSCRIPTION_IN_GRACE_PERIOD (6) → grace_period', async () => {
|
|
227
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_grace' }));
|
|
228
|
-
await server.request(googlePushBody(6, 'tok_grace'));
|
|
229
|
-
expect((await store.getByTransactionId('tok_grace'))?.status).toBe(SUBSCRIPTION_STATUS.GRACE_PERIOD);
|
|
230
|
-
});
|
|
231
|
-
it('SUBSCRIPTION_ON_HOLD (5) → on_hold', async () => {
|
|
232
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_hold' }));
|
|
233
|
-
await server.request(googlePushBody(5, 'tok_hold'));
|
|
234
|
-
expect((await store.getByTransactionId('tok_hold'))?.status).toBe(SUBSCRIPTION_STATUS.ON_HOLD);
|
|
235
|
-
});
|
|
236
|
-
it('SUBSCRIPTION_PURCHASED (4) → active', async () => {
|
|
237
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_buy', status: 'expired' }));
|
|
238
|
-
await server.request(googlePushBody(4, 'tok_buy'));
|
|
239
|
-
expect((await store.getByTransactionId('tok_buy'))?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
|
|
240
|
-
});
|
|
241
|
-
it('unknown notification type (SUBSCRIPTION_DEFERRED=9) falls back to active', async () => {
|
|
242
|
-
// Type 9 is not handled by any isGoogle*Notification helper → else branch → ACTIVE
|
|
243
|
-
await store.save(sampleSub({ originalTransactionId: 'tok_deferred', status: 'on_hold' }));
|
|
244
|
-
await server.request(googlePushBody(9, 'tok_deferred'));
|
|
245
|
-
expect((await store.getByTransactionId('tok_deferred'))?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
|
|
246
|
-
});
|
|
247
|
-
it('returns 200 even when purchaseToken is unknown (no store record, no serviceAccountKey)', async () => {
|
|
248
|
-
// Without serviceAccountKey, server cannot re-fetch from Play API.
|
|
249
|
-
// Should log a warning and ack 200 so Google doesn't retry forever.
|
|
250
|
-
const resp = await server.request(googlePushBody(2, 'tok_unknown_no_key'));
|
|
251
|
-
expect(resp.status).toBe(200);
|
|
252
|
-
expect(resp.body.received).toBe(true);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
//# sourceMappingURL=webhook-google.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-google.test.js","sourceRoot":"","sources":["../../src/__tests__/webhook-google.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { InProcessWebhookQueue } from '../webhook-queue.js';
|
|
3
|
-
describe('InProcessWebhookQueue', () => {
|
|
4
|
-
it('runs the handler synchronously inside enqueue', async () => {
|
|
5
|
-
const queue = new InProcessWebhookQueue();
|
|
6
|
-
const seen = [];
|
|
7
|
-
queue.setHandler(async (job) => {
|
|
8
|
-
seen.push(job);
|
|
9
|
-
});
|
|
10
|
-
await queue.enqueue({ provider: 'apple', eventId: 'uuid-1', payload: { foo: 'bar' } });
|
|
11
|
-
expect(seen).toHaveLength(1);
|
|
12
|
-
expect(seen[0].eventId).toBe('uuid-1');
|
|
13
|
-
});
|
|
14
|
-
it('throws if no handler has been registered', async () => {
|
|
15
|
-
const queue = new InProcessWebhookQueue();
|
|
16
|
-
await expect(queue.enqueue({ provider: 'apple', eventId: 'uuid-1', payload: {} })).rejects.toThrow(/no handler/);
|
|
17
|
-
});
|
|
18
|
-
it('propagates handler errors to enqueue', async () => {
|
|
19
|
-
const queue = new InProcessWebhookQueue();
|
|
20
|
-
queue.setHandler(async () => {
|
|
21
|
-
throw new Error('downstream failed');
|
|
22
|
-
});
|
|
23
|
-
await expect(queue.enqueue({ provider: 'apple', eventId: 'uuid-1', payload: {} })).rejects.toThrow(/downstream failed/);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
//# sourceMappingURL=webhook-queue.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-queue.test.js","sourceRoot":"","sources":["../../src/__tests__/webhook-queue.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,KAAK,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAiB,EAAE,CAAC;QAC9B,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACvF,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,KAAK,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC1C,MAAM,MAAM,CACV,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CACrE,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,KAAK,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC1C,KAAK,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,CACV,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CACrE,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|