企業微信自建應用開發回調事件實現方案

目錄

?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;}

給大家看一下我保存的回調結果日志記錄

?以上就是我的實現方案,如果有問題歡迎大家評論區交流!

路在腳下,勇往直前,追求卓越,成就夢想!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/77968.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77968.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/77968.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux將多個塊設備掛載到一個掛載點

在 Linux 系統中&#xff0c;直接將多個塊設備掛載到同一個掛載點是不可能的。這是因為 Linux 的文件系統掛載機制設計為一個掛載點一次只能關聯一個文件系統。如果嘗試將多個塊設備掛載到同一個掛載點&#xff0c;后一次掛載會覆蓋前一次的掛載&#xff0c;導致只有最后掛載的…

Spark-SQL(四)

本節課學習了spark連接hive數據&#xff0c;在 spark-shell 中&#xff0c;可以看到連接成功 將依賴放進pom.xml中 運行代碼 創建文件夾 spark-warehouse 為了使在 node01:50070 中查看到數據庫&#xff0c;需要添加如下代碼&#xff0c;就可以看到新創建的數據庫 spark-sql_1…

野外價值觀:在真實世界的語言模型互動中發現并分析價值觀

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

el-select+vue-virtual-scroller解決數據量大卡頓問題

解決el-select中數據量過大時&#xff0c;顯示及搜索卡頓問題&#xff0c;及正確的回顯默認選中數據 粗略的封裝了組件&#xff0c;有需要各種屬性自定義的&#xff0c;自己添加設置下 環境 node 16.20.1 npm 8.19.4 vue2、element-ui "vue-virtual-scroller"…

Sqlite3交叉編譯全過程

Sqlite3交叉編譯全過程 一、概述二、下載三、解壓四、配置五、編譯六、安裝七、驗證文件類型八、移植8.1、頭文件sqlite3.h8.2、動態鏈接庫移植8.3、靜態態鏈接庫移植 九、驗證使用9.1. 關鍵函數說明 十、觸發器使用十一、sqlite表清空且恢復id值十二、全文總結 一、概述 SQLi…

軟考軟件設計師考試情況與大綱概述

文章目錄 **一、考試科目與形式****二、考試大綱與核心知識點****科目1&#xff1a;計算機與軟件工程知識****科目2&#xff1a;軟件設計** **三、備考建議****四、參考資料** 這是一個系列文章的開篇 本文對2025年軟考軟件設計師考試的大綱及核心內容進行了整理&#xff0c;并…

【數學建模】孤立森林算法:異常檢測的高效利器

孤立森林算法&#xff1a;異常檢測的高效利器 文章目錄 孤立森林算法&#xff1a;異常檢測的高效利器1 引言2 孤立森林算法原理2.1 核心思想2.2 算法流程步驟一&#xff1a;構建孤立樹(iTree)步驟二&#xff1a;構建孤立森林(iForest)步驟三&#xff1a;計算異常分數 3 代碼實現…

【Android面試八股文】Android系統架構【一】

Android系統架構圖 1.1 安卓系統啟動 1.設備加電后執行第一段代碼&#xff1a;Bootloader 系統引導分三種模式&#xff1a;fastboot&#xff0c;recovery&#xff0c;normal&#xff1a; fastboot模式&#xff1a;用于工廠模式的刷機。在關機狀態下&#xff0c;按返回開機 鍵進…

jvm-獲取方法簽名的方法

在Java中&#xff0c;獲取方法簽名的方法可以通過以下幾種方式實現&#xff0c;具體取決于你的需求和使用場景。以下是詳細的介紹&#xff1a; 1. 使用反射 API Java 提供了 java.lang.reflect.Method 類來獲取方法的相關信息&#xff0c;包括方法簽名。 示例代碼&#xff1a…

DeepSeek和Excel結合生成動態圖表

文章目錄 一、前言二、3D柱狀圖案例2.1、pyecharts可視化官網2.2、Bar3d-Bar3d_puch_card2.3、Deepseek2.4、WPS2.5、動態調整數據 一、前言 最近在找一些比較炫酷的動態圖表&#xff0c;用于日常匯報&#xff0c;于是找到了 DeepseekExcel王牌組合&#xff0c;其等同于動態圖…

探索 .bat 文件:自動化任務的利器

