CRM and CX Blogs by SAP
Stay up-to-date on the latest developments and product news about intelligent customer experience and CRM technologies through blog posts from SAP experts.
cancel
Showing results for 
Search instead for 
Did you mean: 

Introduction:


Twitter is an important channel for businesses to connect with new and existing customers, to increase brand awareness or provide timely customer service, also to connect with brand advocates and influencers.
SAP Hybris Marketing omni-channel experience provides a framework to integrate with Twitter to launch Campaigns, in our use-case, to respond in the form of Direct Message to Twitter users who are follow our Official twitter handle. This is also an example to showcase how the integration of various other channels can be realised similarly.

For this prototype implementation, we rely on the generic Action framework and this prototype implementation is specific to SAP Hybris marketing only (On Premise), the architecture for integration with S/4 HANA Cloud Marketing Edition can be found here.

Configuration


1. Establishing connection to Twitter


a. With the intent of sending Direct Messages from a common account (Twitter Handle), define an App in apps.twitter.com
Note down the Consumer Key, Secret, User Token and Secret for use in steps 1.d and 1.e



b. We use TWIBAP open source program for Connectivity and Authorization (http://scn.sap.com/community/abap/
connectivity/blog/2010/08/12/twibap-the-abap-twitter-api)
c. Use the report Z_OAUTH_SETUP_1_API_KEY to register (From Twibap) the application
The program accepts
1. Consumer Key
2. Consumer Secret
3. API Host (api.twitter.com)
and leave the default selection for radio buttons as is.
d. Use the report Z_OAUTH_SETUP_2_REGISTER_USER (From Twibap) to allow the program to handle actions on behalf of user
This report triggers the OAUTH authentication process to get Access Token
e. SM59: Define RFC destination TWITTER for using Twitter APIs
Create a new RFC destination as shown in the screenshot


2. Interaction Contact (CEI_IMG->Contacts and Profiles->Interaction Contacts)


a. Define Origins of Contact ID: To capture the Twitter handle, we define a new Origin ID



b. Use the Import functionality in Data Management to import new /updates for Interaction Contact (mainly to store twitter handle using the newly defined ORIGIN ID)
1. In the Fiori Launchpad, open the application 'Import Data'
2. In the Data Management section, select the Contacts option
3. Download the CSV template, and introduce a new header column at the very beginning, named 'ID_ORIGIN'.
4. Maintain the values in the downloaded template, in our case a Contact with the newly created/defined ORIGIN_ID
5. Upload the file to create or update a Contact, verify the logs and the Contact to see if the uploaded data is in the system. A screenshot of a sample upload file is below.



6. screenshot of successful upload of Contacts


3. Campaigns /Action Framework (CEI_IMG->Campaigns->Campaign)


a. Define Provider Configuration:
A new provider for Twitter with RFC destination and a Provider class
CL_CUAN_MKT_EXEC_TWITTER, which implements IF_CUAN_MKT_EXEC_HTTP_OUTBOUND. In our case, derived from CL_CUAN_MKT_EXEC_SMS



b. Define Sender Profile:
Marketing area specific, unites Provider with sender profile (Sender name and communication medium)



c. Define Campaign Categories and Actions :
Define a new action "TWI_DIRECT_MESSAGE", with an action class implementing interface IF_CUAN_MKT_EXEC_EXECUTE_ACTN
and IF_CUAN_MKT_EXEC_ACTION_PARAM. In our example, derived from CL_CUAN_MKT_EXEC_EXECUTE_SMS and also implementing the interface
IF_CUAN_MKT_EXEC_ACTION_PARAM.

Once a new Action is defined, assign it to an existing Campaign Category or Create a new Campaign Category.


4. Interactions (CEI_IMG->Data Management->Interactions)


a. Define Interaction Types:
An interaction type, a new type DM_OUTBOUND for every successful Direct Message sent.
For Interaction type OUTBOUND_FAILED, we add new reasons TWITTER_ERROR, TWITTER_LIMIT_EXCEED, and
TWITTER_OPTIN_MISSIN for failure to send Direct Messages



b. Assign Interaction Types and Communication Media to Channels:
Assign DM_OUTBOUND to Twitter (TW) communication medium and Social Channel
Assign OUTBOUND_FAILED to Twitter (TW) communication medium and Social Channel


Implementation Details



Sequence Diagram for the Twitter Campaign execution process

The ABAP code for both Adapter class and Action class is available in the Appendix section of this blog

1. Implementation of Adapter class:


CL_CUAN_MKT_EXEC_TWITTER
This provider class typically implements the interface IF_CUAN_MKT_EXEC_HTTP_OUTBOUND, which enables us to influence the HTTP request, process the HTTP response, and also to check the connection.
In this implementation of Action for sending Twitter Direct Messages, we are deriving the provider class from CL_CUAN_MKT_EXEC_EXECUTE_SMS, which gives us some implementation for free. We may as well implement the interface directly.

IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~BUILD_REQUEST
We build the HTTP request URI, Signature base string, HTTP body consisting of OAUTH parameters and sign the message
We begin with building necessary parameters like 'oauth_nonce', 'oauth_timestamp', 'text', 'screen_name', Followed by building the URI (' /1.1/direct_messages/new.json'). Set the request_uri, request_method, content_type and host for the HTTP request
(sample code is available for download at the end of this blog post)

IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~PROCESS_RESPONSE
Get the HTTP response code
Get the cdata from the response object

Set the values for structure es_member_status

IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~CHECK_CONNECTION
As the name suggests, the connection is checked and returns abap_true or abap_false

2. Implementation of Action class:


CL_CUAN_MKT_EXEC_EXECUTE_TWIT
This action class implements the action interface IF_CUAN_MKT_EXEC_EXECUTE_ACTN, which provides methods for processing the Target Group entries in different stages.This also implements 2nd Interface for Action Parameters IF_CUAN_MKT_EXEC_ACTION_PARAM, which helps implementing partner defines new parameters, the method SET_ACTION_DETAILS helps us select an icon, and method SET_ACTION_PARAMETER helps us in giving a name, data type.
Our prototype implementation derives from an abstract class CL_CUAN_MKT_EXEC_EXECUTE_ACTN which provides some free implementation for checking marketing permission, to check if the segmentation object is valid, posting interactions, and excluding members after restart for those which were executed successfully.

IF_CUAN_MKT_EXEC_ACTION_PARAM~SET_ACTION_DETAILS
set Action Icon URL
Example:
es_action-icon_url = 'http://pbs.twimg.com/
profile_images/2284174872/7df3h38zabcvjylnyfe3_bigger.png'.


IF_CUAN_MKT_EXEC_ACTION_PARAM~SET_ACTION_PARAMETER
Define the parameter name, type
action_parameter - The ID of the parameter, must start with “Z” (ZOC_EXPORT_DESCRIPTION)
action_parameter_name - Label for the parameter used
action_parameter_type - controls how the parameter is rendered on the UI
(if_cuan_mkt_orch_constants=>action_param_type-string)
action_parameter_values (optional) - Possible values for parameter, if the parameter type is defined as dropdown

Example:
APPEND VALUE #( action_parameter = 'ZOC_EXPORT_DESCRIPTION'
action_parameter_name = 'Message'
action_parameter_type = if_cuan_mkt_orch_constants=>action_param_type-string ) TO
et_action_parameter.


IF_CUAN_MKT_EXEC_EXECUTE_ACTN~PRE_PROCESS
As the method name suggests, this is called before the members are processed and is used in our case to build the OAUTH parameters
and also parameters from Sender Profile
Example:
cl_cuan_mkt_exec_sms=>get_parameters( EXPORTING iv_sender = 'ZTWI'
IMPORTING et_parameters = et_param
et_messages = DATA(lt_message)
ev_error = ev_error ).


IF_CUAN_MKT_EXEC_EXECUTE_ACTN~PROCESS
Read all the member info extract the twitter handle for the member, by reading the facet which stores the twitter handle create outbound object
Example:
READ TABLE it_param WITH KEY param_name = if_cuan_mkt_exec_c=>c_param_adapter_class
ASSIGNING FIELD-SYMBOL().
CREATE OBJECT eo_sms TYPE (-param_value)
EXPORTING
it_parameters = it_param.

Send the HTTP request (via the outbound object), refer to method SEND_SMS in action implementation for SMS
Finally, write the outbound interactions in the system, refer to method PROCESS in action implementation for SMS

Testing of the Campaigns Integration with Twitter
a. Create /Update Interaction Contact to contain the facet "twitter handle"
b. Create Target Group consisting of Interaction Contacts with a valid Twitter Handle
c. Create a Campaign of category TW (whichever was created and Action assigned), In Automation Tab, select
the Twitter action and whatever message you would like to send to your official channel followers
d. Save and Execute the campaign
e. and Voila, the program would send the direct message on your behalf


Screenshot of a campaign to send Twitter direct message



Screenshot of the Direct Message received from the Hybris Marketing System

Appendix


ABAP code for the Adapter and Action class
class CL_CUAN_MKT_EXEC_TWITTER definition
public
inheriting from CL_CUAN_MKT_EXEC_SMS
create public .

public section.

methods CONSTRUCTOR
importing
!IT_PARAMETERS type CUAN_T_MKT_EXEC_PARAM optional .

