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:
- API endpoint URL: The endpoint URL for the CORS REST API. You should set the API endpoint URL based on the environment you are on:
- For US Cloud 1 Production environment: Use https://rest.na.zuora.com/v1/rsa-signatures
- For US Cloud 1 Sandbox environment: Use https://rest.na.sandbox.zuora.com/v1/rsa-signatures
- For US Cloud 2 Production environment: Use https://rest.zuora.com/v1/rsa-signatures
- For US Cloud 2 API Sandbox environment: Use https://rest.apisandbox.zuora.com/v1/rsa-signatures
- For US Central Sandbox environment: Use https://rest.test.zuora.com/v1/rsa-signatures
- For EU Cloud Production environment: Use https://rest.eu.zuora.com/v1/rsa-signatures
- For EU Cloud Sandbox environment: Use https://rest.sandbox.eu.zuora.com/v1/rsa-signatures
- For EU Central Sandbox environment: Use https://rest.test.eu.zuora.com/v1/rsa-signatures
uri
: The URL that the Payment Page will be served from.- For US Cloud 1 Production environment: Use https://na.zuora.com/apps/PublicHostedPageLite.do
- For US Cloud 1 Sandbox environment: Use https://sandbox.na.zuora.com/apps/PublicHostedPageLite.do
- For US Cloud 2 Production environment: Use https://www.zuora.com/apps/PublicHostedPageLite.do
- For US Cloud 2 API Sandbox environment: Use https://apisandbox.zuora.com/apps/PublicHostedPageLite.do
- For US Central Sandbox environment: Use https://test.zuora.com/apps/PublicHostedPageLite.do
- For EU Cloud Production environment: Use https://eu.zuora.com/apps/PublicHostedPageLite.do
- For EU Cloud Sandbox environment: Use https://sandbox.eu.zuora.com/apps/PublicHostedPageLite.do
- For EU Central Sandbox environment: Use https://test.eu.zuora.com/apps/PublicHostedPageLite.do
method
: The type of the request. Set it toPOST
.pageId
: The page id of your Payment Pages 2.0 form. To retrieve this information, navigate to Settings > Payments > Setup Payment Page and Payment Link and click Show Page Id next to the Payment Page name in the Page List section.
Here is a sample Curl request to generate a token and a digital signature.
curl -i -k -H "apiAccessKeyId:superadmin@myCompany.com" -H "apiSecretAccessKey:password" -H "Accept:application/json" -H "Content-Type:application/json" -X POST https://rest.zuora.com/v1/rsa-signatures -d ' { "uri": "https://www.zuora.com/apps/PublicHostedPageLite.do", "method": "POST", "pageId":"ff80808145b3bf9d0145b3c6812b0008" }';
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:
- Navigate to Settings > Payments, and then click Setup Payment Page and Payment Link.
- 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("uri", "https://apisandbox.zuora.com/apps/PublicHostedPageLite.do"); requestObject.put("method","POST"); requestObject.put("pageId", "2c92c0f849369b9401493aab4b111111"); RequestEntity requestEntity = new StringRequestEntity( requestObject.toString(), "application/json", "UTF-8"); PostMethod postRequest = new PostMethod( "https://rest.apisandbox.zuora.com/v1/rsa-signatures"); postRequest.addRequestHeader( "apiAccessKeyId", $ZuoraUserName); postRequest.addRequestHeader("apiSecretAccessKey", $ZuoraPassword); postRequest.addRequestHeader("Accept", "application/json"); postRequest.setRequestEntity(requestEntity); HttpClient httpClient = new HttpClient(); if(httpClient.executeMethod(postRequest) != 200) { System.out.println("Fail to get signature."); return; } 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"); System.out.printf( "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 = ‘https://rest.zuora.com/v1/rsa-signatures’ 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 = requests.post(rest_call_url, 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’]