Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
MajoMartinez
Advisor
Advisor
Hello!

This blog post belongs to a Tutorial Blog Post series about where its simulating a sales transaction on buying a new refrigerator using an SAP Build Apps (formerly SAP AppGyver )custom app, while consuming different SAP and 3rd party services.

As we saw in the previous blog posts, we have already configured Open Connectors to connect in an easy way with a 3rd party payment platform as it is Stripe, and leverage Message Mapping capabilities within Cloud Integration to execute a POST request to SAP Sales and Service Core (formerly SAP Cloud for Customer or SAP C4C) to create a Sales Order only after the payment transaction is successful. Also, we've configured a HTTP receiver adapter to send URL encoded parameters to send SMS messages, as a notification that the order was successfully created using a 3rd party solution (Twilio).

Now in this last blog post of the Tutorial Blog Series, we are going to call this Integration Suite API endpoint from a custom application in SAP AppgGyver. Here's a sneak peak of the custom application consuming the API from SAP Integration Suite:



 

Tutorial Blog Post Series - Sections


They are divided into several blog posts to not make it so long in one alone.

  1. Build an integral SAP Integration Suite project and consume it from a SAP Build Apps custom app - Tutorial Blog Post Series Introduction [Link]

  2. Consume a Stripe service from SAP Open Connectors and SAP Cloud Integration to create payment transactions [Link]

  3. Set up Write, Filter and Get tasks in SAP Cloud Integration to save, filter and get your needed message to execute other operations in your Integration Flow [Link]

  4. Consume a SAP Sales and Service Core API to create Sales Orders using an OData receiver adapter in SAP Cloud Integration [Link]

  5. Send application/x-www-form-urlencoded parameters to a HTTP receiver adapter in SAP Cloud Integration to send SMS messages consuming a Twilio API [Link]

  6. Integrate SAP Build Apps with SAP Integration Suite, consuming an Integration Flow levering SAP API Management policies [Here you are in this blog post]


 

Now, we are going to set up the API management policies needed to integrate our IFlow / CPI Endpoint with the custom application in SAP Build Apps.

To configure this step we need to keep in mind that:

  1. We may run into CORS issues while calling the API

  2. If we call the API endpoint like we are doing it right know with Postman, we would need to put our SAP BTP credentials in SAP Build Apps.


For these reasons we need to leverage SAP API Management capabilities and apply policies to:

  1. Avoid CORS issue while calling the API from SAP Build Apps

  2. Enable an API Key to use it, instead of using your SAP Business Technology Platform (and therefore SAP Integration Suite) credentials. This is critical for security purposes.
    a. In addition, if you have a productive SAP Build Apps account, check out this new feature regarding SAP BTP Authentication in a SAP Build Apps application in this blog post by marchuber03


 

Let's start setting up the policy to avoid CORS issues


This blog from Atakan Tokgoz was quite helpful to execute this task. However I needed to make some changes for the policy to work in SAP Build Apps with my application (this is my personal experience, I don't rule out other ways to do it). I'll put it step by step below.

Go to your SAP API Portal (in the main SAP Integration Suite portal). Create an API and select URL. Here you're going to paste your IFlow endpoint from past blog posts. Give it a name, I named mine "APIBestRunDemo". Give it a path, I put the same path I used for my IFlow "/https/salesOrder". And service type "REST".

You should see it like this:


After creating it, go to the Proxy Endpoint tab and add the following in this order, and save it:


Now, let's go to Policies (if it doesn't show up in the top-right of your screen, click on the 3 dots). Here we'll add the required policies to avoid CORS issues while calling this API from SAP Build Apps and configure the API Key policy later on.

On the Edit Mode, start adding the Policies as followed:

In the PostFlow inside the Proxy Endpoint configuration, add an "Assign Message" policy as an "OutgoingResponse" and name it "setCORS". Like this:



