Skip to content

feat(whop): integrate whop payment provider#190

Open
Muhammad-Owais-Warsi wants to merge 6 commits into
getpaykit:mainfrom
Muhammad-Owais-Warsi:whop-integration
Open

feat(whop): integrate whop payment provider#190
Muhammad-Owais-Warsi wants to merge 6 commits into
getpaykit:mainfrom
Muhammad-Owais-Warsi:whop-integration

Conversation

@Muhammad-Owais-Warsi
Copy link
Copy Markdown
Contributor

@Muhammad-Owais-Warsi Muhammad-Owais-Warsi commented May 24, 2026

closes #64

  • New Features
    • Added Whop payment provider: subscription checkout flow, cancel/resume, active subscription listing, product sync, and webhook handling for subscription and payment events.
  • Tests
    • Added unit tests covering provider config, checkout creation, webhook normalization, and related error cases.
  • Chores
    • Added package metadata and TypeScript/packaging configs, documentation build config, and updated repository ignore rules.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 24, 2026

@Muhammad-Owais-Warsi is attempting to deploy a commit to the maxktz Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5d6010a0-099a-48bc-941f-c5f8cc2fff62

📥 Commits

Reviewing files that changed from the base of the PR and between 2c45151 and 2016641.

📒 Files selected for processing (1)
  • packages/whop/src/whop-provider.ts

📝 Walkthrough

Walkthrough

Adds a new packages/whop package: package metadata, build and TypeScript config, public factory and exports, Whop-specific types and helpers, a PaymentProvider adapter implementing checkout/subscription flows and webhook normalization, plus Vitest tests covering core behaviors and error paths.

Changes

Whop Provider Package

Layer / File(s) Summary
Package setup and build configuration
packages/whop/.gitignore, packages/whop/package.json, packages/whop/tsconfig.json, packages/whop/tsdown.config.ts
Development ignore rules, package metadata with ESM/private settings, TypeScript root and include scoped to src, and tsdown build entry mapping index to src/index.ts.
Public API exports and factory function
packages/whop/src/index.ts, packages/whop/src/whop-provider.ts (factory section)
Exports whop and WhopOptions; whop() builds a Whop SDK client from apiKey and returns a provider config delegating adapter creation to createWhopProvider.
Provider types and option contracts
packages/whop/src/whop-provider.ts (types section)
Defines WhopOptions and WhopProviderConfig, plus type aliases for extracting membership and payment webhook event shapes from Whop unwrapped events.
Error helpers & webhook normalization
packages/whop/src/whop-provider.ts (helpers and normalization)
Adds helper functions for standardized PayKit errors and nullable date normalization; implements membership -> subscription and payment -> checkout normalized event mapping with timestamp conversions and metadata stringification.
PaymentProvider adapter implementation
packages/whop/src/whop-provider.ts (implementation sections)
Implements the adapter wiring supported operations: subscription checkout creation (requires purchase_url), cancel/resume, list active subscriptions, sync products (validates Whop plan ids), webhook unwrapping and event routing, and health check(); unsupported methods call notSupported.
Unit tests for provider and factory
packages/whop/src/__tests__/whop-provider.test.ts, packages/whop/src/__tests__/whop.test.ts
Vitest suites asserting provider config shape and adapter API surface; tests for checkout creation, invalid session error, membership/payment webhook normalization, and webhook signature failure handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I stitched a Whop adapter neat and spry,
With webhooks trimmed and checkouts flying by,
Types aligned and tests all set,
A tiny package, ready to be met,
Hop—PayKit and Whop, up to the sky!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding integration for the Whop payment provider into the PayKit system.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

@Muhammad-Owais-Warsi Muhammad-Owais-Warsi marked this pull request as draft May 24, 2026 08:32
Copy link
Copy Markdown

@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: 4

🧹 Nitpick comments (1)
packages/whop/src/whop-provider.ts (1)

6-13: ⚡ Quick win

Add short JSDoc to exported Whop API surface.

Please add concise JSDoc for WhopOptions, createWhopProvider, and whop so integrators can quickly understand required fields and behavior.

As per coding guidelines, "Prefer adding JSDoc on most functions in the library core, and on some object properties mainly if API is used in many places or is user-facing".

