Embed Third-Party Payment Vendor Page in Checkout Workflow

You can extend care checkout flow to initiate a third-party payment page beyond the care application.

You can embed third-party payment vendor pages in checkout process flow. You can do this by creating a new template and adding to the existing dynamic container rule set for the cart checkout.

Create and Publish an App Extension

Here's how you can create and publish an app extension:

  1. Open the Settings and Actions menu by clicking your user image or name in the global header.

  2. Click Edit Pages in Visual Builder to open the page in the VB Designer in Oracle Visual Builder Studio.

    VB Designer opens in a new browser tab in the context of the Fusion Applications page.

  3. If the Visual Builder detects only one available app extension project and workplace, it will auto select the project and workspace during the process. If there are multiple options available then you must select the appropriate project and workspace.

    Note: The navigator lists the apps extensible dynamic UIs and pages. By default, the filter displays extensible artifacts only.

Duplicate Dynamic Container for Adding New Payment Gateway Template

Here's how you can duplicate dynamic container:

  1. In the Application Extensions, select Contact Center > Application > Flows > Main Flows > Cart > Cart-Checkout where you can integrate payment gateway.

  2. Click Dynamic Container > Container Rule set 1 > Layout for Cart Checkout from dynamic components.

  3. Duplicate the built-in template Case 1 as Case 1 (Copy).

  4. Click Add icon in the section and select New Template.

  5. In the Create Template dialog box, enter the ID and title for the new template such as paymentGateway.

  6. Click Code.

  7. In the new template, here's the code to enter:

    <!-- Dynamic Container Templates -->
    <template id="paymentGateway">
    <oj-bind-if test="[[ $base.flow.variables.enablePaymentOptions  && $functions.enablePaymentOptions($base.variables.placeOrder,
    $base.variables.isConfigured,  $base.variables.commitmentCartItem, $base.flow.variables.enablePaymentOptions) === false]]">
    <div class="oj-flex oj-sm-12 oj-sm-margin-3x-top oj-sm-padding-3x-horizontal">
    <!-- Payment Options -->
    <div class="oj-flex-item oj-flex oj-sm-8 oj-sm-padding-4x-bottom oj-sm-padding-2x-end">
    <div role="list" data-oj-context="true" class="oj-sm-12 oj-cxi-cart">
    <oj-sp-expandable-list-item class="oj-flex-item"
    item-title="Payment Options"
    item-subtitle="Enter a valid payment method"
    icon.class="oj-ux-ico-deposits"
    icon.alt-text="Payment Options"
    badge="[[{'text': !$base.variables.isConfigured.paymentInfoConfigured ? 'Required' : 'Configured', 'status':
    $base.variables.isConfigured.paymentInfoConfigured ? 'success' : 'info'}]]"
    expanded="{{ $base.flow.variables.cartCheckoutExpandObj['payment-options'] }}"
    on-sp-before-detail-collapse="[[$listeners.paymentOptionsSpBeforeDetailCollapse]]"
    id="payment-options" on-sp-before-detail-expand="[[$listeners.paymentOptionsSpBeforeDetailExpand]]">
    <div id='paymentContent'>
    <div class="oj-sm-padding-4x">
    <h2 id="paypalHeading" value="Paypal container"></h2>
    <div id="paypal-button-container"></div>
    </div>
    </div>
    </oj-sp-expandable-list-item>
    </div>
    </div>
    </div>
    </oj-bind-if>
    </template> 

Implement PayPal Buttons

Here's how you can implement PayPal buttons:

  1. Click Javascript and enter the following code.

  2. Use the CLIENT_ID of PayPal application.

    define(['https://www.paypal.com/sdk/js?client-id=CLIENT_ID'], function() {
    'use strict';
    var eventHelper;
    var shoppingCartPrice = '0.00';
    var PageModule = function PageModule(context) {
    eventHelper = context.getEventHelper();
    };
    // jQuery(document).ready(checkPaypal);
    function checkPaypal () {
    if($('#paypal-button-container').is(':visible')) {
    var FUNDING_SOURCES = [
    paypal.FUNDING.CREDIT,
    paypal.FUNDING.CARD
    ];
    FUNDING_SOURCES.forEach(function(fundingSource) {
    // Initialize the buttons
    var button = paypal.Buttons({
    fundingSource: fundingSource,
    createOrder: function(data, actions) {
    return actions.order.create({
    purchase_units: [{
    amount: {
    value: shoppingCartPrice
    }
    }]
    });
    },
    // Finalize the transaction
    onApprove: function(data, actions) {
    return actions.order.capture().then(function(details) {
    // Show a success message to the buyer
    if (details.intent === 'CAPTURE' && details.status === 'COMPLETED') {
    eventHelper.fireCustomEvent('/page:assignPaymentDetails', { "details": {'id' : details.purchase_units[0].payments.captures[0].id} });
    }
    });
    }
    });
    // Check if the button is eligible
    if (button.isEligible() && document.getElementsByClassName('paypal-buttons-context-iframe').length ===0) {
    // Render the standalone button for that funding source
    button.render('#paypal-button-container');
    }
    });
    } else {
    setTimeout(checkPaypal, 50);
    }
    }
    /**
    *
    * @param {String} arg1
    * @return {String}
    */
    PageModule.prototype.setTotalPrice = function (cart) {
    var totalPrice = 0;
    cart.forEach(cartPrice => {
    if (cartPrice.priceType === 'oneTime') {
    totalPrice += cartPrice.price.taxIncludedAmount.value;
    }
    });
    shoppingCartPrice = totalPrice.toFixed(2);
    console.log("shoppingCartPrice: "+shoppingCartPrice);
    };
    PageModule.prototype.enablePaypal = function () {
    checkPaypal();
    };
    PageModule.prototype.enablePaymentOptions = function (placeOrder, isConfigured, commitmentCartItem, paymentOptions) {
    let disablePaymentOptions;
    if(!placeOrder && isConfigured.contactInfoConfigured && isConfigured.shippingInfoConfigured) {
    if (Object.keys(commitmentCartItem).length > 0 && !isConfigured.commitmentTermsConfigured) {
    disablePaymentOptions = true;
    }  else if (paymentOptions && isConfigured.paymentInfoConfigured) {
    disablePaymentOptions = true;
    } else {
    disablePaymentOptions = false;
    if (!document.getElementById('paypal-button-container') || (document.getElementById('paypal-button-container') && document.getElementsByClassName('paypal-buttons-context-iframe').length ===0)) {
    checkPaypal();
    }
    }
    } else {
    disablePaymentOptions = true;
    }
    return disablePaymentOptions;
    };
    /**
    *
    * @param {String} arg1
    * @return {String}
    */
    PageModule.prototype.updateExpandCollapseObj = function (action, expandObj, itemKey) {
    Object.keys(expandObj).forEach(expandObjKey => {
    if(action === 'expand') {
    expandObj[expandObjKey] = expandObjKey === itemKey? true : false;
    } else if(action === 'collapse') {
    expandObj[expandObjKey] = false;
    }
    });
    return expandObj;
    };
    /** 
    * Scroll/Focous to the expanded section
    * @param element id to focus/scroll to view
    * @return true
    */
    PageModule.prototype.expandListItemScrollIntoView = function (itemKey) {
    var element = document.getElementById(itemKey);
    element.scrollIntoView();
    return true;
    };
    return PageModule;
    });

Set Shopping Cart Price Required for PayPal