methods IF_CUAN_MKT_EXEC_BOUNCE~GET_BOUNCE_COLLECTION_MODE
redefinition .
methods IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~BUILD_REQUEST
redefinition .
methods IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~CHECK_CONNECTION
redefinition .
methods IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~GET_PARAMETERS
redefinition .
methods IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~PROCESS_RESPONSE
redefinition .
protected section.
private section.

data OAUTH type ref to ZCL_OAUTH .
data PARAMETERS type CUAN_T_MKT_EXEC_PARAM .
ENDCLASS.



CLASS CL_CUAN_MKT_EXEC_TWITTER IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_TWITTER->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_PARAMETERS TYPE CUAN_T_MKT_EXEC_PARAM(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD constructor.
super->constructor( it_parameters = it_parameters ).
me->parameters = it_parameters.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_TWITTER->IF_CUAN_MKT_EXEC_BOUNCE~GET_BOUNCE_COLLECTION_MODE
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RV_MODE TYPE CHAR4
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_bounce~get_bounce_collection_mode.

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_TWITTER->IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~BUILD_REQUEST
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_REQUEST TYPE REF TO IF_HTTP_REQUEST
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_http_outbound~build_request.
DATA: appendix TYPE string,
url TYPE string.
DATA: ls_param LIKE LINE OF parameters.
FIELD-SYMBOLS: <parameter> TYPE cuan_s_mkt_exec_param.
"1. Get consumer and User credentials and Build parameters for OAUTH
"this is done in pre-process of action class

"2. Build parameters for a new DM
oauth ?= zcl_oauth=>get_instance( ).
ls_param-param_name = 'oauth_nonce'. "#EC NOTEXT
ls_param-param_value = oauth->create_nonce( length = 8 ).
INSERT ls_param INTO TABLE parameters.

ls_param-param_name = 'oauth_timestamp'. "#EC NOTEXT
ls_param-param_value = oauth->create_timestamp( ).
INSERT ls_param INTO TABLE parameters.

ls_param-param_name = 'text'. "parameter for Twitter API

* data(lv_text) = |viaActionFrw { sy-datum }-{ sy-timlo }|.
data(lv_text) = me->mv_body.
ls_param-param_value = oauth->percent_encode( lv_text ).
INSERT ls_param INTO TABLE parameters.

ls_param-param_name = 'screen_name'. "Recipient name in Twitter API
* ls_param-param_value = 'DevFlashTwi'.
ls_param-param_value = me->mv_recipient.
INSERT ls_param INTO TABLE parameters.
* ENDIF.

"3. build URI
CONCATENATE
'/1.1'
'/direct_messages/new.json'
INTO appendix.

"*--- set url ---*
CONCATENATE
zcl_twa_api=>api_protocol
zcl_twa_api=>api_host
appendix
INTO url.

"4. Set request uri
DATA: http_body TYPE string,
oauth_signature TYPE string,
uri TYPE string.
SORT me->parameters BY param_name.
data: lt_parameters like TABLE OF <parameter>.
LOOP AT me->parameters ASSIGNING <parameter> FROM 6.
http_body = |{ http_body }{ <parameter>-param_name }={ <parameter>-param_value }|.

IF sy-tabix < lines( me->parameters ).
http_body = |{ http_body }&|.
ENDIF.

INSERT <parameter> INTO TABLE lt_parameters.
ENDLOOP.

* url = |{ url }&{ http_body }|.
oauth->set_oauth_url( url ).
oauth->set_parameters( parameters = lt_parameters ).
oauth->sign_message( ).

IF oauth->get_oauth_signature( ) IS NOT INITIAL.
* me->oauth_signature = percent_encode( me->oauth_signature ).
oauth_signature = oauth->percent_encode( oauth->get_oauth_signature( ) ).
http_body = |{ http_body }&oauth_signature={ oauth_signature }|.

ls_param-param_name = 'oauth_signature'. "#EC NOTEXT
ls_param-param_value = oauth_signature.
INSERT ls_param INTO TABLE parameters.
ENDIF.


uri = |{ appendix }|."?{ http_body }|.

io_request->set_header_field(
EXPORTING
name = '~request_uri'
value = uri ).
io_request->set_header_field(
name = '~request_method'
value = 'POST' ).
io_request->set_header_field(
name = 'Content-Type'
value = 'application/x-www-form-urlencoded' ).
io_request->set_header_field(
name = 'host'
value = 'api.twitter.com' ).

"6. set request->cdata
io_request->set_cdata( http_body ).

DATA: lt_headerfields TYPE tihttpnvp.
io_request->get_header_fields(
CHANGING
fields = lt_headerfields ).
DATA(lv_cdata) = io_request->get_cdata( ).

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_TWITTER->IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~CHECK_CONNECTION
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_HTTP_CODE TYPE I
* | [--->] IV_REASON TYPE STRING
* | [--->] IV_CDATA TYPE STRING
* | [--->] IV_CONNECTION_TYPE TYPE STRING(optional)
* | [<---] EV_SUCCESS TYPE BOOLE_D
* | [<---] ET_MESSAGES TYPE BAL_TT_MSG
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_http_outbound~check_connection.
ev_success = abap_true.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_TWITTER->IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~GET_PARAMETERS
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_MESSAGE TYPE BAL_TT_MSG
* | [<-()] RT_PARAMETERS TYPE CUAN_T_MKT_EXEC_PARAM
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_http_outbound~get_parameters.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_TWITTER->IF_CUAN_MKT_EXEC_HTTP_OUTBOUND~PROCESS_RESPONSE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_RESPONSE TYPE REF TO IF_HTTP_RESPONSE
* | [<---] ES_MEMBER_STATUS TYPE CUAN_S_MKT_EXEC_MEMBER_STATUS
* | [<---] ET_MESSAGES TYPE BAL_TT_MSG
* | [<---] EV_STOP_SENDING TYPE ABAP_BOOL
* | [<-->] CT_REQUEST_PARAM TYPE CUAN_T_MKT_EXEC_PARAM(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_http_outbound~process_response.
DATA: lv_http_code TYPE i,
lv_reason TYPE string,
lv_cdata TYPE string,
lv_message TYPE string.

io_response->get_status( IMPORTING code = lv_http_code
reason = lv_reason ).
DATA: lt_headerfields TYPE tihttpnvp.
io_response->get_header_fields(
CHANGING
fields = lt_headerfields ).
lv_cdata = io_response->get_cdata( ).

CASE lv_http_code.

WHEN 200. "Success
es_member_status-ia_type = 'DM_OUTBOUND'.
WHEN OTHERS. "Error
FIND FIRST OCCURRENCE OF REGEX '"message":"(.*)"' IN lv_cdata SUBMATCHES DATA(lv_error).
FIND FIRST OCCURRENCE OF REGEX '"code":(.*),"message"' IN lv_cdata SUBMATCHES DATA(lv_error_code).

IF lv_error IS INITIAL.
MESSAGE e004(cuan_mkt_exec_frw) INTO lv_message WITH lv_http_code lv_reason lv_cdata.
ELSE.
MESSAGE e063(cuan_mkt_exec_frw) WITH lv_error INTO lv_message.
ENDIF.
cl_cuan_mkt_exec_messages=>add_message( CHANGING ct_messages = et_messages ).

IF lv_error_code = 32 OR lv_error_code = 64 OR lv_error_code = 88 OR lv_error_code = 130 OR lv_error_code = 131 OR lv_error_code = 215.
ev_stop_sending = abap_true.
ENDIF.

es_member_status-ia_type = 'OUTBOUND_FAILED'.
CASE lv_error_code.
WHEN 88.
es_member_status-ia_reason = 'TWITTER_LIMIT_EXCEED'.
WHEN 111.
es_member_status-ia_reason = 'TWITTER_OPTIN_MISSIN'.
WHEN OTHERS.
es_member_status-ia_reason = 'TWITTER_ERROR'.
ENDCASE.
ENDCASE.
ENDMETHOD.
ENDCLASS.

 
class CL_CUAN_MKT_EXEC_EXECUTE_TWIT definition
public
inheriting from CL_CUAN_MKT_EXEC_EXECUTE_SMS
create public .

public section.

methods IF_CUAN_MKT_EXEC_ACTION_PARAM~SET_ACTION_DETAILS
redefinition .
methods IF_CUAN_MKT_EXEC_ACTION_PARAM~SET_ACTION_PARAMETER
redefinition .
methods IF_CUAN_MKT_EXEC_EXECUTE_ACTN~PRE_PROCESS
redefinition .
methods IF_CUAN_MKT_EXEC_EXECUTE_ACTN~PROCESS
redefinition .
protected section.

data OAUTH type ref to ZCL_OAUTH .

methods CHECK_COMMUNICATION_LIMITS
redefinition .
methods CHECK_MARKETING_PERMISSION
redefinition .
methods GET_COMM_ID
redefinition .
methods WRITE_HASHES_INTERACTIONS
redefinition .
methods READ_DEP_DATA
redefinition .
private section.

data PARAMETERS type CUAN_T_MKT_EXEC_PARAM .
data MV_DM_TEXT type STRING .

methods APPEND_OAUTH_PARAMETERS
changing
!CT_PARAM type CUAN_T_MKT_EXEC_PARAM .

methods CREATE_OUTBOUND_OBJECT
importing
!IT_PARAM type CUAN_T_MKT_EXEC_PARAM
exporting
!EO_SMS type ref to CL_CUAN_MKT_EXEC_SMS
!EV_ERROR type BOOLE_D .
ENDCLASS.



CLASS CL_CUAN_MKT_EXEC_EXECUTE_TWIT IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->APPEND_OAUTH_PARAMETERS
* +-------------------------------------------------------------------------------------------------+
* | [<-->] CT_PARAM TYPE CUAN_T_MKT_EXEC_PARAM
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD append_oauth_parameters.
FIELD-SYMBOLS: <parameter> TYPE cuan_s_mkt_exec_param.

INSERT INITIAL LINE INTO TABLE ct_param ASSIGNING <parameter>.
<parameter>-param_name = 'oauth_consumer_key'. "#EC NOTEXT
<parameter>-param_value = oauth->get_consumer_key( ).

INSERT INITIAL LINE INTO TABLE ct_param ASSIGNING <parameter>.
<parameter>-param_name = 'oauth_signature_method'. "#EC NOTEXT
<parameter>-param_value = 'HMAC-SHA1'. "#EC NOTEXT

INSERT INITIAL LINE INTO TABLE ct_param ASSIGNING <parameter>.
<parameter>-param_name = 'oauth_token'. "#EC NOTEXT
<parameter>-param_value = oauth->get_oauth_token( ).

INSERT INITIAL LINE INTO TABLE ct_param ASSIGNING <parameter>.
<parameter>-param_name = 'oauth_version'. "#EC NOTEXT
<parameter>-param_value = '1.0'. "#EC NOTEXT
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->CHECK_COMMUNICATION_LIMITS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_COMM_MEDIUM TYPE CUAN_CE_COMM_MEDIUM
* | [<-->] CT_MEMBER_STATUS TYPE CUAN_T_MKT_EXEC_MEMBER_STATUS
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CHECK_COMMUNICATION_LIMITS.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->CHECK_MARKETING_PERMISSION
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_COMM_MEDIUM TYPE CUAN_CE_COMM_MEDIUM
* | [--->] IV_REASON_FAILED TYPE CUAN_CE_IA_REASON(optional)
* | [<-->] CT_MEMBER_STATUS TYPE CUAN_T_MKT_EXEC_MEMBER_STATUS
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CHECK_MARKETING_PERMISSION.
"check for valid data
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->CREATE_OUTBOUND_OBJECT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_PARAM TYPE CUAN_T_MKT_EXEC_PARAM
* | [<---] EO_SMS TYPE REF TO CL_CUAN_MKT_EXEC_SMS
* | [<---] EV_ERROR TYPE BOOLE_D
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD create_outbound_object.
DATA lv_message TYPE string.
DATA lx_root TYPE REF TO cx_root.
READ TABLE it_param WITH KEY param_name = if_cuan_mkt_exec_c=>c_param_adapter_class
ASSIGNING FIELD-SYMBOL(<ls_adapter_class>).
IF sy-subrc <> 0.
MESSAGE e007(cuan_mkt_exec_frw) INTO lv_message WITH 'UNEXPECTED_NO_ADAPTER_CLASS'.
me->add_message( ).
ev_error = abap_true.
ENDIF.

TRY.
CREATE OBJECT eo_sms TYPE (<ls_adapter_class>-param_value)
EXPORTING
it_parameters = it_param.
CATCH cx_root INTO lx_root.
MESSAGE e012(cuan_mkt_exec_frw) INTO lv_message WITH <ls_adapter_class>-param_value.
me->add_message( ).
ev_error = abap_true.
ENDTRY.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->GET_COMM_ID
* +-------------------------------------------------------------------------------------------------+
* | [<---] EV_ERROR TYPE BOOLE_D
* | [<-->] CT_EXEC_MEMBER_STATUS TYPE CUAN_T_MKT_EXEC_MEMBER_STATUS
* | [<-->] CT_MESSAGE TYPE BAL_TT_MSG
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_comm_id.
DATA lt_ic_key TYPE /bobf/t_frw_key.
DATA lt_facet TYPE cuan_t_ce_ic_facet.


LOOP AT ct_exec_member_status ASSIGNING FIELD-SYMBOL(<ls_exec_member>).
APPEND VALUE #( key = <ls_exec_member>-contact_key ) TO lt_ic_key.
ENDLOOP.

DATA(lo_srv_ic) = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_bo_key = if_cuan_ce_interact_contact_c=>sc_bo_key ).
lo_srv_ic->retrieve_by_association( EXPORTING iv_node_key = if_cuan_ce_interact_contact_c=>sc_node-root
iv_association = if_cuan_ce_interact_contact_c=>sc_association-root-facet
it_key = lt_ic_key
iv_fill_data = abap_true
IMPORTING et_data = lt_facet ).


LOOP AT ct_exec_member_status ASSIGNING <ls_exec_member>.

READ TABLE lt_facet ASSIGNING FIELD-SYMBOL(<ls_facet>)
WITH KEY root_key = <ls_exec_member>-contact_key id_origin = 'ZTWITTER'.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
<ls_exec_member>-comm_id = <ls_facet>-id.
ENDLOOP.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->IF_CUAN_MKT_EXEC_ACTION_PARAM~SET_ACTION_DETAILS
* +-------------------------------------------------------------------------------------------------+
* | [<---] ES_ACTION TYPE TY_ACTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_action_param~set_action_details.
es_action-icon_url = 'http://pbs.twimg.com/profile_images/2284174872/7df3h38zabcvjylnyfe3_bigger.png'.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->IF_CUAN_MKT_EXEC_ACTION_PARAM~SET_ACTION_PARAMETER
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_ACTION_PARAMETER TYPE TT_ACTION_PARAMETER
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_action_param~set_action_parameter.
APPEND VALUE #( action_parameter = 'ZOC_EXPORT_DESCRIPTION'
action_parameter_name = 'Message'
action_parameter_type = if_cuan_mkt_orch_constants=>action_param_type-string ) TO et_action_parameter.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->IF_CUAN_MKT_EXEC_EXECUTE_ACTN~PRE_PROCESS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_EXEC_RUN_KEY TYPE /BOBF/CONF_KEY
* | [<---] EV_NO_PARALLELIZATION TYPE BOOLE_D
* | [<---] EV_PACKAGE_SIZE TYPE I
* | [<---] EV_MAX_PARALLEL_TASKS TYPE I
* | [<---] ET_CONTENT_ATTR TYPE CUAN_T_MKT_EXEC_PERS_ATTR
* | [<---] ET_PARAM TYPE CUAN_T_MKT_EXEC_PARAM
* | [<---] ET_MESSAGE TYPE BAL_TT_MSG
* | [<---] EV_ERROR TYPE BOOLE_D
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_execute_actn~pre_process.

