原理:
接下来,我们以SAP上的Web开发为例(Neptune开发,可以理解就是基于UI5的开发),逐步举例说明如何实现:
1. 弹出外部地址,并把HookURL作为参数传给采购平台(采购目录)
在前端放一个按钮“SRM目录”,按钮的onclick事件:
var h = screen.height - 100;
var w = screen.width - 80;
var lv_url;
var lv_hook;
lv_url = 'http://XXXXsrmepscs.XXXXXXX.com:52000/SRM-MDM/SRM_MDM?username=Master&password=xxx12345&server=xxxxsrm04&catalog=SRM_MDM_Catalog&namedsearch=R000&unilanguage=ZH&datalanguage=ZH';
lv_hook = 'HOOK_URL=http://edq.autoexpr.com:8000/sap(bD16aCZjPTIwMA==)/bc/bsp/sap/ztest_oci_recei/oic_return.htm';
lv_url = lv_url + '&' + lv_hook;
window.open(lv_url,"_blank",'toolbar=no,location=0,status=no,titlebar=no,menubar=no,width='+w+',height='+h);
其中,lv_url可以是SRM-MDM的目录,也可以是任意支持Catalog Punchout的采购平台;lv_hook 必须是内网的用户终端上可以访问的服务器URL,因为本人对SAP比较熟悉,所以采用的是SAP BSP开发语言的应用,我们将在第三部分进一步说明。
到这里,点击“SRM 目录”就可以正常跳转到采购平台上,让用户选择已经定点定价的商品,虽然SAP SRM的目录也提供搜索、图片等功能,但是跟电商的采购平台相比,的确很Low,我们这里举例子,就用这个比较原始的系统为例,等下一篇,我用京东的例子,让大家更有体感。
2.在采购平台上搜索商品,添加购物车,最后点击“结算”(checkout),生成平台订单,并把订单行明细传给HookURL
电商平台上把OCI标准中定义的字段都放在<input>标签并设置为 hidden,然后通过 submit 就可以把商品名称、数量、单位等信息通过http post传输到HookUL对应的应用上。
3.SAP上的HookURL接收采购平台上发送的HTTPRequest, 解析采购平台上传入的订单明细
我们在SAP上通过SE80创建一个bsp应用:
页面属性:
事件处理器,只要初始化就可以:
具体代码:
* event handler for data retrieval
DATA LWA_ATTR LIKE LINE OF GT_MYATTR.
DATA: LV_STRING TYPE STRING.
DATA: LC_AMPERSAND TYPE STRING VALUE '&'.
DATA : LT_STR TYPE TABLE OF SWASTRTAB.
DATA :CNHT_POST_DATA_LINE(256) TYPE C.
DATA : CNHT_POST_DATA_TAB TYPE TABLE OF CNHT_POST_DATA_LINE.
DATA : LTR_FIELDS TYPE TABLE OF SAVWCTXT.
FIELD-SYMBOLS: <LWA_FIELDS> LIKE LINE OF LTR_FIELDS.
DATA: LS_STR LIKE LINE OF LT_STR.
DATA: LT_ITEMS TYPE table of MMPUR_OCI_CAT_RETURN_TYPE,
lt_text TYPE TABLE OF WSI_OCI_LONGTEXT_S.
data: LWA_ITEMS like LINE OF lt_items.
*
CALL METHOD REQUEST->GET_FORM_FIELDS
CHANGING
FIELDS = GT_MYATTR.
LOOP AT GT_MYATTR INTO LWA_ATTR.
CONCATENATE LV_STRING LWA_ATTR-NAME '=' LWA_ATTR-VALUE LC_AMPERSAND INTO LV_STRING.
ENDLOOP.
*Split string in required internal table format
CALL FUNCTION 'SWA_STRING_SPLIT'
EXPORTING
INPUT_STRING = LV_STRING
MAX_COMPONENT_LENGTH = 255
TABLES
STRING_COMPONENTS = LT_STR
EXCEPTIONS
MAX_COMPONENT_LENGTH_INVALID = 1
OTHERS = 2.
LOOP AT LT_STR INTO LS_STR.
CNHT_POST_DATA_LINE = LS_STR-STR.
APPEND CNHT_POST_DATA_LINE TO CNHT_POST_DATA_TAB.
ENDLOOP.
*Pass this to the FM for mapping
CALL FUNCTION 'WSI_MAP_REQUEST'
EXPORTING
IT_REQUEST = CNHT_POST_DATA_TAB
TABLES
ET_ITS_FIELDS = LTR_FIELDS.
LOOP AT LTR_FIELDS ASSIGNING <LWA_FIELDS>.
TRANSLATE <LWA_FIELDS>-FIELDNAME TO UPPER CASE.
ENDLOOP.
DATA LS_FIELDS LIKE LINE OF LTR_FIELDS.
LOOP AT LTR_FIELDS INTO LS_FIELDS.
CHECK LS_FIELDS-FIELDNAME(17) EQ 'NEW_ITEM-LONGTEXT'
OR LS_FIELDS-FIELDNAME EQ 'NEW_ITEM-DESCRIPTION'
OR LS_FIELDS-FIELDNAME EQ 'NEW_ITEM-VENDORMAT'
OR LS_FIELDS-FIELDNAME EQ 'NEW_ITEM-MANUFACTMAT'.
* REPLACE ALL OCCURRENCES OF:
* lc_html_amp IN ls_fields-fieldcont WITH lc_amper IN CHARACTER MODE,
* lc_html_equ IN ls_fields-fieldcont WITH lc_equal IN CHARACTER MODE.
ENDLOOP.
* This FM maps the data as per the DDIC structure
CALL FUNCTION 'WSI_IMPORT_DATA'
EXPORTING
IV_STRUCTURE_NAME = 'MMPUR_OCI_CAT_RETURN_TYPE'
TABLES
IT_FORM_FIELDS = LTR_FIELDS
ET_WS_ITEM_DATA = LT_ITEMS
ET_LONGTEXT = LT_TEXT
EXCEPTIONS
NO_WEBSERVICE_ACTIVE = 0
NO_DDIC_INFO = 0
IMPORT_ERROR = 0
OTHERS = 0.
"MAP THESE LT_ITEMS & LT_TEXT TO YOUR REQUIRED OUTPUT TABLE STRUCTURE THAT NEEDS TO BE SENT TO UI FOR DISPLAY.
"FOR EX :
*LOOP AT LT_ITEMS INTO LWA_ITEMS.
* CLEAR : LWA_PRITEMS.
* LWA_PRITEMS-PREQ_ITEM = LWA_ITEMS-LINE.
* LWA_PRITEMS-CURRENCY = LWA_ITEMS-CURRENCY.
* LWA_PRITEMS-QUANTITY = LWA_ITEMS-QUANTITY.
* LWA_PRITEMS-UNIT = LWA_ITEMS-UNIT.
* LWA_PRITEMS-PREQ_PRICE = LWA_ITEMS-PRICE.
* LWA_PRITEMS-SHORT_TEXT = LWA_ITEMS-DESCRIPTION.
* LOOP AT LT_TEXT INTO DATA(LWA_TEXT) WHERE LINE = LWA_ITEMS-LINE.
* CONCATENATE LWA_PRITEMS-ITEMTEXT LWA_TEXT-TEXT_LINE INTO LWA_PRITEMS- ITEMTEXT SEPARATED BY SPACE.
* ENDLOOP.
* APPEND LWA_PRITEMS TO LT_PRITEMS.
* CLEAR LWA_ITEMS.
*ENDLOOP.
*Convert the internal table to JSON Object
data: LO_JSON_WRITER type REF TO CL_SXML_STRING_WRITER.
LO_JSON_WRITER = CL_SXML_STRING_WRITER=>CREATE( TYPE = IF_SXML=>CO_XT_JSON ).
”GT_CATALOG_OCI_ITEMS 是母窗口接收到的Json名称
CALL TRANSFORMATION ID SOURCE GT_CATALOG_OCI_ITEMS = LT_ITEMS RESULT XML LO_JSON_WRITER.
GV_JSON_C = CL_ABAP_CODEPAGE=>CONVERT_FROM( LO_JSON_WRITER->GET_OUTPUT( ) ).
* GV_JSON_C = LV_STRING.
页面html参考:
<%@page language="abap" %>
<%@extension name="htmlb" prefix="htmlb" %>
<SCRIPT language="JavaScript">
function displayPopup()
{
var id = document.getElementById('tv2');
var value = id.value;
window.opener.CallParent(value); “这个CallParent方法其实是母窗口中定义的JS函数
window.close( );
}
</SCRIPT>
<htmlb:content design="design2003" >
<htmlb:page title = "Welcome"
onLoad = "displayPopup()" >
<htmlb:form>
<htmlb:gridLayout columnSize = "1"
rowSize = "2" >
<htmlb:gridLayoutCell columnIndex = "1"
rowIndex = "1" >
<htmlb:textView id = "tv1"
design = "HEADER1"
text = "Do not close this window. Your shopping cart is being transferred to your procurement application..." />
</htmlb:gridLayoutCell>
<htmlb:gridLayoutCell columnIndex = "1"
rowIndex = "2" >
<htmlb:textEdit id = "tv2"
text = "<%= gv_json_c %>"
disabled = "FALSE" />
</htmlb:gridLayoutCell>
</htmlb:gridLayout>
</htmlb:form>
</htmlb:page>
</htmlb:content>
4.HookURL把订单明细信息传给母窗口,并关闭HookURL对应的应用
在上面的BSP例子中,我们其实已经实现:
5. 主应用中接收从BSP ZTEST_OCI_RECEI 传入的参数
// 这个方法接收从BSP返回的Json数据
window.CallParent = (function(oData){ set_add_srm_catalog_items(oData); }).bind(this);
// 处理接收到的数据
function set_add_srm_catalog_items(oData)
{
sap.ui.core.BusyIndicator.show();
// GT_CATALOG_OCI_ITEMS 与BSP上的Call transfermation 后跟的参数保持一致
var OCI_Data = JSON.parse(oData).GT_CATALOG_OCI_ITEMS;
//OCI 返回的数据
modelGT_CATALOG_OCI_ITEMS.setData(OCI_Data);
modelGT_CATALOG_OCI_ITEMS.refresh();
getOnlineAjax_GET_CATALOG_OCI_ITEMS();
}
6. SICF 把 ZTEST_OCI_RECEI 应用设置为匿名登录
7.Debug
从采购平台上添加到购物车,并check out后,数据返回到http request:
数据已经返回,接下来就把bsp上的数据通过JSON返回到主应用 。