Create the widget
To obtain prices from an external pricing system, you write a custom widget to include on your storefront’s pages.
The custom widget’s JavaScript file extends the storefront’s CartViewModel
class by implementing a prepricing callback function. When a shopper modifies the shopping cart by adding or removing products or changing quantities, this function makes a call to the external pricing system to obtain prices for the items in the cart.
In addition to an externalPrice
property for storing the external
price of a product, the CartViewModel
has an
externalPriceQuantity
property that determines the maximum quantity that
the external price can be applied to. For example, suppose the list
price of
a product is $10.00, but the external pricing system returns an externalPrice
value of $7.00 and an externalPriceQuantity
value of 3. If a shopper selects
this product and specifies a quantity of 2, the price in the cart for the two items is $14.00,
because the external price is applied to both items. However, if the shopper specifies a
quantity of 5, the external price is applied to only three of the items, so the total is
$41.00 (three items at $7.00 each, and two items at $10.00 each).
If the value of externalPriceQuantity
for a specific product is -1, there is no maximum quantity, so the external price is applied to all of the items of the product.
Create the widget structure
Create your widget as a global widget. Global widgets are automatically loaded for all pages; you do not need to add them explicitly to page layouts. Global widgets cannot include any user interface elements, so you should omit any display templates. The following shows an example of the files and directories in a global widget:
External Pricing/
ext.json
widget/
external-pricing/
widget.json
js/
external-pricing.js
To make the widget global, set the global property in the widget.json
file to true:
"global": true
For more information about the widget structure and the contents of the
ext.json
and widget.json
files, see Create a Widget.
Write the JavaScript
The JavaScript code you write extends the CartViewModel
class by implementing a callback function that executes during prepricing
. The following example shows sample JavaScript that implements a prepricing function:
define(
['jquery', 'knockout', 'ccLogger'],
function($, ko, CCLogger) {
'use strict';
return {
onLoad: function(widget) {
CCLogger.info("Loading external pricing widget");
var callbackMap = new Object();
var performPrepricing = function()
{
// sample code to invoke external system
$.ajax({
type: 'POST',
dataType: 'json',
url: EXTERNAL_SYSTEM_SERVICE_URL,
data: widget.cart().items(),
success: function(data) {
// update the cart items with external price details,
// assuming data has item details with external prices
if (data.items && data.items.length > 0) {
for (var i = 0; i < widget.cart().items().length; i++) {
for (var j = 0; j < data.items.length; j++) {
if (widget.cart().items()[i].productId ==
data.items[j].productId &&
widget.cart().items()[i].catRefId ==
data.items[j].catRefId &&
data.items[i].externalPrice &&
data.items[j].externalPriceQuantity) {
widget.cart().items()[i].externalPrice
(data.items[j].externalPrice);
widget.cart().items()[i].externalPriceQuantity
(data.items[j].externalPriceQuantity);
}
}
}
// invoke pricing in this success callback
widget.cart().markDirty();
}
},
error: function() {}
});
};
callbackMap['prepricing'] = performPrepricing;
widget.cart().setCallbackFunctions(callbackMap);
}
}
}
);
Note that because the asynchronous call to the external pricing system may complete after a pricing operation has already taken place on the Oracle Commerce server, the code explicitly marks the cart as having been modified after applying the external price information. This forces another pricing operation to be invoked using the external prices.
Some other considerations to take into account when you create your widget:
- To avoid making unnecessary calls, it is a good idea for your code to check whether external prices have already been applied to the cart items, and if so, skip calling the external system.
- If the external system does not impose a quantity limit on a specific product, your code should set
externalPriceQuantity
to -1, so that the external price is applied to all of the items of the product.
Install the widget
To install the widget, do the following in the administration interface:
- Click the menu icon, then click Settings.
- Click Extensions and display the Developer tab.
- Click Generate ID to generate an extension ID for the widget.
- Edit the widget’s
ext.json
file and set theextensionID
property to the value generated in the previous step. - Package the widget as a ZIP file. Use the structure described in Create the widget structure.
- Display the Installed tab and click Upload Extension. Select the ZIP file.
- Publish your changes.
Price the cart items
The custom widget alters the logic for pricing the shopping cart. This section describes how the pricing of the cart behaves when external pricing is enabled.
When a shopper views the product detail page for a specific product, the page displays the internal price that Oracle Commerce stores for the product. When the shopper modifies the shopping cart (adds or remove an item, or changes the quantity of an item), the custom widget makes a call to the external pricing service, and applies any external prices it receives to the items in the cart. Note that this means that the price of a product in the cart may differ from the price displayed on the product detail page.
After obtaining prices from the external pricing service, the storefront sends the
current contents of the cart to the Oracle Commerce server to calculate pricing (for example, to apply promotions). This call includes
externalPrice
and externalPriceQuantity
values for any
products in the cart that have external prices.
The following shows an example of the data sent to the server:
{
"shoppingCart": {
"items": [
{
"productId": "xprod1003",
"quantity": 3,
"catRefId": "xsku1013",
"stockStatus": true,
"discountInfo": [],
"externalPrice": "21.00",
"externalPriceQuantity": "1",
"invalid": false
},
{
"productId": "xprod1002",
"quantity": 5,
"catRefId": "xsku1007",
"stockStatus": true,
"externalPrice": "18.00",
"externalPriceQuantity": "-1",
"invalid": false,
"currentPrice": 0
}
],
"coupons": []
}
}
In the example above, the cart contains two products, xprod1003 and xprod1002. The quantity of xprod1003 is 3, but only one of those items will have the external price applied to it ($21.00), because the externalPriceQuantity
value for xprod1003 is 1. The other two items will have the internal price applied.
The quantity of xprod1002 is 5, and all of these items will have the external price applied ($18.00), because the externalPriceQuantity
value for xprod1002 is -1.
When the server receives the data above, it performs a pricing operation, using the external prices for any items that have them, and applying internal prices to the rest. The repriced cart data is returned to the storefront for display.
The following example shows part of the data returned to the storefront after a pricing operation:
{
"shoppingCart": {
"numberOfItems": 8,
"items": [
{
"onSale": false,
"catRefId": "xsku1013",
"shippingSurchargeValue": 0,
"externalPrice": 21,
"unitPrice": 36,
"discountAmount": 0,
"productId": "xprod1003",
"externalPriceQuantity": 1,
"rawTotalPrice": 93,
"price": 93,
"discountInfo": [],
"listPrice": 36,
"detailedItemPriceInfo": [
{
"amount": 21,
"currencyCode": "USD",
"tax": 0,
"discounted": false,
"orderDiscountShare": 0,
"quantity": 1,
"detailedUnitPrice": 21
},
{
"amount": 72,
"currencyCode": "USD",
"tax": 0,
"discounted": false,
"orderDiscountShare": 0,
"quantity": 2,
"detailedUnitPrice": 36
}
],
"salePrice": 0,
"quantity": 3
},
{
"onSale": false,
"catRefId": "xsku1007",
"shippingSurchargeValue": 0,
"externalPrice": 18,
"unitPrice": 24,
"discountAmount": 0,
"productId": "xprod1002",
"externalPriceQuantity": -1,
"rawTotalPrice": 90,
"price": 90,
"discountInfo": [],
"listPrice": 24,
"detailedItemPriceInfo": [
{
"amount": 90,
"currencyCode": "USD",
"tax": 0,
"discounted": false,
"orderDiscountShare": 0,
"quantity": 5,
"detailedUnitPrice": 18
}
],
"salePrice": 0,
"quantity": 5
}
]
},
"discountInfo": {
"orderCouponsMap": {},
"orderDiscount": 0,
"orderImplicitDiscountList": [],
"unclaimedCouponsMap": {},
"shippingDiscount": 0
},
"priceInfo": {
"amount": 183,
"total": 183,
"shipping": 0,
"totalWithoutTax": 183,
"currencyCode": "USD",
"shippingSurchargeValue": 0,
"tax": 0,
"subTotal": 183
},
...
The response shows the effect of the external pricing. For example, the detailedItemPriceInfo
object for xprod1003 shows that one item is priced at $21.00 (the external price) and the other two are priced at $36.00 each (the internal price). The total price of the three items is $93.00.