Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Dec 13, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Improved customer ID handling in Stripe webhooks and payment flows: the system now prefers a new external ID key while still falling back to the previous key for backward compatibility, reducing missed or mismatched customer links.
  • Documentation

    • Updated Stripe integration guides and examples to reference the new external metadata key so users can pass the external customer ID consistently.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Contributor

vercel bot commented Dec 13, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
dub Ready Ready Preview Dec 13, 2025 0:53am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

Walkthrough

Multiple Stripe webhook handlers, a customer-creation util, and two guide docs were updated to prefer metadata.dubCustomerExternalId and fall back to legacy metadata.dubCustomerId when deriving Stripe-linked external customer IDs.

Changes

Cohort / File(s) Summary
Webhook handlers
apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts, apps/web/app/(ee)/api/stripe/integration/webhook/customer-created.ts, apps/web/app/(ee)/api/stripe/integration/webhook/customer-updated.ts, apps/web/app/(ee)/api/stripe/integration/webhook/invoice-paid.ts
Replace direct reads of metadata?.dubCustomerId with a preference for metadata?.dubCustomerExternalId and fallback to metadata?.dubCustomerId. No other control-flow or exported API changes.
Customer creation util
apps/web/app/(ee)/api/stripe/integration/webhook/utils/create-new-customer.ts
When assigning externalId for created customers, prefer stripeCustomer.metadata?.dubCustomerExternalId with fallback to stripeCustomer.metadata?.dubCustomerId.
Guides / docs
apps/web/guides/stripe-checkout.md, apps/web/guides/stripe-customers.md
Documentation and code examples updated to use metadata key dubCustomerExternalId instead of dubCustomerId.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Focus areas:
    • Confirm consistent fallback order (dubCustomerExternalId then dubCustomerId) across all modified files.
    • Verify no code paths elsewhere still expect only the legacy key.
    • Ensure docs examples match runtime behavior.

Possibly related PRs

Suggested reviewers

  • devkiran

Poem

Hop hop, I peek through Stripe's tide, πŸ‡
External IDs now take the lead,
If new-field hides, the old one abides,
Backwards-safe, both paths proceed,
A tiny hop for each webhook need.

Pre-merge checks and finishing touches

