Skip to main content
RapidDev - Software Development Agency
lovable-integrationsEdge Function Integration

How to Integrate Lovable with Worldpay

Integrating Worldpay with Lovable uses Edge Functions to create payment sessions via the Worldpay Access Worldpay API. Store your entity credentials (username and password) in Cloud Secrets, create an Edge Function to generate checkout sessions, embed Worldpay's hosted payment page or Access Checkout component, then verify webhook notifications for payment confirmation. Setup takes 40 minutes.

What you'll learn

  • How to authenticate with Worldpay's Access Worldpay API using entity credentials
  • How to create Worldpay checkout sessions via a Supabase Edge Function
  • How to integrate Worldpay's Access Checkout SDK in a React component
  • How to handle Worldpay webhook notifications for payment confirmation
  • How to use Worldpay's sandbox environment for end-to-end testing
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate16 min read40 minutesPaymentMarch 2026RapidDev Engineering Team
TL;DR

Integrating Worldpay with Lovable uses Edge Functions to create payment sessions via the Worldpay Access Worldpay API. Store your entity credentials (username and password) in Cloud Secrets, create an Edge Function to generate checkout sessions, embed Worldpay's hosted payment page or Access Checkout component, then verify webhook notifications for payment confirmation. Setup takes 40 minutes.

Why integrate Worldpay with Lovable?

Worldpay, owned by FIS (Fidelity National Information Services), processes more card transactions than any other company in the world — handling over 40 billion transactions annually for clients ranging from major UK high-street banks to global retailers and airlines. If you're building a Lovable application for an enterprise client or financial institution that already uses Worldpay as their payment processor, Worldpay integration is often a contractual requirement. UK banks like Barclays and HSBC have long-standing Worldpay relationships, making it the default gateway for many enterprise projects.

For Lovable developers, Worldpay is most relevant when working with enterprise clients in banking, retail, or airlines that have established Worldpay merchant relationships, when building in the UK market where Worldpay has dominant market share, or when the client needs features like Worldpay's fraud management tools (Advanced Risk Management), multi-currency acquiring in 40+ currencies, or unified reporting across physical and digital channels.

Worldpay's Access Worldpay API (their modern API platform) is session-based: your Edge Function creates a checkout session which is used to initialize the Access Checkout JavaScript SDK. The SDK renders a secure card collection form, tokenizes the card data, and processes the payment through Worldpay's acquiring network. Worldpay then sends webhook notifications to your server confirming the payment outcome.

Integration method

Edge Function Integration

Worldpay has no native Lovable connector. Integration requires Supabase Edge Functions to create payment sessions via the Worldpay Access Worldpay API, using entity credentials (service account username and password) for authentication. Sessions are passed to Worldpay's Access Checkout SDK for frontend card collection. Webhook notifications confirm payment outcomes and are verified server-side before updating Supabase.

Prerequisites

  • A Lovable project with Cloud enabled
  • A Worldpay sandbox account — request at developer.worldpay.com/docs/access-worldpay/sandbox
  • Your Worldpay entity credentials: service account username (entity ID) and password from the Worldpay Business Gateway
  • Your Worldpay merchant entity reference (provided by Worldpay when your account is set up)
  • Basic understanding of Worldpay's account structure: entities, merchant codes, and service accounts

Step-by-step guide

1

Obtain Worldpay credentials and configure Cloud Secrets

Worldpay's Access Worldpay API uses 'entity credentials' — a service account username and password that represent your merchant entity. Unlike OAuth flows, these credentials are permanent until rotated. You'll receive your sandbox credentials when Worldpay provisions your test account. If you're working with an existing merchant, their Worldpay account administrator can create API credentials in the Worldpay Business Gateway under Administration → API credentials. Your credentials package from Worldpay will include: the entity (merchant) username formatted as your-entity@worldpay.com or similar, the entity password, your merchant entity code (used in API calls), and the service endpoint. For sandbox, the API base URL is https://try.access.worldpay.com. For production, it's https://access.worldpay.com. In your Lovable project, open Cloud tab → Secrets and add: WORLDPAY_USERNAME (your entity username), WORLDPAY_PASSWORD (your entity password), WORLDPAY_MERCHANT_ENTITY_REF (your merchant entity reference code), and WORLDPAY_ENVIRONMENT set to 'sandbox' or 'production'. These credentials authenticate every API call — they must never be exposed in frontend code.