me->read_dep_data( EXPORTING iv_exec_run_key = iv_exec_run_key
IMPORTING ev_error = ev_error ).

DATA: token_secret TYPE string,
consumer_secret TYPE string,
secret TYPE string.
FIELD-SYMBOLS: <parameter> TYPE cuan_s_mkt_exec_param.
oauth ?= zcl_oauth=>get_instance(
consumer_name = 'ZKGPMKT'
screen_name = 'kgpblr'
password = 'Welcome1' ).

IF oauth->is_authorized( ) IS INITIAL.
"raise exception
ENDIF.
me->append_oauth_parameters(
CHANGING
ct_param = et_param ).

consumer_secret = oauth->get_consumer_secret( ).
token_secret = oauth->get_oauth_token_secret( ).
secret = |{ consumer_secret }{ token_secret }|.

oauth->set_oauth_secret( secret ).

* add process relevant parameters from content sender profile
TRY.
cl_cuan_mkt_exec_sms=>get_parameters( EXPORTING iv_sender = 'ZTWI'
IMPORTING et_parameters = et_param
et_messages = DATA(lt_message)
ev_error = ev_error ).
CATCH cx_root.
MESSAGE e010(cuan_mkt_exec_frw) WITH me->ms_campaign_content-sending_profile INTO DATA(lv_message).
cl_cuan_mkt_exec_messages=>add_message( CHANGING ct_messages = lt_message ).
ev_error = abap_true.
RETURN.
ENDTRY.

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->IF_CUAN_MKT_EXEC_EXECUTE_ACTN~PROCESS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_EXEC_RUN_KEY TYPE /BOBF/CONF_KEY
* | [--->] IT_TG_MEMBER TYPE /BOBF/T_FRW_KEY
* | [--->] IT_CONTENT_ATTR TYPE CUAN_T_MKT_EXEC_PERS_ATTR
* | [--->] IT_PARAM TYPE CUAN_T_MKT_EXEC_PARAM
* | [--->] IV_PACKAGE_NUMBER TYPE CUAN_MKT_EXEC_PACKAGE_NO
* | [<---] ET_MESSAGE TYPE BAL_TT_MSG
* | [<---] EV_ERROR TYPE BOOLE_D
* | [<---] EV_NUMBER_ERR_INTERACTIONS TYPE I
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_cuan_mkt_exec_execute_actn~process.
DATA:
lt_exec_member_status TYPE cuan_t_mkt_exec_member_status,
lt_pers_content TYPE cuan_t_mkt_exec_pers_content,
lr_key_table TYPE REF TO data,
lv_sms_addr TYPE ad_telnrlg,
lo_sms TYPE REF TO cl_cuan_mkt_exec_sms.

