OURPAY keeps checkout, customers, orders, subscriptions, invoices, payments, refunds, disputes, fees, and accounting entries in its own provider-neutral domain. Stripe remains the card rail. PayPal can be enabled as a wallet and recurring-payment rail, with every PayPal capture collected in one central Business account controlled by the deployment operator. The organization — whether it represents a company or an individual — remains the customer-facing seller and invoice issuer. OURPAY is identified as the payment collector.

PayPal account model

PayPal is a first-party integration. OURPAY authenticates with the REST app belonging to the operator Business account that receives all customer money. It does not create Partner Referrals, impersonate sellers, add a PayPal partner fee, or ask PayPal to disburse to a seller. Every organization still has a PaymentProcessorAccount so it can enable or disable PayPal and choose its default checkout rail. Those organization-level records all point to the same deployment-managed PayPal credentials. Activating PayPal for an organization authorizes that seller’s checkouts to use the central collection account; it does not connect or settle to the seller’s own PayPal account. This is a central collection arrangement, not PayPal multiparty seller processing. Enabling an organization in OURPAY does not make that organization a PayPal sub-merchant and does not prove that PayPal or a tax authority has approved the operator’s agency arrangement. The deployment operator must obtain the account, contractual, tax, and regulatory approvals required for the countries and products it serves.
Do not enable this model in production merely because live credentials work. PayPal’s current Application Guidelines say the merchant or seller of record must be the primary payment recipient and prohibit payment aggregation. Because this design names the organization as seller while a central OURPAY account receives the funds, treat it as sandbox-only unless PayPal approves this exact arrangement in writing and qualified legal and tax advisers approve it. Without that approval, the commercial model must change: either OURPAY must become the genuine merchant/reseller of record or PayPal funds must flow directly to onboarded seller accounts.

Invoice issuer and tax records

Before PayPal can be enabled, the organization must save its legal invoice name and address under Settings → Payment providers → Invoice issuer. This supports company organizations and individual organizations with the same profile:
  • The saved legal name and address appear as the seller on customer invoices and receipts.
  • Optional tax registrations appear below the seller address.
  • Optional invoice notes appear at the bottom of the document.
  • Every document states that payment was collected by OURPAY on behalf of that seller.
  • The PDF author is the organization, while OURPAY remains the document generator and collector.
The generated PDF is the historical artifact. Changing issuer details changes the invoice checksum for a later explicit regeneration; it never silently substitutes OURPAY’s address under the organization’s name. Legacy records without a complete issuer profile can still be read, but a new PayPal activation, re-enable, checkout, or renewal is rejected before money moves. Tax amounts and jurisdiction breakdowns continue to come from the configured tax provider and are stored on the canonical order. The corresponding provider tax transaction is recorded by the OURPAY deployment as part of its central collection workflow; seller payable excludes collected tax. An organization name on the PDF does not by itself transfer tax registrations, filing duties, or merchant-of-record status. Configure and validate the legal tax treatment for every invoice issuer before taking live payments.
A PayPal Personal account is not sufficient for a live REST app that accepts payments. Use a verified PayPal Business account. The account must be able to receive the currencies offered by your products.

Supported billing lifecycle

  • One-time wallet payments use PayPal Orders v2 and immediate capture.
  • Paid subscription checkouts capture the first payment and save the approved PayPal method.
  • Free trials use a Vault setup token, so no charge is made until the first billing cycle.
  • Renewals use the saved Vault payment token as a merchant-initiated subsequent payment.
  • Full and partial refunds return through the original PayPal capture.
  • PayPal dispute webhooks update the canonical OURPAY dispute and order records.
  • Provider-originated refunds and capture reversals are reconciled even when the operator starts them in PayPal rather than in OURPAY.
  • Capture details store the PayPal payer ID, payer email, and payer name when PayPal supplies them.
  • Every successful checkout follows the normal OURPAY Order, organization-issued invoice number, matching receipt, benefit, ledger, and email pipeline. Initial PayPal orders use the globally unique checkout ID (plus a genuine retry number when needed) as the PayPal purchase-unit invoice ID. Renewals use an ID composed from the OURPAY order ID and the seller-facing invoice number, plus a dunning-attempt suffix after a real failed charge.
  • PayPal’s seller-receivable breakdown remains the authoritative source for processor fees.

Cash versus seller payable

OURPAY deliberately keeps two records that must not be confused:
  • PayPal cash received is the capture’s receivable_amount when PayPal converts currencies, otherwise its net_amount: customer gross minus the PayPal fee and any reported platform fee. That cash belongs to the central operator account until the operator sends a payout.
  • Seller payable is the organization’s internal ledger balance: captured product revenue excluding tax, minus the seller’s configured OURPAY payment and subscription fees, refunds, lost disputes, and any payout transactions already present in the ledger, plus fee credits.
The PayPal capture fee is stored as an operator processor-cost transaction. A PayPal fee returned on a refund is stored as a positive processor-fee credit. Neither is silently passed through to the seller because the published OURPAY transaction fee is the configured seller charge. If that commercial policy changes, change the account fee configuration and ledger rules explicitly instead of deriving seller payables from the PayPal account balance. Finance labels the current liability as Seller Payable. A successful capture does not become a seller payable until the canonical order and balance entries exist. Pending captures and free trials contribute zero. Open disputes do not reduce it until they are lost, so the amount can still change. If the operator has already sent money outside OURPAY, that external transfer is not silently treated as a ledger settlement.

Configure Stripe

Stripe is enabled by default and keeps its existing configuration:
Set OURPAY_STRIPE_ENABLED=false for a PayPal-only deployment.

Configure PayPal