Pro tip: Worldpay credentials are issued per merchant entity. If you're building for a client, they need to create API credentials in their Worldpay Business Gateway and share them with you — never use your own test credentials in their production account.

Expected result: WORLDPAY_USERNAME, WORLDPAY_PASSWORD, WORLDPAY_MERCHANT_ENTITY_REF, and WORLDPAY_ENVIRONMENT stored in Cloud Secrets.

2

Create an Edge Function to generate Worldpay checkout sessions

In Lovable's Code panel, create supabase/functions/worldpay-session/index.ts. This function authenticates with Worldpay and creates a checkout session for a specific payment amount. The Worldpay Access Worldpay API uses HTTP Basic Auth with entity credentials for all requests. The checkout session creation endpoint is POST https://try.access.worldpay.com/sessions/payment-sessions (sandbox) or https://access.worldpay.com/sessions/payment-sessions (production). The request body is a JSON object with value (payment amount details: amount in minor currency units and currencyCode), merchant (containing entityRef — your merchant entity reference), and paymentInstructions (describing what's being paid for). Worldpay returns a 201 Created response with a _links object containing a 'sessions:session' href. This href is the session URL you pass to the Access Checkout SDK. It's safe to pass to the frontend — it's a one-time-use reference that can only be used to complete the specific payment session it represents. Store the session href alongside your order in Supabase so you can track pending payments and expire them if uncompleted.

Lovable Prompt

Create a Supabase Edge Function at supabase/functions/worldpay-session/index.ts. Accept POST requests with JSON body containing amountInMinorUnits (integer), currencyCode (ISO 3-letter code), and orderId. Call the Worldpay sandbox session endpoint https://try.access.worldpay.com/sessions/payment-sessions using Basic Auth with WORLDPAY_USERNAME and WORLDPAY_PASSWORD from Deno.env.get(). Include the WORLDPAY_MERCHANT_ENTITY_REF in the merchant.entityRef field. Return the session href from response._links['sessions:session'].href. Include CORS headers.

Paste this in Lovable chat

