Zuora: Hosted pages advanced integration

[Fuente: https://knowledgecenter.zuora.com/CA_Commerce/G_Hosted_Commerce_Pages/B_Payment_Pages_2.0/H_Integrate_Payment_Pages_2.0/A_Advanced_Integration_of_Payment_Pages_2.0]

When you want to have a full control over submission of payments and interaction with Zuora, you can implement a separate function in your client for Payment Page submission

Then you tie this function to an external submit button to invoked the function when the button is clicked. The response from payment creation is redirected to the configured callback page that you specified during the Payment Pages 2.0 configuration. 

This advanced integration is supported only for the inline style Payment Page forms.

Below is an additional checklist to implement an inline Payment Page form with the external submit button. See Integrate Payment Pages 2.0 for the standard implementation steps.

The following is a modified sample code from Integrate Payment Pages 2.0 to Website. The code was updated to render an inline Payment Page form with the external submit button.

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Zuora Public javascript library -->
<script type="text/javascript" src="https://static.zuora.com/Resources/libs/hosted/1.0.0/zuora-min.js"/></script>
<script>
<!-- optional params in case prepopulation of certain fields is desired-->
var prepopulateFields = {
   creditCardAddress1:"123 Any Street",
   creditCardAddress2:"Suite #999",
   creditCardCountry:"USA",
   creditCardHolderName:"John Doe"
};
 
// Sample params for rendering iFrame on the client side
var params = {
   tenantId:123,
   id:"ff80808145b3bf9d0145b3c6812b0008", <!-- pageId-->
   token:"qJ52b1iCyPXyZTcuQbfZa2qmKhD4qBGz",
   signature:"MjJmYjBmNTY3ZWI3ZjcyZTRmMjZlZWVhMTJhZDhiYWI1ZjUyMGRkNQ==",
   style:"inline",
   key:"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC59DglWlsd82ooSVYyXoniF5rln3edz+5tdPLVBXXPDVXDCI9w7sneaj+XQs5LFaHZby117XzE8CFmoskVd2tsGLvXr83gEQ7eCXUrY0NDBFlAs0t+ChkB18VXG2DBbeUCI2poZJpCbpQm4rSvqUeY+8H/+/Stf4hXFWVPEEWyjwIDQAB",
   submitEnabled:"false", 
   locale:"fr_FR", 
   url:"http://www.zuora.com/apps/PublicHostedPageLite.do",
   paymentGateway: "DefaultGateway" //payment gateway name
};

function forwardCallbackURL(response) {
   var callbackUrl = "<%=request.getContextPath()%>/callback?";
   for(id in response) {
      callbackUrl = callbackUrl+id+"="+encodeURIComponent(response[id])+"&";
   }
   window.location.replace(callbackUrl);
}

var callback = function (response) {
   if(!response.success) {
      // Requesting Payment Page failed. Error handling code should be added here. Simply forward to the callback url in sample code.
      forwardCallbackURL(response);
   }
};

function loadHostedPage() {
   Z.render(
      params,
      prepopulateFields,
      callback
   );
}

//External button: function to submit form
function submitPage() {
    Z.submit();
}
</script>
</head>

<body onload="loadHostedPage();">
   <div id="zuora_payment" ></div>
   <!--Add additional form fields as needed→
   
   <!--External button: button to submit form→
   <button onclick="submitPage()">Submit</button>
</body>

Implement the Callback Page

After the Payment Pages 2.0 form has been submitted, your user is redirected to the callback page. Zuora returns the following results to the callback page by appending them to the callback URL.

  • When a payment method is successfully created, the following are returned:
    • success
    • refId: Represents the newly created payment method ID in Zuora.
    • Any pass-through parameters specified in the client
    • Any form field marked as Returned in Response in the Payment Page configuration. Only the Credit Card type Payment Pages can have fields returned in response.

Example callback URL: http://s1.hpm.com:8000/thanks?success=true&refId=2c92c0f84979bc700149830f938c7e66&phone=%2B1%28123%29456-7896&email=mickey%40zuora.com&creditCardCountry=NPL&token=L8Zh6xjRyVuXQzg0s29VPSLZHL3nQKkG&refId=2c92c0f84979bc700149830f938c7e66&field_passthrough1=Residential

  • When a Payment Page submission fails, the following are returned:
    • success
    • errorCode
    • errorMessage

Example callback URL: http://s1.hpm.com:8000/thanks?success=false&errorCode=HostedPageFieldValidationError&errorMessage=creditCardType%3ANullValue%2C%0A&errorField_creditCardType=NullValue

You need to code the callback page to process the response back from Zuora and any pass through parameters from Payment Pages 2.0.

See Configure Payment Pages 2.0 for setting the Callback Path for the Payment Pages.

Here is a sample code that implements a callback page. This page parses the response information from the callback and composes a message and display it. Then it calls javascript methods, submitSucceed andsubmitFail, defined in the parent window for further procedure. For example, if the Payment Page submission failed, it calls submitFail that re-renders the Payment Page, using Z.renderWithErrorHandler, and displays customized error message, using Z.runAfterRender.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.zuora.hosted.lite.util.HPMHelper" %>
<%
    String message = "";
    if("Response_From_Submit_Page".equals(request.getParameter("responseFrom"))) {
        // Callback for submitting hosted page.
        if("true".equals(request.getParameter("success"))) {
            // Submitting hosted page succeeded.
            try {
                // Validate signature. Signature's expired time is 30 minutes.            
                HPMHelper.validSignature(request.getParameter("signature"), 1000 * 60 * 30);
            } catch(Exception e) {
                // TODO: Error handling code should be added here.            
                
                throw e;
            }
            message = "Hosted Page submitted successfully. The payment method id is " + request.getParameter("refId") + ".";
        } else {
            // Submitting hosted page failed.
            message = "Hosted Page failed to submit. The reason is: " + request.getParameter("errorMessage");
        }        
    } else {
        // Callback for requesting hosted page. And requesting hosted page failed.
        message = "Hosted Page failed to load. The reason is: " + request.getParameter("errorMessage");
    }
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="css/hpm2samplecode.css" rel="stylesheet" type="text/css" />
<title>Result</title>
</head>
<body>
    <div class="firstTitle"><font size="4"><%=message%></font></div>
</body>
</html>
<script type="text/javascript">
<%
if("Response_From_Submit_Page".equals(request.getParameter("responseFrom"))) {
    if("true".equals(request.getParameter("success"))) {
        // Submitting hosted page succeeded.
%>
        window.parent.submitSucceed();
<%
    } else {
        // Submitting hosted page failed.
%>
        window.parent.submitFail("<%=request.getQueryString()%>");
<%
    }
}
%>    
}
</script>
See Callback.jsp in Zuora GitHub for a complete sample implementation designed for all three styles of Payment Pages 2.0, overlay, inline with button inside, inline with button outside.