Also applies to: 128-129, 318-319

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/whop/src/whop-provider.ts` around lines 6 - 13, Add concise JSDoc
comments for the exported API surface: document the WhopOptions interface
(describe apiKey as the secret API key string and companyId as the
tenant/company identifier), and add short JSDoc for the createWhopProvider
factory (explain it constructs and returns a configured provider for Whop using
WhopOptions and any PayKitProviderConfig overrides) and for the whop export
(describe it as the default/provider instance or helper entrypoint and its
intended usage). Place these comments immediately above the WhopOptions
declaration, the createWhopProvider function, and the whop export so integrators
can quickly understand required fields and behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/whop/.gitignore`:
- Line 15: The .gitignore currently contains the overly specific glob "_.log"
which will only match files literally named _.log; update that entry to the more
general "*.log" so all log files (e.g., server.log, app.log) are ignored
consistently — replace the "_.log" line with a "*.log" entry in the .gitignore.

In `@packages/whop/package.json`:
- Line 7: The package.json devDependency for `@types/bun` is set to "latest",
causing non-deterministic installs; change devDependencies["`@types/bun`"] in
packages/whop/package.json to a pinned version or a bounded semver range (e.g.
"0.3.1" or "^0.3.1") to ensure reproducible builds and update lockfile
accordingly.

In `@packages/whop/src/whop-provider.ts`:
- Around line 263-267: Update the thrown PayKitError in the Whop webhook
signature validation to reference the correct provider name: locate the
PayKitError.from call that uses PAYKIT_ERROR_CODES.PROVIDER_SIGNATURE_MISSING in
whop-provider.ts and change the error message string from "Invalid DodoPayments
webhook signature" to something like "Invalid Whop webhook signature" so logs
correctly identify the Whop adapter as the source.
- Around line 158-163: The createSubscriptionCheckout function is using the
non-null assertion on providerProduct.productId and may call
client.checkoutConfigurations.create with undefined; before calling
client.checkoutConfigurations.create, validate that
data.providerProduct.productId is present and non-empty, and if not return or
throw a PayKitError (or the module's standard error type) with a clear message
like "Missing providerProduct.productId" so callers get an explicit, local error
instead of an opaque external Whop failure; remove the `!` usage and branch
early to fail-fast.

---

Nitpick comments:
In `@packages/whop/src/whop-provider.ts`:
- Around line 6-13: Add concise JSDoc comments for the exported API surface:
document the WhopOptions interface (describe apiKey as the secret API key string
and companyId as the tenant/company identifier), and add short JSDoc for the
createWhopProvider factory (explain it constructs and returns a configured
provider for Whop using WhopOptions and any PayKitProviderConfig overrides) and
for the whop export (describe it as the default/provider instance or helper
entrypoint and its intended usage). Place these comments immediately above the
WhopOptions declaration, the createWhopProvider function, and the whop export so
integrators can quickly understand required fields and behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21b526c9-1bd9-49a0-88c3-c88076eec170

📥 Commits

Reviewing files that changed from the base of the PR and between 97cc957 and a49eaf9.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • packages/whop/.gitignore
  • packages/whop/package.json
  • packages/whop/src/index.ts
  • packages/whop/src/whop-provider.ts
  • packages/whop/tsconfig.json
  • packages/whop/tsdown.config.ts

Comment thread packages/whop/.gitignore
Comment thread packages/whop/package.json
Comment thread packages/whop/src/whop-provider.ts
Comment thread packages/whop/src/whop-provider.ts
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 25, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
paykit Skipped Skipped May 25, 2026 3:43pm

@Muhammad-Owais-Warsi Muhammad-Owais-Warsi marked this pull request as ready for review May 25, 2026 08:56
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/whop/src/whop-provider.ts`:
- Around line 208-214: listActiveSubscriptions currently ignores the incoming
providerCustomerId and calls client.memberships.list without filtering,
returning all active/trialing memberships; update listActiveSubscriptions to
pass the user filter (user_id) using data.providerCustomerId to
client.memberships.list (or otherwise filter the result by sub.user_id ===
data.providerCustomerId) so only subscriptions for that specific customer are
returned, and ensure you still filter statuses ["active","trialing"] as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b388bad6-6ea2-4d7b-9331-46040df977c3

📥 Commits

Reviewing files that changed from the base of the PR and between a49eaf9 and a63a823.

📒 Files selected for processing (8)
  • packages/whop/.gitignore
  • packages/whop/package.json
  • packages/whop/src/__tests__/whop-provider.test.ts
  • packages/whop/src/__tests__/whop.test.ts
  • packages/whop/src/index.ts
  • packages/whop/src/whop-provider.ts
  • packages/whop/tsconfig.json
  • packages/whop/tsdown.config.ts
✅ Files skipped from review due to trivial changes (4)
  • packages/whop/tsconfig.json
  • packages/whop/src/index.ts
  • packages/whop/package.json
  • packages/whop/.gitignore

Copy link
Copy Markdown

@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

🧹 Nitpick comments (2)
packages/whop/src/whop-provider.ts (2)

295-298: 💤 Low value

Remove unnecessary type cast.

The as string cast on line 297 is misleading since c.user?.id could be undefined, and the ?? null fallback handles that case already. Remove the cast for clarity.

Suggested change
         const customerSample = (customers.data ?? []).map((c) => ({
           providerEmail: c.user?.email ?? "",
-          paykitCustomerId: (c.user?.id as string) ?? null,
+          paykitCustomerId: c.user?.id ?? null,
         }));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/whop/src/whop-provider.ts` around lines 295 - 298, The map creating
customerSample uses an unnecessary cast (c.user?.id as string) which is
misleading because c.user?.id can be undefined and you already handle that with
?? null; remove the cast and use paykitCustomerId: c.user?.id ?? null in the
customerSample construction so the type accurately reflects possible
undefined/null values when mapping customers.data.

237-253: Address the "need testing" comment.

The comment on line 237 indicates this method needs verification. Consider adding test coverage for syncProducts to validate the product mapping logic and error paths.

Would you like me to help generate test cases for syncProducts, or should I open an issue to track this?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/whop/src/whop-provider.ts` around lines 237 - 253, The syncProducts
method lacks tests and has an unverified "need testing" note; add unit tests for
the syncProducts function to cover: successful mapping when
product.existingProviderProduct.productId exists (assert returned results
include {id, providerProduct:{productId}}), the error branch when
product.existingProviderProduct is missing or productId is null (assert
PayKitError.from is thrown with PAYKIT_ERROR_CODES.PLAN_NOT_SYNCED and the
message contains the product.id), and edge cases such as multiple products and
empty input; locate syncProducts in whop-provider.ts and write tests that call
async syncProducts(data) with crafted data objects verifying both result shape
and thrown error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/whop/src/whop-provider.ts`:
- Around line 208-216: The listActiveSubscriptions implementation is filtering
memberships by sub.member?.id but providerCustomerId is based on the
membership's user id; update the filter in listActiveSubscriptions (the
client.memberships.list result processing) to compare sub.user?.id ===
data.providerCustomerId and keep the mapped output as { providerSubscriptionId:
sub.id } so active/trialing memberships for the provider customer are returned
correctly.

---

Nitpick comments:
In `@packages/whop/src/whop-provider.ts`:
- Around line 295-298: The map creating customerSample uses an unnecessary cast
(c.user?.id as string) which is misleading because c.user?.id can be undefined
and you already handle that with ?? null; remove the cast and use
paykitCustomerId: c.user?.id ?? null in the customerSample construction so the
type accurately reflects possible undefined/null values when mapping
customers.data.
- Around line 237-253: The syncProducts method lacks tests and has an unverified
"need testing" note; add unit tests for the syncProducts function to cover:
successful mapping when product.existingProviderProduct.productId exists (assert
returned results include {id, providerProduct:{productId}}), the error branch
when product.existingProviderProduct is missing or productId is null (assert
PayKitError.from is thrown with PAYKIT_ERROR_CODES.PLAN_NOT_SYNCED and the
message contains the product.id), and edge cases such as multiple products and
empty input; locate syncProducts in whop-provider.ts and write tests that call
async syncProducts(data) with crafted data objects verifying both result shape
and thrown error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 79b524f7-04bf-40fc-9847-762f066e6b6f

📥 Commits

Reviewing files that changed from the base of the PR and between a63a823 and 05f7dc6.

📒 Files selected for processing (1)
  • packages/whop/src/whop-provider.ts

Comment thread packages/whop/src/whop-provider.ts
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/whop/src/whop-provider.ts`:
- Around line 213-215: The filter currently accesses sub.user.id directly which
can throw if sub.user is null; update the filtering predicate in the
result.data.filter call to use a null-safe check (e.g., optional chaining or
explicit null guard) comparing sub.user?.id (or sub.user && sub.user.id) to
data.providerCustomerId, so only subscriptions with a non-null user and matching
id pass through, then keep the existing map that returns {
providerSubscriptionId: sub.id } unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0163628e-9205-4d37-a438-ba4e29c826d2

📥 Commits

Reviewing files that changed from the base of the PR and between 05f7dc6 and 2c45151.

📒 Files selected for processing (1)
  • packages/whop/src/whop-provider.ts

Comment thread packages/whop/src/whop-provider.ts
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.

feat(pay): Whop payments

1 participant