supabase/functions/worldpay-session/index.ts
1import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
2
3const USERNAME = Deno.env.get("WORLDPAY_USERNAME") ?? "";
4const PASSWORD = Deno.env.get("WORLDPAY_PASSWORD") ?? "";
5const MERCHANT_ENTITY_REF = Deno.env.get("WORLDPAY_MERCHANT_ENTITY_REF") ?? "";
6const ENVIRONMENT = Deno.env.get("WORLDPAY_ENVIRONMENT") ?? "sandbox";
7
8const BASE_URL = ENVIRONMENT === "production"
9 ? "https://access.worldpay.com"
10 : "https://try.access.worldpay.com";
11
12const corsHeaders = {
13 "Access-Control-Allow-Origin": "*",
14 "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
15};
16
17serve(async (req) => {
18 if (req.method === "OPTIONS") {
19 return new Response("ok", { headers: corsHeaders });
20 }
21
22 try {
23 const { amountInMinorUnits, currencyCode = "GBP", orderId } = await req.json();
24 const authString = btoa(`${USERNAME}:${PASSWORD}`);
25
26 const payload = {
27 transactionReference: orderId,
28 merchant: { entityRef: MERCHANT_ENTITY_REF },
29 value: { amount: amountInMinorUnits, currency: currencyCode },
30 paymentInstructions: [
31 {
32 narrative: { line1: "Payment" },
33 value: { amount: amountInMinorUnits, currency: currencyCode },
34 paymentMethod: {
35 type: "card/plain",
36 cardHolderName: "{{ cardHolderName }}",
37 cardNumber: "{{ encryptedCardNumber }}",
38 cardExpiryDate: { month: "{{ expiryMonth }}", year: "{{ expiryYear }}" },
39 cvv: "{{ encryptedCvv }}",
40 },
41 },
42 ],
43 };
44
45 const res = await fetch(`${BASE_URL}/sessions/payment-sessions`, {
46 method: "POST",
47 headers: {
48 "Authorization": `Basic ${authString}`,
49 "Content-Type": "application/vnd.worldpay.sessions-v1.hal+json",
50 "Accept": "application/vnd.worldpay.sessions-v1.hal+json",
51 },
52 body: JSON.stringify(payload),
53 });
54
55 if (!res.ok) {
56 const err = await res.text();
57 throw new Error(`Worldpay error: ${res.status} ${err}`);
58 }
59
60 const data = await res.json();
61 const sessionHref = data._links?.["sessions:session"]?.href;
62
63 return new Response(
64 JSON.stringify({ sessionHref }),
65 { headers: { ...corsHeaders, "Content-Type": "application/json" } }
66 );
67 } catch (e) {
68 return new Response(
69 JSON.stringify({ error: (e as Error).message }),
70 { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
71 );
72 }
73});

Pro tip: Worldpay sessions have a 60-minute expiry. If your checkout flow takes longer (e.g., the user leaves and returns), generate a new session. Store the session creation timestamp in Supabase alongside the order so you can detect and refresh expired sessions.

Expected result: Edge Function deployed and returning a Worldpay session href when called with order details.

3

Integrate the Worldpay Access Checkout SDK

Worldpay's Access Checkout SDK is a JavaScript library that uses the session href to initialize a secure payment form. Add the Access Checkout script to your index.html. For sandbox, the CDN URL is https://try.access.worldpay.com/access-checkout/v2/checkout.js. For production, it's https://access.worldpay.com/access-checkout/v2/checkout.js. The SDK creates three input fields — card number, expiry date, and CVV — as iframes within containers you specify. These iframes are hosted on Worldpay's domain, so card data never touches your app's JavaScript context. Initialize the SDK with AccessCheckout.init() passing the session href and callbacks for onPaymentStarted and onPaymentVerified. The SDK handles all card input formatting, validation, and encryption internally. Create a React component with three div containers (for card number, expiry, CVV) and a Pay button. On mount, call your worldpay-session Edge Function to get a session href, then initialize AccessCheckout with that href. When the user clicks Pay, call the SDK's generateSessions() method. The SDK collects and tokenizes the card data, creates a Worldpay checkout session, and triggers the payment. Your webhook Edge Function receives the payment outcome.

Lovable Prompt

Create a WorldpayCheckout React component. Add the Access Checkout sandbox CDN to index.html head. The component should: 1) call the worldpay-session Edge Function on mount with the order amount in minor units, 2) once the session href is received, initialize window.AccessCheckout.init() with the session href, containers for #card-number-container, #expiry-date-container, #cvc-container, 3) show a Pay button that calls generateSessions() on the Access Checkout instance, 4) handle onPaymentVerified to show success state and onPaymentError for error state, 5) style containers with Tailwind border styling for the iframe inputs.

Paste this in Lovable chat

src/components/WorldpayCheckout.tsx
1import { useEffect, useRef, useState } from "react";
2import { supabase } from "@/integrations/supabase/client";
3import { Button } from "@/components/ui/button";
4import { toast } from "@/hooks/use-toast";
5
6declare global {
7 interface Window {
8 AccessCheckout: {
9 init: (options: Record<string, unknown>) => Promise<AccessCheckoutInstance>;
10 };
11 }
12}
13
14interface AccessCheckoutInstance {
15 generateSessions: (sessionTypes: string[]) => void;
16}
17
18interface WorldpayCheckoutProps {
19 amountInMinorUnits: number;
20 currencyCode?: string;
21 orderId: string;
22 onSuccess: () => void;
23}
24
25export function WorldpayCheckout({ amountInMinorUnits, currencyCode = "GBP", orderId, onSuccess }: WorldpayCheckoutProps) {
26 const checkoutRef = useRef<AccessCheckoutInstance | null>(null);
27 const [ready, setReady] = useState(false);
28 const [loading, setLoading] = useState(false);
29
30 useEffect(() => {
31 async function init() {
32 const { data, error } = await supabase.functions.invoke("worldpay-session", {
33 body: { amountInMinorUnits, currencyCode, orderId },
34 });
35 if (error || !data?.sessionHref) {
36 toast({ title: "Checkout error", description: "Could not initialize payment", variant: "destructive" });
37 return;
38 }
39 checkoutRef.current = await window.AccessCheckout.init({
40 checkoutId: data.sessionHref,
41 containerId: "worldpay-form",
42 components: ["card"],
43 onPaymentVerified: () => { setLoading(false); onSuccess(); },
44 onPaymentError: (err: { message: string }) => {
45 setLoading(false);
46 toast({ title: "Payment failed", description: err.message, variant: "destructive" });
47 },
48 styles: {
49 base: { fontSize: "16px", color: "#374151", "::placeholder": { color: "#9CA3AF" } },
50 },
51 });
52 setReady(true);
53 }
54 init();
55 }, [amountInMinorUnits, currencyCode, orderId, onSuccess]);
56
57 const handlePay = () => {
58 if (!checkoutRef.current) return;
59 setLoading(true);
60 checkoutRef.current.generateSessions(["card", "cvv"]);
61 };
62
63 return (
64 <div className="max-w-md mx-auto p-6 bg-white rounded-xl shadow space-y-4">
65 <h2 className="text-xl font-semibold">
66 Pay {currencyCode} {(amountInMinorUnits / 100).toFixed(2)}
67 </h2>
68 <div id="worldpay-form" className="space-y-3">
69 <div id="card-number-container" className="border rounded-md p-3 min-h-[44px]" />
70 <div className="flex gap-3">
71 <div id="expiry-date-container" className="border rounded-md p-3 min-h-[44px] flex-1" />
72 <div id="cvc-container" className="border rounded-md p-3 min-h-[44px] w-24" />
73 </div>
74 </div>
75 <Button onClick={handlePay} disabled={!ready || loading} className="w-full">
76 {loading ? "Processing..." : "Pay Now"}
77 </Button>
78 </div>
79 );
80}

