Skip to content

feat: dispatch card verification events and copy in tokenize-only che… - #278

Merged
jakubjasinsky merged 2 commits into
masterfrom
jakub-tokenize-only-card-verification-events
Aug 18, 2026
Merged

feat: dispatch card verification events and copy in tokenize-only che…#278
jakubjasinsky merged 2 commits into
masterfrom
jakub-tokenize-only-card-verification-events

Conversation

@jakubjasinsky

Copy link
Copy Markdown
Collaborator

Summary

In tokenize-only Dynamic Checkout no money moves — the shopper is verifying a card — but the widget still emitted processout_dynamic_checkout_payment_* events and rendered "This payment is completed." This switches both to card-verification wording.

Changes

  • Events: five new processout_dynamic_checkout_card_verification_{submitted,success,pending,cancelled,error} names. The existing dispatchers take an optional trailing isCardVerification that selects the name — payload, sanitizing and the processout-js.field.unavailable swallow are unchanged.
  • Copy: new utils/status-messages.ts maps each payment message key to a verification counterpart; success/cancelled/pending/info/generic-error views and the pay-button aria-label resolve through it. Six new keys × 14 locales.
  • One predicate: DynamicCheckoutPaymentConfig.isTokenizeOnly() replaces the private hasTokenizeOnlyCard() in payment-methods.ts.
  • dynamic-checkout.ts now calls setInvoiceDetails before the transaction-status check, so that branch can see the mode (it previously always reported false).
  • Tests: 50 cases covering the predicate, all 14 locales × 6 keys in both modes, and event-name routing in both directions.

Impact

  • Merchants listening for payment_* events on a tokenize-only invoice must add listeners for the card_verification_* names. Non-tokenize-only checkouts are unaffected — the flag defaults falsy, so the ~35 dispatch sites in the APM/wallet/saved-method files are untouched.

Additional Context

  • Only card.ts and dynamic-checkout.ts pass the flag: tokenize_only lives on the card method, saved methods are already hidden in this flow, and APM/wallet flows can't be tokenize-only.
  • tokenize-payment-button-text still reads "Tokenize payment" — left as-is, but "Verify card" would match the new copy if we want it.

Copilot AI lite review requested due to automatic review settings August 10, 2026 11:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Dynamic Checkout’s tokenize-only flow to behave like card verification (not payment) by emitting a parallel set of processout_dynamic_checkout_card_verification_* events and by rendering verification-specific status copy across the status views and button aria-label.

Changes:

  • Added card-verification event names and routed existing Dynamic Checkout event dispatchers via an optional isCardVerification flag (payload/sanitization behavior unchanged).
  • Introduced getStatusMessage() and verification message key mapping so tokenize-only flows show verification wording across status screens and the pay button aria-label.
  • Centralized tokenize-only detection via DynamicCheckoutPaymentConfig.isTokenizeOnly() and ensured invoice details are set early enough for status/error handling to detect the mode; added tests covering predicate, locale copy, and event routing.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/support/loadNamespace.ts Adds a Dynamic Checkout loader shim for tests, including event capture and chunk ordering to simulate --outFile concatenation behavior.
test/dynamic-checkout/tokenize-only.test.ts New tests for isTokenizeOnly(), status-message mapping across locales, and payment vs card-verification event name routing.
src/dynamic-checkout/views/payment-success.ts Uses getStatusMessage() so tokenize-only flow shows verification success copy.
src/dynamic-checkout/views/payment-pending.ts Uses getStatusMessage() so tokenize-only flow shows verification pending copy.
src/dynamic-checkout/views/payment-info.ts Uses getStatusMessage() so tokenize-only flow shows verification info copy.
src/dynamic-checkout/views/payment-cancelled.ts Uses getStatusMessage() so tokenize-only flow shows verification cancelled copy.
src/dynamic-checkout/views/payment-methods.ts Uses getStatusMessage() for generic error copy and replaces the private tokenize-only predicate with paymentConfig.isTokenizeOnly().
src/dynamic-checkout/utils/status-messages.ts New helper mapping payment status keys to verification equivalents when isTokenizeOnly() is true.
src/dynamic-checkout/utils/events.ts Adds CARD_VERIFICATION_* event constants and optional isCardVerification routing to existing dispatchers.
src/dynamic-checkout/references.ts Ensures the new status-messages utility is included in the Dynamic Checkout reference chain/bundle order.
src/dynamic-checkout/payment-methods/card.ts Passes isTokenizeOnly() to event dispatchers and resolves button aria-label via getStatusMessage().
src/dynamic-checkout/dynamic-checkout.ts Sets invoice details before the transaction-status check and routes the invalid-status error event using tokenize-only mode.
src/dynamic-checkout/config/payment-config.ts Adds DynamicCheckoutPaymentConfig.isTokenizeOnly() predicate based on invoice payment methods.
src/dynamic-checkout/locales/ar.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/de.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/en.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/es.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/fi.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/fr.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/it.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/ja.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/ko.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/nb.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/pl.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/pt.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/ta.ts Adds verification status and aria-label translation keys.
src/dynamic-checkout/locales/vi.ts Adds verification status and aria-label translation keys.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@lukasz-k-bieszczad-cko

Copy link
Copy Markdown
Contributor

Merchants listening for payment_* events on a tokenize-only invoice must add listeners for the card_verification_* names

Does this need some coordination with merchant experience team?

@mateusz-walesiak-cko

Copy link
Copy Markdown
Contributor

Merchants listening for payment_* events on a tokenize-only invoice must add listeners for the card_verification_* names

Does this need some coordination with merchant experience team?

Ah, good shout out. The only thing we need is to update this reference: https://docs.processout.com/docs/dynamic-checkout-web#event-reference. I should be able to edit it when this is merged.

This task has been requested by the merchants, so mexp is already coordinating I think

@mateusz-walesiak-cko

Copy link
Copy Markdown
Contributor

Merchants listening for payment_* events on a tokenize-only invoice must add listeners for the card_verification_* names

Does this need some coordination with merchant experience team?

Ah, good shout out. The only thing we need is to update this reference: https://docs.processout.com/docs/dynamic-checkout-web#event-reference. I should be able to edit it when this is merged.

This task has been requested by the merchants, so mexp is already coordinating I think

Docs updated: https://docs.processout.com/update/docs/dynamic-checkout-web


// Tokenize-only is exposed per payment method by the API, but it describes the whole
// checkout: the shopper is verifying a card, not paying for the invoice.
public isTokenizeOnly(): boolean {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I can see it's specifically related to card tokenization only. Should we also explicitly mention card in the method's name? As far as I understand, this config can be either card or apm?
In the future, we could even consider creating a union type to explicitly decouple APM and card payments?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The config here is checkout-wide rather than per-method, and isTokenizeOnly() describes the whole session ("this checkout verifies a card, it doesn't pay the invoice") — that's why the comment above it calls that out. The card.tokenize_only lookup is just where the API surfaces the flag. Adding "card" to the name would read as if it only affects the card method, but callers use it to change checkout-wide behavior (e.g. hiding saved payment methods). Happy to revisit as part of a card/APM config split later — agreed that'd be a nice cleanup.

@jakubjasinsky
jakubjasinsky merged commit 2c03dd2 into master Aug 18, 2026
5 checks passed
@jakubjasinsky
jakubjasinsky deleted the jakub-tokenize-only-card-verification-events branch August 18, 2026 09:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants