Download the PHP package sassydigitizing/whop-integration without Composer
On this page you can find all versions of the php package sassydigitizing/whop-integration. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download sassydigitizing/whop-integration
More information about sassydigitizing/whop-integration
Files in sassydigitizing/whop-integration
Package whop-integration
Short Description Whop payment integration: server-side checkout/plan/product creation, Standard-Webhooks-spec signature verification, and payment re-confirmation. Framework-agnostic — the library takes plain constructor arguments, no env/config coupling.
License MIT
Informations about the package whop-integration
sassydigitizing/whop-integration
A small, framework-agnostic PHP library for Whop payments: server-side checkout/plan/product creation, Standard-Webhooks-spec signature verification, and payment re-confirmation. Every class takes plain constructor arguments — no env-loading, no framework coupling, no database requirement in the library itself.
Ships with a reference implementation (bootstrap.php, webhooks/whop.php,
public/*.php) showing one way to wire it end-to-end, meant to be copied and
adapted into your own app rather than depended on directly.
Installation
This package isn't published on Packagist. Install it either as a local path dependency (fastest, no hosting needed) or from your own git remote.
Path repository (the package lives on the same machine / same monorepo):
VCS repository (once you've pushed this to a git host — GitHub, GitLab, a private Bitbucket, etc.):
Either way, only src/ (the actual library, namespace
SassyDigitizing\WhopIntegration\) gets installed as a dependency —
vlucas/phpdotenv and PHPUnit are require-dev only and won't be pulled in
by consumers. The reference files (bootstrap.php, webhooks/, public/)
land in vendor/sassydigitizing/whop-integration/ for reference; copy what
you need into your own app rather than executing them from inside vendor/.
For the complete step-by-step setup (sandbox and production Whop accounts,
webhook registration, wiring into an existing app's database) see
docs/WHOP_INTEGRATION_GUIDE.md —
this README covers the library API; that guide covers the end-to-end process.
Quick start
$apiBase/$checkoutBase are just strings — point them at
https://api.whop.com/api/v1 + /api/v2 for production, or
https://sandbox-api.whop.com/api/v1 + /api/v2 for sandbox. Nothing in the
library cares which; that decision lives entirely in your own config.
Library reference
| Class | Method | Whop endpoint |
|---|---|---|
WhopWebhookVerifier |
verify(string $rawBody, array $headers): bool |
— (local HMAC check) |
WhopApiClient |
get(string $url): array / post(string $url, array $body): array |
any |
WhopProductService |
createProduct(string $title): array |
POST /products |
WhopPlanService |
createOneTimePlan(string $productId, float $amount, string $currency = 'usd'): array |
POST /plans |
WhopCheckoutService |
createCheckoutSession(string $planId, string $orderRef, string $redirectUrl): array |
POST /checkout_sessions |
WhopInvoiceService |
createInvoice(lineItems, currency, emailAddress, customerName, dueDate, productId?, productTitle?): array / getInvoice(string $invoiceId): array |
POST /invoices, GET /invoices/{id} |
WhopPaymentLookup |
getPayment(string $paymentId): array |
GET /payments/{id} |
Logging\Logger |
info(string $event, array $context = []) / error(...) |
— (redacts secret-shaped keys automatically) |
WhopApiClient throws typed exceptions you can catch individually:
WhopAuthException (401/403), WhopNotFoundException (404),
WhopValidationException (422), WhopRateLimitException (429, after
retries), WhopServerException (5xx, after retries) — all extend
WhopApiException.
Running the tests
All 46 tests run against fakes — no live network calls, no database.
Reference implementation
Everything below describes the example app shipped alongside the library
(bootstrap.php, webhooks/whop.php, public/*.php) — useful to see a
complete, working, tested wiring before adapting it into your own project.
Important: no database, dummy data only
The reference app uses no database and no file storage — by design, for
this reference build specifically (your own integration should use real
persistence; see the integration guide, §5.4).
SassyDigitizing\WhopIntegration\Data\DummyOrderStore and DummyWebhookEventStore
hold orders and webhook-idempotency records in a plain PHP array:
- State lives only for the lifetime of one PHP process. Each real HTTP
request (
checkout.php,webhooks/whop.php,order-status.php) gets a fresh, empty store, so an order created bycheckout.phpwill not be visible towebhooks/whop.phpwhen Whop calls it back. - Everything is fully exercised and correct within a single process — see the PHPUnit tests, and "Try it locally" below.
- Before production: implement a real repository with the same method
signatures (
create,findByRef,findByWhopPaymentId,markPaid,markStatus/alreadyProcessed,insert,markProcessed) backed by your database, and pass instances of those intoOrderService/webhooks/whop.phpinstead. Nothing else needs to change.
Setup
WHOP_COMPANY_ID must be the real biz_... ID from your dashboard URL
(whop.com/dashboard/biz_XXXXXXXX/...) — not an app_... ID.
Set WHOP_SANDBOX=true to point both api_base and checkout_base at
Whop's sandbox host in one flag — see config/whop.php. WHOP_API_BASE /
WHOP_CHECKOUT_BASE, if set, always override the flag.
Try it locally
Expect 200 {"status":"ok"}. Check logs/whop.log for the structured log line.
For real end-to-end testing against Whop, expose this endpoint via
ngrok http 8080, register that URL plus the events in
docs/WHOP_INTEGRATION_GUIDE.md §3.6 in the Whop dashboard, and use Whop's
webhook test-send feature or a real sandbox payment.
How checkout works
Two ways to call public/checkout.php:
Fixed price: ?plan_id=plan_xxx&product_id=prod_xxx&[email protected]
Dynamic price: ?product_id=prod_xxx&amount=25.50&[email protected]
(optional ¤cy=usd). Creates a one-time-price plan on the fly via
WhopPlanService, then proceeds like the fixed-price path.
Either way: creates a local (dummy) PENDING order, calls the Whop API to
create a checkout session, redirects to purchase_url. Whop redirects back
to checkout-return.php after payment — that page never treats the
redirect itself as proof of payment; only a verified payment.succeeded
webhook (or, for the return page's own UX, a direct server-side
WhopPaymentLookup re-check) does.
Files
Security notes
- Webhook signature verification uses the raw request body,
hash_equals(constant-time), and rejects timestamps more than 5 minutes old — seeWhopWebhookVerifier. WHOP_API_KEY/WHOP_WEBHOOK_SECRETare never logged (Loggerredacts any context key containingsecret,password,signature,api_key,authorization).- Order fulfillment only happens after signature verification AND a plan-id
match between the webhook payload and the locally stored pending order —
see
OrderService::handlePaymentSucceeded. .envis git-ignored; only.env.example(placeholders) is committed — verify this every time before pushing; it's the easiest way to leak a live key.
License
MIT — see LICENSE.
All versions of whop-integration with dependencies
ext-curl Version *
ext-json Version *