Development and Extension Guide
SAP® Web Channel Experience Management 3.0 SP01 –
Application-Specific Information
Target Audience
Technology consultants
Development consultants
System administrators at customer’s or host’s site
Developers at customer‘s site
Customer
Document version 1.0 – October 2013
SAP AG
Dietmar-Hopp-Allee 16
69190 Walldorf
Germany
T +49/18 05/34 34 24
F +49/18 05/34 34 20
www.sap.com
© Copyright 2009 SAP AG. All rights reserved. Java is a registered trademark of Sun Microsystems, Inc.
No part of this publication may be reproduced or transmitted in any JavaScript is a registered trademark of Sun Microsystems, Inc., used
form or for any purpose without the express permission of SAP AG. under license for technology invented and implemented by Netscape.
The information contained herein may be changed without prior
notice. MaxDB is a trademark of MySQL AB, Sweden.
Some software products marketed by SAP AG and its distributors SAP, R/3, xApps, xApp, SAP NetWeaver, Duet, PartnerEdge,
contain proprietary software components of other software vendors. ByDesign, SAP Business ByDesign, and other SAP products and
services mentioned herein as well as their respective logos are
Microsoft, Windows, Outlook, and PowerPoint are registered trademarks or registered trademarks of SAP AG in Germany and in
trademarks of Microsoft Corporation. several other countries all over the world. All other product and
IBM, DB2, DB2 Universal Database, System i, System i5, System p, service names mentioned are the trademarks of their respective
System p5, System x, System z, System z10, System z9, z10, z9, companies. Data contained in this document serves informational
iSeries, pSeries, xSeries, zSeries, eServer, z/VM, z/OS, i5/OS, S/390, purposes only. National product specifications may vary.
OS/390, OS/400, AS/400, S/390 Parallel Enterprise Server, PowerVM,
Power Architecture, POWER6+, POWER6, POWER5+, POWER5, These materials are subject to change without notice. These materials
POWER, OpenPower, PowerPC, BatchPipes, BladeCenter, System are provided by SAP AG and its affiliated companies ("SAP Group")
Storage, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, for informational purposes only, without representation or warranty of
OS/2, Parallel Sysplex, MVS/ESA, AIX, Intelligent Miner, any kind, and SAP Group shall not be liable for errors or omissions
WebSphere, Netfinity, Tivoli and Informix are trademarks or with respect to the materials. The only warranties for SAP Group
registered trademarks of IBM Corporation. products and services are those that are set forth in the express
warranty statements accompanying such products and services, if any.
Linux is the registered trademark of Linus Torvalds in the U.S. and Nothing herein should be construed as constituting an additional
other countries. warranty.
Adobe, the Adobe logo, Acrobat, PostScript, and Reader are either
trademarks or registered trademarks of Adobe Systems Incorporated in Disclaimer
the United States and/or other countries. Some components of this product are based on Java™. Any
code change in these components may cause unpredictable
Oracle is a registered trademark of Oracle Corporation. and severe malfunctions and is therefore expressively
prohibited, as is any decompilation of these components.
UNIX, X/Open, OSF/1, and Motif are registered trademarks of the
Open Group. Any Java™ Source Code delivered with this product is
Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, only to be used by SAP’s Support Services and may not be
VideoFrame, and MultiWin are trademarks or registered trademarks of modified or altered in any way.
Citrix Systems, Inc.
Documentation in the SAP Service Marketplace
HTML, XML, XHTML and W3C are trademarks or registered You can find this documentation at the following address:
trademarks of W3C®, World Wide Web Consortium, Massachusetts http://service.sap.com/wec-inst
Institute of Technology.
D) Customer shall maintain the following copyright and permissions
Terms for Included Open notices on STLport sources and its documentation unchanged:
Copyright 2001 SAP AG
Source Software E) The Customer may distribute original or modified STLport sources,
This SAP software contains also the third party open source software provided that:
products listed below. Please note that for these third party products o The conditions indicated in the above permissions notice are met;
the following special terms and conditions shall apply. o The following copyright notices are retained when present, and
1. This software was developed using ANTLR. conditions provided in accompanying permission notices are met:
2. gSOAP Coypright 1994 Hewlett-Packard
Part of the software embedded in this product is gSOAP software. Company
Portions created by gSOAP are Copyright (C) 2001-2004 Robert A. Copyright 1996,97 Silicon Graphics
van Engelen, Genivia inc. All Rights Reserved. Computer Systems Inc.
THE SOFTWARE IN THIS PRODUCT WAS IN PART PROVIDED Copyright 1997 Moscow Center for
BY GENIVIA INC AND ANY EXPRESS OR IMPLIED SPARC Technology.
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE Copyright 1999,2000 Boris Fomitchev
IMPLIED WARRANTIES OF MERCHANTABILITY AND Copyright 2001 SAP AG
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. Permission to use, copy, modify, distribute and sell this software and
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY its documentation for any purposes is hereby granted without fee,
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR provided that the above copyright notice appear in all copies and that
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT both that copyright notice and this permission notice appear in
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR supporting documentation. Hewlett-Packard Company makes no
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS representations about the suitability of this software for any purpose.
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY It is provided “as is” without express or implied warranty.
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, Permission to use, copy, modify, distribute and sell this software and
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) its documentation for any purpose is hereby granted without fee,
ARISING IN ANY WAY OUT OF THE USE OF THIS provided that the above copyright notice appear in all copies and that
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF both that copyright notice and this permission notice appear in
SUCH DAMAGE. supporting documentation. Silicon Graphics makes no representations
3. SAP License Agreement for STLport SAP License Agreement for about the suitability of this software for any purpose. It is provided “as
STLPort between SAP Aktiengesellschaft Systems, Applications, is” without express or implied warranty.
Products in Data Processing Neurottstrasse 16 69190 Walldorf, Permission to use, copy, modify, distribute and sell this software and
Germany (hereinafter: SAP) and you (hereinafter: Customer) its documentation for any purposes is hereby granted without fee,
a) Subject Matter of the Agreement provided that the above copyright notice appear in all copies and that
A) SAP grants Customer a non-exclusive, non-transferrable, royalty- both that copyright notice and this permission notice appear in
free license to use the STLport.org C++ library (STLport) and its supporting documentation. Moscow Center for SPARC makes no
documentation without fee. representations about the suitability of this software for any purpose. It
B) By downloading, using, or copying STLport or any portion thereof is provided “as is” without express or implied warranty.
Customer agrees to abide by the intellectual property laws, and to all Boris Fomitchev makes no representations about the suitability of this
of the terms and conditions of this Agreement. software for any purpose. This material is provided "as is", with
C) The Customer may distribute binaries compiled with STLport absolutely no warranty expressed or implied.
(whether original or modified) without any royalties or restrictions.
Development and Extension Guide – Application-Specific Information
Any use is at your own risk. Permission to use or copy this software C) In the case of Art. 4.2 above, SAP shall not be liable for indirect
for any purpose is hereby granted without fee, provided the above damage, consequential damage caused by a defect or lost profit.
notices are retained on all copies. D) SAP and the Customer agree that the typical foreseeable extent of
Permission to modify the code and to distribute modified code is damage shall under no circumstances exceed EUR 5,000.
granted, provided the above notices are retained, and a notice that the E) The Customer shall take adequate measures for the protection of
code was modified is included with the above copyright notice. data and programs, in particular by making backup copies at the
Permission to use, copy, modify, distribute and sell this software and minimum intervals recommended by SAP. SAP shall not be liable for
its documentation for any purposes is hereby granted without fee, the loss of data and its recovery, notwithstanding the other limitations
provided that the above copyright notice appear in all copies and that of the present Art. 4 if this loss could have been avoided by observing
both that copyright notice and this permission notice appear in this obligation.
supporting documentation. SAP makes no representations about the F) The exclusion or the limitation of claims in accordance with the
suitability of this software for any purpose. It is provided with a present Art. 4 includes claims against employees or agents of SAP.
limited warranty and liability as set forth in the License Agreement 4. Adobe Document Services Adobe, the Adobe logo, Acrobat,
distributed with this copy. PostScript, and Reader are either registered trademarks or trademarks
SAP offers this liability and warranty obligations only towards its of Adobe Systems Incorporated in the United States and / or other
customers and only referring to its modifications. countries. For information on Third Party software delivered with
b) Support and Maintenance SAP does not provide software Adobe document services and Adobe LiveCycle Designer, see SAP
maintenance for the STLport. Software maintenance of the STLport Note 854621.
therefore shall be not included.
All other services shall be charged according to the rates for services
quoted in the SAP List of Prices and Conditions and shall be subject to
a separate contract.
c) Exclusion of warranty
As the STLport is transferred to the Customer on a loan basis and free
of charge, SAP cannot guarantee that the STLport is error-free,
without material defects or suitable for a specific application under
third-party rights. Technical data, sales brochures, advertising text and
quality descriptions produced by SAP do not indicate any assurance of
particular attributes.
d) Limited Liability
A) Irrespective of the legal reasons, SAP shall only be liable for
damage, including unauthorized operation, if this (i) can be
compensated under the Product Liability Act or (ii) if caused due to
gross negligence or intent by SAP or (iii) if based on the failure of a
guaranteed attribute.
B) If SAP is liable for gross negligence or intent caused by employees
who are neither agents or managerial employees of SAP, the total
liability for such damage and a maximum limit on the scope of any
such damage shall depend on the extent to which its occurrence ought
to have anticipated by SAP when concluding the contract, due to the
circumstances known to it at that point in time representing a typical
transfer of the software.
Development and Extension Guide – Application-Specific Information
Typographic Conventions
Type Style Description
Example Text Words or characters quoted from the screen. These include field names, screen titles,
pushbuttons labels, menu names, menu paths, and menu options.
Cross-references to other documentation
Example text Emphasized words or phrases in body text, graphic titles, and table titles
EXAMPLE TEXT Technical names of system objects. These include report names, program names, transaction
codes, table names, and key concepts of a programming language when they are surrounded
by body text, for example, SELECT and INCLUDE.
Example text Output on the screen. This includes file and directory names and their paths, messages, names
of variables and parameters, source text, and names of installation, upgrade and database
tools.
Example text Exact user entry. These are words or characters that you enter in the system exactly as they
appear in the documentation.
<Example text> Variable user entry. Angle brackets indicate that you replace these words and characters with
appropriate entries to make entries in the system.
EXAMPLE TEXT Keys on the keyboard, for example, F2 or ENTER.
Icons
Note
Note text
Caution
Caution text
Recommendation
Recommendation text
October 2013 5
Development and Extension Guide – Application-Specific Information
Document History
Before you start the implementation, make sure you have the latest version of this document. You can find the latest
version at the following location:
http://service.sap.com/wec-inst or http://service.sap.com/instguides
The following table provides an overview of the most important document changes:
Version Date Description
1.0 October 2013 Initial version
6 October 2013
Development and Extension Guide – Application-Specific Information
Table of Contents
1 Introduction .......................................................................................................................................................... 10
1.1 About This Document................................................................................................................................. 10
1.2 Naming Conventions .................................................................................................................................. 10
1.3 Introduction to Application-Specific Information .......................................................................................... 11
1.4 Web Channel Builder Modules ................................................................................................................... 12
1.4.1 Common Settings Module (Namespace sap-wcf) ......................................................................... 12
1.4.2 Common Settings Module (Namespace sap) ............................................................................... 13
1.4.3 User Management Module........................................................................................................... 14
1.4.4 Payment Methods Module ........................................................................................................... 16
1.4.5 Sales Transactions Module.......................................................................................................... 17
1.4.6 Checkout Module......................................................................................................................... 18
1.4.7 Wish Lists Module ....................................................................................................................... 20
1.4.8 Trade Articles Module .................................................................................................................. 20
1.4.9 In-Store Pickup Module ............................................................................................................... 22
1.4.10 Store Locator Module .................................................................................................................. 23
1.4.11 Main Module (main) ..................................................................................................................... 24
1.4.12 Content Management Module ...................................................................................................... 26
1.4.13 My Support Module ..................................................................................................................... 26
1.4.14 My Account Module ..................................................................................................................... 27
1.4.15 Shopping Templates Module ....................................................................................................... 27
1.4.16 Product Views Main Module......................................................................................................... 29
1.5 Application Plug-Ins ................................................................................................................................... 31
1.5.1 Sales Transactions and Wish Lists Plug-Ins ................................................................................. 34
2 Generic Topics ..................................................................................................................................................... 36
2.1 Application Modules ................................................................................................................................... 36
2.1.1 Creating and Integrating New Modules into the Application .......................................................... 36
2.1.2 Integrating the New Module into the Common Application Infrastructure ...................................... 38
2.2 Currency Converters .................................................................................................................................. 42
2.3 Central Header and Footer......................................................................................................................... 44
2.4 JavaScript for Web Analytics ...................................................................................................................... 46
2.5 Country-Specific Address Formats ............................................................................................................. 48
2.5.1 Setting Up the SAP CRM or SAP ERP Back End ......................................................................... 48
2.5.2 Creating New Views for New Address Display ............................................................................. 48
2.6 Store Locator - Google Maps ..................................................................................................................... 50
2.6.1 Store Locator............................................................................................................................... 50
2.6.2 Graphical Map Interface .............................................................................................................. 51
2.7 Store Locator - NAVTEQ Maps .................................................................................................................. 56
2.8 CSS-Only Changes to Configuration UI (Status Icons) ............................................................................... 58
3 Product Catalog ................................................................................................................................................... 61
3.1 Transfer of Additional Fields from MDM to Product Catalog ........................................................................ 61
3.2 Transfer of Additional Fields from CRM to MDM ......................................................................................... 64
3.2.1 Introduction ................................................................................................................................. 64
3.2.2 Steps on CRM Side ..................................................................................................................... 65
3.2.3 Steps on MDM Side..................................................................................................................... 72
3.3 Product View Modules................................................................................................................................ 76
3.3.1 Creating an Additional MDM Attribute for Product View ................................................................ 76
3.3.2 Creating an Additional User Context for Product View.................................................................. 82
4 Product Configuration........................................................................................................................................... 83
4.1 Custom UI Rendering for Characteristics on Configuration UI ..................................................................... 83
4.1.1 Adding a Custom Mapper for the Configuration UI ....................................................................... 83
4.1.2 Registering a New UI Type .......................................................................................................... 84
October 2013 7
Development and Extension Guide – Application-Specific Information
4.1.3 Adding the Custom XHTML Fragment ......................................................................................... 85
4.2Shopping Cart Summary with Pricing on Configuration UI .......................................................................... 86
4.2.1 Changing the Layout of the Configuration UI from 2-Column-Navigation to 2-Column-Sidebar ..... 87
4.2.2 Including the Mini Cart Preview in the Sidebar Using Module Interfacing ...................................... 88
4.2.3 Adapting the Re-Render IDs ........................................................................................................ 88
4.3 Removal of “Not Specified” Option on Configuration UI .............................................................................. 90
4.4 Reference Characteristics .......................................................................................................................... 91
5 Shopping Cart and Order ..................................................................................................................................... 97
5.1 Custom Attributes ...................................................................................................................................... 97
5.1.1 Enhancing Fields in the Back End................................................................................................ 97
5.1.2 Displaying Custom Fields on the UI ............................................................................................. 98
5.1.3 Adding Resource Keys for New Labels on the Web Shop UI ...................................................... 101
5.1.4 Reading Custom Fields from the Back End ................................................................................ 101
5.1.5 Writing Custom Fields to the Back End ...................................................................................... 103
5.1.6 Extending the Checkout UI ........................................................................................................ 104
5.2 Additional Fields Read from ERP SD via LO-API ...................................................................................... 107
5.2.1 Extending Module and Registering Extensions........................................................................... 107
5.2.2 Reading Substitution Reason and Attaching it to New Message ................................................. 108
5.3 Shopping Cart - User Interface ................................................................................................................. 110
5.3.1 Adding a New Field Using the AET ............................................................................................ 110
5.3.2 Adding A New Field Using Java ................................................................................................. 117
5.4 Shopping Cart - J2EE Data Persistence ................................................................................................... 122
5.4.1 Creating Class Representing the Object to be Persisted (Serializable) ....................................... 122
5.4.2 Creating View Component ......................................................................................................... 123
5.4.3 Creating View Component Handler ............................................................................................ 125
5.4.4 Registering View Component Handler ....................................................................................... 128
5.4.5 Overwriting Surrounding Component and Including New Component ......................................... 129
5.5 IPC Pricing............................................................................................................................................... 131
5.5.1 Standard Attributes for IPC Pricing (SAP CRM) ......................................................................... 131
5.5.2 Standard Attributes for IPC Pricing (SAP ERP) .......................................................................... 132
5.5.3 Extension Example .................................................................................................................... 133
5.6 Order Search (SAP ERP) ......................................................................................................................... 136
5.6.1 New Search Criteria .................................................................................................................. 136
5.6.2 Search Results for New Search Criteria ..................................................................................... 137
5.6.3 Adding New Fields to the Result List .......................................................................................... 139
5.6.4 Using the New Definition of the Search Description.................................................................... 141
5.7 Display of Schedule Lines (SAP ERP) ...................................................................................................... 142
5.8 Reading of Additional Attributes (SAP CRM) ............................................................................................ 144
5.9 Delivery Types and Requested Delivery Dates ......................................................................................... 148
5.9.1 Adapting BO Layer to Set Requested Delivery Date................................................................... 148
5.9.2 Adapting UI Layer to Set Delivery Type Depending on Requested Delivery Date ....................... 149
5.10 Proposed Shopping Templates ................................................................................................................ 151
5.11 Document Converter Manager ................................................................................................................. 159
5.11.1 Extending the Module Settings .................................................................................................. 159
5.11.2 Implementing and Registering a New Convertible ...................................................................... 161
5.11.3 Implementing the UI Part ........................................................................................................... 162
5.12 Mapping of Back-End Messages to UI Messages ..................................................................................... 163
5.13 Additional Pricing in Cart or Order ............................................................................................................ 164
5.14 In-Store Pickup ........................................................................................................................................ 165
6 Payment Process ............................................................................................................................................... 169
6.1 Payment Service Providers ...................................................................................................................... 169
6.1.1 Architecture Overview................................................................................................................ 170
6.1.2 Web Service Integration (PayPal Example)................................................................................ 171
6.1.3 SAP ERP E-Commerce ............................................................................................................. 229
6.1.4 SAP CRM Replication Scenario ................................................................................................. 259
8 October 2013
Development and Extension Guide – Application-Specific Information
6.1.5 Order-Related SAP CRM Billing................................................................................................. 306
6.1.6 Delivery-Related SAP CRM Billing ............................................................................................. 308
6.1.7 Extension Points........................................................................................................................ 310
6.2 Payment Card Authorization (SAP CRM).................................................................................................. 311
6.3 Integration of E-Payment Processing Service for Credit Card Tokenization............................................... 312
7 Web Services..................................................................................................................................................... 314
7.1 Web Service Entity "Companies" .............................................................................................................. 314
7.2 Web Service Entity "Consumer" ............................................................................................................... 316
7.2.1 Registration Request via Web Service Consumer ...................................................................... 316
7.2.2 Reading Data via Web Service Consumer ................................................................................. 319
7.2.3 Updating Data via Web Service Consumer ................................................................................ 320
7.3 Web Service "SalesOrderItemScheduleLines" .......................................................................................... 322
October 2013 9
Development and Extension Guide – Application-Specific Information
1 Introduction
The information in this guide is confidential and proprietary to SAP and may not be disclosed without the permission of
SAP. This guide is not subject to your license agreement or any other service or subscription agreement with SAP.
SAP has no obligation to pursue any course of business outlined in this document or any related guide, or to develop
or release any functionality mentioned therein. This document, or any related guide about SAP’s strategy and possible
future developments, directions, and functionality of products and/or platforms, are all subject to change and may be
changed by SAP 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. This document is provided without a warranty of any kind, either express or implied, including but not
limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement. This
document is for informational purposes and may not be incorporated into a contract. SAP assumes no responsibility
for errors or omissions in this document, except if such damages were caused by SAP intentionally or grossly
negligent. 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.
SAP AG – Walldorf (Germany)
1.1 About This Document
The Development and Extension Guide for SAP Web Channel Experience Management is written for the following
main target groups:
Technology consultants
Development consultants
System administrators at customer’s or host’s site
Developers at customer‘s site
This document is mainly intended for the above-mentioned target groups who have basic Java skills, who know SAP
CRM and SAP ERP, and who want to set up their own local development environment in order to extend and modify
the Web Channel application to their needs.
The Development and Extension Guide consists of the following main sections:
Introduction
Generic Topics
Product Catalog
Product Configuration
Shopping Cart and Order
Payment Process
Trade
1.2 Naming Conventions
In this documentation, the following naming conventions apply:
Java Server Faces (JSF)
Expression Language expressions (EL expressions)
Development component (DC)
Software component (SC)
Design Time Repository (DTR)
Component Build Service (CBS)
10 October 2013
Development and Extension Guide – Application-Specific Information
Change Management Service (CMS)
Java Runtime Environment (JRE)
SAP Web Channel Experience Management (WCEM)
SAP NetWeaver Developer Studio (NWDS)
SAP NetWeaver Development Infrastructure (NWDI)
Integrated Development Environment (IDE)
System Landscape Directory (SLD)
1.3 Introduction to Application-Specific Information
You can use the information and examples provided in this part of the guide to further develop and extend applications
of SAP Web Channel Experience Management. For more information about development and extension, see the
Development and Extension Guide: Generic Information for SAP Web Channel Experience Management on SAP
Service Marketplace at http://service.sap.com/wec-inst.
October 2013 11
Development and Extension Guide – Application-Specific Information
1.4 Web Channel Builder Modules
The following table explains the Web Channel Builder modules delivered with SAP Web Channel Experience
Management:
Module ID Namespace
Common Settings com.sap.common sap-wcf
Common Settings com.sap.common sap
User Management user sap
Payment Methods payment sap
Sales Transactions salestransactions sap
Checkout checkout sap
Wish Lists wishlist sap
Trade Articles article sap
In-Store Pickup instore sap
Store Locator storelocator sap
Main main sap
Content Management contentmanagement sap
My Support mysupport sap
My Account myaccounts sap
Shopping Templates shoppingtemplates sap
Product Views productviews sap
1.4.1 Common Settings Module (Namespace sap-wcf)
Introduction
The Common Settings module (namespace sap-wcf) of Web Channel Builder provides reusable functionality and
services that can be used by all other modules. For example, this module provides the generic search for the dynamic
UI and the process flow framework.
Detailed Description
This module provides the following generic functionality:
Generic search framework
Help value search
Dynamic UI framework
Process flow
Default layouts
Default content for header view
Application list page
Admin pages
Required Module Interfaces
None
12 October 2013
Development and Extension Guide – Application-Specific Information
Exposed Module Interfaces
Business Object Interfaces
com.sap.wcf.GenericSearchProvider
Provides access to the generic search framework. The interface allows the reuse of generic search while
providing a UI for the results.
UI Interfaces
View Components
com.sap.wcf.GS.SimpleSearch/SimpleSearch
Simple search
com.sap.wcf.GS.AdvancedSearch/AdvancedSearchView
Advanced search
com.sap.wcf.ProcessFlow/processFlow
Process flow entry view component
com.sap.wcf.ProcessFlow/processFlowHorizontalHost
Host for horizontal view
com.sap.wcf.ProcessFlow/processFlowVerticalHost
Host for vertical view
com.sap.wcf.Menu/menu
Dynamic menu view component controlled via menu configuration
com.sap.wcf.contentHeaderInfo/contentHeaderInfo
Generic content header view component that dynamically provides the breadcrumbs
com.sap.wcf.headMetadata/headMetadata
View component to provide metadata from the different views displayed to the header
Layouts
com.sap.wcf.Layouts/1column
One-column layout
com.sap.wcf.Layouts/2columnNavigation
Two-column layout with navigation bar
com.sap.wcf.Layouts/2columnSidebar
Two-column layout with side bar
com.sap.wcf.Layouts/3column
Three-column layout
com.sap.wcf.Layouts/1column
One-column layout
com.sap.wcf.Layouts/baseHeaderFooterLayout
Base page layout with header and footer
1.4.2 Common Settings Module (Namespace sap)
Introduction
The Common Settings module (namespace sap) of Web Channel Builder provides common application functionality
such as conversion, validation, and common application Customizing. Moreover, it contains some re-use functionality.
This module is always part of the application. Do not change the namespace in Web Channel Builder to sap-wcf,
because then only the sap-wcf part of this module is available.
October 2013 13
Development and Extension Guide – Application-Specific Information
Note
If you extend this module in another namespace, ensure that the type is still system. Check attribute moduleType in
metadata.xml.
Detailed Description
The following functions are available:
Access to common customizing (for example, sales area)
Can be access through BO access object CommonConfigurationAccess
Conversion for units, dates, and currencies
Available on BO level through CommonConverterAccess and also on UI level through different JSF
converters (wecCurrency, wecUnit, and wecUnitID).
Available converters:
ID Description
wecCurrency Converts a currency in BigDecimal into a String and vice versa.
Re-uses standard JSF converter for currency symbol display,
but also takes Customizing for decimal places into account.
wecUnit Converts a unit amout in BigDecimal into a String and vice
versa. Takes Customizing for decimal places into account.
wecUnitID Converts a language-independent SAP unit key (for example,
ST) into a language-dependent key (for example, PC in
English).
Required Module Interfaces
None
Exposed Module Interfaces
Business Object Interfaces
Interface ID Description
com.sap.common.Configuration Acess to common configuration (for example, currency or sales area)
com.sap.common.Converter Access to conversion for currencies and units
com.sap.common.Attachment Access to attachment functionality
1.4.3 User Management Module
Introduction
The User Management module of Web Channel Builder provides functions that are related to the logon and
registration of users.
Detailed Description
This module provides the following generic functionality:
Log on to shop (with different logon types)
Registration of new users
Support for forgotten passwords
Support for forgotten user IDs
Change passwords
Change user data
14 October 2013
Development and Extension Guide – Application-Specific Information
Personalization
Required Module Interfaces
com.sap.common.Configuration
com.sap.common.Converter
Optional Module Interfaces
com.sap.sales.Order
com.sap.wishlist.GeneralInfo
com.sap.PaymentMasterDataAccess
com.sap.common.KnowledgeManagement
com.sap.myAccounts
com.sap.mySupport
com.sap.main
com.sap.sales.CheckoutCallback
Exposed Module Interfaces
Business Object Interfaces
com.sap.user.UserDataProvider
Requesting user data information
com.sap.user.UserFunctionProvider
Functions available to the users
com.sap.user.BusinessPartner
Business partners
com.sap.user.UserRegistrationPlugIn
Plug-in for registration page
For more information, see Application Plug-Ins.
UI Interfaces
View Components
com.sap.user.LoginRegisterAnchorView/mainpageLoginRegisterAnchorView
Logon link and status used in the header
com.sap.user.LoginInfoView/mainpageLoginInfoView
User name displayed in the header
com.sap.user.LoginRegistrationView/loginRegistrationView
User login and registration to be used on your own page (for example, process flow). The view itself
has no form tag to submit the data.
com.sap.user.PersonalizationAnchorView/mainpagePersonalizationAnchorView
Personalization link used in the header
com.sap.user.AddressViews/addressSelector
Including address views
com.sap.user.AddressViews/singleAddress
Included address views
com.sap.user.AddressViews/singleAddressReadonly
Included address views
com.sap.user.ContactViews/contactInformation
Included contact information views
com.sap.user.ContactViews/contactInformationReadonly
Included contact information views
com.sap.user.ContactViews/companyCommunData
Included contact information views
October 2013 15
Development and Extension Guide – Application-Specific Information
com.sap.user.ContactViews/companyGeneralData
Included contact information views
com.sap.user.ContactViews/contactCommunData
Included contact information views
com.sap.user.ContactViews/contactGeneralData
Included contact information views
com.sap.user.RegisterView
Plug-in for views on registration page
com.sap.user.RegisterConfirmationView
Plug-in for views on registration confirmation page
For more information, see Application Plug-Ins.
UI Objects
com.sap.user.locking/accountDataLockProvider
Used to lock the user
Navigation Targets
com.sap.user.AccountViews/myAccountAccountDetailsB2C
Navigation for the account details view
com.sap.user.AccountViews/myAccountContactDetailsForBreadcrumb
Navigation for the contact details view
com.sap.user.Login/toUserLogin
Navigation to the user login view
1.4.4 Payment Methods Module
Introduction
The Payment Methods module of Web Channel Builder provides functionality to offer Web shop customers different
payment methods during checkout.
Detailed Description
The following table explains the payment methods supported by each back end:
Payment Method Back End
Invoice SAP CRM and SAP ERP
Credit cards SAP CRM and SAP ERP
Cash on delivery SAP CRM
Payment service providers (using BAdI) SAP CRM and SAP ERP
Required Module Interfaces
sap.wcf
Optional Module Interfaces
com.sap.sales.Order
com.sap.user.BusinessPartner
com.sap.myAccounts
com.sap.sales.Checkout
com.sap.user.locking
16 October 2013
Development and Extension Guide – Application-Specific Information
Exposed Module Interfaces
None
Business Object Interfaces
None
UI Interfaces
View Components
None
Navigation Targets
com.sap.sales.Checkout/preConfirmation
1.4.5 Sales Transactions Module
Introduction
The Sales Transactions module in Web Channel Builder provides functionality to run business-to-consumer (B2C) or
business-to-business (B2B) selling processes on the Internet (that is, the consumer and contact scenarios,
respectively).
Detailed Description
This module enables Web shop customers to do the following:
View the shopping cart and add products directly to the shopping cart
Add products from the product catalog, wish list, or existing order to the shopping cart
View the shopping cart preview after adding products to the shopping cart
Navigate to the checkout (if the Checkout module of Web Channel Builder is available)
Required Module Interfaces
com.sap.main
com.sap.wcf.Layouts
com.sap.common.SearchFilter
com.sap.common.Configuration
com.sap.common.Converter
com.sap.user.UserDataProvider
com.sap.user.UserFunctionProvider
com.sap.user.BusinessPartner
com.sap.user.Login
com.sap.ipc.IPCClient
Optional Module Interfaces
com.sap.PaymentDataAccess
com.sap.PaymentCommunicationAccess
com.sap.sales.CheckoutOrder
com.sap.sales.CheckoutLocking
com.sap.emkt.FreeGoods
com.sap.common.Catalog
com.sap.common.Catalog.DetailPage
com.sap.marketing.Campaign
com.sap.common.ProductRecommend
com.sap.wishlist.WishListProductProvider
October 2013 17
Development and Extension Guide – Application-Specific Information
com.sap.common.Catalog.ContinueShoppingView
com.sap.productAvailabilityViews
Exposed Module Interfaces
Business Object Interfaces
com.sap.sales.Order
Interface for the sales order
com.sap.sales.Basket
Interface for the cart
com.sap.sales.BasketProductProvider
Interface for adding a product to the shopping cart
com.sap.sales.Campaign
Interface for the interaction with a campaign
For information on code plug-ins, see Sales Transactions and Wish Lists Plug-Ins.
UI Interfaces
View Components
com.sap.sales.BasketPreview/addToBasket
Interface for adding products to a cart
minibasketoverlayIncl
Interface for the minibasket used in the header
com.sap.sales.GeneralInfo/trackOrdersIncl
Interface for the My Orders link in the header
orderitemsearch
Interface for including an item search
Objects
com.sap.sales.GeneralInfo/salesDocBeanProvider
Provides access to the sales document bean
com.sap.sales.SalesLocking/salesTransactionsLockProvider
Provides lock services for the sales transaction module
com.sap.sales.Checkout/pageIsDisplayedMediator
Used to find out the currently displayed page (shopping cart or checkout page)
For information on code plug-ins, see Sales Transactions and Wish Lists Plug-Ins.
Navigation Targets
com.sap.sales.Checkout/orderConfirmation
com.sap.sales.Checkout/preConfirmation
com.sap.sales.Checkout/order
com.sap.sales.Checkout/basket
1.4.6 Checkout Module
Introduction
The Checkout module in Web Channel Builder is important when Web shop customers order products. Checkout
aggregates all the information necessary for completing the ordering process, such as the following:
Bill-to and ship-to addresses
Payment methods
A summary of ordered products and costs
18 October 2013
Development and Extension Guide – Application-Specific Information
Detailed Description
When this module is part of the Web shop configuration, you can configure the following in Web Channel Builder for
the Web shop:
URL for terms and conditions
Delivery types allowed
Checkout profile group used
When you add the Checkout module to the configuration, the system adds the Checkout Process Configuration
module (com.sap.checkout.processconfig).
The Checkout Process Configuration module holds the configuration of the checkout process in XML format. This
configuration contains information about the checkout step and checkout step elements the Web shop customer uses
while performing the checkout (for example, the shipping details checkout step might consist of the following
elements: ship-to address and delivery type).
Required Module Interfaces
Check the metadata.xml located in the md part of the module.
com.sap.sales.Checkout
com.sap.sales.SalesLocking
com.sap.user.locking
com.sap.common.Configuration
com.sap.common.Converter
com.sap.PaymentDataAccess
com.sap.user.LoginRegistrationView
com.sap.sales.CheckoutProcessConfig
Exposed Module Interfaces
com.sap.sales.CheckoutOrder
Used in the Sales Transactions module to show views (for example, the shipping collapsed view and the
billing collapsed view) from checkout on the order confirmation page and for navigating to checkout.
com.sap.sales.CheckoutConfiguration
Used from the Main module to get access to the general terms and conditions (GTC) URL. A link to the GTC
is displayed on a view belonging to the Main module. Generally, it is possible to get access to other checkout
configuration information (such as enabled delivery types) by using this interface.
com.sap.sales.CheckoutCallback
Used from the Users module to enable the login of users in checkout when Web shop customers choose the
Continue pushbutton in the Personal Data checkout step.
com.sap.sales.CheckoutLocking
Used from the Sales Transactions module in the context of multiple browser support. This module interface
exposes a UI object that allows for invalidating a checkout process if changes in the shopping cart have
occurred in another browser window or tab in the same session.
com.sap.checkout.FilterPaymentMethodsPlugIn
Used to filter the payment methods that the system displays in checkout.
UI Interfaces
View Components
Check the ui-repository.xml file of the ui part of the module.
com.sap.sales.CheckoutOrder/confirmationIncl
Used from the Sales Transactions module on the order confirmation page
Layouts
Check the ui-repository.xml file of the ui part of the module.
October 2013 19
Development and Extension Guide – Application-Specific Information
1.4.7 Wish Lists Module
Introduction
You make settings in the Wish List module of Web Channel Builder to enable Web shop customers to make persistent
wish lists for Web shops. Web shop customers can use wish lists to remind themselves to purchase products at a later
time.
Detailed Description
This module enables Web shop customers to do the following:
Display their wish lists (logged-in user)
Add products from the product catalog to their wish lists (if the Product Catalog module is available)
Add products from their wish lists to the shopping cart (if the Sales Transactions module is available)
Required Module Interfaces
com.sap.main
com.sap.wcf.Layouts
com.sap.user.Login
Optional Module Interfaces
com.sap.myAccounts
com.sap.common.Catalog
com.sap.common.Catalog.DetailPage
com.sap.common.Catalog.DetailOtherFunctions
com.sap.common.Catalog.BlockViewOtherFunctions
com.sap.common.Catalog.ListViewOtherFunctions
com.sap.marketing.ProductRecommend.OtherFunctions
com.sap.productAvailabilityViews
com.sap.sales.CheckoutLocking
com.sap.sales.SalesLocking
com.sap.sales.Basket
Exposed Module Interfaces
Business Object Interfaces
Code plug-ins
For more information, see Sales Transactions and Wish Lists Plug-Ins.
UI Interfaces
View Components
com.sap.wishlist.GeneralInfo/MyWishListHeaderView
For more information, see Sales Transactions and Wish Lists Plug-Ins.
Objects
None
1.4.8 Trade Articles Module
Introduction
You make settings in the Trade Articles module of Web Channel Builder to enable Web shop customers to order
variants of generic articles.
20 October 2013
Development and Extension Guide – Application-Specific Information
Detailed Description
This module contains implementations of extensions offered by other modules, mainly the Product Catalog module. It
allows a proper handling of generic articles on the browsing page and details page and in the simple search.
Generic articles are displayed on a dedicated product details page. Generic article characteristics can be used for the
filter-based navigation of the product catalog. The usage of generic articles in other modules is controlled as follows:
Sales Transactions
Only variants can be added to the shopping cart.
Wish Lists
Only variants can be added to wish lists.
Shopping Templates
Only variants can be added to shopping templates.
Customer Interaction
Ratings can only be entered for generic articles.
Product Recommendations
Free goods must be defined individually for variants. In addition, it is possible to define free goods for generic
articles displayed on the browsing page.
Product Availability
An availability check is only possible for variants.
In-Store Pickup
In-store handling is only possible for variants.
This module can only be used in conjunction with the SAP CRM back end connected to SAP Retail (SAP ERP).
Required Module Interfaces
com.sap.common.Catalog
com.sap.common.Catalog.PriceView
com.sap.common.Catalog.DetailPage
com.sap.user.UserDataProvider
Exposed module interfaces
Business Object Interfaces
com.sap.wec.trade.Article
Provides access to article specific objects, such as the following:
o Configuration
o Article explorer, public interface for accessing article-specifc information of a catalog item
o Article catalog, provides additional functionality for articles compared to the core catalog
UI Interfaces
View Components
com.sap.wec.trade.BlockViewOtherFunctions
View plug-in; the counterpart to com.sap.common.Catalog.BlockViewOtherFunctions for a tile of the
block view on the catalog browsing page in case a generic article is displayed
com.sap.wec.trade.ListViewOtherFunctions
View plug-in; counterpart to com.sap.common.Catalog.ListViewOtherFunctions for a row of the list
view on the catalog browsing page in case a generic article is displayed
Layouts
None
October 2013 21
Development and Extension Guide – Application-Specific Information
1.4.9 In-Store Pickup Module
Introduction
You make settings in the In-Store Pickup module of Web Channel Builder to enable Web shop customers to order
products in the Web shop and collect their purchases from conventional retail stores.
Detailed Description
In addition to buying products online in the Web shop for delivery, Web shop customers can order products for pickup
in selected stores. Web shop customers select stores using the store locator (note there is a Store Locator module in
Web Channel Builder), which includes a distance search that returns the nearest stores. The system shows product
availability for each store found.
The back end supports a reservation workflow which allows for feedback to Web shop customers that ordered
products are ready for pickup or could not be reserved.
There is also a variant available that only shows product availability in the stores found (without the possibility to
actually order the product). If the desired product is available in a store, Web shop customers find the necessary
contact data (address, telephone, e-mail address, and so on) to take further actions. For example, they can call the
store and agree to reserve products for pickup later.
Required Module Interfaces
com.sap.storelocator.StoreSearchManager
Used to retrieve the StoreSearch object, which provides the list of found stores
com.sap.storelocator.textualSearch
Used to include the store search UI on the in-store pickup page
com.sap.common.Catalog.DetailMiddleBelowAddToCart
Used to integrate into to the product details UI (add a link showing availability in stores)
com.sap.common.Catalog
Used to use the catalog item business object and to register an extension to read additional MDM data (field
WECMDM_INSTORE_PICKUP_MODE)
com.sap.user.BusinessPartner
Used to use the user business object
com.sap.common.Configuration
Used to read the sales organization that is configured for the Web shop
com.sap.common.Catalog.PriceView
Used to integrate the price view of the catalog on the in-store pickup page
com.sap.sales.Basket
Used to perform an "add-to-cart" on the shopping cart business object
com.sap.sales.Order
Used to integrate in-store pickup availability and store address on item level on the My Orders page
com.sap.wec.trade.Article
Used to use the article business objects
com.sap.main
Used to implement breadcrumbs
com.sap.wcf.Layouts
Used to provide the in-store pickup page
com.sap.wcf.Menu
Used to integrate the top-level menu of the store page
Exposed Module Interfaces
Business Object Interfaces
com.sap.wec.trade.instore.businessobject.intf.AvailabilityCheckBOAccess
Provides access to functionality to read availablilty information for stores from the back end
UI Interfaces
22 October 2013
Development and Extension Guide – Application-Specific Information
None
View Components
instore-availability-link.xhtml
Implements the link for checking availability in stores on the product details page
instore-pickup-link.xhtml
Implements the link for in-store pickup on the product details page
instore.xhtml
Implements the whole content of the in-store pickup page
basketRichUIAvailability.xhtml
Implements the rendering of the in-store pickup information and store address of an in-store pickup item
on the extended UI of the shopping cart
basketLeanUIAvailability.xhtml
Implements the rendering of the in-store pickup information and store address of an in-store pickup item
on the standard UI of the shopping cart
orderRichUIDelivery.xhtml
Implements the rendering of the in-store pickup information and store address of an in-store pickup item in
the checkout and in orders
Layouts
The standard column layout is used.
1.4.10 Store Locator Module
Introduction
You make settings in the Store Locator module of Web Channel Builder to enable Web shop customers to search for
stores (including service centers) by using the store locator in the Web shop.
Detailed Description
This module provides the following features:
Textual search for stores
Possibility to integrate a graphical map
Fully functional example integration of Google Maps
Two search modes
o Database-like search (default)
o Distance search using a geo-coding service to find nearby stores
Required Module Interfaces
com.sap.user.UserDataProvider
Used to determine whether a user is logged on
com.sap.user.BusinessPartner
Used to default the search fields according to the user's address (if logged on)
com.sap.common.Configuration
Used to read the sales area information of the common configuration
com.sap.wcf.Layouts
Used to reference the standard layout
Exposed Module Interfaces
Business Object Interfaces
com.sap.wec.app.common.mc.module.storelocator.businessobject.interf.StoreSearchManager
Provides access to functionality to search for stores
October 2013 23
Development and Extension Guide – Application-Specific Information
com.sap.wec.app.common.mc.module.storelocator.businessobject.interf.StoreSearchConfiguration
Provides access to the configuration of store locator
UI Interfaces
com.sap.storelocator.textualSearch
Enables reuse of the search part of the textual store locator search. Also used in the In-Store Pickup module
of Web Channel Builder.
com.sap.storelocator.openingTimes
Enables reuse of the business hours of store locator. Also used in the In-Store Pickup module of Web
Channel Builder.
View Components
graphical-map.xhtml
Contains the graphical map.
graphical-result.xhtml
Contains the store result list in the graphical store locator.
graphical-search.xhtml
Contains the search fields in the graphical store locator.
graphical-store-detail.xhtml
Contains the detail view of a store in the graphical map.
header.xhtml
Header of the store locator (for both graphical and textual store locator)
main-page-link.xhtml
Link for the store locator on the main page
opening-times-overlay.xhtml
Business hours overlay in the textual store locator
opening-times-table.xhtml
Business hours table within the graphical store locator
parent.xhtml
Parent view containing search and result view (for both graphical and textual store locator)
textual-result.xhtml
Contains the store result list of the textual store locator.
textual-search.xhtml
Contains the search fields and buttons of the textual store locator.
Layouts
The standard column layout is used.
1.4.11 Main Module (main)
Introduction
The Main module of Web Channel Builder module provides a page with the header and footer used throughout the
application.
It also contains the configuration files for application menu and breadcrumb handling. If this part of the application
infrastructure needs to be changed, you must extend the Main module.
Note
If you extend this module in a different namespace, ensure that it is still flagged as main module. See attribute
mainModule in the metadata.xml file.
Required Module Interfaces
No required interfaces. The Main module consumes other application module's interfaces softly. This means that if
those interfaces are available, the system renders the respective header entries or menu links.
24 October 2013
Development and Extension Guide – Application-Specific Information
Exposed Module Interfaces
Business Object Interfaces
None
UI Interfaces
View Components
Module interface Include ID Description
com.sap.main header Header area of the WCEM application.
Includes menu, breadcrumb trail, certain
links, and functions for searching, cart
navigation, and checkout.
com.sap.main footer Footer area of the WCEM application.
Includes links to pages like About Us.
Pages
Module interface Page ID Description
com.sap.main basePage Common page, which describes the overall
layout of a WCEM page (besides the content
area, which is controlled by layouts in the
system module). Its layout is defined through
layout baseLayout.
To create another base page, the Main
module needs to be extended or replaced.
The corresponding layout then also needs to
be provided.
com.sap.main myAccountHomePage Page that contains the My Account
pushbutton on the left-hand side of the
screen
com.sap.main mySupportHomePage Page that contains the Service And Support
pushbutton on the left-hand side of the
screen
Navigation Targets
Module interface Navigation Target Description
com.sap.main toCustomerService Forwards the service page, which
by default just provides a static
text. If desired, more content can
be included using an extension.
com.sap.main actionShowAdvancedSearchView Forwards to the Product Catalog
module through interface
com.sap.common.Catalog.Naviga
tionView.
com.sap.main toMyAccount Forwards to
myAccountHomePage to display
the My Account navigation area
on the left-hand side of the
screen.
com.sap.main toMySupport Forwards to
mySupportHomePage to display
the My Support navigation area
on the left-hand side of the
screen.
October 2013 25
Development and Extension Guide – Application-Specific Information
1.4.12 Content Management Module
Introduction
You make settings in the Content Management module of Web Channel Builder to integrate external content into the
Web shop.
Detailed Description
This module provides an interface to integrate external Web content.
Required Module Interfaces
com.sap.wcf.Layouts
Optional Module Interfaces
com.sap.user.Login
com.sap.common.Catalog.SideBarView
Exposed Module Interfaces
UI Interfaces
View Components
com.sap.contentmanagement.ui/externalContextView
com.sap.common.Catalog.SideBarView/plugIn
com.sap.user.RegisterView/plugIn
For more information about plug-ins, see Application Plug-Ins .
Layouts
None
1.4.13 My Support Module
Introduction
You make settings in the My Support module of Web Channel Builder to provide a menu with a hierarchy structure for
support in the Web shop.
Detailed Description
You can make settings to show menu headings in the Web shop for the following:
Service requests
Complaints and returns
Product registration
Knowledge base
Required Module Interfaces
None
Exposed Module Interfaces
Business Object Interfaces
com.sap.mySupport.config.Anchor
Anchor for Web Channel Builder usage reference
UI Interfaces
View Components
26 October 2013
Development and Extension Guide – Application-Specific Information
com.sap.mySupport/tree
Used to show menu tree on the left-hand side
Layouts
None
1.4.14 My Account Module
Introduction
You make settings in the My Account module of Web Channel Builder to add, remove, and arrange menu headings
and menu options in the navigation area of My Account.
Detailed Description
You can add menu headings in the My Account module for the following:
Transactions
Settings
Personalization
Products and service contracts
Preferences
Required Module Interfaces
com.sap.wcf.UserCore
Exposed Module Interfaces
Business Object Interfaces
com.sap.myAccount.config.Anchor
Anchor for Web Channel Builder usage reference
UI Interfaces
View Components
com.sap.myAccounts/tree
Used to show menu tree on the left-hand side
com.sap.myAccounts/content
Default content view
Layouts
None
1.4.15 Shopping Templates Module
Introduction
You make settings in the Shopping Templates module of Web Channel Builder to enable Web shop customers to
save lists of frequently ordered products, in shopping templates.
Detailed Description
This module enables Web shop customers to do the following:
Create, copy, change, and remove shopping templates
Add products from the product catalog to their shopping templates (if the Product Catalog module is available)
Add products from the shopping cart or from orders to their shopping templates (if the Sales Transactions
module is available)
October 2013 27
Development and Extension Guide – Application-Specific Information
Add products from the shopping template to the shopping cart, and order the products (if the Sales
Transactions and Checkout modules are available)
Required Module Interfaces
com.sap.wcf.Layouts
Used to provide the shopping templates page
com.sap.main
Used to implement the breadcrumb logic
com.sap.user.Login
Used to redirect to the logon page
com.sap.user.UserDataProvider
Used to check whether a known user is logged on
com.sap.user.UserFunctionProvider
Used in permission control for requested actions
com.sap.user.BusinessPartner
Used to access the current sold-to party (in particular the key) if a known user is logged on
com.sap.common.Converter
Used to provide converters from internal formats to external formats, such as date or unit key that are also
used by shopping templates
com.sap.common.Catalog
Used to access the product catalog
com.sap.sales.Basket
Used to perform an "add-to-cart" action in the shopping cart business object
com.sap.sales.Checkout
Used to access the maximum quantity per shopping template item
Optional Module Interfaces
com.sap.wcf.Menu
com.sap.productAvailability
Used to access product availability configuration to check whether display of rough stock information is
enabled
com.sap.productAvailabilityViews
Used to render rough stock information for a shopping template item
com.sap.ipc.IPCDataAccess
Used to access IPC configuration to check whether configuration summaries will be rendered
com.sap.ipc.ConfigUI
Used to render configuration summary if a shopping template item is a configurable product
com.sap.ipc.IPCClient
Used to create new IPC item properties for internal processing
com.sap.myAccounts
Used to integrate with My Account page
com.sap.common.Catalog.DetailPage
Used to navigate to the product details page of a shopping template item
Exposed Module Interfaces
Business Object Interfaces
com.sap.shoppingtemplates.CheckBeforeAddToShoppingTemplatePlugIn
Used to check whether a catalog item can be added to a shopping template; only within the catalog. The
check takes place regardless of the user logon status.
com.sap.shoppingtemplates.ShoppingTemplateItemReplacementPlugIn
Used to replace a catalog item to be added to a shopping template; only within the catalog. The user must
be logged on.
28 October 2013
Development and Extension Guide – Application-Specific Information
UI Interfaces
View Components
com.sap.shoppingtemplates/ShoppingTemplatesMainPageLinkInclude
Link My Shopping Templates in the page header
Objects
None
Navigation Targets
com.sap.shoppingtemplates.toMyShoppingtemplates/toMyShoppingtemplates
Navigation to the shopping template overview page
1.4.16 Product Views Main Module
Introduction
You add the Product Views Main and Product Views module of Web Channel Builder to make it possible to apply
some "filtering" criteria on some attributes to a specific user context. By adding this module, an additional setting is
available in the Product Catalog module that specifies the product view to be used by the shop. The configuration of
the product view itself is performed by the Product View Web Channel Builder application that is integrated into Web
Channel Builder. This module does not contain any specific settings for product views; however, you must include it in
the configuration of your Web Channel applications if you want to use product views.
Detailed Description
The Product View Main and the Product View module allow the filtering of catalog content based on the following:
User Context
Target Group(CRM)
Account Hierarchy(CRM)
Main Customer Hierarchy Node(ERP)
Subordinate Customer Hierarchy Node(ERP)
URL Parameter
URL wec-locale
Attributes
Category(CRM)
Material Classification(ERP)
Distribution Channel
Sales Organization
MDM Taxonomy
Product views are available in both the consumer scenario and the contact scenario.
Required Module Interfaces
com.sap.common.ProductView
com.sap.common.Catalog
com.sap.wcf.Layouts
Optional Module Interfaces
com.sap.wcf.UserCore
com.sap.user.UserDataProvider
com.sap.user.BusinessPartner
Exposed Module Interfaces
October 2013 29
Development and Extension Guide – Application-Specific Information
Business Object Interfaces
ProductViewRuntime
BusinessPartnerAccess
UserDataProviderAccess* UserFunctionProviderAccess
UI Interfaces
View Components
productViewRuntimeHeader
Objects
None
Navigation Targets
None
30 October 2013
Development and Extension Guide – Application-Specific Information
1.5 Application Plug-Ins
Task Plugin Type Module Ref. Impl.
in Module
Implement additional com.sap.sales.ItemListButtons View salestransactions shoppingte
buttons in the item list mplates
toolbar of the shopping
cart (standard or
extended UI)
Add new partner com.sap.sales.PartnerFunctionPlugIn Code salestransactions instore
functions
Show alternative com.sap.sales.AlternativeAvailabilityPlugI Code salestransactions instore
availability views n
com.sap.sales.AlternativeAvailabilityView View
s
Replace products com.sap.sales.BasketItemReplacementPl Code salestransactions article
before adding to ugIn
shopping cart
Prevent products from com.sap.sales.CheckBeforeAddToCartPlu Code salestransactions article
being added to gin
shoppping cart
Read or write additional com.sap.sales.SalesDocumentMapperPlu Code salestransactions loyalty
data from SAP CRM gInCRM
back end
Add JavaScript to the com.sap.sales.salesJS View salestransactions extension
order, quotation, and/or example
request for quotation
views
Add information for a com.sap.sales.SalesOrderItemAttributesR Relatio salestransactions instore
sales order item elationPlugIn n
Replace products com.sap.sales.WishListItemReplacement Code wishlist article
before adding to wish PlugIn
list
Prevent products from com.sap.wishlist.CheckBeforeAddToCart Code wishlist article
being added to wish list WishListPlugIn
Replace catalog item com.sap.common.Catalog.ProductDetailsI Code catalog article
used on the page temReplacementPlugIn
showing product details
Prevent, replace, and com.sap.common.Catalog.PriceCalculatio Code catalog article
delegate the pricing of nItemReplacementPlugIn
catalog items
Substitute catalog UI (code) Code catalog article
based on catalog item's com.sap.common.Catalog.CatalogViewO
type verridePlugIn
(view) View
com.sap.common.Catalog.ItemBlockView
(view)
com.sap.common.Catalog.ItemListView
(view)
com.sap.common.Catalog.DetailContentU
pper
October 2013 31
Development and Extension Guide – Application-Specific Information
(view)
com.sap.common.Catalog.DetailMiddleSe
ction
Add additional MDM com.sap.common.Catalog.FilterExpansio Code catalog article
taxonomy table as nPlugIn
catalog filters
Replace the catalog ID com.sap.common.Catalog.CatalogSearch Code catalog E-service
of advanced search #1 IDPlugIn_1
Replace the catalog ID com.sap.common.Catalog.CatalogSearch Code catalog E-service
of advanced search #2 IDPlugIn_2
Add UI content below com.sap.common.Catalog.BottomLeftNav View catalog campaign
the left navigation
Add UI content in block com.sap.common.Catalog.BlockViewBelo View catalog prodavailab
view between product wTitle ility
title and image
Add UI content in block com.sap.common.Catalog.BlockView View catalog customerint
view between product eraction
detail link and price productreco
mmend
Add UI content in block com.sap.common.Catalog.BlockViewOthe View catalog wishlist
view below the price rFunctions
Add UI content in list com.sap.common.Catalog.ListViewBelow View catalog prodavailab
view between product Title ility
title and image
Add UI content in list com.sap.common.Catalog.ListView3rdCol View catalog customerint
view in the 3rd column umn eraction
Add UI content in list com.sap.common.Catalog.ListView4thCol View catalog productreco
view in the 4th column umn mmend
(top)
Add UI content in list com.sap.common.Catalog.ListViewOtherF View catalog wishlist
view in the 4th column unctions
(bottom)
Add UI content on detail com.sap.common.Catalog.DetailMiddleCo View catalog productreco
page, middle section, lumn1 mmend
1st column (top)
Add UI content on detail com.sap.common.Catalog.DetailOtherFun View catalog wishlist
page, middle section, ctions
1st column (bottom)
Add UI content on detail com.sap.common.Catalog.DetailMiddleCo View catalog prodavailab
page, middle section, lumn2 ility
2nd column
Add UI content on detail com.sap.common.Catalog.DetailMiddleCo View catalog customerint
page, middle section, lumn3 eraction
3rd column
Add UI content on detail com.sap.common.Catalog.DetailMiddleBe View catalog instore
page, middle section, lowAddToCart
4th column (bottom)
Add UI content on detail com.sap.common.Catalog.TabPanelView View catalog catalog
page, bottom tabs customerint
32 October 2013
Development and Extension Guide – Application-Specific Information
eraction
knowledge
manageme
nt
productreco
mmend
Add UI content in detail com.sap.common.Catalog.SideBarView View catalog productreco
page, right side bar mmend
Add information for a com.sap.common.Catalog.Products Relatio catalog Instore
product n productreco
mmend
Replace item for free com.sap.marketing.FreeGoods.FreeGood Code productrecommen article
goods lookup ReplacementPlugIn d
Add UI content in single com.sap.user.RegisterView View user loyalty
page user registration contentman
agement
Add UI content in single com.sap.user.RegisterConfirmationView View user loyalty
page user registration
confirmation
Enable processing of com.sap.user.UserRegistrationPlugIn Code user loyalty
additional logic during
and after user
registration
Add UI content in block com.sap.wec.trade.ListViewOtherFunction View article None
view, below the price s
Replaces
com.sap.common.Catalog.ListViewOtherF
unctions for generic articles
Add UI content in list com.sap.wec.trade.ListViewOtherFunction View article None
view, below the price s
Replaces
com.sap.common.Catalog.ListViewOtherF
unctions for generic articles
Add UI com.sap.common.header View com.sap.common extension
content/JavaScript in examples
the contentHeader view
Add UI com.sap.common.contentHeader View com.sap.common extension
content/JavaScript in examples
the contentHeader view,
offers access to the
view handler
for retrieving information
such as breadcrumbs
and application title
Add UI content in the com.sap.main.footer View main
footer view of the
application
Add UIcContent in the com.sap.main.header View main
header view of the
application
Add UI content to the com.sap.ipc.otherFunctions View ipc shoppingte
October 2013 33
Development and Extension Guide – Application-Specific Information
sidebar view in the mplates
configuration UI under
the picture of the
product and the total
price, e.g Add to
Templates button
For more information about plug-ins, see the Development and Extension Guide: Generic Information for SAP Web
Channel Experience Management on SAP Service Marketplace at http://service.sap.com/wec-inst, under Modules ->
Module Dependencies -> Module Interface Plug-In.
1.5.1 Sales Transactions and Wish Lists Plug-Ins
1.5.1.1 Sales Transactions Plug-Ins
Adding New Partner Functions
If you want to read and write additional partner functions to the SAP CRM back end, you can implement the
com.sap.sales.PartnerFunctionPlugIn plug in. You must define the following:
The mapping between business partner role and partner function
A list of business partner roles for the system to process (in order to read and write additional business
partner roles)
A list of business partner roles written for items
Showing Alternative Availability Views
If you want the system to show an alternative availability view for sales transactions, implement the following plug-ins:
com.sap.sales.AlternativeAvailabilityPlugIn
You can control whether the system shows the alternative availability view for a specific item.
com.sap.sales.AlternativeAvailabilityViews
You can define which of the following views the system uses as an alternative availability view:
o basketRichUIAvailability
Used in the shopping cart of the extended UI
o basketLeanUIAvailability
Used in the shopping cart of the standard UI
o orderRichUIDelivery
Used in the order and in checkout
Replacing Products Before Adding to Shopping Cart
If you want to adjust or replace products before they are added to the shopping cart, you can implement the plug-in
com.sap.sales.BasketItemReplacementPlugIn. Your implementation will receive a status and a list of items that will be
added to the shopping cart. The status can be used to prevent the items from being added to the shopping cart and to
add messages to the UI. The item list can be changed to adapt the items to be added to the shopping cart. In
summary, items can be added, replaced, or removed from the list.
Preventing Products from Being Added to the Shopping Cart
There is a possibility to check products before they are added to the shopping cart. By implementing the plug-in
com.sap.sales.CheckBeforeAddToCartPlugin, you will be able to check the item before it is processed. Any messages
created will be displayed on the Web shop UI.
Reading or Writing Additional Data from the SAP CRM Back End
To read or write additional data from the RFC function modules CRM_WEC_ORDER_READ and
CRM_WEC_ORDER_SET, you can use plug-in com.sap.sales.SalesDocumentMapperPlugInCRM. You must define
34 October 2013
Development and Extension Guide – Application-Specific Information
the data to be requested (or set). You must also read or write the data to the RFC call. The processing of the
additional data must be added to the function modules. As an alternative, you can use the extension concept of the
SAP CRM back end. In this case, you do not have to use this plug-in, but can enhance the class ExtensionMapper for
the SAP CRM back end.
1.5.1.2 Wish List Plug-Ins
Replacing Products Before Adding to the Wish List
If you want to adjust or replace a product before it is added to the wish list, you can implement the plug-in
com.sap.sales.WishListItemReplacementPlugIn. Your implementation receives a status and a list containing the item
to be added to the wish list. The status can be used to prevent the item from being added to the wish list and to add
messages to the UI. The item in the item list can be changed. The list must only contain 1 item. If the status is set to
error, the list might be empty.
Preventing Products from Being Added to the Wish List
There is a possibility to check products before they are added to the wish list. By implementing the plug-in
com.sap.wishlist.CheckBeforeAddToCartWishListPlugIn, you can check the item before it is processed. Any
messages created are displayed on the Web shop UI.
October 2013 35
Development and Extension Guide – Application-Specific Information
2 Generic Topics
2.1 Application Modules
You can create a new Web Channel module from scratch and integrate the module into the common application
infrastructure.
2.1.1 Creating and Integrating New Modules into the Application
You can use a wizard to create new modules for Web Channel Builder. You can either generate only the module parts
that are needed or generate all three (that is, md, ui, and bo) as shown in the following figure:
36 October 2013
Development and Extension Guide – Application-Specific Information
The deployment unit of the new module has to be added to the extension application as a dependency. In this way,
we make sure that the new module is deployed with the whole application, as shown in the following figure:
In Web Channel Builder, the new module is shown as part of the customer namespace when adding it to the
configuration, as shown in the following figure:
Now we can add content to the new module, for example add a new page showing a simple text as content, as shown
in the following code:
<!DOCTYPE ui:composition SYSTEM "-//W3C//DTD XHTML 1.0 Transitional//EN">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:wcf="http://java.sun.com/jsf/composite/wec"
October 2013 37
Development and Extension Guide – Application-Specific Information
xmlns:wecf="http://java.sap.com/wec/wcf/composition"
template="#{wecf:getBasePage('invoices','invoicePage')}">
<ui:define name="baseExtension">
<ui:decorate template="#{wecf:getPageLayout('invoices','invoicePage')}">
<ui:define name="content">
<wcf:pageArea areaName="content" id="paCAU"/>
</ui:define>
</ui:decorate>
</ui:define>
</ui:composition>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<UIRepository xmlns="http://www.sap.com/wec/wcf/viewcomposition/ui-repository"
xmlns:wec="com.sap.wec.core.config" module="invoices">
<PageReference moduleInterface="com.sap.main" moduleInterfacePage="basePage"
name="refBasePage" />
<Page defaultLayout="1column"
name="invoicePage"
contentArea = "contentInvoice"
extends="refBasePage"
ownLayoutUsed="true"
menu="highlightInvoice">
<Layout name="1column"/>
<Area defaultInclude="invoiceInclude" name="content"/>
</Page>
<Layout name="1column" moduleInterfaceLayout="1column" moduleInterface="com.sap.wcf.Layouts"
/>
<UIInclude name="invoiceInclude"/>
</UIRepository>
2.1.2 Integrating the New Module into the Common Application Infrastructure
Once you have created a new module, you can integrate it into the common application infrastructure and add the
following:
Breadcrumbs for the new page
A new menu entry corresponding to the new functionality
A new entry in the My Account area of the Web shop
2.1.2.1 Adding a New Entry in My Account
After following the steps below, you will be able to configure the My Account module by using Web Channel Builder in
such a way that a new entry corresponding to the module you have created is available in the left menu navigation of
My Account.
1. In the metadata part of the new module, create a file called myaccount.xml with the following content:
<LEFTMENU xmlns:wec="com.sap.wec.core.config" xmlns:x="http://www.w3.org/2001/XInclude">
<MENUITEM type="4" level="1" position="3">
<INAME resourcekey="invoices.ui.myaccount.invoice" id="iP">Invoice</INAME>
<TARGET>toInvoice</TARGET>
</MENUITEM>
38 October 2013
Development and Extension Guide – Application-Specific Information
</LEFTMENU>
2. Define the navigational target toInvoice in the the ui-repository.xml, which belongs to the ui part of the module,
as shown in the following code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<UIRepository xmlns="http://www.sap.com/wec/wcf/viewcomposition/ui-repository"
xmlns:wec="com.sap.wec.core.config" module="invoices">
...
<NavigationTarget name="toInvoice" targetComposition="Area:invoiceInclude"/>
...
</UIRepository>
3. Register the myAccount.xml file in the metadata.xml, as shown in the following code:
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata" lazyLoad="true"
mainModule="false" moduleID="invoices">
<moduleType>application</moduleType>
<configForModule>invoices</configForModule>
...
<config-file namespace="customer" part="md" type="myaccount">myaccount.xml</config-file>
...
</module>
2.1.2.2 Adding a New Entry to the Menu Shown in the Header Area of the Application
After completing the steps below you will see a new menu entry corresponding to the new module (in the header area
of the application).
The menu in the header area of the application that contains the links to the main areas of the application, such as
Shop, My Account, Service and Support, is not configurable in Web Channel Builder. The definition of the menu is part
of the main module; therefore, in order to define new menu entries, you must create an extension of the main module.
In the ui part of the extended main module, define the menuConfig.xml as follows:
<MenuConfiguration xmlns:wec="com.sap.wec.core.config">
<wec:ifValue variable="${invoices#_ACTIVE_}" value="true">
<Menu name="invoices" navigation="toMyInvoices" order = "4000"
description="main.ui.header.invoices.menu" />
</wec:ifValue>
<MenuMapping moduleMenuName="invoices:highlightInvoice" menuName= "invoices"/>
</MenuConfiguration>
The definition of the new menu entry is surrounded by an ifValue expression with the purpose of making the menu
entry visible only if the new module:invoices is active in the configuration of the shop. The MenuMapping tag specifies
which menu item should be highlighted when the Web shop customers are on a page that belongs to the invoices
module.
<Page defaultLayout="1column" name="invoicePage"
contentArea = "contentInvoice"
extends="refBasePage"
ownLayoutUsed="true"
October 2013 39
Development and Extension Guide – Application-Specific Information
menu="highlightInvoice">
<Layout name="1column"/>
<Area defaultInclude="invoiceInclude" name="content"/>
</Page>
The navigational target toMyInvoices is defined in the ui-repository.xml of the extended Main module:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<UIRepository xmlns="http://www.sap.com/wec/wcf/viewcomposition/ui-repository"
xmlns:wec="com.sap.wec.core.config" module="main">
<NavigationTarget name="toMyInvoices"
moduleInterface="com.sap.customer.invoices.Invoice"
moduleInterfaceTarget="toMyInvoices"/>
</UIRepository>
The module interface com.sap.customer.invoices.Invoice is defined in the interfaceDefinition.xml in the metadata part
of the Invoices module. The extended main module has a dependency to this interface and can use only what the
invoices module exposes via this interface:
<module-interfaces xmlns="http://www.sap.com/wec/frw/tc/modules/metadata/interfaceDefinitions"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sap.com/wec/frw/tc/modules/metadata
interfaceDefinitions.xsd">
<!-- Module interface for including account views -->
<module-interface name="com.sap.customer.invoices.Invoice">
<navigationTarget name="toMyInvoices" />
</module-interface>
</module-interfaces>
The actual navigation target with the same name toMyInvoices is defined in the ui-repository.xml that belongs to the ui
part of the invoices module:
<NavigationTarget name="toMyInvoices" targetComposition="Page:invoicePage"/>
2.1.2.3 Adding Breadcrumbs to a Page Belonging to a New Module
You can create breadcrumbs for a page belonging to the newly created Invoices module. The breadcrumbs in the
Web shop are not navigation paths, but are rather hierarchical paths. Therefore, you must define breadcrumbs in a
configuration file, which is defined in the extended main module.
1. In the ui part of the extended main module, define the breadcrumbConfig.xml file as shown in the following
code:
<BreadcrumbConfiguration>
<BreadcrumbTrail name="invoices:invoiceBC" >
<BreadcrumbEntry name="myAccount" order = "10" target="toMyAccount"
description="main.ui.header.myaccount" />
<BreadcrumbEnd name="end" description="main.ui.header.myaccount.invoice"
hasId="false"/>
</BreadcrumbTrail>
</BreadcrumbConfiguration>
40 October 2013
Development and Extension Guide – Application-Specific Information
2. Register the breadcrumbConfig.xml file in the metadata.xml file of the main module, as shown in the following
code:
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata" lazyLoad="true"
mainModule="true" moduleID="main">
<moduleType>application</moduleType>
<configForModule>main</configForModule>
<config-file namespace="customer" part="ui"
type="breadcrumbs">breadcrumbConfig.xml</config-file>
....
</module>
3. Use the breadcrumb defined in the extended main module in the ui-repository.xml file of the invoices module,
as shown in the following code:
<ViewComponent name="invoiceView" breadcrumb="invoiceBC" />
October 2013 41
Development and Extension Guide – Application-Specific Information
2.2 Currency Converters
Currency converters, like other converters or validators, are managed by JSF and registered in the faces-config.xml
file. This implies that the extension technique is different compared to extending configuration files that are managed
by the SAP Web Channel Experience Management framework (WCEM).
While a new implementation of a converter or a validator resides in an extended WCEM module like for other WCEM
entities, the extension of the faces-config.xml file does not need to be declared, but a JSF specific tag needs to be
used to guarantee that the order of interpreting the different faces-config.xml files is correct.
Extending the Common Settings Module
As converters are part of the Common Settings module (com.sap.common) and need infrastructure, an extension of
the common m module needs to be done with the WCEM eclipse plug-in. Only the md and ui parts are necessary. The
plug-in also generates the DPU development component. The following figure shows the module settings:
Note
Depending on the version, the plug-in does not take care of the module type. As the common module is a system
module (that is, always available), you should check the module type in the metadata.xml. If the module type is
application, Web Channel Builder raises an exception.
42 October 2013
Development and Extension Guide – Application-Specific Information
Therefore, metadata.xml must look like this for the extended common module:
...
<moduleType>system</moduleType>
...
Implementing and Registering New Converter
Implement a new converter in the ui part of the extended common module. Note that for you to be able to access the
SAP version of the Common Settings module, both the ui and the dpu part need the appropriate references to the
standard development components. For the DPU, a reference to wec/comm/mc/common/dpu is necessary.
Register the new implementation in the faces-config.xml as shown in the following code (and also specify the ordering
of the faces-config files so that your version is processed after the standard ones have been inspected):
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<name>extension</name>
<ordering>
<after>
<others />
</after>
</ordering>
<converter>
<converter-id>wecCurrency</converter-id>
<converter-class>
com.customer.wec.app.common.ui.converter.CurrencyConverter</converter-class>
</converter>
</faces-config>
October 2013 43
Development and Extension Guide – Application-Specific Information
2.3 Central Header and Footer
This example demonstrates how to add information to the common application header or footer, and how to replace
the standard footer with a custom one.
Creating a New Module
You need to create a new module, and attach it to your Java application and Web Channel Builder application. Since
the extension of header and footer is possible via a plug-in, this new module does not need to be an extension of the
Main module in the sap namespace. You can check the development components starting with wec/extexample that
are part of software component SAP-WEC.
This new module needs the md, the bo, and the ui parts.
Adding Information to Application Header
The application header provides the plug-in com.sap.main.header. You can declare its implementation in the
metadata.xml file of your module:
<interfaceImplementation interfaceName="com.sap.main.header">
<view viewName="plugIn" usedView="additionalHeader" />
</interfaceImplementation>
This declaration states that you need to provide the include additionalHeader.xhtml that points to a corresponding
component. The component could look as follows:
...
<cc:interface componentType="sap.wec.ViewComponent">
</cc:interface>
<cc:implementation>
<wec:panelGroup id="pgExtToolbarBtns" styleClass="fw-toolbar-btn">
<wec:commandButton value="#{i18n['basics.ui.header.menu1']}"></wec:commandButton>
<wec:commandButton value="#{i18n['basics.ui.header.menu2']}"></wec:commandButton>
</wec:panelGroup>
<wec:outputText
id="addHdr"
styleClass="fw-link-bt-text"
value="#{i18n['basics.ui.header']}" />
</cc:implementation>
...
Adding Information to Application Footer
The application footer provides a plug-in that is similar to the one described in the section above, called
com.sap.main.footer. You can declare its implementation in the metadata.xml file of your module:
<interfaceImplementation interfaceName="com.sap.main.footer">
<view viewName="plugIn" usedView="footer" />
</interfaceImplementation>
This declaration states that you need to provide the include footer.xhtml that points to a corresponding component.
The component could look like this:
...
<cc:interface componentType="sap.wec.ViewComponent">
</cc:interface>
44 October 2013
Development and Extension Guide – Application-Specific Information
<cc:implementation>
<wec:panelGroup
layout="block"
styleClass="fw-footer-box">
<wec:outputText
id="oTHL" styleClass="fw-footer-title"
value="#{i18n['basics.ui.footer']}" />
</wec:panelGroup>
</cc:implementation>
...
Disabling the Standard Footer
If you want to remove the entire existing footer, the plug-in com.sap.main.footer, mentioned above, also provides a
Java part that allows you to disable the standard footer. To achieve this, you need to introduce a module access class
for the new module, and register it in the metadata.xml file.
<moduleClasses>
<moduleAccessClass>com.sap.customer.basics.modulemgmt.BasicsModuleAccess</moduleAccessClas
s>
</moduleClasses>
This module access class would then state that the standard footer should be hidden, and annotate this method with
the name of the plug-in:
@ModuleInterfacePlugin(interfaceName = "com.sap.main.footer")
public FooterPlugIn getFooterPlugIn() {
return new FooterPlugIn() {
public void controlStandardFooter(ControlFooter control) {
control.hidden = true;
}
};
}
October 2013 45
Development and Extension Guide – Application-Specific Information
2.4 JavaScript for Web Analytics
This example demonstrates how to put JS code in central parts of the WCEM application, to enable basic Web
analytics. There are much more sophisticated techniques available if specific actions should be tracked. This is
possible for example via extensions of the 'comp.theme' module and by enriching JS code that is connected to buttons
or other UI elements.
Creating a New Module
You need to create a new module and attach it to your Java application and Java Web Channel Builder application.
You can check the development components starting with wec/extexample which are part of software component
SAP-WEC; this example also covers these DCs.
This new module needs the md, bo, and ui parts.
Central JS for Page Tracking
The system module provides a plug-in com.sap.common.header that allows you to extend the application header. In
metadata.xml, its implementation can be declared like this:
<interfaceImplementation interfaceName="com.sap.common.header">
<view viewName="plugIn" usedView="genericJS" />
</interfaceImplementation>
Create an include ../includes/genericJS.xml which points to the actual component in ../components like this
<!DOCTYPE ui:composition SYSTEM "-//W3C//DTD XHTML 1.0 Transitional//EN">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:basics="http://java.sun.com/jsf/composite/customer/basics/components">
<basics:genericJS id="cGJS" />
</ui:composition>
The composite component could then look like this. Note that in the example, no CC handler is needed. If you need
your own Customizing to be included in the JS, a CC handler is required that, for example, can read attributes such as
a tracking key from the new module's configuration.
<cc:interface componentType="sap.wec.ViewComponent">
</cc:interface>
<cc:implementation>
<script type="text/javascript">
//Generic JS, e.g. for page tracking. This coding will be part of any WCEM page
</script>
</cc:implementation>
Note
There is another plug-in com.sap.common.contentHeader available that allows you to use general application
information within JS; this can be used to make the application title or the breadcrumbs available for Web analytics.
This view plug-in has an instance of com.sap.wcf.beans.contentheaderinfo.ContentHeaderInfoVCHandlerInterf
available that provides this data.
46 October 2013
Development and Extension Guide – Application-Specific Information
Tracking Orders and Order Items
The salestransactions module provides a plug-in com.sap.sales.salesJS that is included on the pages for order and
quotation display. You can declare its implementation as follows:
<interfaceImplementation interfaceName="com.sap.sales.salesJS">
<view viewName="plugIn" usedView="salesJS" />
</interfaceImplementation>
As in the section above, an include called salesJS that points to the corresponding composite component needs to be
provided. The implementation of the composite component could be similar to the following one, extracting header
and item information and making it available for JS. This coding assumes that a CC handler is present that provides
the items from the view interface data. As a reference, see com.sap.customer.basics.ui.SalesJSHandlerImpl in DC
wec/extexample/basics/ui.
..
<cc:interface componentType="sap.wec.ViewComponent">
<cc:attribute name="salesDocumentBeanJS"
type="com.sap.wec.app.esales.module.transaction.ui.beans.interf.SalesDocumentJSInbound" />
</cc:interface>
<cc:implementation>
<script type="text/javascript">
var confirmation= #{cc.attrs.salesDocumentBeanJS.orderConfirmation};
if (confirmation){
//This will only be executed in the context of order confirmation.
//You might put javascript here related to orders and items. E.g. for web analytics
purposes.
//Example: Order ID: #{cc.attrs.salesDocumentBeanJS.salesDocumentBean.id}
//Order gross value: #{cc.vch.header.grossValue}
}
</script>
<ui:repeat id="jscrItemExt" value="#{cc.vch.items}" var="item">
<script type="text/javascript">
var confirmation= #{cc.attrs.salesDocumentBeanJS.orderConfirmation};
if (confirmation){
//This will only be executed in the context of order confirmation.
//Example: Extract item information like this
//Product ID : #{item.productId}
//Item gross value : #{item.grossValue}
}
</script>
</ui:repeat>
</cc:implementation>
..
October 2013 47
Development and Extension Guide – Application-Specific Information
2.5 Country-Specific Address Formats
You can add a country-specific view for rendering addresses. In the standard system, the following address formats
are provided:
Japanese
United States
European
In this example, we add a address format (that is, family name followed by given name). The family name is displayed
at the top of the address details view.
2.5.1 Setting Up the SAP CRM or SAP ERP Back End
SAP CRM Back End
1. Define the new address layout in Customizing for SAP CRM under Customer Relationship Management ->
SAP Web Channel Experience Management -> Basic Settings -> Define Address Layouts.
2. Define a new address layout as key 03.
3. Assign the new address layout to the address layout keys as needed.
4. Map the address layout keys to countries in Customizing for SAP CRM under SAP NetWeaver -> General
Settings -> Set Countries -> Specify Countries in mySAP Systems (CRM, SRM, SCM, …).
SAP ERP Back End
1. Define the new address layout in Customizing for SAP ERP under Sales and Distribution -> SAP Web
Channel Experience Management -> Basic Settings -> Define Address Layouts.
2. Define a new address layout as key 3.
3. Assign the new address layout to the address layout keys as needed.
4. Map the address layout keys to countries in Customizing for SAP ERP under SAP NetWeaver -> General
Settings -> Set Countries -> Specify Countries in mySAP Systems (CRM, SRM, SCM, …).
2.5.2 Creating New Views for New Address Display
The system searches for address views with the Web Channel address layout key as suffix (in this example, key 03).
You only need to do extensions in the md and ui part of the user module. You need to create composite components
(that is, views) with the following names (and also the corresponding include files):
META-INF/resources/customer/user/components/user/bp/address/addressLayout03.xhtml
META-INF/resources/customer/user/components/user/bp/address/addressLayoutReadonly03.xhtml
Declaring the ui-repository.xml File in the Customer Namespace
In the md part of the extended user module, you must declare the customer version of the ui repository in the
metadata.xml file, as shown in the following code:
<config-file namespace="customer" part="ui" type="ui-repository">ui-repository.xml
</config-file>
Creating and Registering New Views in the Customer Namespace
You need to create the new views in the ui part. To create the views, copy the standard views and includes, which you
can find at the following locations:
META-INF/resources/sap/user/includes/user/bp/address
META-INF/resources/sap/user/components/user/bp/address
Ensure that you make the required changes to the address format. The target directories in your version of the
user module should look like this, assuming the extension namespace is called customer:
META-INF/resources/customer/user/includes/user/bp/address
META-INF/resources/customer/user/components/user/bp/address
Note that in the include file, you also need to refer to the correct namespace, as shown in the following code:
48 October 2013
Development and Extension Guide – Application-Specific Information
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:userBpAddress=
"http://java.sun.com/jsf/composite/customer/user/components/user/bp/address">
<userBpAddress:addressLayout03View id="addlayinc" viewInterface="#{viewInterface}"/>
</ui:composition>
Register the new views in the ui-repository.xml file as shown in the following code:
<ViewComponent
componentHandlerClassName=
"com.sap.wec.app.common.module.user.ui.bp.address.
handler.impl.AddressLayoutViewHandlerImpl"
name="addressLayout03View" />
<ViewComponent
componentHandlerClassName=
"com.sap.wec.app.common.module.user.ui.bp.address.
handler.impl.SingleAddressReadOnlyViewHandlerImpl"
name="addressLayoutReadonly03View" />
October 2013 49
Development and Extension Guide – Application-Specific Information
2.6 Store Locator - Google Maps
2.6.1 Store Locator
A typical extension of the store locator is to make the delivered example integration of Google Maps the productive
version. If another map should be integrated or further enhancements to the example should be done, the integration
interface is also described below.
2.6.1.1 Setting the Example Implementation to Productive
An example that embeds the Google Map in the graphical store locator by using the integration interface described
here can be found in the Javascript file graphical-map-script-google-example.js. See the information below on how to
enable the example integration in Web Channel Builder.
Caution
SAP does not provide licensing for the Google Map or Geocoding API. You must ensure that you take steps to fulfill
all licensing conditions. Therefore, before you use Google services, you must contact Google to obtain the necessary
right of use. For more information about terms of service, see
http://code.google.com/apis/maps/terms.html#section_10_12..
When the example integration is enabled, the graphical store locator can be used for testing purposes. However, the
system displays a text at the top of the map that indicates that the implementation is only an example, as shown in the
following figure:
To remove this text and to have the example integration as the productive version, you must extend the Web shop as
follows:
1. Create an extension for the storelocator module.
2. In the new ui DC, create a new class which extends class GraphicalMapViewHandlerImpl and overwrite only
the method isRenderExampleString. The new method should only contain a return false; statement.
3. In the new ui DC, create a ui repository which contains the following (note that
ExtensionFromGraphicalMapViewHandlerImpl must be replaced by the name of your class):
?xml version="1.0" encoding="UTF-8" standalone="no"?>
<UIRepository xmlns="http://www.sap.com/wec/wcf/viewcomposition/ui-repository"
xmlns:wec="com.sap.wec.core.config" module="storelocator">
<ViewComponent componentHandlerClassName="ExtensionFromGraphicalMapViewHandlerImpl"
name="graphical-map"/>
</UIRepository>
50 October 2013
Development and Extension Guide – Application-Specific Information
2.6.1.2 Settings in Web Channel Builder
The following settings are relevant for the integration of a graphical map:
Path to JavaScript File for Map Integration
The path to the Javascript file that contains the implementation of the map integration must be entered. The
path to the example implementation is sap/storelocator/ui/scripts/graphical-map-script-google-example.js.
Determine Geocoordinates in SAP CRM Back End
If this setting is activated, the geocoordinates of the stores are determined in the SAP CRM back end and
transferred to the graphical map where the locations of the stores are marked accordingly. The setting is
available only if the setting Show Distances to Stores in Search Results is not activated. If this setting is
activated, then the geocoordinates are determined in the SAP CRM system and transferred to the graphical
map by default. If the geocoordinates are not determined in the SAP CRM system, then the addresses of the
stores can be used to determine the geocoordinates by calling a geocoder using Javascript. The example
implementation described uses the geocoder service from Google in this case.
Key for Map Integration
In this setting, you can enter a key (or client ID) for the map integration. The usage of the example
implementation of the Google Map described requires a client ID from Google, which can be entered in this
field.
2.6.2 Graphical Map Interface
2.6.2.1 Interface for Map Integration
You can integrate a graphical map from a third-party vendor to display the locations of stores graphically. The
integration of a map can be done by using the Javascript interface, which is located in the view component graphical-
map.xhtml. The integrated map is displayed at a predefined place on the UI of the graphical store locator.
The following figure shows a schematic overview of the interaction between the Internet browser and the Java-server
when Web shop customers enter search criteria and search for stores:
During the construction of the html page in the Java-Server (see 1 in the figure above), the data needed for the map
integration is constructed. This data is then passed to the map integration by way of a set of global Javascript
variables, which are located in the view component graphical-map.xhtml. These global Javascript variables are the
interface to the map integration. In the construction step of the html page, the assignment statements that fill the
global variables are constructed. The execution of these assignment statements is not carried out here but in the next
step after the loading of the page in the Internet browser. After the execution of the assignment statements, the
system calls special Javascript hook methods that must be implemented in order to display the map. In the next step
(see 2 in the figure above), the Internet browser loads the generated html page first and then carries out the Javascript
coding for the map integration. The integration must contain the implementation of the two hook methods and can be
October 2013 51
Development and Extension Guide – Application-Specific Information
done in an own Javascript file (that is, .js). The path to this Javascript file can be entered in a configuration setting of
the store locator module in Web Channel Builder. An example implementation that embeds the Google Map into the
store locator using this Javascript interface is part of the delivery. The technical details that are used in order to fill the
data in the interface are explained below. This description can be helpful if an enhancement of the interface is
necessary.
2.6.2.2 Global Javascript Variables in the graphical-map.xhtml File
The Javascript coding that is embedded in the view component graphical-map.xhtml contains several global variables
that are used to transfer data to the map integration. These global variables are the interface to the map integration.
The following explains the content of these global variables:
Variable Content
gv_gsl_country_name The name of the country that the user has selected in the selection screen
in the language used in the browser.
gv_gsl_region_name The name of the state/region that the user has selected in the selection
screen in the language used in the browser.
gv_gsl_address_string Concatenation of the addresses of all stores that were found in the last
search.
gv_gsl_index_to_csv Contains the “Index to” for each address in gv_gsl_address_string. The
values are separated by the character in gc_gsl_value_separator (which is
a comma by default; CSV = Comma-Separated Values)
gv_gsl_event The last “event” that the user has initiated. Possible values:
gc_do_search_event
User has clicked the Search button
gc_gsl_change_state_event
User has selected another state in the state dropdown listbox
gc_gsl_change_country_event
User has selected another country in the state dropdown listbox
gc_gsl_select_store_event
User has selected one store in the list containing the search results
gc_gsl_reset_search_event
User has clicked the Clear link in the selection view
gc_gsl_switch_to_graphical_event
User has switched from textual to graphical store locator
gv_gsl_map_values_csv String that has been passed to the Java server via hidden input field in the
last step
gv_gsl_lat_csv Latitudes of all stores that were found in the last search. This variable is
only filled if one of the settings Use Geocoding from the back end and Show
Distances to Stores in Search Results is activated in the configuration. If the
geocoding data of a store cannot be found in the back end, the latitude is 0
for this store.
gv_gsl_lng_csv Longitudes of all stores that were found in the last search. This variable is
only filled if one of the settings Use Geocoding from the back end and Show
Distances to Stores in Search Results is activated in the configuration. If the
geocoding data of a store cannot be found in the back end, the longitude is
0 for this store.
gv_gsl_sel_store_html_id The ID of the UI component that contains the html coding of the details of
the store that the user has selected in the result list (to be shown in an info
window in the map).
gv_gsl_store_list_data_table_id The ID of the data table that contains the html coding with the details of all
stores found in the last search (to be shown in an info window in the map).
52 October 2013
Development and Extension Guide – Application-Specific Information
gv_gsl_selected_store_address The address of the store that the user has selected in the result list.
gv_gsl_input_field_map_values_id The ID of the hidden input field that can be filled via Javascript in order to
pass values to the Java Server.
gv_gsl_selected_store_lat The latitude of the store that the user has selected in the result list. This
variable is only filled if one of the settings Use Geocoding from the back end
and Show Distances to Stores in Search Results is activated in the
configuration.
gv_gsl_selected_store_lng The longitude of the store that the user has selected in the result list. This
variable is only filled if one of the settings Use Geocoding from the back end
and Show Distances to Stores in Search Results is activated in the
configuration.
gv_gsl_selected_store_geo_found Boolean value that indicates whether the geocoordinates of the store that
the user has selected in the result list have been found in the back end.
true – geocoordinates found
false – geocoordinates not found
gv_gsl_city The city that the user has entered in the selection field City.
gv_gsl_store_id_csv Concatenation of the IDs of all stores found in the last search (separated by
the character gc_gsl_value_separator).
gv_gsl_key_for_map_integration Key for map integration as defined in the configuration settings of the store
locator in Web Channel Builder.
gv_gsl_is_secure Information whether the application is running in secure mode (using https)
or in unsecure mode (using http).
true – secure mode
false – unsecure mode
gv_gsl_message_no_coords_found Predefined message text that can be shown if the coordinates of the store
that the user has clicked in the result list could not be determined by the
geocoding service.
gv_gsl_search_panel_id The client ID of the panelGroup that contains graphical search view and
graphical result view.
gv_gsl_is_show_distance_in_result_list Boolean value that indicates whether distance search is used.
true – distance search is used
false – normal search is used
gv_gsl_last_store_index_in_paginator Index of the store that is displayed at the last position on the current page. Is
needed for the zooming functionality in the distance search.
gv_gsl_lat_start_address Latitude of the start address for the distance search.
gv_gsl_lng_start_address Longitude of the start address for the distance search.
gv_gsl_you_are_here_title Predefined text in the language used by the user (English: You are here)
that is displayed in the map in order to identify the starting point of the
distance search.
gc_gsl_do_search_event Constant StoreSearch.DO_SEARCH_EVENT
( = "SEARCH_EVENT")
gc_gsl_change_region_event Constant StoreSearch.CHANGE_REGION_EVENT
( = "CHANGE_REGION_EVENT")
gc_gsl_change_country_event Constant StoreSearch.CHANGE_COUNTRY_EVENT
( = "CHANGE_COUNTRY_EVENT")
gc_gsl_select_store_event Constant StoreSearch.SELECT_STORE_EVENT
( = "SELECT_STORE_EVENT")
gc_gsl_value_separator Constant StoreSearchBeanImpl.VALUE_SEPARATOR
October 2013 53
Development and Extension Guide – Application-Specific Information
(= ",")
gc_gsl_apply_map_values_event Constant StoreSearch.APPLY_MAP_VALUES_EVENT
( = "APPLY_MAP_VALUES_EVENT")
gc_gsl_reset_search_event Constant StoreSearch.RESET_SEARCH_EVENT
( = "RESET_EVENT")
gc_gsl_switch_to_graphical_event Constant StoreSearch.SWITCH_TO_GRAPHICAL_EVENT
( = "SWITCH_TO_MAP_EVENT")
2.6.2.3 Javascript Hook Methods in the graphical-map.xhtml File
The Javascript coding that is embedded in the view component graphical-map.xhtml is divided into two parts:
The first part is carried out at the point in time whern the whole page is loaded in the Web browser. This part
contains the assign statements that fill the global JavaScript variables, as well as a call of the hook method
com.sap.wec.appl.storelocator.gsl_load_script(). This call is carried out after the page has been loaded in the
Web browser and can be used to instantiate and display the graphical map (example: the point in time when
the graphical store locator is displayed the first time).
The second part is carried out at the point in time when the user triggers an AJAX event that needs to refresh
the already displayed graphical map. This part also contains the assign statements that fill the global
JavaScript variables and a call of the hook method
com.sap.wec.appl.storelocator.gsl_load_script_on_ajax().This call is carried out after the parts of the html
page related to the AJAX event have been loaded in the Web browser. The method can be used to refresh
the graphical map that is already displayed at that time (example: the user clicks the Search button and the
stores found are marked on the graphical map).
2.6.2.4 Call of a Getter Method
This is the easiest way to transfer data from the Java server to the JavaScript implementation. Inside the JavaScript
coding of the map integration, a getter method of one of the Java beans can be called in order to fill a JavaScript
variable with the data. The Java beans that are related to the view component graphical-map.xhtml are the view
component handler (GraphicalMapViewHandlerImpl.java) and the BO bean (StoreSearchBeanImpl.java).
If, for example, the enhancement of the interface with the additional field myProperty of the BO bean
StoreSearchBeanImpl is necessary then this can be done in the following way:
The property myProperty and the getter method getMyProperty are added to the BO bean
In the JavaScript coding, a variable can be filled with the value of the property in the following way:
gv_gsl_my_property = '$ {this.storeSearchBean.myProperty}';
During the construction time of the html page in the Java server the call of the getter method is carried out. That is
why in the html coding that is sent to the browser only the result of this call is visible, for example, gv_gsl_my_property
= ‘XYZ’
2.6.2.5 Display of Generated HTML Coding
It is possible to access parts of the generated html page inside the map integration. This mechanism can be used in
order to display detailed data of one store inside the map (with a so called “Info Window”).
The following steps have to be carried out in order to implement this:
Creation of a “binding” for the desired UI component.
With a binding (attribute binding of the UI component) the desired UI component is linked to a property of the
related Java bean. The implementation of the Java bean must contain a property of the correct type and a
setter method that sets this property.
Providing a getter method for the AD of the UI component.
In the related Java bean, a getter method must be implemented that provides the ID of the linked UI
component.
Access to generated html coding
In the JavaScript coding of the map integration, the getter method for the ID of the UI component can be
called and then the html coding can be accessed, for example, using the JavaScript command innerhtml.
The following is an example in GraphicalMapViewHandlerImpl.java:
54 October 2013
Development and Extension Guide – Application-Specific Information
Property: selStoreUIComponent
Setter method: setSelStoreUIComponent
Getter method for the UI component: getSelStoreHtmlId
2.6.2.6 Transfer of Data from Javascript to the Java-Server by Hidden Field
The transfer of data from the JavaScript coding of the map integration to the Java server can be done by filling a
hidden input field with the desired data and by transferring this input field with the next request. The hidden input field,
which can be used for this purpose, is located in the view component graphical-search.xhtml (id = iTMapValues). If the
hidden input field is filled, then its content is available after the next request in the global JavaScript variable
gv_gsl_map_values_csv.
October 2013 55
Development and Extension Guide – Application-Specific Information
2.7 Store Locator - NAVTEQ Maps
Note
Ensure that you follow the guidelines about how you can extend the store locator. For more information, see Store
Locator - Google Maps.
You can extend the Web shop by implementing NAVTEQ instead of Google. The implementation of NAVTEQ maps is
based on the general extension concept. The whole implementation is done in the customer namespace. Therefore,
no modification is necessary from the customer perspective. The relevant information concerning NAVTEQ maps can
be found in the NAVTEQ developer guide (see http://Jsapi.lbsp.navteq.com/v1/developerguide).
Caution
Ensure that you read and follow all NAVTEQ terms and conditions before extending the Web shop with NAVTEQ
maps.
You must put the component view graphical-map to the customer namespace (and the corresponding JavaScript file
from resource folder resources.sap.storelocator.ui.scripts). You can implement these according to your requirements.
Do not forget to redefine the view handler MapViewHandlerImpl as described in the information about the store
locator. Afterwards, you can configure your Web shop and activate your specific enhancement for the storelocator
module. The following figure shows the storelocator module in Web Channel Builder:
56 October 2013
Development and Extension Guide – Application-Specific Information
The following screenshot shows what the graphical map might look like using NAVTEQ:
October 2013 57
Development and Extension Guide – Application-Specific Information
2.8 CSS-Only Changes to Configuration UI (Status Icons)
This example shows how simple UI modifications can be achieved by simply changing the CSS.
Goal: The status icons on group and instance level shall be moved from the right-hand side to the left-hand
side. There shall also not be any status icons on characteristic level.
Before:
After:
Prerequisite - Creating a Theme
Before adapting the CSS file, a custom theme has to be created. For information on how to create a custom theme,
see the Development and Extension Guide: Generic Information.
58 October 2013
Development and Extension Guide – Application-Specific Information
Identifiying Changes
One possibility to try out changes made to the CSS in advance is by using the Firefox plugin "Firebug" or a similar
tool. Using this, it is possible to identify the styling you want to adapt. It is even possible to make the adaption on-the-
fly and check whether the result meets the expectations. With this approach, you can change the CSS so that the
page matches your requirements.
Change CSS
As a last step you can enter the changes that you made to the CSS, in the stylesheet. If you always maintain your
changes at the bottom (or in a separate file included at the end), these changes will overrule the existing rules. You
only have to maintain the delta in the standard stylesheet.
October 2013 59
Development and Extension Guide – Application-Specific Information
/*### customer extension/adjustment ###*/
.fw-step-title span { margin: 20px; }
.fw-step-title .fw-step-title-price span { margin: 0px; }
.fw-dui-v1-status { display: none; }
.fw-nested-accordion-step-status-image-ok, .fw-nested-accordion-step-status-image-okay, .fw-
nested-accordion-step-status-image-error { left: 0px; }
.fw-nested-accordion-step-status-img-ok, .fw-nested-accordion-step-status-img-okay, .fw-nested-
accordion-step-status-img-error { left: 0px; }
60 October 2013
Development and Extension Guide – Application-Specific Information
3 Product Catalog
3.1 Transfer of Additional Fields from MDM to Product
Catalog
This section explains how to extend the product catalog to retrieve additional fields from MDM. The extension
prototype was done for a CRM scenario, however the same steps apply to an ERP scenario. The only difference is
that the CatalogMDMERP class must be extended instead of the CatalogMDMCRM class. In the prototype, we
retrieve all 4 fields of the GTIN tuple as an example.
1. Extend the result definition to contain the additional fields. This is achieved by overriding the method below
and adding to the result definition the name of the field in the main table pointing to the tuple that contains the
desired fields.
@Override
protected ResultDefinitionManager createResultDefinitionForItems() {
ResultDefinitionManager resultDefinitionForItems =
super.createResultDefinitionForItems();
/** The GTIN tuple field from main item table */
resultDefinitionForItems.addField(this.rse.getField(Tables.CATALOG_ITEM_TABLE_NAME,
WECMDM_CRM_GTIN));
return resultDefinitionForItems;
}
2. Extend the supporting result definition to contain the desired tuple fields and any additional lookup fields
required. The code snippet below covers how to fetch two different field types from the tuple: A regular field
(for example, of type text) and a lookup field to another table. In the example below the fields
WECMDM_CRM_UNIT_OF_MEASURE and WECMDM_CRM_GTIN_TYPE are lookups to other existing
tables.
@Override
protected ResultDefinitionManager createSupportingResultDefinitionForItems()
throws BackendException {
ResultDefinitionManager srdm = super.createSupportingResultDefinitionForItems();
/** Tuple : Global Trade Item Numbers */
/** Global Trade Item Number - Text */
srdm.addField(this.rse.getTupleMemberField(WECMDM_CRM_GTINS, WECMDM_CRM_GTIN));
/** Units of Measure - Lookup [Flat] */
srdm.addField(this.rse.getTupleMemberField(WECMDM_CRM_GTINS,
WECMDM_CRM_UNIT_OF_MEASURE));
/** Global Trade Item Number Type - Lookup [Flat] */
srdm.addField(this.rse.getTupleMemberField(WECMDM_CRM_GTINS,
WECMDM_CRM_GTIN_TYPE));
/** Main Global Trade Item Number Indicator - Boolean */
srdm.addField(this.rse.getTupleMemberField(WECMDM_CRM_GTINS,
WECMDM_CRM_MAIN_GTIN));
/** Needed for (Units of Measure - Lookup [Flat]) */
October 2013 61
Development and Extension Guide – Application-Specific Information
/** Table : Units */
/** Unit of Measurement - Text */
/**
* Even if this field is already added by the super call, adding this
* field again cause no issues.
*/
srdm.addField(rse.getField(Tables.UNITS_TABLE_NAME,
Fields.PRODCATALOG_UNITS_UOM_FLD_NAME));
/** Needed for (Global Trade Item Number Type - Lookup [Flat]) */
/** Table : Global Trade Item Number Types */
/** Global Trade Item Number Type - Text */
srdm.addField(rse.getField(WECMDM_CRM_GTIN_TYPES, WECMDM_CRM_GTIN_TYPE));
return srdm;
}
3. Extend the CatalogItem object to contain the additional field values. MDM returns the desired values in a
Record object, which is passed to the method below. The values are copied from the Record object into a
container object (in this example, GTIN). This is done by first retrieving the MDM field ID of each field from the
repository schema, and then fetching the corresponding values from the Record object. Finally, the container
object is added to the extension map. Note that the GTIN field is multi-valued, which means that several tuple
records can be returned, and a loop is needed to get all the values.
@Override
protected CatalogItem parseCatalogItem(Record record) throws BackendException {
CatalogItem catalogItem = super.parseCatalogItem(record);
/** The record's field */
FieldId gtinsFID = this.rse.getField(Tables.CATALOG_ITEM_TABLE_NAME, WECMDM_CRM_GTIN)
.getId();
/** All fields in the tuple */
FieldId gtinFID = this.rse.getTupleMemberField(WECMDM_CRM_GTINS, WECMDM_CRM_GTIN).getId();
FieldId uomFID = this.rse.getTupleMemberField(WECMDM_CRM_GTINS, WECMDM_CRM_UNIT_OF_MEASURE)
.getId();
FieldId typeFID = this.rse.getTupleMemberField(WECMDM_CRM_GTINS, WECMDM_CRM_GTIN_TYPE)
.getId();
FieldId mainFID = this.rse.getTupleMemberField(WECMDM_CRM_GTINS, WECMDM_CRM_MAIN_GTIN)
.getId();
/** Needed lookup tables */
FieldId lookupUomFID = rse.getField(Tables.UNITS_TABLE_NAME,
Fields.PRODCATALOG_UNITS_UOM_FLD_NAME).getId();
FieldId lookupTypeFID = rse.getField(WECMDM_CRM_GTIN_TYPES, WECMDM_CRM_GTIN_TYPE).getId();
List<GTIN> gtins = new ArrayList<GTIN>();
MdmValue mv = record.getFieldValue(gtinsFID);
if (!mv.isNull()) {
/** The gtin field in the main table is a multi value tuple */
MultiTupleValue mtv = (MultiTupleValue) mv;
for (MdmValue v : mtv.getValues()) {
TupleValue tv = (TupleValue) v;
62 October 2013
Development and Extension Guide – Application-Specific Information
GTIN gtin = new GTIN();
/** toString() is fine for TextAttributeValue & MultiregionValue */
gtin.gtin = tv.getFieldValue(gtinFID).toString();
/** The text value isn't in the tuple but the lookup table field */
gtin.uom = this.catalogHelper.getSingleValueStringLookupValue(tv,
uomFID,
lookupUomFID);
/** The text value isn't in the tuple but the lookup table field */
gtin.type = this.catalogHelper.getSingleValueStringLookupValue(tv,
typeFID,
lookupTypeFID);
/** MdmValue must be checked for null before being type casted */
MdmValue fieldValue = tv.getFieldValue(mainFID);
if (!fieldValue.isNull()) {
BooleanValue bv = (BooleanValue) fieldValue;
gtin.main = bv.getBoolean();
}
else {
gtin.main = false;
}
gtins.add(gtin);
}
}
/** This extension container is propagated to the BO.getExtensionData() */
catalogItem.getExtensionMapInternal().put(EXT_GTINS, gtins);
return catalogItem;
}
October 2013 63
Development and Extension Guide – Application-Specific Information
3.2 Transfer of Additional Fields from CRM to MDM
3.2.1 Introduction
Using a Web shop also means having different systems in use. If your system landscape includes ERP, CRM, and
MDM, you often face the issue that you need more information on the Web shop side that is given in CRM, but not
available on the MDM side. This section describes how you can enhance your MDM repository to have the
corresponding information in MDM as well. Based on that, you can refer to the preceding section to bring this
information from MDM to the Java layer. This enhancement is based on the precondition of having an existing set type
in CRM (including an attribute) that you want to pass to MDM. The documentation describes the steps that need to be
performed both on the CRM side (ABAP) and on the MDM side, to get the new field (attribute) from CRM to MDM.
In this document, we describe how to bring the information about the country of origin to the MDM product catalog.
This field exists for all products of subtype material -> trading goods.
Minimum system requirements:
1. SAP Web Channel Experience Management 2.0 or higher
2. SAP CRM EhP1 or higher
Out of scope:
Creation of the set type that carries the additional information. Here, only the set type created beforehand is
presented.
Maintenance of the set type on CRM side
Field extension on ERP side and transfer from CRM to MDM
MDM connected directly to an ERP system
Extraction of new lookup tables/customizing to MDM
Products other than materials
The documentation is splitted into two parts:
Steps on CRM side
Steps on MDM side
64 October 2013
Development and Extension Guide – Application-Specific Information
3.2.2 Steps on CRM Side
3.2.2.1 Locating the Set Type
The country of origin is stored in a separate set type, ZORG_COUNTRY, which is relevant for materials only.
October 2013 65
Development and Extension Guide – Application-Specific Information
This set type contains only one field, the attribute ZORIGIN_COUNTRY_ATTR.
The attribute ZORIGIN_COUNTRY_ATTR is defined as a CHAR3 field, like the country code it refers to.
66 October 2013
Development and Extension Guide – Application-Specific Information
The assignment of set types to products takes place via transaction COMM_ATTRSET. The assignment takes place
only for materials of subtype HAWA (trading goods).
October 2013 67
Development and Extension Guide – Application-Specific Information
Using this, it is possible to maintain the country of origin, for example, in transaction COMMPR01. In this example, we
have an original babushka from Russia.
68 October 2013
Development and Extension Guide – Application-Specific Information
3.2.2.2 Bringing the Set Type to BDoc PRODUCT_MAT
For this step, nothing needs to be done. As soon as the set type is put into a workbench request, the BDoc definition
is updated automatically. This can be seen in transaction SBDM:
The DDIC type COMT_PROD_MATERIAL_BDOC_TAB is a table with the line type
COMT_PROD_MATERIAL_BDOC. The data section of the BDoc refers to DDIC structure
COMT_PROD_MAT_MAINTAIN_API. This has been automatically enhanced by the new set type.
October 2013 69
Development and Extension Guide – Application-Specific Information
3.2.2.3 Enhancing the MDM Outbound Adapter for PRODUCT_MAT
In the MDM outbound adapter not every data segment of the PRODUCT_MAT BDoc will be forwarded to MDM.
Instead, a mapping to the communication structure CRMS_MDM_MATERIAL_DATAEXCHANGE takes place. The
members of this structure will then be converted into an XML file which is sent to MDM. The mapping from the BDoc
structure to the communication structure takes place in class CL_CRM_MW_MDM_DATAEX_PRODMAT, method
MAP_PRODMAT_DATA_TO_MDMFORMAT. At the end of this method, a BAdI call is offered to adjust or enhance
the mapping.
70 October 2013
Development and Extension Guide – Application-Specific Information
For the additional field, an implementation of the enhancement ES_CRM_WEC_MDM_ENHANCEMENTS and the
BAdI CRM_WEC_MDM_MAPPING_BADI has to be created.
The method IF_BADI_CRM_WEC_MDM_MAPPING~MAP_CRM_MDM_PRODUCTDATA has to be implemented as
shown below. Depending on your specific case, the field names of <cs_dataexchange> and <is_product_mat> may be
different.
if_badi_crm_wec_mdm_mapping~map_crm_mdm_productdata
METHOD if_badi_crm_wec_mdm_mapping~map_crm_mdm_productdata.
FIELD-SYMBOLS <is_product_mat> TYPE comt_prod_material_bdoc.
FIELD-SYMBOLS <cs_dataexchange> TYPE crms_mdm_material_dataexchange.
FIELD-SYMBOLS <is_org_country> TYPE zorg_country_maintain.
ASSIGN is_mbdoc_msg TO <is_product_mat>.
ASSIGN cs_mdm_data_msg TO <cs_dataexchange>.
READ TABLE <is_product_mat>-data-zorg_country INDEX 1 ASSIGNING <is_org_country>.
IF sy-subrc <> 0.
RETURN.
ENDIF.
<cs_dataexchange>-zzorigin_country = <is_org_country>-data-zz0010.
ENDMETHOD.
Once the BAdI implementation is active, the country of origin automatically appears in the XML file sent to MDM.
<?xml version="1.0" encoding="UTF-8"?>
<TABLE xmlns:asx="http://www.sap.com/abapxml">
<CRMS_MDM_MATERIAL_DATAEXCHANGE>
...
October 2013 71
Development and Extension Guide – Application-Specific Information
<ZZORIGIN_COUNTRY>RU</ZZORIGIN_COUNTRY>
</CRMS_MDM_MATERIAL_DATAEXCHANGE>
</TABLE>
Note
If you examine the XML file more closely you will see that the new set type may also be included in the element
<SETTYPE_ATTRIBUTES>, even without implementing the mapping BAdI. Nevertheless, we recommend following
the procedure described above, for the following reasons:
With this approach it is also possible to enhance the set type with additional information.
The element SETTYPE_ATTRIBUTES is intended for the import of MDM taxonomies. Trying to access the
information of the additional set type within SETTYPE_ATTRIBUTES would result in a much more complicated
mapping on MDM side, and may interfere with the existing taxonomy import mapping.
3.2.3 Steps on MDM Side
This part describes the steps that need to be done on MDM side to be able to import a new field called Country of
Origin to the repository.
Before this step can be executed you need to ensure that the corresponding enhanced XML file is available on the file
server. It must include the new field and its value.
3.2.3.1 Creating a New Field on MDM Side via MDM Console
Within the MDM Console you need to create your new field for your repository. Access the MDM Console, build up a
connection to your repository and unload it.
After doing this, you are able to create your new field:
72 October 2013
Development and Extension Guide – Application-Specific Information
3.2.3.2 Adjusting the XML Schema
You also need to update your existing XML schema. To do this, export your existing schema, store it locally, and
adjust it according to your added field:
October 2013 73
Development and Extension Guide – Application-Specific Information
3.2.3.3 Importing the Updated XML Schema via MDM Console
After you have adjusted your schema you need to import it to the repository as well. Use the MDM Console and
navigate to folder XML Schemas there.
Attention: You also need to be connected to the corresponding repository, and you need to stop it before you can
change the XML schema.
It is possible to update the existing schema that is affected by your change. You do not need to create a new one:
3.2.3.4 Adjusting the Data Mapping
After performing the steps mentioned above you need to enhance your mapping via the MDM Import Manager. There,
map your new CRM field to the new MDM field.
Load the relevant map first:
74 October 2013
Development and Extension Guide – Application-Specific Information
Then, enhance your mapping accordingly:
3.2.3.5 Checking via MDM Data Manager
Finally, you can check whether everything works correctly by using the MDM Data Manager. Start the CRM download
to MDM on the CRM side. Start MDM Data Manager, where you should find the new field and its value:
October 2013 75
Development and Extension Guide – Application-Specific Information
3.3 Product View Modules
This guide explains how to extend product views to support modification or addition of user contexts (for CRM/ERP) or
attributes (MDM).
3.3.1 Creating an Additional MDM Attribute for Product View
The creation of a new attribute in the product view requires the following:
1. Extending the product view modules
wec/comm/mc/productview/bo
wec/comm/mc/productviewmain/bo
wec/comm/mc/productviewmain/md
wec/comm/mc/productviewmain/dpu
wec/comm/mc/wcbproductview/bo
wec/comm/mc/wcbproductview/md
wec/comm/mc/wcbproductview/dpu
2. Creating a new class that implements AttributeType
3. Enhancing backendobject-config.xml files
4. Enhancing productview/wcbext/bo/helpvalues-config.xml
5. Enhancing wcf_resources.xlf
6. Enhancing sap/productviewmain/md/metadata.xml and sap.productview/wcbext/metadata.xml
The current example describes the creation of a new MDM attribute based on the distribution channel tuple. During
this process, the GenericTupleWithLookupAttributeImpl.java will be created. This implementation could be re-used for
the Product Catalog Item tuples attribute linked to a lookup[flat].
3.3.1.1 Extending the Product View Modules
The following DC structure needs to be created:
Here is the list of dependencies that need to be set up for the DCs.
76 October 2013
Development and Extension Guide – Application-Specific Information
3.3.1.2 Creating a New Implementation of Type AttributeType
A new class needs to be created to provide a new MDM attribute. This class is responsible for retrieving (F4 Help) and
validating the data in the configuration time, as well as for applying the constraint during the runtime. In the following
example, a new GenericTupleWithLookupAttributeImpl.java class is created in the test/extens/productview/bo.
To provide a generic way to deal with tuples using a Lookup[Flat] within product catalog items,
GenericTupleWithLookupAttributeImpl is initialized using the metadata provided by the backendobject-config.xml. This
metadata contains the proper MDM path for the attribute.
public class GenericTupleWithLookupAttributeImpl extends BackendBusinessObjectBase implements
AttributeType {
[...]
public static final String SEARCH_HELP_ID = "searchHelpId";
public static final String ATTR_DESCRIPTION = "attributeDescription";
public static final String ATTR_ID = "attributeId";
public static final String ATTR_TABLE_NAME = "attributeTableName";
public static final String ATTR_FIELD_NAME = "attributeFieldName";
public static final String ATTR_DESC_FIELD_NAME = "attributeDescriptionFieldName";
public static final String PRODUCT_TABLE_NAME = "productTableName";
public static final String PRODUCT_TABLE_FIELD_NAME = "productTableFieldName";
public static final String PRODUCT_TUPLE_NAME = "productTupleName";
public static final String PRODUCT_TUPLE_FIELD_NAME = "productTupleFieldName";
private String attributeDescription;
private String attributeId;
private String attributeTableName;
private String attributeFieldName;
private String attributeDescriptionFieldName;
private String productTableName;
private String productTableFieldName;
private String productTupleName;
private String productTupleFieldName;
private String searchHelpId;
October 2013 77
Development and Extension Guide – Application-Specific Information
[...]
public void initBackendObject(Properties backendParams, BackendBusinessObjectParams params)
throws BackendException {
attributeDescription = backendParams.getProperty(ATTR_DESCRIPTION);
attributeId = backendParams.getProperty(ATTR_ID);
searchHelpId = backendParams.getProperty(SEARCH_HELP_ID);
attributeTableName = backendParams.getProperty(ATTR_TABLE_NAME);
attributeFieldName = backendParams.getProperty(ATTR_FIELD_NAME);
attributeDescriptionFieldName = backendParams.getProperty(ATTR_DESC_FIELD_NAME);
productTableName = backendParams.getProperty(PRODUCT_TABLE_NAME);
productTableFieldName = backendParams.getProperty(PRODUCT_TABLE_FIELD_NAME);
productTupleName = backendParams.getProperty(PRODUCT_TUPLE_NAME);
productTupleFieldName = backendParams.getProperty(PRODUCT_TUPLE_FIELD_NAME);
}
[...]
}
Please note that the various methods within the AttributeType are used for different aspects. Since the product view
has a configuration and a runtime aspect, some methods are used in both aspects. Here is the list of methods used in
the different aspects:
Configuration Time
o void setMdmConnector(...)
o String getId()
o String getDescription()
o boolean isValueIdValid(...)
o String getValueDescription(...)
o String getSearchHelpName()
o public Map<String, String> getHelpValuesSearchMapping(...)
o public HelpValues getHelpValues(...)
Runtime
o void setMdmConnector(...)
o String getId()
o void processAttribute(...)
3.3.1.3 Enhancing backendobject-config.xml
There are two backendobject-config.xml files used within the product view modules:
sap/productviewmain/bo/backendobject-config.xml and sap.productview/wcbext/bo/backendobject-config.xml. The first
one defines the product view backend objects used during the runtime and the second one defines the product view
back-end objects used during the configuration time. The main difference between the two back-end object definitions
is the defaultConnectionName type. The runtime uses a stateful connection whereas the configuration uses the
stateless connection (using the technical user) to communicate with the CRM/ERP back end. Except the type of
defaultConnectionName, the two files must be identical in terms of content and entries. Both backendobject-config.xml
files need to be extended via the module extension concept.
The following gives an example of adding an additional attribute called Distribution Channel Extended via the module
extension concept that allows changes and addition of metadata content. In this case, both extensions of the
backendobject-config.xml are identical since they connect to MDM and do not need to specify the back-end
connection type.
78 October 2013
Development and Extension Guide – Application-Specific Information
<?xml version="1.0" encoding="UTF-8"?>
<backend xmlns="http://www.sap.com/wec/frw/tc/common/backendconfig"
xmlns:wec="com.sap.wec.core.config" xmlns:xi="http://www.w3.org/2001/XInclude">
<businessObjects>
<businessObject name="SimpleCRMMdMAttributeFactory"
className="com.sap.wec.app.common.module.productview.backend.attribute.mdm.impl.SimpleAttributeF
actory">
<params>
<param name="AttributeType"
value="CategoryCRM,
SalesOrg,
DCExt,
DistChannel" />
</params>
</businessObject>
<businessObject name="SimpleERPMdMAttributeFactory"
className="com.sap.wec.app.common.module.productview.backend.attribute.mdm.impl.SimpleAttributeF
actory">
<params>
<param name="AttributeType"
value="MaterialClassificationCRM,
SalesOrg,
DCExt,
DistChannel" />
</params>
</businessObject>
<businessObject name="DCExt"
className="com.sap.wec.app.common.module.productview.backend.attribute.mdm.impl.GenericTupleWith
LookupAttributeImpl">
<params>
<param name="searchHelpId" value="DCExt_sh" />
<param name="attributeDescription"
value="wcbext.productview.bo.attribute.distributionchannelExt" />
<param name="attributeId" value="DCE" />
<param name="attributeTableName" value="WECMDM_CRM_ERP_DIST_CHANS" />
<param name="attributeFieldName" value="WECMDM_CRM_ERP_DIST_CHAN" />
<param name="attributeDescriptionFieldName"
value="WECMDM_CRM_ERP_DIST_CHAN_DESC" />
<param name="productTableName" value="WECMDM_CRM_ERP_PRD_CATALOG_ITMS" />
<param name="productTableFieldName" value="WECMDM_CRM_ERP_SALES_AREA" />
<param name="productTupleName" value="WECMDM_CRM_ERP_SALES_AREA_ATTRIBUTES" />
<param name="productTupleFieldName" value="WECMDM_CRM_ERP_DISTRIBUTION_CHANNEL"
/>
</params>
</businessObject>
</businessObjects>
</backend>
October 2013 79
Development and Extension Guide – Application-Specific Information
Please note that in the above example, SimpleCRMMdMAttributeFactory and SimpleERPMdMAttributeFactory are
enhanced to provide the additional DCExt value to the AttribyteType parameter. At the end of the file, there is the
definition of the additional DCExt business object.
The DCExt business object specifies as parameters all the information needed that will be injected into the business
object when this one is initialized.
Attribute Current Value Description
searchHelpId DCExt_sh Name of the search help ID used as
defined in the helpvalues-config.xml.
This search help ID needs to be
unique.
attributeDescription wcbext.productview.bo.attribute.distributionchannelExt i18n ID of the description of this
attribute
attributeId DCE ID of the attribute. This value must
be unique. It is used to identify the
attribute type in the product view.
productTableName WECMDM_CRM_ERP_PRD_CATALOG_ITMS This table represents the product
catalog item table in MDM.
productTableFieldNa WECMDM_CRM_ERP_SALES_AREA Thie field represents the field in the
me table defined in the
productTableName table. This field
must be a tuple.
productTupleName WECMDM_CRM_ERP_SALES_AREA_ATTRIBUTES Name of the tuple table that is
referenced in the
productTableFieldName
productTupleFieldNa WECMDM_CRM_ERP_DISTRIBUTION_CHANNEL Name of the field within the tuple
me table defined in productTupleName.
This field must be of type lookup[flat]
attributeTableName WECMDM_CRM_ERP_DIST_CHANS Name of the table that is referenced
in the productTupleFieldName
attributeFieldName WECMDM_CRM_ERP_DIST_CHAN Name of the column in the
attributeTableName that will be used
as ID in the product view attribute
value
attributeDescriptionF WECMDM_CRM_ERP_DIST_CHAN_DESC Name of the column in the
ieldName attributeTableName that will be used
as description in the product view
attribute description
3.3.1.4 Enhancing productview/wcbext/bo/helpvalues-config.xml
The following section shows the content of the helpvalues-config.xml that is used during the configuration time. This
content enhances the current content via the module extension concept and defines (1) the search help and (2) the
definition of its columns using the i18n text ID as defined in the xlf ressource file. One <helpValuesSearch> entry must
be created for each new attribute type created.
<helpValuesSearches xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:wec="com.sap.wec.core.config">
<helpValuesSearch name="DCExt_sh" type="simple"
description="wcbext.productview.bo.attribute.distributionchannelExt" maxRow="10">
<method name="getHelpValues" type="businessObject"
businessObjectName="ProductViewBO" />
<parameter name="id"
description="wcbext.productview.bo.searchhelp.distchannelattribytevaluef4helpExt.id"
valueDescriptionKey="wcbext.productview.bo.searchhelp.distchannelattribytevaluef4helpExt.id" />
<additionalParameter name="description" type="out"
80 October 2013
Development and Extension Guide – Application-Specific Information
description="wcbext.productview.bo.searchhelp.distchannelattribytevaluef4helpExt.description"
valueDescriptionKey="wcbext.productview.bo.searchhelp.distchannelattribytevaluef4helpExt.descrip
tion" />
</helpValuesSearch>
</helpValuesSearches>
3.3.1.5 Enhancing wcf_resources.xlf
Since a new attribute has been defined, we need to enhance the content of the wcf_resources.xml file via the module
extension concept. The following entry needs to be created in a new wcf_resources.xml file located under
/src/customer/wcbext/bo :
i18n ID i18n English Text
wcbext.productview.bo.attribute.distributionchannelExt Distribution Channel Extended
wcbext.productview.bo.searchhelp.distchannelattribytevaluef4helpExt.id Distribution Channel Extended ID
wcbext.productview.bo.searchhelp.distchannelattribytevaluef4helpExt.description Distribution Channel Description
Extended
3.3.1.6 Enhancing sap/productviewmain/md/metadata.xml and sap.productview/wcbext/metadata.xml
The metadata of the productviewmain and wcbext module needs to be extended to provide the additional content that
will refer to all the newly created xml metadata files.
The sap/productviewmain/md/metadata.xml must be enhanced following the module extension concept in the
src/customer/productviewmain/md/metadata.xml file. Here is an example of the content:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata"
xmlns:wec="com.sap.wec.core.config" lazyLoad="false" mainModule="false"
moduleID="productviewmain" resourceBundlePrefix="productviewmain">
<moduleType>application</moduleType>
<configForModule>productviewmain</configForModule>
<config-file namespace="customer" part="bo" type="backend-objects">backendobject-
config.xml</config-file>
</module>
The sap.productview/wcbext/metadata.xml must be enhanced following the module extension concept in the
src/customer/wcbext/md/metadata.xml file. Here is an example of the content:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata"
xmlns:wec="com.sap.wec.core.config" lazyLoad="true" mainModule="false"
moduleID="wcbext" resourceBundlePrefix="wcbext">
<moduleType>application</moduleType>
<config-file namespace="customer" part="bo" type="backend-objects">backendobject-
config.xml</config-file>
<config-file namespace="customer" part="bo" type="helpvalues">helpvalues-config.xml</config-
file>
</module>
October 2013 81
Development and Extension Guide – Application-Specific Information
3.3.2 Creating an Additional User Context for Product View
The creation of a new user context in the product view requires the following:
1. Extending the product view modules
wec/comm/mc/productview/bo
wec/comm/mc/productviewmain/bo
wec/comm/mc/productviewmain/md
wec/comm/mc/productviewmain/dpu
wec/comm/mc/wcbproductview/bo
wec/comm/mc/wcbproductview/md
wec/comm/mc/wcbproductview/dpu
2. Creating a new class implementing ContextType
3. Enhancing backendobject-config.xml files
4. Enhancing productview/wcbext/bo/helpvalues-config.xml
5. Enhancing wcf_resources.xlf
6. Enhancing sap/productviewmain/md/metadata.xml and sap.productview/wcbext/metadata.xml
Please note that all the steps needed to create a new context are identical to those required for the creation of a new
AttributeType, with the following differences:
The new Java implementation needs to implement ContextType.
Enhancement of the the two backendobject-config.xml to add a new business object entry that will point to the
new implementation
Enhancement of the the two backendobject-config.xml to enhance the business object
ProductViewCRMBackendImpl and/or ProductViewERPBackendImpl with the new "Business Object" to the
ContextType parameter
82 October 2013
Development and Extension Guide – Application-Specific Information
4 Product Configuration
4.1 Custom UI Rendering for Characteristics on
Configuration UI
This example shows you how to add a new UI type to the configuration UI.
Goal: The standard is enhanced so that the characteristic Expected Number of Users is rendered with a stepper
control instead of a simple input field.
Standard:
Enhancement:
To achieve this, you have to enhance the ipc module, as shown in the following steps.
4.1.1 Adding a Custom Mapper for the Configuration UI
UIElementMappers determine which characteristics are rendered in which format on the UI. To enhance this, an
additional mapper is introduced. This is accomplished via the UIElementMapperFactory.
To use a custom factory for the mappers, the factory-config.xml has to be adapted:
<factoryClass
name="com.sap.wec.app.common.module.ipc.ui.dynamic.ui.interf.UIElementMapperFactory"
singleton="false"
className="com.customer.wec.app.common.module.ipc.ui.dynamic.ui.impl.CustUIElementMapperFactoryI
mpl" />
Now, the class CustUIElementMapperFactoryImpl can enhance the existing implementation:
public class CustUIElementMapperFactoryImpl extends UIElementMapperFactoryImpl {
@Override
public void registerUIElementMappers() {
CustNumericStepperForNumberOfUsersMapperImpl numericStepperMapper = new
CustNumericStepperForNumberOfUsersMapperImpl();
registerUIElementMapper(numericStepperMapper);
super.registerUIElementMappers();
}
}
October 2013 83
Development and Extension Guide – Application-Specific Information
The order of the mappers is very important. The first applicable mapper is used. Therefore, the new mapper is
registered BEFORE super.rigisterUIElementMappers() is called.
4.1.2 Registering a New UI Type
In this example, we do not want to change the data or behavior of the UI element, only the rendering. Therefore, the
new mapper changes only the UI type to be used for rendering. Furthermore, we have to ensure that the mapper in
our example is only applicable if the characteristic is Expected Number of Users.
public class CustNumericStepperForNumberOfUsersMapperImpl extends InputUIElementMapperImpl {
@Override
public boolean isMapperForCharacteristic(Characteristic cstic, boolean isExpandedOnUI)throws
BusinessObjectException {
boolean isNumberOfUsers = cstic.getName().equals("EXP_NO_USERS");
return isNumberOfUsers;
}
@Override
public void initUIElement(EntryField uiElement,boolean validateCharacteristicOnline) throws
BusinessObjectException { super.initUIElement(uiElement, cstic, validateCharacteristicOnline);
uiElement.setUiType("uitype_numeric_stepper");
}
}
Two more steps are needed to register the new custom UI type:
1. Register a renderer class for the used string constant (in this case, uitype_numeric_stepper).
public class CustUIRendererManager extends IPCUIRendererManager {
private static final UITypeRenderer UI_TYPE_RENDERER_NUMERIC_STEPPER = new
CustUITypeRendererNumericStepper();
private static final String UI_TYPE_NUMERIC_STEPPER = "uitype_numeric_stepper";
@Override
public UITypeRenderer getUIRenderer(String uiType) {
UITypeRenderer uiRenderer;
if (UI_TYPE_NUMERIC_STEPPER.equals(uiType)) {
uiRenderer = UI_TYPE_RENDERER_NUMERIC_STEPPER;
}else {
uiRenderer = super.getUIRenderer(uiType);
}
return uiRenderer;
}
}
84 October 2013
Development and Extension Guide – Application-Specific Information
2. Define a renderer class that defines which UI include is used.
public class CustUITypeRendererNumericStepper implements UITypeRenderer {
private static String XHTML_INCLUDE_NAME = "uitype_numeric_stepper";
@Override
public String getXHTMLIncludeName() {
return UITypeRendererHandler.getXHTMLInclude(XHTML_INCLUDE_NAME);
}
}
4.1.3 Adding the Custom XHTML Fragment
Finally, we can add the XHTML fragment to be used for the introduced UI type and add the mapping between this
XHTML file and the UI include name.
To enhance the mapping of the UI includes to the XHTML file, we have to define a custom config file in the
metadata.xml file of the md part.
<config-file namespace="customer" part="ui" type="dynamic-ui-config">dynamicXHTMLInclude-
config.xml</config-file>
Then the mapping for the newly created XHTML file can be added in dynamicXHTMLInclude-config.xml.
<dynamicXHTMLIncludes xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
<xhtmlinclude name ="uitype_numeric_stepper"
value="/resources/customer/ipc/includes/dynUI/uiTypeNumericStepper.xhtml" ></xhtmlinclude >
</dynamicXHTMLIncludes>
October 2013 85
Development and Extension Guide – Application-Specific Information
4.2 Shopping Cart Summary with Pricing on Configuration UI
This example shows how the layout of the configuration UI can be changed to integrate a shopping cart summary
view. The first image shows the configuration UI before, and the second one after, the enhancement.
86 October 2013
Development and Extension Guide – Application-Specific Information
4.2.1 Changing the Layout of the Configuration UI from 2-Column-Navigation
to 2-Column-Sidebar
To use a different layout, you need to create the new page configUIWithSidebar.xhtml. It is quite similar compared to
the original configUI.xhtml page. It will have a content area as well, but instead of a navigation area, it defines a
sidebar.
<ui:define name="baseExension">
<wec:form id="fC">
<ui:decorate template="#{wecf:getPageLayout('ipc','configUIWithSidebar')}">
<ui:define name="content" >
<wcf:pageArea areaName="content" id="paC"/>
</ui:define>
<ui:define name="sidebar" >
<wcf:pageArea areaName="sidebar" id="paS"/>
</ui:define>
</ui:decorate>
</wec:form>
</ui:define>
With the EL-Expression #{wecf:getPageLayout('ipc','configUIWithSidebar')} you make a reference to the ui-
repository.xml file, where you need to declare the new page and assign the predefined 2columnSidebar layout.
October 2013 87
Development and Extension Guide – Application-Specific Information
<Page defaultLayout="2columnSidebar" name="configUIWithSidebar" extends="refBasePage"
contentArea="content" menu="shop" ownLayoutUsed="true">
<Layout name="2columnSidebar"/>
<Area defaultInclude="configUIContentIncl" name="content"/>
<Area defaultInclude="custSidebarIncl" name="sidebar"/>
</Page>
The configuration UI is accessed using the navigation target configUI. So, we overwrite the standard target by defining
it in the ui-repository.xml file, but letting it point to the new page.
<NavigationTarget name="configUI"
targetComposition="Page:configUIWithSidebar[content=configUIContentIncl,sidebar=custSidebarIncl]
"/>
4.2.2 Including the Mini Cart Preview in the Sidebar Using Module Interfacing
The new page and navigation target reference two UI includes. The configUIContentIncl include is just the standard
SAP include containing the main part of the configuration UI where you can change the configuration characteristics.
The custSidebarIncl include is new, so it needs to be declared in the ui-repository.xml file as well.
<UIInclude name="custSidebarIncl"/>
The corresponding file custSidebarIncl.xhtml just contains the single composite component ipc:custSidebar.
<ipc:custSidebar id="cSB"/>
The composite component is new as well, and will include the mini cart preview using a module interface provided by
the salestransaction module. So the custSidebar.xthml file will look like this:
<cc:implementation>
<wcf:moduleInterface id="mIbp" name="com.sap.sales.Checkout"
viewComponent="minibasketpreview" />
</cc:implementation>
Due to the simplicity of the view, there is no need to declare a view handler. The module interface already exists,
since the mini cart preview is already used within the checkout, so finally only the dependency on the module interface
should be added to metadata.xml, if not present yet.
<interfaceDependency dependencyType="hard"
interfaceName="com.sap.sales.Checkout" namespace="sap" />
4.2.3 Adapting the Re-Render IDs
Since we removed the old navigation area from the configuration UI, it is necessary to adapt the list of re-render IDs
that will identify the components to be re-rendered on AJAX requests. The standard list contains IDs that refer to the
old navigation bar. Referring to non-existent IDs will lead to a runtime exception. In addition, you need to add the new
sidebar to the re-render ID list, so you can see price changes in the cart summary when a pricing-relevant
characteristic is changed. The re-render IDs for the configuration UI are defined in the dynamic UI inbound interface,
which is implemented by class DynamicUIInboundImpl. Since this class is instantiated using the generic factory we
can easily exchange it with a customer implementation using the factory-config.xml file.
88 October 2013
Development and Extension Guide – Application-Specific Information
<factoryClass singleton="false"
name="com.sap.wec.app.common.module.ipc.ui.view.interf.DynamicUiInboundInternal"
className="com.customer.wec.app.common.module.ipc.ui.view.impl.CustDynamicUiInboundImpl"
/>
The class CustDynamicUiInboundImpl extends the SAP implementation and looks like the example below.
public class CustDynamicUiInboundImpl extends DynamicUiInboundImpl {
public static final String RERENDER_ID_CUSTSIDEBAR = "fC:pg2ndColumn";
public CustDynamicUiInboundImpl() {
super();
// remove all but first ID
String id = reRenderIds.get(0);
reRenderIds.clear();
reRenderIds.add(id);
reRenderIds.add(RERENDER_ID_CUSTSIDEBAR);
}
}
The re-render ID list is filled in the constructor of the super implementation. The first ID refers to the header, so we
keep it. The other IDs refer to the navigation bar, so we discard them. Instead, we add an ID to re-render the entire
new sidebar.
October 2013 89
Development and Extension Guide – Application-Specific Information
4.3 Removal of “Not Specified” Option on Configuration UI
This example shows how the layout of the configuration UI can be changed when the default option Not Specified for
radio button lists is removed.
The first image shows the configuration UI before, and the second one after, the enhancement.
1. Create a class that inherits from RadioButtonUIElementMapperImpl (for example
CustRadioButtonUIElementMapperImpl).
2. Register the class (for example CustRadioButtonUIElementMapperImpl) in the factory-config.xml file as
described in the general enhancement concepts.
3. Override the updateUIElement method to call updateAllowedValues with parameter includeNilValue set to
false.
package com.customer.wec.app.common.module.ipc.ui.dynamic.ui.impl;
import com.sap.wec.app.common.module.ipc.businessobject.interf.Characteristic;
import com.sap.wec.app.common.module.ipc.ui.dynamic.ui.impl.RadioButtonUIElementMapperImpl;
import com.sap.wec.tc.core.businessobject.BusinessObjectException;
import com.sap.wec.tc.core.ui.model.interf.EntryField;
public class CustRadioButtonUIElementMapperImpl extends RadioButtonUIElementMapperImpl {
@Override
public void updateUIElement(EntryField uiElement, Characteristic cstic, boolean isCheckMode)
throws BusinessObjectException {
super.updateUIElement(uiElement, cstic, isCheckMode);
if (cstic.isDomainConstrained() || cstic.allowsAdditionalValues()) {
updateAllowedValues(uiElement, cstic, false);
}
}
}
90 October 2013
Development and Extension Guide – Application-Specific Information
4.4 Reference Characteristics
You can use reference characteristics to automatically apply certain values from the environment as context
information, or to copy values to the environment, during runtime of product configuration with the configuration
engine. You can use the dependency to then include these values in rules. This extension example describes how to
set reference characteristics out of SAP Web Channel Experience Management. Note that several standard reference
characteristics are already set.
Standard reference characteristics supported in the SAP CRM deployment scenario:
BUT000-PARTNER
BUT000-AG
VBAK-KUNNR
VBPA_AG-KUNNR
VBPA_AG-LAND1
VBPA_RG-KUNNR
VBPA_RG-LAND1
VBAK-VKORG
VBAK-VTWEG
VBAK-SPART
VBAK-ERDAT
VBAP-KWMENG
COMM_PRODUCT-PRODUCT_ID
VBAP-MATNR
Standard reference characteristics supported in the SAP ERP deployment scenario:
VBAK-KUNNR
VBPA_AG-KUNNR
VBPA_AG-LAND1
VBPA_RG-KUNNR
VBPA_RG-LAND1
VBAK-VKORG
VBAK-VTWEG
VBAK-SPART
VBAK-ERDAT
VBAP-KWMENG
VBAP-MATNR
For more information about reference characteristics, see
http://help.sap.com/saphelp_crm70/helpdata/en/47/68c3aedc6e17f9e10000000a42189c/frameset.htm.
October 2013 91
Development and Extension Guide – Application-Specific Information
Proceed as follows:
1. Create customer module extension for module ipc.
92 October 2013
Development and Extension Guide – Application-Specific Information
2. Add newly created custom module to custom Web Channel application (maintain dependency to DPU part).
3. Maintain development component dependencies and public parts for the created custom modules.
o Dependencies:
o Public Parts:
4. Create file businessobject-config.xml.
October 2013 93
Development and Extension Guide – Application-Specific Information
<?xml version="1.0" encoding="UTF-8"?>
<businessObjects xmlns="http://www.sap.com/wec/frw/tc/common/boconfig">
<businessObject name="ReferenceCsticsProvider"
className="com.customer.wec.app.common.module.ipc.businessobject.impl.CustReference
CsticsProviderImpl">
</businessObject>
</businessObjects>
5. Add businessobject-config.xml to metadata.xml.
94 October 2013
Development and Extension Guide – Application-Specific Information
File: metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata" lazyLoad="true"
mainModule="false" moduleID="ipc">
<moduleType>application</moduleType>
<configForModule>ipc</configForModule>
<config-file namespace="customer" part="bo" type="bo-config">businessobject-
config.xml</config-file>
</module>
6. Create custom class for the above mentioned business object and implement your own version of method
setReference.
Example:
package com.customer.wec.app.common.module.ipc.businessobject.impl;
import java.util.Map;
import
com.sap.wec.app.common.module.ipc.businessobject.integration.impl.ReferenceCsticsProviderI
mpl;
import
com.sap.wec.app.common.module.ipc.businessobject.integration.interf.ReferenceCsticsProvide
r;
import com.sap.wec.app.common.module.ipc.businessobject.interf.IPCItemProperties;
import com.sap.wec.tc.core.businessobject.BusinessObjectException;
public class CustReferenceCsticsProviderImpl extends ReferenceCsticsProviderImpl
implements ReferenceCsticsProvider{
@Override
public void setReferenceCstics(IPCItemProperties props) throws BusinessObjectException
{
super.setReferenceCstics(props);
Map<String, String> contextAttribs = props.getContext();
October 2013 95
Development and Extension Guide – Application-Specific Information
contextAttribs.put("VBAK-AUART", "TA");
props.setContext(contextAttribs);
}
}
Note that in case of additional back-end calls or back-end specifics, it is probably better to extend the
respective back-end classes of class ReferenceCsticsProviderImpl and implement your custom version of
method setReferenceCstics there.
96 October 2013
Development and Extension Guide – Application-Specific Information
5 Shopping Cart and Order
5.1 Custom Attributes
You can display new fields on the Web shop UI or change the value of these fields.
Note that the extensibility concept provided by the back end is illustrated using the SAP ERP back end using the
enhancement capabilities of the Lean Order API (LO API). The back-end independent parts are also valid for a Web
shop using the SAP CRM back end.
5.1.1 Enhancing Fields in the Back End
For an extensive description of the extension concept provided by the LO API, see the attachment to SAP Note
1224179. For the following example, the first two subchapters of the Enhancement Options chapter were followed. We
defined an append structure having the fields BSTKD_E and BSTDK_E. This was defined for TDS_HEAD_COMV.
Afterwards, the mapping between the append structure fields and the fields in the business logic were defined in
LORD_MAPPING table.
Note
Extensions using subobjects HDDATAA, HDDATAB, IDATAA, and IDATAB are not supported using the technique we
describe in this example (see chapter Enhanceable Lean Order Objects in the attachment to SAP Note 1224179).
For supporting the reading of the fields mentioned above using the LO API, it is enough for you to enhance
TDS_HEAD_COMV and maintain LORD_MAPPING. In order to support editing and maintainance of the fields, an
append structure must be added to TDS_HEAD_COMC and an implementation should be provided for the
BADI_LORD_DO_PAI in order to trigger the processing of fields after input. For more information, see the following
code:
method IF_BADI_LORD_DO_PAI~ADD_SUPPLY_LIST.
data: ls_supply type tds_field_supply.
if iv_object_id eq 'HEAD'.
if iv_module eq 'VBAK_BEARBEITEN'.
ls_supply-field = 'ZZ_BSTKD_E'.
append ls_supply to ct_supply.
ls_supply-field = 'ZZ_BSTDK_E'.
append ls_supply to ct_supply.
endif.
October 2013 97
Development and Extension Guide – Application-Specific Information
5.1.2 Displaying Custom Fields on the UI
To make additional fields from the back end available to Web shop customers, you must first identify the view where
the new fields are supposed to be shown. It most often helps to add &wec-debug=true to the current URL and to
refresh the page to see the actual page and view structure. For example, see the following screenshot of the order
overview page:
Suppose that we want to add new fields on order header level. We know from the debugging information displayed
that we need to work with view richheader-readonly.xhtml to display new fields on the UI.
Now the SAP delivered view will be copied into the UI part of the extension module. Assuming the extension name
space is customer, it is located in the following path:
..\src\META-INF\resources\customer\salestransactions\components\richheader-readonly.xhtml
98 October 2013
Development and Extension Guide – Application-Specific Information
You need to modify the view by adding the necessary JSF components for display. For example, an extension to the
view might look like the following code:
<wec:comment value="WEC Extension Purchase Order Nr"/>
<wec:outputLabel for="txtPurchOrdNo" id="oLbPurchOrdNo"
value="#{i18n['sapsalestransactions.ui.purchase.number']}"/>
<wec:outputText id="txtPurchOrdNo" styleClass="fw-form-gridcol3"
value="#{cc.vch.salesDocumentHeaderBean.shippingPurchaseOrderNo}"/>
<wec:comment value="WEC Extension Purchase Order Date"/>
<wec:outputLabel for="txtPurchOrdDate" id="oLbPurchOrdDate"
rendered="#{cc.vch.salesDocumentHeaderBean.shippingPurchaseOrderDateAvailable}"
value="#{i18n['sapsalestransactions.ui.purchase.date']}"/>
<wec:outputText id="txtPurchOrdDate"
rendered="#{cc.vch.salesDocumentHeaderBean.shippingPurchaseOrderDateAvailable}"
styleClass="fw-form-gridcol3"
value="#{cc.vch.salesDocumentHeaderBean.shippingPurchaseOrderDate}">
<wec:convertDateShort4/>
</wec:outputText>
The new view needs to be present in the ui-repository of the extension module, as shown in the following code:
<ViewComponent name="richheader-readonly" componentHandlerClassName=
"com.sap.wec.app.esales.module.transaction.ui.viewhandler.SalesDocumentHeaderViewHandlerImpl" />
The ui-repository itself must be registered for extension in the module metadata.xml, as shown in the following code:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata"
lazyLoad="true"
mainModule="false"
moduleID="salestransactions">
<moduleType>application</moduleType>
<configForModule>salestransactions</configForModule>
<config-file namespace="customer" part="ui" type="ui-repository">ui-repository.xml</config-
file>
Metadata.xml resides in the md part of the module while ui-repository.xml resides in the ui part of the module under
the folders with the names formatted as follows: <module namespace>.<module id>.<module part>. These can be
found in the module.properties. In order for the system to display the fields in the view, the corresponding bean must
know about them. Therefore, new getter methods will be added to the bean, which will extend the bean
implementation provided by SAP.
Recommendation
Use typed attributes for the extensions on the level of the BO beans in the UI layer because this leads to views that
are easier to understand. We sub-class the respective UI bean and implement typed attributes for the new attributes.
October 2013 99
Development and Extension Guide – Application-Specific Information
The following shows a code snippet of the extended BO bean, which should support the new purchasing attributes:
public class CustHeaderBeanImpl extends SalesDocumentHeaderBeanImpl {
private static final String
EXT_FIELD_SHIPPING_PURCHASE_ORDER_NUMBER = "ZZ_BSTKD_E";
public String getShippingPurchaseOrderNo() {
String shippingPurchaseOrderNo = "";
if (getBO().getExtensionData(
EXT_FIELD_SHIPPING_PURCHASE_ORDER_NUMBER) != null) {
shippingPurchaseOrderNo = (String) getBO().getExtensionData(
EXT_FIELD_SHIPPING_PURCHASE_ORDER_NUMBER);
}
return shippingPurchaseOrderNo;
}
public Date getShippingPurchaseOrderDate() {
Object extensionObject = getBO().getExtensionData(
EXT_FIELD_SHIPPING_PURCHASE_DATE);
if (extensionObject != null){
String dateAsString = (String) extensionObject;
if (!dateAsString.isEmpty() && (!dateAsString.equals("00000000"))){
Date shippingPurchaseOrderDate = ConversionHelper.convertDateStringToDate(dateAsString);
return shippingPurchaseOrderDate;
}
}
return new Date(System.currentTimeMillis());
}
Note
We convert the date string into a Java date in the UI layer, which does not match the standard pattern, as standard
date or currency amount attributes are converted in the back-end layer and are then available as typed attributes in bo
and ui. But as LO-API provides the extension attributes in character format and WCEM puts all extension attributes
directly into the bo extensions, this approach is appropriate for extension attributes.
By declaring the implementation class in the factory-config.xml, you ensure that the new bean will be in place and
used at runtime instead of the default implementation provided. Factory-config.xml will be linked in the metadata.xml
in the same way as the ui-repository, as shown in the following code:
<factory xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:wec="com.sap.wec.core.config">
<factoryClass name=
"com.sap.wec.app.esales.module.transaction.ui.beans.interf.SalesDocumentHeaderBean"
singleton="false"
className=
"com.customer.wec.app.esales.module.salestransactions.ui.beans.impl.CustHeaderBeanImpl" />
</factory>
100 October 2013
Development and Extension Guide – Application-Specific Information
5.1.3 Adding Resource Keys for New Labels on the Web Shop UI
The resource keys are used as shown below and defined in the wcf_resources.xlf file in the ui part of the module (the
salestransactions module, in this example). The file must be created under the folder with the name <module
namespace>.<module name>.ui, as shown in the figure below:
The prefix of the resource key must be the same as defined in the metadata.xml file of the salestransactions module
as shown in the following code:
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata"
lazyLoad="true"
mainModule="false"
moduleID="salestransactions"
resourceBundlePrefix="sapsalestransactions"
standalone="true">
<wec:comment value="WEC Extension Purchase Order Nr" />
<wec:outputLabel id="oLbPurchOrdNo"
value="#{i18n\['sapsalestransactions.ui.purchase.number'\]}"
for="txtPurchOrdNo" />
5.1.4 Reading Custom Fields from the Back End
In order to fill the fields that are supposed to be shown with values, you must extend the back end.
You need to let LO-API know that it should provide us the additional attributes. In this example, we want to display the
purchase order number BSTKD_E and the purchase order date BSTDK_E, in addition. To do this, a new
implementation of ERPLO_APICustomerExits is required, which should subclass
com.sap.wec.app.esales.module.transaction.salesdocument.backend.impl.erp.strategy.
October 2013 101
Development and Extension Guide – Application-Specific Information
The class implementation could look like the following code:
public class CustomerExits extends ERPLO_APICustomerExitsImpl {
public Map<LrdFieldExtension.FieldType, LrdFieldExtension> customerExitGetExtensionFields() {
if (extensionFields != null) {
return extensionFields;
}
else {
extensionFields = new HashMap<LrdFieldExtension.FieldType, LrdFieldExtension>();
}
// Register the new attributes for reading
// Both attributes are on header level
LrdFieldExtension headerComVExtension = new LrdFieldExtension(
LrdFieldExtension.FieldType.HeadComV);
headerComVExtension.addField("ZZ_BSTKD_E");
headerComVExtension.addField("ZZ_BSTDK_E");
extensionFields.put(LrdFieldExtension.FieldType.HeadComV,
headerComVExtension);
return extensionFields;
}
Additionally, the respective entries must be made in the factory-config.xml file to register our CustomerExits class.
This class and the factory-config.xml file are placed in the bo part of the module, as shown in the following code:
<factoryClass name="com.sap.wec.app.esales.module.transaction.
salesdocument.backend.interf.erp.strategy.ERPLO_APICustomerExits"
singleton="false"
className="com.customer.wec.app.esales.module.salestransactions.
backend.impl.erp.strategy.CustomerExits"
/>
The application automatically puts these extensions into the extension map of the sales document header or the item.
Therefore, it is not required to handle these extensions in the business object layer. Of course, there might be cases
where such extensions could also influence the business objects (for example, if other attributes depend on them). In
these cases, the business objects also need to be changed.
102 October 2013
Development and Extension Guide – Application-Specific Information
5.1.5 Writing Custom Fields to the Back End
You can enhance the checkout process with an additional step. The following figure shows the checkout step for
purchase information:
To set the values of the fields for purchase order number and purchase date, you must implement the setter methods
in the view handler of the checkout step for purchase information, as shown in the following code:
public class PurchaseDataExpandedViewHandlerImpl
extends StepElementBaseViewHandlerImpl {
public void setShippingPurchaseOrderNo(String shippingPurchaseOrderNo) {
CustHeaderBeanImpl header =(CustHeaderBeanImpl)getSalesDocumentHeaderBean();
header.setShippingPurchaseOrderNo(shippingPurchaseOrderNo);
}
public void setShippingPurchaseOrderDate(Date shippingPurchaseOrderDate) {
CustHeaderBeanImpl header =(CustHeaderBeanImpl)getSalesDocumentHeaderBean();
header.setShippingPurchaseOrderDate(shippingPurchaseOrderDate);
}
...
October 2013 103
Development and Extension Guide – Application-Specific Information
The setters called by CustHeaderBeanImpl set the values introduced on the Web shop UI to the extension map of the
business object, as shown in the following code:
public class CustHeaderBeanImpl extends SalesDocumentHeaderBeanImpl {
public void setShippingPurchaseOrderNo(String purchaseOrderNo) {
getBO().addExtensionData(EXT_FIELD_SHIPPING_PURCHASE_ORDER_NUMBER, purchaseOrderNo);
}
public void setShippingPurchaseOrderDate(Date purchaseOrderDate) {
String dateString = ConversionHelper.convertDateToDateString(purchaseOrderDate);
getBO().addExtensionData(EXT_FIELD_SHIPPING_PURCHASE_DATE, dateString);
}
The Lean Order API knows about the fields which are marked for back-end enhancement. For more information, see
Reading Custom Fields from the Back End.
Note
Due to the way the Lean Order API handles date attributes, date conversion does not correspond to the pattern used
for handling dates in SAP Web Channel Experience Management.
5.1.6 Extending the Checkout UI
Checkout Implementation
You must define the look of the new step in checkout. That is, which view is shown in the collapsed mode, which view
is shown in expanded mode, or if the data is validated (that is, the sales document is updated) when Web shop
customers choose the Continue pushbutton. This is done in the checkoutProcessMetadata.xml file. This definition is
the basis for creating the checkoutProcessConfig.xml, which you upload using Web Channel Builder.
<CheckoutMetadataConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="checkoutProcessMetadataSchema.xsd">
<!-- StepElements repository -->
<StepElementConfiguration>
<StepElement ID="SE_CUSTPURCHASEDATA"
collapsedViewName="/checkout/includes/purchaseCollapsedIncl.xhtml"
expandedViewName="/checkout/includes/purchaseExpandedIncl.xhtml"
orderConfirmationViewName=""
UITitle="checkout.ui.stepelement.custelement.uititle"
validatorClass=
"com.customer.wec.app.ecom.module.checkout.ui.stepelements.validator.PurchaseDataValidator" />
</StepElementConfiguration>
<ProcessTypes>
<ProcessType ID="Sales">
...
<!-- Purchase Data -->
<allowedStepElement ID="SE_CUSTPURCHASEDATA" />
...
</allowedStepGroup>
...
104 October 2013
Development and Extension Guide – Application-Specific Information
The CheckoutProcessMetadata.xml file must be linked in the metadata.xml file of the extended Checkout Process
Configuration module, as shown in the following code:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata"
lazyLoad="true"
mainModule="false"
moduleID="com.sap.checkout.processconfig">
<moduleType>application</moduleType>
<configForModule>com.sap.checkout.processconfig</configForModule>
<config-file namespace="customer"
part="md"
type="checkoutconfig">
checkoutProcessMetadata.xml
</config-file>
...
After defining these two configuration files in the md part of the checkout.processconfig module, you can define the
views in the checkout module.
You need to define the two views and includes and put them in the resources folder of the checkout module. For
example, the folder structure might look like the following figure:
For these two views the corresponding view handlers must also be defined in the ui part of the customer checkout
module. The view handlers must be defined in the ui-repository.xml file, as shown in the following code:
...
<ViewComponent name="purchaseCollapsed"
componentHandlerClassName="com.customer..." />
<ViewComponent name="purchaseExpanded"
componentHandlerClassName="com.customer..." />
...
October 2013 105
Development and Extension Guide – Application-Specific Information
In order to make sure that the sales document is updated when Web shop customers choose the Continue pushbutton
(meaning the values entered are sent to the back end), a validator must be implemented as shown in the following
code:
public class PurchaseDataValidator extends BaseValidator {
public PurchaseDataValidator() {
super();
}
@Override
public boolean isUpdateNeeded() {
return true;
Checkout Customizing
You need to upload a changed process configuration in the checkout.processconfig module of Web Channel Builder.
The new step might look like the following code:
<Step Description="" ID="S_CUST" STEPGROUP_ID="SG_DETAILS"
UITitle="checkout.ui.step.custstep.uititle">
<StepElementRef Description="" ID="SE_CUSTPURCHASEDATA"
UITitle="checkout.ui.stepelement.custelement.uititle" showOnOrderConfirm="false" />
</Step>
Note that the ID of the step element must match the previously defined metadata.
106 October 2013
Development and Extension Guide – Application-Specific Information
5.2 Additional Fields Read from ERP SD via LO-API
This example shows how to read additional information from LO-API. Assume that for product substitution, you also
want to display the substitution reason along with the information message. This information is not considered in
WCEM standard.
5.2.1 Extending Module and Registering Extensions
You need to extend the salestransactions module in your namespace. Since this extension affects the back-end layer,
the bo part is necessary. The extension is done in a custom extension of
com.sap.wec.app.esales.module.transaction.salesdocument.backend.impl.erp.strategy.GetAllStrategyERP605, which
is the class that handles the sales document read process.
To instantiate a new strategy implementation, a new StragegyFactory is needed, which looks like this:
public class CustStrategyFactory extends StrategyFactoryERP {
@Override
public GetAllStrategy createGetAllStrategy() {
return new CustGetAllStrategyERP();
}
}
October 2013 107
Development and Extension Guide – Application-Specific Information
Register this factory in factory-config.xml as follows:
...
<factoryClass name="STStrategyFactoryERP" singleton="false"
className="com.customer.wec.app.esales.module.transaction.salesdocument.
backend.impl.erp.strategy.CustStrategyFactory" />
...
And state that factory-config.xml is extended. Excerpt from metadata.xml:
...
<config-file namespace="customer" part="bo" type="factory-config">factory-config.xml</config-
file>
...
5.2.2 Reading Substitution Reason and Attaching it to New Message
You need to perform two steps: Reading the substitution reason from structure TDS_RFC_ITEM_COMR, and later on
enriching the information message that explains the substitution. The resource key for the new message
sapsalestransactions.erp.ui.rfc.newmsg needs to be maintained outside CustGelAllStrategyERP. The coding of
CustGetAllStrategyERP looks like this:
@Override
protected void mapItemComR(....) {
super.mapItemComR(salesDoc, ttItemComR, shop, subTotalItemFreight,
setIpcPriceAttributes, item, itemsPriceAttribMap,
itemVariantMap, boBaseR3Lrd);
// now check for the substitution reason and store it for later processing
String substitutionReason = ttItemComR.getString("SUGRD_T");
item.addExtensionData(SUBST_REASON, substitutionReason);
}
@Override
public BackendCallResult execute(....) throws BackendException {
BackendCallResult result = super.execute(backendState, salesDocument,
itemBuffer, readParams, cn, cardType, creditCardStrategy);
exchangeMessage(salesDocument);
return result;
}
private void exchangeMessage(SalesDocument salesDocument) {
String resourceKey = "sapsalestransactions.erp.ui.rfc.messages.label.V2167";
//check if the document carries the warning message for substitution
MessageList messageList = salesDocument.getOwnMessageList();
108 October 2013
Development and Extension Guide – Application-Specific Information
MessageList newMessages = new MessageList();
for (Message message: messageList){
if (message.getResourceKey().equals(resourceKey)){
String productId = message.getResourceArgs()[0];
String newProduct = message.getResourceArgs()[1];
String substReason = getReason(newProduct, salesDocument);
String[] args = new String[]{productId,newProduct,substReason};
Message newMessage = new Message(Message.INFO, "sapsalestransactions.erp.ui.rfc.newmsg",
args, null);
newMessages.add(newMessage);
}
}
messageList.remove(resourceKey);
messageList.add(newMessages);
}
private String getReason(String newProduct, SalesDocument salesDocument) {
for (Item item: salesDocument.getItemList()){
if (item.getProductId().equals(newProduct)){
return (String) item.getExtensionData(SUBST_REASON);
}
}
return null;
}
October 2013 109
Development and Extension Guide – Application-Specific Information
5.3 Shopping Cart - User Interface
You can enhance the shopping cart UI from the following perspectives:
SAP CRM (based on applying the Application Enhancement Tool)
Java (based on the SAP module enhancement concept)
5.3.1 Adding a New Field Using the AET
In SAP CRM, you can enhance CRM sales orders by adding a new field (for example, a CRM Order Extension field)
to the General Data area of the sales order application with the Application Enhancement Tool (AET), as follows:
1. To enable the configuration mode, choose Personalize Settings and enable the configuration mode as shown
in the following figures:
2. Switch to configuration mode by choosing the Show Configuration Mode pushbutton, as highlighted in the
following figure:
110 October 2013
Development and Extension Guide – Application-Specific Information
3. To add the CRM Order Extension field to the General Data area of the sales order application, select the
General Data area as shown in the following figure:
After you have selected the General Data area, the system displays the UI Configuration Tool.
October 2013 111
Development and Extension Guide – Application-Specific Information
4. To start the AET, choose the Create Field pushbutton as highlighted in the figure below:
112 October 2013
Development and Extension Guide – Application-Specific Information
5. In the AET, select the BO part that you want to enhance (in this example, the ORDERADMIN_H part), as
shown in the following figure:
October 2013 113
Development and Extension Guide – Application-Specific Information
6. On the Field Details – Webpage Dialog screen, enter field details (for example, field label, field type, and
length), as shown in the following figure:
7. To go back to the configuration overview, choose the Back pushbutton.
8. To trigger the generation process, choose the Save and Generate pushbutton.
The system creates the new field, enhances the relevant external interfaces (for example, if you select the BW
Reporting checkbox, the system modifies the data source and the BI extractor), adds the structural changes
and the enhancement metadata to a transport request, and starts the activation process.
114 October 2013
Development and Extension Guide – Application-Specific Information
9. To show the available fields in the view, choose the Show Available Fields pushbutton highlighted in the
following figure:
October 2013 115
Development and Extension Guide – Application-Specific Information
10. To add the CRM Order Extension field to the configuration view, select the field and choose the Add Field
pushbutton highlighted in the following figure:
116 October 2013
Development and Extension Guide – Application-Specific Information
11. To go back to the sales order application, choose the Save and Close pushbutton.
The following figure shows the new CRM Order Extension field on the UI:
5.3.2 Adding A New Field Using Java
You can add a new field (in this example, the CRM Customer Extension Field) to the to the Web shop UI, as shown in
the following figure:
The content of this field must be passed to the back end by a generic BO feature. In this example, the header view of
the shopping cart (called leanbasketheader.xhtml) is enhanced by one additional field as displayed in the figure
above.
October 2013 117
Development and Extension Guide – Application-Specific Information
Create customer DCs in the customer namespace according to the general SAP Web Channel Experience
Management enhancement concept. The following customer specific DCs need to be created:
MD
BO
UI
You need these DCs in the customer namespace as shown in the following figure:
Note that all DCs are included in the corresponding deployment unit.
UI Development Component
The ui-repository.xml file must include the corresponding enhanced view component (called leanbasketheader) as
shown in the following code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<UIRepository xmlns="http://www.sap.com/wec/wcf/viewcomposition/ui-repository"
xmlns:wec="com.sap.wec.core.config" module="salestransactions">
<ViewComponent name="leanbasketheader"
componentHandlerClassName="com.sap.wec.app.esales.module.transaction.ui.viewhandler.LeanBasketHe
aderViewHandlerImpl" />
</UIRepository>
Note
In this example the standard bean is used. If an enhancement of the bean is applied as well, then the corresponding
bean must also be implemented in the extension DC part.
118 October 2013
Development and Extension Guide – Application-Specific Information
A customer-specific view component must be created to include the customer-specific fields. In this example, it is
called the same as the original component (that is, leanbasketheader.xhtml) and is shown in the structure in the
following figure:
The following figure shows how the customer-specific field is implemented in the customer-specific view component
leanbasketheader.xhtml. You can use the original view as a template.
The new field ZZORDERADM_H6801 (as an enhancement of structure ORDERADM_H) is added to the original view
leanbasketheader.xhtml, as highlighted in the figure below:
October 2013 119
Development and Extension Guide – Application-Specific Information
MD Development Component
The metadata.xml file is part of the MD DC, as shown in the following figure:
The metadata.xml file needs to include the entries shown in the following figure:
120 October 2013
Development and Extension Guide – Application-Specific Information
BO Development Component
In the customer-specific BO DC, you need to create an extension mapper class called ExtMapperImpl that extends
class ExtensionMapperImpl (to declare the new fields), as shown in the following figure:
In this example, field ZZORDERADM_H6801 in structure ORDERADM_H is added in the following code (for more
information, see Adding a New Field Using the AET):
package com.customer.wec.app.esales.module.salestransactions.backend.impl.crm.strategy;
import com.sap.conn.jco.JCoFunction;
import com.sap.wec.app.esales.module.transaction.businessobject.interf.SalesDocument;
import
com.sap.wec.app.esales.module.transaction.salesdocument.backend.impl.crm.mapper.ExtensionMapperI
mpl;
public class ExtMapperImpl extends ExtensionMapperImpl
public void addRequestedExtensionTables(SalesDocument salesDoc, JCoFunction func)
super.addRequestedExtensionTables(salesDoc, func, null);
addRequestedExtension(func, true, "ORDERADM_H", "ZZORDERADM_H6801", null);
Additionally, you need to maintain the created mapper class in the factory-config.xml file, which is shown in the
following figure:
You must use code, such as the following, to announce that this new class or extension exists and needs to be
considered by the system:
<factoryClass
name="com.sap.wec.app.esales.module.transaction.salesdocument.backend.interf.crm.mapper.Extensio
nMapper" singleton="false"
className="com.customer.wec.app.esales.module.salestransactions.backend.impl.crm.strategy.ExtMap
perImpl" />
October 2013 121
Development and Extension Guide – Application-Specific Information
5.4 Shopping Cart - J2EE Data Persistence
This extension example shows how you can extend the standard shopping cart and persist the additional data in the
J2EE.
In this example, we add an additional view to the shopping cart, where you can maintain additional URLs as links.
These links will be persisted as shopping cart extensions in the J2EE database. They will be shown in the same view
and it will be possible to navigate to the related URLs.
5.4.1 Creating Class Representing the Object to be Persisted (Serializable)
Create a class that represents the object that needs to be persisted. In this example, we persist a URL and a
description for the URL. The class needs to implement the interface Serializable, so that it can be serialized to the
J2EE database, as shown in the following code:
package com.customer.wec.app.esales.module.salestransactions.businessobject.impl;
import com.customer.wec.app.esales.module.salestransactions.businessobject.interf.CustLink;
public class CustLinkImpl implements CustLink { // CustLink inherits from Serializable
private static final long serialVersionUID = 6448561614476397841L;
protected String description;
protected String url;
@Override
public String getDescription() {
return description;
}
@Override
public void setDescription(String description) {
this.description = description;
}
@Override
public String getUrl() {
return url;
}
@Override
public void setUrl(String url) {
this.url = url;
}
}
122 October 2013
Development and Extension Guide – Application-Specific Information
5.4.2 Creating View Component
Create a view component in the customer namespace that contains all required functionality (input fields, labels,
buttons, and so on). In this example, this view component is named extcartlinks.xhtml and is shown in the following
figure:
The view component retrieves SalesDocumentBean as an attribute to get a reference to the SalesDocument business
object. This is required to access the extension maps and is shown in the following code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:sales="http://java.sun.com/jsf/composite/sap/salestransactions/components"
xmlns:wcf="http://java.sun.com/jsf/composite/wec"
xmlns:wec="http://java.sap.com/wec/wcf/html">
<head>
<title>My Links</title>
</head>
<body>
<cc:interface componentType="sap.wec.ViewComponent">
<cc:attribute name="salesDocumentBean"
type="com.sap.wec.app.esales.module.transaction.ui.beans.interf.SalesDocumentBean"
/>
</cc:interface>
<cc:implementation>
<wec:panelBox collapsible="false" id="pBform" styleType="form">
October 2013 123
Development and Extension Guide – Application-Specific Information
<wec:panelGrid
columnClasses="fw-formlayout-2col1, fw-formlayout-2col2" columns="2"
id="pGdFrmLnks" styleClass="fw-form-layout">
<wec:panelBox collapsible="false" id="pBLFrmLnks" styleType="partform">
<wec:comment value="title for left part form" />
<wec:panelGroup id="pGFrmTitLLnks" layout="block"
styleClass="fw-form-title">
<wec:title id="titFrmTitLLnks" level="5">
<wec:outputText id="txtFrmTitLLnks"
value="#{i18n['sapsalestransactions.ui.extensJCart.title']}" />
</wec:title>
</wec:panelGroup>
<wec:panelGrid columnClasses="fw-form-label,fw-form-field"
columns="2" id="pGdL" styleClass="fw-form-elements">
<wec:outputLabel for="itNewLinkUrl"
value="#{i18n['sapsalestransactions.ui.extensJCart.urlLabel']}"/>
<wec:inputText id="itNewLinkUrl"
value="#{cc.vch.newUrl}"/>
</wec:panelGrid>
</wec:panelBox>
<wec:panelBox collapsible="false" id="pBRFrmLnks" styleType="partform">
<wec:comment value="title for left part form" />
<wec:panelGroup id="pGFrmTitRLnks" layout="block"
styleClass="fw-form-title">
<wec:title id="titFrmTitRLnks" level="5">
<wec:outputText id="txtFrmTitRLnks" value="" />
</wec:title>
</wec:panelGroup>
<wec:panelGrid columnClasses="fw-form-label,fw-form-field, fw-form-
field"
columns="3" id="pGdRLnks" styleClass="fw-form-elements">
<wec:outputLabel for="itNewLinkDesc"
value="#{i18n['sapsalestransactions.ui.extensJCart.descLabel']}"/>
<wec:inputText id="itNewLinkDesc" value="#{cc.vch.newDesc}"/>
<wec:commandButton id="cBtSaveNewLink"
value="#{i18n['sapsalestransactions.ui.extensJCart.saveButton']}" action="#{cc.vch.saveLink}"/>
</wec:panelGrid>
</wec:panelBox>
</wec:panelGrid>
<wec:panelGrid
124 October 2013
Development and Extension Guide – Application-Specific Information
columnClasses="fw-formlayout-1col" columns="2"
id="pGdFrmLnkTab" styleClass="fw-form-layout">
<wec:panelBox collapsible="false" id="pBRFrmLnkTab"
styleType="partform">
<wec:dataTable value="#{cc.vch.linkList}" var="link">
<wec:column id="colLinks">
<f:facet name="header">
<wec:outputText id="headerIdLink"
value="#{i18n['sapsalestransactions.ui.extensJCart.colMyLinks']}" />
</f:facet>
<wec:outputLink value="#{link.url}">
<wec:outputText value="#{link.description}"
/>
</wec:outputLink>
</wec:column>
</wec:dataTable>
</wec:panelBox>
</wec:panelGrid>
</wec:panelBox>
</cc:implementation>
</body>
</html>
5.4.3 Creating View Component Handler
1. Create a view component handler class, which is the controller of the view. In this example, the class is called
CustCartLinksViewHandlerImpl and extends SalesDocumentBeanViewHandlerImpl. The
SalesDocumentBeanViewHandlerImpl class already provides getter, setter, and intialization methods for
SalesDocumentBean. This ensures a convenient handling of SalesDocumentBean in the view component and
the view component handler.
The getLinkList method retrieves the extension map from the business object and puts our example extension to the map, as shown in
the following code:
package com.customer.wec.app.esales.module.transaction.ui.viewhandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
October 2013 125
Development and Extension Guide – Application-Specific Information
import com.customer.wec.app.esales.module.salestransactions.businessobject.impl.CustLinkImpl;
import com.customer.wec.app.esales.module.salestransactions.businessobject.interf.CustLink;
import com.sap.wec.app.esales.module.transaction.ui.viewhandler.SalesDocumentBeanViewHandlerImpl;
import com.sap.wec.tc.core.businessobject.BusinessObjectException;
public class CustCartLinksViewHandlerImpl extends SalesDocumentBeanViewHandlerImpl {
private static final String EXT_CUSTOMER_LINK_LIST = "ZZ_CustomerLinkList";
protected String newUrl;
protected String newDesc;
@SuppressWarnings("unchecked")
public List<CustLink> getLinkList() {
List<CustLink> linkList = (List<CustLink>) getSalesDocumentBean().getBO()
.getHeader()
.getExtensionData(
EXT_CUSTOMER_LINK_LIST);
if (null == linkList) {
linkList = new ArrayList<CustLink>();
Map<Object, Object> extensionMap = getSalesDocumentBean().getBO()
.getHeader()
.getExtensionMap();
extensionMap.put(EXT_CUSTOMER_LINK_LIST, linkList);
}
return linkList;
}
public String getNewUrl() {
return newUrl;
}
public void setNewUrl(String newUrl) {
this.newUrl = newUrl;
}
public String getNewDesc() {
return newDesc;
}
public void setNewDesc(String newDesc) {
this.newDesc = newDesc;
}
public void saveLink() throws BusinessObjectException {
CustLink link = new CustLinkImpl();
link.setDescription(newDesc);
link.setUrl(newUrl);
getLinkList().add(link);
triggerUpdate();
setNewUrl("");
setNewDesc("");
}
}
2. The extension is not registered in the back end. Therefore, you must remove the extension from the extension
map before transferring it to the back end. For example, you could enhance the
126 October 2013
Development and Extension Guide – Application-Specific Information
SalesDocumentBeanViewHandlerImpl class and remove the extension in the checkout method, as shown in
the following code:
package com.sap.wec.app.esales.module.transaction.ui.viewhandler;
import com.customer.wec.app.esales.module.transaction.ui.viewhandler.CustCartLinksViewHandlerImpl;
public class CustSalesDocumentBeanViewHandlerImpl extends SalesDocumentBeanViewHandlerImpl {
/**
* Overwrites the super implementation.<br>
* ToDo: Describe the difference to super implementation.<br>
*
* @return
* @see
com.sap.wec.app.esales.module.transaction.ui.viewhandler.SalesDocumentBeanViewHandlerImpl#checkout()
*/
@Override
public String checkout() {
getSalesDocumentBean().getBO().getHeader().getExtensionMap().remove(
CustCartLinksViewHandlerImpl.EXT_CUSTOMER_LINK_LIST);
return super.checkout();
}
}
October 2013 127
Development and Extension Guide – Application-Specific Information
5.4.4 Registering View Component Handler
The newly created view component handler and the view component need to be registered in the ui-repository.xml file,
which is shown in the following figure:
The following code shows how you can register the view component handler and the view component:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<UIRepository xmlns="http://www.sap.com/wec/wcf/viewcomposition/ui-repository"
xmlns:wec="com.sap.wec.core.config" module="salestransactions">
....
<ViewComponent name="extcartlinks"
componentHandlerClassName="com.customer.wec.app.esales.module.transaction.ui.viewhandler.CustCar
tLinksViewHandlerImpl"/>
....
</UIRepository>
128 October 2013
Development and Extension Guide – Application-Specific Information
5.4.5 Overwriting Surrounding Component and Including New Component
Finally, include the surrounding component, as follows:
Identify the surrounding view (in this example leanbasket.xhtml)
Copy the surrounding view and paste into the customer namespace to overwrite the deliverd component
The following figure shows the leanbasket.xhtml view in the structure:
October 2013 129
Development and Extension Guide – Application-Specific Information
Enhance the pasted component (in this example, by including a new UI feature), as shown in the following code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:sales="http://java.sun.com/jsf/composite/sap/salestransactions/components"
xmlns:wcf="http://java.sun.com/jsf/composite/wec"
xmlns:wec="http://java.sap.com/wec/wcf/html">
<cc:interface componentType="sap.wec.ViewComponent">
</cc:interface>
<cc:implementation>
<c:if test="#{cc.vch.basketAuthority}">
<wec:form id="fB">
....
<sales:extcartlinks id="cCH"
rendered="#{cc.vch.salesDocumentBean.visibility['ext.showJavaCartExt']}"
salesDocumentBean="#{cc.vch.salesDocumentBean}" />
....
</wec:form>
</c:if>
</cc:implementation>
</html>
130 October 2013
Development and Extension Guide – Application-Specific Information
5.5 IPC Pricing
If your pricing procedure contains attributes which are not supported in the standard system (see the information
about standard attributes for IPC pricing in the back ends), you can provide those attributes by influencing the creation
of IPC items on the Java side. For example, consider the situation where the product catalog displays list prices (that
is, no IPC pricing is done in the product catalog) and you want the Java Cart shopping cart to display dynamic prices
(that is, perform IPC pricing).
5.5.1 Standard Attributes for IPC Pricing (SAP CRM)
This example assumes that the product catalog shows list prices. If the product catalog uses IPC pricing, the product-
related attributes are read from MDM. The following figure shows the IPC attributes that are supported in the standard
version of the Java Cart shopping cart:
Source Attribute
BP TAX_DEPART_CTY
BP TAX_DEPART_REG
BP TAX_DEST_REG
BP TAX_DEST_CTY
BP TAX_DEST_CTY_ISO
BP TAX_DEPT_TYPE_01
BP TAX_DEPT_GRP_01
BP TAX_GROUP_BP_01
BP TAX_DEP_CTY_ISO
BP TAX_TYPE_BP_01
BP TAXJURCODE
BP TAXJURCODE_FROM
BP TTE_PARTNER_ID
BP SOLD_TO_PARTY
BP KUNNR
BP VBPA_AG-KUNNR
BP VBPA_RG-KUNNR
BP VBPA_WE-KUNNR
BP VBPA_RE-KUNNR
BP SHIP_COND
BP KDGRP
BP DIS_CHANNEL
BP INCOTERMS1
BP VBAK-VKORG
BP VBAK-KUNNR
BP PMNTTRMS
Item TAX_GROUP_P
October 2013 131
Development and Extension Guide – Application-Specific Information
Item TAX_TYPE_01
Item PRC_GROUP2
Item PRC_GROUP1
Item PRODH1
Item PRODH2
Item PRODH3
5.5.2 Standard Attributes for IPC Pricing (SAP ERP)
In case the product catalog in the Java Cart scenario uses IPC pricing, the product-related attributes are read from
MDM.
The following table shows the supported attributes in case Java cart uses dynamic pricing whereas in the catalog, list
prices are used. In addition, the supported attributes for the back-end cart are listed.
Note
When using the back-end cart, the prices in the cart and checkout are retrieved from SD. Only the prices for
configurable products within the configuration UI are determined using the IPC, so it is only for these prices that the
table shown below needs to be considered.
Attribute Java Cart JCart Source BE Cart
LAND1 yes BP no
INCO1 yes BP yes
INCO2 no n.a. yes
KURST yes BP yes
KUNNR yes BP yes
KDGRP yes BP yes
STCEG yes BP no
PLTYP yes BP yes
KONDA yes BP yes
AWAHR yes BP no
ZTERM yes BP yes
TAXK1-9 yes BP no
VKORG yes BP yes
VTWEG yes BP yes
VTWEG yes BP yes
SPART yes BP yes
VSBED no n.a. yes
KONDM yes Item no
PMATN yes Item yes
PROVG yes Item no
132 October 2013
Development and Extension Guide – Application-Specific Information
MVGR1-5 yes Item yes
TAXM1-9 yes Item no
SKTOF yes Item no
BONUS yes Item no
PRODH yes Item yes
5.5.3 Extension Example
Extension Implementation
The Java Cart shopping cart, whose logic is mainly implemented in class SalesDocumentDB, delegates the creation
of IPC documents and items to a service class that communicates to IPC. If the Web shop runs against the SAP CRM
back end, then the class is ServiceBasketIPCCRM. For the SAP ERP back end, the class is ServiceBasketIPCERP.
The reason for having a separate class is mainly that the class SalesDocumentDB does not have a connection to the
SAP CRM back end or the SAP ERP back end. Therefore, this service class is introduced, which can connect to the
ABAP back end (maintained in the backendobjectconfig.xml file). Note that this class does not correspond to any
business object. If a custom attribute should be maintained, this class must be extended, and a customer exit
methodcustomerExitCreateIPCItems needs to be implemented, such as the following code (the example extends the
class ServiceBasketIPCCRM):
public class CustServiceBasketIPCCRM extends ServiceBasketIPCCRM {
@Override
public void customerExitCreateIPCItems(IPCDocument ipcDocument, IPCItemProperties[]
itemProperties){
for (int i = 0; i<itemProperties.length;i++){
Map<String, String> itemAttributes = itemProperties[i].getItemAttributes();
itemAttributes.put("TG_BP_GUID", "ABCDEF");
itemProperties[i].setItemAttributes(itemAttributes);
}
}
}
It is also possible to do calls to SAP CRM or SAP ERP, if required. The connection can be obtained with
getDefaultJCoConnection(). If the creation of the entire IPC document shall be influenced, you can use the following
method:
public void customerExitCreateIPCDocument(SalesDocument salesDoc,
IPCDocumentProperties docProperties,
HashMap<String, String> headerPriceAttributes,
HashMap<String, String> headerIPCProps,
boolean doPricing)
Extension Registration
As this example is concerned with the shopping cart, we need to create a new version of the salestransactions module
in a new namespace. Suppose that the salestransactions module has been extended using the WCEM workbench.
The module properties for the bo part could look like the following code:
sap.com.moduleId=salestransactions
sap.com.moduleNamespace=customer
sap.com.extendsNamespace=sap
sap.com.modulePart=bo
October 2013 133
Development and Extension Guide – Application-Specific Information
Next, we need to define the configuration file backendobject-config in the customer namespace, as the new service
class is defined here. The respective excerpt from the metadata.xml file in the md part of the module looks as follows:
…
<config-file namespace="customer" part="bo" type="backend-objects">backendobject-config.xml
</configfile>
…
Finally, we need to provide the new version of the backendobject-config.xml file, as shown in the following code:
<?xml version="1.0" encoding="UTF-8"?>
<backend xmlns="http://www.sap.com/wec/frw/tc/common/backendconfig"
xmlns:wec="com.sap.wec.core.config" xmlns:xi="http://www.w3.org/2001/XInclude">
<businessObjects>
<wec:ifValue variable="${backend}" value="crmdefault">
<businessObject name="ServiceBasketIPC"
className=
"com.customer.wec.app.esales.module.transaction.backend.basketdb.CustServiceBasketIPCCRM"/>
</wec:ifValue>
</businessObjects>
</backend>
Note that only the delta to the standard version is necessary. This file needs to be placed in the
<namespace>.salestransactions.bo folder.
Extension Activation
After the extension code has been deployed, you need to activate it in Web Channel Builder. Create a new
configuration and change the default namespace for the salestransactions module to customer. The following figure
shows that the salestransactions module has been changed to the customer default namespace:
In the salestransactions module of Web Channel Builder, make sure that you choose the extended UI for the shopping
cart UI and enable price analysis just for the development phase.
134 October 2013
Development and Extension Guide – Application-Specific Information
Note
In the standard UI, the links for viewing the price analysis are not available.
October 2013 135
Development and Extension Guide – Application-Specific Information
5.6 Order Search (SAP ERP)
You can add or remove search fields and search result columns for orders in the SAP ERP back end.
5.6.1 New Search Criteria
No view must be adapted to make additional search criteria available on the Web shop UI. You only need to change
the generic search configuration file where the search criteria and the structure of the search result list are defined.
The following figure shows the search in the standard system:
The following figure shows the extended search criteria and includes an entry for Purchase order number:
The file containing the generic search description is defined in the bo part of the salestransactions extension module.
The use of the generic search configuration file for the salestransactions module is declared in the md part of the
module in the metadata.xml file. Only the field to be added to the existing search criteria must be declared. If you want
to remove fields from the delivered search criteria, all the necessary fields must be declared as part of a new
description using a different name as shown in the following code:
<description
name="SearchCriteria_B2B_Order"resultlistDescription="Resultlist_B2B_SalesOrderERPCust">
<property name="ZZ_BSTKD_E"
type="input"label="sapsalestransactions.ui.purchase.number"option="EQ" />
</description>
136 October 2013
Development and Extension Guide – Application-Specific Information
5.6.2 Search Results for New Search Criteria
The changes described previously ensure that the search criterion is shown on the UI. However, you must write a new
implementation for the BAdI ERP_ISA_GEN_DOC_SEL and activate it for the document type filter WEC_ORDER.
You must copy the content of all the methods offered in the CL_IM_ERP_ISA_SFRW_ORD_SEL class to the new
class. The PERFORM_SELECTION method is changed so that the new search criterion ZZ_BSTKD_E is handed
over to the SAP ERP search framework. The following code shows an append structure added to the search criteria
structure TDS_SW_SELCRIT_ORDER, which contains the field ZZ_BSTKD_E:
LOOP AT gt_sel_opt INTO ls_sel_opt.
CASE: ls_sel_opt-select_param.
....
WHEN 'ZZ_BSTKD_E'.
ls_selcrit-zz_bstkd_e = ls_sel_opt-low
....
ENDCASE.
ENDLOOP.
Now, the SAP ERP search framework receives the search criterion that the user entered on the Web shop UI, but the
system still cannot fetch the results from the SAP ERP database tables. A new document search class is necessary to
achieve this. Any document search class implements the interface IF_FIND_SDOCS_BY_ELEMENTS. By
implementing IF_FIND_SDOCS_BY_ELEMENTS~GET_INSTANCE, you associate the search criterion ZZ_BSTKD_E
with the document search instance as shown in the following code:
method if_find_sdocs_by_elements~get_instance.
data: lt_inst type if_find_sdocs_by_elements=>tct_find_docs_by_instance,
lv_bstkd_e type bstkd_e,
ls_inst type if_find_sdocs_by_elements=>tcs_find_docs_by_instance.
* Init exporting parameter
clear et_find_by_inst.
* Check if my instance actually is needed (in this case if at least Customer number is supplied)
io_sw_sdoc->get_selcrit( exporting iv_selcrit_comp = 'ZZ_BSTKD_E'
importing ev_selcrit_value = lv_bstkd_e ).
if not lv_bstkd_e is initial.
if not so_my_find_docs is bound.
* Construct my get_docs singleton
create object so_my_find_docs.
endif.
* Implementation for get_by_kunag available
ls_inst-key = 'ZZ_BSTKD_E'.
ls_inst-object_type = cl_lord_co=>sc_ot_head.
ls_inst-seltype = if_find_sdocs_by_elements=>c_get_selection.
ls_inst-inst = so_my_find_docs.
append ls_inst to lt_inst.
else.
* Nothing to do as instance is not required
return.
endif.
* Set exporting parameter
October 2013 137
Development and Extension Guide – Application-Specific Information
append lines of lt_inst to et_find_by_inst.
endmethod.
The selection of the results from VBKD is implemented in the method
IF_FIND_SDOCS_BY_ELEMENTS~GET_DOCS_BY. The most important excerpt of coding from the method in the
code above is shown in the following code:
lt_vbeln = io_sw_sdoc->get_table_vbeln( ).
io_sw_sdoc->get_selcrit( exporting iv_selcrit_comp = 'ZZ_BSTKD_E'
importing ev_selcrit_value = lv_bstkd_e ).
if lt_vbeln is initial.
try.
select vbeln
from vbkd
into corresponding fields of table lt_vbeln
where bstkd_e eq lv_bstkd_e
order by vbeln.
catch cx_sy_dynamic_osql_error.
raise exception type cx_sy_dynamic_osql_error.
endtry.
else.
try.
select vbeln
from vbkd
into corresponding fields of table lt_vbeln
for all entries in lt_vbeln
where vbeln eq lt_vbeln-vbeln
and bstkd_e eq lv_bstkd_e.
sort lt_vbeln by vbeln.
catch cx_sy_dynamic_osql_error.
raise exception type cx_sy_dynamic_osql_error.
endtry.
endif.
The order in which these document selector instances run is important for system performance. When entering
ZZ_BSTKD_E as search criteria, make sure that the document search instance class corresponding to it runs. The
sold-to party field KUNAG is always an additional search criterion because Web shop customers must find only
documents created by themselves. Therefore, in this case, two document search instances run. To determine the
order of running, implement the BAdI BADI_SW_SELECTION_SEQ. For more information, see the following code:
method IF_BADI_SW_SELECTION_SEQ~SET_SEL_SEQ.
FIELD-SYMBOLS <ls_find_docs_by_instance> TYPE
if_find_sdocs_by_elements=>tcs_find_docs_by_instance.
LOOP AT it_find_docs_by_inst ASSIGNING <ls_find_docs_by_instance>
WHERE ( key = 'ZZ_BSTKD_E ' )
AND object_type = cl_lord_co=>sc_ot_head
AND seltype =
if_find_sdocs_by_elements=>c_get_selection.
READ TABLE ct_get_docs_inst WITH KEY inst = <ls_find_docs_by_instance>-inst TRANSPORTING NO
FIELDS.
IF sy-subrc NE 0.
INSERT <ls_find_docs_by_instance> INTO TABLE ct_get_docs_inst.
ENDIF.
138 October 2013
Development and Extension Guide – Application-Specific Information
ENDLOOP.
endmethod.
5.6.3 Adding New Fields to the Result List
If you want to change the structure of the result list by adding a new column, add the new property to the result list.
The following code shows the result list:
<description name="Resultlist_B2B_SalesOrderERP">
<property name="WEC_SHIP_STATUS" type="text"
columnTitle="sapsalestransactions.erp.ui.searching.criteria.label.shippingstatus"
fieldOutputHandlerClass="com.sap.wec.app.esales.module.transaction.ui.util.GenericSearchDynamicC
ontentOrderERP"
fieldOutputHandlerMethod="getModifiedOverallStatus" />
</description>
The following figure shows the purchase order number search criterion and the purchase order number column on the
Web shop UI:
If you want to remove an attribute from the result list, redefine the result list completely, and link it to the description of
the search criteria using the attribute resultlistDescription, proceed as shown in the following code:
<description
name="SearchCriteria_B2B_Order"resultlistDescription="Resultlist_B2B_SalesOrderERPCust">
<property name="ZZ_BSTKD_E"
type="input"
label="sapsalestransactions.ui.purchase.number"
option="EQ" />
</description>
<description name="Resultlist_B2B_SalesOrderERPCust">
October 2013 139
Development and Extension Guide – Application-Specific Information
<property name="VBELN"
type="text"
parameterType="rowkey"
columnTitle="sapsalestransactions.erp.ui.searching.criteria.label.orderid"
navigationTarget="#com.sap.wec.app.esales.module.transaction.ui.util.GenericSearchDynamicContent
OrderERP$buildNavigationTargetOrder" />
<property name="ZZ_BSTKD_E"
readOnly="true"
columnTitle="sapsalestransactions.ui.purchase.number" />
<property name="WEC_SHIP_STATUS"
type="text"
columnTitle="sapsalestransactions.erp.ui.searching.criteria.label.shippingstatus"/>
</description>
In the SAP ERP back end, you must implement a mapping in the method GET_MAPPRING_TABLE of the
implementation class for the BADI definition ERP_ISA_GEN_DOC_SEL as shown in the following code:
ls_map_fields-object_type = 'HEAD'.
ls_map_fields-field_external = 'ZZ_BSTKD_E'.
ls_map_fields-field_internal = 'BSTKD_E'.
ls_map_fields-assign = space.
ls_map_fields-object_source = 'VBKD'.
READ TABLE gt_sel_fields WITH KEY fieldname = ls_map_fields-field_external TRANSPORTING NO
FIELDS.
IF sy-subrc EQ 0.
INSERT ls_map_fields INTO TABLE lt_map_fields.
ENDIF.
140 October 2013
Development and Extension Guide – Application-Specific Information
5.6.4 Using the New Definition of the Search Description
Save the configuration file for the search (that is, the generic-searchbackend-config.xml file) in the bo part of the
salestransactions extension module as shown in the following figure:
Note
You must register this configuration file in the md part of the salestransactions extension module inside the
metadata.xml file. This file is shown in the previous figure.
October 2013 141
Development and Extension Guide – Application-Specific Information
5.7 Display of Schedule Lines (SAP ERP)
This example explains how you can enable the display of schedule lines for orders. In the standard delivery, this is not
supported for WCEM deployed against SAP ERP. You need to extend the salestransactions module in your
namespace.
1. Register factory-config.xml for extensions.
For the schedule lines to be read, you need to do extensions in the bo part of the salestransactions module.
This extension is activated through a configuration file called factory-config.xml, therefore you need to state
that this configuration file needs to be extended. This is done in metadata.xml of your extension module, and
activation looks like this:
<config-file namespace="customer" part="bo" type="factory-config">factory-
config.xml</config-file>
2. Create a new implementation class for reading the schedule lines from SAP ERP and activate it.
SAP ERP has to read the schedule line information along with the sales document items. Therefore you need
to extend the so-called item request parameters for the SAP ERP call. This needs to be done in an extension
to the central class that takes care of reading a sales document, namely GetAllStrategyERP in
com.sap.wec.app.esales.module.transaction.salesdocument.backend.impl.erp.strategy.
The implementation might look like this:
public class CustGetAllStrategyERP extends GetAllStrategyERP605 {
protected void buildDefaultItemObjectRequestParameters(
JCoFunction function, boolean isDocFlowRead, BackendState baseDocErp) {
super.buildDefaultItemObjectRequestParameters(function, isDocFlowRead,
baseDocErp);
JCoTable objReq = function.getImportParameterList().getTable(
"IT_ITEM_OBJREQ");
objReq.appendRow();
objReq.setValue("OBJECT", "SLINE");
objReq.setValue("COMV_REQUEST", "X");
objReq.setValue("COMR_REQUEST", "X");
objReq.setValue("DEF_REQUEST", "");
}
}
This class is being instantiated by a factory that takes care of the classes for exchanging data with SAP ERP
SD via LO-API:
public class CustStrategyFactory extends StrategyFactoryERP {
@Override
public GetAllStrategy createGetAllStrategy() {
return new CustGetAllStrategyERP();
}
}
142 October 2013
Development and Extension Guide – Application-Specific Information
3. Register this factory in the above mentionend factory-config.xml <your
namespace>/salestransactions/bo/factory-config.xml.
<factoryClass name="STStrategyFactoryERP" singleton="false"
className="com.customer.wec.app.esales.module.transaction.salesdocument.backend.impl.erp.s
trategy.CustStrategyFactory" />
October 2013 143
Development and Extension Guide – Application-Specific Information
5.8 Reading of Additional Attributes (SAP CRM)
You can enhance the Java back-end layer for the SAP CRM back end to enable the system to read and update
attributes that are already part of the Web Channel function module interfaces (CRM_WEC_ORDER_SET and
CRM_WEC_ORDER_GET), but not part of the delivered Java back-end layer. For example, you can enhance the
Java back-end layer to write and read business partners with a specific partner function (in this case, vendor) on item
level.
The following example code contains some calls to helper methods that already exist in delivered coding (for example,
addPartnerFieldParameter). Depending on the required extension, similar helper methods must be written as an
extension as well.
1. Inform the back end which fields will be updated.
To write fields to the SAP CRM back end layer, you must inform the back end which fields you want to update.
You do this by filling a table of CRM_WEC_ORDER_SET interface with naming convention *SET, in this
example, IT_FIELDS_PARTNER_SET.
In this example, you create an extension of the PartnerMapperImpl class (for example,
ExtensionPartnerMapperImpl) and overwrite the method addUpdatedPartnerFields as shown in the following
code:
/**
* Which field shall be updated
*/
@Override
public void addUpdatedPartnerFields(SalesDocument salesDoc,
JCoFunction func,
ControlParams controlParams) throws
BackendMappingException {
super.addUpdatedPartnerFields(salesDoc, func, controlParams);
String partnerFunction;
JCoTable partnerFields = func.getTableParameterList().getTable(
RFCConstantsCRM.InputTable.PARTNER_FIELDS_SET);
String guid = null;
String handle = null;
partnerFunction =
partnerFctMapping.getPartnerFunctionCRM(PartnerFunctionData.VENDOR);
ItemList items = salesDoc.getItemList();
int numOfItems = items.size();
for (int index = 0; index < numOfItems; index++) {
Item item = items.get(index);
TechKey techKey = item.getTechKey();
// for new items, use handle, techkey in other case
if (TechKey.isEmpty(techKey)) {
guid = "";
handle = String.valueOf(item.getHandle());
}
// existing item
else {
guid = techKey.getIdAsString();
144 October 2013
Development and Extension Guide – Application-Specific Information
handle = "";
}
addPartnerFieldParameter(partnerFields, guid, handle,
RFCConstantsCRM.Kind.ADMIN_ITEM,
partnerFunction, PARTNER_ID);
}
}
2. Write the field values from the business object into the JCO structure.
Find out which structure in the back end expects the field values to be taken over. In this example, the
partners are written into table IT_PARTNER. Therefore, the required extension of method writePartners in
PartnerMapperImpl would appear as shown in the following code:
@Override
public void writePartners(SalesDocument salesDoc, JCoFunction func, ControlParams
controlParams)
throws BackendMappingException {
super.writePartners(salesDoc, func, controlParams);
JCoParameterList tableParams = func.getTableParameterList();
JCoTable partnerTable = tableParams.getTable(PARTNER_TABLE_SET);
JCoTable partnerFields =
tableParams.getTable(RFCConstantsCRM.InputTable.PARTNER_FIELDS_SET);
TechKey techKey = salesDoc.getTechKey();
String scenario = salesDoc.getTransactionConfiguration().getScenario();
ItemList itemList = salesDoc.getItemList();
int numOfItems = itemList.size();
String itemKind = RFCConstantsCRM.Kind.ADMIN_ITEM;
String itemGUID;
String itemHandle;
for (int index = 0; index < numOfItems; index++) {
Item item = itemList.get(index);
PartnerList partnerList = item.getPartnerListData();
techKey = item.getTechKey();
if (TechKey.isEmpty(techKey)) {
itemGUID = "";
itemHandle = item.getHandle();
}
else {
itemGUID = techKey.getIdAsString();
itemHandle = "";
}
October 2013 145
Development and Extension Guide – Application-Specific Information
Map<String, String> bpRolesAndAndPartnerFunctions =
getItemBPRolesAndPartnerFunctions(
salesDoc, item);
// Add customer specific business partner function (e.g. Vendor)
String bpRoleVendor = PartnerFunctionData.VENDOR;
bpRolesAndAndPartnerFunctions.put(bpRoleVendor,
partnerFctMapping.getPartnerFunctionCRM(bpRoleVendor));
// End customer specific business partner function (e.g. Vendor)
for (Entry<String, String> entry : bpRolesAndAndPartnerFunctions.entrySet()) {
String bpRole = entry.getKey();
String partnerFunction = entry.getValue();
Address address = searchItemPartnerAddress(item, bpRole);
writePartner(itemGUID, itemHandle, itemKind, bpRole, partnerFunction,
partnerList,
partnerTable, address, partnerFields, null, scenario, null);
}
}
}
3. Request additional fields to be read from the back end.
When performing the read from the ABAP back end, the back end needs to know which data shall be read, for
performance reasons. The following code shows how, in this example, you would request the vendor to be
read from the back end:
@Override
public void addRequestedPartnerFunctions(SalesDocument salesDoc,
JCoFunction func,
ControlParams controlParams)
throws BackendMappingException {
super.addRequestedPartnerFunctions(salesDoc, func, controlParams);
JCoTable parameters = func.getTableParameterList().getTable(
RFCConstantsCRM.InputTable.PARAMETERS);
parameters.appendRow();
parameters.setValue(RFCConstantsCRM.Name.PARAMETER, PARTNER_TABLE_GET);
String partnerFunction;
JCoTable partners = func.getTableParameterList().getTable(
RFCConstantsCRM.InputTable.PARTNER_REQUESTED);
// only one line without guid means -> get all items
// VENDORS
partnerFunction =
partnerFctMapping.getPartnerFunctionCRM(PartnerFunctionData.VENDOR);
partners.appendRow();
// empty guid means - get this for all items
partners.setValue(REF_KIND, RFCConstantsCRM.Kind.ADMIN_ITEM);
partners.setValue(PARTNER_FCT, partnerFunction);
146 October 2013
Development and Extension Guide – Application-Specific Information
}
The coding enhances the method addRequestedPartnerFunctions in class PartnerMapperImpl.
4. Read fields values from JCO structure into the business object.
In this example, all requested partners are filled by the delivered code into the PartnerList on item level.
Therefore, no extension is required. In general, one would again enhance the required mapper class and read
method. The read methods have the JCO structure and the business object as a parameter.
Therefore, you would read the required data from the JCO structure and pass it to the business object as
shown in the following code:
@Override
protected void readMethod(JCoTable table, SalesDocument salesDoc, ControlParams
controlParams)
throws BackendMappingException {
int numLines = table.getNumRows();
for (int index = 0; index < numLines; index++) {
table.setRow(index);
// Read data from JCO Structure
String kind = table.getString(REF_KIND);
String partnerFct = table.getString(PARTNER_FCT);
String partnerId = table.getString(PARTNER_ID);
TechKey techKey = new TechKey(table.getString(PARTNER_GUID));
...
// Pass above data to intended business object
}
}
October 2013 147
Development and Extension Guide – Application-Specific Information
5.9 Delivery Types and Requested Delivery Dates
You can create a link between delivery type and requested delivery date (this example enhancement focuses on the
UI and BO layer in the salestransactions module). When the delivery type is changed, the requested delivery date is
adapted (and also the other way around). You can enhance the following:
The order business object to check the delivery type and set the requested delivery date accordingly
The shopping cart UI so that whenever the requested delivery date is changed, the delivery type is changed
as well (if needed)
5.9.1 Adapting BO Layer to Set Requested Delivery Date
1. To enhance the order BO, make an entry in the businessobject-config.xml file to use the enhanced order
object instead of the standard one, as shown in the following code:
<businessObject name="Order"
className="com.customer.wec.app.esales.module.salestransactions.businessobject.impl.CustOr
derImpl" />
2. To check the delivery type and set the requested delivery date accordingly, adapt the newly generated object
CustOrderImpl, as shown in the following code:
@Override
public void update() throws CommunicationException {
adaptRequestedDeliveryDate();
super.update();
}
private void adaptRequestedDeliveryDate() {
Header orderHeader = getHeader();
String shipCond = orderHeader.getShipCond();
Date currentDate = orderHeader.getReqDeliveryDate();
Date expressDate = getExpressDeliveryDate();
Date standardDate = getEarliestStandardDeliveryDate();
// overnight means as fast as possible
if (OVERNIGHT_SHIPPING.equals(shipCond) && currentDate.after(expressDate)) {
applyReqDelDate(expressDate);
}
// standard means not before standard delivery time
if (STANDARD_SHIPPING.equals(shipCond) && currentDate.before(standardDate)) {
applyReqDelDate(standardDate);
}
}
private void applyReqDelDate(Date reqDeliveryDate) {
applyReqDelDateToHeader(reqDeliveryDate);
applyReqDelDateToItems(reqDeliveryDate);
}
...
148 October 2013
Development and Extension Guide – Application-Specific Information
5.9.2 Adapting UI Layer to Set Delivery Type Depending on Requested
Delivery Date
To enhance the system so that it reacts to any change of the requested delivery date by changing the delivery type
accordingly, you must enhance the HeaderViewHandler of the extended UI as follows:
1. Add the enhanced class to the ui-repository.xml file, as shown in the following code:
<ViewComponent name="richbasketheader" componentHandlerClassName=
"com.customer.wec.app.esales.module.transaction.ui.viewhandler.CustSalesDocumentHeaderView
HandlerImpl"/>
2. So that the enhanced view handler overrides the method called by the value change listener of the requested
delivery date and executes the specific changes, use code similar to the following:
@Override
public boolean reqDeliveryDateUpdateRequired() {
boolean updateRequired = super.reqDeliveryDateUpdateRequired();
// change shipping condition depending on requested delivery date, if
// necessary
Date expressDate = getExpressDeliveryDate();
Header headerBO = getSalesDocumentHeaderBean().getBO();
Date reqDeliveryDate = headerBO.getReqDeliveryDate();
String shipCond = headerBO.getShipCond();
if (reqDeliveryDate.after(expressDate) &&
shipCond.equals(CustOrderImpl.OVERNIGHT_SHIPPING)) {
headerBO.setShipCond(CustOrderImpl.STANDARD_SHIPPING);
updateRequired = true;
}
if (!reqDeliveryDate.after(expressDate)
&& !shipCond.equals(CustOrderImpl.OVERNIGHT_SHIPPING)) {
headerBO.setShipCond(CustOrderImpl.OVERNIGHT_SHIPPING);
updateRequired = true;
}
return updateRequired;
}
3. The requested delivery date is AJAX enabled and the system only refreshes those parts of the UI that could
have changed. In the standard system, the delivery type could never change by changing the requested
delivery date. Therefore, to achieve a re-rendering, the ID of the delivery type component on the UI must be
added to the list of IDs to be re-rendered. You can do this by overwriting the method with code such as the
following:
@Override
public String getReRenderIds() {
String reRenderIds = super.getReRenderIds();
TransactionConfiguration transactionConfiguration =
getModuleAccess().getTransactionConfiguration();
// in case of java basket + list pricing, delivery type is not
// displayed, hence adding it to the re-render IDs would cause a dump
October 2013 149
Development and Extension Guide – Application-Specific Information
if (!isJavaBasket() || transactionConfiguration.isForceIPCPricing()) {
reRenderIds += SalesTransactionsUtil.RERENDER_SEPARATOR + ID_OT_DELIVER_TYPE;
}
return reRenderIds;
}
150 October 2013
Development and Extension Guide – Application-Specific Information
5.10 Proposed Shopping Templates
A typical extension of the shopping templates could be to enable assigning a shopping template to other Web shop
customers as a proposed shopping template on the UI. A Web shop administrator (for example, a sales
representative) could propose shopping templates to users. For Web shop customers, those proposed shopping
templates have the same meaning as product recommendations. You can assign Web shop customers (sold-to
parties) to proposed shopping templates for various validity periods. Web shop customers that are assigned to a
proposed shopping template see it in their list of shopping templates. Proposed shopping templates are read-only for
Web shop customers. However, they can use proposed shopping templates to order products. They can also copy
proposed shopping templates and change them. A Web shop administrator requires authorization to assign Web shop
customers to proposed shopping templates.
In the BO layer of the shoppingtemplates module, SAP delivers public methods that enable Web shop administrators
to do the following:
Create shopping templates for other users
Assign sold-to parties to shopping templates
Change the validity period for a shopping template
Change the owner for a shopping template
Details about the shopping templates business objects can be found in the javadoc documentation of the shopping
templates module’s interface part.
Furthermore, SAP delivers an authorization concept to ensure that only users with a special authorization can perform
these actions. To assign an authorization to a Web shop administrator, go to role maintenance (transaction PFCG)
and enhance a role, in SAP CRM back end for the authorization object WEC_AUTH and in SAP ERP back end for the
authorization object WEC_AUTERP (Web Channel Document Authorizations). You do this by choosing Change ->
Authorizations -> Change Authorization Data. Expand the tree and choose Change Object Types for Authorization
and enter SHTEMPLEXTMAINT (Shopping Templates Extended Maintenance).
For more information about the authorization concept, see the Security Guide for SAP Web Channel Experience
Management on SAP Service Marketplace at http://service.sap.com/wec-inst. You can also see SAP Library for SAP
Web Channel Experience Management on SAP Help Portal at http://help.sap.com/wec. Choose a release and then
Application Help. In SAP Library, choose SAP Web Channel Experience Management -> User Management ->
Authorization Concept.
The following example shows how to enhance the existing UI so that Web shop users with special authorization can
use the Web shop to create a shopping template with themselves as the owner and to assign sold-to parties to the
shopping template. Furthermore, the validity period of the shopping template (which is not shown on the UI) is
changed in this example, so that the proposed shopping template is only visible for a certain period to the assigned
Web shop customers.
October 2013 151
Development and Extension Guide – Application-Specific Information
1. Create an extension module for the shopping template module, including corresponding applications and Web
Channel Builder configuration.
In this example, it is sufficient to create an md and ui part (Development Component (DC)). For more
information about Web Channel Builder, see the section on Web Channel Builder modules in this guide. You
can also see SAP Library for SAP Web Channel Experience Management on SAP Help Portal at
http://help.sap.com/wec. Choose a release and then Application Help. In SAP Library, choose SAP Web
Channel Experience Management -> Configuration -> Configuring Web Channel Applications (Web Channel
Builder).
The new DCs might look like this:
152 October 2013
Development and Extension Guide – Application-Specific Information
2. Add the following additional dependencies to the new ui DC:
3. Add the following additional dependencies to the new dpu DC:
4. Add the following content to the metadata.xml file of the created md part. This enables you to use an
extended view handler class for your new ui view:
metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata" lazyLoad="true"
mainModule="false" moduleID="shoppingtemplates">
<moduleType>application</moduleType>
<configForModule>shoppingtemplates</configForModule>
<config-file namespace="customer" part="ui" type="ui-repository">ui-
repository.xml</config-file>
</module>
October 2013 153
Development and Extension Guide – Application-Specific Information
5. Specify your own namespace (here customer) in the module.properties file of both the md part and ui part.
This could look like this:
module.properties
sap.com.moduleId=shoppingtemplates
sap.com.moduleNamespace=customer
sap.com.extendsNamespace=sap
sap.com.modulePart=ui
6. Copy the file shopping-template.xhtml from the original shopping template ui DC to your extension ui DC.
7. Enhance the view by adding a new button called Add Assignees:
shopping-template.xhtml
<c:if test="#{cc.vch.listFilled}">
<wec:panelBox collapsible="false" id="pBTTB"
styleType="top-table-toolbar">
<wec:panelGroup id="pgRG" styleClass="fw-table-toolbar-btn"
layout="block">
<wec:commandButton id="cBATB" styleType="form-em"
tabindex="20"
value="#{i18n['shoppingtemplates.ui.AllToCart']}">
<wec:ajax event="click" id="ajATB" execute="@form"
listener="#{cc.vch.addAllItemsToBasket}"
render="msgContentHdr pGItm pGpMini" />
</wec:commandButton>
<c:if test="#{!cc.vch.readOnlyTemplate}">
<wec:commandButton id="cBSaQu" tabindex="20"
value="#{i18n['shoppingtemplates.ui.saveQuantities']}">
<wec:ajax event="click" id="ajSQ" execute="@form"
listener="#{cc.vch.saveQuantities}"
render="msgContentHdr pGItm" />
</wec:commandButton>
154 October 2013
Development and Extension Guide – Application-Specific Information
<!-- New button -->
<wec:commandButton id="cBSaQu2" tabindex="20"
value="Add Assignees"
rendered="#{cc.vch.assignmentButtonVisible}">
<wec:ajax event="click" id="ajSQ2"
execute="@form"
listener="#{cc.vch.addAssignees}"
render="msgContentHdr pGItm" />
</wec:commandButton>
<!-- End of new button -->
</c:if>
</wec:panelGroup>
</wec:panelBox>
8. Create a custom view handler in your ui DC to manage the newly created view.
ShoppingTemplateViewhandlerImplExt.java
package customer.beans.impl;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
import javax.faces.event.AjaxBehaviorEvent;
import
com.sap.wec.app.esales.module.shoppingtemplates.beans.impl.ShoppingTemplateViewhandlerImpl
;
import
com.sap.wec.app.esales.module.shoppingtemplates.businessobject.interf.ShoppingTemplatePerm
issionControl;
October 2013 155
Development and Extension Guide – Application-Specific Information
import
com.sap.wec.app.esales.module.shoppingtemplates.businessobject.interf.ShoppingTemplatePerm
issionControl.Action;
import
com.sap.wec.app.esales.module.shoppingtemplates.businessobject.intl.interf.ShoppingTemplat
eInternal;
import com.sap.wec.tc.core.businessobject.BusinessObjectException;
public class ShoppingTemplateViewhandlerImplExt extends
ShoppingTemplateViewhandlerImpl {
public void addAssignees(AjaxBehaviorEvent notUsed)
throws BusinessObjectException {
Set<String> soldTos = retrieveAssigneesFromSomeWhere();
this.shoppingTemplate.setAssignedSoldTos(soldTos);
setValidityperiod();
this.shoppingTemplate.update();
}
// In this example, we have hard-coded the GUIDs of the sold-to-parties, which
should be assigned.
// Of course the customer might want to read the sold-tos from the CRM backend. In
this case this method
// would be in the bo-part
private Set<String> retrieveAssigneesFromSomeWhere() {
Set<String> soldTos = new HashSet<String>();
soldTos.add("9E3C4D4FB4C61062E10000000A428783");
soldTos.add("1804E24F1229004CE10000000A4282C0");
soldTos.add("8906E24F1229004CE10000000A4282C0");
return soldTos;
}
private void setValidityperiod() {
Calendar cal = new GregorianCalendar(2013, 06, 30);
this.shoppingTemplate.setValidFrom(new Date());
this.shoppingTemplate.setValidTo(cal.getTime());
}
public boolean isAssignmentButtonVisible() throws BusinessObjectException {
ShoppingTemplateInternal shoppingTemplate = (ShoppingTemplateInternal)
this.shoppingTemplate;
ShoppingTemplatePermissionControl permissionControl = shoppingTemplate
.getPermissionControl();
return !this.shoppingTemplate.isReadOnlyTemplate()
&& permissionControl.hasPermission(
Action.CHANGE_OWN_TEMPLATE_ASSIGNMENTS,
shoppingTemplate);
}
}
156 October 2013
Development and Extension Guide – Application-Specific Information
9. Add a ui-repository.xml file in your ui DC with the following content:
ui-repository.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<UIRepository xmlns="http://www.sap.com/wec/frw/tc/ui/runtime/ui-repository"
xmlns:wec="com.sap.wec.core.config" module="shoppingtemplates">
<ViewComponent name="shopping-template"
componentHandlerClassName="customer.beans.impl.ShoppingTemplateViewhandlerImplExt"
/>
</UIRepository>
10. Add the source root folder for your chosen namespace (in this example customer) to the assembly public part
of the ui DC, as a Java package tree. Otherwise, the new class added might not be deployed on the server
and an exception might occur since the class is not found.
11. Make sure you have the correct configuration within Web Channel Builder.
October 2013 157
Development and Extension Guide – Application-Specific Information
Proposed shopping templates are read-only for the assigned Web shop customers. Web shop customers can use
proposed shopping templates to order products and they can copy and change copied proposed shopping templates.
This is represented by a lock icon next to the shopping template’s name.
There is also an icon for the owner of the proposed shopping template, which visualizes that the shopping template
has assignees and that all changes such as deleting or removing products are also visible to these assignees.
158 October 2013
Development and Extension Guide – Application-Specific Information
5.11 Document Converter Manager
Document converter manager manages how a document should be converted to a certain format, or how a file in a
certain format should be converted into a certain document. The document converter manager instantiates a
convertible class. This class performs the conversion into the document or format.
5.11.1 Extending the Module Settings
A convertible is part of the module setting. An extension of the module needs to be performed with the WCEM eclipse
plug-in. Only the BO and UI parts are necessary. The plug-in also generates the DPU development component. The
following figure shows the module settings, for example, the enhancement of the salestransactions module:
October 2013 159
Development and Extension Guide – Application-Specific Information
160 October 2013
Development and Extension Guide – Application-Specific Information
5.11.2 Implementing and Registering a New Convertible
Implement a convertible in the BO part of the extended module. There you have to implement a class that implements
the interface Convertible. An example is shown in the figure below:
The registration is performed by inserting an entry in the factory_config.xml file, with key (name UDM_ +
sourceObject+ _ + targetObject), with which the document manager instantiates the class that performs the
conversion of the business object. This figure shows an example:
Note
You can also set a converter util class to separate the business part and the technical part, which can be the same for
different documents. This allows you to reuse the technical part in different modules. You only have to register the
class (second line in the figure above). The naming convention is UDM_CONVERTER_UTIL_ + formatName.
October 2013 161
Development and Extension Guide – Application-Specific Information
5.11.3 Implementing the UI Part
You get the document manager by implementing the following lines:
You get the convertible by implementing these lines:
In the convertible, you can set the source object, trigger the conversion, and then get the target object.
162 October 2013
Development and Extension Guide – Application-Specific Information
5.12 Mapping of Back-End Messages to UI Messages
You can influence which texts are shown on the Web Channel UI with messages that come from the SAP ERP or SAP
CRM back end.
For example, message 097 of message class SLS_LORD in SAP ERP reads: Sales order item &1 &2 has already
been delivered (first argument is the document number, second argument is the ID of the item ordered). For the Web
shop customer, a different message text would be more user-friendly, for example: Product (0) has been shipped.
1. Define the type rfc_messages in the metadata.xml in the md part of the enhanced salestransactions module
as follows:
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata" lazyLoad="true" mainModule="false"
moduleID="salestransactions">
<moduleType>application</moduleType>
<configForModule>salestransactions</configForModule>
...
<config-file namespace="customer" part="bo" type="rfc_messages">messages.xml</config-file>
...
</module>
2. Create the file messages.xml in the bo part of the enhanced salestransactions module with the following
content:
<messages xmlns="http://www.sap.com/rfcmessages/"
xmlns:wec="com.sap.wec.core.config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sap.com/rfcmessages/ messages.xsd ">
<wec:ifValue variable="${backend}" value="erpdefault">
<message>
<source id="SLS_LORD" number="097" type="E" />
<destination type="E"
resource_key_shorttext=sapsalestransactions.erp.ui.rfc.messages.label.lord097
resource_key_longtext="" />
</message>
</wec:ifValue>
</messages>
As the message above can be raised by the SAP ERP back end only, we made the message mapping valid only for
shops running against SAP ERP (note the use of <wec:ifValue> above).
The message mapping above can be put into words like: When the error message 097 defined in class SLS_LORD is
raised by the back end, this message will be shown on the UI as an error message having the text maintained under
the resource key sapsalestransactions.erp.ui.rfc.messages.label.lord097.
You can access the message in the Java code by accessing an instance of the TransactionConfiguration, as follows:
List<RfcMessage> lst= transConf.getRFCMessages().getMessages();
October 2013 163
Development and Extension Guide – Application-Specific Information
5.13 Additional Pricing in Cart or Order
In order to trigger additional pricing in the cart or the order, you have to extend the salestransactions module. For this
example, the bo and md parts are relevant.
backendobject-config.xml (should be placed in the bo part of the extended module):
<?xml version="1.0" encoding="UTF-8"?>
<backend xmlns="http://www.sap.com/wec/frw/tc/common/backendconfig"
xmlns:wec="com.sap.wec.core.config" xmlns:xi="http://www.w3.org/2001/XInclude">
<businessObjects>
<wec:ifValue variable="${backend}" value="erpdefault">
<businessObject name="AdditionalPricing" type="AdditionalPricing"
className="com.sap.wec.app.esales.module.transaction.salesdocument.backend.impl.erp.AdditionalPr
icingImpl"
attributes="standalone">
<params>
<param name="basket.additionalCall" value="TRUE" />
</params>
</businessObject>
</wec:ifValue>
</businessObjects>
</backend>
metadata.xml (should be placed in the md part of the extended module):
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata" lazyLoad="true"
mainModule="false" moduleID="salestransactions">
<moduleType>application</moduleType>
<configForModule>salestransactions</configForModule>
...
<config-file namespace="customer" part="bo" type="backend-objects">backendobject-
config.xml</config-file>
...
</module>
You can trigger additional pricing in the context of the order as well, for example if the ship-to party is changed in
checkout via extension), and, in addition, also choose a different pricing type. See the possible pricing types in domain
KNPRS in ABAP.
To do so, the following parameters are available:
<param name="order.additionalCall" value="FALSE" />
<param name="pricingType" value="H" />
164 October 2013
Development and Extension Guide – Application-Specific Information
5.14In-Store Pickup
If stores were originally created as ERP plants in SAP ERP (called sites in SAP Retail), you must have replicated
business partners and ERP plants from SAP ERP to SAP CRM to use the in-store pickup function. Note that you must
have replicated customer master data first. However, if you did not replicate customer master data first or you
replicated ERP plants with no customer master data, you must extend SAP Web Channel Experience Management.
This extension supports in-store pickup without the requirement that customers are associated with plants in SAP
ERP.
Background: The instore module creates sales items that have an in-store specific partner function. By default, this is
the ISTP_partner function. Within this partner function, the business partner ID of the selected store is written. But this
requires that in SAP ERP a customer is associated with the store (called plants in SAP ERP). The following extension
modifies the behavior of the instore module so that the ID of the logged-on Web shop customer is written to the ISTP
partner function and not the ID of the store:
1. Create an extension module for the instore module, including corresponding test applications and Web Channel
Builder configuration. In this case, it suffices to create an md and bo part (Development Component (DC)). For
more information about Web Channel Builder, see the section on Web Channel Builder modules in this guide. You
can also see SAP Library for SAP CRM on SAP Help Portal at http://help.sap.com/wec. Choose a release and
then Application Help. In SAP Library, choose SAP Web Channel Experience Management -> Configuration ->
Configuring Web Channel Applications (Web Channel Builder).
The new DCs might look as follows:
2. Add the following additional dependencies to the bo DC:
wec/comm/mc/storelocator/intf
wec/comm/mc/user/intf
wec/comm/rc/transaction/intf
wec/ecom/mc/salestransactions/intf
wec/frw/tc/core
wec/trade/mc/instore/bo
wec/trade/mc/instore/intf
Please be aware to have corresponding Enterprise Applications (one for the Application itself and another one for
the configuration). These must have the following dependencies maintained:
Web Channel Builder DC (called j2eeappwcb) with dependencies:
October 2013 165
Development and Extension Guide – Application-Specific Information
Application DC (called j2eeapp) with dependencies:
3. Add the following content to the metadata.xml file of the created md part. This enables you to use an extended
module access class:
<moduleClasses>
<moduleAccessClass>com.sap.wec.app.trade.module.instore.modulemgmt.impl.InstoreModuleAccessIm
plExt</moduleAccessClass>
</moduleClasses>
4. Create class com.sap.wec.app.trade.module.instore.modulemgmt.impl.InstoreModuleAccessImplExt in the bo part
using the following code:
InstoreModuleAccessImplExt.java
package com.sap.wec.app.trade.module.instore.modulemgmt.impl;
import com.sap.wec.app.trade.module.instore.businessobject.InstoreShipToImplExt;
import com.sap.wec.app.trade.module.instore.businessobject.intf.InstoreShipTo;
public class InstoreModuleAccessImplExt extends InstoreModuleAccessImpl {
@Override
// we override this method in order to bring an extended implementation of
// InstoreShipTo into play
public InstoreShipTo createInstoreShipTo() {
return new InstoreShipToImplExt(getBasketAccess(),
getBusinessPartnerAccess().getAddressManager(),
getBusinessPartnerAccess().getBusinessPartnerManager(),
getAvailabilityCheckBO(), getInstoreConfiguration());
}
}
166 October 2013
Development and Extension Guide – Application-Specific Information
5. Create class com.sap.wec.app.trade.module.instore.businessobject.InstoreShipToImplExt in the bo part using the
following coding (this coding changes the partner ID of the in-store pickup partner function from store to user):
InstoreShipToImplExt .java
package com.sap.wec.app.trade.module.instore.businessobject;
import com.sap.wec.app.common.mc.module.storelocator.businessobject.interf.StoreDetail;
import com.sap.wec.app.common.module.businesspartner.businessobject.interf.AddressManager;
import com.sap.wec.app.common.module.businesspartner.businessobject.interf.BusinessPartner;
import
com.sap.wec.app.common.module.businesspartner.businessobject.interf.BusinessPartnerManager;
import com.sap.wec.app.common.module.transaction.item.businessobject.interf.Item;
import
com.sap.wec.app.common.module.transaction.order.businessobject.interf.PartnerListEntry;
import com.sap.wec.app.esales.module.transaction.modulemgmt.interf.BasketAccess;
import com.sap.wec.app.trade.module.instore.businessobject.impl.InstoreSalesItemHelperImpl;
import com.sap.wec.app.trade.module.instore.businessobject.impl.InstoreShipToImpl;
import com.sap.wec.app.trade.module.instore.businessobject.intf.AvailabilityCheckBO;
import com.sap.wec.app.trade.module.instore.businessobject.intf.InstoreConfiguration;
import com.sap.wec.app.trade.module.instore.businessobject.intf.InstoreSalesItemHelper;
public class InstoreShipToImplExt extends InstoreShipToImpl {
private final BusinessPartnerManager bpManager;
private final InstoreConfiguration instoreConfiguration;
// we have to override the constructor to store bpManager and
// instoreConfiguration since they have been defined private in the
// superclass
public InstoreShipToImplExt(BasketAccess basketAccess,
AddressManager addressManager,
BusinessPartnerManager businessPartnerManager,
AvailabilityCheckBO availabilityCheckBO,
InstoreConfiguration instoreConfiguration) {
super.setBasketAccess(basketAccess);
super.setBpManager(businessPartnerManager);
super.setAvailabilityCheckBO(availabilityCheckBO);
super.setAddressManager(addressManager);
super.setInstoreConfiguration(instoreConfiguration);
this.bpManager = businessPartnerManager;
this.instoreConfiguration = instoreConfiguration;
}
@Override
// we need to override this method in order to change the partner Id of the
// instore pickup partner function. Instead of the (default) store Id we
// enter the ID of the logged in user. The method gets called in two cases:
// 1. when the product is added to the basket and 2. when the user logs on
// (triggerd by the SoldToChangedEvent).
public void addShipTo(Item item, StoreDetail storeDetail) {
super.addShipTo(item, storeDetail);
BusinessPartner soldTo = bpManager.getSoldto();
October 2013 167
Development and Extension Guide – Application-Specific Information
if (soldTo == null) {
return;
}
InstoreSalesItemHelper helper = new InstoreSalesItemHelperImpl();
String partnerId = bpManager.getSoldto().getId();
if (helper.isInstoreItem(item, instoreConfiguration)) {
PartnerListEntry entry = item.getPartnerListData().getPartnerData(
instoreConfiguration.getPartnerFunctionInStorePickup());
entry.setPartnerId(partnerId);
}
}
}
6. Add source root folder com as Java package tree to the assembly public part of the bo DC. Otherwise, the two
classes added might not be deployed on the server and an exception might occur for the class not found.
7. Take care of having the correct configuration within WCEM:
168 October 2013
Development and Extension Guide – Application-Specific Information
6 Payment Process
6.1 Payment Service Providers
You can enable your Web shop to accept payment from your Web shop customers by way of payment service
providers (PSPs). Integrating payment service providers enables your Web shop to offer the payment methods
provided by payment service providers to their customers. For more information, see SAP Library on SAP Help Portal
at http://help.sap.com/wec. Choose a release and then Application Help. In SAP Library, choose SAP Web Channel
Experience Management -> E-Commerce -> Checkout -> Payment Methods -> Payment Service Providers.
If you want to integrate payment service providers, you must implement extensions.
Two major decisions will influence the scope:
Which payment service provider will you integrate?
Each payment service provider offers a specific technical framework to integrate their services.
If you use PayPal, you must start your integration as described in chapter Web Service Integration
(PayPal Example).
Note
The examples are based on webservices provided by PayPal. If you integrate another payment service
provider, you must adapt these examples to the technical services provided by the payment service
provider.
Which back end integration scenario will you use?
October 2013 169
Development and Extension Guide – Application-Specific Information
6.1.1 Architecture Overview
The following figure shows an overview of the system architecture:
The payment service provider integration framework enables you to integrate with various PSP platforms. The current
integration is based on the advanced payment concept. By submitting orders, Web shop customers trigger the initial
communication to PSPs. Web shop customers are redirected to the PSP system to confirm payments. The Web shop
receives confirmations containing unique transaction IDs and statuses of payments (for example, complete or
pending). PSP payment statuses are used in order management to manage logistic execution and ensure that
merchants receive payment in Financials.
Note
Note that the payment service provider interface (PSP IF) is a reuse component which is part of both the SAP CRM
back end and the SAP ERP back end.
170 October 2013
Development and Extension Guide – Application-Specific Information
6.1.2 Web Service Integration (PayPal Example)
SAP delivers a generic interface for the integration of payment service providers. This section describes relevant
activities to consume Web services. We will use PayPal services as an example.
The PayPal Web service is a third party product. More information regarding the PayPal API can be found in the
PayPal Developer Area:
https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/howto_api_overview
The SAP system consumes the services provided by PayPal in order to trigger operations on the PayPal system such
as triggering a payment or a refund. This PayPal integration sees the SAP system as a consumer. The SAP system
sends a request to the PayPal system and the PayPal system sends back a response. However, PayPal does not
directly call the SAP system. In other words, the integration follows a ‘pull’ approach but there is no ‘push’.
For more information about using PayPal as a payment service provider, see http://www.paypal.de/SAP.
6.1.2.1 Downloading WSDL and XSD
Web services are usually defined via WSDL (Web Service Definition Language). A WSDL file is an XML file, which
defines the API of a Web service provider. For example, it specifies the available methods and the respective
parameters. A WSDL file can be accompanied by one or more XSD (XML Schema Definition) files. XSD files define
XML tags and attributes that are used in the WSDL file. This way, data types can be defined in a generic way. Note
that this is a very simplified view on WSDL and XSD. More information on this topic is widely available on the Internet.
Here are the sources for the PayPal WSDL file and XSD files:
Location for PayPal Sandbox
Web Service Definition https://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl
XML Schema Definition https://www.sandbox.paypal.com/wsdl/eBLBaseComponents.xsd
https://www.sandbox.paypal.com/wsdl/CoreComponentTypes.xsd
https://www.sandbox.paypal.com/wsdl/EnhancedDataTypes.xsd
Location for PayPal Productive System
Web Service Definition https://www.paypal.com/wsdl/PayPalSvc.wsdl
XML Schema Definition http://www.paypal.com/wsdl/eBLBaseComponents.xsd
http://www.paypal.com/wsdl/CoreComponentTypes.xsd
http://www.paypal.com/wsdl/EnhancedDataTypes.xsd
6.1.2.2 Editing WSDL File
Ideally, the WSDL file can be directly used for the generation of the Web service consumer. In practice, however, this
is usually not possible. This has two reasons. First, there can be errors in the WSDL file. For example, this is the case
for the files provided by PayPal. Second, there are limitations of the SAP Web Service Generation Tool. The following
subsections show the necessary changes to the PayPal WSDL file.
1. Copy XML schema definition into WSDL.
The web service proxy generation tool from SAP NetWeaver does not support mutually recursive schema
imports in the WSDL. Mutually recursive schema imports cause an endless loop.
The PayPal WSDL file references the two XSD files. The XSD files reference each other. Because of this
mutually recursive import, the generation does not work.
The workaround for this limitation is to copy the XML Schema Definitions into the WSDL file. This way there is
no mutually recursive schema import anymore. The following two steps are necessary to do this.
1. Copy the contents of the XSD files into the wsdl:types section of the WSDL file
2. Remove the schemaLocation attributes which import the XSD files.
Note
This is a limitation of SAP Net Weaver. A fix might be provided in the future.
October 2013 171
Development and Extension Guide – Application-Specific Information
2. Remove attribute version.
If an XML element or attribute is not defined correctly, the generation of the web service proxy aborts with a
syntax error.
The attribute version in the PayPal WSDL file specifies the version of the PayPal API. The current version is
‘60.0’. Unfortunately, the attribute version is not defined and causes an exception in the library handler.
The workaround for this error is to simply delete the attribute version from the WSDL file. Since this attribute
only has informational purpose there are no technical consequences.
Note
This is an error in the PayPal WSDL file. This issue has been addressed to PayPal.
3. Change fixed length of payerID (in earlier versions of PayPal only).
Parameters of methods specified in the WSDL file can be defined with a fixed length. This can cause issues in
Web service communication because attribute values are filled with blanks. For example, if a parameter has
the fixed length of 100 characters and the parameter value is shorter than 100 characters, then the remaining
characters are filled with blanks.
In the PayPal XSD file eBLBaseComponents.xsd, the data type UserIDType is defined with a fixed length of
127 characters. This data type is used for the PayerID. In practice, the payer ID is shorter than 127
characters. The blanks after the PayerID cause issues in the communication to PayPal because PayPal no
longer recognizes the PayerID. For example, the PayPal API receives “PayerA “ which is not
equal to “PayerA”.
<simpleType>
<restriction base="xs:string">
<length value="127" />
</restriction>
</simpleType>
The workaround for this error is to simply change the attribute length to maxLength. Then the parameter value
can be up to the number of specified characters but also can be less.
Note
This is an error in the PayPal WSDL file. This issue has been solved by PayPal in later versions.
4. Make parameter EBAY_TRANSACTION_ID optional.
Parameters can be specified in the WSDL file using a minimum and maximum occurrence. If the minimum
occurrence is not specified, this means that it is one. Mandatory attributes have a minimum occurrence of
one. If a mandatory attribute is not returned from the Web service, there will be an error in the XML
transformation in the back end.
The parameter EBAY_TRANSACTION_ID is not returned by PayPal in the method
GET_TRANSACTION_DETAILS because it is not relevant here. However, it is marked in the WSDL file as
mandatory and hence the XML transformation expects it to be returned. This causes an error when receiving
a response from PayPal. The workaround for this error is to simply specify the minimum occurrence of zero
for the parameter EBAY_TRANSACTION_ID in the PayPal WSDL file:
172 October 2013
Development and Extension Guide – Application-Specific Information
<element ref="ns:EbayTransactionID" *minOccurs="0"*>
<annotation>
<documentation>
Its Ebay transaction id.
<br />
EbayTransactionID will returned for immediate pay item transaction in ECA
</documentation>
</annotation>
</element>
Note
This is an error in the PayPal WSDL file. In different versions of PayPal, the exact syntax may differ.
6.1.2.3 Generating Web Service Proxy
You can create a Web service consumer proxy using the following steps:
1. Enter transaction SE80.
2. Right-click on a package. Choose Create -> Enterprise Service.
3. Choose Service Consumer and then Continue.
4. Choose Local File and then Continue.
5. Enter C:\<Path>PayPalSvc.wsdl and choose Continue.
6. Choose Local Object. Enter the transport request and choose Continue.
7. Choose Complete.
8. Choose the first entry PayPalAPIInterface.
9. Activate the created Web service proxy.
10. Confirm the popup saying that the object name SOLUTION_TYPE is reserved for package SO.
11. Choose the Used Objects tab and scroll down to the object SOLUTION_TYPE_TYPE.
12. Change the object name from SOLUTION_TYPE_TYPE to PAYPAL_SOLUTION_TYPE_TYPE.
13. Repeat steps 1 to 9 but choose the second entry PayPalAPIAAInterface in step 8.
October 2013 173
Development and Extension Guide – Application-Specific Information
The following diagrams show an example of creating a Web service consumer proxy:
174 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 175
Development and Extension Guide – Application-Specific Information
176 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 177
Development and Extension Guide – Application-Specific Information
178 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 179
Development and Extension Guide – Application-Specific Information
180 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 181
Development and Extension Guide – Application-Specific Information
182 October 2013
Development and Extension Guide – Application-Specific Information
The Web service proxy CO_PAY_PAL_APIAAINTERFACE is created by the proxy generation tool based on a WSDL
file. All methods provided by a proxy can be easily shown in the External View and Internal View tabs. The External
View tab shows the external (PayPal) view on the methods. The Internal View tab shows the internal (ABAP) view on
the methods.
Note
A Web service proxy is a class. Its methods can be accessed just as in any other call of an ABAP class method.
October 2013 183
Development and Extension Guide – Application-Specific Information
6.1.2.4 Creating Web Service Wrapper
The Web service proxy is automatically created based on an XML file. The automatically created structures for the
method parameters are usually very nested just like an XML document. This means that it is not very convenient to
call a Web service proxy. Therefore, we recommend that you create a wrapper class for the proxy. A wrapper class
has the following advantages:
Encapsulates one or more Web service proxies
Serves as an API for the Web service
Provides convenient access to the functionality of the Web service
Abstracts from the technical details (for example, nested structures)
Only offers required parameters in its interface (not the complete list defined in the WSDL)
Data mapping such as ISO conversions
Error handling
In the following example we assume that there is a wrapper class ZCL_COMMON_PAYPAL_API (not part of the SAP
standard delivery) that encapsulates some Web service proxy functions. It serves as the API for the PayPal Web
service.
ISO Conversion
The PayPal system can use ISO currency and language codes. Therefore, the SAP currency and SAP language need
to be converted to ISO codes. You can do this with the following code:
DATA:
lv_iso_langu TYPE laiso,
lv_iso_currency TYPE tcurc-isocd.
TRY.
* Convert language key to ISO language code
CALL METHOD cl_gdt_conversion=>language_code_outbound
EXPORTING
im_value = sy-langu
IMPORTING
ex_value = lv_iso_langu.
* Convert currency key to ISO currency code
CALL METHOD cl_gdt_conversion=>currency_code_outbound
EXPORTING
im_value = iv_currency
IMPORTING
ex_value = lv_iso_currency.
CATCH cx_gdt_conversion INTO le_gdt_conv.
ls_message-type = 'E'.
ls_message-message = le_gdt_conv->if_message~get_text( ).
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_message-system.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDTRY.
184 October 2013
Development and Extension Guide – Application-Specific Information
Call to the Proxy
Calling a method of the proxy is just like calling a normal class method. Each method of the proxy has the following
parameters:
The parameter INPUT is an importing parameter and is a structure containing all parameters that are sent to the
Web service.
The parameter OUTPUT is an exporting parameter and is a structure containing all parameters that are returned
from the Web service.
The following is an exemplary code excerpt from the method
ZZCL_COMMON_PAYPAL_API=>SET_EXPRESS_CHECKOUT.
DATA:
lo_ws_proxy TYPE REF TO co_pay_pal_apiaainterface.
[…]
* Call webservice proxy
TRY.
CALL METHOD lo_ws_proxy->set_express_checkout
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
CATCH cx_ai_system_fault INTO le_system_fault.
lv_text = le_system_fault->if_message~get_text( ).
MESSAGE lv_text TYPE 'E'.
CATCH cx_ai_application_fault INTO le_app_falut.
lv_text = le_app_falut->if_message~get_text( ).
MESSAGE lv_text TYPE 'E'.
ENDTRY.
Error Handling
There are two kinds of errors:
Errors that occur on SAP side (application error or system error)
Errors that occur on PayPal side
You must detect and deal with both types of errors. The following code detects an error on SAP side, returns the error
with the message text, and aborts in case of an error:
* Call webservice proxy
TRY.
CALL METHOD lo_ws_proxy->set_express_checkout
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
CATCH cx_ai_system_fault cx_ai_application_fault INTO le_root.
ls_message-type = 'E'.
ls_message-message = le_app_falut->if_message~get_text( ).
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_message-system.
APPEND ls_message TO et_messages.
October 2013 185
Development and Extension Guide – Application-Specific Information
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDTRY.
The following code detects an error that was returned from PayPal and returns the errors with the message texts:
method GET_ERRORS_FROM_PAYPAL.
DATA:
ls_message TYPE bapiret2.
FIELD-SYMBOLS:
<ls_paypal_error> TYPE error_type3.
* Error detection
CASE is_abstract_response_type-ack.
WHEN gc_ack_success.
ev_success = abap_true.
WHEN gc_ack_successwithwarning.
ev_success = abap_true.
WHEN gc_ack_failure.
ev_success = abap_false.
WHEN gc_ack_failurewithwarning.
ev_success = abap_false.
* For the values below we cannot be really sure whether the operation was successful.
* Therefore, the parameter returned by PayPal is checked. If it is provided, the
* operation was successful - otherwise it failed. For example, if the method
* set_express_checkout returns with a warning but the token is returned from
* PayPal, the operation was a success.
WHEN gc_ack_warning.
IF iv_returned_value IS INITIAL.
ev_success = abap_false.
ELSE.
ev_success = abap_true.
ENDIF.
WHEN gc_ack_customcode. "Reserved by PayPal for internal or future use
IF iv_returned_value IS INITIAL.
ev_success = abap_false.
ELSE.
ev_success = abap_true.
ENDIF.
WHEN OTHERS.
IF iv_returned_value IS INITIAL.
ev_success = abap_false.
ELSE.
ev_success = abap_true.
ENDIF.
186 October 2013
Development and Extension Guide – Application-Specific Information
ENDCASE.
* Loop over all messages returned from PayPal
LOOP AT is_abstract_response_type-errors ASSIGNING <ls_paypal_error>.
CASE <ls_paypal_error>-severity_code.
WHEN gc_severity_code_warning.
ls_message-type = 'W'.
WHEN gc_severity_code_error.
ls_message-type = 'E'.
WHEN gc_severity_code_custom. "Reserved by PayPal for internal or future use
ls_message-type = 'I'.
ENDCASE.
ls_message-message = <ls_paypal_error>-short_message.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ENDLOOP.
endmethod.
The application that calls the Web service wrapper receives the exporting parameter EV_SUCCESS, which indicates
the success of the operation, and it receives the exporting parameter ET_MESSAGES, which contains all error
messages. The system needs to handle the errors. For example, the system can log the error messages and inform
the Web shop customer that the operation is aborted.
Caution
If PayPal returns an error, PayPal usually does not return any parameter values. For example, if the authentication
fails, PayPal does not return a token in method SET_EXPRESS_CHECKOUT. Many returning parameters such as
the token are marked as mandatory in the WSDL file. If a mandatory parameter is not returned by PayPal, the XML
transformation (XSLT) in SAP NetWeaver aborts with the exception cx_ai_system_fault. This makes it impossible to
get the error message returned from PayPal with the coding above. Therefore, it will be necessary either to trace the
XML response in the XML Monitor (transaction SXMB_MONI) or to debug to the code that processes the XML
response.
Note that this is an error in the WSDL file from PayPal. This is not an error in SAP NetWeaver. PayPal does not return
attributes that are marked as mandatory in the WSDL file. Therefore, those parameters should be marked as optional
in the WSDL file from PayPal.
For many attributes, PayPal does not specify the occurrence of a parameter. According to the World Wide Web
Consortium (W3C), “The default value for both the minOccurs and the maxOccurs attributes is 1.”
http://www.w3.org/TR/xmlschema-0/ This means that parameters are mandatory if the occurrence is not specified.
PayPal might have mistakenly forgotten to specify those parameters as optional.
For more information about error handling, see https://cms.paypal.com/us/cgi-bin/?cmd=_render-
content&content_ID=developer/e_howto_api_nvp_errorcodes.
October 2013 187
Development and Extension Guide – Application-Specific Information
Additional Attributes in SOAP Header
A normal call to the proxy only fills the data in the body of a SOAP message. The SOAP header is created
automatically. Sometimes it is required to add additional data to the header of a SOAP message.
Note
SOAP is an XML format used in Web service communication. More information on SOAP is widely available on the
Internet.
For example, many Web service providers require an authentication via the SOAP header. This means that the user
name and password are transmitted in the header of the SOAP message.
Caution
SOAP messages can be traced, for example via the XML Monitor (transaction SXMB_MONI) and via an ICF (Internet
Communication Framework) trace. Users with the required authorization for such tracing tools can view SOAP
messages in plain text. Therefore, it is not compliant with the SAP security standard to send credentials via the SOAP
header in plain text. The same applies for the SOAP body.
Authentication via the SOAP header is a proprietary security mechanism. Therefore it is not supported out of the box
by SAP NetWeaver. SAP supports the Web Service Security protocol, which is the standard security mechanism for
Web service calls.
Caution
PayPal requires authentication via signature and certificate. User name and Password (signature) must be sent in the
SOAP header in plain text. This security issue has been addressed to PayPal. The certificate is not part of SOAP
header. For more information, see section Import Client Certificate.
The following coding shows how to generate the additional data for the SOAP header using the SAP NetWeaver iXML
library and how to put it into the SOAP header. Note that knowledge about XML and about DOM (Document Object
Model) is required to understand the coding. Information on XML and DOM is widely available on the Internet.
method GET_WS_INTERFACE.
DATA:
lr_protocol TYPE REF TO if_wsprotocol_ws_header,
lr_xml_document TYPE REF TO if_ixml_document.
DATA:
le_system_fault TYPE REF TO cx_ai_system_fault,
lv_text TYPE string.
TRY.
* Create instance
CREATE OBJECT er_interface
EXPORTING
logical_port_name = iv_logical_port.
* Get the web service protocol for access to additional fields of the WS SOAP message header
lr_protocol ?= er_interface->get_protocol( if_wsprotocol=>ws_header ).
188 October 2013
Development and Extension Guide – Application-Specific Information
* Get additional fields for the authentication in the SOAP header
CALL METHOD get_soap_header_auth
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
IMPORTING
er_xml_document = lr_xml_document.
* Add additional fields to the SOAP header
CALL METHOD add_to_soap_header
EXPORTING
ir_xml_document = lr_xml_document
ir_protocol = lr_protocol.
CATCH cx_ai_system_fault INTO le_system_fault.
lv_text = le_system_fault->if_message~get_text( ).
MESSAGE lv_text TYPE 'X'.
ENDTRY.
endmethod.
METHOD get_soap_header_auth.
CONSTANTS:
co_tag_header TYPE string VALUE 'Header', "#EC NOTEXT
co_tag_req_cred TYPE string VALUE 'RequesterCredentials', "#EC NOTEXT
co_tag_credentials TYPE string VALUE 'Credentials', "#EC NOTEXT
co_tag_username TYPE string VALUE 'Username', "#EC NOTEXT
co_tag_password TYPE string VALUE 'Password', "#EC NOTEXT
co_tag_signature TYPE string VALUE 'Signature', "#EC NOTEXT
co_attr_xmlns TYPE string VALUE 'xmlns', "#EC NOTEXT
co_attr_type TYPE string VALUE 'type', "#EC NOTEXT
co_namesp_soap TYPE string VALUE 'SOAP-ENV', "#EC NOTEXT
co_namesp_xsi TYPE string VALUE 'xsi', "#EC NOTEXT
co_ns_paypalapi TYPE string VALUE 'urn:ebay:api:PayPalAPI', "#EC
NOTEXT
co_ns_eblbase TYPE string VALUE 'urn:ebay:apis:eBLBaseComponents', "#EC
NOTEXT
co_ns_xsi TYPE string VALUE 'http://www.w3.org/2001/XMLSchema-instance', "#EC
NOTEXT
co_ns_enc TYPE string VALUE 'http://schemas.xmlsoap.org/soap/encoding/', "#EC
NOTEXT
co_ns_env TYPE string VALUE 'http://schemas.xmlsoap.org/soap/envelope/', "#EC
NOTEXT
co_ns_xsd TYPE string VALUE 'http://www.w3.org/2001/XMLSchema', "#EC
NOTEXT
co_ns_encoding TYPE string VALUE 'http://schemas.xmlsoap.org/soap/encoding/', "#EC
NOTEXT
co_ns_security_h TYPE string VALUE 'ebl:CustomSecurityHeaderType', "#EC
NOTEXT
October 2013 189
Development and Extension Guide – Application-Specific Information
co_ns_base_comp TYPE string VALUE 'urn:ebay:apis:eBLBaseComponents', "#EC
NOTEXT
co_ns_user_pwd TYPE string VALUE 'ebl:UserIdPasswordType'. "#EC
NOTEXT
DATA:
l_ixml TYPE REF TO if_ixml,
l_document TYPE REF TO if_ixml_document,
l_encoding TYPE REF TO if_ixml_encoding,
l_root TYPE REF TO if_ixml_element,
l_req_cred TYPE REF TO if_ixml_element,
l_credentials TYPE REF TO if_ixml_element,
l_username TYPE REF TO if_ixml_element,
l_password TYPE REF TO if_ixml_element,
l_signature TYPE REF TO if_ixml_element,
l_rc LIKE sy-subrc,
l_streamfactory TYPE REF TO if_ixml_stream_factory,
l_stream TYPE REF TO if_ixml_ostream,
l_renderer TYPE REF TO if_ixml_renderer,
l_xstring TYPE xstring.
* Initialize the iXML-Toolkit
l_ixml = cl_ixml=>create( ).
* Create the xml-document
l_document = l_ixml->create_document( ).
* Set encoding to UTF-8
l_encoding = l_ixml->create_encoding(
byte_order = 0 " little endian byte ordering
character_set = 'UTF-8' ).
CALL METHOD l_document->set_encoding
EXPORTING
encoding = l_encoding.
* Create the root element (SOAP header)
l_root = l_document->create_simple_element(
name = co_tag_header
namespace = co_namesp_soap
parent = l_document ).
* Create the element RequesterCredentials
l_req_cred = l_document->create_simple_element(
name = co_tag_req_cred
parent = l_root ).
* Create the element Credentials
l_credentials = l_document->create_simple_element(
190 October 2013
Development and Extension Guide – Application-Specific Information
name = co_tag_credentials
parent = l_req_cred ).
* Create the element Username
l_username = l_document->create_simple_element(
name = co_tag_username
value = iv_username
parent = l_credentials ).
* Create the element Password
l_password = l_document->create_simple_element(
name = co_tag_password
value = iv_password
parent = l_credentials ).
* Create the element Signature
IF iv_signature IS NOT INITIAL.
l_signature = l_document->create_simple_element(
name = co_tag_signature
value = iv_signature
parent = l_credentials ).
ENDIF.
* Add attributes to the elements
l_rc = l_req_cred->set_attribute(
name = co_attr_xmlns
value = co_ns_paypalapi ).
l_rc = l_req_cred->set_attribute( "xmlns:xsi=
name = co_namesp_xsi
namespace = co_attr_xmlns
value = co_ns_xsi ).
l_rc = l_req_cred->set_attribute(
name = co_attr_type
namespace = co_namesp_xsi
value = co_ns_security_h ).
l_rc = l_credentials->set_attribute(
name = co_attr_xmlns
value = co_ns_base_comp ).
l_rc = l_credentials->set_attribute(
name = co_attr_type
namespace = co_namesp_xsi
value = co_ns_user_pwd ).
er_xml_document = l_document.
ENDMETHOD.
October 2013 191
Development and Extension Guide – Application-Specific Information
method ADD_TO_SOAP_HEADER.
DATA:
l_root TYPE REF TO if_ixml_element,
l_element TYPE REF TO if_ixml_element.
DATA:
lv_element_name TYPE string,
lv_namespace TYPE string.
* Get root element
l_root = ir_xml_document->get_root_element( ).
* Get first child element
l_element ?= l_root->get_first_child( ).
* Loop over all child elements
WHILE NOT l_element IS INITIAL.
* Get element name and namespace
lv_element_name = l_element->get_name( ).
lv_namespace = l_element->get_namespace_uri( ).
* Add header element to SOAP header
ir_protocol->set_request_header(
name = lv_element_name
namespace = lv_namespace
dom = l_element ).
* Get next element
l_element ?= l_element->get_next( ).
ENDWHILE.
endmethod.
The following example shows what the XML data added to the SOAP header looks like:
<RequesterCredentials xmlns=”urn:ebay:api:PayPalAPI” xsi:type=”ebl:CustomSecurityHeaderType”>
<Credentials xmlns=”urn:ebay:apis:eBLBaseComponents” xsi:type=”ebl:UserIdPasswordType”>
<Username>api_username</Username>
<Password>api_password</Password>
<Signature>api_signature</Signature>
</Credentials>
</RequesterCredentials>
Caution
The data must be added to the SOAP header before each call to the proxy. It is not sufficient to add the data to the
variable lr_protocol (see coding above) only once.
192 October 2013
Development and Extension Guide – Application-Specific Information
6.1.2.5 Regenerating Web Service Proxy
It might be necessary to make changes to the WSDL file after the proxy was already generated. For example, there
could be an error in the file that was not identified at the time of the proxy generation. In such a case, there is no need
to start from scratch. The Web service proxy can be regenerated with the following steps:
1. Enter transaction SE80.
2. Enter package COM_WEC_PAYPAL_IMPL.
3. Open the service consumer CO_PAY_PAL_APIINTERFACE.
4. Choose Regenerate.
5. Choose Local File.
6. Enter the location of the modified WSDL document.
7. Choose Complete.
8. Activate the proxy.
The following figures show how you can regenerate the Web service proxy:
October 2013 193
Development and Extension Guide – Application-Specific Information
194 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 195
Development and Extension Guide – Application-Specific Information
196 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 197
Development and Extension Guide – Application-Specific Information
6.1.2.6 Setting Up Connection to PayPal (Customizing)
Logical Port Configuration
You can create a logical port using the following steps:
1. Enter transaction SE80.
2. Enter package COM_WEC_PAYPAL_IMPL.
3. Open the service consumer CO_PAY_PAL_APIINTERFACE.
4. Choose Start SOAMANAGER.
Alternatively, start transaction SOAMANAGER and search for the service consumer.
5. Select the service consumer and choose Apply Selection.
6. Choose Configurations.
7. Choose Create Logical Port.
8. Enter the name of the logical port and a description.
9. Select the Logical Port is Default check box.
(Otherwise, you must specify the name of the logical port in the coding.)
10. To generate the logical port automatically from the WSDL file from PayPal, choose WSDL Based
Configuration and enter the location of the WSDL file.
11. Choose Apply Settings.
The system automatically creates the configuration for the logical port. You can change the configuration, if
necessary.
198 October 2013
Development and Extension Guide – Application-Specific Information
12. Choose the Transport Settings tab.
13. Verify that the generated settings match the correct PayPal API endpoints.
14. Enter the proxy host and port, for example proxy and 8080.
Caution
The proxy proxy could also be an IP address. No ‘http://’ must be specified in the proxy field.
Note
The proxy of the Web shop owner must be entered. Therefore, this information cannot be provided by PayPal
in the WSDL file. PayPal does not know the proxy of any Web shop owner.
15. Choose Save.
16. Repeat steps 1 to 15 for the service consumer CO_PAY_PAL_APIAAINTERFACE.
Note
A logical port always belongs to one service consumer. Therefore, there can be two logical ports with the
same name but for different service consumers.
October 2013 199
Development and Extension Guide – Application-Specific Information
The following figures show an example of how you can create a logical port:
200 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 201
Development and Extension Guide – Application-Specific Information
202 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 203
Development and Extension Guide – Application-Specific Information
204 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 205
Development and Extension Guide – Application-Specific Information
206 October 2013
Development and Extension Guide – Application-Specific Information
Setup of Secure Connection
The following sections examine the steps to set up a secure connection with PayPal.
1. Import Server Certificate
A Secure Socket Layer (SSL) connection to a server can only be established if the server is trusted.
Therefore, it is necessary to install the server certificate from PayPal via transaction STRUST.
Note
A server certificate is provided by the server but it is no means of authentication required by the server. Its
purpose is that the caller (SAP system in our case) trusts the server (PayPal in our case). Note that browsers
such as the Internet Explorer make use of server certificates also. The difference to a SAP system is that the
Internet Explorer downloads the server certificate automatically whereas in an SAP system is has to be
explicitly installed for security reasons.
If the server certificate is not installed correctly, the following error message will be issued when connecting
to the server (PayPal in this case): "ICF Error when receiving the response: ICM_HTTP_SSL_ERROR".
Download the server certificate from PayPal and install it on the SAP back-end system as follows:
a. Point your browser to the PayPal homepage www.paypal.com.
b. Choose the lock symbol in the lower right corner of the browser.
c. Export the certificate (save it to your hard drive).
d. Import this certificate into your SAP system (transaction STRUST).
October 2013 207
Development and Extension Guide – Application-Specific Information
The following figure shows the location of the lock symbol in a Web browser:
208 October 2013
Development and Extension Guide – Application-Specific Information
The following figures show an example of how to import a certificate:
October 2013 209
Development and Extension Guide – Application-Specific Information
Caution
The server certificate needs to be installed to the SSL Client Standard, not to the SSL Server Standard.
The server certificate is only valid in a certain time period (see first screenshot below). Therefore, it is
recommended to install the VeriSign Root Certificate. This means only to import the first two levels of the
certification path (see second screenshot below). Otherwise, the certificate would have to be replaced each
time before its validity ends.
210 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 211
Development and Extension Guide – Application-Specific Information
2. Import Client Certificate
Caution
Importing the client certificate will not work without the complete certificate chain. Intermediate certificates are
owned only by PayPal. Ask PayPal for these certificates.
A client certificate is a means of authentication. The client certificate uniquely identifies the client (for example,
the SAP system of a Web shop owner) and is used by the server (for example, PayPal) to authenticate the
client.
PayPal authenticates as follows:
The system authenticates using a username, password, and a signature in the SOAP header. This
process is easier to implement and can be used for testing against the PayPal sandbox system.
The system authenticates using a username and a password in the SOAP header and, additionally, the
client certificate. This process is more secure and can be used for productive use.
The second option provides additional security. The disadvantage of the second option is the additional effort
of installing the client certificate.
Caution
Providing any credentials in the SOAP header in plain text is not secure because this data can be traced, for
example in the XML Monitor (transaction SXMB_MONI) or in the ICF recorder. Therefore, neither the first nor
the second options meet SAP security standards.
212 October 2013
Development and Extension Guide – Application-Specific Information
Download the client certificate from PayPal and install it in the SAP system as follows:
a. Open a Web browser.
b. Go to your PayPal merchant account.
c. Download the PayPal client certificate.
d. Import this certificate into your SAP system (transaction STRUST).
e. Import all intermediate certificates of the certificate chain from the downloaded one to the root
certification authority.
Caution
All PayPal intermediate certificates are needed.
Additional information from PayPal:
Requesting an API Certificate:
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/apicertificates
3. (If Applicable) Configure HTTP Destination
Note
In later versions, the destination concept was deprecated.
Configure the HTTP Destination as follows to support SSL encryption:
a. Open the logical port for the service consumer CO_PAY_PAL_APIINTERFACE.
b. Choose the Additional Information tab.
c. Copy the HTTP destination.
d. Enter RFC and HTTP destinations (transaction SM59).
e. Search for the HTTP destination that you copied previously.
f. Choose the Logon & Security tab.
g. Choose the Default SSL Client SSL certificate.
h. Save your entries.
i. Repeat this procedure for the logical port of the service consumer
CO_PAY_PAL_APIAAINTERFACE.
October 2013 213
Development and Extension Guide – Application-Specific Information
The following figures show an example of how you can configure the HTTP destination.
214 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 215
Development and Extension Guide – Application-Specific Information
216 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 217
Development and Extension Guide – Application-Specific Information
4. Test connection
Test the connection to the PayPal Web service as follows:
a. Enter transaction SM59.
b. Open the HTTP connection for the logical port.
c. Test the connection.
If the logical port, the HTTP connection, the server certificate, and the client certificate are set up correctly, an
HTTP response should be received (see second screenshot below).
Caution
The test needs to be executed for each logical port. There are two logical ports for the PayPal integration.
Note
It does not matter if errors are returned in the status text, the response body, or the response text (see third
screenshot below). No actual data is transferred to the Web service. Therefore, it is likely that an error is
returned. This is not a problem. The connection test only shows whether the connection between the SAP
system and the PayPal system is working.
Note
If you get an error or you do not get a response, the connection is not set up correctly. In most cases, the
server or client certificate is not imported correctly or the proxy settings in the logical port are not correct.
218 October 2013
Development and Extension Guide – Application-Specific Information
October 2013 219
Development and Extension Guide – Application-Specific Information
If the logical port, the HTTP connection, the server certificate, and the client certificate are set up correctly, an
HTTP response should be received as shown in the following figure:
220 October 2013
Development and Extension Guide – Application-Specific Information
It does not matter if errors are returned in the status text, the response body, or the response text as shown in
the following figure (No data is transferred to the Web service).
6.1.2.7 Best Practices for Debugging
Check XML Sent to Web Service
Check the XML that will be sent to the Web service in the debugger tTranslate ABAP to XML request) as follows:
1. Set a breakpoint in the class method CL_SOAP_MESSAGE_NEW->
IF_SOAP_MESSAGE_PART~SERIALIZE in line 200.
2. Choose F6 to execute the method GET_XML_WRITER_OUTPUT.
3. Check the parameter XMLOUT.
4. Change the view of the parameter value to XML.
The following figure shows the SOAP message sent to the Web service:
October 2013 221
Development and Extension Guide – Application-Specific Information
The following figure shows where you change the view of the parameter value to XML:
222 October 2013
Development and Extension Guide – Application-Specific Information
Checking XML Received from Web Service
Check the XML that was received from the Web service in the debugger (translate XML response to ABAP) as
follows:
1. Set a breakpoint in the class method CL_SXMLP_LIST->_READ_CHILDREN in line 26.
2. Do not execute the method DESERIALIZE yet.
3. Check the READER parameter.
4. Check the M_INPUT attribute of the parameter.
5. Change the view of the attribute value to XML.
The system shows the SOAP message that was received from the Web service.
The following figure shows line 26 and the reader parameter in the debugger:
October 2013 223
Development and Extension Guide – Application-Specific Information
The following figure shows the M_INPUT attribute:
224 October 2013
Development and Extension Guide – Application-Specific Information
The following figure shows where you change the view of the attribute value to XML:
October 2013 225
Development and Extension Guide – Application-Specific Information
6.1.2.8 Tips
This section provides helpful tips when errors occur in the Web service integration.
6.1.2.8.1 Issues with Web Service Proxy Generation
The subsections below examine common errors during the Web service proxy generation and how they can be fixed.
Infinite Loop in WSDL Parser
Should the WSDL parser not return, this is most likely due to an infinite loop because of mutual schema imports.
Syntax Error: Invalid Attribute
If the following exception is returned during the proxy generation, this is most likely due to an XML attribute that is not
defined correctly in the WSDL document (see technical section):
“Exception occurred in library handler
Illegal syntax: Element definitions has invalid enhancement attribute
urn:ebay:api:PayPalAPI:version"
The following figure shows the exception in the Object Navigtor:
226 October 2013
Development and Extension Guide – Application-Specific Information
No Use Access for Objects from Another Package
If the following error is returned when activating the proxy, this is most likely due to missing package interfaces:
“Package Check for Table/Structure ABSTRACT_REQUEST_TYPE
The object TABL ABSTRACT_REQUEST_TYPE uses DTEL XSDANY
Data Element XSDANY
There is no use access for the object from another structure package”
The following figure shows the syntax error:
To solve this issue, add the following on the User Access tab of both the package and the structure package:
SABP_TRFO: Data element XSDANY and XSDDATETIME_Z
SAI_PROXY_PUBLIC: Table type PRXCTRLTAB
6.1.2.8.2 Issues with Firewalls
The IP address for PayPal servers is as follows: https://ppmts.custhelp.com/app/answers/detail/a_id/92
October 2013 227
Development and Extension Guide – Application-Specific Information
6.1.2.8.3 Issues with Web Service Proxies
The following subsections explain common errors during Web service communication and how they can be fixed.
Issue with Mandatory Attributes
Parameters can be specified in the WSDL file using a minimum and maximum occurrence. If the minimum occurrence
is not specified, this means that it equals one. Mandatory attributes have a minimum occurrence of one. This
information is used by the Web service proxy and is shown in the following figure:
If a mandatory parameter is not passed to the Web service proxy, there will be an error. This can be fixed easily by
passing the parameter.
If a mandatory parameter is not returned from the Web service, there will be an error in the XML transformation in the
back end (in the case of the parameter EBAY_TRANSACTION_ID, this is an error in the PayPal WSDL file). The
parameter is not returned by PayPal in the method GET_TRANSACTION_DETAILS because it is not relevant there.
However, it is marked in the WSDL file as mandatory and hence the XML transformation expects it to be returned.
The workaround for this issue is to enter a minimum occurrence of zero for the attribute zero (see technical section).
SSL Connection Issue
If the following error is returned when making a connection to the Web service, this is because the secure connection
is not set up correctly (see Customizing section). Check whether the server certificate was installed successfully in
transaction STRUST.
“SOAP:1.023 SRT: Processing error in Internet Communication Framework:
("ICF Error when receiving the response: ICM_HTTP_SSL_ERROR")”
228 October 2013
Development and Extension Guide – Application-Specific Information
6.1.3 SAP ERP E-Commerce
In the E-Commerce SAP ERP back end scenario, order management, order fulfillment, billing, and financials are
completed in the SAP ERP back end. You do all configuration and BAdI implementation in the SAP ERP back end.
The following figure shows the scenario:
The order in the SAP ERP back end gets status information from the payment service provider using the payment
service provider interface (PSP IF). The system passes status information by way of billing to financials where
settlement takes place.
October 2013 229
Development and Extension Guide – Application-Specific Information
Consider the following activities when using the E-Commerce SAP ERP back-end integration scenario.
1. Activate business function in the SAP ERP back end.
Activate the ERP_WEB_CHANNEL_1 business function.
2. Maintain Customizing for PSP integration in the SAP ERP back end.
Make the settings in Customizing for SAP ERP under Sales and Distribution -> SAP Web Channel Experience
Management -> Payment Service Prov.
3. Implement BAdI Integration of Payment Service Providers in the SAP ERP back end.
Make sure you make the settings in Customizing for SAP ERP under Sales and Distribution -> SAP Web
Channel Experience Management -> Payment Service Prov. -> Business Add-Ins (BAdIs).
As a prerequisite, you must have already implemented all relevant proxy calls to the Web services provided
by the payment service provider (see subsection Call to the Proxy in section Creating Web Service Wrapper).
For more information, see Sample Implementation of BAdI 'Integration of Payment Service Providers' in the
SAP ERP Back End.
4. Implement BAdI Import Settlement Files for Each Payment Service Provider.
You can use this BAdI to import settlement files from different payment service providers into the system.
Further processing takes place in the electronic account statement.
The BAdI is always called when a user executes the following transaction: Import Settlement File of
Payment Service Provider (transaction FEBPS).
To import the settlement file, the READ_PAYSP_SETTLEMENT_FILE method must be implemented.
The payment service provider's ID serves as a filter value in the implementation.
Caution
PayPal requires activation to receive the settlement file. In addition, you must enter an FTP user and
password.
For more information, see Sample Implementation of BAdI 'Import Settlement Files for Each Payment
Service Provider'.
5. Schedule periodic tasks in the SAP ERP back end.
Use program SLS_LPAYSP_DOCUMENT_UPDATE (transaction VPP1) to identify and process incomplete
sales orders and service orders in the SAP ERP back end that Web shop customers create using payment
service providers. For more information, see the online documentation for the program.
230 October 2013
Development and Extension Guide – Application-Specific Information
6.1.3.1 Sample Implementation of BAdI 'Import Settlement Files for Each Payment Service Provider'
The following code is an example for IF_EX_FPS_IMPORT_PAYSP_FILE~READ_PAYSP_SETTLEMENT_FILE.
method IF_EX_FPS_IMPORT_PAYSP_FILE~READ_PAYSP_SETTLEMENT_FILE.
data: l_t_auszug type zfps_t_char800,
lsep(3) type c,
lsep1(2) type c,
lsep2(2) type c,
sart(2) type c,
ls_t012k type t012k,
l_db_cr_ind(2),
l_db_cr_ind_fee(2),
l_curr_iso(3),
l_date(8),
l_waer type waers,
l_betrag type ssbtr_eb,
field_tab type zpaypal_t_char35,
ls_field_type type zpaypal_char35,
value_tab type zpaypal_t_value,
ls_value type zpaypal_value,
ls_febko type febko,
l_count type i value 0,
l_absnd(50),
ls_auszug type fps_header,
ls_umsatz type fps_item,
ls_bapiret type bapiret2,
l_item_count type i value 0.
field-symbols: <line> type any.
*------------------------------------------------------------------------------------------
refresh: et_items, et_header.
clear: ls_t012k, ls_auszug.
*--- Upload File
CALL METHOD me->upload_data
EXPORTING
i_pfname = i_pfname
IMPORTING
e_auszug = l_t_auszug.
check not l_t_auszug is initial.
*---
CALL FUNCTION 'GET_BANK_ACCOUNT'
EXPORTING
i_bankl = i_bank
i_bankn = i_account
IMPORTING
e_t012k = ls_t012k
EXCEPTIONS
October 2013 231
Development and Extension Guide – Application-Specific Information
input_wrong = 1
bank_account_not_found = 2
bank_key_false = 3
bank_key_not_found = 4
currency_false = 5
currency_not_found = 6
multiple_bank_account = 7
account_type_false = 8
account_type_not_found = 9
others = 10.
if sy-subrc = 0.
CALL METHOD me->determine_decimals
EXPORTING
i_waers = ls_t012k-waers.
move ls_t012k-waers to ls_auszug-waers.
l_absnd(15) = i_bank.
l_absnd+15 = i_account.
l_absnd+45 = ls_t012k-waers.
*-- Statement number not provided => take last statement no + 1 --
select * from febko into ls_febko
where anwnd = '0001'
and absnd = l_absnd
order by aznum descending.
exit.
endselect.
if sy-subrc <> 0. "First Stmt
ls_auszug-aznum = 1. "Set Stmt Number
else.
ls_auszug-aznum = ls_febko-aznum + 1. "Set Statement Number
endif.
else.
exit.
endif.
if not ls_febko is initial.
*-- START SALDO
*-- make end saldo of the previous statement as new start saldo of of the current statement
move ls_febko-esbtr to ls_auszug-ssald.
if ls_febko-esvoz = 'S'.
multiply ls_auszug-ssald by -1.
endif.
endif.
ls_auszug-bank = i_bank.
ls_auszug-ktonr = i_account.
concatenate '"' gd_separator '"' into lsep.
concatenate '"' gd_separator into lsep1.
concatenate gd_separator '"' into lsep2.
*--------------------------------------------------------------------------------------
loop at l_t_auszug assigning <line>.
232 October 2013
Development and Extension Guide – Application-Specific Information
*-- clean-up line from the redundant characters
while sy-subrc = 0.
replace lsep1 with gd_separator into <line>.
endwhile.
sy-subrc = 0.
while sy-subrc = 0.
replace lsep2 with gd_separator into <line>.
endwhile.
if <line>+0(1) = '"'.
shift <line> left by 1 places.
endif.
sy-subrc = 0.
while sy-subrc = 0.
replace '"' with '' into <line>.
endwhile.
sart = <line>+0(2).
if sart = 'SH'.
add 1 to l_count.
if l_count ne 1.
*--- only one paypal file is processed
exit.
endif.
clear: value_tab[].
split <line> at gd_separator into table value_tab.
loop at value_tab into ls_value.
case sy-tabix.
when '2'.
if not ls_value-content is initial.
clear l_date.
l_date(4) = ls_value-content(4).
l_date+4(2) = ls_value-content+5(2).
l_date+6(2) = ls_value-content+8(2).
move l_date to ls_auszug-azdat.
endif.
endcase.
endloop.
endif.
*---- Get Variable names
if sart = 'CH'.
clear field_tab[].
split <line> at gd_separator into table field_tab.
endif.
*---- Get values of the variables
if sart = 'SB'.
add 1 to l_item_count.
clear: value_tab[], ls_umsatz.
split <line> at gd_separator into table value_tab.
clear l_db_cr_ind.
loop at value_tab into ls_value.
read table field_tab into ls_field_type index sy-tabix.
October 2013 233
Development and Extension Guide – Application-Specific Information
check sy-subrc = 0.
case ls_field_type-name.
when 'InvoiceID'.
if not ls_value-content is initial.
move ls_value-content to ls_umsatz-vwz01.
endif.
when 'TransactionID'.
if not ls_value-content is initial.
move ls_value-content to ls_umsatz-vwz03.
endif.
when 'CustomField'. "GUID
if not ls_value-content is initial.
move ls_value-content to ls_umsatz-vwz02.
endif.
when 'TransactionDebitOrCredit'.
if not ls_value-content is initial.
move ls_value-content to l_db_cr_ind.
endif.
when 'GrossTransactionCurrency'.
*-- conversion from iso to sap
if not ls_value-content is initial.
move ls_value-content to l_curr_iso.
CALL FUNCTION 'CURRENCY_CODE_ISO_TO_SAP'
EXPORTING
iso_code = l_curr_iso
IMPORTING
sap_code = l_waer.
if l_waer ne ls_auszug-waers.
break ayat.
MESSAGE e001(ZPAYPAL) WITH l_waer ls_t012k-waers l_item_count .
endif.
move l_waer to ls_umsatz-waers.
endif.
when 'GrossTransactionAmount'.
if not ls_value-content is initial.
* move ls_value-content to ls_umsatz-WRBTR.
clear l_betrag.
CALL METHOD me->trunc_decimals
EXPORTING
amount = ls_value-content
IMPORTING
e_amount = l_betrag.
move l_betrag to ls_umsatz-wrbtr.
endif.
when 'TransactionEventCode'.
*T0006 Express Checkout APIs (incoming payment at merchant)
234 October 2013
Development and Extension Guide – Application-Specific Information
*T1107 Payment Refund initiated by merchant (triggered by cancellation)
if ls_value-content = 'T0006' or ls_value-content = 'T1107'.
move ls_value-content to ls_umsatz-gcode.
else.
clear ls_umsatz.
continue.
endif.
when 'TransactionCompletionDate'.
if not ls_value-content is initial.
clear l_date.
l_date(4) = ls_value-content(4).
l_date+4(2) = ls_value-content+5(2).
l_date+6(2) = ls_value-content+8(2).
move l_date to: ls_umsatz-valut, ls_umsatz-bvdat.
endif.
*FeeDebitOrCredit
when 'FeeDebitOrCredit'.
if not ls_value-content is initial.
move ls_value-content to l_db_cr_ind_fee.
endif.
*FeeAmount
when 'FeeAmount'.
if not ls_value-content is initial.
clear l_betrag.
CALL METHOD me->trunc_decimals
EXPORTING
amount = ls_value-content
IMPORTING
e_amount = l_betrag.
move l_betrag to ls_umsatz-spesk.
endif.
*FeeCurrency
endcase.
endloop.
if not ls_umsatz is initial.
ls_umsatz-bank = ls_auszug-bank.
ls_umsatz-ktonr = ls_auszug-ktonr.
ls_umsatz-aznum = ls_auszug-aznum.
if l_db_cr_ind = g_credit.
ls_umsatz-wrbtr = ls_umsatz-wrbtr - ls_umsatz-spesk.
add ls_umsatz-wrbtr to ls_auszug-sumha.
elseif l_db_cr_ind = g_debit.
ls_umsatz-wrbtr = ls_umsatz-wrbtr + ls_umsatz-spesk.
add ls_umsatz-wrbtr to ls_auszug-sumso.
multiply ls_umsatz-wrbtr by -1.
endif.
append ls_umsatz to et_items.
October 2013 235
Development and Extension Guide – Application-Specific Information
endif.
endif.
endloop.
*-- END SALDO
*-- SUM OF SUMHA&SUMSO&SSALD with signs into ESALD
ls_auszug-esald = ls_auszug-ssald - ls_auszug-sumso + ls_auszug-sumha.
if not et_items is initial.
append ls_auszug to et_header.
else.
MESSAGE i002(ZPAYPAL).
endif.
endmethod.
6.1.3.2 Sample Implementation of BAdI 'Integration of Payment Service Providers' in the SAP ERP Back
End
The following code is a sample implementation. In this sample implementation, the Web service calls are
encapsulated in class ZCL_COMMON_PAYPAL_API (see section Sample Implementation of BAdI 'Integration of
Payment Service Providers' in the SAP CRM Back End).
Sample BAdI Implementation ZCL_ERP_PAYPAL_IMPL:
class ZCL_ERP_PAYPAL_IMPL definition
public
final
create public .
public section.
*"* public components of class ZCL_ERP_PAYPAL_IMPL
*"* do not include other source files here!!!
interfaces IF_BADI_INTERFACE .
interfaces IF_COM_WEC_PSP_INTEGRATION .
protected section.
*"* protected components of class ZCL_ERP_PAYPAL_IMPL
*"* do not include other source files here!!!
private section.
*"* private components of class ZCL_ERP_PAYPAL_IMPL
*"* do not include other source files here!!!
types:
begin of LTY_PSP_SHIPPIG_ADDRESS .
types TITLE TYPE AD_TITLE.
types NAME_FIRST TYPE AD_NAMEFIR.
types NAME_LAST TYPE AD_NAMELAS.
types NAME2_P TYPE AD_NAME2_P.
types NAMEMIDDLE TYPE AD_NAMEMID.
types NAME_LAST2 TYPE AD_NAMLAS2.
types NICKNAME TYPE AD_NICKNAM.
types INITIALS TYPE AD_INITS.
types NAME1 TYPE AD_NAME1.
types NAME2 TYPE AD_NAME2.
236 October 2013
Development and Extension Guide – Application-Specific Information
types NAME3 TYPE AD_NAME3.
types NAME4 TYPE AD_NAME4.
types CITY1 TYPE AD_CITY1.
types CITY2 TYPE AD_CITY2.
types HOME_CITY TYPE AD_CITY3.
types POST_CODE1 TYPE AD_PSTCD1.
types POST_CODE2 TYPE AD_PSTCD2.
types POST_CODE3 TYPE AD_PSTCD3.
types PCODE1_EXT TYPE AD_PST1XT.
types PCODE2_EXT TYPE AD_PST2XT.
types PCODE3_EXT TYPE AD_PST3XT.
types PO_BOX TYPE AD_POBX.
types PO_BOX_NUM TYPE AD_POBXNUM.
types PO_BOX_LOC TYPE AD_POBXLOC.
types PO_BOX_REG TYPE AD_POBXREG.
types PO_BOX_CTY TYPE AD_POBXCTY.
types STREET TYPE AD_STREET.
types HOUSE_NUM1 TYPE AD_HSNM1.
types HOUSE_NUM2 TYPE AD_HSNM2.
types HOUSE_NUM3 TYPE AD_HSNM3.
types STR_SUPPL1 TYPE AD_STRSPP1.
types STR_SUPPL2 TYPE AD_STRSPP2.
types STR_SUPPL3 type AD_STRSPP3.
types LOCATION type AD_LCTN.
types BUILDING type AD_BLDNG.
types FLOOR type AD_FLOOR.
types ROOMNUMBER type AD_ROOMNUM.
types COUNTRY type LAND1.
types REGION type REGIO.
types TAXJURCODE type AD_TXJCD.
types end of LTY_PSP_SHIPPIG_ADDRESS .
class-data GC_SIGNATURE type STRING value `YourPayPalTestAccountSignature`. "#EC NOTEXT .
class-data GC_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME value SPACE. "#EC NOTEXT .
class-data GC_MESSAGE_ID type SYMSGID value 'ZERP_WEC_PAYPAL_IMPL'. "#EC NOTEXT .
class-data GC_PAYPAL_CHECKOUT_URL type STRING value
`https://www.sandbox.paypal.com/webscr&cmd=_express-checkout&token=`. "#EC NOTEXT .
class-data GC_PAYPAL_PAYMENT_STATUS_COMP type COM_WEC_PAYPAL_PAYMENT_STATUS value `Completed`.
"#EC NOTEXT .
class-data GC_PAYPAL_PAYMENT_STATUS_DENI type COM_WEC_PAYPAL_PAYMENT_STATUS value `Denied`.
"#EC NOTEXT .
class-data GC_PAYPAL_PAYMENT_STATUS_NONE type COM_WEC_PAYPAL_PAYMENT_STATUS value `None`. "#EC
NOTEXT .
class-data GC_PAYPAL_PAYMENT_STATUS_PEND type COM_WEC_PAYPAL_PAYMENT_STATUS value `Pending`.
"#EC NOTEXT .
class-data GC_PAYPAL_PAYMENT_STATUS_REFU type COM_WEC_PAYPAL_PAYMENT_STATUS value `Refunded`.
"#EC NOTEXT .
class-data GC_TXN_PROFILE type COM_WEC_TRANSACTION_PROFILE value 'PF01'. "#EC NOTEXT .
class-data GC_TXN_STATUS_COMP type COM_WEC_TRANSACTION_STATUS value 'COMP'. "#EC NOTEXT .
class-data GC_TXN_STATUS_PEND type COM_WEC_TRANSACTION_STATUS value 'PEND'. "#EC NOTEXT .
class-data GC_TXN_STATUS_REJE type COM_WEC_TRANSACTION_STATUS value 'REJE'. "#EC NOTEXT .
data GC_TXN_STATUS_RFND type COM_WEC_TRANSACTION_STATUS value 'RFND'. "#EC NOTEXT .
data MV_USERNAME type STRING .
data MV_PASSWORD type STRING .
October 2013 237
Development and Extension Guide – Application-Specific Information
data MV_TOKEN type COM_WEC_PAYPAL_TOKEN .
class-data GC_PROCESS_STATUS_CONFIRMED type STRING value 'confirmed'. "#EC NOTEXT .
type-pools ABAP .
methods SEARCH_TRANSACTION_BY_REF_ID
importing
!IV_REFERENCE_ID type COM_WEC_TRANSACTION_ID
exporting
!EV_ERROR_OCCURRED type ABAP_BOOL
!EV_TRANSACTION_EXISTS type ABAP_BOOL
!EV_PAYPAL_TRANSACTION_ID type COM_WEC_PAYPAL_TRANSACTION_ID
changing
!CT_MESSAGES type COMT_WEC_MESSAGES
!CT_SYSLOG_MESSAGES type COMT_WEC_MESSAGES .
class-methods ADD_MESSAGE
importing
!IV_TYPE type BAPI_MTYPE
!IV_ID type SYMSGID default GC_MESSAGE_ID
!IV_NUMBER type SYMSGNO
!IV_MESSAGE_V1 type SIMPLE optional
!IV_MESSAGE_V2 type SIMPLE optional
!IV_MESSAGE_V3 type SIMPLE optional
!IV_MESSAGE_V4 type SIMPLE optional
changing
!CT_MESSAGES type COMT_WEC_MESSAGES optional .
class-methods GET_PAYER_ID
importing
!IT_PARAMETERS type COMT_WEC_HTTP_PARAMETERS
!IT_NAME_VALUE type COMT_WEC_PSP_NAME_VALUE_PAIR
returning
value(RV_PAYER_ID) type COM_WEC_PAYPAL_PAYER_ID .
class-methods GET_SHIPTO_ADDRESS
importing
!IS_SHIPPING_ADDRESS type ANY
returning
value(RS_SHIPTO_ADDRESS) type COMS_WEC_PAYPAL_SHIPTO_ADDRESS .
methods IS_TOKEN_VALID
importing
!IT_PARAMETERS type COMT_WEC_HTTP_PARAMETERS
!IT_NAME_VALUE type COMT_WEC_PSP_NAME_VALUE_PAIR
returning
value(RV_TOKEN_VALID) type ABAP_BOOL .
class-methods IS_TRANSACTION_CONFIRMED
importing
!IT_PARAMETERS type COMT_WEC_HTTP_PARAMETERS
!IT_NAME_VALUE type COMT_WEC_PSP_NAME_VALUE_PAIR
returning
value(RV_TRANSACTION_CONFIRMED) type COM_WEC_PAYPAL_PAYER_ID .
class-methods ADD_API_MESSAGES
importing
!IT_API_MESSAGES type BAPIRET2_TAB
changing
!CT_MESSAGES type COMT_WEC_MESSAGES .
238 October 2013
Development and Extension Guide – Application-Specific Information
class-methods COUNTRY_SAP2PP
importing
!IV_COUNTRY type LAND1
returning
value(RV_COUNTRY) type STRING .
class-methods REGION_SAP2PP
importing
!IV_REGIO type REGIO
!IV_COUNTRY type LAND1
returning
value(RV_REGIO_PP) type STRING .
class-methods GET_DEFAULT_USERNAME
returning
value(RV_USERNAME) type STRING .
class-methods GET_DEFAULT_PASSWORD
returning
value(RV_PASSWORD) type STRING .
ENDCLASS.
CLASS ZCL_ERP_PAYPAL_IMPL IMPLEMENTATION.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->ADD_API_MESSAGES
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method ADD_API_MESSAGES.
* Add API messages to message table
DATA ls_message LIKE LINE OF ct_messages.
FIELD-SYMBOLS <ls_api_message> LIKE LINE OF it_api_messages.
LOOP AT it_api_messages ASSIGNING <ls_api_message>.
CLEAR ls_message.
MOVE-CORRESPONDING <ls_api_message> TO ls_message.
INSERT ls_message INTO TABLE ct_messages.
ENDLOOP.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->ADD_MESSAGE
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method ADD_MESSAGE.
* Add a message to table CT_MESSAGES
October 2013 239
Development and Extension Guide – Application-Specific Information
DATA ls_message LIKE LINE OF ct_messages.
ls_message-type = iv_type.
ls_message-id = iv_id.
ls_message-number = iv_number.
ls_message-message_v1 = iv_message_v1.
ls_message-message_v2 = iv_message_v2.
ls_message-message_v3 = iv_message_v3.
ls_message-message_v4 = iv_message_v4.
MESSAGE ID iv_id
TYPE iv_type
NUMBER iv_number
WITH iv_message_v1 iv_message_v2 iv_message_v3 iv_message_v4
INTO ls_message-message.
INSERT ls_message INTO TABLE ct_messages.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->CONSTRUCTOR
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->COUNTRY_SAP2PP
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method COUNTRY_SAP2PP.
DATA lv_country_iso TYPE INTCA.
CALL FUNCTION 'COUNTRY_CODE_SAP_TO_ISO'
EXPORTING
sap_code = iv_country
IMPORTING
ISO_CODE = lv_country_iso
EXCEPTIONS
NOT_FOUND = 1
OTHERS = 2
.
IF sy-subrc <> 0.
rv_country = iv_country.
ELSE.
rv_country = lv_country_iso.
ENDIF.
endmethod.
240 October 2013
Development and Extension Guide – Application-Specific Information
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->GET_DEFAULT_PASSWORD
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_DEFAULT_PASSWORD.
* detmermine the default password
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->GET_DEFAULT_USERNAME
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_DEFAULT_USERNAME.
* determine the default username
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->GET_PAYER_ID
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_PAYER_ID.
* Get the payer ID of the PayPal customer; this is passed in by PayPal in the
* redirect to the Web Channel
FIELD-SYMBOLS <ls_parameter> TYPE coms_wec_http_parameter.
FIELD-SYMBOLS <lv_payer_id> TYPE string.
FIELD-SYMBOLS <fs_name_value> TYPE coms_wec_psp_name_value_pair.
DATA dref TYPE REF TO coms_wec_http_parameter.
DATA lv_subrc TYPE sysubrc.
CLEAR rv_payer_id.
* Get the payer ID from the HTTP parameters passed in by PayPal
READ TABLE it_parameters ASSIGNING <ls_parameter> WITH TABLE KEY name = `PayerID`.
lv_subrc = sy-subrc.
IF lv_subrc NE 0.
CREATE DATA dref.
ASSIGN dref->* TO <ls_parameter>.
READ TABLE it_name_value ASSIGNING <fs_name_value> WITH KEY name = `payerID`.
lv_subrc = sy-subrc.
IF lv_subrc EQ 0.
<ls_parameter>-name = <fs_name_value>-name.
October 2013 241
Development and Extension Guide – Application-Specific Information
INSERT <fs_name_value>-value INTO TABLE <ls_parameter>-values.
ENDIF.
ENDIF.
* We expect exactly one value for the payer id
IF sy-subrc = 0 AND lines( <ls_parameter>-values ) = 1.
READ TABLE <ls_parameter>-values ASSIGNING <lv_payer_id> INDEX 1.
IF sy-subrc = 0.
rv_payer_id = <lv_payer_id>.
ENDIF.
ENDIF.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->GET_SHIPTO_ADDRESS
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_SHIPTO_ADDRESS.
DATA ls_shipping_address TYPE lty_psp_shippig_address.
DATA lv_name_string TYPE string.
* Convert the internal shipping address to the PayPal shipto address
MOVE-CORRESPONDING is_shipping_address TO ls_shipping_address.
IF ls_shipping_address-name1 IS NOT INITIAL.
lv_name_string = ls_shipping_address-name1.
ENDIF.
IF ls_shipping_address-name2 IS NOT INITIAL.
lv_name_string = lv_name_string && ` ` && ls_shipping_address-name2.
ENDIF.
IF ls_shipping_address-name3 IS NOT INITIAL.
lv_name_string = lv_name_string && ` ` && ls_shipping_address-name3.
ENDIF.
IF ls_shipping_address-name4 IS NOT INITIAL.
lv_name_string = lv_name_string && ` ` && ls_shipping_address-name4.
ENDIF.
IF lv_name_string IS INITIAL.
lv_name_string = ls_shipping_address-name_first.
IF ls_shipping_address-namemiddle IS NOT INITIAL.
lv_name_string = lv_name_string && ` ` && ls_shipping_address-namemiddle.
ENDIF.
IF ls_shipping_address-name_last IS NOT INITIAL.
lv_name_string = lv_name_string && ` ` && ls_shipping_address-name_last.
ENDIF.
IF ls_shipping_address-name_last2 IS NOT INITIAL.
lv_name_string = lv_name_string && ` ` && ls_shipping_address-name_last2.
ENDIF.
242 October 2013
Development and Extension Guide – Application-Specific Information
ENDIF.
CLEAR rs_shipto_address.
rs_shipto_address-name = lv_name_string.
rs_shipto_address-street1 = ls_shipping_address-street.
rs_shipto_ADDRESS-STREET2 = ls_shipping_address-str_suppl1.
rs_shipto_address-city_name = ls_shipping_address-city1.
rs_shipto_address-state_or_province = region_sap2pp(
iv_regio = ls_shipping_address-region
iv_country = ls_shipping_address-country ).
rs_shipto_address-country = country_sap2pp(
iv_country = ls_shipping_address-country ).
rs_shipto_address-postal_code = ls_shipping_address-post_code1.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Public Method ZCL_ERP_PAYPAL_IMPL->IF_COM_WEC_PSP_INTEGRATION~CANCEL_TRANSACTION
* +---------------------------------------------------------------------------------------------
----+
* | [--->] IS_REFERENCE_DOCUMENT TYPE COMS_WEC_BUSINESS_OBJECT
* | [--->] IV_REFERENCE_GUID TYPE COM_WEC_TRANSACTION_GUID
* | [--->] IV_REFERENCE_ID TYPE COM_WEC_TRANSACTION_ID
* | [--->] IV_PSP_TRANSACTION_ID TYPE COM_WEC_PSP_TRANSACTION_ID
* | [<---] ER_ACTION TYPE REF TO CL_COM_WEC_CANCEL_TRANS_PARAM
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD if_com_wec_psp_integration~cancel_transaction.
* Refund a PayPal transaction after cancelling the corresponding order
DATA lv_paypal_original_trans_id TYPE com_wec_paypal_transaction_id.
DATA lv_paypal_refund_trans_id TYPE com_wec_paypal_transaction_id.
DATA lv_psp_refund_trans_id TYPE com_wec_psp_transaction_id.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lv_api_success TYPE abap_bool.
DATA lt_messages TYPE comt_wec_messages.
DATA lt_syslog_messages TYPE comt_wec_messages.
************************************************************************
* Call Sandbox
" Call Sandbox System
" Convert the original transaction ID of the payment to be refunded
lv_paypal_original_trans_id = iv_psp_transaction_id.
" Call the PayPal refund API
ZCL_COMMON_PAYPAL_API=>refund_transaction(
EXPORTING
iv_username = get_default_username( )
iv_password = get_default_password( )
iv_signature = gc_signature
iv_logical_port = gc_logical_port
October 2013 243
Development and Extension Guide – Application-Specific Information
iv_transaction_id = lv_paypal_original_trans_id
iv_refund_type = ZCL_COMMON_PAYPAL_API=>gc_refund_type_full
IMPORTING
ev_refund_trans_id = lv_paypal_refund_trans_id
et_messages = lt_api_messages
ev_success = lv_api_success ).
* If refund successfull, finalize the cancellation
IF lv_api_success = abap_true.
* Convert the refund transaction ID to the internal format
lv_psp_refund_trans_id = lv_paypal_refund_trans_id.
CREATE OBJECT er_action TYPE cl_com_wec_finalize_cancel
EXPORTING
iv_transaction_status_profile = 'PF01'
iv_transaction_status = 'RFND'.
* If an error occured, schedule for later reprocessing
ELSE.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'RefundTransaction'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'RefundTransaction'
CHANGING
ct_messages = lt_syslog_messages ).
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_cancel
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
ENDIF.
ENDMETHOD.
244 October 2013
Development and Extension Guide – Application-Specific Information
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Public Method ZCL_ERP_PAYPAL_IMPL-
>IF_COM_WEC_PSP_INTEGRATION~GET_TRANSACTION_DETAILS
* +---------------------------------------------------------------------------------------------
----+
* | [--->] IS_REFERENCE_DOCUMENT TYPE COMS_WEC_BUSINESS_OBJECT
* | [--->] IV_REFERENCE_GUID TYPE COM_WEC_TRANSACTION_GUID
* | [--->] IV_REFERENCE_ID TYPE COM_WEC_TRANSACTION_ID
* | [--->] IV_PSP_TRANSACTION_ID TYPE COM_WEC_PSP_TRANSACTION_ID
* | [<---] ER_ACTION TYPE REF TO CL_COM_WEC_UPDATE_TRANS_PARAM
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD if_com_wec_psp_integration~get_transaction_details.
* Get PayPal transaction details for an order
DATA lv_psp_transaction_id TYPE com_wec_psp_transaction_id.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lv_api_success TYPE abap_bool.
DATA lt_messages TYPE comt_wec_messages.
DATA lt_syslog_messages TYPE comt_wec_messages.
DATA: lv_vbeln TYPE vbeln,
ls_vbak TYPE vbak,
lr_paysp TYPE REF TO cl_sls_paysp_integration,
ls_paysp_hl TYPE paysp_hl.
* Call Sandbox
* If the PSP transaction ID is given, we assume it is valid and use it to get the transaction
details
DATA lv_error_occurred_in_search TYPE abap_bool.
DATA lv_transaction_exists TYPE abap_bool.
DATA lv_paypal_transaction_id TYPE com_wec_paypal_transaction_id.
DATA lv_paypal_payment_status TYPE com_wec_paypal_payment_status.
IF iv_psp_transaction_id IS NOT INITIAL.
lv_paypal_transaction_id = iv_psp_transaction_id.
* If the refernce ID is given, use it to check if the transaction exists in the PayPal system
ELSEIF iv_reference_id IS NOT INITIAL.
search_transaction_by_ref_id(
EXPORTING
iv_reference_id = iv_reference_id
IMPORTING
ev_error_occurred = lv_error_occurred_in_search
ev_transaction_exists = lv_transaction_exists
ev_paypal_transaction_id = lv_paypal_transaction_id
CHANGING
ct_messages = lt_messages
ct_syslog_messages = lt_syslog_messages ).
* If search failed, reprocess the order later
October 2013 245
Development and Extension Guide – Application-Specific Information
IF lv_error_occurred_in_search = abap_true.
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_update
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* If transaction is not known in the PayPal system, cancel the order
IF lv_transaction_exists = abap_false.
CREATE OBJECT er_action TYPE cl_com_wec_invalidate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* Neither PSP transaction ID or reference ID supplied. Give up because a search by transaction
GUID
* is not supported by PayPal so there is no other option to find the transaction.
ELSE.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 007
iv_message_v1 = 'GET_TRANSACTION_DETAILS'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 007
iv_message_v1 = 'GET_TRANSACTION_DETAILS'
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_update
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* Get transaction details from PayPal
ZCL_COMMON_PAYPAL_API=>get_transaction_details(
EXPORTING
iv_username = get_default_username( )
246 October 2013
Development and Extension Guide – Application-Specific Information
iv_password = get_default_password( )
iv_signature = gc_signature
iv_logical_port = gc_logical_port
iv_transaction_id = lv_paypal_transaction_id
IMPORTING
ev_payment_status = lv_paypal_payment_status
et_messages = lt_api_messages
ev_success = lv_api_success ).
* Put API messages in the application log
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = lt_syslog_messages ).
************************************************************************
* PayPal API call successfull -> process PayPal payment status
IF lv_api_success = abap_true.
lv_psp_transaction_id = lv_paypal_transaction_id.
CASE lv_paypal_payment_status.
* PayPal has no payment status -> cancel corresponding order
WHEN gc_paypal_payment_status_none.
CREATE OBJECT er_action TYPE cl_com_wec_invalidate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal transaction has status completed -> set PSP status accordingly
WHEN gc_paypal_payment_status_comp.
CREATE OBJECT er_action TYPE cl_com_wec_update_transaction
EXPORTING
iv_transaction_status_profile = 'PF01'
iv_transaction_status = 'COMP'
iv_psp_transaction_id = lv_psp_transaction_id
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal transaction has status pending -> set PSP status accordingly
WHEN gc_paypal_payment_status_pend.
CREATE OBJECT er_action TYPE cl_com_wec_update_transaction
EXPORTING
iv_transaction_status_profile = 'PF01'
iv_transaction_status = 'PEND'
iv_psp_transaction_id = lv_psp_transaction_id
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal transaction has status refunded -> set PSP status accordingly
October 2013 247
Development and Extension Guide – Application-Specific Information
WHEN gc_paypal_payment_status_refu.
CREATE OBJECT er_action TYPE cl_com_wec_update_transaction
EXPORTING
iv_transaction_status_profile = 'PF01'
iv_transaction_status = 'RFND'
iv_psp_transaction_id = lv_psp_transaction_id
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal transaction has status denied -> set PSP status to rejected
WHEN gc_paypal_payment_status_deni.
CREATE OBJECT er_action TYPE cl_com_wec_update_transaction
EXPORTING
iv_transaction_status_profile = 'PF01'
iv_transaction_status = 'REJE'
iv_psp_transaction_id = lv_psp_transaction_id
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal returned an unexpected status -> raise an error and reprocess later
WHEN OTHERS.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 004
iv_message_v1 = 'GetTransactionDetails'
iv_message_v2 = lv_paypal_payment_status
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 004
iv_message_v1 = 'GetTransactionDetails'
iv_message_v2 = lv_paypal_payment_status
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_update
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
ENDCASE.
* If an error occured, schedule for later reprocessing
ELSE.
add_message(
EXPORTING
iv_type = 'E'
248 October 2013
Development and Extension Guide – Application-Specific Information
iv_number = 000
iv_message_v1 = 'GetTransactionDetails'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'GetTransactionDetails'
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_update
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
ENDIF.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Public Method ZCL_ERP_PAYPAL_IMPL->IF_COM_WEC_PSP_INTEGRATION~INITIATE_TRANSACTION
* +---------------------------------------------------------------------------------------------
----+
* | [--->] IS_REFERENCE_DOCUMENT TYPE COMS_WEC_BUSINESS_OBJECT
* | [--->] IV_TRANSACTION_AMOUNT TYPE COM_WEC_TRANSACTION_AMOUNT
* | [--->] IV_TRANSACTION_CURRENCY TYPE COM_WEC_TRANSACTION_CURRENCY
* | [--->] IS_SHIPPING_ADDRESS TYPE COMS_WEC_PAYMENT_ADDR
* | [--->] IV_REFERENCE_GUID TYPE COM_WEC_TRANSACTION_GUID
* | [--->] IV_REFERENCE_ID TYPE COM_WEC_TRANSACTION_ID
* | [--->] IV_WEC_SOURCE_URL TYPE STRING
* | [--->] IT_NAME_VALUE TYPE COMT_WEC_PSP_NAME_VALUE_PAIR
* | [<---] ER_ACTION TYPE REF TO CL_COM_WEC_CREATE_TRANS_PARAM
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD if_com_wec_psp_integration~initiate_transaction.
* Initiate a PayPal transaction (call the PayPal web service DoExpressCheckoutPayment
* and redirect the user to the PayPal web site)
DATA lv_return_url TYPE string.
DATA lv_cancel_url TYPE string.
DATA lv_invoice_id TYPE com_wec_paypal_invoice_id.
DATA lv_custom TYPE com_wec_paypal_custom.
DATA lv_target_url TYPE string.
DATA lv_api_success TYPE abap_bool.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lt_messages TYPE comt_wec_messages.
DATA lt_syslog_messages TYPE comt_wec_messages.
* Build the return and cancel URLs
October 2013 249
Development and Extension Guide – Application-Specific Information
lv_return_url = iv_wec_source_url && `sap-wec-pp-status=` && gc_process_status_confirmed.
lv_cancel_url = iv_wec_source_url && `sap-wec-pp-status=cancelled`.
* Fill invoice ID (order number) and custom field (transaction GUID)
lv_invoice_id = iv_reference_id.
lv_custom = iv_reference_guid.
* Call the PayPal API
ZCL_COMMON_PAYPAL_API=>set_express_checkout(
EXPORTING
iv_username = get_default_username( )
iv_password = get_default_password( )
iv_signature = gc_signature
iv_logical_port = gc_logical_port
iv_amount = iv_transaction_amount
iv_currency = iv_transaction_currency
iv_return_url = lv_return_url
iv_cancel_url = lv_cancel_url
iv_invoice_id = lv_invoice_id
iv_custom = lv_custom
IMPORTING
ev_token = mv_token
et_messages = lt_api_messages
ev_success = lv_api_success ).
* If an error occured in the API call, output messages and return to checkout page
IF lv_api_success = abap_false.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'doExpressCheckout'
CHANGING
ct_messages = lt_messages ).
lt_syslog_messages = lt_messages.
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* If the token is initial, ouptut messages and return to checkout page
ELSEIF mv_token IS INITIAL.
add_message(
EXPORTING
250 October 2013
Development and Extension Guide – Application-Specific Information
iv_type = 'E'
iv_number = 001
iv_message_v1 = 'doExpressCheckout'
CHANGING
ct_messages = lt_messages ).
lt_syslog_messages = lt_messages.
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* If no error occured, redirect to PayPal
ELSE.
lv_target_url = `https://www.sandbox.paypal.com/webscr&cmd=_express-checkout&token=` &&
mv_token.
CREATE OBJECT er_action TYPE cl_com_wec_trigger_redirect
EXPORTING
iv_target_url = lv_target_url
it_syslog_messages = lt_syslog_messages.
ENDIF.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Public Method ZCL_ERP_PAYPAL_IMPL->IF_COM_WEC_PSP_INTEGRATION~PROCESS_CALLBACK
* +---------------------------------------------------------------------------------------------
----+
* | [--->] IS_REFERENCE_DOCUMENT TYPE COMS_WEC_BUSINESS_OBJECT
* | [--->] IV_TRANSACTION_AMOUNT TYPE COM_WEC_TRANSACTION_AMOUNT
* | [--->] IV_TRANSACTION_CURRENCY TYPE COM_WEC_TRANSACTION_CURRENCY
* | [--->] IS_SHIPPING_ADDRESS TYPE COMS_WEC_PAYMENT_ADDR
* | [--->] IV_REFERENCE_GUID TYPE COM_WEC_TRANSACTION_GUID
* | [--->] IV_REFERENCE_ID TYPE COM_WEC_TRANSACTION_ID
* | [--->] IV_WEC_TARGET_URL TYPE STRING
* | [--->] IT_PARAMETERS TYPE COMT_WEC_HTTP_PARAMETERS
* | [--->] IT_NAME_VALUE TYPE COMT_WEC_PSP_NAME_VALUE_PAIR
* | [<---] ER_ACTION TYPE REF TO CL_COM_WEC_CREATE_TRANS_PARAM
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD if_com_wec_psp_integration~process_callback.
* Process the redirection from PayPal to the Web Channel
DATA lv_paypal_transaction_id TYPE com_wec_paypal_transaction_id.
October 2013 251
Development and Extension Guide – Application-Specific Information
DATA lv_paypal_payment_status TYPE com_wec_paypal_payment_status.
DATA lv_psp_transaction_id TYPE com_wec_psp_transaction_id.
DATA lv_api_success TYPE abap_bool.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lt_messages TYPE comt_wec_messages.
DATA lt_syslog_messages TYPE comt_wec_messages.
* If the transaction is not confirmed, redirect the user to the checkout page
IF is_transaction_confirmed( it_parameters = it_parameters
it_name_value = it_name_value ) = abap_false.
add_message(
EXPORTING
iv_type = 'I'
iv_number = 002
CHANGING
ct_messages = lt_messages ).
lt_syslog_messages = lt_messages.
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* If the token returned by PayPal is invalid, redirect the user to the checkout page
IF is_token_valid( it_parameters = it_parameters
it_name_value = it_name_value ) = abap_false.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 003
CHANGING
ct_messages = lt_messages ).
lt_syslog_messages = lt_messages.
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* Call the PayPal API
ZCL_COMMON_PAYPAL_API=>do_express_checkout_payment(
EXPORTING
iv_username = get_default_username( )
iv_password = get_default_password( )
iv_signature = gc_signature
252 October 2013
Development and Extension Guide – Application-Specific Information
iv_logical_port =gc_logical_port
iv_amount =iv_transaction_amount
iv_currency =iv_transaction_currency
iv_token =mv_token
iv_payerid =get_payer_id( it_parameters = it_parameters
it_name_value = it_name_value )
is_shipto_address = get_shipto_address( is_shipping_address )
IMPORTING
ev_transaction_id = lv_paypal_transaction_id
ev_payment_status = lv_paypal_payment_status
et_messages = lt_api_messages
ev_success = lv_api_success ).
* If an error occured in the API call, return the user to the checkout page
IF lv_api_success = abap_false.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'doExpressCheckoutPayment'
CHANGING
ct_messages = lt_messages ).
lt_syslog_messages = lt_messages.
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* Convert PayPal transaction ID to SAP internal transaction ID
lv_psp_transaction_id = lv_paypal_transaction_id.
* Check the payment status and finalize the transaction or start over with the checkout
CASE lv_paypal_payment_status.
WHEN gc_paypal_payment_status_comp.
CREATE OBJECT er_action TYPE cl_com_wec_finalize_trans
EXPORTING
iv_transaction_status_profile = gc_txn_profile
iv_transaction_status = gc_txn_status_comp
iv_psp_transaction_id = lv_psp_transaction_id.
WHEN gc_paypal_payment_status_pend.
CREATE OBJECT er_action TYPE cl_com_wec_finalize_trans
EXPORTING
iv_transaction_status_profile = gc_txn_profile
iv_transaction_status = gc_txn_status_pend
October 2013 253
Development and Extension Guide – Application-Specific Information
iv_psp_transaction_id = lv_psp_transaction_id.
WHEN OTHERS.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'doExpressCheckoutPayment'
iv_message_v2 = lv_paypal_payment_status
CHANGING
ct_messages = lt_messages ).
lt_syslog_messages = lt_messages.
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
ENDCASE.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->IS_TOKEN_VALID
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD is_token_valid.
* Check if the token returned by PayPal after the redirect to the Web Channel
* is the same as supplied by the web service SetExpressCheckout
FIELD-SYMBOLS <ls_parameter> TYPE coms_wec_http_parameter.
FIELD-SYMBOLS <lv_token> TYPE string.
FIELD-SYMBOLS <fs_name_value> TYPE coms_wec_psp_name_value_pair.
DATA dref TYPE REF TO coms_wec_http_parameter.
DATA lv_subrc TYPE sysubrc.
rv_token_valid = abap_false.
* Read the URL parameter
READ TABLE it_parameters ASSIGNING <ls_parameter> WITH TABLE KEY name = `token`.
lv_subrc = sy-subrc.
IF lv_subrc NE 0.
CREATE DATA dref.
ASSIGN dref->* TO <ls_parameter>.
READ TABLE it_name_value ASSIGNING <fs_name_value> WITH KEY name = `token`.
lv_subrc = sy-subrc.
IF lv_subrc EQ 0.
254 October 2013
Development and Extension Guide – Application-Specific Information
<ls_parameter>-name = <fs_name_value>-name.
INSERT <fs_name_value>-value INTO TABLE <ls_parameter>-values.
ENDIF.
ENDIF.
* We expect exactly one value for the token
IF lv_subrc = 0 AND lines( <ls_parameter>-values ) = 1.
READ TABLE <ls_parameter>-values ASSIGNING <lv_token> INDEX 1.
IF sy-subrc = 0 AND mv_token = <lv_token>.
rv_token_valid = abap_true.
ENDIF.
ENDIF.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->IS_TRANSACTION_CONFIRMED
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD is_transaction_confirmed.
* Check if the payment transaction was confirmed by the payer
FIELD-SYMBOLS <ls_parameter> TYPE coms_wec_http_parameter.
FIELD-SYMBOLS <lv_status> TYPE string.
FIELD-SYMBOLS <fs_name_value> TYPE coms_wec_psp_name_value_pair.
DATA dref TYPE REF TO coms_wec_http_parameter.
DATA lv_subrc TYPE sysubrc.
rv_transaction_confirmed = abap_false.
* Get the URL parameter from the HTTP parameters passed in by PayPal
READ TABLE it_parameters ASSIGNING <ls_parameter> WITH TABLE KEY name = `sap-wec-pp-status`.
lv_subrc = sy-subrc.
* We expect exactly one value for the parameter
IF lv_subrc = 0 AND lines( <ls_parameter>-values ) = 1.
READ TABLE <ls_parameter>-values ASSIGNING <lv_status> INDEX 1.
IF sy-subrc = 0 AND <lv_status> = gc_process_status_confirmed.
rv_transaction_confirmed = abap_true.
ENDIF.
ENDIF.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->REGION_SAP2PP
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method REGION_SAP2PP.
October 2013 255
Development and Extension Guide – Application-Specific Information
* region codes of paypal for canada differ from sap region codes(table T005S).
* Map the ones that are differing.
CASE iv_country.
WHEN 'CA'.
CASE iv_regio.
WHEN 'NL'.
rv_regio_pp = 'NF'.
WHEN 'YT'.
rv_regio_pp = 'YK'.
WHEN OTHERS.
rv_regio_pp = iv_regio.
ENDCASE.
WHEN OTHERS.
rv_regio_pp = iv_regio.
ENDCASE.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_ERP_PAYPAL_IMPL->SEARCH_TRANSACTION_BY_REF_ID
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD search_transaction_by_ref_id.
* Search for a PayPal transaction by our reference ID (= PayPal invoice ID). Note
* that searching by our transaction GUID is currently not supported by PayPal's web
* services.
* Possible return values:
* EV_ERROR_OCCURRED = ABAP_FALSE and EV_TRANSACTION_EXISTS = ABAP_TRUE
* -> Transaction does exist in the PayPal system. Transaction ID returned in
EV_PAYPAL_TRANSACTION_ID
*
* EV_ERROR_OCCURRED = ABAP_FALSE and EV_TRANSACTION_EXISTS = ABAP_FALSE
* -> Transaction does not exist in the PayPal system.
*
* EV_ERROR_OCCURRED = ABAP_TRUE
* -> An error occured when searching in the PayPal system; cannot tell if transactoin
* exists or not.
* -> More than one transaction found (should never occur)
DATA lv_paypal_invoice_id TYPE com_wec_paypal_invoice_id.
DATA lv_start_date TYPE timestamp.
DATA lt_paypal_transaction_ids TYPE comt_wec_paypal_transaction_id.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lv_api_success TYPE abap_bool.
ev_error_occurred = abap_true.
ev_transaction_exists = abap_false.
CLEAR ev_paypal_transaction_id.
* Convert SAP reference ID to PayPal's invoice ID
256 October 2013
Development and Extension Guide – Application-Specific Information
lv_paypal_invoice_id = iv_reference_id.
* Set start date for search
CONVERT DATE '19000101' TIME '000000' INTO TIME STAMP lv_start_date TIME ZONE 'UTC '.
* Execute the search
ZCL_COMMON_PAYPAL_API=>transaction_search(
EXPORTING
iv_username = mv_username
iv_password = mv_password
iv_signature = gc_signature
iv_logical_port = gc_logical_port
iv_invoice_id = lv_paypal_invoice_id
iv_start_date = lv_start_date
IMPORTING
et_transaction_ids = lt_paypal_transaction_ids
et_messages = lt_api_messages
ev_success = lv_api_success ).
* Put API messages in the application log
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = ct_syslog_messages ).
* API call not successfull -> add error and return
IF lv_api_success = abap_false.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 005
iv_message_v1 = iv_reference_id
CHANGING
ct_messages = ct_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 005
iv_message_v1 = iv_reference_id
CHANGING
ct_messages = ct_syslog_messages ).
RETURN.
ENDIF.
* More than one transaction found for the reference number; this indicates a potential
* error in the SAP system -> add error and return
IF lines( lt_paypal_transaction_ids ) > 1.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 006
iv_message_v1 = iv_reference_id
October 2013 257
Development and Extension Guide – Application-Specific Information
CHANGING
ct_messages = ct_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 006
iv_message_v1 = iv_reference_id
CHANGING
ct_messages = ct_syslog_messages ).
RETURN.
ENDIF.
* If we got here, the API call was successful and returned no transaction ID
* (transaction not known in the PayPal system) or one transaction ID (transaction
* known in the PayPal system)
ev_error_occurred = abap_false.
* Read transaction ID if any
READ TABLE lt_paypal_transaction_ids INTO ev_paypal_transaction_id INDEX 1.
IF sy-subrc = 0 AND ev_paypal_transaction_id IS NOT INITIAL.
ev_transaction_exists = abap_true.
ENDIF.
ENDMETHOD.
ENDCLASS.
258 October 2013
Development and Extension Guide – Application-Specific Information
6.1.4 SAP CRM Replication Scenario
In the SAP CRM replication scenario, order management is completed in the SAP CRM back end. Order fulfillment,
billing, and financials are completed in the SAP ERP back end. The following figure shows the SAP CRM replication
scenario:
In the SAP CRM replication scenario, some configuration and the implementation of BAdI Integrating Payment Service
Providers must be completed in the SAP CRM back end. Some configuration and the BAdI Import Settlement Files for
Each Payment Service Provider must be implemented in the SAP ERP back end.
The sales order in the SAP CRM back end gets status information from the payment service provider using the
payment service provider interface (PSP IF). The sales order in the SAP CRM back end, including its payment service
provider status information, is replicated to the sales order in the SAP ERP back end. The sales order in SAP ERP
passes the payment service provider information by way of billing to financials for settlement.
October 2013 259
Development and Extension Guide – Application-Specific Information
Consider the activities in the following sections when using the SAP CRM replication scenario.
1. Activate business function in the SAP ERP back end.
Activate the ERP_WEB_CHANNEL_1 business function.
2. Maintain Customizing for payment service provider integration in the SAP ERP back end.
Make the settings in Customizing for SAP ERP under Sales and Distribution -> SAP Web Channel Experience
Management -> Payment Service Prov.
3. Activate business function in the SAP CRM back end.
Activate the CRM_WEB_CHANNEL business function.
4. Maintain Customizing for payment service provider integration in the SAP CRM back end.
Make the settings in Customizing for SAP CRM under Customer Relationship Management -> SAP Web
Channel Experience Management -> E-Commerce -> Payment Service Providers.
5. Implement BAdI: Integration of Payment Service Providers in the SAP CRM back end.
Implement all relevant proxy calls to the Web services provided by the payment service provider (see
subsection Call to the Proxy in section Creating Web Service Wrapper).
For more information, see Sample Implementation of BAdI 'Integration of Payment Service Providers' in the
SAP CRM Back End.
6. Schedule periodic tasks in the SAP CRM back end.
Use the program Process Incomplete Payment Service Provider Orders (transaction
CRMD_WEC_PSP_ORDER) to identify and process incomplete sales orders and service orders in the SAP
CRM back end that Web shop customers create using payment service providers. For more information, see
the online documentation for the program.
260 October 2013
Development and Extension Guide – Application-Specific Information
6.1.4.1 Sample Implementation of BAdI 'Integration of Payment Service Providers' in the SAP CRM
Back End
The following code is a sample implementation. In this sample implementation, the Web service calls are
encapsulated in class ZCL_COMMON_PAYPAL_API.
Sample BAdI implementation ZCL_CRM_PAYPAL_IMPL:
class ZCL_CRM_PAYPAL_IMPL definition
public
final
create public .
public section.
*"* public components of class ZCL_CRM_PAYPAL_IMPL
*"* do not include other source files here!!!
interfaces IF_BADI_INTERFACE .
interfaces IF_COM_WEC_PSP_INTEGRATION .
methods CONSTRUCTOR .
protected section.
*"* protected components of class ZCL_CRM_PAYPAL_IMPL
*"* do not include other source files here!!!
private section.
*"* private components of class ZCL_CRM_PAYPAL_IMPL
*"* do not include other source files here!!!
types:
begin of LTY_PSP_SHIPPIG_ADDRESS .
types TITLE TYPE AD_TITLE.
types NAME_FIRST TYPE AD_NAMEFIR.
types NAME_LAST TYPE AD_NAMELAS.
types NAME2_P TYPE AD_NAME2_P.
types NAMEMIDDLE TYPE AD_NAMEMID.
types NAME_LAST2 TYPE AD_NAMLAS2.
types NICKNAME TYPE AD_NICKNAM.
types INITIALS TYPE AD_INITS.
types NAME1 TYPE AD_NAME1.
types NAME2 TYPE AD_NAME2.
types NAME3 TYPE AD_NAME3.
types NAME4 TYPE AD_NAME4.
types CITY1 TYPE AD_CITY1.
types CITY2 TYPE AD_CITY2.
types HOME_CITY TYPE AD_CITY3.
types POST_CODE1 TYPE AD_PSTCD1.
types POST_CODE2 TYPE AD_PSTCD2.
types POST_CODE3 TYPE AD_PSTCD3.
types PCODE1_EXT TYPE AD_PST1XT.
types PCODE2_EXT TYPE AD_PST2XT.
types PCODE3_EXT TYPE AD_PST3XT.
types PO_BOX TYPE AD_POBX.
types PO_BOX_NUM TYPE AD_POBXNUM.
types PO_BOX_LOC TYPE AD_POBXLOC.
October 2013 261
Development and Extension Guide – Application-Specific Information
types PO_BOX_REG TYPE AD_POBXREG.
types PO_BOX_CTY TYPE AD_POBXCTY.
types STREET TYPE AD_STREET.
types HOUSE_NUM1 TYPE AD_HSNM1.
types HOUSE_NUM2 TYPE AD_HSNM2.
types HOUSE_NUM3 TYPE AD_HSNM3.
types STR_SUPPL1 TYPE AD_STRSPP1.
types STR_SUPPL2 TYPE AD_STRSPP2.
types STR_SUPPL3 type AD_STRSPP3.
types LOCATION type AD_LCTN.
types BUILDING type AD_BLDNG.
types FLOOR type AD_FLOOR.
types ROOMNUMBER type AD_ROOMNUM.
types COUNTRY type LAND1.
types REGION type REGIO.
types TAXJURCODE type AD_TXJCD.
types end of LTY_PSP_SHIPPIG_ADDRESS .
constants GC_SIGNATURE type STRING value `YourPayPalTestAccountSignature`. "#EC NOTEXT
constants GC_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME value SPACE. "#EC NOTEXT
constants GC_MESSAGE_ID type SYMSGID value 'CRM_WEC_PAYPAL_IMPL'. "#EC NOTEXT
constants GC_PAYPAL_CHECKOUT_URL type STRING value
`https://www.sandbox.paypal.com/webscr&cmd=_express-checkout&token=`. "#EC NOTEXT
constants GC_PAYPAL_PAYMENT_STATUS_COMP type COM_WEC_PAYPAL_PAYMENT_STATUS value `Completed`.
"#EC NOTEXT
constants GC_PAYPAL_PAYMENT_STATUS_DENI type COM_WEC_PAYPAL_PAYMENT_STATUS value `Denied`.
"#EC NOTEXT
constants GC_PAYPAL_PAYMENT_STATUS_NONE type COM_WEC_PAYPAL_PAYMENT_STATUS value `None`. "#EC
NOTEXT
constants GC_PAYPAL_PAYMENT_STATUS_PEND type COM_WEC_PAYPAL_PAYMENT_STATUS value `Pending`.
"#EC NOTEXT
constants GC_PAYPAL_PAYMENT_STATUS_REFU type COM_WEC_PAYPAL_PAYMENT_STATUS value `Refunded`.
"#EC NOTEXT
constants GC_PAYPAL_PAYMENT_STATUS_REVE type COM_WEC_PAYPAL_PAYMENT_STATUS value `Reversed`.
"#EC NOTEXT
data MV_USERNAME type STRING .
data MV_PASSWORD type STRING .
data MV_TOKEN type COM_WEC_PAYPAL_TOKEN .
type-pools ABAP .
methods SEARCH_TRANSACTION_BY_REF_ID
importing
!IV_REFERENCE_ID type COM_WEC_TRANSACTION_ID
exporting
!EV_ERROR_OCCURRED type ABAP_BOOL
!EV_TRANSACTION_EXISTS type ABAP_BOOL
!EV_PAYPAL_TRANSACTION_ID type COM_WEC_PAYPAL_TRANSACTION_ID
changing
!CT_MESSAGES type COMT_WEC_MESSAGES
!CT_SYSLOG_MESSAGES type COMT_WEC_MESSAGES .
class-methods ADD_MESSAGE
importing
!IV_TYPE type BAPI_MTYPE
!IV_ID type SYMSGID default GC_MESSAGE_ID
262 October 2013
Development and Extension Guide – Application-Specific Information
!IV_NUMBER type SYMSGNO
!IV_MESSAGE_V1 type SIMPLE optional
!IV_MESSAGE_V2 type SIMPLE optional
!IV_MESSAGE_V3 type SIMPLE optional
!IV_MESSAGE_V4 type SIMPLE optional
changing
!CT_MESSAGES type COMT_WEC_MESSAGES .
class-methods GET_PAYER_ID
importing
!IT_PARAMETERS type COMT_WEC_HTTP_PARAMETERS
returning
value(RV_PAYER_ID) type COM_WEC_PAYPAL_PAYER_ID .
class-methods GET_SHIPTO_ADDRESS
importing
!IS_SHIPPING_ADDRESS type ANY
returning
value(RS_SHIPTO_ADDRESS) type COMS_WEC_PAYPAL_SHIPTO_ADDRESS .
methods IS_TOKEN_VALID
importing
!IT_PARAMETERS type COMT_WEC_HTTP_PARAMETERS
returning
value(RV_TOKEN_VALID) type ABAP_BOOL .
class-methods IS_TRANSACTION_CONFIRMED
importing
!IT_PARAMETERS type COMT_WEC_HTTP_PARAMETERS
returning
value(RV_TRANSACTION_CONFIRMED) type COM_WEC_PAYPAL_PAYER_ID .
class-methods ADD_API_MESSAGES
importing
!IT_API_MESSAGES type BAPIRET2_TAB
changing
!CT_MESSAGES type COMT_WEC_MESSAGES .
class-methods REGION_SAP2PP
importing
!IV_REGIO type REGIO
!IV_COUNTRY type LAND1
returning
value(RV_REGIO_PP) type STRING .
class-methods COUNTRY_SAP2PP
importing
!IV_COUNTRY type LAND1
returning
value(RV_COUNTRY) type STRING .
class-methods GET_PASSWORD
returning
value(RV_PASSWORD) type STRING .
class-methods GET_USERNAME
returning
value(RV_USERNAME) type STRING .
ENDCLASS.
October 2013 263
Development and Extension Guide – Application-Specific Information
CLASS ZCL_CRM_PAYPAL_IMPL IMPLEMENTATION.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->ADD_API_MESSAGES
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD add_api_messages.
* Add API messages to message table
DATA ls_message LIKE LINE OF ct_messages.
FIELD-SYMBOLS <ls_api_message> LIKE LINE OF it_api_messages.
LOOP AT it_api_messages ASSIGNING <ls_api_message>.
CLEAR ls_message.
MOVE-CORRESPONDING <ls_api_message> TO ls_message.
INSERT ls_message INTO TABLE ct_messages.
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->ADD_MESSAGE
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD add_message.
* Add a message to table CT_MESSAGES
DATA ls_message LIKE LINE OF ct_messages.
ls_message-type = iv_type.
ls_message-id = iv_id.
ls_message-number = iv_number.
ls_message-message_v1 = iv_message_v1.
ls_message-message_v2 = iv_message_v2.
ls_message-message_v3 = iv_message_v3.
ls_message-message_v4 = iv_message_v4.
MESSAGE ID iv_id
TYPE iv_type
NUMBER iv_number
WITH iv_message_v1 iv_message_v2 iv_message_v3 iv_message_v4
INTO ls_message-message.
INSERT ls_message INTO TABLE ct_messages.
ENDMETHOD.
264 October 2013
Development and Extension Guide – Application-Specific Information
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->CONSTRUCTOR
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD constructor.
* Import user/password for PayPal API from user parameters. If parameters
* are not set, use default user/password.
mv_username = get_username( ).
mv_password = get_password( ).
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->COUNTRY_SAP2PP
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method COUNTRY_SAP2PP.
DATA lv_country_iso TYPE INTCA.
CALL FUNCTION 'COUNTRY_CODE_SAP_TO_ISO'
EXPORTING
sap_code = iv_country
IMPORTING
ISO_CODE = lv_country_iso
EXCEPTIONS
NOT_FOUND = 1
OTHERS = 2
.
IF sy-subrc <> 0.
rv_country = iv_country.
ELSE.
rv_country = lv_country_iso.
ENDIF.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->GET_PASSWORD
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_PASSWORD.
* implement your own logic to determine the password
endmethod.
October 2013 265
Development and Extension Guide – Application-Specific Information
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->GET_PAYER_ID
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_PAYER_ID.
* Get the payer ID of the PayPal customer; this is passed in by PayPal in the
* redirect to the Web Channel
FIELD-SYMBOLS <ls_parameter> TYPE coms_wec_http_parameter.
FIELD-SYMBOLS <lv_payer_id> TYPE string.
CLEAR rv_payer_id.
* Get the payer ID from the HTTP parameters passed in by PayPal
READ TABLE it_parameters ASSIGNING <ls_parameter> WITH TABLE KEY name = `PayerID`.
* We expect exactly one value for the payer id
IF sy-subrc = 0 AND lines( <ls_parameter>-values ) = 1.
READ TABLE <ls_parameter>-values ASSIGNING <lv_payer_id> INDEX 1.
IF sy-subrc = 0.
rv_payer_id = <lv_payer_id>.
ENDIF.
ENDIF.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->GET_SHIPTO_ADDRESS
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD get_shipto_address.
DATA ls_shipping_address TYPE lty_psp_shippig_address.
DATA lv_name_string TYPE string.
* Convert the internal shipping address to the PayPal shipto address
MOVE-CORRESPONDING is_shipping_address TO ls_shipping_address.
IF ls_shipping_address-name1 IS NOT INITIAL.
lv_name_string = ls_shipping_address-name1.
ENDIF.
IF ls_shipping_address-name2 IS NOT INITIAL.
lv_name_string = lv_name_string && ' ' && ls_shipping_address-name2.
ENDIF.
IF ls_shipping_address-name3 IS NOT INITIAL.
lv_name_string = lv_name_string && ' ' && ls_shipping_address-name3.
ENDIF.
IF ls_shipping_address-name4 IS NOT INITIAL.
lv_name_string = lv_name_string && ' ' && ls_shipping_address-name4.
266 October 2013
Development and Extension Guide – Application-Specific Information
ENDIF.
IF lv_name_string IS INITIAL.
lv_name_string = ls_shipping_address-name_first.
IF ls_shipping_address-namemiddle IS NOT INITIAL.
lv_name_string = lv_name_string && ' ' && ls_shipping_address-namemiddle.
ENDIF.
IF ls_shipping_address-name_last IS NOT INITIAL.
lv_name_string = lv_name_string && ' ' && ls_shipping_address-name_last.
ENDIF.
IF ls_shipping_address-name_last2 IS NOT INITIAL.
lv_name_string = lv_name_string && ' ' && ls_shipping_address-name_last2.
ENDIF.
ENDIF.
CLEAR rs_shipto_address.
rs_shipto_address-name = lv_name_string.
rs_shipto_address-street1 = ls_shipping_address-street.
rs_shipto_ADDRESS-STREET2 = ls_shipping_address-str_suppl1.
rs_shipto_address-city_name = ls_shipping_address-city1.
rs_shipto_address-state_or_province = region_sap2pp(
iv_regio = ls_shipping_address-region
iv_country = ls_shipping_address-country ).
rs_shipto_address-country = country_sap2pp(
iv_country = ls_shipping_address-country ).
rs_shipto_address-postal_code = ls_shipping_address-post_code1.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->GET_USERNAME
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_USERNAME.
* implement your own logic to determine the username
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Public Method ZCL_CRM_PAYPAL_IMPL->IF_COM_WEC_PSP_INTEGRATION~CANCEL_TRANSACTION
* +---------------------------------------------------------------------------------------------
----+
* | [--->] IS_REFERENCE_DOCUMENT TYPE COMS_WEC_BUSINESS_OBJECT
* | [--->] IV_REFERENCE_GUID TYPE COM_WEC_TRANSACTION_GUID
* | [--->] IV_REFERENCE_ID TYPE COM_WEC_TRANSACTION_ID
* | [--->] IV_PSP_TRANSACTION_ID TYPE COM_WEC_PSP_TRANSACTION_ID
October 2013 267
Development and Extension Guide – Application-Specific Information
* | [<---] ER_ACTION TYPE REF TO CL_COM_WEC_CANCEL_TRANS_PARAM
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD if_com_wec_psp_integration~cancel_transaction.
* Refund a PayPal transaction after cancelling the corresponding order
DATA lv_error_occurred_in_search TYPE abap_bool.
DATA lv_transaction_exists TYPE abap_bool.
DATA lv_paypal_transaction_id TYPE com_wec_paypal_transaction_id.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lv_api_success TYPE abap_bool.
DATA lt_messages TYPE comt_wec_messages.
DATA lt_syslog_messages TYPE comt_wec_messages.
* If the PSP transaction ID is given, we assume it is valid and use it to trigger the refunding
IF iv_psp_transaction_id IS NOT INITIAL.
lv_paypal_transaction_id = iv_psp_transaction_id.
* If the refernce ID is given, use it to check if the transaction exists in the PayPal system
ELSEIF iv_reference_id IS NOT INITIAL.
search_transaction_by_ref_id(
EXPORTING
iv_reference_id = iv_reference_id
IMPORTING
ev_error_occurred = lv_error_occurred_in_search
ev_transaction_exists = lv_transaction_exists
ev_paypal_transaction_id = lv_paypal_transaction_id
CHANGING
ct_messages = lt_messages
ct_syslog_messages = lt_syslog_messages ).
* If search failed, reprocess the order later
IF lv_error_occurred_in_search = abap_true.
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_cancel
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* If transaction is not known in the PayPal system, cancel the order
IF lv_transaction_exists = abap_false.
CREATE OBJECT er_action TYPE cl_com_wec_finalize_cancel
EXPORTING
iv_transaction_status_profile =
cl_crm_wec_psp_constants=>gc_transaction_status_profile
iv_transaction_status = cl_crm_wec_psp_constants=>gc_transaction_status_rfnd.
268 October 2013
Development and Extension Guide – Application-Specific Information
RETURN.
ENDIF.
* Neither PSP transaction ID or reference ID supplied. Give up because a search by transaction
GUID
* is not supported by PayPal so there is no other option to find the transaction.
ELSE.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 007
iv_message_v1 = 'GET_TRANSACTION_DETAILS'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 007
iv_message_v1 = 'GET_TRANSACTION_DETAILS'
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_cancel
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* Call the PayPal web service to refund the transaction
ZCL_COMMON_PAYPAL_API=>refund_transaction(
EXPORTING
iv_username = mv_username
iv_password = mv_password
iv_signature = gc_signature
iv_logical_port = gc_logical_port
iv_transaction_id = lv_paypal_transaction_id
iv_refund_type = ZCL_COMMON_PAYPAL_API=>gc_refund_type_full
IMPORTING
et_messages = lt_api_messages
ev_success = lv_api_success ).
* Add API messages to application log
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = lt_syslog_messages ).
October 2013 269
Development and Extension Guide – Application-Specific Information
* If refund successfull, finalize the cancellation
IF lv_api_success = abap_true.
CREATE OBJECT er_action TYPE cl_com_wec_finalize_cancel
EXPORTING
iv_transaction_status_profile = cl_crm_wec_psp_constants=>gc_transaction_status_profile
iv_transaction_status = cl_crm_wec_psp_constants=>gc_transaction_status_rfnd.
* If an error occured, schedule for later reprocessing
ELSE.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'RefundTransaction'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'RefundTransaction'
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_cancel
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
ENDIF.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Public Method ZCL_CRM_PAYPAL_IMPL-
>IF_COM_WEC_PSP_INTEGRATION~GET_TRANSACTION_DETAILS
* +---------------------------------------------------------------------------------------------
----+
* | [--->] IS_REFERENCE_DOCUMENT TYPE COMS_WEC_BUSINESS_OBJECT
* | [--->] IV_REFERENCE_GUID TYPE COM_WEC_TRANSACTION_GUID
* | [--->] IV_REFERENCE_ID TYPE COM_WEC_TRANSACTION_ID
* | [--->] IV_PSP_TRANSACTION_ID TYPE COM_WEC_PSP_TRANSACTION_ID
* | [<---] ER_ACTION TYPE REF TO CL_COM_WEC_UPDATE_TRANS_PARAM
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD if_com_wec_psp_integration~get_transaction_details.
* Get PayPal transaction details for an order
DATA lv_error_occurred_in_search TYPE abap_bool.
DATA lv_transaction_exists TYPE abap_bool.
DATA lv_paypal_transaction_id TYPE com_wec_paypal_transaction_id.
DATA lv_psp_transaction_id TYPE com_wec_psp_transaction_id.
270 October 2013
Development and Extension Guide – Application-Specific Information
DATA lv_transaction_amount TYPE com_wec_transaction_amount.
DATA lv_transaction_currency TYPE com_wec_transaction_currency.
DATA lv_paypal_payment_status TYPE com_wec_paypal_payment_status.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lv_api_success TYPE abap_bool.
DATA lt_messages TYPE comt_wec_messages.
DATA lt_syslog_messages TYPE comt_wec_messages.
* If the PSP transaction ID is given, we assume it is valid and use it to get the transaction
details
IF iv_psp_transaction_id IS NOT INITIAL.
lv_paypal_transaction_id = iv_psp_transaction_id.
* If the refernce ID is given, use it to check if the transaction exists in the PayPal system
ELSEIF iv_reference_id IS NOT INITIAL.
search_transaction_by_ref_id(
EXPORTING
iv_reference_id = iv_reference_id
IMPORTING
ev_error_occurred = lv_error_occurred_in_search
ev_transaction_exists = lv_transaction_exists
ev_paypal_transaction_id = lv_paypal_transaction_id
CHANGING
ct_messages = lt_messages
ct_syslog_messages = lt_syslog_messages ).
* If search failed, reprocess the order later
IF lv_error_occurred_in_search = abap_true.
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_update
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* If transaction is not known in the PayPal system, cancel the order
IF lv_transaction_exists = abap_false.
CREATE OBJECT er_action TYPE cl_com_wec_invalidate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
October 2013 271
Development and Extension Guide – Application-Specific Information
* Neither PSP transaction ID or reference ID supplied. Give up because a search by transaction
GUID
* is not supported by PayPal so there is no other option to find the transaction.
ELSE.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 007
iv_message_v1 = 'GET_TRANSACTION_DETAILS'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 007
iv_message_v1 = 'GET_TRANSACTION_DETAILS'
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_update
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* Get transaction details from PayPal
ZCL_COMMON_PAYPAL_API=>get_transaction_details(
EXPORTING
iv_username = mv_username
iv_password = mv_password
iv_signature = gc_signature
iv_logical_port = gc_logical_port
iv_transaction_id = lv_paypal_transaction_id
IMPORTING
ev_payment_status = lv_paypal_payment_status
ev_transaction_amount = lv_transaction_amount
ev_transaction_currency = lv_transaction_currency
et_messages = lt_api_messages
ev_success = lv_api_success ).
* Put API messages in the application log
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = lt_syslog_messages ).
* PayPal API call successful -> process PayPal payment status
IF lv_api_success = abap_true.
272 October 2013
Development and Extension Guide – Application-Specific Information
lv_psp_transaction_id = lv_paypal_transaction_id.
CASE lv_paypal_payment_status.
* PayPal has no payment status -> cancel corresponding order
WHEN gc_paypal_payment_status_none.
CREATE OBJECT er_action TYPE cl_com_wec_invalidate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal transaction has status completed -> set PSP status accordingly
WHEN gc_paypal_payment_status_comp.
CREATE OBJECT er_action TYPE cl_com_wec_update_transaction
EXPORTING
iv_transaction_status_profile =
cl_crm_wec_psp_constants=>gc_transaction_status_profile
iv_transaction_status = cl_crm_wec_psp_constants=>gc_transaction_status_comp
iv_psp_transaction_id = lv_psp_transaction_id
iv_transaction_amount = lv_transaction_amount
iv_transaction_currency = lv_transaction_currency
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal transaction has status pending -> set PSP status accordingly
WHEN gc_paypal_payment_status_pend.
CREATE OBJECT er_action TYPE cl_com_wec_update_transaction
EXPORTING
iv_transaction_status_profile =
cl_crm_wec_psp_constants=>gc_transaction_status_profile
iv_transaction_status = cl_crm_wec_psp_constants=>gc_transaction_status_pend
iv_psp_transaction_id = lv_psp_transaction_id
iv_transaction_amount = lv_transaction_amount
iv_transaction_currency = lv_transaction_currency
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal transaction has status refunded -> set PSP status accordingly
WHEN gc_paypal_payment_status_refu.
CREATE OBJECT er_action TYPE cl_com_wec_update_transaction
EXPORTING
iv_transaction_status_profile =
cl_crm_wec_psp_constants=>gc_transaction_status_profile
iv_transaction_status = cl_crm_wec_psp_constants=>gc_transaction_status_rfnd
iv_psp_transaction_id = lv_psp_transaction_id
iv_transaction_amount = lv_transaction_amount
iv_transaction_currency = lv_transaction_currency
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal transaction has status denied -> set PSP status to rejected
WHEN gc_paypal_payment_status_deni OR
gc_paypal_payment_status_reve.
October 2013 273
Development and Extension Guide – Application-Specific Information
CREATE OBJECT er_action TYPE cl_com_wec_update_transaction
EXPORTING
iv_transaction_status_profile =
cl_crm_wec_psp_constants=>gc_transaction_status_profile
iv_transaction_status = cl_crm_wec_psp_constants=>gc_transaction_status_reje
iv_psp_transaction_id = lv_psp_transaction_id
iv_transaction_amount = lv_transaction_amount
iv_transaction_currency = lv_transaction_currency
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
* PayPal returned an unexpected status -> raise an error and reprocess later
WHEN OTHERS.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 004
iv_message_v1 = 'GetTransactionDetails'
iv_message_v2 = lv_paypal_payment_status
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 004
iv_message_v1 = 'GetTransactionDetails'
iv_message_v2 = lv_paypal_payment_status
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_update
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
ENDCASE.
* PayPal API returned an error -> reprocess order later
ELSE.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'GetTransactionDetails'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'GetTransactionDetails'
CHANGING
274 October 2013
Development and Extension Guide – Application-Specific Information
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_reprocess_update
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
ENDIF.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Public Method ZCL_CRM_PAYPAL_IMPL->IF_COM_WEC_PSP_INTEGRATION~INITIATE_TRANSACTION
* +---------------------------------------------------------------------------------------------
----+
* | [--->] IS_REFERENCE_DOCUMENT TYPE COMS_WEC_BUSINESS_OBJECT
* | [--->] IV_TRANSACTION_AMOUNT TYPE COM_WEC_TRANSACTION_AMOUNT
* | [--->] IV_TRANSACTION_CURRENCY TYPE COM_WEC_TRANSACTION_CURRENCY
* | [--->] IS_SHIPPING_ADDRESS TYPE COMS_WEC_PAYMENT_ADDR
* | [--->] IV_REFERENCE_GUID TYPE COM_WEC_TRANSACTION_GUID
* | [--->] IV_REFERENCE_ID TYPE COM_WEC_TRANSACTION_ID
* | [--->] IV_WEC_SOURCE_URL TYPE STRING
* | [--->] IT_NAME_VALUE TYPE COMT_WEC_PSP_NAME_VALUE_PAIR
* | [<---] ER_ACTION TYPE REF TO CL_COM_WEC_CREATE_TRANS_PARAM
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD if_com_wec_psp_integration~initiate_transaction.
* Initiate a PayPal transaction (call the PayPal web service SetExpressCheckoutPayment
* and redirect the user to the PayPal web site)
DATA lv_return_url TYPE string.
DATA lv_cancel_url TYPE string.
DATA lv_invoice_id TYPE com_wec_paypal_invoice_id.
DATA lv_custom TYPE com_wec_paypal_custom.
DATA lv_target_url TYPE string.
DATA lv_api_success TYPE abap_bool.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lt_messages TYPE comt_wec_messages.
DATA lt_syslog_messages TYPE comt_wec_messages.
* Build the return and cancel URLs
lv_return_url = iv_wec_source_url && `sap-wec-pp-status=confirmed`.
lv_cancel_url = iv_wec_source_url && `sap-wec-pp-status=cancelled`.
* Fill invoice ID (order number) and custom field (transaction GUID)
lv_invoice_id = iv_reference_id.
lv_custom = iv_reference_guid.
* Call the PayPal API for starting the checkout
ZCL_COMMON_PAYPAL_API=>set_express_checkout(
EXPORTING
iv_username = mv_username
iv_password = mv_password
October 2013 275
Development and Extension Guide – Application-Specific Information
iv_signature = gc_signature
iv_logical_port = gc_logical_port
iv_amount = iv_transaction_amount
iv_currency = iv_transaction_currency
iv_return_url = lv_return_url
iv_cancel_url = lv_cancel_url
iv_invoice_id = lv_invoice_id
iv_custom = lv_custom
IMPORTING
ev_token = mv_token
et_messages = lt_api_messages
ev_success = lv_api_success ).
* Add API messages to application log
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = lt_syslog_messages ).
* If an error occured in the API call, output messages and return to checkout page
IF lv_api_success = abap_false.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'SetExpressCheckout'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'SetExpressCheckout'
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* If the token is initial, ouptut messages and return to checkout page
IF mv_token IS INITIAL.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 001
iv_message_v1 = 'SetExpressCheckout'
CHANGING
ct_messages = lt_messages ).
add_message(
276 October 2013
Development and Extension Guide – Application-Specific Information
EXPORTING
iv_type = 'E'
iv_number = 001
iv_message_v1 = 'SetExpressCheckout'
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* If we got here no error occured -> redirect the user to PayPal
* Add token returned by DoExpressCheckoutPayment to the PayPal URL
lv_target_url = gc_paypal_checkout_url && mv_token.
* Trigger the redirect
CREATE OBJECT er_action TYPE cl_com_wec_trigger_redirect
EXPORTING
iv_target_url = lv_target_url
it_syslog_messages = lt_syslog_messages.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Public Method ZCL_CRM_PAYPAL_IMPL->IF_COM_WEC_PSP_INTEGRATION~PROCESS_CALLBACK
* +---------------------------------------------------------------------------------------------
----+
* | [--->] IS_REFERENCE_DOCUMENT TYPE COMS_WEC_BUSINESS_OBJECT
* | [--->] IV_TRANSACTION_AMOUNT TYPE COM_WEC_TRANSACTION_AMOUNT
* | [--->] IV_TRANSACTION_CURRENCY TYPE COM_WEC_TRANSACTION_CURRENCY
* | [--->] IS_SHIPPING_ADDRESS TYPE COMS_WEC_PAYMENT_ADDR
* | [--->] IV_REFERENCE_GUID TYPE COM_WEC_TRANSACTION_GUID
* | [--->] IV_REFERENCE_ID TYPE COM_WEC_TRANSACTION_ID
* | [--->] IV_WEC_TARGET_URL TYPE STRING
* | [--->] IT_PARAMETERS TYPE COMT_WEC_HTTP_PARAMETERS
* | [--->] IT_NAME_VALUE TYPE COMT_WEC_PSP_NAME_VALUE_PAIR
* | [<---] ER_ACTION TYPE REF TO CL_COM_WEC_CREATE_TRANS_PARAM
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD if_com_wec_psp_integration~process_callback.
* Process the redirection from PayPal back to the Web Channel
DATA lv_paypal_transaction_id TYPE com_wec_paypal_transaction_id.
DATA lv_paypal_payment_status TYPE com_wec_paypal_payment_status.
DATA lv_psp_transaction_id TYPE com_wec_psp_transaction_id.
DATA lv_api_success TYPE abap_bool.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lt_messages TYPE comt_wec_messages.
October 2013 277
Development and Extension Guide – Application-Specific Information
DATA lt_syslog_messages TYPE comt_wec_messages.
DATA lv_payer_id(127) TYPE c.
DATA lv_cccategory TYPE cccategory.
* If the transaction is not confirmed, redirect the user to the checkout page
IF is_transaction_confirmed( it_parameters ) = abap_false.
add_message(
EXPORTING
iv_type = 'I'
iv_number = 002
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'I'
iv_number = 002
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* If the token returned by PayPal is invalid, redirect the user to the checkout page
IF is_token_valid( it_parameters ) = abap_false.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 003
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 003
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* Call the PayPal API to complete the checkout process
ZCL_COMMON_PAYPAL_API=>do_express_checkout_payment(
EXPORTING
iv_username = mv_username
iv_password = mv_password
278 October 2013
Development and Extension Guide – Application-Specific Information
iv_signature = gc_signature
iv_logical_port = gc_logical_port
iv_amount = iv_transaction_amount
iv_currency = iv_transaction_currency
iv_token = mv_token
iv_payerid = get_payer_id( it_parameters )
is_shipto_address = get_shipto_address( is_shipping_address )
IMPORTING
ev_transaction_id = lv_paypal_transaction_id
ev_payment_status = lv_paypal_payment_status
et_messages = lt_api_messages
ev_success = lv_api_success ).
* Add API messages to application log
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = lt_syslog_messages ).
* If an error occured in the API call, return the user to the checkout page
IF lv_api_success = abap_false OR lv_paypal_transaction_id IS INITIAL.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'DoExpressCheckoutPayment'
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'DoExpressCheckoutPayment'
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
RETURN.
ENDIF.
* Convert PayPal transaction ID to SAP internal transaction ID
lv_psp_transaction_id = lv_paypal_transaction_id.
* Check the payment status and finalize the transaction or start over with the checkout
CASE lv_paypal_payment_status.
WHEN gc_paypal_payment_status_comp.
CREATE OBJECT er_action TYPE cl_com_wec_finalize_trans
October 2013 279
Development and Extension Guide – Application-Specific Information
EXPORTING
iv_transaction_status_profile =
cl_crm_wec_psp_constants=>gc_transaction_status_profile
iv_transaction_status = cl_crm_wec_psp_constants=>gc_transaction_status_comp
iv_psp_transaction_id = lv_psp_transaction_id.
WHEN gc_paypal_payment_status_pend.
CREATE OBJECT er_action TYPE cl_com_wec_finalize_trans
EXPORTING
iv_transaction_status_profile =
cl_crm_wec_psp_constants=>gc_transaction_status_profile
iv_transaction_status = cl_crm_wec_psp_constants=>gc_transaction_status_pend
iv_psp_transaction_id = lv_psp_transaction_id.
WHEN OTHERS.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'DoExpressCheckoutPayment'
iv_message_v2 = lv_paypal_payment_status
CHANGING
ct_messages = lt_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 000
iv_message_v1 = 'DoExpressCheckoutPayment'
iv_message_v2 = lv_paypal_payment_status
CHANGING
ct_messages = lt_syslog_messages ).
CREATE OBJECT er_action TYPE cl_com_wec_initiate_trans
EXPORTING
it_messages = lt_messages
it_syslog_messages = lt_syslog_messages.
ENDCASE.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->IS_TOKEN_VALID
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD is_token_valid.
* Check if the token returned by PayPal after the redirect to the Web Channel
* is the same as supplied by the web service SetExpressCheckout
280 October 2013
Development and Extension Guide – Application-Specific Information
FIELD-SYMBOLS <ls_parameter> TYPE coms_wec_http_parameter.
FIELD-SYMBOLS <lv_token> TYPE string.
rv_token_valid = abap_false.
* Read the URL parameter
READ TABLE it_parameters ASSIGNING <ls_parameter> WITH TABLE KEY name = `token`.
* We expect exactly one value for the token
IF sy-subrc = 0 AND lines( <ls_parameter>-values ) = 1.
READ TABLE <ls_parameter>-values ASSIGNING <lv_token> INDEX 1.
IF sy-subrc = 0 AND mv_token = <lv_token>.
rv_token_valid = abap_true.
ENDIF.
ENDIF.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->IS_TRANSACTION_CONFIRMED
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD is_transaction_confirmed.
* Check if the payment transaction was confirmed by the payer
FIELD-SYMBOLS <ls_parameter> TYPE coms_wec_http_parameter.
FIELD-SYMBOLS <lv_status> TYPE string.
rv_transaction_confirmed = abap_false.
* Get the URL parameter from the HTTP parameters passed in by PayPal
READ TABLE it_parameters ASSIGNING <ls_parameter> WITH TABLE KEY name = `sap-wec-pp-status`.
* We expect exactly one value for the parameter
IF sy-subrc = 0 AND lines( <ls_parameter>-values ) = 1.
READ TABLE <ls_parameter>-values ASSIGNING <lv_status> INDEX 1.
IF sy-subrc = 0 AND <lv_status> = `confirmed`.
rv_transaction_confirmed = abap_true.
ENDIF.
ENDIF.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->REGION_SAP2PP
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD region_sap2pp.
October 2013 281
Development and Extension Guide – Application-Specific Information
* region codes of paypal for canada differ from sap region
* codes(table T005S). Map the differing ones.
CASE iv_country.
WHEN 'CA'.
CASE iv_regio.
WHEN 'NL'.
rv_regio_pp = 'NF'.
WHEN 'YT'.
rv_regio_pp = 'YK'.
WHEN OTHERS.
rv_regio_pp = iv_regio.
ENDCASE.
WHEN OTHERS.
rv_regio_pp = iv_regio.
ENDCASE.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_CRM_PAYPAL_IMPL->SEARCH_TRANSACTION_BY_REF_ID
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD search_transaction_by_ref_id.
* Search for a PayPal transaction by our reference ID (= PayPal invoice ID). Note
* that searching by our transaction GUID is currently not supported by PayPal's web
* services.
* Possible return values
*
* EV_ERROR_OCCURRED = ABAP_FALSE and EV_TRANSACTION_EXISTS = ABAP_TRUE
* -> Transaction does exist in the PayPal system. Transaction ID returned in
EV_PAYPAL_TRANSACTION_ID
*
* EV_ERROR_OCCURRED = ABAP_FALSE and EV_TRANSACTION_EXISTS = ABAP_FALSE
* -> Transaction does not exist in the PayPal system.
*
* EV_ERROR_OCCURRED = ABAP_TRUE
* -> An error occured when searching in the PayPal system; cannot tell if transactoin
* exists or not.
* -> More than one transaction found (should never occur)
DATA lv_paypal_invoice_id TYPE com_wec_paypal_invoice_id.
DATA lv_start_date TYPE timestamp.
DATA lt_paypal_transaction_ids TYPE comt_wec_paypal_transaction_id.
DATA lt_api_messages TYPE bapiret2_tab.
DATA lv_api_success TYPE abap_bool.
ev_error_occurred = abap_true.
ev_transaction_exists = abap_false.
282 October 2013
Development and Extension Guide – Application-Specific Information
CLEAR ev_paypal_transaction_id.
* Convert SAP reference ID to PayPal's invoice ID
lv_paypal_invoice_id = iv_reference_id.
* Set start date for search
CONVERT DATE '20000101' TIME '000000' INTO TIME STAMP lv_start_date TIME ZONE 'UTC '.
* Execute the search
ZCL_COMMON_PAYPAL_API=>transaction_search(
EXPORTING
iv_username = mv_username
iv_password = mv_password
iv_signature = gc_signature
iv_logical_port = gc_logical_port
iv_invoice_id = lv_paypal_invoice_id
iv_start_date = lv_start_date
IMPORTING
et_transaction_ids = lt_paypal_transaction_ids
et_messages = lt_api_messages
ev_success = lv_api_success ).
* Put API messages in the application log
add_api_messages(
EXPORTING
it_api_messages = lt_api_messages
CHANGING
ct_messages = ct_syslog_messages ).
* API call not successfull -> add error and return
IF lv_api_success = abap_false.
add_message(
EXPORTING
iv_type = 'E'
iv_number = 005
iv_message_v1 = iv_reference_id
CHANGING
ct_messages = ct_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 005
iv_message_v1 = iv_reference_id
CHANGING
ct_messages = ct_syslog_messages ).
RETURN.
ENDIF.
* More than one transaction found for the reference number; this indicates a potential
* error in the SAP system -> add error and return
IF lines( lt_paypal_transaction_ids ) > 1.
add_message(
October 2013 283
Development and Extension Guide – Application-Specific Information
EXPORTING
iv_type = 'E'
iv_number = 006
iv_message_v1 = iv_reference_id
CHANGING
ct_messages = ct_messages ).
add_message(
EXPORTING
iv_type = 'E'
iv_number = 006
iv_message_v1 = iv_reference_id
CHANGING
ct_messages = ct_syslog_messages ).
RETURN.
ENDIF.
* If we got here, the API call was successful and returned no transaction ID
* (transaction not known in the PayPal system) or one transaction ID (transaction
* known in the PayPal system)
ev_error_occurred = abap_false.
* Read transaction ID if any
READ TABLE lt_paypal_transaction_ids INTO ev_paypal_transaction_id INDEX 1.
IF sy-subrc = 0 AND ev_paypal_transaction_id IS NOT INITIAL.
ev_transaction_exists = abap_true.
ENDIF.
ENDMETHOD.
ENDCLASS.
Sample helper class ZCL_COMMON_PAYPAL_API:
class ZCL_COMMON_PAYPAL_API definition
public
final
create public .
public section.
*"* public components of class ZCL_COMMON_PAYPAL_API
*"* do not include other source files here!!!
type-pools ABAP .
constants GC_PAYPAL_API_VERSION type STRING value '60.0'. "#EC NOTEXT
constants GC_PAYMENT_ACTION_NONE type COM_WEC_PAYPAL_PAYMENT_ACTION value 'None'. "#EC NOTEXT
constants GC_PAYMENT_ACTION_SALE type COM_WEC_PAYPAL_PAYMENT_ACTION value 'Sale'. "#EC NOTEXT
constants GC_PAYMENT_ACTION_AUTH type COM_WEC_PAYPAL_PAYMENT_ACTION value 'Authorization'.
"#EC NOTEXT
constants GC_PAYMENT_ACTION_ORDER type COM_WEC_PAYPAL_PAYMENT_ACTION value 'Order'. "#EC
NOTEXT
constants GC_REFUND_TYPE_OTHER type COM_WEC_PAYPAL_REFUND_TYPE value 'Other'. "#EC NOTEXT
constants GC_REFUND_TYPE_FULL type COM_WEC_PAYPAL_REFUND_TYPE value 'Full'. "#EC NOTEXT
constants GC_REFUND_TYPE_PARTIAL type COM_WEC_PAYPAL_REFUND_TYPE value 'Partial'. "#EC NOTEXT
constants GC_ACK_SUCCESS type COM_WEC_PAYPAL_ACKNOWLEDGEMENT value 'Success'. "#EC NOTEXT
constants GC_ACK_FAILURE type COM_WEC_PAYPAL_ACKNOWLEDGEMENT value 'Failure'. "#EC NOTEXT
284 October 2013
Development and Extension Guide – Application-Specific Information
constants GC_ACK_WARNING type COM_WEC_PAYPAL_ACKNOWLEDGEMENT value 'Warning'. "#EC NOTEXT
constants GC_ACK_SUCCESSWITHWARNING type COM_WEC_PAYPAL_ACKNOWLEDGEMENT value
'SuccessWithWarning'. "#EC NOTEXT
constants GC_ACK_FAILUREWITHWARNING type COM_WEC_PAYPAL_ACKNOWLEDGEMENT value
'FailureWithWarning'. "#EC NOTEXT
constants GC_ACK_CUSTOMCODE type COM_WEC_PAYPAL_ACKNOWLEDGEMENT value 'CustomCode'. "#EC
NOTEXT
constants GC_SEVERITY_CODE_WARNING type COM_WEC_PAYPAL_SEVERITY_CODE value 'Warning'. "#EC
NOTEXT
constants GC_SEVERITY_CODE_ERROR type COM_WEC_PAYPAL_SEVERITY_CODE value 'Error'. "#EC NOTEXT
constants GC_SEVERITY_CODE_CUSTOM type COM_WEC_PAYPAL_SEVERITY_CODE value 'CustomCode'. "#EC
NOTEXT
class-methods SET_EXPRESS_CHECKOUT
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING optional
!IV_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME optional
!IV_AMOUNT type COM_WEC_TRANSACTION_AMOUNT
!IV_CURRENCY type COM_WEC_TRANSACTION_CURRENCY
!IV_RETURN_URL type STRING
!IV_CANCEL_URL type STRING
!IV_INVOICE_ID type COM_WEC_PAYPAL_INVOICE_ID optional
!IV_CUSTOM type COM_WEC_PAYPAL_CUSTOM optional
exporting
!EV_TOKEN type COM_WEC_PAYPAL_TOKEN
!ET_MESSAGES type BAPIRET2_TAB
!EV_SUCCESS type ABAP_BOOL .
class-methods DO_EXPRESS_CHECKOUT_PAYMENT
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING optional
!IV_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME optional
!IV_AMOUNT type COM_WEC_TRANSACTION_AMOUNT
!IV_CURRENCY type COM_WEC_TRANSACTION_CURRENCY
!IV_TOKEN type COM_WEC_PAYPAL_TOKEN
!IV_PAYERID type COM_WEC_PAYPAL_PAYER_ID
!IS_SHIPTO_ADDRESS type COMS_WEC_PAYPAL_SHIPTO_ADDRESS
exporting
!EV_TRANSACTION_ID type COM_WEC_PAYPAL_TRANSACTION_ID
!EV_PAYMENT_STATUS type COM_WEC_PAYPAL_PAYMENT_STATUS
!EV_PENDING_REASON type COM_WEC_PAYPAL_PENDING_REASON
!ET_MESSAGES type BAPIRET2_TAB
!EV_SUCCESS type ABAP_BOOL .
class-methods GET_EXPRESS_CHECKOUT_DETAILS
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING optional
!IV_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME optional
!IV_TOKEN type COM_WEC_PAYPAL_TOKEN
exporting
October 2013 285
Development and Extension Guide – Application-Specific Information
!EV_PAYER_ID type COM_WEC_PAYPAL_PAYER_ID
!EV_INVOICE_ID type COM_WEC_PAYPAL_INVOICE_ID
!EV_CUSTOM type COM_WEC_PAYPAL_CUSTOM
!ET_MESSAGES type BAPIRET2_TAB
!EV_SUCCESS type ABAP_BOOL .
class-methods GET_TRANSACTION_DETAILS
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING optional
!IV_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME optional
!IV_TRANSACTION_ID type COM_WEC_PAYPAL_TRANSACTION_ID
exporting
!EV_PAYMENT_STATUS type COM_WEC_PAYPAL_PAYMENT_STATUS
!EV_PENDING_REASON type COM_WEC_PAYPAL_PENDING_REASON
!EV_PAYER_ID type COM_WEC_PAYPAL_PAYER_ID
!EV_INVOICE_ID type COM_WEC_PAYPAL_INVOICE_ID
!EV_CUSTOM type COM_WEC_PAYPAL_CUSTOM
!EV_TRANSACTION_AMOUNT type COM_WEC_TRANSACTION_AMOUNT
!EV_TRANSACTION_CURRENCY type COM_WEC_TRANSACTION_CURRENCY
!ET_MESSAGES type BAPIRET2_TAB
!EV_SUCCESS type ABAP_BOOL .
class-methods TRANSACTION_SEARCH
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING
!IV_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME
!IV_TRANSACTION_ID type COM_WEC_PAYPAL_TRANSACTION_ID optional
!IV_INVOICE_ID type COM_WEC_PAYPAL_INVOICE_ID optional
!IV_AMOUNT type COM_WEC_TRANSACTION_AMOUNT optional
!IV_CURRENCY type COM_WEC_TRANSACTION_CURRENCY optional
!IV_START_DATE type TIMESTAMP
!IV_END_DATE type TIMESTAMP optional
exporting
!ET_TRANSACTION_IDS type COMT_WEC_PAYPAL_TRANSACTION_ID
!ET_MESSAGES type BAPIRET2_TAB
!EV_SUCCESS type ABAP_BOOL .
class-methods REFUND_TRANSACTION
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING optional
!IV_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME optional
!IV_AMOUNT type COM_WEC_TRANSACTION_AMOUNT optional
!IV_CURRENCY type COM_WEC_TRANSACTION_CURRENCY optional
!IV_TRANSACTION_ID type COM_WEC_PAYPAL_TRANSACTION_ID
!IV_REFUND_TYPE type COM_WEC_PAYPAL_REFUND_TYPE
!IV_MEMO type COM_WEC_PAYPAL_MEMO optional
exporting
!EV_REFUND_TRANS_ID type COM_WEC_PAYPAL_REFUND_TRANS_ID
!ET_MESSAGES type BAPIRET2_TAB
!EV_SUCCESS type ABAP_BOOL .
286 October 2013
Development and Extension Guide – Application-Specific Information
protected section.
*"* protected components of class ZCL_COMMON_PAYPAL_API
*"* do not include other source files here!!!
private section.
*"* private components of class ZCL_COMMON_PAYPAL_API
*"* do not include other source files here!!!
constants GC_PAYPAL_PAYMENT_STATUS_NONE type COM_WEC_PAYPAL_PAYMENT_STATUS value 'None'. "#EC
NOTEXT
class-methods GET_SOAP_HEADER_AUTH
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING optional
exporting
!ER_XML_DOCUMENT type ref to IF_IXML_DOCUMENT .
class-methods ADD_TO_SOAP_HEADER
importing
!IR_XML_DOCUMENT type ref to IF_IXML_DOCUMENT
!IR_PROTOCOL type ref to IF_WSPROTOCOL_WS_HEADER .
class-methods GET_WS_INTERFACE
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING optional
!IV_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME optional
exporting
!ER_INTERFACE type ref to CO_PAY_PAL_APIAAINTERFACE .
class-methods GET_WS_INTERFACE_FOR_TRANS
importing
!IV_USERNAME type STRING
!IV_PASSWORD type STRING
!IV_SIGNATURE type STRING optional
!IV_LOGICAL_PORT type PRX_LOGICAL_PORT_NAME optional
exporting
!ER_INTERFACE type ref to CO_PAY_PAL_APIINTERFACE .
class-methods GET_ERRORS_FROM_PAYPAL
importing
!IS_ABSTRACT_RESPONSE_TYPE type ABSTRACT_RESPONSE_TYPE
!IV_RETURNED_VALUE type ANY
exporting
!ET_MESSAGES type BAPIRET2_TAB
!EV_SUCCESS type ABAP_BOOL .
ENDCLASS.
CLASS ZCL_COMMON_PAYPAL_API IMPLEMENTATION.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
October 2013 287
Development and Extension Guide – Application-Specific Information
* | Instance Private Method ZCL_COMMON_PAYPAL_API->ADD_TO_SOAP_HEADER
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method ADD_TO_SOAP_HEADER.
DATA:
l_root TYPE REF TO if_ixml_element,
l_element TYPE REF TO if_ixml_element,
lv_element_name TYPE string,
lv_namespace TYPE string.
* Get root element
l_root = ir_xml_document->get_root_element( ).
* Get first child element
l_element ?= l_root->get_first_child( ).
* Loop over all child elements
WHILE NOT l_element IS INITIAL.
* Get element name and namespace
lv_element_name = l_element->get_name( ).
lv_namespace = l_element->get_namespace_uri( ).
* Add header element to SOAP header
ir_protocol->set_request_header(
name = lv_element_name
namespace = lv_namespace
dom = l_element ).
* Get next element
l_element ?= l_element->get_next( ).
ENDWHILE.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->DO_EXPRESS_CHECKOUT_PAYMENT
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method DO_EXPRESS_CHECKOUT_PAYMENT.
DATA:
lv_iso_langu TYPE laiso,
lv_iso_currency TYPE tcurc-isocd,
ls_request TYPE doexpress_checkout_payment_r7,
ls_response TYPE doexpress_checkout_payment_r6,
ls_payment_info TYPE payment_info_type,
ls_abstract_request_type TYPE abstract_request_type,
ls_set_express_checkout_req TYPE doexpress_checkout_payment_r5,
ls_payment_details TYPE payment_details_type,
288 October 2013
Development and Extension Guide – Application-Specific Information
lr_ws_proxy TYPE REF TO co_pay_pal_apiaainterface,
le_root TYPE REF TO cx_root,
ls_message TYPE bapiret2.
TRY.
* Convert language key to ISO language code
CALL METHOD cl_gdt_conversion=>language_code_outbound
EXPORTING
im_value = sy-langu
IMPORTING
ex_value = lv_iso_langu.
* Convert currency key to ISO currency code
CALL METHOD cl_gdt_conversion=>currency_code_outbound
EXPORTING
im_value = iv_currency
IMPORTING
ex_value = lv_iso_currency.
* fill request data
ls_abstract_request_type-error_language = lv_iso_langu.
ls_abstract_request_type-version = gc_paypal_api_version.
ls_payment_details-order_total-currency_id = lv_iso_currency.
ls_payment_details-order_total-content = iv_amount.
MOVE-CORRESPONDING is_shipto_address TO ls_payment_details-ship_to_address.
* At the moment only advance payment is supported
ls_set_express_checkout_req-payment_action = ZCL_COMMON_PAYPAL_API=>gc_payment_action_sale.
ls_set_express_checkout_req-token = iv_token.
ls_set_express_checkout_req-payer_id = iv_payerid.
ls_set_express_checkout_req-payment_details = ls_payment_details.
ls_request-do_express_checkout_payment_re-base = ls_abstract_request_type.
ls_request-do_express_checkout_payment_re-do_express_checkout_payment_re =
ls_set_express_checkout_req.
* Get webservice proxy
CALL METHOD get_ws_interface
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
iv_logical_port = iv_logical_port
IMPORTING
er_interface = lr_ws_proxy.
* Call webservice proxy
CALL METHOD lr_ws_proxy->do_express_checkout_payment
EXPORTING
input = ls_request
IMPORTING
October 2013 289
Development and Extension Guide – Application-Specific Information
output = ls_response.
* Error handling
CATCH cx_gdt_conversion cx_ai_system_fault cx_ai_application_fault INTO le_root.
ls_message-type = 'E'.
ls_message-message = le_root->if_message~get_text( ).
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_message-system.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDTRY.
* Return transaction ID and payment status
ls_payment_info = ls_response-do_express_checkout_payment_re-do_express_checkout_payment_re-
payment_info.
ev_transaction_id = ls_payment_info-transaction_id.
ev_payment_status = ls_payment_info-payment_status.
ev_pending_reason = ls_payment_info-pending_reason.
* Handling of errors returned by PayPal
CALL METHOD get_errors_from_paypal
EXPORTING
is_abstract_response_type = ls_response-do_express_checkout_payment_re-base
iv_returned_value = ev_transaction_id
IMPORTING
et_messages = et_messages
ev_success = ev_success.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->GET_ERRORS_FROM_PAYPAL
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_ERRORS_FROM_PAYPAL.
DATA:
ls_message TYPE bapiret2.
FIELD-SYMBOLS:
<ls_paypal_error> TYPE error_type3.
* Error detection
CASE is_abstract_response_type-ack.
WHEN gc_ack_success.
ev_success = abap_true.
290 October 2013
Development and Extension Guide – Application-Specific Information
WHEN gc_ack_successwithwarning.
ev_success = abap_true.
WHEN gc_ack_failure.
ev_success = abap_false.
WHEN gc_ack_failurewithwarning.
ev_success = abap_false.
* For the values below we cannot be really sure whether the operation was successful.
* Therefore, the parameter returned by PayPal is checked. If it is provided, the
* operation was successful - otherwise it failed. For example, if the method
* set_express_checkout returns with a warning but the token is returned from
* PayPal, the operation was a success.
WHEN gc_ack_warning.
IF iv_returned_value IS INITIAL.
ev_success = abap_false.
ELSE.
ev_success = abap_true.
ENDIF.
WHEN gc_ack_customcode. "Reserved by PayPal for internal or future use
IF iv_returned_value IS INITIAL.
ev_success = abap_false.
ELSE.
ev_success = abap_true.
ENDIF.
WHEN OTHERS.
IF iv_returned_value IS INITIAL.
ev_success = abap_false.
ELSE.
ev_success = abap_true.
ENDIF.
ENDCASE.
* Loop over all messages returned from PayPal
LOOP AT is_abstract_response_type-errors ASSIGNING <ls_paypal_error>.
CASE <ls_paypal_error>-severity_code.
WHEN gc_severity_code_warning.
ls_message-type = 'W'.
WHEN gc_severity_code_error.
ls_message-type = 'E'.
WHEN gc_severity_code_custom. "Reserved by PayPal for internal or future use
ls_message-type = 'I'.
ENDCASE.
ls_message-message = <ls_paypal_error>-short_message.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ENDLOOP.
endmethod.
October 2013 291
Development and Extension Guide – Application-Specific Information
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->GET_EXPRESS_CHECKOUT_DETAILS
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD get_express_checkout_details.
DATA:
lv_iso_langu TYPE laiso,
ls_request TYPE get_express_checkout_details_5,
ls_response TYPE get_express_checkout_details_4,
ls_checkout_details TYPE get_express_checkout_details_3,
ls_abstract_request_type TYPE abstract_request_type,
lr_ws_proxy TYPE REF TO co_pay_pal_apiaainterface,
le_root TYPE REF TO cx_root,
ls_message TYPE bapiret2.
TRY.
* Convert language key to ISO language code
CALL METHOD cl_gdt_conversion=>language_code_outbound
EXPORTING
im_value = sy-langu
IMPORTING
ex_value = lv_iso_langu.
* fill request data
ls_abstract_request_type-error_language = lv_iso_langu.
ls_abstract_request_type-version = gc_paypal_api_version.
ls_request-get_express_checkout_details_r-base = ls_abstract_request_type.
ls_request-get_express_checkout_details_r-token = iv_token.
* Get webservice proxy
CALL METHOD get_ws_interface
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
iv_logical_port = iv_logical_port
IMPORTING
er_interface = lr_ws_proxy.
* Call proxy
CALL METHOD lr_ws_proxy->get_express_checkout_details
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
* Error handling
CATCH cx_gdt_conversion cx_ai_system_fault cx_ai_application_fault INTO le_root.
292 October 2013
Development and Extension Guide – Application-Specific Information
ls_message-type = 'E'.
ls_message-message = le_root->if_message~get_text( ).
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_message-system.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDTRY.
* Return Payer ID, Invoice ID, and Custom field
ls_checkout_details = ls_response-get_express_checkout_details_r-
get_express_checkout_details_r.
ev_payer_id = ls_checkout_details-payer_info-payer_id.
ev_invoice_id = ls_checkout_details-invoice_id.
ev_custom = ls_checkout_details-custom.
* Handling of errors returned by PayPal
CALL METHOD get_errors_from_paypal
EXPORTING
is_abstract_response_type = ls_response-get_express_checkout_details_r-base
iv_returned_value = ev_payer_id
IMPORTING
et_messages = et_messages
ev_success = ev_success.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->GET_SOAP_HEADER_AUTH
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD get_soap_header_auth.
CONSTANTS:
co_tag_header TYPE string VALUE 'Header', "#EC NOTEXT
co_tag_req_cred TYPE string VALUE 'RequesterCredentials', "#EC NOTEXT
co_tag_credentials TYPE string VALUE 'Credentials', "#EC NOTEXT
co_tag_username TYPE string VALUE 'Username', "#EC NOTEXT
co_tag_password TYPE string VALUE 'Password', "#EC NOTEXT
co_tag_signature TYPE string VALUE 'Signature', "#EC NOTEXT
co_attr_xmlns TYPE string VALUE 'xmlns', "#EC NOTEXT
co_attr_type TYPE string VALUE 'type', "#EC NOTEXT
co_namesp_soap TYPE string VALUE 'SOAP-ENV', "#EC NOTEXT
co_namesp_xsi TYPE string VALUE 'xsi', "#EC NOTEXT
co_ns_paypalapi TYPE string VALUE 'urn:ebay:api:PayPalAPI', "#EC NOTEXT
co_ns_eblbase TYPE string VALUE 'urn:ebay:apis:eBLBaseComponents', "#EC NOTEXT
October 2013 293
Development and Extension Guide – Application-Specific Information
co_ns_xsi TYPE string VALUE 'http://www.w3.org/2001/XMLSchema-instance', "#EC
NOTEXT
co_ns_enc TYPE string VALUE 'http://schemas.xmlsoap.org/soap/encoding/', "#EC
NOTEXT
co_ns_env TYPE string VALUE 'http://schemas.xmlsoap.org/soap/envelope/', "#EC
NOTEXT
co_ns_xsd TYPE string VALUE 'http://www.w3.org/2001/XMLSchema', "#EC NOTEXT
co_ns_encoding TYPE string VALUE 'http://schemas.xmlsoap.org/soap/encoding/', "#EC
NOTEXT
co_ns_security_h TYPE string VALUE 'ebl:CustomSecurityHeaderType', "#EC NOTEXT
co_ns_base_comp TYPE string VALUE 'urn:ebay:apis:eBLBaseComponents', "#EC NOTEXT
co_ns_user_pwd TYPE string VALUE 'ebl:UserIdPasswordType'. "#EC NOTEXT
DATA:
l_ixml TYPE REF TO if_ixml,
l_document TYPE REF TO if_ixml_document,
l_encoding TYPE REF TO if_ixml_encoding,
l_root TYPE REF TO if_ixml_element,
l_req_cred TYPE REF TO if_ixml_element,
l_credentials TYPE REF TO if_ixml_element,
l_username TYPE REF TO if_ixml_element,
l_password TYPE REF TO if_ixml_element,
l_signature TYPE REF TO if_ixml_element,
l_rc LIKE sy-subrc.
* Initialize the iXML-Toolkit
l_ixml = cl_ixml=>create( ).
* Create the xml-document
l_document = l_ixml->create_document( ).
* Set encoding to UTF-8
l_encoding = l_ixml->create_encoding(
byte_order = 0 " little endian byte ordering
character_set = 'UTF-8' ).
CALL METHOD l_document->set_encoding
EXPORTING
encoding = l_encoding.
* Create the root element (SOAP header)
l_root = l_document->create_simple_element(
name = co_tag_header
namespace = co_namesp_soap
parent = l_document ).
* Create the element RequesterCredentials
l_req_cred = l_document->create_simple_element(
name = co_tag_req_cred
parent = l_root ).
* Create the element Credentials
l_credentials = l_document->create_simple_element(
name = co_tag_credentials
parent = l_req_cred ).
294 October 2013
Development and Extension Guide – Application-Specific Information
* Create the element Username
l_username = l_document->create_simple_element(
name = co_tag_username
value = iv_username
parent = l_credentials ).
* Create the element Password
l_password = l_document->create_simple_element(
name = co_tag_password
value = iv_password
parent = l_credentials ).
* Create the element Signature
IF iv_signature IS NOT INITIAL.
l_signature = l_document->create_simple_element(
name = co_tag_signature
value = iv_signature
parent = l_credentials ).
ENDIF.
* Add attributes to the elements
l_rc = l_req_cred->set_attribute(
name = co_attr_xmlns
value = co_ns_paypalapi ).
l_rc = l_req_cred->set_attribute(
name = co_namesp_xsi
namespace = co_attr_xmlns
value = co_ns_xsi ).
l_rc = l_req_cred->set_attribute(
name = co_attr_type
namespace = co_namesp_xsi
value = co_ns_security_h ).
l_rc = l_credentials->set_attribute(
name = co_attr_xmlns
value = co_ns_base_comp ).
l_rc = l_credentials->set_attribute(
name = co_attr_type
namespace = co_namesp_xsi
value = co_ns_user_pwd ).
er_xml_document = l_document.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->GET_TRANSACTION_DETAILS
* +---------------------------------------------------------------------------------------------
----+
October 2013 295
Development and Extension Guide – Application-Specific Information
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD get_transaction_details.
DATA:
lv_iso_langu TYPE laiso,
ls_request TYPE get_transaction_details_reque1,
ls_response TYPE get_transaction_details_respo1,
ls_transaction_details TYPE payment_transaction_details,
ls_abstract_request_type TYPE abstract_request_type,
lr_ws_proxy TYPE REF TO co_pay_pal_apiinterface,
le_root TYPE REF TO cx_root,
ls_message TYPE bapiret2.
TRY.
* Convert language key to ISO language code
CALL METHOD cl_gdt_conversion=>language_code_outbound
EXPORTING
im_value = sy-langu
IMPORTING
ex_value = lv_iso_langu.
* fill request data
ls_abstract_request_type-error_language = lv_iso_langu.
ls_abstract_request_type-version = gc_paypal_api_version.
ls_request-get_transaction_details_reques-base = ls_abstract_request_type.
ls_request-get_transaction_details_reques-transaction_id = iv_transaction_id.
* Get webservice proxy
CALL METHOD get_ws_interface_for_trans
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
iv_logical_port = iv_logical_port
IMPORTING
er_interface = lr_ws_proxy.
* Call webservice proxy
CALL METHOD lr_ws_proxy->get_transaction_details
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
* Error handling
CATCH cx_gdt_conversion cx_ai_system_fault cx_ai_application_fault INTO le_root.
ls_message-type = 'E'.
ls_message-message = le_root->if_message~get_text( ).
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_message-system.
296 October 2013
Development and Extension Guide – Application-Specific Information
APPEND ls_message TO et_messages.
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDTRY.
* Return transaction details
ls_transaction_details = ls_response-get_transaction_details_respon-
payment_transaction_details.
ev_payment_status = ls_transaction_details-payment_info-payment_status.
ev_pending_reason = ls_transaction_details-payment_info-pending_reason.
ev_payer_id = ls_transaction_details-payer_info-payer_id.
ev_invoice_id = ls_transaction_details-payment_item_info-invoice_id.
ev_custom = ls_transaction_details-payment_item_info-custom.
ev_transaction_amount = ls_transaction_details-payment_info-gross_amount-content.
ev_transaction_currency = ls_transaction_details-payment_info-gross_amount-currency_id.
* Handling of errors returned by PayPal
CALL METHOD get_errors_from_paypal
EXPORTING
is_abstract_response_type = ls_response-get_transaction_details_respon-base
iv_returned_value = ls_transaction_details-payment_info-transaction_id
IMPORTING
et_messages = et_messages
ev_success = ev_success.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->GET_WS_INTERFACE
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_WS_INTERFACE.
DATA:
lr_protocol TYPE REF TO if_wsprotocol_ws_header,
lr_xml_document TYPE REF TO if_ixml_document,
le_system_fault TYPE REF TO cx_ai_system_fault,
lv_text TYPE string.
TRY.
* Create instance
CREATE OBJECT er_interface
EXPORTING
logical_port_name = iv_logical_port.
* Get the web service protocol for access to additional fields of the WS SOAP message header
lr_protocol ?= er_interface->get_protocol( if_wsprotocol=>ws_header ).
October 2013 297
Development and Extension Guide – Application-Specific Information
* Get additional fields for the authentication in the SOAP header
CALL METHOD get_soap_header_auth
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
IMPORTING
er_xml_document = lr_xml_document.
* Add additional fields to the SOAP header
CALL METHOD add_to_soap_header
EXPORTING
ir_xml_document = lr_xml_document
ir_protocol = lr_protocol.
CATCH cx_ai_system_fault INTO le_system_fault.
lv_text = le_system_fault->if_message~get_text( ).
MESSAGE lv_text TYPE 'X'.
ENDTRY.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->GET_WS_INTERFACE_FOR_TRANS
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method GET_WS_INTERFACE_FOR_TRANS.
DATA:
lr_protocol TYPE REF TO if_wsprotocol_ws_header,
lr_xml_document TYPE REF TO if_ixml_document,
le_system_fault TYPE REF TO cx_ai_system_fault,
lv_text TYPE string.
TRY.
* Create instance
CREATE OBJECT er_interface
EXPORTING
logical_port_name = iv_logical_port.
* Get the web service protocol for access to additional fields of the WS SOAP message header
lr_protocol ?= er_interface->get_protocol( if_wsprotocol=>ws_header ).
* Get additional fields for the authentication in the SOAP header
CALL METHOD get_soap_header_auth
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
298 October 2013
Development and Extension Guide – Application-Specific Information
IMPORTING
er_xml_document = lr_xml_document.
* Add additional fields to the SOAP header
CALL METHOD add_to_soap_header
EXPORTING
ir_xml_document = lr_xml_document
ir_protocol = lr_protocol.
CATCH cx_ai_system_fault INTO le_system_fault.
lv_text = le_system_fault->if_message~get_text( ).
MESSAGE lv_text TYPE 'X'.
ENDTRY.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->REFUND_TRANSACTION
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
method REFUND_TRANSACTION.
DATA:
lv_iso_langu TYPE laiso,
lv_iso_currency TYPE tcurc-isocd,
ls_request TYPE refund_transaction_request,
ls_response TYPE refund_transaction_response,
ls_abstract_request_type TYPE abstract_request_type,
lr_ws_proxy TYPE REF TO co_pay_pal_apiinterface,
le_root TYPE REF TO cx_root,
ls_message TYPE bapiret2.
TRY.
* Convert language key to ISO language code
CALL METHOD cl_gdt_conversion=>language_code_outbound
EXPORTING
im_value = sy-langu
IMPORTING
ex_value = lv_iso_langu.
* In case of partial refunding
IF iv_refund_type EQ ZCL_COMMON_PAYPAL_API=>gc_refund_type_partial.
* If the amount to be refunded is not provided
IF iv_currency IS INITIAL OR iv_amount IS INITIAL.
* An amount and a currency must be provided for partial refunding
MESSAGE e015 INTO ls_message-message.
CALL FUNCTION 'BALW_BAPIRETURN_GET2'
October 2013 299
Development and Extension Guide – Application-Specific Information
EXPORTING
type = sy-msgty
cl = sy-msgid
number = sy-msgno
par1 = sy-msgv1
par2 = sy-msgv2
par3 = sy-msgv3
par4 = sy-msgv4
IMPORTING
return = ls_message.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDIF. "If the amount to be refunded is not provided
* Convert currency key to ISO currency code
CALL METHOD cl_gdt_conversion=>currency_code_outbound
EXPORTING
im_value = iv_currency
IMPORTING
ex_value = lv_iso_currency.
ENDIF. "In case of partial refunding
* fill request data
ls_abstract_request_type-error_language = lv_iso_langu.
ls_abstract_request_type-version = gc_paypal_api_version.
ls_request-refund_transaction_request-base = ls_abstract_request_type.
ls_request-refund_transaction_request-transaction_id = iv_transaction_id.
ls_request-refund_transaction_request-refund_type = iv_refund_type.
ls_request-refund_transaction_request-memo = iv_memo.
* In case of partial refunding
IF iv_refund_type EQ ZCL_COMMON_PAYPAL_API=>gc_refund_type_partial.
ls_request-refund_transaction_request-amount-currency_id = iv_currency.
ls_request-refund_transaction_request-amount-content = iv_amount.
ENDIF.
* Get webservice proxy
CALL METHOD get_ws_interface_for_trans
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
iv_logical_port = iv_logical_port
IMPORTING
er_interface = lr_ws_proxy.
300 October 2013
Development and Extension Guide – Application-Specific Information
* Call webservice proxy
CALL METHOD lr_ws_proxy->refund_transaction
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
* Error handling
CATCH cx_gdt_conversion cx_ai_system_fault cx_ai_application_fault INTO le_root.
ls_message-type = 'E'.
ls_message-message = le_root->if_message~get_text( ).
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_message-system.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDTRY.
* Return the refund transaction ID
ev_refund_trans_id = ls_response-refund_transaction_response-refund_transaction_id.
* Handling of errors returned by PayPal
CALL METHOD get_errors_from_paypal
EXPORTING
is_abstract_response_type = ls_response-refund_transaction_response-base
iv_returned_value = ev_refund_trans_id
IMPORTING
et_messages = et_messages
ev_success = ev_success.
endmethod.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->SET_EXPRESS_CHECKOUT
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD set_express_checkout.
DATA:
lv_iso_langu TYPE laiso,
lv_iso_currency TYPE tcurc-isocd,
ls_request TYPE set_express_checkout_request,
ls_response TYPE set_express_checkout_response1,
ls_abstract_request_type TYPE abstract_request_type,
ls_set_express_checkout_req TYPE set_express_checkout_request_1,
lr_ws_proxy TYPE REF TO co_pay_pal_apiaainterface,
October 2013 301
Development and Extension Guide – Application-Specific Information
le_root TYPE REF TO cx_root,
ls_message TYPE bapiret2.
TRY.
* Convert language key to ISO language code
CALL METHOD cl_gdt_conversion=>language_code_outbound
EXPORTING
im_value = sy-langu
IMPORTING
ex_value = lv_iso_langu.
* Convert currency key to ISO currency code
CALL METHOD cl_gdt_conversion=>currency_code_outbound
EXPORTING
im_value = iv_currency
IMPORTING
ex_value = lv_iso_currency.
* fill request data
ls_abstract_request_type-error_language = lv_iso_langu.
ls_abstract_request_type-version = gc_paypal_api_version.
ls_set_express_checkout_req-order_total-currency_id = lv_iso_currency.
ls_set_express_checkout_req-order_total-content = iv_amount.
ls_set_express_checkout_req-return_url = iv_return_url.
ls_set_express_checkout_req-cancel_url = iv_cancel_url.
ls_set_express_checkout_req-invoice_id = iv_invoice_id.
ls_set_express_checkout_req-custom = iv_custom.
ls_request-set_express_checkout_request-base = ls_abstract_request_type.
ls_request-set_express_checkout_request-set_express_checkout_request_d =
ls_set_express_checkout_req.
* Get webservice proxy
CALL METHOD get_ws_interface
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
iv_logical_port = iv_logical_port
IMPORTING
er_interface = lr_ws_proxy.
* Call webservice proxy
CALL METHOD lr_ws_proxy->set_express_checkout
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
* Error handling
CATCH cx_gdt_conversion cx_ai_system_fault cx_ai_application_fault INTO le_root.
302 October 2013
Development and Extension Guide – Application-Specific Information
ls_message-type = 'E'.
ls_message-message = le_root->if_message~get_text( ).
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_message-system.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDTRY.
* Return the token
ev_token = ls_response-set_express_checkout_response-token.
* Handling of errors returned by PayPal
CALL METHOD get_errors_from_paypal
EXPORTING
is_abstract_response_type = ls_response-set_express_checkout_response-base
iv_returned_value = ev_token
IMPORTING
et_messages = et_messages
ev_success = ev_success.
ENDMETHOD.
* <SIGNATURE>-----------------------------------------------------------------------------------
----+
* | Instance Private Method ZCL_COMMON_PAYPAL_API->TRANSACTION_SEARCH
* +---------------------------------------------------------------------------------------------
----+
* +--------------------------------------------------------------------------------------
</SIGNATURE>
METHOD transaction_search.
DATA:
lv_iso_langu TYPE laiso,
ls_request TYPE transaction_search_request,
ls_response TYPE transaction_search_response,
ls_abstract_request_type TYPE abstract_request_type,
lr_ws_proxy TYPE REF TO co_pay_pal_apiinterface,
le_root TYPE REF TO cx_root,
ls_message TYPE bapiret2.
FIELD-SYMBOLS:
<ls_payment_transaction> TYPE payment_transactions.
TRY.
* Convert language key to ISO language code
CALL METHOD cl_gdt_conversion=>language_code_outbound
EXPORTING
October 2013 303
Development and Extension Guide – Application-Specific Information
im_value = sy-langu
IMPORTING
ex_value = lv_iso_langu.
* Fill request data
ls_abstract_request_type-error_language = lv_iso_langu.
ls_abstract_request_type-version = gc_paypal_api_version.
ls_request-transaction_search_request-base = ls_abstract_request_type.
ls_request-transaction_search_request-start_date = iv_start_date.
ls_request-transaction_search_request-end_date = iv_end_date.
ls_request-transaction_search_request-transaction_id = iv_transaction_id.
ls_request-transaction_search_request-invoice_id = iv_invoice_id.
ls_request-transaction_search_request-amount-currency_id = iv_currency.
ls_request-transaction_search_request-amount-content = iv_amount.
* Get webservice proxy
CALL METHOD get_ws_interface_for_trans
EXPORTING
iv_username = iv_username
iv_password = iv_password
iv_signature = iv_signature
iv_logical_port = iv_logical_port
IMPORTING
er_interface = lr_ws_proxy.
* Call webservice proxy
CALL METHOD lr_ws_proxy->transaction_search
EXPORTING
input = ls_request
IMPORTING
output = ls_response.
* Error handling
CATCH cx_gdt_conversion cx_ai_system_fault cx_ai_application_fault INTO le_root.
ls_message-type = 'E'.
ls_message-message = le_root->if_message~get_text( ).
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_message-system.
APPEND ls_message TO et_messages.
CLEAR ls_message.
ev_success = abap_false.
RETURN.
ENDTRY.
* Return found transactions
LOOP AT ls_response-transaction_search_response-payment_transactions ASSIGNING
<ls_payment_transaction>.
APPEND <ls_payment_transaction>-transaction_id TO et_transaction_ids.
304 October 2013
Development and Extension Guide – Application-Specific Information
ENDLOOP.
* Handling of errors returned by PayPal
CALL METHOD get_errors_from_paypal
EXPORTING
is_abstract_response_type = ls_response-transaction_search_response-base
iv_returned_value = et_transaction_ids
IMPORTING
et_messages = et_messages
ev_success = ev_success.
ENDMETHOD.
ENDCLASS.
Note
In many countries, legal regulations apply if you transfer personal data to a third party. To comply with these
regulations, you might need to implement additional measures not included in this document that are not directly
releated to communication with the payment service provider (for example, a logging mechanism to trace which data
is transferred, to whom, and for what purpose).
October 2013 305
Development and Extension Guide – Application-Specific Information
6.1.5 Order-Related SAP CRM Billing
In order-related SAP CRM billing, order management and billing is completed in the SAP CRM back end. Only
financials is completed in the SAP ERP back end. We recommend this scenario when no order fulfillment components
are required (for example, when selling digital services like software by download).
In the order-related SAP CRM billing scenario, configuration and the implementation of BAdI Integrate Payment
Service Providers must be completed in the SAP CRM back end. You must implement BAdI Import Settlement Files
for Each Payment Service Provider in the SAP ERP back end.
The sales order in the SAP CRM back end gets status information from the payment service provider by way of the
payment service provider interface (PSP IF). The sales order in the SAP CRM back end passes the payment service
provider information by way of the CRM billing engine application to financials in the SAP ERP back end for
settlement.
306 October 2013
Development and Extension Guide – Application-Specific Information
Consider the following activities when using the order-related CRM billing scenario.
1. Activate business function in the SAP CRM back end.
Activate the business function CRM_WEB_CHANNEL.
2. Maintain Customizing for PSP integration in the SAP CRM back end.
Make the settings in Customizing for SAP CRM under Customer Relationship Management -> SAP Web
Channel Experience Management -> E-Commerce -> Payment Service Providers.
Note
The first setting Download Payment … is not required.
3. Implement BAdI Integration of Payment Service Providers in the SAP CRM back end.
For more information, see Sample Implementation of BAdI 'Integration of Payment Service Providers' in the
SAP CRM Back End.
4. Configure CRM billing to process transactions involving payment service providers.
Activate the Processing Transactions Involving PSPs feature in the CRMB application in Customizing for
Customer Relationship Management under Billing -> Configure Application.
5. Implement BAdI Import Settlement Files for Each Payment Service Provider.
For more information, see Sample Implementation of BAdI 'Import Settlement Files for Each Payment Service
Provider'.
6. Schedule periodic tasks in the SAP CRM back end.
Use the program Process Incomplete Payment Service Provider Orders (transaction
CRMD_WEC_PSP_ORDER) to identify and process incomplete sales orders and service orders in the SAP
CRM back end that Web shop customers create using payment service providers. For more information, see
the online documentation for the program.
October 2013 307
Development and Extension Guide – Application-Specific Information
6.1.6 Delivery-Related SAP CRM Billing
In delivery-related CRM billing, order management and billing is completed in the SAP CRM back end. Order
fulfillment and financials is completed in the SAP ERP back end.
In the delivery-related CRM billing scenario, configuration and implementation of BAdI Integrate Payment Service
Provider must be completed in the SAP CRM back end. You must implement BAdI Import Settlement Files for Each
Payment Service Provider in the SAP ERP back end.
The sales order in the SAP CRM back end gets status information from the payment service provider by way of the
payment service provider interface (PSP IF). The sales order including its PSP status information is replicated to the
SAP ERP back end. In SAP ERP, logistics execution is processed. Delivery in SAP ERP indicates fulfillment to the
CRM billing engine application in the SAP CRM back end.
The sales order in the SAP CRM back end passes the payment service provider information by way of the CRM billing
engine to financials for settlement.
308 October 2013
Development and Extension Guide – Application-Specific Information
Consider the activities in the following sections when using the delivery-related SAP CRM billing scenario.
1. Activate business function in the SAP ERP back end.
Activate the ERP_WEB_CHANNEL_1 business function.
2. Maintain Customizing for PSP integration in the SAP ERP back end.
Make the settings in Customizing for SAP ERP under Sales and Distribution -> SAP Web Channel Experience
Management -> Payment Service Prov.
3. Activate business function in the SAP CRM back end.
Activate the CRM_WEB_CHANNEL business function.
4. Maintain Customizing for payment service provider integration in the SAP CRM back end.
Make the settings in Customizing for SAP CRM under Customer Relationship Management -> SAP Web
Channel Experience Management -> E-Commerce -> Payment Service Providers.
5. Implement BAdI Integration of Payment Service Providers in the SAP CRM back end.
For more information, see Sample Implementation of BAdI 'Integration of Payment Service Providers' in the
SAP CRM Back End.
6. Configure the CRM billing engine application to process transactions involving payment service providers.
Activate the Processing Transactions Involving PSPs feature in the CRM billing engine application (CRMB) in
Customizing for SAP CRM under Customer Relationship Management -> Billing -> Configure Application.
7. Implement BAdI Import Settlement Files for Each Payment Service Provider.
For more information, see Sample Implementation of BAdI 'Import Settlement Files for Each Payment Service
Provider'.
8. Schedule periodic tasks in the SAP CRM back end.
Use the program Process Incomplete Payment Service Provider Orders (transaction
CRMD_WEC_PSP_ORDER) to identify and process incomplete sales orders and service orders in the SAP
CRM back end that Web shop customers create using payment service providers. For more information, see
the online documentation for the program.
October 2013 309
Development and Extension Guide – Application-Specific Information
6.1.7 Extension Points
6.1.7.1 Passing Custom or Additional Attributes to the Payment Service Provider Interface
To pass additional attributes to the payment service provider interface (PSP IF), you must redefine the
PaymentServiceProviderConnectorImpl class of the module wec/ecom/mc/salestransactions/bo. The corresponding
interface contains the two template methods for this purpose: mapToProcessInitiatePaymentServiceAPIExtension and
mapToProcessCallbackPaymentServiceAPIExtension.
The following code is an example:
public List<NameValueParameter> mapToProcessInitiatePaymentServiceAPIExtension(Order order){
List<NameValueParameter> parameterListIn = new ArrayList<NameValueParameter>();
String netValueWOFreight =
ConversionHelper.convertBigDecimalToStringABAPCommercialNotation(order.getNetValueWOFreight());
parameterListIn.add(new NameValueParameter
("netValueWOFreight", netValueWOFreight));
}
6.1.7.2 Embedding Icons for the Payment Service Provider on the User Interface
Some payment service providers explicitly require Web shop owners to embed icons or graphics on the user
interfaces of Web shops. Icons also enable Web shop owners to emphasize the payment services offered (for
example, to gain attention).
In order to embed icons or graphics, you can extend the following views:
paymentServiceProviderDetailsCheckoutView.xhtml in module wec/comm/mc/payment/ui
This view is used in the checkout process and it contains a list of configured payment services that can be
selected for Web shop orders.
paymentServiceProviderCheckoutCollapsedView.xhtml in module wec/comm/mc/payment/ui
This view displays the selected payment service during checkout (while the checkout step is collapsed).
You can also create a new view which contains all icons of all payment services (also credit cards, if applicable). You
must then include this new view into one of the view areas of your basic pages (for example, in the right hand column
of your home page or the checkout page).
310 October 2013
Development and Extension Guide – Application-Specific Information
6.2 Payment Card Authorization (SAP CRM)
When Web shop customers save orders, the system executes the standard payment card authorization check in the
SAP CRM back end. Note that if authorizations fail or only partially cover transaction amounts, Web shop customers
can still save orders. Therefore, depending on your business scenario, you may want to prevent Web shop customers
from submitting and saving orders when transaction amounts are not fully authorized by implementing the PREPARE
method in Customizing for SAP CRM under Customer Relationship Management -> Transactions -> Basic Settings ->
Business Add-Ins -> BAdI: Transfer Customer-Specific Fields to Middleware. The system calls the method after
authorization and can abort the save with the DO_NOT_SAVE exception. The example implementation
CRM_WEC_PAY_ORD_AUTH shows how to perform such a check.
Caution
The example implementation is for reference only and may not suit your business needs in a productive environment.
October 2013 311
Development and Extension Guide – Application-Specific Information
6.3 Integration of E-Payment Processing Service for Credit
Card Tokenization
Integrating an e-payment processing service into SAP Web Channel Experience Management (WCEM) allows you to
support your preferred secure e-payment provider (SEPP) in your Web shops.
This example shows the steps necessary for enabling credit card number tokenization with a third-party SEPP. With
credit card number tokenization, the issue of PCI compliance is outsourced to the provider since no credit card
numbers reach the SAP CRM or SAP ERP back-end system. Note that in the SAP CRM or SAP ERP system, credit
card tokenization needs to be active. The example only covers the main aspects of the Java UI side.
1. Extend the payment module.
The view in which the Web shop customer enters the credit card data is replaced by the corresponding view
provided by the payment provider. The view delivered by SAP can be found in the payment module, which is
why this module has to be extended.
Suppose the extension namespace is cust.
metadata.xml:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata" lazyLoad="true"
mainModule="false" moduleID="payment">
<moduleType>application</moduleType>
<configForModule>payment</configForModule>
<config-file namespace="cust" part="ui" type="ui-repository">ui-repository.xml</config-
file>
</module>
ui-repository.xml:
<UIRepository xmlns="http://www.sap.com/wec/frw/tc/ui/runtime/ui-repository"
module="payment">
<ViewComponent name="paymentCCardCheckoutView"
componentHandlerClassName="com.cust.wec.app.common.module.payment.ui.handler.CustPa
ymentCCardCheckoutViewHandler" />
</UIRepository>
The custom view needs to be placed into META-INF/resources/cust/payment/components.
2. Provide the implementation of the view paymentCCardCheckoutView in order to reflect how the SEPP
handles the input of credit cards.
The SEPP provides the HTML view for entering the credit card data. This service, which can for example be
JavaScript (JS) based, is called from the view handler CustPaymentCCardCheckoutViewHandler and
exposes the results to the view.
CustPaymentCCardCheckoutViewHandler needs to fulfill 2 tasks: Providing the script coding to the view that
loads the credit card form from the SEPP, and providing the methods to attach a new credit card to the order,
including the credit card attributes such as validity, issuer, CVV, and the tokenized credit card number.
Triggering this view handler method can be done from the JS coding on the view.
An important aspect of the integration is to make sure that it handles AJAX requests (toggling between the
payment methods Invoice - Credit Cards - Cash On Delivery is done using AJAX). Based on the credit card
data entered by the Web shop customer, a token is generated by the SEPP. This token, the credit card type,
and the expiration date are handed over to the SAP CRM back end. This way, user-sensitive data such as the
credit card number are not stored in the SAP CRM back end, but are handled by the SEPP.
3. Encapsulate other payment-relevant options such as gift cards, promotion codes, or loyalty points in a new
step in checkout.
A change in the checkout process configuration is needed in order to separate the payment methods from the
312 October 2013
Development and Extension Guide – Application-Specific Information
other payment-relevant options. This is needed since the payment through the SEPP authorizes and
generates the token first. Only when this is done can the sales transaction be updated.
<Step UITitle="checkout.ui.step.paymentDetails.uititle" ID="S_PAY01" Description="Payment
Details"
STEPGROUP_ID="SG_DETAILS">
<StepElementRef UITitle="checkout.ui.stepelement.promotionCode.uititle"
ID="SE_PAY04" Description="Promotions and Campaigns" showOnOrderConfirm="true"/>
<StepElementRef UITitle="checkout.ui.stepelement.loyalty.uititle" ID="SE_LOY01"
Description="Loyalty" showOnOrderConfirm="true"/>
<StepElementRef UITitle="checkout.ui.stepelement.giftCard.uititle" ID="SE_GC01"
Description="" showOnOrderConfirm="true"/>
</Step>
<Step UITitle="checkout.ui.step.paymentDetails.uititle" ID="S_PAY02" Description="Payment
Details II" STEPGROUP_ID="SG_DETAILS">
<StepElementRef UITitle="checkout.ui.stepelement.paymentMethods.uititle" ID="SE_PAY01"
Description="Payment Methods" showOnOrderConfirm="true"/>
</Step>
4. Take care of the following issues:
Reading of the credit card data from the SEPP in order to display the data in a consistent and user-
friendly way in the collapsed and expanded step in checkout and in the order confirmation, in case the
Web shop customer wants to change the previously entered credit card data
The SEPP process is a 2-step mechanism: The SEPP has to be contacted first, then the token is sent to
the back end. Each checkout step has a Continue button; this button should be hidden or disabled until
the payment step data is ready to be sent to the SAP CRM back end.
October 2013 313
Development and Extension Guide – Application-Specific Information
7 Web Services
7.1 Web Service Entity "Companies"
Web service entity Companies supports the Web service framework functionality for extensions. This allows you to
store and retrieve additional data without making enhancements in the Java code (see also the Development and
Extension Guide: Generic Information for SAP Web Channel Experience Management on SAP Service Marketplace at
http://service.sap.com/wec-inst, section Web Service Extension Handling).
The following example shows how to retrieve the additional field DUNS-NUMBER for a SAP CRM back end.
The recommended test environment is Mozilla Firefox, with the plug-in RESTClient being installed. The corresponding
ABAP object is CRM_WEC_BP_GET_CONT_AND_COMP.
Parameter Value
METHOD GET
URL https://<your_server>:<port>/main/odata/appid/<appID>/Companies(‘<companyID’)?$expand=Extens
ions
HTTP Add to Request Header:
Headers Name: Content-Type
Value: application/atom+xml;charset=iso-8859-1
Basic Authentication: <user> / <password>
HTTP <?xml version='1.0' encoding='utf-8'?>
Response <entry
...
<m:inline>
<feed>
...
<content type="application/xml">
<m:properties>
<d:Parent>Companies</d:Parent>
<d:ParentKeys>'600673'</d:ParentKeys>
<d:PropertyName>DUNS</d:PropertyName>
<d:StringValue>76-982-0861</d:StringValue>
</m:properties>
</content>
</entry>
<entry>
<category term="SAP_WEC.Companies"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<content type="application/xml">
<m:properties>
<d:City>Chicago</d:City>
...
</content>
</entry>
314 October 2013
Development and Extension Guide – Application-Specific Information
Required ABAP adaptations:
Function module CRM_WEC_BP_GET_CONT_AND_COMP: Use an implicit enhancement point at the end of the
function module.
data:
LT_IDENTDETAIL type table of BAPIBUS1006_ID_DETAILS,
LS_IDENTDETAIL type BAPIBUS1006_ID_DETAILS,
LS_EXTENSION_OUT type CRMT_ISALES_EXTENSION_INT,
LV_COMPANY_GUID type BU_PARTNER_GUID.
call function 'BUPA_IDENTIFICATIONDETAILS_GET'
exporting
IV_PARTNER = IV_COMPANY_ID
tables
ET_IDENTIFICATIONDETAIL = LT_IDENTDETAIL.
read table LT_IDENTDETAIL into LS_IDENTDETAIL
with key IDENTIFICATIONTYPE = 'BUP001'. "DUNS
* Create extension entries in case DUNS is maintained
if SY-SUBRC = 0.
call function 'BUPA_NUMBERS_READ'
exporting
IV_PARTNER = IV_COMPANY_ID
importing
EV_PARTNER_GUID = LV_COMPANY_GUID.
* Set ref_guid to separate extension entries for company and contact entity
LS_EXTENSION_OUT-REF_GUID = LV_COMPANY_GUID.
LS_EXTENSION_OUT-NAME = 'DUNS'.
LS_EXTENSION_OUT-VALUE = LS_IDENTDETAIL-IDENTIFICATIONNUMBER.
append LS_EXTENSION_OUT to ET_EXTENSION_OUT.
endif.
October 2013 315
Development and Extension Guide – Application-Specific Information
7.2 Web Service Entity "Consumer"
Web service entity Consumer supports the Web service framework functionality for extensions. This allows you to
store and retrieve additional data without making enhancements in the Java code (see also the Development and
Extension Guide: Generic Information for SAP Web Channel Experience Management on SAP Service Marketplace at
http://service.sap.com/wec-inst, section Web Service Extension Handling).
The following example shows how to store and retrieve the additional fields BUILDING, FLOOR, and ROOM_NO for a
SAP CRM back end. For this example, we use the advantage that the ABAP structure of the underlying function
module already contains these fields. While simply setting these fields, this will be sufficient for the write process, but
other fields that are not yet in the structure might require more enhancements in the system - these are not included in
this example.
The recommended test environment is Mozilla Firefox, with the plug-in RESTClient being installed. The corresponding
ABAP objects are:
CRM_WEC_REGISTER_CONSUMER
CRM_WEC_GET_BP_CONSUMER_DETAIL
CRM_WEC_IUSER_CHANGE
7.2.1 Registration Request via Web Service Consumer
Parameter Value
METHOD POST
URL https://<your_server>:<port>/main/odata/appid/<appID>/Consumers
HTTP Add to Request Header:
Headers Name: Content-Type
Value: application/atom+xml;charset=iso-8859-1
Body <?xml version="1.0" encoding="UTF-8"?>
Content <entry xmlns="http://www.w3.org/2005/Atom"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xml:base="http://<your server>:<port>/main/odata/appid/<appID>/">
<content type="application/xml">
<m:properties>
<d:City>Chicago</d:City>
<d:ConsumerID>temp</d:ConsumerID>
<d:CountryCode>US</d:CountryCode>
<d:DistrictCode>COOK</d:DistrictCode>
<d:EmailAddress>john.doe@anycompany.com</d:EmailAddress>
<d:FaxNumber>759293</d:FaxNumber>
<d:FirstName>John</d:FirstName>
<d:FormattedAddress></d:FormattedAddress>
<d:FormattedName></d:FormattedName>
<d:HouseNumber>644</d:HouseNumber>
<d:LastName>Doe</d:LastName>
<d:LogonID>johndoe4711</d:LogonID>
<d:MiddleName></d:MiddleName>
<d:MobileNumber>759292</d:MobileNumber>
<d:Password>welcome1</d:Password>
<d:PhoneNumber>759291</d:PhoneNumber>
<d:PostalCode>60611-3017</d:PostalCode>
<d:RegionCode>IL</d:RegionCode>
<d:Street>North Lake Shore Drive</d:Street>
<d:TitleCode>0002</d:TitleCode>
</m:properties>
316 October 2013
Development and Extension Guide – Application-Specific Information
</content>
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/wec_Extensions"
type="application/atom+xml;type=feed" title="wec_Extensions" >
<m:inline>
<feed>
<entry>
<category term="SAP_WEC.wec_Extension"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<content type="application/xml">
<m:properties>
<d:Parent>user_Consumers</d:Parent>
<d:ParentKeys>ConsumerID=’temp’</d:ParentKeys>
<d:PropertyName>BUILDING</d:PropertyName>
<d:StringValue>LAK01</d:StringValue>
</m:properties>
</content>
<category term="SAP_WEC.wec_Extension"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<content type="application/xml">
<m:properties>
<d:Parent>user_Consumers</d:Parent>
<d:ParentKeys>ConsumerID=’temp’</d:ParentKeys>
<d:PropertyName>FLOOR</d:PropertyName>
<d:StringValue>3</d:StringValue>
</m:properties>
</content>
<category term="SAP_WEC.wec_Extension"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<content type="application/xml">
<m:properties>
<d:Parent>user_Consumers</d:Parent>
<d:ParentKeys>ConsumerID=’temp’</d:ParentKeys>
<d:PropertyName>ROOM_NO</d:PropertyName>
<d:StringValue>A.23</d:StringValue>
</m:properties>
</content>
</entry>
</feed>
</m:inline>
</link>
</entry>
October 2013 317
Development and Extension Guide – Application-Specific Information
A screenshot should look like this:
Required ABAP adaptations:
Function module CRM_WEC_REGISTER_CONSUMER: Use an implicit enhancement point at the beginning of the
function module.
field-symbols:
<LS_EXTENSION_IN> type CRMT_ISALES_EXTENSION_INT,
<LS_ADDRESS> type CRMS_WEC_ADDRESS,
<LV_VALUE_TO> type ANY.
data:
LV_FIELDNAME_TO(40) type C.
* Read address entry (always 1)
read table ADDRESSES assigning <LS_ADDRESS> index 1.
* Modify extension entries
loop at EXTENSION_IN assigning <LS_EXTENSION_IN>.
318 October 2013
Development and Extension Guide – Application-Specific Information
* For security reason check on the specific fields to be moved
if <LS_EXTENSION_IN>-NAME eq 'BUILDING' or
<LS_EXTENSION_IN>-NAME eq 'ROOM_NO' or
<LS_EXTENSION_IN>-NAME eq 'FLOOR'.
concatenate '<ls_address>-' <LS_EXTENSION_IN>-NAME into LV_FIELDNAME_TO.
assign (LV_FIELDNAME_TO) to <LV_VALUE_TO>.
<LV_VALUE_TO> = <LS_EXTENSION_IN>-VALUE.
endif.
endloop.
7.2.2 Reading Data via Web Service Consumer
Parameter Value
METHOD GET
URL https://<your_server>:<port>/main/odata/appid/<appID>/Consumers(‘<consumerID’)?$expand=Exten
sions
HTTP Add to Request Header:
Headers Name: Content-Type
Value: application/atom+xml;charset=iso-8859-1
Basic Authentication: <user> / <password>
HTTP <?xml version='1.0' encoding='utf-8'?>
Response <entry
...
<m:inline>
<feed>
...
<content type="application/xml">
<m:properties>
<d:Parent>Consumers</d:Parent>
<d:ParentKeys>'7000084664'</d:ParentKeys>
<d:PropertyName>BUILDING</d:PropertyName>
<d:StringValue>LAK01</d:StringValue>
</m:properties>
</content>
</entry>
<entry>
...
<content type="application/xml">
<m:properties>
<d:Parent>Consumers</d:Parent>
<d:ParentKeys>'7000084664'</d:ParentKeys>
<d:PropertyName>ROOM_NO</d:PropertyName>
<d:StringValue>A.23</d:StringValue>
</m:properties>
</content>
</entry>
<entry>
...
<content type="application/xml">
<m:properties>
<d:Parent>Consumers</d:Parent>
<d:ParentKeys>'7000084664'</d:ParentKeys>
<d:PropertyName>FLOOR</d:PropertyName>
<d:StringValue>5</d:StringValue>
</m:properties>
October 2013 319
Development and Extension Guide – Application-Specific Information
</content>
</entry>
</feed>
</m:inline>
</link>
<category term="SAP_WEC.Consumer"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<content type="application/xml">
<m:properties>
<d:City>Chicago</d:City>
<d:ConsumerID>7000084664</d:ConsumerID>
<d:CountryCode>US</d:CountryCode>
<d:CountryDescription>USA</d:CountryDescription>
<d:DistrictCode>COOK</d:DistrictCode>
...
</content>
</entry>
Required ABAP adaptations:
Function module CRM_WEC_GET_BP_CONSUMER_DETAIL: Use an implicit enhancement point at the end of the
function module.
data:
LS_EXTENSION_OUT type CRMT_ISALES_EXTENSION_INT.
* Read standard address as this is the address of Consumer entity
* itself (all other addresses are AdditionalConsumerAddresses)
read table ET_ADDRESSES_DATA into LS_ADDRESS_DATA
with key STANDARDADDRESS = 'X'.
* Create extension entry (no key required)
LS_EXTENSION_OUT-NAME = 'BUILDING'.
LS_EXTENSION_OUT-VALUE = LS_ADDRESS_DATA-BUILDING.
append LS_EXTENSION_OUT to ET_EXTENSION_OUT.
LS_EXTENSION_OUT-NAME = 'FLOOR'.
LS_EXTENSION_OUT-VALUE = LS_ADDRESS_DATA-FLOOR.
append LS_EXTENSION_OUT to ET_EXTENSION_OUT.
LS_EXTENSION_OUT-NAME = 'ROOM_NO'.
LS_EXTENSION_OUT-VALUE = LS_ADDRESS_DATA-ROOM_NO.
append LS_EXTENSION_OUT to ET_EXTENSION_OUT.
7.2.3 Updating Data via Web Service Consumer
Parameter Value
METHOD PUT
URL https://<your_server>:<port>/main/odata/appid/<appID>/Extensions(Parent='Consumers',ParentKeys='
ConsumerID=''7000084664''',PropertyName='FirstName')
HTTP Add to Request Header:
Headers Name: Content-Type
Value: application/atom+xml;charset=iso-8859-1
<b>Basic Authentication: <user> / <password></b>
Body <?xml version="1.0" encoding="UTF-8"?>
Content <entry xmlns="http://www.w3.org/2005/Atom"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
320 October 2013
Development and Extension Guide – Application-Specific Information
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xml:base=" http://<your server>:<port>/main/odata/appid/<appID>/">
<category term="SAP_WEC.wec_Extension"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<content type="application/xml">
<m:properties>
<d:Parent>user_Consumers</d:Parent>
<d:ParentKeys>ConsumerID='7000084664'</d:ParentKeys>
<d:PropertyName>ROOM_NO</d:PropertyName>
<d:StringValue>A.25</d:StringValue>
</m:properties>
</content>
</entry>
Required ABAP adaptations:
Function module CRM_WEC_IUSER_CHANGE: Use an implicit enhancement point at the beginning of the function
module.
field-symbols:
<LS_EXTENSION_IN> type CRMT_ISALES_EXTENSION_INT,
<LS_ADDRESS> type CRMS_WEC_ADDRESS, <LS_ADDRESS_X> type
CRMS_WEC_ADDRESS_X.
* Read standard address as this is the address of Consumer entity
* itself (all other addresses are AdditionalConsumerAddresses)
read table ADDRESSES assigning <LS_ADDRESS>
with key STANDARDADDRESS = 'X'.
read table ADDRESSES_X assigning <LS_ADDRESS_X>
with key STANDARDADDRESS = 'X'.
* Modify extension entries
loop at EXTENSION_IN assigning <LS_EXTENSION_IN>.
* For security reason check on the specific fields to be moved
if <LS_EXTENSION_IN>-NAME eq 'BUILDING'.
<LS_ADDRESS>-BUILDING = <LS_EXTENSION_IN>-VALUE.
<LS_ADDRESS_X>-BUILDING = 'X'.
endif.
if <LS_EXTENSION_IN>-NAME eq 'ROOM_NO'.
<LS_ADDRESS>-ROOM_NO = <LS_EXTENSION_IN>-VALUE.
<LS_ADDRESS_X>-ROOM_NO = 'X'.
endif.
if <LS_EXTENSION_IN>-NAME eq 'FLOOR'.
<LS_ADDRESS>-FLOOR = <LS_EXTENSION_IN>-VALUE.
<LS_ADDRESS_X>-FLOOR = 'X'.
endif.
endloop.
October 2013 321
Development and Extension Guide – Application-Specific Information
7.3 Web Service "SalesOrderItemScheduleLines"
This example shows how you can extend the sales order Web services delivered by SAP, to get the schedule lines for
each sales order item. The SalesOrderItems Web service will have a relation to the SalesOrderItemScheduleLines
Web service and will be the root Web service for the schedule lines. The dependent Web service
SalesOrderItemScheduleLines can be accessed via the navigation property of the root Web service.
Note
With this example, it is only possible to get the schedule lines while a sales order is being read (GET request). It is not
possible to get the schedule lines in response of a POST request since the schedule lines are determined in the back
end and cannot be created using an inline create request (deep create).
1. Create an extension module for the salestransactions module, including corresponding applications (for more
information, , see the Development and Extension Guide: Generic Information for SAP Web Channel
Experience Management on SAP Service Marketplace at http://service.sap.com/wec-inst, section Creating a
Custom Web Site and Custom Web Channel Builder) and Web Channel Builder configuration. In this
example, it is sufficient to create an md and ws development component (DC). For more information about
Web Channel Builder, see the section on Web Channel Builder modules in this guide. You can also see SAP
Library for SAP Web Channel Experience Management on SAP Help Portal at http://help.sap.com/wec.
Choose a release and then Application Help. In SAP Library, choose SAP Web Channel Experience
Management -> Configuration -> Configuring Web Channel Applications (Web Channel Builder).
The new DCs might look like this:
2. Add the following dependencies to the new ws DC:
322 October 2013
Development and Extension Guide – Application-Specific Information
3. Add the following dependencies to the new dpu DC:
4. Add the following dependencies to the new md DC:
5. Add the following content to the metadata.xml file of the created md part. This allows you to use the relation
plug-in provided in the salestransactions module:
metadata.xml
<?xml version="1.0" encoding="UTF-8"?><?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.sap.com/wec/frw/tc/modules/metadata" lazyLoad="true"
mainModule="false" moduleID="salestransactions">
<moduleType>application</moduleType>
<configForModule>salestransactions</configForModule>
<config-file namespace="customer" part="ws" type="ws-config">ws-config.xml</config-file>
<public-part>
<interfaceImplementations>
<!-- Interface for Sales Order Item Attributes relation plugin-->
<interfaceImplementation
interfaceName="com.sap.sales.SalesOrderItemAttributesRelationPlugIn">
<webServiceRelation webServiceName="SalesOrderItems"
targetWebServiceName="SalesOrderItemSchedules"
relationName="SalesOrderItemSchedules" cardinality="MANY" />
</interfaceImplementation>
</interfaceImplementations>
</public-part>
</module>
October 2013 323
Development and Extension Guide – Application-Specific Information
6. Specify your own namespace (here customer) in the module.properties file of both the md part and ws part.
This could look like this:
module.properties
sap.com.moduleId=salestransactions
sap.com.moduleNamespace=customer
sap.com.extendsNamespace=sap
sap.com.modulePart=ws
7. Define your own Web service for reading schedule lines in the ws-config-xml in the ws part:
ws-config.xml
<webServices
xmlns="http://www.sap.com/wec/frw/tc/modules/metadata/webServices"
xmlns:wec="com.sap.wec.core.config" xmlns:xi="http://www.w3.org/2001/XInclude">
<webService webServiceEntityName="SalesOrderItemSchedule"
webServiceName="SalesOrderItemSchedules">
<serviceObject authRequired="true"
beanClassName="com.customer.wec.app.esales.module.transaction.ws.beans.SalesOrderItemSched
uleLineSOBean"
handlerClassName="com.customer.wec.app.esales.module.transaction.ws.handler.SalesOrderItem
ScheduleLineSOHandler"/>
</webService>
</webServices>
8. Create your own service object bean in your ws DC to define the metadata of the newly created Web service:
SalesOrderItemScheduleLineSOBean.java
324 October 2013
Development and Extension Guide – Application-Specific Information
package com.customer.wec.app.esales.module.transaction.ws.beans;
import java.math.BigDecimal;import java.util.Date;package
com.customer.wec.app.esales.module.transaction.ws.beans;
import java.math.BigDecimal;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
import com.sap.wec.tc.core.webservices.metadata.annotation.ServiceBean;
import com.sap.wec.tc.core.webservices.metadata.annotation.ServiceProperty;
import com.sap.wec.tc.core.webservices.so.ServiceObjectBeanBase;
@XmlRootElement(name = "SalesOrderItemSchedule")
@ServiceBean(rootNode = false, shortDescription = "Sales Order Item Schedule Lines")
public class SalesOrderItemScheduleLineSOBean extends ServiceObjectBeanBase {
private String salesOrderKey;
private int itemNumber;
private int scheduleNumber;
private BigDecimal confirmedQuantity;
private Date confirmedDate;
@ServiceProperty(key = true, shortDescription = "Sales Order Key Field", readonly =
true, creatable = false)
public String getSalesOrderKey() {
return salesOrderKey;
}
public void setSalesOrderKey(String salesOrderKey) {
this.salesOrderKey = salesOrderKey;
}
@ServiceProperty(readonly = true, key = true, shortDescription = "Sales Order Item Key
Field)", creatable = false)
public int getItemNumber() {
return itemNumber;
}
public void setItemNumber(int itemNumber) {
this.itemNumber = itemNumber;
}
@ServiceProperty(readonly = true, key = true, shortDescription = "Schedule Item (Key
Field)", creatable = false)
public int getScheduleNumber() {
return scheduleNumber;
}
public void setScheduleNumber(int scheduleNumber) {
this.scheduleNumber = scheduleNumber;
}
@ServiceProperty(readonly = true, creatable = false)
public BigDecimal getConfirmedQuantity() {
October 2013 325
Development and Extension Guide – Application-Specific Information
return confirmedQuantity;
}
public void setConfirmedQuantity(BigDecimal confirmedQuantity) {
this.confirmedQuantity = confirmedQuantity;
}
@ServiceProperty(readonly = true, creatable = false)
public Date getConfirmedDate() {
return confirmedDate;
}
public void setConfirmedDate(Date confirmedDate) {
this.confirmedDate = confirmedDate;
}
}
9. Create your own service object handler in your ws DC to manage the newly created Web service:
SalesOrderItemScheduleLineSOHandler
package com.customer.wec.app.esales.module.transaction.ws.handler;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import
com.customer.wec.app.esales.module.transaction.ws.beans.SalesOrderItemScheduleLineSOBean;
import com.sap.wec.app.common.module.transaction.businessobject.interf.Schedline;
import com.sap.wec.app.common.module.transaction.item.businessobject.interf.Item;
import com.sap.wec.app.common.module.transaction.item.businessobject.interf.ItemList;
import com.sap.wec.app.esales.module.transaction.businessobject.interf.Order;
import com.sap.wec.app.esales.module.transaction.ws.beans.SalesOrderItemSOBean;
import
com.sap.wec.app.esales.module.transaction.ws.handler.SalesOrderDependentObjectSOHandler;
import com.sap.wec.app.esales.module.transaction.ws.util.ExceptionMessageTexts;
import com.sap.wec.tc.core.webservices.so.ServiceObjectKey;
import com.sap.wec.tc.core.webservices.so.ServiceObjectRelation;
import com.sap.wec.tc.core.webservices.so.exception.ServiceApplicationProcessingException;
import com.sap.wec.tc.core.webservices.so.exception.ServiceBadRequestException;
import com.sap.wec.tc.core.webservices.so.request.ServiceRelationRequest;
import com.sap.wec.tc.core.webservices.so.request.ServiceRequestContext;
import com.sap.wec.tc.core.webservices.so.request.ServiceRetrieveRequest;
import com.sap.wec.tc.core.webservices.so.request.ServiceRetrieveRequest.RetrieveType;
public class SalesOrderItemScheduleLineSOHandler extends
SalesOrderDependentObjectSOHandler {
@Override
326 October 2013
Development and Extension Guide – Application-Specific Information
public List<SalesOrderItemScheduleLineSOBean> getObjects(ServiceRetrieveRequest
retrieveRequest)
throws ServiceApplicationProcessingException {
checkRetrieveType(retrieveRequest);
getOrder(orderKeyFromRequest(retrieveRequest));
List<SalesOrderItemScheduleLineSOBean> result = new
ArrayList<SalesOrderItemScheduleLineSOBean>();
for (ServiceObjectKey key : retrieveRequest.getKeyList()) {
Item item = getItem(order, key);
List<Schedline> scheduleLines = item.getScheduleLines();
int scheduleLinesNumber = 1;
for (Schedline schedline : scheduleLines) {
SalesOrderItemScheduleLineSOBean bean = (SalesOrderItemScheduleLineSOBean)
createServiceObjectBean();
bean.setSalesOrderKey(order.getTechKey().getIdAsString());
bean.setItemNumber(item.getNumberInt());
bean.setScheduleNumber(scheduleLinesNumber);
bean.setConfirmedDate(schedline.getCommittedDate());
bean.setConfirmedQuantity(schedline.getCommittedQuantity());
result.add(bean);
scheduleLinesNumber++;
}
}
return result;
}
public ServiceObjectRelation getRelation(ServiceRelationRequest relationRequest)
throws ServiceApplicationProcessingException {
ServiceObjectRelation relation = relationRequest.getRelation();
if ("SalesOrderItemSchedules".equals(relation.getRelationName())) {
ServiceObjectKey sourceKey = relation.getSourceKey();
getOrder(helper.toOrderKey(sourceKey));
String orderKey = order.getTechKey().getIdAsString();
Item item = getItem(order, sourceKey);
int scheduleLinesSize = item.getScheduleLines().size();
if (scheduleLinesSize > 0) {
List<ServiceObjectKey> targetKeys = new
ArrayList<ServiceObjectKey>(scheduleLinesSize);
for (int i = 0; i < scheduleLinesSize; i++) {
Map<String, Object> keyList = new TreeMap<String, Object>();
keyList.put("ScheduleNummber", i + 1);
keyList.put("SalesOrderKey", orderKey);
keyList.put("ItemNumber", Integer.valueOf(item.getNumberInt()));
ServiceObjectKey targetKey = createServiceObjectKey(keyList);
targetKeys.add(targetKey);
}
relation.setTargetKeys(targetKeys);
}
}
return relation;
}
October 2013 327
Development and Extension Guide – Application-Specific Information
private void checkRetrieveType(ServiceRetrieveRequest retrieveRequest)
throws ServiceBadRequestException {
if (retrieveRequest.getType() == RetrieveType.UNSPECIFIED)
throw new
ServiceBadRequestException(ExceptionMessageTexts.SALES_ORDER_ITEMS_ONLY_VIA_MULTI_READ);
}
@Override
public Item getBOReference(ServiceObjectKey key, ServiceRequestContext requestContext)
throws ServiceApplicationProcessingException {
getOrder(helper.toOrderKey(key));
return getItem(order, key);
}
protected Item getItem(Order order, ServiceObjectKey key)
throws ServiceApplicationProcessingException {
Item result = null;
Integer expectedKey = null;
Object no =
key.getComplexKeys().get(SalesOrderItemSOBean.SALES_ORDER_ITEM_NUMBER);
expectedKey = no instanceof Integer ? (Integer) no : Integer.parseInt((String)
no);
result = getItemByKey(expectedKey);
if (result == null)
throw new
ServiceApplicationProcessingException(ExceptionMessageTexts.ITEM_WITH_KEY_DOES_NOT_EXIST
+ expectedKey);
return result;
}
private Item getItemByKey(Integer expectedKey) {
Item result = null;
ItemList itemList = order.getItemList();
for (Item item : itemList) {
int number = item.getNumberInt();
if (expectedKey == number) {
result = item;
break;
}
}
return result;
}
}
10. Add the source root folder for your chosen namespace (in this example, customer) to the assembly public
part of the ui DC, as a Java package tree. Otherwise, the new class added might not be deployed on the
server and an exception might occur since the class is not found.
328 October 2013
Development and Extension Guide – Application-Specific Information
11. Make sure you have the correct configuration within Web Channel Builder:
12. Activate the Web service for schedule lines in the Web Channel Builder configuration:
October 2013 329
Development and Extension Guide – Application-Specific Information
13. Now your GET request will return the available schedule lines for the order items:
330 October 2013