* clear messages from log
clear_messages( ).

* read data of assigned objects
me->read_dep_data( EXPORTING iv_exec_run_key = iv_exec_run_key
it_tg_member = it_tg_member
IMPORTING ev_error = ev_error ).
IF ev_error IS NOT INITIAL.
et_message = me->get_messages( ).
RETURN.
ENDIF.

IF ev_error IS NOT INITIAL.
et_message = me->get_messages( ).
RETURN.
ENDIF.

* convert it tg member to segmentation key structure
me->convert_tg_members( EXPORTING it_tg_member = it_tg_member
IMPORTING er_key_table = lr_key_table
et_ic_key = DATA(lt_ic_key)
et_ia_key = DATA(lt_ia_key)
et_root_ia_key = DATA(lt_root_ia_key)
et_object_type_key = DATA(lt_segobj_key)
et_object_type_ds_key = DATA(lt_segobj_ds_key)
ev_error = ev_error
ev_ic_comp_name = DATA(lv_ic_comp_name)
ev_ia_comp_name = DATA(lv_ia_comp_name) ).
IF ev_error IS NOT INITIAL.
et_message = me->get_messages( ).
RETURN.
ENDIF.

me->initialize_member_status( EXPORTING it_ic_key = lt_ic_key
it_ia_key = lt_ia_key
it_root_ia_key = lt_root_ia_key
ir_key_table = lr_key_table
it_object_type_key = lt_segobj_key
iv_ic_comp_name = lv_ic_comp_name
iv_ia_comp_name = lv_ia_comp_name
it_content_attr = it_content_attr
IMPORTING et_exec_member_status = lt_exec_member_status
et_pers_content = lt_pers_content
ev_error = ev_error ).
IF ev_error IS NOT INITIAL.
APPEND LINES OF me->get_messages( ) TO et_message.
RETURN.
ENDIF.

