You are on page 1of 20

How to consume an account web service via PHP 1

How-To Guide
Document Version: 1.0 2014.12.05

How to Call SAP Cloud for Customer SOAP API for


Account Creation and Query from an External PHP
Application
Copyright
How to consume an account web service via PHP 2

Content

1 Introduction ..................................................................................................................................................... 3
1.1 Business Scenario ........................................................................................................................................ 3
1.2 Prerequisites ................................................................................................................................................. 3
2 Download WSDL files from C4C ................................................................................................................... 4
2.1 Edit the WSDL files....................................................................................................................................... 5
3 PHP consumption application structure ...................................................................................................... 6
4 Create application index file .......................................................................................................................... 7
5 Extend PHP class SoapClient ..................................................................................................................... 10
6 Query C4C from PHP using Account ID ..................................................................................................... 11
6.1 Execute query in C4C system .................................................................................................................... 11
6.2 Display query results .................................................................................................................................. 12
6.3 Query an existing account from C4C ......................................................................................................... 14
7 Create an Account ........................................................................................................................................ 15
7.1 Create Account in the C4C system ............................................................................................................ 15
7.2 Display account creation return .................................................................................................................. 17
7.3 Create an account in C4C using web service ............................................................................................ 18
How to consume an account web service via PHP 3

1 Introduction
1.1 Business Scenario
Customers or Partners who use SAP Cloud for Customer solution tend to already have another
running system, which needs to export its data to SAP Cloud for Customer system or even
display the data stored inside SAP’s solution. This is the reason why a web service integration
between SAP Cloud for Customer and other systems is important.

1.2 Prerequisites
SAP Cloud for Customer
Initial setup and configuration was already performed in tenant as it is mentioned in the SAP Cloud for
Customer Administrator Guide. A business user with Customer work center assigned is required to execute
the web service’s requests afterwards.

XAMPP (or another PHP Development Environment)


PHP applications need an environment to be executed, such as XAMPP or LAMP.

Notepad++ (or another text editor)


Coding and text edition are required for this guide.
How to consume an account web service via PHP 4

2 Download WSDL files from C4C


In order to access the web service, the WSDL file must be downloaded from the Cloud for Customer
system. Since this application is going to use both query and creation services, there are two different files
that must be downloaded.
The WSDL files are located in the path Application and user management > Input and output Management
> Service Explorer.

Download Maintain Accounts WSDL


In the Service Explorer screen, search for “*Maintain Accounts*” in the Find field. Select accordingly and
download the WSDL file:

Save the file as “ManageAccounts.wsdl”.

Download Find Accounts WSDL


Repeat the same steps and search for “*Find Accounts*”. Select accordingly and download the WSDL file:

Save the file as “QueryAccounts.wsdl”.


How to consume an account web service via PHP 5

2.1 Edit the WSDL files


The files downloaded from Cloud for Customer system must be edited before being used, due to security
polices issues.
Open the files with Notepad++ and search for “UsingPolicy wsdl:required”. The standard value for this field
is true, but it must be changed to false:

This change is required in both WSDL files.


How to consume an account web service via PHP 6

3 PHP consumption application


structure
The web service consumption is going to be built on PHP language. The application will have the following
structure:

The css folder will have the bootstrap library, and the js folder will have jQuery library, validation files and a
file containing country and state info, which will be used later by the app. As this is not the focus of the
guide, there will just this overview about it.

The wsdl folder is where are located the WSDL files which were downloaded and edited in the previous
step.
How to consume an account web service via PHP 7

4 Create application index file


The index.html file is the home page of the application. It contains two different forms: one for account
query and one for account creation. The focus of this guide is not the html part as well, so follows a quick
overview about the forms:

Query Account form


This form will have only the Account ID field, which is the only necessary field for query an account in C4C.
The action of the form must send the parameters via POST to the file “search_account.php”.

Create Account form


This form will have the following fields:
• Account Name
• E-mail
• Country
• State
• City
• Street
• Number
• Postal Code
• Phone Number
• Contact Name
• Contact E-mail
The action of this form must send the parameters via POST to the file “new_account.php”.

