ShipRush

My.ShipRush.Shipping - Non-Visual Javascript API Guide

Background

Existing Web Shipping Javascript API was designed for a "visual" interaction with WebShipping form. It uses a new browser tab or IFrame to open WebShipping form, that looks/feels just like My.ShipRush (because it is My.ShipRush). Any developer can use this integration point without restriction, because there is no way to automatically initiate any action on the customer's behalf. Customer is the one who has to press "rate/ship/void" and we think that it is hard to "trick" the customer to do something against his will with IFrame/new tabs.

Advantage of this "IFrame/new tab" architecture is the simplicity. We rely on standard browser cookie/session based authentication and customer gets full power of WebShipping form embedded into his own merchant portal.

Disadvantages of "IFrame/new tab" architecture:

  • Slow to load (at least extra 500ms to fully load and render WebShipping)

  • Security model assumes that customer is going to use his brain (any Website could initiate a prompt for a non-visual shipping)


Landscape

The non-visual part of Web Shipping Javascript API is based on the following "best practices"

  • Javascript API authentication should be based on a short lived token that is NOT stored anywhere. (ephemeral tokens)

  • Storing of the "renewal" token, that is used to get new "auth" token is allowed (similar to OAuth implementations)

  • To obtain that auth token customer must login to his account with his username/password (this is done on the main Website aka my.shiprush)

  • Customer must acknowledge the fact that he is giving permission to Website "acme.com" to perform non-visual operations with his account/data

  • Developer must be "approved" by ShipRush team and use his ID to initiate AUTH request

  • If Javascript API uses browser redirect to pass auth token back (the most popular method), then developer must pre-specify the list of allowed redirect URL (to prevent man-in-the-middle attack that forwards auth token to another site)

So far, we have avoided (and hope continue to avoid) the use of OAuth, as it requires developers to build custom end point on their site and dramatically increases the integration difficulty.

However, OAuth is the industry standard, and it addresses many concerns. We may end up using OAuth, even though the imposed consumer overhead is material.


Implementation

Current implementation uses the same client-side javascript library as "Visual" Javascript API (webshipping.integration.client.js) and uses the same shipment structure (which we call internally "ShipmentView").

New "shipRushClient" methods:

  • IsAuthenticated(): Checks if the library has auth token

  • Authenticate(): Starts authentication flow (that includes redirect to My.ShipRush.com signin page and then redirects back to the original site with SessionToken in the URL)

  • Rate: Gets a single rate for a shipment

  • RateShop: Gets a list of available services/rates for a shipment

Both "Rate" and "RateShop" would start authentication workflow automatically if library has no auth token (same as calling shipRushClient.Authenticate()).

New properties for the "params" object that is passed to Open/Rate/RateShop.

  • DeveloperId: Unique ID assigned to your application. While developing on My.ShipRush Sandbox you can use "Test Developer" 7be1ae06-1875-42c0-bd16-a82c016f43cc, which allows redirect to any URL. For production use contact ShipRush Developer Support to set up your production credentials and approved ReturnURLs.

  • ReturnUrl (optional): Entry point to which redirect after getting new auth token (via SessionToken URL parameter). If not specified - the "shipRushClient" will use current url.

  • SessionToken (optional): Auth token. May be useful if developer implements a custom entry point for redirects. Javascript API sets this property automatically based on SessionToken URL parameters (if present).

  • IntegrationToken (optional): Licensing token. Contact ShipRush support team for discussing bulk licensing terms.

Note that using "out-of-the-box" authentication mechanism (without custom ReturnUrl and SessionToken) opens customers to data leaks via HTTP Referrer (see https://blog.mozilla.org/security/2018/01/31/preventing-data-leaks-by-stripping-path-information-in-http-referrers/). We recommend implementing at least one redirect after authentication to strip SessionToken from URL.

For non-visual Rate/RateShopping calls you have to handle both OnCompleted and OnError callback events.

var shipment = { <ShipmentView> };

shipRushClient.RateShop(
{
IsSandbox: true,
DeveloperId: "7be1ae06-1875-42c0-bd16-a82c016f43cc",
Shipment: shipment,
OnCompleted: function (data) {
var shipment = data.Shipment;
var availableServices = shipment.AvailableServices;
var rateExplanation = "";
for (i = 0; i < availableServices.length; i++) {
var rateDetails = availableServices[i];
var rate = rateDetails.Rate;
var shippingAccount = rateDetails.ShippingAccount;
rateExplanation +=
"ShippingAccountName: " + shippingAccount.DisplayName + "\r\n" +
"CarrierName: " + shippingAccount.Carrier.CarrierTypeName + "\r\n" +
"Carrier: " + shippingAccount.Carrier.CarrierType + "\r\n" +
"ServiceType: " + rateDetails.ServiceType + "\r\n" +
"ServiceTypeName: " + rateDetails.ServiceTypeName + "\r\n" +
"PackagingType: " + rateDetails.PackagingType + "\r\n" +
"PackagingTypeName: " + rateDetails.PackagingTypeName + "\r\n" +
"PackagingTypeAffectsRate: " + rateDetails.PackagingTypeAffectsRate + "\r\n" +
"Currency: " + rate.Currency + "\r\n" +
"CurrencySymbol: " + rate.CurrencySymbol + "\r\n" +
"CarrierRate: " + rate.CarrierRate + "\r\n" +
"ShippingCharges: " + rate.Total + "\r\n" +
"ExpectedDelivery: " + rate.ExpectedDelivery + "\r\n" +
"SaturdayDelivery: " + rate.SaturdayDelivery + "\r\n" +
"TimeInTransit: " + rate.TimeInTransit + "\r\n" +
"TimeInTransitDays: " + rate.TimeInTransitDays + "\r\n" +
"TimeInTransitBusinessDays: " + rate.TimeInTransitBusinessDays + "\r\n" +
"-----------------" + "\r\n\r\n";
}
$("#textLog").val(rateExplanation);
},
OnError: function (errorMessage) {
$("#textLog").val("Error: " + errorMessage);
},
});


Back to Top