在現代計算機操作中&#xff0c;批處理文件&#xff08;.bat 文件&#xff09;是一種簡單而強大的工具&#xff0c;它可以幫助我們自動化重復性任務&#xff0c;工作效率提高。盡管隨著編程語言和腳本工具的發展&#xff0c;.bat 文件的使用頻率有所下降&#xff0c;但它依然是…

PyTorch與自然語言處理:從零構建基于LSTM的詞性標注器

目錄 1.詞性標注任務簡介 2.PyTorch張量&#xff1a;基礎數據結構 2.1 張量創建方法 2.2 張量操作 3 基于LSTM的詞性標注器實現 4.模型架構解析 5.訓練過程詳解 6.SGD優化器詳解 6.1 SGD的優點 6.2 SGD的缺點 7.實用技巧 7.1 張量形狀管理 7.2 廣播機制 8.關鍵技…

【C++】特殊類的設計、單例模式以及Cpp類型轉換

&#x1f4da; 博主的專欄 &#x1f427; Linux | &#x1f5a5;? C | &#x1f4ca; 數據結構 | &#x1f4a1;C 算法 | &#x1f310; C 語言 上篇文章&#xff1a; C 智能指針使用&#xff0c;以及shared_ptr編寫 下篇文章&#xff1a; C IO流 目錄 特殊類的設…

探索 Flowable 后端表達式:簡化流程自動化

什么是后端表達式&#xff1f; 在 Flowable 中&#xff0c;后端表達式是一種強大的工具&#xff0c;用于在流程、案例或決策表執行期間動態獲取或設置變量。它還能實現自定義邏輯&#xff0c;或將復雜邏輯委托…… 后端表達式在 Flowable 的后端運行&#xff0c;無法訪問前端…

【Lua】Lua 入門知識點總結

Lua 入門學習筆記 本教程旨在幫助有編程基礎的學習者快速入門Lua編程語言。包括Lua中變量的聲明與使用&#xff0c;包括全局變量和局部變量的區別&#xff0c;以及nil類型的概念、數值型、字符串和函數的基本操作&#xff0c;包括16進制表示、科學計數法、字符串連接、函數聲明…

符號速率估計——小波變換法

[TOC]符號速率估計——小波變換法 一、原理 1.Haar小波變換 小波變換在信號處理領域被成為數學顯微鏡&#xff0c;不同于傅里葉變換&#xff0c;小波變換可以觀測信號隨時間變換的頻譜特征&#xff0c;因此&#xff0c;常用于時頻分析。 ??當小波變換前后位置處于同一個碼元…

android contentProvider 踩坑日記

寫此筆記原因 學習《第一行代碼》到第8章節實現provider時踩了一些坑&#xff0c;因此記錄下來給后來人和自己一個提示&#xff0c;僅此而已。 包含內容 Sqlite數據庫CURD內容provider界面provider項目中書籍管理provider實現邏輯用adb shell確認providercontentResolver接收…

Eureka、LoadBalance和Nacos

Eureka、LoadBalance和Nacos 一.Eureka引入1.注冊中心2.CAP理論3.常見的注冊中心 二.Eureka介紹1.搭建Eureka Server 注冊中心2.搭建服務注冊3.服務發現 三.負載均衡LoadBalance1.問題引入2.服務端負載均衡3.客戶端負載均衡4.Spring Cloud LoadBalancer1).快速上手2)負載均衡策…

【開關電源】關于GaN反激電源開關噪聲

文章目錄 0 前言1 設計信息1.1 設計需求1.2 原理圖1.3 電源表現 2 原因分析3 橫向對比TI UCG28826 &#xff08;GaN&#xff09;采購的普通QR反激變換器 4 總結 0 前言 筆者原計劃設計一款省電的&#xff0c;效率尚可的&#xff0c;穩定的2路輸出反激電源&#xff0c;用于系統…

DOCA介紹

本文分為兩個部分&#xff1a; DOCA及BlueField介紹如何運行DOCA應用&#xff0c;這里以DNS_Filter為例子做大致介紹。 DOCA及BlueField介紹&#xff1a; 現代企業數據中心是軟件定義的、完全可編程的基礎設施&#xff0c;旨在服務于跨云、核心和邊緣環境的高度分布式應用工作…