Skip to content

Add ach payment method#1313

Open
pbennett1-godaddy wants to merge 19 commits into
mainfrom
add-ach-paymentMethod
Open

Add ach payment method#1313
pbennett1-godaddy wants to merge 19 commits into
mainfrom
add-ach-paymentMethod

Conversation

@pbennett1-godaddy
Copy link
Copy Markdown
Collaborator

@pbennett1-godaddy pbennett1-godaddy commented Mar 6, 2026

Summary

Adds ACH (bank account) as a new payment method for GoDaddy Payments, surfaces tips, fees, shipping, and taxes correctly in the order summary, rewrites the custom tip input for better
multi-currency UX, and ships several checkout bug fixes (inline billing for ACH & pickup, stuck nonce loading state, $0 line items, duplicate DOM IDs).

Packages affected: @godaddy/react (patch), @godaddy/localizations (patch)


🆕 ACH Payment Method

Adds full support for ACH (bank account) payments via GoDaddy Payments:

  • New components
    • GoDaddyACHForm — Collect iframe for bank account input (account holder name/type, routing number, account number) with custom CSS matching the checkout theme
    • ACHCheckoutButton — submit button that triggers nonce collection and form validation
  • New provider: PoyntACHCollectProvider — dedicated React context for the ACH collect instance and nonce loading state, separate from the credit card collect provider
  • Payment registry: ACH registered in lazyPaymentComponentRegistry with lazy-loaded form and button components
  • Payment form UI: Added Landmark icon and label/description resolution for the ACH tab
  • Conditional wiring: ConditionalPaymentProviders wraps children in the ACH provider only when GoDaddy Payments is configured and session.paymentMethods.ach.processor === 'godaddy'
  • Lazy renderer guard: LazyPaymentMethodRenderer returns null for the ACH method unless GoDaddy Payments has an appId and the session lists ach with the godaddy processor (and similarly
    hides the GoDaddy CC form when no appId is configured)
  • GraphQL: Updated CreateCheckoutSessionMutation, GetCheckoutSessionQuery, and the introspection schema to include ach { processor, checkoutTypes }
  • Types: Added PaymentMethodType.ACH = 'ach'
  • Example: Next.js example app updated with ach and express payment method config

🧾 Inline Billing for ACH & Pickup Fix for Credit Card

Refactored billing-address logic in payment-form.tsx and payment-methods/credit-card/container.tsx:

  • Introduced an INLINE_BILLING_PAYMENT_METHODS list (card, ach) — these collect billing inline, so the standalone billing block / address toggle is suppressed for both
  • PaymentAddressToggle now only renders for non-inline-billing methods
  • For credit card with local pickup, shouldShowBillingNamesOnly now correctly evaluates (!useShippingAddress || isPickup) so the names-only billing block appears when needed
  • GoDaddyACHForm mirrors the same logic, including names-only fallback when enableBillingAddressCollection === false

💰 Order Summary: Tips, Fees, Shipping, Taxes

  • Tips included in total: displayed order total now includes the tip amount (total + tip) so customers see the true amount they'll be charged
  • New fees line item: added a Fees line in DraftOrderTotals (with skeleton + checkout.summary.totals.fees.before extension target). Wired through feeTotal from useDraftOrderTotals and
    an update-draft-order-fees mutation-key loading state
  • Show lines when there's a value, even if collection is disabled: introduced showShippingLine, showTaxesLine, showFeesLine in CheckoutForm. Merchants who disable collection but pre-apply
    a value still see it reflected in the summary:
    • Shipping: (isShipping && enableShipping) || shipping > 0
    • Taxes: enableTaxCollection || taxTotal > 0
    • Fees: feeTotal > 0
  • Shipping source: shipping is now read directly from totals.shippingTotal.value instead of summing order.shippingLines (removes the unused useDraftOrder call)

✏️ Custom Tip Input Rewrite