* read IC root data (TODO integrate with comm ID retrieval)
cl_cuan_mkt_exec_helper=>get_ic_root_data( IMPORTING ev_error = ev_error
CHANGING ct_pers_content = lt_pers_content
ct_member_status = lt_exec_member_status ).

* read communication ids (Twitter Handle)
me->get_comm_id( IMPORTING ev_error = ev_error
CHANGING ct_exec_member_status = lt_exec_member_status
ct_message = et_message ).
IF ev_error IS NOT INITIAL.
RETURN.
ENDIF.
* continue only with successfully checked members
LOOP AT lt_exec_member_status ASSIGNING FIELD-SYMBOL(<ls_exec_member_status>).
READ TABLE lt_pers_content ASSIGNING FIELD-SYMBOL(<ls_personalized_content>)
WITH KEY tg_member_key = <ls_exec_member_status>-tg_member_key BINARY SEARCH.

CHECK sy-subrc IS INITIAL. "todo error handling

* for successful checks create email or sms class
IF <ls_exec_member_status>-ia_type IS INITIAL.

* create email instance and set email address
lv_sms_addr = <ls_exec_member_status>-comm_id.

create_outbound_object( EXPORTING it_param = it_param
IMPORTING eo_sms = lo_sms
ev_error = ev_error ).
IF ev_error = abap_true.
et_message = me->get_messages( ).
RETURN.
ENDIF.

