API Management, SAP Business Technology Platform, SAP Integration Suite, SAP S/4HANA

Create Purchase Orders in S/4HANA by enabling a public API from a S/4HANA On-Premise System using SAP API Management and Cloud Connector

The use case I wanted to set up was to expose an API from a S/4HANA on-premise system to consume it in a custom application developed in SAP Business Technology Platform, which its purpose is to create a Purchase Orders in the S/4HANA system.

Prerequisites:

  • Create an SAP Business Technology Platform (BTP) trial account (if case you don’t have one).
  • Enable the Integration Suite service and API Management in SAP BTP. This tutorial can give you through.
  • A S/4HANA system.
  • Install the Cloud Connector in the same network where your S/4HANA system resides: https://tools.hana.ondemand.com/#cloud.

Important note: Make sure your Cloud Connector is running otherwise you won’t be able to access it.

To run it (after you have downloaded and unzip it), double-click on go.bat:

When you have already changed the password, you must define your SAP BTP Subaccount.

Enter your SAP BTP information, at least with this info:

  • Subaccount ID
  • Region
  • User
  • Password

You should see it like this:

Now you can check in your BTP account that indeed the Cloud Connector is connected.

Now, as we want to consume the API from a custom SAP BTP App, we need to configure a Cloud To On-Premise connection.

Go back to your Cloud Connector and click on “Cloud To On-Premise” and add a System Mapping.

The blog post I mentioned above helped a lot to configure my System Mapping.

  • Back-end Type: ABAP System (I used Non-SAP System and worked as well)
  • Protocol: HTTP
  • Internal Host & Port: You can find it while executing a Get request in your SAP Gateway Client, open “Response in Browser” and you’ll see the Internal Host and Port in the “xml:base”, see below the [optional] test (or follow as the blog post mentioned above).
  • Virtual Host: you can provide any name (like: sanbox.company.com)
  • Virtual Port: you can provide any number
  • Principal type: None
  • Host in Request Header: Use Virtual Host
  • Description: anything you want (I left it blank)

Click on Finish. Now, add a resource to your System Mapping. I added /sap/opu/odata with the access policy “Path and All Sub-Paths” and leave the check box “active”. After these steps are done, you should see your system like this:

Now check again in your SAP BTP account, you should be able to see your Back-End system available.

To consume this service, it is not necessary to create a Destination in your SAP BTP account.

Now go to your SAP API Management account.

Create an API Provider.

  • Overview tab: Enter any name you want and description you want.
  • Connection tab:
    • Type: On Premise
    • Host: The Virtual Host you set in the Cloud Connector
    • Port: The Virtual Port you set in the Cloud Connector
  • Catalog Service Settings:
    • Path Prefix: /sap/opu/odata
    • Service Collection URL: /IWFND/CATALOGSERVICE;v=2/ServiceCollection
    • Authentication type: Basic
      • Username: Your S/4HANA username
      • Password: Your S/4HANA user password.

Click Save and Deploy.

[Optional:

If you want, you can test the Service Collection URL directly in your SAP Gateway Client.

1. Go to your SAP Logon, select your S/4HANA system and enter it using your S/4HANA credentials.
2. Enter the TCODE “/N/IWFND/MAINT_SERVICE”. Search in the icon “Catalog Service” and double-click in “Catalog Service Version 2”, so the button SAP Gateway Client gets available to press it.

3. Execute the Get request and click on “Response in Browser” to see the XML response:

]

Now you need to create the API.

Select the API Provider you just created and click on “Discover”.

For this exercise we are going to create Purchase Orders, so let’s search for “Purchase”:

You can find more in the SAP API Business Hub documentation.

Click in your API, Save and Deploy it.

Go to Resources and you’ll be able to see the Path and Payload needed to create Purchase Orders.

Open Postman, and let’s test it first by sending a Get request of the top 1 PO and let’s fetch the access token.

  • URL: your API Proxy URL
  • Authentication: Basic
    • Username: Your S/4HANA username
    • Password: Your S/4HANA user password.
  • Add in Headers:
    • x-csrf-token: Fetch

