目錄
?1. 前言
2. 正文
2.1 技術方案
2.2 策略上下文
2.2 添加客戶策略實現類
2.3?修改客戶信息策略實現類
2.4 默認策略實現類
2.5 接收事件的實體類(可以根據事件格式的參數做修改)
2.6 實際接收回調結果的接口
近日在開發企業微信的自建應用時,涉及到一個需求需要監聽企業微信的事件通知比如:刪除聯系,添加聯系人,修改聯系人等事件通知,今天給大家看一下我是怎么實現的。
?1. 前言
? ? ? ? 在企業微信中以客戶聯系功能舉例,客戶聯系的回調事件如下:
? ? ? ? 需要注意的是只有用戶在客戶端或者說管理端進行操作的時候才會回調響應的事件通知,如果說通過api去進行操作的話是不會產生回調事件的。
? ? ? ? 然后需要到我們企微后臺中將應用的消息通知給打開:
? ? ? ? 配置回調地址如下:
? ? ? ? 需要注意的時候,在配置回調地址的時候,企微會向該url發起一個get請求來進行校驗,(而實際上回調事件是post請求,所以需要有兩個方式的請求)所以這個url必須是公網能夠訪問的,官網鏈接
? ? ? ? get請求如下:
@ApiOperation("驗證回調接口")@GetMapping("/callback/external-user")public String verifyURL(@RequestParam(name = "msg_signature") final String msgSignature,@RequestParam(name = "timestamp") final String timestamp,@RequestParam(name = "nonce") final String nonce,@RequestParam(name = "echostr") final String echostr) {String sEchoStr = null;try {WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, aesKey, corpId);// 隨機字符串sEchoStr = wxcpt.verifyUrl(msgSignature, timestamp, nonce, echostr);} catch (Exception e) {logger.error("error ", e);}return sEchoStr;}
我使用的依賴如下:
<dependency><groupId>com.github.liyiorg</groupId><artifactId>weixin-popular</artifactId><version>2.8.30</version>
</dependency>
2. 正文
2.1 技術方案
? ? ? ? 為了代碼以后能夠更好的維護和擴展。結合企微回調事件的特點:不同的事件有不同的ChangeType,所以我這里使用策略模式來對不同的事件進行解耦操作具體如下
2.2 策略上下文
@Component
public class CallbackContext {@Autowiredprivate WechatCallbackLogService callbackLogService;private final Map<String, CallbackStrategy> callbackStrategyMap;/*** 通過不同的changeType返回不同的策略,沒有選擇則返回默認策略模式* @param callbackStrategyMap spring容器管理的所有CallbackStrategy類*/@Autowiredpublic CallbackContext(Map<String, CallbackStrategy> callbackStrategyMap) {this.callbackStrategyMap = callbackStrategyMap;}public void execute(WechatCallbackLog callbackBean) {CallbackStrategy callbackStrategy = callbackStrategyMap.get(callbackBean.getChangeType());if (Objects.isNull(callbackStrategy)) {callbackStrategy = callbackStrategyMap.get("default_external_contact");}//保存日志callbackStrategy.operate(callbackBean);callbackLogService.insertLog(callbackBean);}
}
2.2 添加客戶策略實現類
/*** @author light pwd* @description 添加企業客戶事件* @date 2024/11/25*/
@Component("add_external_contact")
public class AddExternalCallbackStrategy implements CallbackStrategy {private static final Logger LOGGER = LoggerFactory.getLogger(AddExternalCallbackStrategy.class);/*** 添加企業客戶事件* changeType:add_external_contact*/@Overridepublic void operate(WechatCallbackLog callbackBean) {System.out.println("我是添加客戶回調事件");}}
2.3?修改客戶信息策略實現類
/*** @author light pwd* @description* @date 2024/11/25*/
@Component("edit_external_contact")
public class EditExternalCallbackStrategy implements CallbackStrategy {/*** 編輯企業客戶事件:edit_external_contact* 如果備注修改了則同步修改線索的名稱,如果備注為空則取昵稱* 線索判斷邏輯:(通過手機號Or當前員工的userId)+當前客戶的externalUserId* 優先使用手機號*/@Overridepublic void operate(WechatCallbackLog callbackBean) {System.out.println("我是修改客戶信息回調事件");}}
2.4 默認策略實現類
當觸發沒有實現的回調事件時會調用該方法
/*** @author light pwd* @description* @date 2024/11/25*/
@Component("default_external_contact")
public class DefaultCallBackStrategy implements CallbackStrategy {/***默認策略模式*/@Overridepublic void operate(WechatCallbackLog callbackBean) {callbackBean.setRemark("沒有該回調的實現方法:" + callbackBean.getChangeType());}
}
2.5 接收事件的實體類(可以根據事件格式的參數做修改)
/*** @author light pwd* @description* @date 2024/11/25*/
public class WechatCallbackLog implements Serializable {private String id;private String changeType;private String userId;private Date createTime;private String event;private String toUserName;private String fromUserName;private String msgType;private String externalUserId;private String state;private String source;private String failReason;private String data;private String remark;private Date createTime1;private String errorCode;private String errMsg;/*** 回調的策略方法執行狀態:0成功,1失敗*/private Short status;//省略了getter和setter方法
}
2.6 實際接收回調結果的接口
@ApiOperation("實際回調請求的接口")@ResponseBody@PostMapping(value = "/callback/external-user")public Result<String> callbackApp(@RequestBody String sPostData,@RequestParam(name = "msg_signature") final String sMsgSignature,@RequestParam(name = "timestamp") final String sTimestamp,@RequestParam(name = "nonce") final String sNonce) {try {WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, aesKey, corpId);//解密String sMsg = wxcpt.decryptMsg(sMsgSignature, sTimestamp, sNonce, sPostData);//將post數據轉換為mapMap<String, String> dataMap = MessageUtil.parseXml(sMsg);WechatCallbackLog callbackBean = convertToBean(dataMap);callbackContext.execute(callbackBean);logger.info("event json : {}", JSONObject.toJSONString(dataMap));} catch (Exception e) {logger.error("error ", e);}return Result.success("成功");}/*** 將回調的值轉為WechatCallbackLog* @param dataMap* @return*/private WechatCallbackLog convertToBean(Map<String, String> dataMap) {String changeType = MapUtils.getString(dataMap, "ChangeType");String userId = MapUtils.getString(dataMap, "UserID");Date createTime = new Date(MapUtils.getLong(dataMap, "CreateTime") * 1000);String event = MapUtils.getString(dataMap, "Event");String toUserName = MapUtils.getString(dataMap, "ToUserName");String fromUserName = MapUtils.getString(dataMap, "FromUserName");String msgType = MapUtils.getString(dataMap, "MsgType");String externalUserId = MapUtils.getString(dataMap, "ExternalUserID");String state = MapUtils.getString(dataMap, "State");String source = MapUtils.getString(dataMap, "Source");String failReason = MapUtils.getString(dataMap, "FailReason");WechatCallbackLog callbackLog = new WechatCallbackLog();callbackLog.setChangeType(changeType);callbackLog.setCreateTime(createTime);callbackLog.setUserId(userId);callbackLog.setEvent(event);callbackLog.setToUserName(toUserName);callbackLog.setFromUserName(fromUserName);callbackLog.setMsgType(msgType);callbackLog.setExternalUserId(externalUserId);callbackLog.setState(state);callbackLog.setSource(source);callbackLog.setFailReason(failReason);callbackLog.setData(dataMap.toString());return callbackLog;}
給大家看一下我保存的回調結果日志記錄
?以上就是我的實現方案,如果有問題歡迎大家評論區交流!
路在腳下,勇往直前,追求卓越,成就夢想!!