Skip to main content

Generate and manage the Digital Signature and Token for Payment Pages 2.0


Generate and manage the Digital Signature and Token for Payment Pages 2.0

This article describes how to generate the digital signature for the Payment Pages 2.0.

Request the digital signature and token

The REST API used in Payment Pages 2.0 is CORS (Cross-Origin Resource Sharing) enabled and therefore requires a digital signature. You need to pass the generated signature to your client for it to access Payment Pages 2.0.

To generate the digital signature and token for your Payment Pages 2.0 form, you can use one of the following methods.

  • Use the Generate RSA signature REST API operation. 
  • Submit a Zuora CORS REST request to the Zuora server in your local client.

The CORS REST response contains a token, a signature, and a public key. The following information is required for the request:

Here is a sample Curl request to generate a token and a digital signature.

curl -i -k -H "" -H "apiSecretAccessKey:password" -H "Accept:application/json" -H "Content-Type:application/json" -X POST -d '
   "uri": "",
   "method": "POST",

Manage Token Issuance

To prevent multiple renderings, when creating or editing a Payment Page, set the Limit the number of submissions before blocking submission field value to a positive integer. When an end-user hits this threshold by repeatedly submitting incorrect information on the Payment Page, they will see the error message and will be blocked from further submission. When the submission limit is reached, you must provide your end-users with a way to re-render the page, which requires the regeneration of a signature. 

For more information about the Limit the number of submissions before blocking submission setting, see Security Measures for Payment Pages 2.0.

Check token usage analysis

You can check the usage analysis of tokens used for rendering payment pages in the past 30 days in Zuora UI:

  1. Navigate to Settings > Payments, and then click Setup Payment Page and Payment Link.
  2. On the Payment Pages tab page, click the Hosted Pages Render Page Token Usage Analysis link above the Page List section, and the following information for the past 30 days is available in a pop-up window:
    • The number of tokens used for rendering payment pages.
    • The number of page rendering failures due to the reuse of the same token.
    • If the rate of failures due to the reuse of the same token is significant, a suggestion and related article are provided for your further analysis.

Validate Client-side HPM Parameters

The Client-side HPM Parameter Validation feature is supported to better protect the client-side HPM parameter in the request for rendering or submitting Payment Pages 2.0. When receiving such a request, Zuora validates the client parameters in this request by comparing with the value specified in the digital signature. Therefore, you have to specify these parameters when calling the Generate RSA signature API operation to generate the digital signature.

See Security Measures for Payment Pages 2.0 for more information.

Validate the Digital Signature

When you implement a Payment Page with the Submit button outside, you need to validate the digital signature that Zuora returns to your callback page. Verify whether the signature is a valid response from Zuora and whether it is not expired. See Validate the Digital Signature for Payment Pages 2.0 for details.

Troubleshoot Failed Signature Validation

A signature validation failure could be a result of several possible causes. Examples are:

  • A failure caused by your implementation
  • If you are constructing the integration for the first time, check the process of validation in the following areas:
    • Did you use the correct username and password to send signature POST request? 
    • Was the signature request sent to the correct endpoint?
    • Was the POST response received successfully and parsed correctly?
    • Was the signature decrypted correctly? Debug the decryption action.
    • Were the correct parameters used to validate the signature?
  • If your integration has worked for a while before you started seeing validation failures, it may be a security issue. Perform security-related checks.
  • If none of the above is the cause of the signature validation failure, contact Zuora Global Support with the error message for help.

Receive the Digital Signature

Write the server-side code to receive the digital signature for the Payment Pages 2.0 form. You need to pass the necessary information in the response to your client.

A successful call returns the following, all of which your client needs to load your Payment Pages form:

  • signature: Digital signature generated
  • token: Token generated
  • tenantId: ID of your Zuora tenant
  • key: Public key generated
  • success: True if the request is successful

Signature Expiration

Your Payment Page signature expires in the following scenario. When an expired signature is used, your user will receive the specified error code.

Page Load or Page Submit When Expires Error Code Returned
In the Payment Page load request When a Payment Page is not loaded within 30 minutes of the signature generation Invalid_Security error code
In the Payment Page load request When a signature is used by a Direct POST request Attempt_Exceed_Limitation
In the Payment Page load request When a signature is used to successfully render the page  Attempt_Exceed_Limitation
In the Payment Page submit request When the page is not submitted within 24 hours after its generation Invalid_Security error code
In the Payment Page submit request When a signature is used to submit page more than the threshold Attempt_Exceed_Limitation

If the signature expires, resend the request to get a new signature and validate again. 

If you are implementing a Payment Page with the Submit button outside, see Validate the Digital Signature for Payment Pages 2.0 for validating the digital signature in your callback page.

Sample Code to Generate the Digital Signature

Here is a sample code in Java that requests the digital signature and other information from Zuora:

package com.zuora.hpm;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.json.JSONObject;