Pro tip: The Access Checkout SDK creates iframes inside your div containers. The divs must exist in the DOM before calling AccessCheckout.init(). Use a loading state to defer SDK initialization until the component has fully mounted.

Expected result: Worldpay card input iframes rendered inside the container divs. Card fields accept input with proper formatting. Clicking Pay triggers the SDK's payment flow.

4

Handle Worldpay webhook notifications

Worldpay sends HTTP POST webhook notifications (called 'notifications' or 'events') to your specified endpoint when payment events occur. Create a Supabase Edge Function to receive these and update your orders table. Set up webhook notifications in the Worldpay Business Gateway under Administration → Notifications. Provide your Supabase Edge Function URL as the notification endpoint. Worldpay sends notifications for events including payment.authorized, payment.refused, and payment.cancelled. The payload contains the transactionReference (your order ID) and the outcome. Worldpay notification payloads can be sent via XML or JSON depending on configuration. The modern Access Worldpay API sends JSON. Your Edge Function should verify the notification is from Worldpay — Worldpay recommends IP allowlisting or a shared secret in the notification URL path as authentication. Check the event type and update the corresponding order in Supabase. For complex Worldpay integrations involving 3DS2, multi-currency, or batch reconciliation, RapidDev's team can help configure the full notification workflow.

Lovable Prompt

Create a Supabase Edge Function at supabase/functions/worldpay-webhook/index.ts. Accept POST requests with Worldpay notification JSON. Parse the transactionReference as orderId and the event type. For payment.authorized events, update the order in Supabase to status 'paid' using the service role key. For payment.refused or payment.cancelled, update to 'failed'. Return HTTP 200 with empty body. Include CORS headers.

Paste this in Lovable chat

supabase/functions/worldpay-webhook/index.ts
1import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
2import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
3
4const SUPABASE_URL = Deno.env.get("SUPABASE_URL") ?? "";
5const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? "";
6
7const corsHeaders = {
8 "Access-Control-Allow-Origin": "*",
9 "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
10};
11
12serve(async (req) => {
13 if (req.method === "OPTIONS") {
14 return new Response("ok", { headers: corsHeaders });
15 }
16
17 try {
18 const notification = await req.json();
19 const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
20
21 const orderId = notification.transactionReference;
22 const eventType = notification.type ?? notification.eventName ?? "";
23
24 if (!orderId) {
25 return new Response("ok", { headers: corsHeaders });
26 }
27
28 let newStatus = "";
29 if (eventType.includes("authorized") || eventType === "payment.authorized") {
30 newStatus = "paid";
31 } else if (eventType.includes("refused") || eventType.includes("cancelled")) {
32 newStatus = "failed";
33 }
34
35 if (newStatus) {
36 await supabase.from("orders").update({
37 status: newStatus,
38 worldpay_notification: notification,
39 }).eq("id", orderId);
40 }
41
42 return new Response("ok", { status: 200, headers: corsHeaders });
43 } catch (e) {
44 console.error("Worldpay webhook error:", e);
45 return new Response("ok", { status: 200, headers: corsHeaders }); // Always return 200 to prevent retries
46 }
47});

