Choose your integration
Before you start
Both paths need the same three things:- A verified payment method domain. Wallets open only on pages whose domain you registered and verified with Whop. Follow Enable Apple Pay and Google Pay once per domain. Pages on whop.com are pre-approved.
- An
httpspage. Apple and Google require a secure page for their sheets, andreturnUrlmust behttpstoo (httponly on localhost). - A device with a wallet. Both paths show only the wallets the buyer’s device can pay with, so test on a real device with a wallet set up, not in a simulator.
- Payment request
- Express checkout element
PaymentRequest is the wallet sheet without an element. You render the button, name the amount, and answer the sheet’s shipping and billing changes. The sheet hands back a confirmation token that your server confirms with the Payments API.Step 1: Create the request and check availability
Create the request with your account, the currency, and the amount in minor units. AwaitcanMakePayment() before you show a button. It reports which wallets this device, this account, and this domain can pay with, and it primes the sheet.Apple and Google each require their own button artwork on a custom button. Follow the Apple Pay button guidelines and the Google Pay brand guidelines.
Step 2: Open the sheet from your button
Callshow(type) first thing in the button’s event handler, before any await. Apple refuses a sheet opened outside that user gesture, which is why canMakePayment() ran ahead of time. The sheet asks for the buyer’s email unless you pass one: show("apple_pay", { email }) fills it from a field your page already collected.show resolves with the result once the buyer authorizes:A buyer who dismisses the sheet rejects
show with a payment_request_cancelled error and fires onCancel. The sheet closes with a checkmark as soon as the token mints, before your server confirms, so show your server’s result on your page.Step 3: Confirm the payment on your server
Create the payment with the confirmation token. Whop resolves the buyer from the token’s email, charges the plan, and returns the payment with aclient_secret the browser uses to finish any pending step.amount is in minor units, so 1000 on the sheet is an initial_price of 10.0 here. Pass plan_id for a plan you already created, or an inline plan to find or create one for this payment. metadata comes back on the payment and its webhook, which is how you tie the charge to your own order. For physical goods, send the result’s shipping.address along with the token and pass it as shipping_address. Its recipient becomes name. The line1, line2, city, state, postal_code, and country fields keep their names.Step 4: Finish the payment
A payment that comes backpaid is done. Any other status means the buyer still has a step, such as 3D Secure, or the charge is still being decided. Pass the payment’s client_secret to handleNextAction. It runs an inline step in a dialog and resolves with redirected: false, or sends the buyer to your returnUrl and resolves with redirected: true. Branch on the status it returns: succeeded is paid, processing is still being decided, and anything else needs another try. A dismissed dialog leaves the payment at requires_action with no error, so a missing lastPaymentError isn’t success.Whether the buyer pays inline or comes back through returnUrl, fulfill from the payment.succeeded webhook below, never from the browser.Collect a shipping address
SetrequestShipping to ask the sheet for a shipping address and offer shippingOptions. The sheet reports each change with a redacted address (city, state, postal code, and country) before authorization. Answer every change with updateWith exactly once, or the sheet stalls until the wallet times it out. The resource doesn’t calculate shipping: your handler sets the new amount.shipping.address is the full address once the buyer authorizes, and shipping.option is the option they picked. onBillingAddressChange works the same way for tax: it fires at sheet open and on card switches with the redacted billing address, and you answer updateWith({ amount }) or updateWith({}) to keep the total.For every option, method, and event, see the PaymentRequest reference.Handle payment webhooks
Fulfill orders from thepayment.succeeded webhook on your server, never from the browser. A wallet payment reports apple_pay or google_pay in payment_method_type, and the metadata you attached comes back on the event. The accept payments guide shows a handler and a sample payload.
Next steps
Accept payments
Checkout links, the Checkout element, and the payment elements
Enable Apple Pay and Google Pay
Verify your domain as a payment method domain
Webhooks
Handle payment events in real-time
Appearance
Theme the elements to match your site

