微信开发系列之四 - 将SAP C4C的数据更改通知发送到微信公众号上
文章系列目录
- Wechat development series 1 – setup your development environment
- Wechat development series 2 – development Q&A service using nodejs
- Wechat development series 3 – Trigger C4C Account creation in Wechat app
- Wechat development series 4 – Send C4C Data change notification to Wechat app
- Wechat development series 5 – embedded your UI5 application to Wechat app
- Wechat development series 6 – Retrieve Wechat User info via oAuth2 and display it in UI5 application
- Wechat development series 7 – use Redis to store Wechat conversation history
- Wechat development series 8 – Map integration
- Wechat development series 9 – Create C4C Social Media Message and Service within Wechat app
- Wechat development series 10 – Use Wechat app to receive Service Request reply made from C4C
In previous blog when a Wechat user subscribes the subscription Wechat account, a new individual customer is automatically created in C4C system.
So technically Wechat is the source(sender) of dataflow and our C4C system is the dataflow target ( receiver ), and the nodejs server acts as a middleware.
In this blog, let’s try the other way around: suppose any one has made changes on this automatically created account in C4C system, the corresponding Wechat user will receive a notification in his/her Wechat app. Such notification is sent by C4C and Wechat app is the receiver.
Implementation detail
(1) Since in the third blog of this series, I use the standard field “LastName” of Customer BO to store the Wechat ID of the user who has performed the subscription,
and later in C4C, any user could change this field.
As a result in this blog, I create a new extension field in common node of Customer BO to store the Wechat ID.
import AP.Common.GDT;
import AP.FO.BusinessPartner.Global;
[Extension] businessobject AP.FO.BusinessPartner.Global:Customer {
// root node of Customer is not extendable
node Common {
[Label("Wechat ID")] element WechatID:LANGUAGEINDEPENDENT_EXTENDED_Text;
}
}
And create a new BeforeSave.absl to copy the value of FamilyName into extension field WechatID.
import ABSL;
var common = this.Common.GetFirst();
if( common.WechatID.IsInitial()) {
common.WechatID = common.Person.Name.FamilyName;
}
(2) Create a new OData service to expose this WechatID, mark field ObjectID, ParentObjectID and WechatID.
Test this OData Service via url: https:///sap/c4c/odata/cust/v1/zindividualcustomer/CustomerCommonCollection?$filter=ParentObjectID%20eq%20%2700163E20C9511EE7B8975BD4AB3F60C0%27 Make sure it can return the correct value of three fields as expected:
(3) Once the account is changed in C4C, a notification should be sent from C4C to our nodejs server. This automatic notification mechanism could be achieved via C4C OData event notification. See another of my blog Leverage C4C Odata notification to monitor C4C Opportunity change in CRM system for detail.
The setting below means whenever a change on Customer BO occurs in C4C, a change notification will be sent to the endpoint automatically: https://wechatjerry.herokuapp.com/c4c So far all development / configuration in C4C side is done.
(4) In nodejs server implementation, create a new field in config object:
- field name: indivudualCustomerNewurl
- field value: https:///sap/c4c/odata/cust/v1/zindividualcustomer/CustomerCommonCollection?$filter= Since the endpoint I configure in C4C system is: https://wechatjerry.herokuapp.com/c4c And when a given account is changed in C4C, a HTTP post with the following kind of payload will be sent to this endpoint:
{“businessObject”:”CUSTOMER”,”businessObjectId”:”00163E20C9511EE7B8975BD4AB3F60C0″,”event”:””,”odataServiceEndpoint”:”https://<your tenant>/sap/byd/odata/v1/zindividualcustomer/CustomerCommonCollection(‘00163E20C9511EE7B8975BD4AB3F60C0’)”}
So in nodejs server, I have to react to this Post request.
Main logic is implemented in module notifyWechatUser, which uses the guid of changed Customer BO instance as an input parameter.
Inside the implementation of notifyWechatUser, which consists of two steps:
function notifyWechatUser(uuid,res){
console.log("begin to read uuid: " + uuid);
_getAccount(uuid).then(function(wechatID){
res.status(200).end();
sendMessage(wechatID, "Dear user, A kind reminder: your C4C account is changed in the system.");
});
}
(1) call _getAccount to get the WechatID stored on Common node of Customer BO via OData call. (2) sendMessage to send a hard coded sentence to the corresponding Wechat user.
Implementation of _getAccount
function _getAccount(uuid) {
var AccountBOguid = uuid;
var detailODataUrl = config.indivudualCustomerNewurl;
var parentID = 'ParentObjectID eq '' + AccountBOguid + ''';
detailODataUrl = detailODataUrl + encodeURI(parentID);
var getOptions = {
url: detailODataUrl,
method: "GET",
json:true,
headers: {
"content-type": "application/json",
'Authorization': 'Basic ' + new Buffer(config.credential).toString('base64')
}
};
return new Promise(function(resolve,reject){
var requestC = request.defaults({jar: true});
console.log("request with url: " + detailODataUrl);
requestC(getOptions,function(error,response,body){
var wechatID = body.d.results[0].WechatID;
console.log("wechat id: " + wechatID);
resolve(wechatID);
}); // end of requestC
});
}
Implementation of sendMessage
var config = require("../../config.js");
var request = require("request");
function printObject(oData){
for( var a in oData){
console.log("key: " + a);
console.log("value: " + oData[a]);
if( typeof oData[a] === "object"){
printObject(oData[a]);
}
}
}
function sendWCMeaasge(toUser,sMessage){
console.log("begin to send message to user: " + toUser + " with message: " + sMessage);
var options = {
url:"https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" +
config.accessToken,
method: "POST",
json:true,
headers: {
"content-type": "application/json"},
body:{
"touser":toUser,
"msgtype":"text",
"text":
{
"content":sMessage
}
}
};
request(options,function(error,response,data){
console.log("error? " + error);
console.log("response: " + response);
console.log("data: " + data);
console.log("response...............................................");
//printObject(response);
console.log("data.....................................................");
console.log("Status message: " + response.statusMessage);
console.log("Data: " + data.errmsg);
});
}
module.exports = sendWCMeaasge;
Final achievement
As soon as I subscribe the test Wechat account by scanning QRCode, a new account 1000443 is created in C4C system.
When this account is changed in the system:
The corresponding Wechat user successfully received the notification sent by C4C in the Wechat app:
- 基于机器学习方法的POI品类推荐算法
- 【Scikit-Learn 中文文档】多类和多标签算法 - 监督学习 - 用户指南 | ApacheCN
- 【Scikit-Learn 中文文档】新异类和异常值检测 - 无监督学习 - 用户指南 | ApacheCN
- Golang中使用echo框架、MongoDB、JWT搭建REST API
- 在对象的原型上添加方法?
- KMeans聚类算法思想与可视化
- 控制台断点调试
- 函数声明与表达式的区别
- 揭开身份证验证的神秘面纱
- return语句的用法
- JavaScript基础讲解 - 函数与参数
- Go实战--golang中使用RethinkDB(gorethink/gorethink.v3)
- 如何修改alert样式
- 用R语言做数据清理(详细教程)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python入门教程笔记(一)简介、变量及基本数据类型
- C#知识点讲解之C#delegate、event、Action、EventHandler的使用和区别
- typescript高级用法之infer的理解与使用
- 基于业务场景下的图片/文件上传方案总结
- LeetCode96|二叉搜索树中的搜索
- LeetCode95|字符串中的第一个唯一字符
- LeetCode94|Pow(x,n)
- LeetCode93|数值的整数次方
- LeetCode92|排序数组
- 缓存 | 从本地缓存到分布式缓存, Guava, Caffeine, Memcached, Redis
- WebView三问—B站真题
- C++核心准则T.140:为所有可能重用的操作命名
- Service三问
- 事件分发机制三问
- C++核心准则T.141:如果你需要只在一个地方使用的简单的函数对象,使用无名的lambda表达式