Pro tip: Always return HTTP 200 to Worldpay webhooks even if your processing fails — a non-200 response causes Worldpay to retry the notification multiple times over several hours. Log errors for async investigation instead.

Expected result: Webhook Edge Function deployed. URL configured in Worldpay Business Gateway. Test notifications from Worldpay (if available) result in order status updates in Supabase.

Common use cases

Enterprise retail checkout with Worldpay acquiring

A large UK retailer building a new digital storefront integrates Worldpay because their bank-provided merchant account routes through Worldpay's acquiring network. The Edge Function creates a Worldpay checkout session, the frontend Access Checkout SDK collects and tokenizes card data, and the webhook confirms payment authorization. The retailer keeps their existing bank relationship and favorable interchange rates while gaining a modern web storefront.

Lovable Prompt

Add a Worldpay checkout to the product purchase page. Create an Edge Function that authenticates with Worldpay using entity credentials and creates a checkout session with the order amount and currency. Return the session href to the frontend. Initialize the Worldpay Access Checkout SDK with the session URL and mount it to a payment form div. When the user submits payment, Worldpay handles card collection and sends a webhook. Create a webhook Edge Function that updates the order status in Supabase to 'paid' when the payment.authorized event is received.

Copy this prompt to try it in Lovable

Airline ancillary services payment portal

An airline partner builds a Lovable app for booking ancillary services (seat upgrades, baggage, lounge access) that integrates with the airline's existing Worldpay merchant account. Multiple currencies are supported for international passengers. The Edge Function creates sessions in the passenger's currency, Worldpay handles Dynamic Currency Conversion where applicable, and payments are reconciled against the airline's existing Worldpay reporting.

Lovable Prompt

Build a payment portal for airline ancillary services. Accept amounts in multiple currencies (USD, EUR, GBP) based on the passenger's home country stored in their profile. Create an Edge Function that creates a Worldpay session with the currency code from the passenger's profile. On successful webhook notification, update the booking record in Supabase and trigger a confirmation email with the Worldpay transaction reference for reconciliation.

Copy this prompt to try it in Lovable

Subscription management for enterprise software

An enterprise B2B software platform uses Worldpay for annual subscription billing. The Edge Function creates a Worldpay payment session for the annual invoice amount, the enterprise buyer's finance team completes payment via their corporate card, and Worldpay's Level 2 and Level 3 data processing reduces interchange costs on B2B card transactions. The webhook confirms payment and activates the annual subscription.

Lovable Prompt

Implement annual subscription payment with Worldpay. When an enterprise customer approves an annual invoice, create a Worldpay session for the invoice amount in their currency. Email the payment link to the billing contact. Track session expiry and send reminder emails if payment is not completed within 24 hours. On webhook confirmation of payment, mark the subscription as active for 12 months in Supabase and generate a VAT invoice PDF.

Copy this prompt to try it in Lovable

Troubleshooting

Session creation returns 401 Unauthorized or 403 Forbidden

Cause: Entity credentials are incorrect, the merchant entity reference doesn't match the credentials, or the account is not provisioned for the Access Worldpay API (some older Worldpay accounts use the legacy API).

Solution: Verify WORLDPAY_USERNAME and WORLDPAY_PASSWORD in Cloud Secrets match exactly what Worldpay issued. The username format varies — it may look like your-entity-code@service.worldpay.com or a UUID. Confirm with your Worldpay account manager that your account has Access Worldpay API access enabled. Some merchant accounts default to the legacy Worldpay Online Payments API which uses different credentials and endpoints.

Access Checkout SDK iframes don't appear inside the container divs

Cause: The Worldpay Access Checkout JS script hasn't loaded before AccessCheckout.init() is called, the container div IDs don't match what the SDK expects, or the session href is malformed.

Solution: Confirm the Worldpay Access Checkout CDN script is in index.html head (not deferred). Log data.sessionHref from your Edge Function response — it should be a URL starting with https://try.access.worldpay.com or https://access.worldpay.com. Verify your container IDs exactly match what you pass to the SDK's containerId option. The containers must exist in the DOM at the time init() is called.

Webhook notifications not arriving at the Edge Function

Cause: The webhook URL in the Worldpay Business Gateway points to the wrong endpoint, or the Edge Function URL wasn't deployed before configuring the webhook.