You can copy/paste this JSON Object as headers for your custom application.

{
    "Accept": "application/json",
    "Content-Type": "application/json",
    "x-csrf-token": "Fetch",
    "Accept-Encoding": "application/json",
    "Connection": "keep-alive",
    "Authorization": "<S/4HANA credentials in Base64>"
}

Now, let’s test the Post request. Of course, it’s important you test it with actual data Supplier, Material, Purchase Org, Company Code, etc. from your S/4HANA system. Remember to pass the x-csrf-token in the header.

I used this Payload as an example, to create a PO with a single material item:

{
    "CompanyCode": "R100",
    "PurchaseOrderType": "NB",
    "PurchasingDocumentDeletionCode": "",
    "PurchasingProcessingStatus": "05",
    "Supplier": "RSU1000000",
    "PurchaseOrderSubtype": "",
    "Language": "EN",
    "PaymentTerms": "0002",
    "CashDiscount1Days": "14",
    "CashDiscount2Days": "30",
    "NetPaymentDays": "0",
    "CashDiscount1Percent": "2.000",
    "CashDiscount2Percent": "0.000",
    "PurchasingOrganization": "R100",
    "PurchasingDocumentOrigin": "9",
    "PurchasingGroup": "WSG",
    "PurchaseOrderDate": "/Date(1492041600000)/",
    "DocumentCurrency": "EUR",
    "ExchangeRate": "1.00000",
    "ExchangeRateIsFixed": false,
    "ValidityStartDate": null,
    "ValidityEndDate": null,
    "SupplierQuotationExternalID": "",
    "SupplierRespSalesPersonName": "",
    "SupplierPhoneNumber": "",
    "SupplyingSupplier": "",
    "SupplyingPlant": "",
    "IncotermsClassification": "FOB",
    "CorrespncExternalReference": "",
    "CorrespncInternalReference": "4100000004",
    "InvoicingParty": "",
    "ReleaseIsNotCompleted": false,
    "PurchasingCompletenessStatus": false,
    "IncotermsVersion": "",
    "IncotermsLocation1": "Free on Board",
    "IncotermsLocation2": "",
    "ManualSupplierAddressID": "",
    "IsEndOfPurposeBlocked": "",
    "AddressCityName": "Bremen",
    "AddressFaxNumber": "",
    "AddressHouseNumber": "9C",
    "AddressName": "Joghurt Lieferant",
    "AddressPostalCode": "28217",
    "AddressStreetName": "Konsul-Smidt-Straße",
    "AddressPhoneNumber": "(0421)3889512",
    "AddressRegion": "HB",
    "AddressCountry": "DE",
    "AddressCorrespondenceLanguage": "EN",
    "to_PurchaseOrderItem": {
        "results": [
            {
                "PurchaseOrderItem": "10",
                "PurchasingDocumentDeletionCode": "",
                "PurchaseOrderItemText": "Roma Tomato Organic",
                "Plant": "R163",
                "StorageLocation": "R10A",
                "MaterialGroup": "RS11910",
                "PurchasingInfoRecord": "",
                "SupplierMaterialNumber": "",
                "OrderQuantity": "1",
                "PurchaseOrderQuantityUnit": "PC",
                "OrderPriceUnit": "PC",
                "OrderPriceUnitToOrderUnitNmrtr": "1",
                "OrdPriceUnitToOrderUnitDnmntr": "1",
                "DocumentCurrency": "EUR",
                "NetPriceAmount": "0.00",
                "NetPriceQuantity": "1",
                "TaxCode": "",
                "TaxDeterminationDate": null,
                "TaxCountry": "",
                "PriceIsToBePrinted": true,
                "OverdelivTolrtdLmtRatioInPct": "0.0",
                "UnlimitedOverdeliveryIsAllowed": false,
                "UnderdelivTolrtdLmtRatioInPct": "0.0",
                "ValuationType": "",
                "IsCompletelyDelivered": false,
                "IsFinallyInvoiced": false,
                "PurchaseOrderItemCategory": "0",
                "AccountAssignmentCategory": "",
                "MultipleAcctAssgmtDistribution": "",
                "PartialInvoiceDistribution": "",
                "GoodsReceiptIsExpected": false,
                "GoodsReceiptIsNonValuated": false,
                "InvoiceIsExpected": false,
                "InvoiceIsGoodsReceiptBased": false,
                "PurchaseContract": "",
                "PurchaseContractItem": "0",
                "Customer": "",
                "Subcontractor": "",
                "SupplierIsSubcontractor": false,
                "ItemNetWeight": "0",
                "ItemWeightUnit": "LB",
                "TaxJurisdiction": "",
                "PricingDateControl": "",
                "ItemVolume": "0.000",
                "ItemVolumeUnit": "",
                "SupplierConfirmationControlKey": "",
                "IncotermsClassification": "",
                "IncotermsTransferLocation": "",
                "EvaldRcptSettlmtIsAllowed": false,
                "PurchaseRequisition": "",
                "PurchaseRequisitionItem": "0",
                "IsReturnsItem": false,
                "RequisitionerName": "",
                "ServicePackage": "0",
                "EarmarkedFunds": "",
                "EarmarkedFundsDocument": "",
                "EarmarkedFundsItem": "0",
                "EarmarkedFundsDocumentItem": "0",
                "IncotermsLocation1": "",
                "IncotermsLocation2": "",
                "Material": "4909",
                "InternationalArticleNumber": "",
                "ManufacturerMaterial": "4909",
                "ServicePerformer": "",
                "ProductType": "1",
                "ExpectedOverallLimitAmount": "0.00",
                "OverallLimitAmount": "0.00",
                "PurContractForOverallLimit": "",
                "ReferenceDeliveryAddressID": "",
                "DeliveryAddressID": "",
                "DeliveryAddressName": "Berlin Store",
                "DeliveryAddressName2": "",
                "DeliveryAddressFullName": "Berlin Store",
                "DeliveryAddressStreetName": "St. Wolfgang-Str",
                "DeliveryAddressHouseNumber": "13",
                "DeliveryAddressCityName": "Berlin",
                "DeliveryAddressPostalCode": "10178",
                "DeliveryAddressRegion": "11",
                "DeliveryAddressCountry": "DE",
                "DownPaymentType": "",
                "DownPaymentPercentageOfTotAmt": "0.00",
                "DownPaymentAmount": "0.00",
                "DownPaymentDueDate": null,
                "BR_MaterialUsage": "",
                "BR_MaterialOrigin": "",
                "BR_CFOPCategory": "",
                "BR_IsProducedInHouse": false,
                "ConsumptionTaxCtrlCode": "",
                "ProductSeasonYear": "",
                "ProductSeason": "",
                "ProductCollection": "",
                "ProductTheme": "",
                "SeasonCompletenessStatus": "",
                "ProductCharacteristic1": "",
                "ProductCharacteristic2": "",
                "ProductCharacteristic3": "",
                "PurchasingParentItem": "0",
                "SubItemCategory": "",
                "CrossPlantConfigurableProduct": "",
                "DiversionStatus": "",
                "ReferenceDocumentNumber": "",
                "ReferenceDocumentItem": "0",
                "PurchaseOrderReferenceType": "",
                "ReferenceDocumentScheduleLine": "0",
                "ArticleCategory": "00",
                "ItemHasValueAddedService": "",
                "ValAddedSrvcParentItmNumber": "0",
                "StockSegment": "",
                "RequirementSegment": ""
            }
        ]
    }
}

In conclusion, you can benefit from SAP API Management to expose all APIs from your on premise back-end systems, in this example S/4HANA. You can leverage this blog post to prototype custom applications to create Purchase Orders in S/4HANA, even go further and integrate it with SAP Workflow Management for instance, to request first the approval of these Purchase Orders before creating them. SAP Business Technology Platform offers you flexibility to keep extending functionality to your different IT systems/applications (and integrating them).

Rating: 0 / 5 (0 votes)