Here's how you can set the shopping cart price required for PayPal:

  1. Create new EventListener on vbEnter and click Next.

  2. Create new page action chain as setTotalPrice.

  3. Go to action chain setTotalPrice and add new step as General - Call function.

  4. Select function as setTotalPrice and pass the $base.flow.variables.cartTotalPrice parameter value.

  5. Click Page Designer and go to HTML code of paymentGateway, the dynamic container template.

  6. Click Components > Get Components.

  7. Search for oj-sp-expandable-list-item and install it.

  8. Click Events tab of Expandable List Items.

  9. Click New Event > New Custom Event. Expand Expandable List Item Events.

  10. Select spBeforeDetailCollapse and select New actionChain.

  11. In the action chain, add variables itemKey and pageType, and set to enabled.

  12. Add Call function to the action chain. Select updateExpandCollapseObj function.

  13. Pass parameters

    [
    "collapse",
    "{{ $base.flow.variables.cartCheckoutExpandObj }}",
    "{{ $variables.itemKey }}"
    ]
  14. Add Assign Variables, select $base.flow.variables.cartCheckoutExpandObj as target and source as $chain.results.callFunctionUpdateExpandCollapseObj

  15. Go to HTML code, assign input parameters to new event.

    {
    "itemKey": "{{ $event.target.id }}",
    "pageType": "checkout"
    }
  16. Repeat steps 8 to 11 for the spBeforeDetailExpand event.

  17. Add Call function to the action chain, select updateExpandCollapseObj function.

  18. Pass parameters

    [
    "expand",
    "{{ $base.flow.variables.cartCheckoutExpandObj }}",
    "{{ $variables.itemKey }}"
    ]
  19. Add Assign Variables, select $base.flow.variables.cartCheckoutExpandObj as target, and source as $chain.results.callFunctionUpdateExpandCollapseObj

  20. Add Call function and select expandListItemScrollIntoView function.

  21. Pass parameters

    [
    "{{ $variables.itemKey }}"
    ]
  22. Go to HTML code, assign input parameters to new event.

    {
    "itemKey": "{{ $event.target.id }}",
    "pageType": "checkout"
    }

    Here's the code to enter:

    {
    "description": "",
    "variables": {},
    "types": {},
    "eventListeners": {
    "paymentOptionsSpBeforeDetailCollapse": {
    "chains": [
    {
    "chainId": "ExpandableListItemSpBeforeDetailCollapseChain",
    "parameters": {
    "itemKey": "{{ $event.target.id }}",
    "pageType": "checkout"
    }
    }
    ]
    },
    "paymentOptionsSpBeforeDetailExpand": {
    "chains": [
    {
    "chainId": "ExpandableListItemSpBeforeDetailExpandChain",
    "parameters": {
    "itemKey": "{{ $event.target.id }}",
    "pageType": "checkout"
    }
    }
    ]
    },
    "vbEnter": {
    "chains": [
    {
    "chainId": "setTotalPrice",
    "parameters": {}
    }
    ]
    }
    },
    "events": {},
    "imports": {},
    "chains": {
    "ExpandableListItemSpBeforeDetailCollapseChain": {
    "description": "",
    "root": "callFunctionUpdateExpandCollapseObj",
    "actions": {
    "callFunctionUpdateExpandCollapseObj": {
    "module": "vb/action/builtin/callModuleFunctionAction",
    "parameters": {
    "module": "[[ $functions ]]",
    "functionName": "updateExpandCollapseObj",
    "params": [
    "collapse",
    "{{ $base.flow.variables.cartCheckoutExpandObj }}",
    "{{ $variables.itemKey }}"
    ]
    },
    "outcomes": {
    "success": "assignVariables"
    }
    },
    "assignVariables": {
    "module": "vb/action/builtin/assignVariablesAction",
    "parameters": {
    "$base.flow.variables.cartCheckoutExpandObj": {
    "source": "{{ $chain.results.callFunctionUpdateExpandCollapseObj }}",
    "auto": "always"
    }
    }
    }
    },
    "variables": {
    "itemKey": {
    "type": "string",
    "input": "fromCaller"
    },
    "pageType": {
    "type": "string",
    "input": "fromCaller"
    }
    }
    },
    "ExpandableListItemSpBeforeDetailExpandChain": {
    "description": "",
    "root": "callFunctionUpdateExpandCollapseObj",
    "actions": {
    "callFunctionUpdateExpandCollapseObj": {
    "module": "vb/action/builtin/callModuleFunctionAction",
    "parameters": {
    "module": "[[ $functions ]]",
    "functionName": "updateExpandCollapseObj",
    "params": [
    "expand",
    "{{ $base.flow.variables.cartCheckoutExpandObj }}",
    "{{ $variables.itemKey }}"
    ]
    },
    "outcomes": {
    "success": "assignVariablesCartCheckoutExpandObj"
    }
    },
    "assignVariablesCartCheckoutExpandObj": {
    "module": "vb/action/builtin/assignVariablesAction",
    "parameters": {
    "$base.flow.variables.cartCheckoutExpandObj": {
    "source": "{{ $chain.results.callFunctionUpdateExpandCollapseObj }}",
    "auto": "always"
    }
    },
    "outcomes": {
    "success": "callFunctionExpandListItemScrollIntoView"
    }
    },
    "callFunctionExpandListItemScrollIntoView: {
    "module": "vb/action/builtin/callModuleFunctionAction",
    "parameters": {
    "module": "[[ $functions ]]",
    "functionName": "expandListItemScrollIntoView",
    "params": [
    "{{ $variables.itemKey }}"
    ]
    }
    }
    },
    "variables": {
    "itemKey": {
    "type": "string",
    "input": "fromCaller"
    },
    "pageType": {
    "type": "string",
    "input": "fromCaller"
    }
    }
    },
    "setTotalPrice": {
    "root": "callFunctionSetTotalPrice",
    "description": "",
    "variables": {},
    "actions": {
    "callFunctionSetTotalPrice": {
    "module": "vb/action/builtin/callModuleFunctionAction",
    "parameters": {
    "module": "[[ $functions ]]",
    "functionName": "setTotalPrice",
    "params": [
    "{{ $base.flow.variables.cartTotalPrice }}"
    ]
    }
    }
    }
    }
    },
    "addLayouts": {
    "containerLayout1-rule1": {
    "expression": "case1"
    }
    },
    "addSubLayouts": {
    "containerLayout1": {
    "case1": {
    "layoutType": "container",
    "label": "Case 1 (Copy)",
    "layout": {
    "displayProperties": [
    "section2",
    "section1",
    "paymentGateway"
    ],
    "sectionTemplateMap": {
    "section1": "/contentPane",
    "section2": "/headerTemplate",
    "paymentGateway": "paymentGateway"
    }
    }
    }
    }
    },
    "chainRules": {
    "containerLayout1": {
    "rules": [
    "containerLayout1-rule1"
    ]
    }
    },
    "addTemplates": {
    "paymentGateway": {
    "title": "Payment Gateway",
    "description": "",
    "extensible": "byReference",
    "@dt": {
    "type": "section",
    "layout": "containerLayout1"
    },
    "dependencies": [
    "oj-sp/expandable-list-item/loader"
    ]
    }
    }
    }