Solution: In Lovable's Cloud tab → Logs, check that the worldpay-webhook function appears as deployed. Copy the function URL (format: https://{project-ref}.supabase.co/functions/v1/worldpay-webhook) and update it in Worldpay Business Gateway → Administration → Notifications. Test by triggering a test transaction through the Worldpay sandbox interface if available, or check Cloud tab → Logs for any recent invocations.

Payment session endpoint returns 422 Unprocessable Entity

Cause: The request body structure or Content-Type header doesn't match Worldpay's HAL+JSON format. Worldpay's Access API requires a specific Content-Type header and JSON structure that differs from typical REST APIs.

Solution: Ensure the Content-Type header is set to 'application/vnd.worldpay.sessions-v1.hal+json' (not plain 'application/json'). Also set the Accept header to the same HAL+JSON content type. Verify the amount is an integer (minor currency units, not decimal) and currencyCode is an uppercase ISO 4217 code like 'GBP' or 'USD'.

typescript
1headers: {
2 "Authorization": `Basic ${authString}`,
3 "Content-Type": "application/vnd.worldpay.sessions-v1.hal+json",
4 "Accept": "application/vnd.worldpay.sessions-v1.hal+json",
5}

Best practices

  • Store all Worldpay credentials (username, password, merchant entity reference) in Cloud Secrets and never include them in frontend code — even the session href should be treated with care as it authorizes a specific payment
  • Generate a new session for each checkout attempt — do not cache session hrefs, as they expire after 60 minutes and represent a specific payment amount that must not be reused
  • Store Worldpay transaction references alongside your order IDs in Supabase — you need these for refunds, dispute responses, and reconciliation with Worldpay reporting
  • Always return HTTP 200 to Worldpay webhook notifications even when your processing logic fails — non-200 responses trigger automatic retries that can cause duplicate processing
  • Use Worldpay's sandbox environment for all development and testing — sandbox credentials are completely separate from production and running test charges against production is a serious compliance violation
  • Convert amounts to minor currency units before sending to Worldpay: £19.99 = 1999, €5.00 = 500. Never send decimal amounts — the API expects integers
  • Test both the happy path and failure scenarios in sandbox: use Worldpay test cards that simulate declined payments, 3DS challenges, and network errors to ensure your error handling works correctly

Alternatives

Frequently asked questions

What's the difference between Worldpay's old XML API and the Access Worldpay API?

Worldpay has two separate API platforms. The legacy XML API (Worldpay Online Payments or WP-XML) is older and uses XML request/response format with different credentials. The Access Worldpay API is their modern REST/JSON platform launched around 2018 with a different authentication model and session-based integration. New integrations should use the Access Worldpay API. If your client has an older Worldpay account, they may need to apply to Worldpay to enable Access API access alongside their existing account.

How do I find Worldpay test card numbers for sandbox testing?

Worldpay provides test card numbers in their developer documentation at developer.worldpay.com. Common test cards include 4444 3333 2222 1111 (Visa, successful transaction), 4444 1111 1111 1113 (Visa, refused), and 4444 3333 2222 1118 (3DS required). Use expiry date 01/30 and CVV 123. Test card behavior in the sandbox is controlled by the card number, not the amount (unlike some other gateways).

Is Worldpay suitable for small businesses?

Worldpay offers SMB-focused products alongside their enterprise platform, but the Access Worldpay API featured in this tutorial is oriented toward mid-market and enterprise. Small businesses may find Stripe or Square more cost-effective with simpler setup. Worldpay's transaction fees and monthly fees for SMBs can be higher than newer fintech gateways. If you're building for a small business that has no existing Worldpay relationship, Stripe is typically the better choice.

Can Worldpay handle recurring payments and subscriptions?

Yes — Worldpay supports stored card tokens (called Recurring Payment Agreements or RPAs) that allow subsequent charges without collecting card details again. During initial payment, request a recurring token from the session response. Use this token reference for future charges via the Worldpay Recurring Payments API. Unlike Stripe Billing or Braintree Subscriptions, Worldpay's recurring system is lower-level and requires you to implement your own billing scheduler.

How do I handle refunds through Worldpay?

Use the Worldpay Order Management API to issue refunds. Call POST https://access.worldpay.com/v1/orders/{orderCode}/refund with the refund amount in minor units. You need the Worldpay order code (returned in the payment notification) to reference the original transaction. Partial refunds are supported. Refunds can take 3-5 business days to appear on the cardholder's statement, which is similar to other payment gateways.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.