C4C Authentication fields


Have in mind that every web service call to a Cloud for Customer system must have a C4C user and
password, which give the permission for the request to be completed. In queries and creations, the user
will have to enter a valid authentication.
For this, the index will have username and password fields, and a checkbox indicating if his connection uses
prox. This indicator is required due to a problem with PHP, where it is not able to find the system in proxy-
based connections. This issue will be explained in details in section 3.2.

The index screen must have the fields as follows:


How to consume an account web service via PHP 8
How to consume an account web service via PHP 9
How to consume an account web service via PHP 10

5 Extend PHP class SoapClient


PHP’s default class SoapClient has an issue with proxy-based connections that prevents the requests from
reaching the C4C system. As many of SAP’s customers and partners use proxy in their connections, it is
necessary to resolve this problem.

The workaround for this is defining a login details array, where the proxy host and proxy port are defined,
when necessary. Additionally, a new parameter must be added to the location of the system: the sap-
language has to be defined as “EN”.

At the end, the file must be as follows:

<?php

global $loginDetails;
// variable with proxy information, which is completed when necessary
$loginDetails = array(
'proxy_host' => '',
'proxy_port' => '',
'verify_peer' => true,
'allow_self_signed' => true,
'connection_timeout' => 300,
'exceptions' => true,
'login' => '',
'password' => ''
);

class ByDSoapClient extends SoapClient