public class SignatureTest {
    public static void main(String[] args) throws Exception {
        JSONObject requestObject = new JSONObject();
        requestObject.put("pageId", "2c92c0f849369b9401493aab4b111111");
        RequestEntity requestEntity = 
           new StringRequestEntity(
              requestObject.toString(), "application/json", "UTF-8");
        PostMethod postRequest = ​​​​​new PostMethod(
           "apiAccessKeyId", $ZuoraUserName);
        postRequest.addRequestHeader("apiSecretAccessKey", $ZuoraPassword);
        postRequest.addRequestHeader("Accept", "application/json");
        HttpClient httpClient = new HttpClient();
        if(httpClient.executeMethod(postRequest) != 200) {
            System.out.println("Fail to get signature.");
        byte[] res = postRequest.getResponseBody();
        JSONObject resultObject = new JSONObject(new String(res));
        String token = resultObject.getString("token");
        String key = resultObject.getString("key");
        String tenantId = resultObject.getString("tenantId");
        String signature = resultObject.getString("signature");
        Boolean success = resultObject.getBoolean("success");
        ​​​   "success: %s\n token: %s\n tenantId: %s\n signature: %s\n public key: %s\n", 
           success, token, tenantId, signature, key);   

The following is a sample response from the above request:

success: true
token: FZ8Xtefcm5qvZi3Fz4rvTWU0pMVbNCzq
tenantId: 123
signature: Oio9UxQ+sUfHXOy7K5sSyQ6QJNVkoHfPRoGdjlkY70q2dlAOKthpKaZPc8DIUhOY6Oz/jbP0bAiZsjW9fnEMLi43bUV5prBc5HE1urPN4LGFK/mlmXSOkKpTWXF0JnQSvyl57bQCLusd+LLpaSnraC1N3J/DsJQuGpyhCRQeZxM3lUKm/AWUiJAIgGPqiIsNKRj9eS5Zz03hPRajTzDPG00M3jiG8EX+a2MvptXjFc0lJK8eZz1g0/piLaFxNlhI59dJpxwhO0K0onE19EgJWHbkYJzxbi4UMoI6WOi9axa877Z6bijUqV9+F2DvVUdQb47Q2+56foIitKc1NtxCCZ6VuOF97JwjXdkr8oSqF7JKC55IVNyh7clCHziPag2q+tjRW8VqhHa2dont+lDvN14uuA2F1Rro6Txrh0tdJu/gxTCCzgTaqzAQzHjtf4hL3aHH40K6sI9ZIAlL6rqzO1THHkr35kueolDnSIegVfM0sC2u7g799JBfgS9d/3EjSwRCyOxk5jGk4Ec6cmU++bNqIshVsr0DnnNw9gvoKqck6uRRoZkCOWo2NA128CHdm6qhbC62oJaWNadYomByonjF3WY5hbmOvEfIi8V4M2K0F1jbodFJVcCQCemmd9M9ElI0wnG/X0s2Lop/ZhR8lseOgsnQloRoRYfioOAcUj8=
public key: MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6WzeUhwUnQoshk0QokZlKjwcSiYoDP3/BRIa40lfsmlTzBquhZgOq7qhgYqaSNq1Mqk1oEIAEhPtv6s7EELGO76Avo1niwVJw3A78gMS2T35Li4mjH+Kzf3nqSP6AhsV6EF8frLgQklvHV1nem5HZrMdmqlsqK1j4oc6YwR9mVPrbzzolMMZOnTwap7RsApxfMi5OSYxIWJ7PykQNwPH8G99smY6yb095zlJDl9/yPt9amCKIdjgfCdXlVNqhfIq/633i4R5I+dMqiW6JblxzqoQ3Xg/gP+5LKzXQUBgnMW4G0r8VP7kyZh8yfEplNxRjpGzGFjdmAlm0XhvF525IkUqjQaEY3J8lfMruaf/Rwo44Grb3+8lKNyGZfh39AfnJNkZHO/NFkcPhcq6gOtTV1OFCDrqAJTzGMVwVB05PTAPX0osH1fktvlYERtVa4YrJrZrF+E+1MXdtVx/pxGEzLBdE/AISXxDLN6r11upTbNi8f+H5Hc30iAk32hQSOf12R4nwYSvCPhtHh6O8+/XD9QfBJtLErqo0BnkZRljRA8jF3YFQ7Vwg+k5iqeMA4kt51pgOdEAbD13eeinOQQnx8sBwFO+PELUXOmxEWAMmUxkqklU0rjH6cHyl290hgRK6y9B0Oogd+QfbL8p4+Dwyp7tqwIs0XkJhEHWHVkXz1cCAwEAAQ==

Here is a sample code in Python that requests the digital signature and other information from Zuora:

import requests
import json

rest_call_url = ‘’
my_hosted_page_url = ‘’
my_hosted_page_id = ‘’
my_username = $ZuoraUserName
my_password = $ZuoraPassword

data = {"uri": my_hosted_page_url, "method": "POST", "pageId": my_hosted_page_id}
headers = {'content-type': 'application/json'}

response =, data=json.dumps(data), auth=(my_username, my_password), headers=headers)
response_json = response.json()

token = response_json['token']
signature = response_json['signature']
key = response_json['key']
tenant_id = response_json[‘tenantId’]