<ls_personalized_content>-sms_message_ref = lo_sms.
<ls_personalized_content>-sms_message_ref->if_cuan_mkt_exec_sms~set_recipient( iv_recipient = lv_sms_addr ).
<ls_personalized_content>-sms_message_ref->if_cuan_mkt_exec_sms~set_body( mv_dm_text ).
ELSE.
* checks not successful write hash to outbound ID and delete entry from personalization table
<ls_exec_member_status>-outbound_id = <ls_personalized_content>-personalization_hash.
DELETE lt_pers_content WHERE tg_member_key = <ls_exec_member_status>-tg_member_key.
ENDIF.
ENDLOOP.

* call http send requests
send_sms( EXPORTING it_param = it_param
it_pers_content = lt_pers_content
CHANGING ct_member_status = lt_exec_member_status ).

* persist hashes & interactions
DATA(lv_error) = me->write_hashes_interactions( it_exec_member_status = lt_exec_member_status
iv_exec_run_key = iv_exec_run_key ).
IF ev_error IS NOT INITIAL.
RETURN.
ENDIF.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->READ_DEP_DATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_EXEC_RUN_KEY TYPE /BOBF/CONF_KEY
* | [--->] IT_TG_MEMBER TYPE /BOBF/T_FRW_KEY(optional)
* | [<---] EV_ERROR TYPE BOOLE_D
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD read_dep_data.
DATA:
lt_key TYPE /bobf/t_frw_key,
lt_root_key TYPE /bobf/t_frw_key,
lt_root TYPE cuan_t_marketing_orch_root,
lt_campaign_root TYPE cuan_t_initiative_root,
lt_action_parameter TYPE cuan_t_marketing_orc_act_par,
lv_content_id TYPE cuan_me_engagement_id.

