Skip to navigation

Collect payments with payment form

Discover comprehensive code samples demonstrating integration with Payment Form. Understand how to swiftly implement hosted payment forms on your website.
View as Markdown

This tutorial builds a working checkout that collects a card payment using Zuora’s hosted Payment Form. Your server mints a short-lived payment session; the browser loads zuora.js, renders the form, and reports the result — all without card data ever touching your backend.

You’ll need a Zuora publishable key (Settings > Payments > Payment Form) and a set of OAuth credentials (client ID and secret) for the server. Test with card 4111 1111 1111 1111.

Walkthrough

Scroll through the steps below. The code panel on the right follows along — switching files and focusing the lines that matter for each step.

1. Quick Start
Configure a Zuora client instance

Set your OAuth client ID and secret, then construct the ZuoraClient against the sandbox environment (SBX).

Review the payment form and copy the publishable key

In the Zuora UI, open Settings > Payments > Payment Form to review your form and copy its publishable key into the client.

Initialize an instance of the Zuora object

Create a Zuora object in the browser with the publishable key you copied.

Run the payment form

Build and start the sample server, then open the checkout page in your browser.

Try it out

Open the checkout page and pay with the Zuora test card to run a payment end to end.

2. Customize
Customize the checkout page

Adjust the order summary markup to match your product and branding.

Customize the return page

Style the page shoppers land on after paying. It displays the returned payment ID.

Handle payment result

The onComplete callback receives the result. Redirect to the return page on success, or surface the error message on failure.

3. Integrate
Import Zuora Java client library to your project

Add the Zuora Java SDK as a Maven dependency. Check Maven Central for the latest version.

Implement support for multi-entity

For multi-entity tenants, scope requests to a specific entity by calling zuoraClient.setEntityId(...) after building the client.

Implement backend API to create a payment session

This endpoint creates an account for the shopper, then creates a payment session and returns its one-time token to the browser.

Load zuora.js

Include the Zuora Payments library on your checkout page.

Create a container for the payment form

Add the element the hosted form mounts into.

Initialize an instance of the Zuora object

Instantiate the Zuora object with your publishable key.

Populate the payment form configuration

Configure the form -- locale, region, currency, amount, and a createPaymentSession callback that calls your backend when the shopper clicks Pay.

Create and mount the payment form

Create the hosted payment form from the configuration and mount it into the container element.

1package com.zuora.sample;
2​
3import static spark.Spark.port;
4import static spark.Spark.post;
5import static spark.Spark.staticFiles;
6​
7import com.zuora.ZuoraClient;
8import com.zuora.model.*;
9import com.google.gson.Gson;
10​
11import java.math.BigDecimal;
12import java.nio.file.Paths;
13import java.util.Map;
14​
15public class Server {
16​
17 private static Gson gson = new Gson();
18​
19 // Please configure your OAuth client id here.
20 private static final String CLIENT_ID = "a113*****************************6e5e";
21 // Please configure your OAuth client secret here.
22 private static final String CLIENT_SECRET = "=kSm9jIc****************************wvwJ";
23 private final static ZuoraClient zuoraClient = new ZuoraClient(CLIENT_ID, CLIENT_SECRET, ZuoraClient.ZuoraEnv.SBX);
24​
25 public static void main(String[] args) {
26 port(8888);
27 staticFiles.externalLocation(Paths.get("public").toAbsolutePath().toString());
28 zuoraClient.initialize();
29 zuoraClient.setDebugging(true);
30 post("create-payment-session", (request, response) -> {
31 response.type("application/json");
32 Map map = gson.fromJson(request.body(), Map.class);
33 String firstName = (String) map.get("firstName");
34 String lastName = (String) map.get("lastName");
35 String currency = (String) map.get("currency");
36 String amount = (String) map.get("amount");
37​
38 final CreateAccountContact contact = new CreateAccountContact().firstName(firstName)
39 .lastName(lastName)
40 .country("US")
41 .state("CA");
42 final CreateAccountRequest createAccountRequest = new CreateAccountRequest()
43 .name(String.join(" ", firstName, lastName))
44 .billToContact(contact)
45 .billCycleDay(1)
46 .soldToSameAsBillTo(true) // alternatively, use .soldToContact(contact)
47 .autoPay(false)
48 .currency(currency);
49 final CreateAccountResponse createAccountResponse = zuoraClient.accountsApi().createAccountApi(createAccountRequest).execute();
50​
51 final CreatePaymentSessionRequest createPaymentSessionRequest = new CreatePaymentSessionRequest()
52 .currency(currency)
53 .amount(new BigDecimal(amount))
54 .processPayment(true)
55 .accountId(createAccountResponse.getAccountId());
56 final CreatePaymentSessionResponse createPaymentSessionResponse = zuoraClient.paymentMethodsApi().createPaymentSessionApi(createPaymentSessionRequest).execute();
57​
58 return gson.toJson(createPaymentSessionResponse.getToken());
59 });
60 }
61}

Run it

  1. Build the server: mvn package
  2. Start it: java -cp target/sample-jar-with-dependencies.jar com.zuora.sample.Server
  3. Open http://localhost:8888/checkout.html and pay with the test card.

On success, the customer is redirected to your return page with the resulting paymentId.

What’s next

  • Save the payment method — switch the payment session to a create-and-save flow to reuse the method for recurring billing.
  • Handle failures — inspect result.error in the onComplete callback to surface gateway decline reasons.
  • Go to production — pin a versioned zuora.js URL and swap the sandbox publishable key for your live key.