Copy and paste this script:
<!-- This policy can be used to create or modify the standard HTTP request and response messages -->
<AssignMessage async="false" continueOnError="false" enabled="true" xmlns='http://www.sap.com/apimgmt'>
<Set>
<Headers>
<Header name="Access-Control-Allow-Origin">*</Header>
<Header name="Access-Control-Allow-Headers">set-cookie, origin, accept, maxdataserviceversion, x-csrf-token, authorization, dataserviceversion, accept-language, x-http-method, content-type, X-Requested-With, apikey</Header>
<Header name="Access-Control-Max-Age">3628800</Header>
<Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
<Header name="Access-Control-Expose-Headers">set-cookie, x-csrf-token, x-http-method</Header>
</Headers>
</Set>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<AssignTo createNew="false" type="response">response</AssignTo>
</AssignMessage>

Note: notice that I'm already adding "apikey" as a header in the policy.

You should look it like this:


In the ProxyEndpoint click on "+" to add one. Name it "preflight" and in the condition string paste: request.verb == "OPTIONS". Like this:



This is all we need to avoid CORS issues when calling our API from SAP Build Apps.

 

Let's now add the Verify API Key policy


This great blog post from benno_grimm about SAP API Management and policies. It was quite helpful for configuring the API Key. I'll put it step by step below for the purpose of the exercise.

Before adding the needed policies, let's create first a Key Value Map with our CPI credentials (to access the CPI API endpoint). We will need this credential to reference it in the API Key Policy.

Go to Configure (click on the tool icon) -> go to the "Key Value Maps" tab and create one.


Put a name and declare your CPI credentials (username and password), I named mine "CPICredentials" and check the "Encrypt Key Value Map" box.


Now let's add the policies needed to create an API Key. Go back to your API policies.

