Integration of SAP CPQ System in BTP

In this blog post, i would like to give you a brief overview ‘destinations’ in SAP BTP, Cloud Foundry. I will also show real time use case. “How to connect to SAP CPQ Service from BTP CAP Application”

This  will be similar approach “How  to connect to any external REST API /endpoint from BTP Application”

SAP BTP Offering   

SAP BTP Cloud Foundry environment offers two services for Connectivity

1) Connectivity service   : The Connectivity service provides a connectivity proxy that you can use to access on-premise resources.

Additionally you need The Cloud Connector is a proxy that connects On-Premise systems with the BTP.

2) Destination service :

BTP Destination Service support  outbound connectivity to the any third party systems .

You can retrieve and store the configuration information  of target system for example service endpoints and credential details in a secure way that applications that is required to access a remote service or system from your Cloud Foundry application. To consume the external service from cloud deployed application, you will create a Destination and a Destination Service.

Basically Destination service offers advantages compared to just hard-coding these connection  & configuration information of external system , in your Application

Advantages of BTP Destination  service

  • BTP Destination are powerful to establish a connection to a specific external system
  • Securely Store : You can securely store System information like URL , Credentials of external system
  • No Deployment : You can update this configuration without stopping  your application . Whereas if you hard code  this information you need to rebuild , deploy your application
  • No touch application code :
  • You can update system information without touching the application code.
  • You can maintain different configurations  as per your system (Dev, Test , Prod)
  • Destinations can be retrieved on behalf of multiple tenants
  • Reliable Connection :

The Destination take care of security, connectivity i.e authentication tokens for the target systems

  • Reusability

Instance Based Destination : Multiple applications can access the same systems without configuration destination for each application in your space

Sub account level Destination : If you configure destination at sub-account i.e global  destination then this will be available for all your  spaces in your BTP sub-account.

You can find more details in the SAP BTP Destination Service documentation.

SAP CPQ

SAP CPQ (Configure, Price, and Quote) is a multi-tenant SaaS application designated to help sales representatives to configure products, apply pricing and generate quotes, a highly configurable system . SAP CPQ is part of the SAP Sales Cloud portfolio.

A live version (example, www.webcomcpq.com)

If you are a beginner user of SAP CPQ, first read the Getting Started Guide to get familiar with the system

SAP CPQ Integration Guide

Now Let’s see how to implement  use case “How to connect to SAP CPQ Service from BTP CAP Application”

  • Create & Bind Destination Instance in BTP
  • Configure Destination
  • Consume the destination in BTP CAP Application

Step1 : Create & Bind Destination Instance in BTP

There are multiple ways to create destinations instance

  • Use BTP Cockpit

BTP >> Subaccount >> Space >> instances >> Create Destination Instance

  • Create & Bind Destination Instance Using the MTA Descriptor
  • BTP CLI

I would like to suggest to use approach 2 , When modelling a multitarget application (MTA), you can create and update destinations from your MTA

Create & Bind Destination Instance  Using the MTA Descriptor

resources:

name: demo-destination-service

  type: org.cloudfoundry.managed-service

  parameters:

    service-plan: lite

    service: destination

Bind the Destination services to your service in MTA

requires:

      – name: demo-destination-service

Step2 : Configure Destination

There are multiple ways to create destinations instance

  1. Using the Destinations Editor in the Cockpit
  2. Destination Service REST API
  3. Create Destinations Using the MTA Descriptor
  4. Create Destinations on Service Instance Creation

Lest try first approach

  • BTP >> Subaccount >> Space>> instances >> DestinationInstance
  • Click on New Destination
  • In the Destination Configuration, provide below information

Name  = Name of your choice and choose : Example

Type = HTTP.

URL =

Do not use the entire path for the URL. The URL should only be https://systemdomainYou can find more information on the used properties in th

Proxy Type = Internet

Authentication

User

Password

  • Technical User: the application calls another application/service with a technical user, e.g. used for machine to machine communication or for scheduling background jobs
       You need to ask CQP Admin to create Technical User & Once you receive credentials you can maintain in BTP Destination

  • Named User: the application calls another application/service with a business user, meaning the user information is propagated
  •   If you have requirement of SSO then you need to ask BTP SubAccount Admin , CPQ Admin to Establish Trust between BTP & CPQ for SAML flow
  • Once Trust established you need to maintain Destination as shown below

             You can read more about HTTP Destination & other options here

https://help.sap.com/docs/CP_CONNECTIVITY/cca91383641e40ffbe03bdc78f00f681/42a0e6b966924f2e902090bdf435e1b2.html?locale=en-US

Step3  : Consume the destination

Good to know

SAP Cloud SDK one-stop shop to overcome regulation programming challenges of connectivity . The SAP Cloud SDK comes with two variants—one for Java and one for JavaScript/Type-Script—and provides libraries, project templates to ease the development of cloud applications on SAP BTP. These libraries communicate with other SAP solutions and services, such as SAP S/4HANA CloudSAP SuccessFactors solutions, and OData services, just to name a few. At the same time, SAP Cloud SDK is fully compatible with the SAP Cloud application programming model (see https://cap.cloud.sap/docs/), which is SAP’s recommended approach to developing enterprise-grade services and applications on SAP BTP

In Package.json add destination details as shown below

“cds”: {

“ext_cpq_con_demo”: {

“kind”: “rest”,

“credentials”: {

“destination”: “ext_cpq_demo”,

“forwardAuthToken”: true

}

},

To connect to Required External Services in CAP Node JS you need to write below source code

Reference :

https://cap.cloud.sap/docs/node.js/cds-connect

https://cap.cloud.sap/docs/node.js/cds-serve

Example 1

To create a middleware with CAP, you only need to create a file srv/server.js and listen to the bootstrap event before you can initialize

const cds = require(‘@sap/cds’)// handle bootstrapping events…cds.on(‘bootstrap’, (app)=>{  // add your own middleware before any by cds are added

app.post(‘/invokecpqhandler’, async function (req, res) {

let response;

let status;

let json_data = { Param: JSON.stringify(req.body) }

const cpqservice = await cds.connect.to(‘ext_cpq_con_demo’)

try {

response = await cpqservice.send({

query: ‘POST /customapi/executescript?scriptname=scriptname,

headers: {

‘Content-Type’: ‘application/json’

},

data: json_data

})

status = 200;

} catch (error) {

response = error.message

status = 500

}

res.status(status).send(response);

})

});// delegate to default server.js:module.exports = cds.server

Example 2

A querystring parsing and stringifying library with some added security.

https://www.npmjs.com/package/qs

const cds = require(“@sap/cds”);

const qs = require(“qs”);

const getQuoteData = async (Param) => {

const cpqservice = await cds.connect.to(‘ext_cpq_con_demo);

const scriptname = “your_cpq_scriptname”;

const params = qs.stringify({

scriptname,

Param: JSON.stringify(Param),

});

try {

const response = await cpqservice.send({

method: “POST”,

path: “/customapi/executescript”,

data: params,

headers: { “content-type”: “application/json” }

});

return response;

} catch (err) {

console.log(err);

return {

message: “Error”,

error: err.message,

};

}

};