{
private $defaultLocation = null;

function __construct($wsdl, $location, $options)


{
global $loginDetails;

$this->defaultLocation = $location;

use_soap_error_handler(true);
parent::__construct($wsdl, array_merge($loginDetails, $options));
}

function __doRequest($soapRequest, $location, $action, $version, $one_way = NULL)


{
$domDocument = new DOMDocument("1.0");

$location = $this->defaultLocation;

// Read the language from the configuration file


$language = 'EN';
if (!empty($language)) {
$location = $location . '?sap-language=' . $language;
}

//Consuming the web service


$soapResponse = parent::__doRequest($soapRequest, $location, $action, $version);

if (empty($soapResponse))
{
throw new Exception($this->__soap_fault->faultcode . ": Cannot connect to
host: $location. Reason:" . $this->__soap_fault->getMessage());
}

return $soapResponse;
}
}
?>

This class is going to be instantiated afterwards, in the web service consumption on both queries and
creations.
How to consume an account web service via PHP 11

6 Query C4C from PHP using Account


ID
This section describes using the PHP application to query C4C. The query section of the application
consists in one PHP file responsible for displaying the return on the screen and one PHP class responsible
for querying the account on the C4C system.

6.1 Execute query in C4C system


The query is executed in the class QueryAccounts.php, which performs three main steps to query accounts
on the C4C system.

First, it generates the XML that is going to be used later on the web service request. This XML is a
predefined string, with all the parameters required by C4C system to query an account, concatenated with
the account ID received via parameter from the form.

After that, the XML string is converted into a SOAP variable that will be passed as a parameter later on the
query.

The final step is execute the query. The SOAP client created refers to the extended class (created in step
3.2) which receives the WSDL location, the web service location and the authentication data as a
parameter. The authentication data may or may not have proxy information, depending on the user’s
connection.

The complete class must look like this:

<?php

require_once 'ByDSoapClient.php';

class QueryAccounts
{

public function execute($accountId, $username, $password, $proxy_enabled) {


$xml = $this->generateXml($accountId);
$soapVar = $this->generateSoapVar($xml);
$result = $this->executeQuery($soapVar, $username, $password, $proxy_enabled);
return $result;
}

public function executeQuery($soapVar, $username, $password, $proxy_enabled) {


$auth = null;
if ($proxy_enabled == true) {
$auth = array(
'proxy_host' => 'proxy',
'proxy_port' => '8080',
'login' => $username,
'password' => $password
);
} else {
$auth = array(
'proxy_host' => '',
'proxy_port' => '',
'login' => $username,
'password' => $password
);
}

$wsdl = 'wsdl/QueryAccounts.wsdl';
$location =
'https://<YOUR_SYSTEM_TENANT_HERE>/sap/bc/srt/scs/sap/querycustomerin1?sap-
vhost=<YOUR_SYSTEM_TENANT_HERE>';
$soapClient = new ByDSoapClient($wsdl, $location, $auth);

try {
$result = $soapClient->FindByElements(
new SoapParam($soapVar, 'CustomerSelectionByElements')
);
return $result;
} catch(Exception $e) {
How to consume an account web service via PHP 12

$message = $e->getMessage();
}
}

public function generateSoapVar($xml) {


try {
$soapVar = new SoapVar($xml, XSD_ANYXML, null, null, null);
return $soapVar;
} catch(Exception $e) {
$message = $e->getMessage();
}
}

public function generateXml($accountId) {


$xml = '<ns1:CustomerByElementsQuery_sync>
<CustomerSelectionByElements>
<SelectionByInternalID>
<InclusionExclusionCode>I</InclusionExclusionCode>
<IntervalBoundaryTypeCode>1</IntervalBoundaryTypeCode>
<LowerBoundaryInternalID>' . $accountId .'</LowerBoundaryInternalID>
<UpperBoundaryInternalID></UpperBoundaryInternalID>
</SelectionByInternalID>
</CustomerSelectionByElements>
<ProcessingConditions>
<QueryHitsUnlimitedIndicator>true</QueryHitsUnlimitedIndicator>
</ProcessingConditions>
</ns1:CustomerByElementsQuery_sync>';
return $xml;
}

As seen, the XML does not need the <soapenv:Envelope>, <soapenv:Header> and <soapenv:Body> tags,
since they are provided automatically when the XML is converted to a SOAP variable.
In addition, the InclusionExclusionCode is hardcoded to I, which means the selection must return an
account with an ID equal to the ID given. The ProcessingConditions determine that the query can return an
unlimited number of registers, but our application will only be able to handle the first one. Additionally,
since it searches by ID, there must not be duplicated registers on the system.

The generateSoapVar function has the only purpose of converting the string into an SOAP parameter,
passing the required parameters to the standard PHP class SoapVar.

The function executeQuery is the one that runs the web service. The authentication has a validation for the
proxy, and the SOAP client is created using the extended class created on step 3.2. The SOAP client created
has all the web service’s operations, and the one used by the application’s query is “FindByElements”. This
operation requires a SOAP parameter, which has the name “CustomerSelectionByElements”.

All the errors that might happen (such as no account found for that ID or authentication error) are treated
in the PHP file that displays the return of the query.

6.2 Display query results


This is the file to which the action the form points, meaning that it receives all the parameters from POST,
passes it to the QueryAccounts class (created in step 6.1) and treats the result to display it accordingly on
the screen.

After receiving the parameters via POST, an instance of QueryAccounts class is created and the query is
executed passing the required parameters. After that, the return from the query is treated as follows:
 If the result is not set, there was an authentication error with the query preventing it from
being executed and an error is shown.
 The response from C4C has a field where the number of accounts found by the query is
returned. It is located in ProcessingConditions > ReturnedQueryHitsNumberValue. If this
number is equal to zero, then an error message is shown.
 If none of this errors occur, the results must be displayed.

The file must look like as follows:


How to consume an account web service via PHP 13

<?php
require_once 'QueryAccounts.php';

$accountId = $_POST['accountId'];
$username = $_POST['username'];
$password = $_POST['password'];
$proxy_enabled = (isset($_POST['proxy']) ? true : false);

$query = new QueryAccounts();


$result = $query->execute($accountId, $username, $password, $proxy_enabled);

// Verify if the query returned any account


if (isset($result)) {
$num_registers = $result->ProcessingConditions->ReturnedQueryHitsNumberValue;
// if the query did not find any account
if ($num_registers == 0) {
displayErrorNotFound($accountId);
}
// if the query find an account
else {
displayQueryResults($result);
}
}
// if the result is not set, the user and password given are incorrect
else {
displayErrorAuthentication();
}

function displayQueryResults($info) {
$account_id = (isset($info->Customer->InternalID) ? $info->Customer->InternalID : " ");
$organization = (isset($info->Customer->Organisation->FirstLineName) ? $info->Customer-
>Organisation->FirstLineName : " ");
$address = (isset($info->Customer->AddressInformation->Address->FormattedAddress-
>FormattedPostalAddress) ? $info->Customer->AddressInformation->Address->FormattedAddress-
>FormattedPostalAddress : " ");
$address1 = (isset($address->FirstLineDescription) ? $address->FirstLineDescription : " ");
$address2 = (isset($address->SecondLineDescription) ? $address->SecondLineDescription : "
");
$address3 = (isset($address->ThirdLineDescription) ? $address->ThirdLineDescription : " ");
$phone = (isset($info->Customer->AddressInformation->Address->Telephone-
>FormattedNumberDescription) ? $info->Customer->AddressInformation->Address->Telephone-
>FormattedNumberDescription : " ");
$email = (isset($info->Customer->AddressInformation->Address->EmailURI->_) ? $info-
>Customer->AddressInformation->Address->EmailURI->_ : " ");
$contact_name = (isset($info->Customer->ContactPerson->GivenName) ? $info->Customer-
>ContactPerson->GivenName : " ");
$contact_name = (isset($info->Customer->ContactPerson->FamilyName) ? $contact_name . " " .
$info->Customer->ContactPerson->FamilyName : $contact_name);
$contact_email = (isset($info->Customer->ContactPerson->WorkplaceEmailURI->_) ? $info-
>Customer->ContactPerson->WorkplaceEmailURI->_ : " ");

echo "<h3>Account " . $account_id . "</h3>


<dl class='dl-horizontal'>
<dt>Organization</dt>
<dd>" . $organization . "</dd>
<dt>Address</dt>
<dd>" . $address1 . " <br> " . $address2 ." <br> " . $address3 . "</dd>
<dt>Phone</dt>
<dd>" . $phone . "</dd>
<dt>E-Mail</dt>
<dd>" . $email . "</dd>
<dt>Primary Contact</dt>
<dd>" . $contact_name . "</dd>
<dt>Contact E-Mail</dt>
<dd>" . $contact_email . "</dd>
</dl>";
}

function displayErrorNotFound($id) {
echo 'The Account ID ' . $id . ' was not found on the Cloud for Customer System. Try again
with another Account ID.';
}

function displayErrorAuthentication() {
echo 'Authentication error! Check username, password and proxy settings then try again.';
}

?>
How to consume an account web service via PHP 14

As seen, the only work done by this PHP file is receive the parameters from form, pass them to
QueryAccounts class, check the response and display the results by just accessing its relative path in the
response itself.

6.3 Query an existing account from C4C


To perform a quick test in the application, log into the Cloud for Customer system and get an account ID.
For test purposes, the account ID chosen is 10009, which is a relevant ID in the system being used.

This is the account on the C4C system:

After executing the query by ID number 10009 on the PHP application, besides inserting correct C4C login
information, the result has to bring exactly the same data show in C4C:
How to consume an account web service via PHP 15

7 Create an Account
This section describes how to create an account in C4C from the PHP application. The create section of
the application consists in one PHP file responsible for displaying a message whether the account was
successfully created showing its ID and another PHP file responsible for creating the account on the C4C
system.

7.1 Create Account in the C4C system


The account is created in the CreateAccount class, which receives all the fields by parameter, prepare a
XML with the values in it and execute the web service.

Actually the steps performed by the CreateAccount class are identical to the ones performed by the
QueryAccounts class (created in step 6.1), but of course performing a different action. The difference
between the two classes is the WSDL used, the web service location and the XML passed as parameter.

First the XML is generated based on the parameters received, returning a string which is then converted to
a SOAP variable.

The final step is create the account. A SOAP client is created using the extended class (created in step 5)
which receives the WSDL location, the web service location and the authentication data as a parameter.
The authentication data may or may not have proxy information, depending on the user’s connection.

The complete class must look like this:

<?php
require_once 'ByDSoapClient.php';

class CreateAccount
{
public function execute($username, $password, $accountName, $email, $countryCode,
$countryName, $stateCode, $stateName, $postalCode, $street, $number, $phoneNumber, $city,
$givenName, $familyName, $contactEmail, $proxy_enabled) {

$xml = $this->generateXml($accountName, $email, $countryCode, $countryName,


$stateCode, $stateName, $postalCode, $street, $number, $phoneNumber, $city,
$givenName, $familyName, $contactEmail);

$soapVar = $this->generateSoapVar($xml);

$result = $this->create($soapVar, $username, $password, $proxy_enabled);

return $result;
}

public function create($soapVar, $username, $password, $proxy_enabled) {


$auth = null;
if ($proxy_enabled == true) {
$auth = array(
'proxy_host' => 'proxy',
'proxy_port' => '8080',
'login' => $username,
'password' => $password
);
} else {
$auth = array(
'proxy_host' => '',
'proxy_port' => '',
'login' => $username,
'password' => $password
);
}

$wsdl = 'wsdl/ManageAccounts.wsdl';
$location =
'https://<YOUR_SYSTEM_TENANT_HERE>/sap/bc/srt/scs/sap/managecustomerin1?sap-
vhost=<YOUR_SYSTEM_TENANT_HERE>';
$soapClient = new ByDSoapClient($wsdl, $location, $auth);

try {
$result = $soapClient->MaintainBundle_V1(
How to consume an account web service via PHP 16

new SoapParam($soapVar, 'CustomerBundleMaintainRequestMessage')


);
return $result;
} catch(Exception $e) {
$message = $e->getMessage();
}
}

public function generateSoapVar($xml) {


try {
$soapVar = new SoapVar($xml, XSD_ANYXML, null, null, null);
return $soapVar;
} catch(Exception $e) {
$message = $e->getMessage();
}
}

public function generateXml($accountName, $email, $countryCode, $countryName, $stateCode,


$stateName, $postalCode, $street, $number, $phoneNumber, $city, $givenName, $familyName,
$contactEmail) {
$xml = '
<ns1:CustomerBundleMaintainRequest_sync_V1>
<Customer actionCode="01">
<CategoryCode>2</CategoryCode>
<CustomerIndicator>true</CustomerIndicator>
<Organisation>
<FirstLineName>'. $accountName .'</FirstLineName>
<SecondLineName></SecondLineName>
<ThirdLineName></ThirdLineName>
<FourthLineName></FourthLineName>
</Organisation>
<AddressInformation actionCode="01">
<Address actionCode="01" telephoneListCompleteTransmissionIndicator="true">
<EmailURI>' . $email . '</EmailURI>
<PostalAddress>
<CountryCode>' . $countryCode . '</CountryCode>
<RegionCode>' . $stateCode . '</RegionCode>
<CountyName>' . $countryName . '</CountyName>
<CityName>' . $city . '</CityName>
<AdditionalCityName></AdditionalCityName>
<DistrictName>' . $stateName . '</DistrictName>
<StreetPostalCode>' . $postalCode . '</StreetPostalCode>
<POBoxPostalCode>' . $postalCode . '</POBoxPostalCode>
<StreetPrefixName></StreetPrefixName>
<StreetName>' . $street . '</StreetName>
<HouseID>' . $number . '</HouseID>
</PostalAddress>
<Telephone>
<FormattedNumberDescription>' . $phoneNumber . '</FormattedNumberDescription>
</Telephone>
</Address>
</AddressInformation>
<ContactPerson actionCode="01">
<GivenName>' . $givenName . '</GivenName>
<FamilyName>' . $familyName . '</FamilyName>
<WorkplaceEmailURI>' . $contactEmail . '</WorkplaceEmailURI>
</ContactPerson>
</Customer>
</ns1:CustomerBundleMaintainRequest_sync_V1>';
return $xml;
}

?>

Just like in the QueryAccounts class, the XML file does not contain <soapenv:Envelope>, <soapenv:Header>
and <soapenv:Body> sections. In Customer, AddressInformation and ContactPerson, the action code is set
as 01, which means that it is a creation and not an update. The CategoryCode is hardcoded to “2” meaning
that it is an account being created, and not an individual customer. In addition, the CustomerIndicator is
hardcoded as “true”, meaning that this is a customer account.

The generateSoapVar function is the same as in QueryAccounts class, with the only purpose of converting
the string into an SOAP parameter, passing the required parameters to the standard PHP class SoapVar.

The function create is responsible for running the web service and creating the account. The authentication
follows the same process of validation for the proxy, and the SOAP client is created using the extended
class created on step 3.2. The SOAP client created has all the web service’s operations, and the one used
How to consume an account web service via PHP 17

for the creation is called “MaintainBundle_V1”. This function requires a SOAP parameter named
“CustomerBundleMaintainRequestMessage”.

All the errors that might happen (such as no account found for that ID or authentication error) are treated
in the PHP file that runs this class and displays the ID of the created account.

7.2 Display account creation return


The POST parameters from the form are sent to this PHP file, which instantiates and executes the
CreateAcount class, displaying the created account ID afterwards or an error message, in case it happens.
The only error case that might happen is an authentication error, due to all the fields from the form being
required, avoiding errors caused by lack of information in the parameter of the XML.

The file must look as follows:

<?php

require_once 'CreateAccount.php';

$username = $_POST['username2'];
$password = $_POST['password2'];
$accountName = $_POST['accountName'];
$email = $_POST['accountEmail'];
$countryCode = $_POST['accountCountryCode'];
$countryName = $_POST['accountCountryName'];
$stateCode = $_POST['accountStateCode'];
$stateName = $_POST['accountStateName'];
$postalCode = $_POST['accountPostalCode'];
$street = $_POST['accountStreet'];
$number = $_POST['accountNumber'];
$phoneNumber = $_POST['accountPhone'];
$city = $_POST['accountCity'];
$givenName = $_POST['contactGivenName'];
$familyName = $_POST['contactFamilyName'];
$contactEmail = (isset($_POST['contactEmail']) ? $_POST['contactEmail'] : " ");
$proxy_enabled = (isset($_POST['proxy2']) ? true : false);

$account = new CreateAccount();


$result = $account->execute(
$username,
$password,
$accountName,
$email,
$countryCode,
$countryName,
$stateCode,
$stateName,
$postalCode,
$street,
$number,
$phoneNumber,
$city,
$givenName,
$familyName,
$contactEmail,
$proxy_enabled
);

if ($result != null) {
displaySuccess($result);
}
else {
displayError();
}

function displaySuccess($info) {
echo '<h3>Account ' . $info->Customer->InternalID . ' Created</h3>';
}

function displayError() {
echo 'Authentication error! Check username, password and proxy settings then try again.';
}

?>
How to consume an account web service via PHP 18

As seen, this PHP file only receives the parameters and submits them to CreateAccount class, which creates
the account and returns the Account ID or an authentication error.

7.3 Create an account in C4C using web service


To perform a test in the create part of the application, complete the form and insert valid login and
password information for the Cloud for Customer system. After sending the information, the account is
created on the C4C system.

After clicking in create, the web service is executed and the account is created on the system:
How to consume an account web service via PHP 19

Searching the system for the account ID, the same data inserted in the PHP application must appear on the
account:
How to consume an account web service via PHP 20

© 2014 SAP SE or an SAP affiliate company. All rights reserved.


No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP
SE or an SAP affiliate company.
SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. Please see http://global.sap.com/corporate-
en/legal/copyright/index.epx#trademark for additional trademark information and notices.
Some software products marketed by SAP SE and its distributors contain proprietary software components of other software
vendors.
National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or
warranty of any kind, and SAP SE or its affiliated companies shall not be liable for errors or omissions with respect to the materials.
The only warranties for SAP SE or SAP affiliate company products and services are those that are set forth in the express warranty
statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional
warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or
any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation,
and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platform directions and
functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason without
notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or
functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ
materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, which speak
only as of their dates, and they should not be relied upon in making purchasing decisions.

You might also like