Callback Function vs Callback Page

The Callback URL in the advanced integration is not the same as the callback JavaScript function required for the basic integration. See Callback Function for the cases when you need to implement the JavaScript callback function.

The following table summarizes the Payment Pages 2.0 callback model to help you correctly design a callback function and/or a callback page.

Form with the Submit Button Inside Form with the Submit Button Outside
Additional fields required when configuring the Payment Page in Zuora application None Callback Path field
When is the JavaScript callback function called?
  • When the Payment Page request fails
  • When the Payment Page submission fails
  • When the payment method is successfully created
  • When the payment method creation fails
  • When a Payment Page request fails
What does the JavaScript callback function handle? Handles all success or error responses from the Z.render function. Handles only the error responses in Payment Page request from the Z.render function.
What happens after the Payment Page is submitted and Payment Method is created? Your user is redirected to the callback function.

The callback function processes the response back from Zuora and any pass through-parameters from Payment Pages 2.0.

Your user is redirected to the callback page.

The callback page processes the response back from Zuora and any pass-through parameters from Payment Pages 2.0.

Customize Error Messages in Advanced Integration

If you implement Payment Pages with the Submit button outside, some errors will be generated after the Payment Page is submitted. Zuora will forward these error messages based on your callback URL.

Use the Z.runAfterRender function to handle the server-side error messages: Z.runAfterRender(serverErrorMessageCallback)

The function takes one input parameter which is the name of your custom function that handles the server-side error messages.

To customize error messages for Payment Pages with an external submit button:

  1. Define the error handling function.
  2. Use Z.renderWithErrorHandler to handle the client-side error messages.
  3. Use Z.runAfterRender to handle the server-side error messages.