Replaced <input type="number"> with a polished currency input using the "format on blur" pattern (same UX as Stripe, Square, Shopify):

  • While focused: raw text editing with sanitization (digits + single decimal only); intermediate states like "10." or "" are preserved for natural editing
  • On blur: parses input, converts to minor units, syncs to form state, and reformats display (e.g. "10.5""10.50")
  • Debounced sync: after 1.5s of inactivity while focused, form state and totals update automatically (via @tanstack/react-pacer's useDebouncedValue)
  • Multi-currency: respects per-currency precision (0 decimals for JPY/KRW, 3 for KWD/BHD, etc.) and symbol placement (prefix $ vs suffix )
  • convertMajorToMinorUnits hardened: now returns 0 for NaN, negative, or otherwise invalid input
  • Responsive: tip button grids stack on small screens (grid-cols-1 sm:grid-cols-3 / grid-cols-1 sm:grid-cols-2)

🐛 Bug Fixes

  • Stuck nonce loading state: credit card and ACH Pay Now buttons now flip isLoadingNonce to true only after validation succeeds, and reset it correctly on error, on failed validated
    events, and inside the confirmCheckout catch block. The button is also short-circuited when already disabled or when collect isn't ready
  • $0 line items: changed item.originalPrice && …item.originalPrice != null && … so items with a 0 original price correctly render the price column instead of being falsy-skipped
  • Duplicate DOM IDs: GoDaddy credit card and ACH forms now generate their mount-target IDs with React useId() (gdpay-card-element-…, gdpay-ach-element-…), preventing collisions when
    multiple checkouts mount on the same page
  • Stable applicationId deps: ApplePay, GooglePay, Paze, Express, credit card, and ACH forms now compute applicationId once at the component level and include it in their useEffect deps
    instead of re-deriving inline (previously caused subtle re-mount churn)

🌐 Localizations

  • Added ach payment method name ("Bank Account" / localized equivalents) and description across all 20 locales
  • Added a fees totals label across all locales
  • Added AUTHORIZATION_FAILED error message ("Failed to authorize payment" / localized equivalents) across all 20 locales

Changeset

  • Changeset added (docs)

Test Plan

…-ach-paymentMethod

# Conflicts:
#	examples/nextjs/app/page.tsx
#	packages/localizations/src/deDe.ts
#	packages/localizations/src/enIe.ts
#	packages/localizations/src/enUs.ts
#	packages/localizations/src/esAr.ts
#	packages/localizations/src/esCl.ts
#	packages/localizations/src/esCo.ts
#	packages/localizations/src/esEs.ts
#	packages/localizations/src/esMx.ts
#	packages/localizations/src/esPe.ts
#	packages/localizations/src/esUs.ts
#	packages/localizations/src/frCa.ts
#	packages/localizations/src/frFr.ts
#	packages/localizations/src/idId.ts
#	packages/localizations/src/itIt.ts
#	packages/localizations/src/ptBr.ts
#	packages/localizations/src/qaPs.ts
#	packages/localizations/src/trTr.ts
#	packages/localizations/src/viVn.ts
#	packages/localizations/src/zhCn.ts
#	packages/localizations/src/zhSg.ts
#	packages/react/src/components/checkout/payment/lazy-payment-loader.tsx
#	packages/react/src/lib/godaddy/checkout-mutations.ts
#	packages/react/src/lib/godaddy/checkout-queries.ts
…-ach-paymentMethod

# Conflicts:
#	packages/react/src/components/checkout/payment/checkout-buttons/express/godaddy.tsx
…-ach-paymentMethod

# Conflicts:
#	packages/localizations/src/deDe.ts
#	packages/react/src/components/checkout/payment/lazy-payment-loader.tsx
#	packages/react/src/components/checkout/payment/utils/conditional-providers.tsx
@pbennett1-godaddy pbennett1-godaddy self-assigned this Mar 6, 2026
@pbennett1-godaddy pbennett1-godaddy requested a review from a team as a code owner March 6, 2026 15:28
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 6, 2026

🦋 Changeset detected

Latest commit: d913f07

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@godaddy/localizations Patch
@godaddy/react Patch
nextjs Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 6, 2026

'This PR is stale as it has been open for 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'

@github-actions github-actions Bot added the stale label Apr 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor

'This PR was closed because it has been stalled for 5 days with no activity.'

@github-actions github-actions Bot closed this Apr 12, 2026
# Conflicts:
#	packages/react/src/components/checkout/payment/checkout-buttons/express/godaddy.tsx
#	packages/react/src/components/checkout/payment/checkout-buttons/paze/godaddy.tsx
#	packages/react/src/components/checkout/pickup/local-pickup.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant