@mpgd/game-services 0.17.1 → 0.17.2

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.
@@ -1,6 +1,6 @@
1
1
  import { type AppsInTossPurchaseAuthority, type AppsInTossPurchaseAuthorityInput, type AppsInTossPurchaseAuthorityResult, type AppsInTossRewardAuthority, type AppsInTossRewardAuthorityInput, type AppsInTossRewardAuthorityResult, type CreateAppsInTossProductionEvidenceVerifierInput } from './apps-in-toss-evidence-verification.js';
2
2
  import type { GameServicesEvidenceVerifier } from './evidence-verification.js';
3
- export declare const appsInTossProductionEvidenceConformanceScenarios: readonly ['callback-only-fail-closed', 'purchase-product-grant-callback', 'purchase-authority-retry', 'purchase-pending-order-restore', 'purchase-authority-matching', 'purchase-timestamp-normalization', 'reward-authority-retry-and-replay', 'reward-timestamp-validation', 'authority-errors-and-reward-matching'];
3
+ export declare const appsInTossProductionEvidenceConformanceScenarios: readonly ['callback-only-fail-closed', 'purchase-product-grant-callback', 'purchase-authority-retry', 'purchase-pending-order-restore', 'purchase-authority-matching', 'purchase-subscription-unsupported', 'purchase-timestamp-normalization', 'reward-authority-retry-and-replay', 'reward-timestamp-validation', 'authority-errors-and-reward-matching'];
4
4
  export type AppsInTossProductionEvidenceConformanceScenario = (typeof appsInTossProductionEvidenceConformanceScenarios)[number];
5
5
  export type CreateAppsInTossProductionEvidenceVerifier = (input?: CreateAppsInTossProductionEvidenceVerifierInput) => GameServicesEvidenceVerifier;
6
6
  export interface RunAppsInTossProductionEvidenceConformanceInput {
@@ -6,6 +6,7 @@ export const appsInTossProductionEvidenceConformanceScenarios = [
6
6
  'purchase-authority-retry',
7
7
  'purchase-pending-order-restore',
8
8
  'purchase-authority-matching',
9
+ 'purchase-subscription-unsupported',
9
10
  'purchase-timestamp-normalization',
10
11
  'reward-authority-retry-and-replay',
11
12
  'reward-timestamp-validation',
@@ -26,6 +27,17 @@ const catalog = {
26
27
  ait: 'ait.conformance.coins',
27
28
  },
28
29
  },
30
+ {
31
+ id: 'CONFORMANCE_PASS',
32
+ type: 'subscription',
33
+ grant: {
34
+ type: 'entitlement',
35
+ entitlement: 'conformance_pass',
36
+ },
37
+ platformProductIds: {
38
+ ait: 'ait.conformance.pass',
39
+ },
40
+ },
29
41
  ],
30
42
  };
31
43
  const placements = {
@@ -54,6 +66,7 @@ const scenarioRunners = {
54
66
  'purchase-authority-retry': runPurchaseAuthorityRetryScenario,
55
67
  'purchase-pending-order-restore': runPurchasePendingOrderRestoreScenario,
56
68
  'purchase-authority-matching': runPurchaseAuthorityMatchingScenario,
69
+ 'purchase-subscription-unsupported': runPurchaseSubscriptionUnsupportedScenario,
57
70
  'purchase-timestamp-normalization': runPurchaseTimestampNormalizationScenario,
58
71
  'reward-authority-retry-and-replay': runRewardAuthorityRetryAndReplayScenario,
59
72
  'reward-timestamp-validation': runRewardTimestampValidationScenario,
@@ -309,6 +322,30 @@ async function runPurchaseAuthorityMatchingScenario(createVerifier, now) {
309
322
  assertEqual(progress.reason, 'AIT_PURCHASE_ORDER_ORDER_IN_PROGRESS', 'in-progress purchase');
310
323
  await assertEntitlementCount(context.store, 0, 'purchase mismatches and status');
311
324
  }
325
+ async function runPurchaseSubscriptionUnsupportedScenario(createVerifier, now) {
326
+ const fixture = createAppsInTossProductionEvidenceAuthorityFixture();
327
+ fixture.enqueuePurchaseResult(resolvedOrder({
328
+ orderId: 'ait-order-subscription',
329
+ sku: 'ait.conformance.pass',
330
+ }));
331
+ const context = createScenarioContext(createVerifier, now, {
332
+ purchaseAuthority: fixture.purchaseAuthority,
333
+ });
334
+ const subscription = await context.backend.purchases.verifyPurchase(purchaseRequest({
335
+ productId: 'CONFORMANCE_PASS',
336
+ platformTransactionId: 'ait-order-subscription',
337
+ idempotencyKey: 'purchase-subscription',
338
+ evidence: createAppsInTossPurchaseCallbackEvidence({
339
+ orderId: 'ait-order-subscription',
340
+ platformSku: 'ait.conformance.pass',
341
+ source: 'process-product-grant',
342
+ }),
343
+ }));
344
+ assertEqual(subscription.verified, false, 'subscription purchase must not grant');
345
+ assertEqual(subscription.reason, 'APPS_IN_TOSS_SUBSCRIPTION_UNSUPPORTED', 'subscription purchase must be rejected explicitly');
346
+ assertEqual(fixture.purchaseInputs.length, 0, 'unsupported subscriptions must fail before the purchase authority is called');
347
+ await assertEntitlementCount(context.store, 0, 'unsupported subscription purchase');
348
+ }
312
349
  async function runPurchaseTimestampNormalizationScenario(createVerifier, now) {
313
350
  const fixture = createAppsInTossProductionEvidenceAuthorityFixture();
314
351
  fixture.enqueuePurchaseResult(resolvedOrder({
@@ -150,6 +150,11 @@ async function verifyAppsInTossPurchase(authority, input) {
150
150
  if (request.target !== 'ait') {
151
151
  return rejected('AIT_PURCHASE_TARGET_REQUIRED');
152
152
  }
153
+ // One-time order status cannot express renewal, expiry, or revocation. Reject
154
+ // explicitly instead of relying on the adapter hiding SUBSCRIPTION products.
155
+ if (input.product.type === 'subscription') {
156
+ return rejected('APPS_IN_TOSS_SUBSCRIPTION_UNSUPPORTED');
157
+ }
153
158
  if (request.evidence?.schema !== appsInTossPurchaseCallbackEvidenceSchema) {
154
159
  return rejected('AIT_PURCHASE_EVIDENCE_SCHEMA_INVALID');
155
160
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpgd/game-services",
3
- "version": "0.17.1",
3
+ "version": "0.17.2",
4
4
  "description": "Client, contract, server, store, and test helpers for authoritative mpgd game services.",
5
5
  "license": "MIT",
6
6
  "repository": {