Configure your storefront for punchout shoppers

You must make changes to a number of the storefront layouts as part of the punchout integration.

To learn how to make changes to existing layouts, widgets, and elements, see Design Your Store Layout. To learn about creating custom widgets and elements, see Create a Widget.

This section includes the following topics:

Design the storefront for punchout shopping

Keep the following in mind when you design your store layout to support punchout shopping.

  • Oracle recommends that you create a separate site just for punchout shoppers. The punchout site has its own URL, which you provide to the procurement system, plus its own catalog, price group, and contract terms. See Configure Sites to learn how to create additional sites.
  • Punchout shoppers require only a subset of the features you might otherwise provide on your store and they might be confused if they see design elements that do not apply to them. For example, punchout shoppers do not select shipping methods or have wish lists.

A punchout site should include Home, Product, Collection, and Cart layouts.

However, to ensure a smooth experience for punchout shoppers, remove the following components from your punchout site:

  • Any layouts related to profiles, including Profile, Order History, Purchase List, and Scheduled Order.
  • Any of the checkout layouts, including Checkout, Checkout with GiftCard, Checkout Payment, and Checkout Stack.
  • All wish list layouts, widgets, and elements.
  • Any links to external sites.
  • The Login/Registration and My Account elements in the Header widget.

    It is important to remove these components because shoppers who did not arrive at the site via punchout should not be able to log in or complete an order. If the shopper’s session expires, do not prompt them to log in again; redirect them to the procurement system, instead.

  • The Cart Shipping widget from the Cart layout. Instead, you can add a button to the Cart layout that shoppers click when they want to return to the procurement system. See Add a punchout checkout button to the Order Summary widget for more information.
  • The Checkout button element in the Cart Summary widget. You could also modify this button to redirect the shopper to the Cart layout, where they can click a button that sends them back to the procurement site. See Add a punchout checkout button to the Order Summary widget for more information.

Indicate that a logged-in shopper is a punchout shopper

A flag that specifies that a shopper has been redirected from a procurement site is available from the User view model. However, it is not included in the out-of-the-box widgets. If you want to indicate that a shopper is a punchout shopper in a widget, you can do so using code similar to the sample below:

widget.user().isPunchout()

See Add a punchout checkout button to the Order Summary widget for a code sample that uses this functionality in a method that redirects the punchout shopper back to the procurement system.

Add a punchout checkout button to the Order Summary widget

The Order Summary widget (available for the Cart layout) lets the shopper review their order from the cart page before proceeding to checkout. This section describes how to add a button to the Order Summary widget that a punchout shopper clicks when they are ready to complete their order.

First, customize the Order Summary widget’s JavaScript file to handle the button click. In the following example, the handlePunchoutOrder() function handles the button click.

handlePunchoutOrder: function() {
       var widget = this;
       if(data.cart().items().length > 0) {
         data.cart().validatePrice = true;
         data.cart().skipPriceChange(true);
         data.redirectToProcurement("SSEURL",false);
       }
       return true;
     },

The following method redirects the shopper back to their procurement system.

/**
 * Method to redirect punchout user back to procurement using Form post.
 *
 * Before redirecting, call the server-side extension URL with orderjson
 * to convert it to CXML and post it to the procurement system.
 */
redirectToProcurement : function(){
  var widget=this;
  if(widget.user().isPunchout()){
    //get request data saved in local storage when shopper was
 * redirected from procurement to Commerce
    var punchoutStorageData =CCRestClient.
getStoredValue(CCConstants.LOCAL_STORAGE_ADDITIONAL_FORM_DATA);
    if(punchoutStorageData){
      var punchoutStorageObject =JSON.parse(punchoutStorageData);
      if(punchoutStorageObject){
        widget.punchoutBuyerCookie
=punchoutStorageObject.buyerCookie?punchoutStorageObject.buyerCookie:null;
        widget.punchoutBrowserFormPost
=punchoutStorageObject.browserFormPost?punchoutStorageObject.browserFormPost:null;
      }
    }
    //Creating form element
    var form = document.createElement('form');
    document.body.appendChild(form);
    form.method = 'post';
    //Setting form action URL sent by procurement
  form.action = widget.punchoutBrowserFormPost;
  if(widget.user().orderId() && widget.user().orderId() != ''){
      var contextObj = {};
      var data ={};
      contextObj[CCConstants.ENDPOINT_KEY] = CCConstants.ENDPOINT_GET_ORDER;
      var filterKey = widget.cart().storeConfiguration.getFilterToUse(contextObj);
      if (filterKey) {
        data[CCConstants.FILTER_KEY] = filterKey;
      }
      //Get Order Call
      CCRestClient.request(CCConstants.ENDPOINT_GET_ORDER, data,
        function(data) {
            //Success function of get order
            //Call to SSE to convert Order Json to CXML
  $.ajax({
     type: 'post',
     url: 'http://example.com:8080/ccstorex/custom/v1/punchOut/punchOutComplete',
             data: JSON.stringify(data),
             headers:{"X-BuyerCookie":widget.punchoutBuyerCookie},
             contentType: "application/json",
             dataType: 'text',
             success: function (response) {
     //setting CXML order in form element
     var input = document.createElement('input');
     input.type = 'hidden';
     input.name = "cxml-urlencoded";
     input.value = response;
     form.appendChild(input);
     //cleanup in Commerce before form submission
     CCRestClient.
clearStoredValue(CCConstants.LOCAL_STORAGE_ADDITIONAL_FORM_DATA);
               CCRestClient.clearStoredValues();
               widget.user().clearUserData();
               widget.cart().clearCartForProfile();

               form.submit();
             }
         });

   },
   function(data) {
     navigation.goTo(widget.contextData.global.links['404'].route);
   },
   widget.user().orderId());
  }else{
  //If there is no order id, redirect with empty cart.
  //removing punchout related data from localstorage and empty cart;
    CCRestClient.clearStoredValue(CCConstants.LOCAL_STORAGE_ADDITIONAL_FORM_DATA);
    CCRestClient.clearStoredValues();
    widget.user().clearUserData();
    widget.cart().clearCartForProfile();
    form.submit();
  }
 }
}

Display information about a punchout shopper in a widget

When a procurement system directs a punchout shopper to your store, it can also pass the shopper’s name and email address. Commerce maintains this data in local storage, where widgets can access it.

The following sample customizes the JavaScript file for the Contact Login for Managed Accounts element, which is available for the Header widget, to display the punchout shopper’s name and email address. For more information about this element, see Create Page Layouts that Support Different Types of Shoppers.

//Changes to be added in onLoad method of element.js file in contact-login-for-managed-accounts-v2 element of header widget
onLoad : function(widget) {
    var self = this;
    var afterLogIn = false;
    if(widget.user().isPunchout()){
// Get user details from local storage punchout form post data and
// override firstName,lastName and Email
        var punchoutStorageData =
CCRestClient.getStoredValue(CCConstants.LOCAL_STORAGE_ADDITIONAL_FORM_DATA);
        if (punchoutStorageData) {
            var punchoutStorageObject = JSON.parse(punchoutStorageData);
            if (punchoutStorageObject) {
                var punchoutUserFirstName = punchoutStorageObject.firstName;
                if(punchoutUserFirstName){
                  widget.user().firstName(punchoutStorageObject.firstName);
                  widget.user().loggedInUserName(punchoutStorageObject.firstName);
                }
                if(punchoutStorageObject.lastName){
                  widget.user().lastName(punchoutStorageObject.lastName);
                }
              if(punchoutStorageObject.emailAddress){
                  widget.user().emailAddress(punchoutStorageObject.emailAddress);
                }
            }
        }
    }
}