Wednesday, August 27, 2014

Connecting to SAP Cloud for Customer from a Mobile App build with SAPUI5

Recently, a colleague found this document describing a REST/OData service that is available in Cloud for Customer. Using this service, it's possible to read, create and update data in your Cloud for Customer system from other systems or applications. I started to think about a nice scenario to create a mobile app using SAPUI5I came up with the idea of an app that enables customers to view and create service requests in the Cloud for Customer system by filling in a simple form. In this blog I will describe the basic steps to connect to the cloud for customer system using odata.

1. Set up a basic SAPUI5 Mobile application.

To set-up a basic SAPUI5 mobile app, I would recommend the steps described here. The documentation that you can find there is a basic step by step guide to set up a SAPUI5 application. I created a basic app with the following screens:

  • Main Screen for the menu
  • TicketList that lists the customers service requests
  • CreateTicket to create new service requests in the Cloud for Customer system.
  • Settings screen to facilitate customer authentication (not in this example)

2. Create a service that connects to Cloud for Customer

Since the service we are talking about is an OData service, we can use the ODataModel class in SAPUI5 to connect to it:

var oModel = new sap.ui.model.odata.ODataModel(
"<your cloud for customer system>/sap/byd/odata/v1/c4c.svc/", true, "username", "password");

3. Reading Customer Information

Let's assume that the customer was already identified inside the app. Using the customer's unique id (guid) from the system, we can read the account details:"/CorporateAccountCollection('<ACCOUNT GUID>')",  { 
      success: function(odata,response){ 
          // handle results here 
      error: function(error){ 
          //handle error here 

The result will contain information about the account, here is a small snippet from the JSON formatted result:

AddressFirstLineDescription" Den Bosch"

CityName"Den Bosch"

4. Reading Service Requests

To read the customer's service requests, we have to append /ServiceRequest to the url we used to read the customer information:"/CorporateAccountCollection('<ACCOUNT GUID>')/ServiceRequest",  { 
        success: function(odata,response){ 
             // handle results here 
        error: function(error){ 
              //handle error here 


The result looks something like this:

ChangedBy"Acorel Administrator"
CreatedBy"Acorel Administrator"
PartnerName"Arjan Nieuwenhuizen"
Description"Fix email to customer"

5. Creating Service Requests

I struggled a bit to get the create working. The Cloud for Customer OData service uses CSRF token validation, but the base url it uses to fetch a token from the server gives an error in the current version of Cloud for Customer (500 internal server error), so CSRF validation and creation fails. I made a small modification in the ODataModel class of SAPUI5 to get it to work again. I adjusted the refreshSecurityToken method use another url instead of the base url to get a new CSRF token. It reads one ticket from the server to get a valid response and a valid csrf token. Here's a snippet from the refreshSecurityToken method where the modification is done:

ODataModel.prototype.refreshSecurityToken = function(fnSuccess, fnError, bAsync) {
        var that = this, sUrl, sToken;
        // bAsync default is false ?!
         bAsync = bAsync === true;
        // trigger a read to the service url to fetch the token
        //sUrl = this._createRequestUrl("/");
        sUrl = this._createRequestUrl("/TicketCollection?$top=1");
        var oRequest = this._createRequest(sUrl, "GET", bAsync);

         oRequest.headers["x-csrf-token"] = "Fetch";

To create a new service request, you can use the following code snippet:

var serviceRequest = {};
serviceRequest.Type = "SRRQ";
serviceRequest.Description = "Fix machine 12121";
serviceRequest.CustomerID = "99999"; // Account/Customer Id, not the guid
serviceRequest.Priority = "1";
//etc. etc.

_modelBase.create("/TicketCollection", serviceRequest, { 
          success: function(odata,response){ 
               // handle results here 
           error: function(error){ 
               //handle error here 
           async: true

6. The final app I created

With the steps described above to get data from and to Cloud for Customer, I build a simple app that lists service request and has functionality to create a new one. Below are some screenshots of the final app I created. It's just a proof of concept that took me about 6 hours to build. I plan on expanding this app with more functionality, it might be a nice addition for our customers that are currently using Cloud for Customer.