您现在的位置是:首页 >技术交流 >BTP 使用SPA开发工作流网站首页技术交流

BTP 使用SPA开发工作流

SAP小白kenny 2023-05-27 04:00:02
简介BTP 使用SPA开发工作流

1、前言

目前SAP ABAP 工作流比较难用,BTP上的工作流比较简单便捷。

BTP上面有两款服务可以执行工作流,一种是workflow management 配合Business Rules Services简称BRS,还有一种是接下来会介绍的SP Bulide Process Automation 简称SBPA。

SBPA是从SAP iRPA发展来的,然后再2021年发展为了SPA,除了保留原有的传统的可以自动化处理企业的重复性流程,降低企业成本。SPA增添了workflow的的功能,可以进行审批页面。2023年开始发展为SBPA,在原有的功能上,添加了api触发的手段。

我做的例子是物料主数据的审批,下面介绍整个流程。

2、SPA 创建workflow

 2.1、创建一个流程Process

 

2.2、创建一个API Trigger

 

2.3、创建一个审批通知邮件

 2.3.1、编辑mail process ( 这里首先必须要保证SPA要具备 Outlook的SDK )

 send email 步骤

 2.4、添加一个Approval Form

 

2.5、审批成功的记录调用API写入结果到对应的后台服务器

 2.5.1、获取token

由于我消费的API是需要token验证的odata接口,所以这里需要调用两次 Call Web Service

 

2.5.2、消费API

这里注意,我们取的token是返回参数的header数据,这里如果我们再call web service后面添加一个log message的话,会发现并没有headers参数数据。但是其实是存在的,获取header数据的步骤是:

Step2.obj.headers['x-csrf-token']

 2.6、在完成开发和测试之后,需要点击release和deploy。

然后再Monitor页签的Tri 

 点击view,可以看到调用服务的API,但是注意BTP的上面你的API服务一般都是需要用到oauth 2.0的。

 3、消费SPA的API

3.1、查找spa的token以及相关clientId 或者密码等。

再BTP Cockpit控制台处,点击实例和订阅

找到SPA服务的key,点击

 下图分别展示着SPA服务对应的url , clientid,clientsecret

 3.2、postman测试API

如下图所示,在相应的位置填入相应的内容 

 然后点击get new access token

在弹出框点击use token,然后

在body里面填入相应的报文,点击send

 说明spa没有问题。

3.3、配置spa服务对应的destination

点击Service Instance

选择SPA Instance

 创建之后效果如下

 3.4、Bas开发触发app的功能

3.4.1、在xs-app.json里面配置好destination

 source中就是之前在destinations中添加的配置

3.4.2、ajax调用API

sap.ui.define([
	"sap/ui/model/json/JSONModel"
], function(JSONModel) {
	return {

        fetchToken: function (oController,oData) {
			var that = this;
            var oThisController = oController;
            oThisController.getView().setBusy(true);
            $.ajax({
                url: this._getWorkflowRuntimeBaseURL(oController)+ "/xsrf-token",
                //"/comsapbpmDocumentCentricStartUI/workflowruntime/v1/xsrf-token",
                method: "GET",
                headers: {
                    "X-CSRF-Token": "Fetch"
                },
                success: function (result, xhr, data) {

                    // After retrieving the xsrf token successfully
                    var workflowtoken = data.getResponseHeader("X-CSRF-Token");

                    // Values entered by the user stored in the payload and push to the server.
                    that.startInstance(workflowtoken,oController,oData);

                },
                error: function (jqXHR, textStatus, errorThrown) {

                    //MessageBox.error("Error occurred while fetching work-flow access token.");
                    var sErrorText = oThisController.getMessage("WORKFLOW_ACCESS_TOKEN_ERROR");
                    MessageBox.error(sErrorText + "
 Error:" + errorThrown + ".");
                    oThisController.oBusyDialog.close();
                    return;

                }
            });
        },
		_getWorkflowRuntimeBaseURL: function (oController) {
            var appId = oController.getOwnerComponent().getManifestEntry("/sap.app/id");
            var appPath = appId.replaceAll(".", "/");
            var appModulePath = jQuery.sap.getModulePath(appPath);

            return appModulePath + "/spaWorkflowMaterial/v1";
        },

		startInstance:function(workflowtoken,oController,oData){
            var oThisController = oController;
                // oMdlCommon = oThisController.getParentModel("mCommon");
            var sUrl = this._getWorkflowRuntimeBaseURL(oController) + "/workflow-instances";
            //"/comsapbpmDocumentCentricStartUI/workflowruntime/v1/workflow-instances";
			var sDefinitionId2 = "cn40.syntax.workflowapply.applyPropcess";
			var sPayload = {
                "definitionId": sDefinitionId2,
                "context": {
                    "materialline": {
						"Mateiral": oData.Matnr,
						"MatGrp": oData.Matkl,
						"Unit": oData.Meins,
						"Receipter": "user039@sap-hackathon.io",
						"MateiralDesc": oData.Maktx,
						"ProductId": oData.Spart,
						"OldMaterial":oData.Bismt,
						"RejectReason":""
					}
                    }
                };
				$.ajax({
					url: sUrl,
					method: "POST",
					dataType: "json",
					crossDomain: false,
					contentType: "application/json",
					data: JSON.stringify(sPayload),
					cache: true,
					headers: { // pass the xsrf token retrieved earlier
						"X-CSRF-Token": workflowtoken
	
					},
					success: function (data) {
						MessageBox.success("Request '" +  "' is submitted.");
	
					},
					error: function (jqXHR, textStatus, errorThrown) {
						oThisController.getView().setBusy(false);
						var sErrorText = oThisController.getMessage("WORKFLOW_SERVICE_ERROR");
						MessageBox.error(sErrorText + "
 Error: " + errorThrown + ".");
						return;
					}
				});
		},

		createWorkflowInstance:function(oController, oJsonModel){
			var oData = oJsonModel.getData();
            this.fetchToken(oController,oData);
	}
});

 3.5、失败

这时候如果报错http 403,就需要看看是不是fetch token那里是不是有问题,去network那里看看request header那里是不是有问题

如果是httlp 500 错误,这时候应该是没有根据xs-app.json那里的source和ajax的路径拼接上正确的url。

这时候首先检查xs-app,然后检查ajax的url是不是和destination的名字一样

如果都没有问题的话,点击控制台,进去这个服务看看里面是不是有spa 的detination。

如果没有的话,从控制台cockpit那里导出一份,然后着服务里面impot。

 

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。