feat(adapters): forward customer IP address on checkout creation
Summary
Related Issue: Plain thread th_01M3ZN8RAM580Z4Z2H3GVCQ3KP (Strats.gg)
The Better Auth, Next.js, Nuxt and TanStack Start adapters now send customer_ip_address on checkout creation, so Polar can show the visitor's local currency. Until now they always got the default currency.
What
- Better Auth: sends the IP from Better Auth's
getIP, which follows the app'sadvanced.ipAddresssettings. - Next.js / Nuxt / TanStack Start: send the first valid IP from
x-forwarded-for,x-real-iporcf-connecting-ip, unless acustomer_ip_addressquery param is passed. - New
customerIpAddressoption on every adapter: a function to resolve the IP yourself, orfalseto not send it. @polar-sh/adapter-utils: the sharedgetCustomerIpAddressandresolveCustomerIpAddresshelpers. zod is added as acatalog:dependency.
No SDK bump needed: @polar-sh/sdk 1.0.2 already has the field.
Why
The API uses customer_ip_address to find the visitor's country (_get_ip_country in checkout/service.py) and pick the presentment currency.
How
The API rejects an invalid IP with a 422, which fails the checkout, so the default lookups only send valid IPs. Better Auth's getIP validates on its own; the header lookup uses zod's ipv4/ipv6. The query param and a custom function's result are passed through as given.
Clients can fake these headers unless the host or proxy sets them. Since the IP only picks the currency the checkout opens in, that's an acceptable default.
Checklist
- This PR addresses a single concern (one bug fix, one feature, one refactor)
- The diff is reasonably sized and easy to review
- New functionality is covered by tests
- Linting and type checking pass (
vitest run,tsc/vue-tscandoxfmt --checkin each adapter package) - No unrelated changes or drive-by fixes are included
๐ค Generated with Claude Code