βœ… Passed checks (3 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title clearly and accurately summarizes the main objective of the changeset: updating the Stripe integration to use dubCustomerExternalId instead of dubCustomerId for consistency across multiple files and workflows.
Docstring Coverage βœ… Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dub-customer-external-id

πŸ“œ Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 2d3a4c2 and 92f3ea1.

πŸ“’ Files selected for processing (7)
  • apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts (2 hunks)
  • apps/web/app/(ee)/api/stripe/integration/webhook/customer-created.ts (1 hunks)
  • apps/web/app/(ee)/api/stripe/integration/webhook/customer-updated.ts (1 hunks)
  • apps/web/app/(ee)/api/stripe/integration/webhook/invoice-paid.ts (1 hunks)
  • apps/web/app/(ee)/api/stripe/integration/webhook/utils/create-new-customer.ts (1 hunks)
  • apps/web/guides/stripe-checkout.md (2 hunks)
  • apps/web/guides/stripe-customers.md (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
πŸ“š Learning: 2025-07-17T06:41:45.620Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.620Z
Learning: In the Singular integration (apps/web/app/(ee)/api/singular/webhook/route.ts), the event names in the singularToDubEvent object have intentionally different casing: "Copy GAID" and "copy IDFA". This casing difference is valid and should not be changed, as these are the correct event names expected from Singular.

Applied to files:

  • apps/web/app/(ee)/api/stripe/integration/webhook/customer-updated.ts
πŸ“š Learning: 2025-06-19T01:46:45.723Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 0
File: :0-0
Timestamp: 2025-06-19T01:46:45.723Z
Learning: PayPal webhook verification in the Dub codebase is handled at the route level in `apps/web/app/(ee)/api/paypal/webhook/route.ts` using the `verifySignature` function. Individual webhook handlers like `payoutsItemFailed` don't need to re-verify signatures since they're only called after successful verification.

Applied to files:

  • apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts
πŸ”‡ Additional comments (7)
apps/web/guides/stripe-checkout.md (1)

9-9: LGTM! Documentation correctly updated.

The documentation accurately reflects the migration to dubCustomerExternalId as the preferred metadata key for passing customer IDs in Stripe checkout sessions.

Also applies to: 29-29

apps/web/app/(ee)/api/stripe/integration/webhook/utils/create-new-customer.ts (1)

21-23: LGTM! Fallback pattern correctly implemented.

The utility function now properly prefers dubCustomerExternalId and falls back to dubCustomerId, maintaining consistency with the webhook handlers.

apps/web/app/(ee)/api/stripe/integration/webhook/invoice-paid.ts (1)

42-44: LGTM! Fallback pattern correctly applied.

The external ID derivation properly prioritizes dubCustomerExternalId with a fallback to dubCustomerId when retrieving metadata from connected customers.

apps/web/guides/stripe-customers.md (1)

3-3: LGTM! Documentation comprehensively updated.

All references to the metadata key have been correctly updated to dubCustomerExternalId across both customer creation and update flows, aligning with the code changes.

Also applies to: 20-20, 26-26, 41-41

apps/web/app/(ee)/api/stripe/integration/webhook/customer-created.ts (1)

9-11: LGTM! Consistent fallback pattern.

The external ID extraction correctly prioritizes dubCustomerExternalId with a fallback to dubCustomerId, maintaining consistency across webhook handlers.

apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts (2)

45-46: LGTM! Fallback pattern correctly applied.

The initial external ID extraction properly prioritizes dubCustomerExternalId from charge metadata with a fallback to dubCustomerId.


242-247: LGTM! Connected customer fallback correctly implemented.

The connected customer external ID derivation properly follows the same fallback pattern, ensuring consistency across all customer lookup paths.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts (1)

242-253: Critical: Condition must check for both metadata fields.

The condition on line 242 only checks for dubCustomerId, which means customers with only dubCustomerExternalId in their metadata will be skipped. This breaks the new field support.

Apply this diff to fix the condition:

-        if (connectedCustomer?.metadata.dubCustomerId) {
+        if (connectedCustomer?.metadata.dubCustomerExternalId || connectedCustomer?.metadata.dubCustomerId) {
           dubCustomerExternalId =
             connectedCustomer.metadata.dubCustomerExternalId ||
             connectedCustomer.metadata.dubCustomerId;
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 2d3a4c2 and 188badb.

πŸ“’ Files selected for processing (4)
  • apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts (2 hunks)
  • apps/web/app/(ee)/api/stripe/integration/webhook/customer-created.ts (1 hunks)
  • apps/web/app/(ee)/api/stripe/integration/webhook/customer-updated.ts (1 hunks)
  • apps/web/app/(ee)/api/stripe/integration/webhook/invoice-paid.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
πŸ”‡ Additional comments (4)
apps/web/app/(ee)/api/stripe/integration/webhook/customer-created.ts (1)

9-11: LGTM! Backward-compatible fallback implemented correctly.

The fallback pattern ensures existing integrations using dubCustomerId continue to work while supporting the new dubCustomerExternalId field. The || operator correctly handles all falsy values.

apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts (2)

45-46: LGTM! Consistent fallback pattern.

The extraction correctly prefers dubCustomerExternalId and falls back to dubCustomerId for backward compatibility.


243-245: LGTM! Extraction logic is correct.

The fallback pattern properly supports both the new dubCustomerExternalId and legacy dubCustomerId fields. However, this code's effectiveness depends on fixing the conditional check at line 242.

apps/web/app/(ee)/api/stripe/integration/webhook/invoice-paid.ts (1)

42-44: LGTM! Proper use of optional chaining with fallback.

The extraction correctly handles potentially undefined connectedCustomer with optional chaining while maintaining backward compatibility through the fallback to dubCustomerId.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/web/guides/stripe-checkout.md (1)

9-9: Consider documenting backwards compatibility.

The documentation now shows only dubCustomerExternalId, but the implementation (in create-new-customer.ts) maintains fallback support for the legacy dubCustomerId key. Consider adding a note that existing integrations using dubCustomerId will continue to work, to avoid confusion or unnecessary migration concerns.

Example addition:

  metadata: {
    dubCustomerExternalId: user.id, // the unique user ID of the customer in your database
  },
+  // Note: The legacy 'dubCustomerId' key is still supported for backwards compatibility

Also applies to: 29-29

apps/web/guides/stripe-customers.md (1)

3-3: Consider adding backwards compatibility note.

Similar to the Stripe Checkout guide, this documentation now shows only dubCustomerExternalId in both the customer creation and update flows. Consider adding a note that the legacy dubCustomerId key remains supported for backwards compatibility, helping users understand that immediate migration is optional.

Example addition:

  metadata: {
    dubCustomerExternalId: user.id,
    dubClickId: dub_id,
  },
+  // Note: The legacy 'dubCustomerId' key is still supported for backwards compatibility

Also applies to: 20-20, 26-26, 41-41

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 188badb and 92f3ea1.

πŸ“’ Files selected for processing (4)
  • apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts (2 hunks)
  • apps/web/app/(ee)/api/stripe/integration/webhook/utils/create-new-customer.ts (1 hunks)
  • apps/web/guides/stripe-checkout.md (2 hunks)
  • apps/web/guides/stripe-customers.md (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
πŸ”‡ Additional comments (1)
apps/web/app/(ee)/api/stripe/integration/webhook/utils/create-new-customer.ts (1)

21-23: LGTM! Fallback pattern is consistently implemented across all webhook handlers.

The implementation in lines 21-23 correctly uses the fallback from dubCustomerExternalId to dubCustomerId. Verified that the same pattern is consistently applied across all Stripe webhook handlers (invoice-paid.ts, customer-created.ts, customer-updated.ts, checkout-session-completed.ts, and create-new-customer.ts).

@steven-tey
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

βœ… Actions performed

Full review triggered.

@steven-tey steven-tey merged commit e909677 into main Dec 13, 2025
7 of 8 checks passed
@steven-tey steven-tey deleted the dub-customer-external-id branch December 13, 2025 01:37
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.

2 participants