Skip to main content
Payframes lets you own the donation form while card details are collected inside secure embedded fields. Your page receives tokenized card values, and your server uses a secret key to process the donation. Tokenization alone never charges a card. Before starting, enable access, register your website origin, and install the SDK. Use matching test publishable and secret keys from your organization.

How the flow works

  1. Your backend creates a donation attempt and records the donor-authorized amount, currency, and attribution.
  2. Your browser mounts Payframes with the publishable key and collects donor and billing details outside the secure card fields.
  3. Payframes tokenizes the card. Your page sends the returned values and fraud session to your backend over HTTPS.
  4. Your backend validates the attempt, stores its exact processing request, and calls the WeGive API with its secret key and stable idempotency key.
  5. Your application records the returned transaction ID and state, then shows success, pending, or an appropriate failure/reconciliation state.
There is no browser-side SDK charge method. Never call the secret-key processing API directly from client JavaScript.

Mount the form

This form assumes your server renders a unique attempt ID and CSRF token into the placeholders. Adapt authentication and CSRF protection to your framework. The amount comes from your backend’s attempt record, not an untrusted hidden input.
After loading the SDK, run this browser code. /donation-attempts/submit is your application’s route, not a WeGive endpoint. The response shape used here is also an example contract for your own backend.
Once submitted, keep the form from creating a second attempt while the first outcome is unknown. Your backend should offer a way to retrieve its saved attempt state after a reload. Only offer a fresh attempt after confirming that it will not duplicate the donor’s payment. Remove your listeners and call fields.destroy() when leaving the form; see asynchronous cleanup.

Implement your backend route

Your route should:
  1. Authenticate or otherwise validate the donor’s authorized checkout session, apply CSRF protection where applicable, and load its server-side attempt.
  2. Verify that the attempt belongs to this checkout and that its donation choices are allowed. Do not trust client-supplied amount, customer IDs, or attribution IDs.
  3. Atomically claim an unsubmitted attempt so two requests cannot both start it. For an existing attempt, return its saved state or reconcile its existing request.
  4. Build an inline charge or a by-reference charge as described in the API reference.
  5. Save the exact serialized request, endpoint, original browser User-Agent, secret-key identifier, and idempotency key before submitting it. Keep sensitive request material in protected server-side storage, out of ordinary logs.
  6. Send the request, record the response, and return a minimal result to the page. A timeout or 5xx response must leave the attempt unresolved until reconciled.
Forward the initiating browser’s User-Agent on processing requests and preserve it for retries so the request retains its checkout context. Do not replace it with your HTTP client’s default agent. Do not accept arbitrary client-supplied forwarding headers as trusted IP identity. For the inline path, map tokenized.cardNumber, cardExpiration, and cardCvv into the API’s tokens object, and place tokenized.fraudSessionId at the top level. Donor details go into donor; billing name and postal code go into cardholder. The backend supplies amount, currency, frequency, and approved attribution. Payframes does not add attribution to your server request automatically: validate and forward the values returned by getAttribution(). Do not log credentials, raw card data, tokenized payment values, fraud-session handles, or full request bodies. Retain the transaction ID, attempt ID, timestamp, and sanitized error information for support and reconciliation.

Field styling and validation

Host-page CSS controls the containers; it cannot style inside the secure frames. Use the mount call’s style object for field CSS. The SDK also reads these CSS variables from your page at mount time:
Styles are resolved when fields mount. For a changed theme, destroy and remount the fields, allowing the donor to re-enter their details. ready() means the fields mounted; use isValid() before tokenizing and still handle tokenization or processing failures. Test keyboard navigation, labels, zoom, and mobile layouts.

Recurring donations and bank methods

For recurring donations, create a customer, profile, and payment method, then call POST /api/pay/recurring-plans. This can take the first payment immediately. Do not separately create a one-time transaction for the same initial payment. See recurring plans. Payframes exposes card fields. The processing API accepts bank methods collected through an approved bank-tokenization integration; it does not provide a bank field mount method in this SDK. Use the hosted pop-up for its enabled bank flow or contact WeGive to configure your custom bank integration. Never substitute ordinary browser inputs that send raw bank details through your backend.