Create a REST app under the operator PayPal Business account that should receive every payment, then set:
Use sandbox app credentials until the full billing flow passes. Change the environment to live and use that same Business account’s live app credentials only when you are ready to accept real money.
Before replacing credentials from an older connected-seller or partner setup, finish or separately reconcile every existing PayPal order, refund, dispute, and disbursement. The central account’s credentials cannot capture or refund an order owned by a different PayPal merchant account.
Turn on Save payment methods for the REST app and obtain PayPal’s required live approval before setting OURPAY_PAYPAL_VAULTING_ENABLED=true. Set OURPAY_PAYPAL_MERCHANT_ID to the receiving Business account’s merchant ID. Both settings are required before OURPAY exposes saved methods, free trials, merchant-initiated renewals, or subscriptions. One-time payments do not require them.
The merchant ID is the PayPal account ID (payer ID), not the REST app client secret. OURPAY disables vaulting and removes the value from public checkout responses when both settings are identical.
OURPAY labels fixed, undiscounted plans as SUBSCRIPTION_PREPAID. Metered, seat-based, unit-based, custom-priced, or discounted plans use RECURRING_PREPAID, and that consent pattern is stored with the vaulted method and reused on every merchant-initiated renewal. Complex plan terms remain visible in OURPAY checkout; PayPal’s approval screen uses its generic recurring flow where a complete fixed billing-plan representation would be inaccurate. PayPal also requires Risk Data Acquisition for customer-initiated transactions that save a PayPal payment method. OURPAY loads FraudNet on PayPal checkout, generates its per-attempt client metadata ID in the buyer’s browser, and sends that same ID to PayPal when it creates the order or setup token. The checkout Content Security Policy allows only the required PayPal FraudNet hosts. Vault and reference-transaction availability is account- and country-dependent, so a successful sandbox flow does not replace PayPal’s live approval. OURPAY_PAYPAL_PAYOUTS_ENABLED should remain false. Seller payout is intentionally a separate, operator-controlled process. Standard Payouts is a different PayPal product and is outside this central checkout collection flow. The current seller-payable ledger is denominated in the organization’s account currency (USD in the standard deployment). OURPAY rejects a PayPal checkout in a different currency before charging the customer rather than inventing an exchange rate or overstating what the seller will receive. It also rejects currencies outside PayPal’s published REST-payment set and fractional HUF, JPY, or TWD amounts, which PayPal does not accept. For local or private gateways, OURPAY_PAYPAL_API_BASE_URL can override the PayPal API host. Leave it unset for PayPal sandbox or live.

Webhooks and return URLs

Register this webhook URL on the PayPal REST app, replacing the host with the public OURPAY API host:
Subscribe it to these implemented events:
  • CHECKOUT.ORDER.APPROVED and CHECKOUT.PAYMENT-APPROVAL.REVERSED
  • PAYMENT.CAPTURE.COMPLETED, PAYMENT.CAPTURE.PENDING, PAYMENT.CAPTURE.DECLINED, PAYMENT.CAPTURE.DENIED, PAYMENT.CAPTURE.REFUNDED, and PAYMENT.CAPTURE.REVERSED
  • PAYMENT.REFUND.PENDING and PAYMENT.REFUND.FAILED
  • CUSTOMER.DISPUTE.CREATED, CUSTOMER.DISPUTE.UPDATED, and CUSTOMER.DISPUTE.RESOLVED
  • VAULT.PAYMENT-TOKEN.CREATED and VAULT.PAYMENT-TOKEN.DELETED
The order-approved event lets OURPAY capture an approved payment even if the buyer closes the browser before returning. OURPAY verifies every webhook through PayPal’s signature-verification endpoint before durably enqueueing it and ignores duplicate PayPal event IDs. Capture and Vault operations also use stable idempotency keys so an uncertain network response can be retried without intentionally creating a second charge or token. A later dunning attempt uses a new key and a new PayPal order, while a transport retry of the same attempt retains its original key. Checkout and Vault approval calls send these return URLs dynamically:

Enable PayPal for an organization

Open Settings → Payment providers and choose Enable PayPal. OURPAY validates the configured invoice-issuer profile, client ID, and secret, creates or refreshes the direct PayPal processor record, and exposes the capabilities allowed by the deployment configuration. No seller PayPal onboarding redirect is involved. When Stripe and PayPal are both active, checkout shows both choices. Selecting a rail locks the checkout to that processor before creating an external order or intent.

Settlement and reporting

PayPal places captures in the central Business account according to PayPal’s normal availability lifecycle. Finance separately shows the seller payable and the sales, configured fees, refunds, disputes, payer identity, and invoice records behind it. Automatic PayPal seller payouts are not offered. Sending seller money and recording that settlement against the payable are intentionally left for the later payout phase, so this release leaves the liability outstanding in OURPAY. Stripe settlements remain independent.

Test safely

  1. Use a PayPal sandbox Business account for the REST app and a separate sandbox Personal account as the buyer.
  2. Enable PayPal under Settings → Payment providers.
  3. Complete a one-time checkout and verify the Payment, Order, invoice, receipt, payer metadata, PayPal gross/fee/net breakdown, and seller-payable ledger entries.
  4. Enable Vaulting, then test a paid subscription, a free trial, and at least one automatic renewal.
  5. Exercise full and partial refunds and a dispute.
  6. Replay a webhook event ID and confirm it does not duplicate a payment, fee, order transition, or seller payable.
  7. Confirm pending captures and free trials add no payable, then confirm each successful refund, capture reversal, and lost dispute reduces seller payable exactly once.
  8. Repeat the checklist with low-value live products before opening normal sales.
See PayPal’s official documentation for REST app setup, Orders v2, saved payment methods, Vault setup tokens, and webhook verification.