diff --git a/README.md b/README.md index f518c6f..7665725 100644 --- a/README.md +++ b/README.md @@ -99,10 +99,15 @@ Management; the backend needs its own runtime switch for a system-wide shutdown. ## Donation checkout presentation Donation links navigate to `/donate/`, which embeds the existing Inttegro checkout -using `@inttegro/js` 0.5.8. The purchase intent, payment processing, hosted fields, +using `@inttegro/js` 0.7.1. The purchase intent, payment processing, hosted fields, and invoice/receipt features are unchanged. The old presentation flag is no longer used; existing `modal` or `redirect` environment values do not change this flow. +The embedded payment form uses the SDK's semantic appearance controls to carry +DevCongress's cream, pink, yellow, black, and muted-gray palette into the hosted +surface. Button, input, selection, focus, typography, and radius values are set +explicitly while Inttegro continues to own the secure fields and payment states. + Prepared order IDs retain the original same-tab session-storage key. Reloads and retries reopen that order. Completion and errors keep the reference; uncertain payment outcomes never automatically start a new donation or redirect to a fresh diff --git a/docs/changelog.md b/docs/changelog.md index f33afc8..327fae3 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 2026-10-21 — Match the donation form to DevCongress + +- Update the embedded donation checkout to `@inttegro/js` 0.7.1 and apply the + DevCongress palette to its background, surfaces, text, controls, focus state, + typography and radius through the SDK appearance API. +- Remove the persistent prepared-order recovery statement beneath the form while + retaining the guarded restart controls and actual same-tab order recovery. + ## 2026-10-19 — Consolidate dependency updates from #66 - Include Astro 7.4.0, Zod 4.6.7, Cloudflare Workers types 5.20261016.1 and Wrangler 4.151.0 in the donation follow-up, preserving Inttegro 0.5.8 and the donation recovery build checks. Raise the Node engine minimum to 22.22.0 to match Astro 7.4.0. diff --git a/docs/donation-checkout.md b/docs/donation-checkout.md index c127c26..c63fed6 100644 --- a/docs/donation-checkout.md +++ b/docs/donation-checkout.md @@ -1,7 +1,7 @@ # Donation checkout The `/donate/` page replaces PR #61's homepage modal. It uses the same Inttegro -purchase intent, `@inttegro/js` 0.5.8, hosted fields, payment processing, locale, +purchase intent, `@inttegro/js` 0.7.1, hosted fields, payment processing, locale, and document/payment-method features. `/support` remains the hosted redirect. The old presentation environment flag is ignored. @@ -28,10 +28,11 @@ contact support, rather than being sent into a potentially duplicate checkout. The page reuses the website's Bricolage Grotesque/Source Sans 3 fonts, cream palette, spacing, responsive layout, and contact information. Hosted fields are rendered in -an Inttegro-controlled cross-origin iframe. Version 0.5.8 supports theme and primary -color, not font, radius, spacing, or custom field styling. Matching those controls -exactly requires a provider-supported extension; the website must not proxy or -modify the hosted payment runtime. The accepted boundary is a site-styled surrounding page with provider-owned fields. +an Inttegro-controlled cross-origin iframe. Version 0.7.1 applies DevCongress's +semantic background, surface, foreground, muted, border, focus, button, input, and +selection colors, along with the SDK's sans-serif typography and shared 8px radius. +The website must not proxy or modify the hosted payment runtime; Inttegro continues +to own the secure controls, validation, and payment states. ## Verification diff --git a/package.json b/package.json index bf195c9..68412a9 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "check:donation": "node scripts/check-donation-checkout.mjs" }, "dependencies": { - "@inttegro/js": "0.5.8", + "@inttegro/js": "0.7.1", "astro": "^7.4.0", "zod": "^4.6.7" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e70cd0..298359f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,8 +13,8 @@ importers: .: dependencies: '@inttegro/js': - specifier: 0.5.8 - version: 0.5.8 + specifier: 0.7.1 + version: 0.7.1 astro: specifier: ^7.4.0 version: 7.4.0(esbuild@0.28.2)(yaml@2.9.1) @@ -580,8 +580,8 @@ packages: cpu: [x64] os: [win32] - '@inttegro/js@0.5.8': - resolution: {integrity: sha512-aAysBIhLWrdcd/Nm2hsZHzXpFSjG+L0YbYcQhtKo5FbCssZj0HIYSu6VVYw4l42iAphiaoh10oWleBgoZGnKbQ==} + '@inttegro/js@0.7.1': + resolution: {integrity: sha512-OROkXyMtIGpT0FIdjisSnvW0WEbf7fmX4HzFYTwOR6Owigc47ot4dBJ4KiuSwFuBRBDOLHqkvokUwvzKCJ8nqg==} engines: {node: '>=18'} '@jridgewell/resolve-uri@3.1.2': @@ -1939,7 +1939,7 @@ snapshots: '@img/sharp-win32-x64@0.35.5': optional: true - '@inttegro/js@0.5.8': {} + '@inttegro/js@0.7.1': {} '@jridgewell/resolve-uri@3.1.2': {} diff --git a/scripts/check-donation-checkout.mjs b/scripts/check-donation-checkout.mjs index 23a6f5f..6f22a10 100644 --- a/scripts/check-donation-checkout.mjs +++ b/scripts/check-donation-checkout.mjs @@ -94,10 +94,27 @@ function harness(storage = new Map(), storageBlocked = false) { const h = harness(); await h.settle(); assert.equal(h.controllers[0].options.purchaseIntentId, intent); +assert.deepEqual(JSON.parse(JSON.stringify(h.controllers[0].options.appearance)), { + theme: 'light', + colors: { + background: '#FFFFFF', + surface: '#F5F2E8', + foreground: '#111111', + mutedForeground: '#555555', + border: '#E0DDD4', + focus: '#E8117F', + }, + button: { background: '#E8117F', foreground: '#FFFFFF', border: '#111111' }, + input: { background: '#FFFFFF', foreground: '#111111', border: '#111111' }, + selection: { background: '#FEFCE8', foreground: '#111111', border: '#111111' }, + typography: { fontFamily: 'sans-serif' }, + shape: { borderRadius: 8 }, +}); const order = { id: orderId, status: 'requires_payment' }; h.controllers[0].emit({ type: 'orderPrepared', order }); assert.equal(h.storage.get(key), orderId); assert.deepEqual([...h.storage.keys()], [key]); +assert.doesNotMatch(h.element('[data-checkout-status]').textContent, /prepared order can/i); const resumed = harness(h.storage); await resumed.settle(); @@ -148,6 +165,8 @@ await blocked.click('[data-checkout-retry]'); assert.equal(blocked.controllers.at(-1).options.orderId, orderId, 'memory recovery survives storage failure'); const worker = readFileSync('src/worker.ts', 'utf8'); +const donationPage = readFileSync('src/pages/donate.astro', 'utf8'); assert.match(worker, /SUPPORT_PATHS = new Set\(\['\/support', '\/support\/'\]\)/); assert.doesNotMatch(readFileSync('src/pages/index.astro', 'utf8'), /useDonationModal|InttegroDonationCheckout/); -console.log('PASS donation recovery: legacy resume, ID-only storage, completion/error retention, same-order retries, stale events, pending-payment guard, acknowledged restart, blocked storage, and page routing.'); +assert.doesNotMatch(donationPage, /A prepared order can/i); +console.log('PASS donation recovery: branded checkout appearance, legacy resume, ID-only storage, completion/error retention, same-order retries, stale events, pending-payment guard, acknowledged restart, blocked storage, and page routing.'); diff --git a/src/lib/donation-checkout.ts b/src/lib/donation-checkout.ts index 33ea90c..fa8961c 100644 --- a/src/lib/donation-checkout.ts +++ b/src/lib/donation-checkout.ts @@ -1,7 +1,44 @@ -import { loadInttegro, type CheckoutController, type CheckoutOrder } from '@inttegro/js'; +import { + loadInttegro, + type CheckoutAppearance, + type CheckoutController, + type CheckoutOrder, +} from '@inttegro/js'; const orderPattern = /^or_[A-Za-z0-9]{20,128}$/; const intentPattern = /^sale_[A-Za-z0-9]{20,128}$/; +const checkoutAppearance = { + theme: 'light', + colors: { + background: '#FFFFFF', + surface: '#F5F2E8', + foreground: '#111111', + mutedForeground: '#555555', + border: '#E0DDD4', + focus: '#E8117F', + }, + button: { + background: '#E8117F', + foreground: '#FFFFFF', + border: '#111111', + }, + input: { + background: '#FFFFFF', + foreground: '#111111', + border: '#111111', + }, + selection: { + background: '#FEFCE8', + foreground: '#111111', + border: '#111111', + }, + typography: { + fontFamily: 'sans-serif', + }, + shape: { + borderRadius: 8, + }, +} satisfies CheckoutAppearance; export function initializeDonationCheckout(root: ParentNode = document): void { const page = root.querySelector('[data-donation-page]'); @@ -81,7 +118,7 @@ export function initializeDonationCheckout(root: ParentNode = document): void { remember(order); const messages: Record = { - requires_payment: 'Your donation is ready. Complete payment below. This prepared order can resume in this tab.', + requires_payment: 'Your donation is ready. Complete payment below.', requires_action: 'Your payment needs confirmation. Follow the instructions below; do not start another donation.', processing: 'Your payment is processing. Keep this reference and check this donation again before paying again.', paid: 'Thank you for supporting DevCongress. Your payment is confirmed. Your receipt is available in checkout below.', @@ -111,7 +148,7 @@ export function initializeDonationCheckout(root: ParentNode = document): void { const checkout = inttegro.createCheckout({ ...(orderId ? { orderId } : { purchaseIntentId }), - appearance: { primaryColor: '#E8117F', theme: 'light' }, + appearance: checkoutAppearance, features: { showLineItems: true, showInvoiceDownload: true, diff --git a/src/pages/donate.astro b/src/pages/donate.astro index 356bc6d..c4145ba 100644 --- a/src/pages/donate.astro +++ b/src/pages/donate.astro @@ -36,15 +36,12 @@ const hostedCheckout = `https://pages.inttegro.com/buy/${site.inttegro_purchase_
-
-

A prepared order can resume when you reload this tab. Details entered before that point are not saved. Closing the tab may end recovery.

- -
+