me->mv_exec_run_key = iv_exec_run_key.
me->mt_tg_members = it_tg_member.
CLEAR: ev_error.
DATA(lo_srv_mktorc) = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_bo_key = if_cuan_marketing_orch_c=>sc_bo_key ).

APPEND VALUE #( key = iv_exec_run_key ) TO lt_key.
lo_srv_mktorc->retrieve_by_association(
EXPORTING
iv_node_key = if_cuan_marketing_orch_c=>sc_node-execution_run
iv_association = if_cuan_marketing_orch_c=>sc_association-execution_run-to_root
it_key = lt_key
iv_fill_data = abap_true
IMPORTING
et_data = lt_root ).

READ TABLE lt_root INDEX 1 ASSIGNING FIELD-SYMBOL(<ls_root>).
IF sy-subrc = 0.
me->ms_mktorc_root = <ls_root>.
APPEND VALUE #( key = <ls_root>-key ) TO lt_root_key.
lo_srv_mktorc->retrieve_by_association(
EXPORTING
iv_node_key = if_cuan_marketing_orch_c=>sc_node-root
iv_association = if_cuan_marketing_orch_c=>sc_association-root-initiative
it_key = lt_root_key
iv_fill_data = abap_true
IMPORTING
et_data = lt_campaign_root ).
READ TABLE lt_campaign_root INDEX 1 INTO me->ms_campaign_root.
IF sy-subrc <> 0.
* -> no error, e.g. confirmation scenario
ENDIF.
ENDIF.

* read tg data by first entry of it_tg_member_keys
READ TABLE it_tg_member ASSIGNING FIELD-SYMBOL(<ls_member>) INDEX 1.
IF sy-subrc IS INITIAL.

DATA: lt_tg_root TYPE cuan_t_tg_root.
DATA: lt_member_key TYPE /bobf/t_frw_key.

* retrieve tg member data
DATA(lo_srv_tg) = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_bo_key = if_cuan_target_group_c=>sc_bo_key ).

APPEND VALUE #( key = <ls_member>-key ) TO lt_member_key.
lo_srv_tg->retrieve_by_association(
EXPORTING
iv_node_key = if_cuan_target_group_c=>sc_node-customer_member
iv_association = if_cuan_target_group_c=>sc_association-customer_member-to_root
iv_fill_data = abap_true
it_key = lt_member_key
IMPORTING
et_data = lt_tg_root ).

* read tg root to determine member type for first entry
READ TABLE lt_tg_root INTO me->ms_tg_root INDEX 1.
IF sy-subrc <> 0.
MESSAGE e007(cuan_mkt_exec_frw) INTO DATA(lv_message) WITH 'READ_TG_ROOT'.
me->add_message( ).
ev_error = abap_true.
ENDIF.
ENDIF.

lo_srv_mktorc->retrieve_by_association(
EXPORTING
iv_node_key = if_cuan_marketing_orch_c=>sc_node-execution_run
iv_association = if_cuan_marketing_orch_c=>sc_association-execution_run-to_parent
it_key = lt_key
IMPORTING
et_target_key = DATA(lt_action_key) ).

lo_srv_mktorc->retrieve_by_association(
EXPORTING
iv_node_key = if_cuan_marketing_orch_c=>sc_node-action
iv_association = if_cuan_marketing_orch_c=>sc_association-action-action_parameter
it_key = lt_action_key
iv_fill_data = abap_true
IMPORTING
et_data = lt_action_parameter ).

* read content ID from action parameter
READ TABLE lt_action_parameter ASSIGNING FIELD-SYMBOL(<ls_action_parameter>)
WITH KEY parameter_id = 'ZOC_EXPORT_DESCRIPTION'.
me->mv_dm_text = <ls_action_parameter>-parameter_value.
ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method CL_CUAN_MKT_EXEC_EXECUTE_TWIT->WRITE_HASHES_INTERACTIONS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_EXEC_MEMBER_STATUS TYPE CUAN_T_MKT_EXEC_MEMBER_STATUS
* | [--->] IV_EXEC_RUN_KEY TYPE /BOBF/CONF_KEY
* | [<---] EV_NUMBER_ERR_INTERACTIONS TYPE I
* | [<-()] RV_ERROR TYPE BOOLE_D
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD write_hashes_interactions.
* write hashes for tracking
* write_hashes( it_exec_member_status ).

* create interactions
DATA ls_template_interaction TYPE cuan_s_ce_ia_int.
ls_template_interaction = VALUE #( id_origin = 'ZTWITTER'
comm_medium = 'SMS'
quantifier = 1
marketing_orchestration_id = me->ms_campaign_content-id
content_title = me->ms_campaign_content-name ).

me->post_interactions(
EXPORTING
it_member_status = it_exec_member_status
is_template_interaction = ls_template_interaction
IMPORTING
ev_error = rv_error ).
ENDMETHOD.
ENDCLASS.
13 Comments