In the TargetEndpoint we are going to add 3 policies in the PreFlow.

  • First, we are going to get the CPI credentials we created before as a Key Value Map. Add a Key Value Map Operations policy, name it and leave it as a Incoming Request. Like this:






    • Copy and Paste this script (see that I'm referencing my CPICredentials with the mapIdentifier parameter):




<KeyValueMapOperations mapIdentifier="CPICredentials" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
<!-- Read parameter with key "username" and assign its value to private variable BasicAuthUsername-->
<Get assignTo="private.BasicAuthUsername" index='1'>
<Key><Parameter>username</Parameter></Key>
</Get>
<!-- Read parameter with key "password" and assign its value to private variable BasicAuthPassword-->
<Get assignTo="private.BasicAuthPassword" index='1'>
<Key><Parameter>password</Parameter></Key>
</Get>
<Scope>environment</Scope>
</KeyValueMapOperations>​

 

Like this:



  • Then, add a Basic Authentication policy, name it and leave it with the "IncomeRequest" stream. Like this:






    • Copy and paste this script:




<BasicAuthentication async='true' continueOnError='false' enabled='true' xmlns='http://www.sap.com/apimgmt'>
<!-- Operation can be Encode or Decode -->
<Operation>Encode</Operation>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<!-- for Encode, User element can be used to dynamically populate the user value -->
<User ref='private.BasicAuthUsername'></User>
<!-- for Encode, Password element can be used to dynamically populate the password value -->
<Password ref='private.BasicAuthPassword'></Password>

<!-- Assign to is used to assign the encoded value of username and password to a variable. This should not be used if the operation is Decode -->
<AssignTo createNew="true">request.header.Authorization</AssignTo>
</BasicAuthentication>​

 



    • You should look it like this:






  • Lastly, we are going to add a API Key verification policy to request the API Key every time our API is called (we'll later need to create the API Product and subscribe to the application to get our API Key). Let's add the "Verify API Key" policy, same in the Preflow. Like this:






    • Copy and paste this script:




<!--Specify in the APIKey element where to look for the variable containing the api key--> 
<VerifyAPIKey async='true' continueOnError='false' enabled='true'
xmlns='http://www.sap.com/apimgmt'>
<APIKey ref='request.header.ApiKey'/>
</VerifyAPIKey>




    • And this should be the first policy to be triggered. Make sure it is set it up as the first one (you can change the order with the arrows in the top-right). Like this:






Now click on Update, Save and Deploy your API project.


 

Let's create an API Product and Subscribe to the Application


Now we need to create the API Product. Go to the pencil icon (develop), click on the "Products" tab and create one. I'm defining mine as APIBestRunDemoProduct.


Reference your API to your Product.


Now you can Publish your Product. Now go to the API Business Hub Enterprise portal.


You should be able to see it in your SAP API Business Hub:


Enter the API product and subscribe it by creating a new Application:


I named mine "APIBestRunDemoApplication", like this:


Here's where you can get your API Key, crucial to authenticate to this API endpoint when consuming its service.






 

Let's add additional tasks to the IFlow for the purpose of the integral exercise


Right now, as following the whole exercises, the IFlow is returning us the SMS message sent by consuming the Twilio API. But for the purpose of the exercise with SAP Build Apps, I'm going to use as the return message, mainly the receipt URL when the payment transaction is successfully done with Stripe. For this, we need to save this message in the IFlow and retrieve it at the end of the IFlow.

Remember the blog about "Set up Write, Filter and Get Tasks in the Integration Flow..." for filtering the payment data and later calling the SAP C4C OData service? well, we are going to do the same, but in this case to retrieve the receipt URL from the Stripe request response.

Add a Write task after the Stripe Connector request reply, and configure the task as following:


And now add a Get task at the end of the IFlow to retrieve this returned message:


Save and deploy your IFlow.

 

Now let's test the integration with SAP Build Apps


Go to your SAP Build Apps custom app, click on "Data" on the menu and Add a Data Resource and select "REST API direct integration". Remember we are using for this exercise an already created custom app, if you haven't done it yet, you can follow this blog post I created before.


Copy and paste your API endpoint from SAP API Management as the base resource url and name your Data Resource (I named mine "IntegrationSuite_API_CORS"):


Go now to the "Create Record (POST)" section, make sure "id" is erased from the relative path and enter your API Key as a header (make sure you don't put it as optional and mark it as static).


Now, let's set up the custom needed schema for testing a POST request. Remember the payload structure we are using for this exercise:
{
"AppGyverSalesOrder": {
"customer": {
"ObjectID": "<Object ID from SAP C4C>",
"BuyerPartyID": <BuyerPartyID from SAP C4C>
},
"paymentData": {
"amount": <Payment transaction amount to be processed in Stripe>,
"customer": "<stripe customer id>",
"currency": "<currency selected in stripe account>",
"source": "<card id>",
"description": "Test payment via CPI"
},
"product": [
{
"ProductID": "<Product ID from SAP C4C>",
"Quantity": <Product quantity to be purchased>
}
]
}
}

So to "translated it" into the custom schema in SAP Build Apps, you'll need to add these properties manually, as shown in the following image:


Now, go to the Test tab and open your custom object, where you are going to add the values as the payload for testing.


And setting for testing purposes a Product ID from SAP Sales and Service core (formerly SAP Cloud for Customer or SAP C4C).


Save it and now click on "Run Test". You should see this response "Status: OK":


If we check on the Stripe developers account, you can see the amount and description "Ta dá!! Integration scenario is set up" 🙂 :


Now, we need to set up the schema from response, to let SAP Build Apps know we want to create a variable for getting the receipt url.


Now you can see "receipt_url" from the return message, as a property, like in the following image. Save your configuration.


Now, what you need to do is to create a variable to enable this "receipt_url" as a variable to be linked in your application UI. Click again on "Data" to close it and go back to your application design. Click on "View - Variables" and click on "Add Page Variable" as it is in the following image:


 

Finally, let's call the service from the custom application in SAP Build Apps


Remember we're following this previous exercise of a custom application developed in SAP Build Apps (as mentioned in the prerequisites in the Introduction blog post). The differences are:

  1. We are going to add one field to the QR code (ProductID) for the purpose of the integration exercise and update the variables we've already created in our SAP Build Apps app. Of course, in reality you would want to add as many Product fields as necessary to execute the Sales Order transaction.

  2. We are going to add an additional Button (to trigger the API call) and an WebView component (to see the Stripe's payment confirmation with the receipt url).


Let's go with the 1st point:


Go back to your QR code generator (I'm using this one), and paste this JSON object:
{
"ProductID": "<your SAP C4C product ID>",
"model": "Samsung French Door 29 ft",
"imgURL": "https://samsungmx.vtexassets.com/arquivos/ids/180853-800-auto?width=800&height=auto&aspect=true"
}

Save the generated QR Code:


Go back to your SAP Build Apps custom app, and click on "View - Variables", go to Page Variables and update them, by adding "ProductID" as a new property of the parsedJson object:


Click again in "View - Variables" to go back to your UI editor, change the first title of the Product from "brand" to the "model" page variable, to make it consistent with the generated QR code:


Then, add the ProductID page variable to the second Product component:


Leave the image url as it is in the original exercise.

Let's go now with the 2nd point:


Add the button and change its name to "Create Order consuming CPI":


Add the WebView component (this one, you have to install it):


And link it to the page variable "receipt_url" we created before. Like this:


Let's go back to the button and add it the needed logic. Select the button and click on the bottom-right "Show logic for BUTTON.." and add a "Create Record" logic component.

  • In the Resource name: select the Data Resource Id we created before "IntegrationSuite_API_CORS"

  • For the Records properties: here you'll see the custom schema we created before for requesting POST calls from SAP Build Apps.



Click on "Record properties" -> "Custom object". And add the newly created property: ProductID.


After save it, you'll see it like this in the Product List Object:


If you want, you can create as may variables as you want to make the demo more dynamic. As I mentioned before, for the purpose of the integration exercise I'll use only ProductID. If you are following me, you'll see your payload structured in SAP Build Apps, like this:


Save it.

Now let's configure the getting of the receipt url from the Stripe request response. Add a Javascript logic component:


Erase the original "input1" name and change it for "response". Click to bind the data.


Select the binding type: Output value of another node, then create record and select receipt_url as field we want to get from the response.


Save it and close it.

Now, let's add a Dialog Toast, just to show up a message that the request call was successful.


And now we are going to finally retrieve the receipt url of the payment transaction. Add a "Set page variable" logic component and add as the variable name the page variable we created before (receipt_url):


Link the variable like this and save it:


Do the same for assigning the value. Here you are going to link it with the receipt_url Javascript component we created before:


Now it's time to test the app and the whole integration 🙂

 

Test the results of the whole integration scenario now


Grab your phone and enter your SAP Build Apps mobile app. Link it to your account as explained in the original exercise. Read the generated QR code:


 

And click on "Create Order consuming CPI" and you'll see that the order was successfully created. Like this:


 

Checking in the SAP Sales and Service Core tenant (formerly SAP Cloud for Customer / SAP C4C):


 

Conclusions


Congratulations for making it to this last part. You've successfully created an E2E integration demo using different SAP and third-party solutions. Just to summarize, we've integrated solutions and services from:

  • SAP Sales and Service Core (formerly SAP C4C)

  • Twilio

  • Stripe

  • SAP Integration Suite:

    • SAP Open Connectors

    • SAP API Management

    • SAP Cloud Integration



  • SAP Build Apps


To create a Sales Order in SAP C4C, after a the payment transaction using Stripe is successful, and then sending a SMS with the Order Id confirmation.

Hope you've enjoyed this exercise as much as I did 🙂

 

Want to know more about SAP Business Technology Platform?


To learn more about SAP BTP, see the learning journey Discover SAP Business Technology Platform, a great introduction to BTP and the Intelligent Enterprise strategy to see what it’s all about for free. Discover BTP, LCNC plus much more free learning at SAP Learning site.

 

 

 
8 Comments
quovadis
Product and Topic Expert
Product and Topic Expert

Hello mariajosemq741 , a great blog of yours. Thanks for showcasing the value of SAP API Management and how one can leverage it as a conduit to implement various SAP security policies like the CORS policy for instance.

Personally, I can see a great added value of API Management as a LCNC tool per se whenever there is need to implementing various API packages of any SAP LOBs with the SAP compliance in mind.

Personally I tried it and did it for SAP S/4HANA Cloud APIs, for SAP S/4HANA OP, for SAP SuccessFactors, SAP Analytics Cloud or even SAP API Business Hub itself. It is so worth it. And additionally any of the "proxified" and CORS-enabled APIs can be used out-of-the-box with SAP Appgyver.

kind regards; Piotr

PS.

FYI: Here goes a selection of my own blog posts where I feature SAP API Business Hub, SAP Appgyver and API Management:

MajoMartinez
Advisor
Advisor
0 Kudos

Hi Piotr, thanks for sharing your experience about API Management and AppGyver, and for sharing your blog posts! They are very useful to keep collaborating with the SAP community.

Low-code/no-code will continue to increase interest as it helps to reduce time to value in developing custom applications, and API Management is also key to this purpose.

ag3silaus
Participant
0 Kudos

Hello mariajosemq741,

Foremost, thank you for this excellent Blog series. I'm stuck at one step and need help. I followed all

the steps correctly, but I still get the following error in Appgyver. One thing I noticed is that even

though, I created a new Key Value Map. It shows Key Value Map Associated (undefined) in API

overview.

 

 

Kind regards

Burak

MajoMartinez
Advisor
Advisor
0 Kudos

Hi Burak,

Thanks for your comments!

I noticed that too, for some reason it doesn't show up the Key Value MAp associated to the API in my environment as well, however this didn't stop the API from working correctly. Make sure you are pointing the same name of the Key Value Map / Credentials in the API Key script's policy.

Another thing you can do is debug the browser when testing the POST call, to really understand if the issue is the avoid CORS policy or if it is something else.

 

 

Keerthana
Participant
0 Kudos

Hi mariajosemq741 ,

I am trying the same thing to deal with the CORS issue so i am only doing the first part,but once i add the preflight the update option is getting disabled and not getting enabled.And previously working APIs are throwing 502 gateway error(In trial account).Could you please help me with this.

Thanks & Regards,
Keerthana

MajoMartinez
Advisor
Advisor
Hi Keerthana,

This happened to me to, I assume it's because it is a trial account. What I would recommend (and it worked for me), try to click Policies first and then inside it click on Edit. Add the Preflight first and then setCORS policy. The Update button should be enabled to click it.
stephen-le
Explorer
0 Kudos

Hi mariajosemq741,

Thank you so much for such a great series. It really helps me a lot. I am curious about 2 topics I'd like to ask for your opinion:

  1. How can we handle a commit/rollback situation where one of the request-reply to a receiver failed to execute? Does it mean that the request-reply to the previous Receivers got rollback automatically (let's say we trigger a Odata Create entity in one of the previous Receiver already) or do we have to always consider the rollback while designing our iflows?
  2. Let's say I have a CAP application (MTA) with 1 UI, 1 Microservice and 1 SAP HANA Cloud db. The UI is similar to the appgyver UI where we have the button "Create Order Consuming CPI". When I click on this button, I would like to create a table record in my CAP Database and also trigger the CPI endpoint as well. My question is: Should I make a request-reply to the CAP microservice Receiver in the CPI iflow to handle creating a new record in my CAP Hana DB or should my CAP node application create that entry first and then make a call the the CPI endpoint? With the first option, I assume that the sender of my iflow is the CAP Microservice and one of the Receiver in my iflow is that CAP Microservice. With the second option, we dont' have to change the existing iflow, however we have to handle the commit/rollback for this because we make 2 separate calls from the CAP UI (1 to the CAP microservice to create SAP HANA table entry, 1 to trigger the CPI endpoint). Which option should be the right approach?

Could you please share some thoughts? Thank you!!

Thanks & Regards!!

Stephen

MioYasutake
Active Contributor
0 Kudos
Hi mariajosemq741,

Thank you for this blog post. I was able to follow it to build my own API proxy.

This may be a beginner question, but in the policy, what does "preflight" proxy endpoint do? Why is this required?