← Provider replacement walkthrough

Commerce Protocol Example · client-bridge.mjs

Source snapshot · 2026-09-09

SHA-256 a6760f1a9059e650fa19ef96403b16f7860390fce390262276020bd2cc7d5078
1import assert from "node:assert/strict";2import { operation, validate } from "./contract.mjs";3 4// Run on the app backend; the provider still authenticates the store evidence.5export function toVerifyPurchaseInput(purchase, context = {}) {6  const { store, purchaseToken } = purchase ?? {};7  let input;8  const required = (value) => {9    if (typeof value !== "string" || !value.trim())10      throw new Error("Purchase evidence is required");11    return value;12  };13  switch (store) {14    case "apple":15      input = { store, apple: { jws: required(purchaseToken) } };16      break;17    case "google":18      input = { store, google: { purchaseToken: required(purchaseToken) } };19      break;20    case "amazon":21      input = {22        store,23        amazon: {24          userId: required(context.storeUserId),25          receiptId: required(purchaseToken),26          ...(context.amazonSandbox === true ? { sandbox: true } : {}),27        },28      };29      break;30    case "horizon":31      input = {32        store,33        horizon: {34          userId: required(context.storeUserId),35          sku: required(purchase.productId),36        },37      };38      break;39    default:40      throw new Error("Unsupported purchase store");41  }42  if (!validate(operation("verifyPurchase").input, input))43    throw new Error("Purchase evidence does not match the protocol input");44  return input;45}46 47export function runBridgeDemo() {48  const checks = [];49  for (const store of ["apple", "google"]) {50    const token = `fictional-${store}-evidence`;51    const input = toVerifyPurchaseInput({52      store,53      purchaseToken: token,54      productId: "premium.monthly",55      userId: "untrusted-client-claim",56    });57    assert.deepEqual(input, {58      store,59      ...(store === "apple"60        ? { apple: { jws: token } }61        : { google: { purchaseToken: token } }),62    });63    checks.push(`${store}: maps evidence without forwarding client identity`);64    assert(validate(operation("verifyPurchase").input, input));65    checks.push(`${store}: matches the installed verification input schema`);66  }67  for (const store of ["amazon", "horizon"]) {68    const input = toVerifyPurchaseInput(69      {70        store,71        purchaseToken: "receipt-1",72        productId: "premium.monthly",73        userId: "untrusted-app-user",74      },75      { storeUserId: "authenticated-store-user", amazonSandbox: true },76    );77    assert.deepEqual(78      input,79      store === "amazon"80        ? {81            store,82            amazon: {83              userId: "authenticated-store-user",84              receiptId: "receipt-1",85              sandbox: true,86            },87          }88        : {89            store,90            horizon: {91              userId: "authenticated-store-user",92              sku: "premium.monthly",93            },94          },95    );96    checks.push(97      `${store}: uses server-selected store identity, distinct from the app user`,98    );99    assert(validate(operation("verifyPurchase").input, input));100    checks.push(`${store}: matches the installed verification input schema`);101  }102  for (const [label, purchase] of [103    ["missing purchase", null],104    ["unknown store", { store: "unknown", purchaseToken: "fictional" }],105    [106      "Amazon requires its authenticated store user",107      { store: "amazon", purchaseToken: "fictional" },108    ],109    [110      "Horizon requires its authenticated store user",111      { store: "horizon", purchaseToken: "fictional" },112    ],113    ["missing evidence", { store: "apple" }],114    ["blank evidence", { store: "google", purchaseToken: " " }],115    ["non-string evidence", { store: "apple", purchaseToken: 123 }],116    [117      "oversized evidence",118      { store: "apple", purchaseToken: "x".repeat(16385) },119    ],120  ]) {121    assert.throws(() => toVerifyPurchaseInput(purchase), Error);122    checks.push(`Rejects ${label}`);123  }124  return checks;125}126 127if (import.meta.main)128  console.log(129    `Client boundary: ${runBridgeDemo().length} checks passed against the installed contract. Fixture fields only; no SDK checkout or store contacted.`,130  );131