diff --git a/test_webhook.js b/test_webhook.js
new file mode 100755
index 0000000..b2c4b5c
--- /dev/null
+++ b/test_webhook.js
@@ -0,0 +1,85 @@
+
+const crypto = require('crypto');
+const axios = require('axios');
+
+class WecomCrypto {
+ constructor(token, encodingAesKey) {
+ this.token = token;
+ const aesKey = Buffer.from(encodingAesKey + '=', 'base64');
+ if (aesKey.length !== 32) {
+ throw new Error('Invalid encodingAesKey');
+ }
+ this.key = aesKey;
+ this.iv = aesKey.slice(0, 16);
+ }
+
+ getSignature(timestamp, nonce, encrypt) {
+ const sorted = [this.token, timestamp, nonce, encrypt].sort().join('');
+ const sha1 = crypto.createHash('sha1');
+ sha1.update(sorted);
+ return sha1.digest('hex');
+ }
+
+ encrypt(text) {
+ const randomBytes = crypto.randomBytes(16);
+ const textBytes = Buffer.from(text);
+ const textLengthBytes = Buffer.alloc(4);
+ textLengthBytes.writeUInt32BE(textBytes.length, 0);
+
+ const corpId = "ww0da105afdbf73b04"; // Hardcoded from your config
+ const corpIdBytes = Buffer.from(corpId);
+
+ const buffer = Buffer.concat([randomBytes, textLengthBytes, textBytes, corpIdBytes]);
+
+ const cipher = crypto.createCipheriv('aes-256-cbc', this.key, this.iv);
+ cipher.setAutoPadding(false);
+
+ // PKCS#7 padding
+ const blockSize = 32;
+ const padding = blockSize - (buffer.length % blockSize);
+ const paddingBytes = Buffer.alloc(padding, padding);
+
+ const finalBuffer = Buffer.concat([buffer, paddingBytes]);
+
+ const encrypted = Buffer.concat([cipher.update(finalBuffer), cipher.final()]);
+ return encrypted.toString('base64');
+ }
+}
+
+async function sendTestRequest() {
+ const token = "NC73HfvnFUgz";
+ const encodingAesKey = "YsZhCtNwguf7jGFKo1GSaraYekbm28tFWaqzH4vItGV";
+ const corpId = "ww0da105afdbf73b04";
+ const user = "test_user_from_script";
+
+ const wecomCrypto = new WecomCrypto(token, encodingAesKey);
+
+ const timestamp = Math.floor(Date.now() / 1000).toString();
+ const nonce = Math.random().toString(36).substring(2);
+
+ const plainXml = `${timestamp}msg_${nonce}1000002`;
+
+ const encryptedMsg = wecomCrypto.encrypt(plainXml);
+ const signature = wecomCrypto.getSignature(timestamp, nonce, encryptedMsg);
+
+ const url = `http://127.0.0.1:18789/webhooks/wecom/self_build_app?msg_signature=${signature}×tamp=${timestamp}&nonce=${nonce}`;
+ const postBody = ``;
+
+ console.log("Sending request to:", url);
+
+ try {
+ const response = await axios.post(url, postBody, {
+ headers: { 'Content-Type': 'application/xml' }
+ });
+ console.log("Response Status:", response.status);
+ console.log("Response Body:", response.data);
+ } catch (error) {
+ console.error("Error sending request:", error.message);
+ if (error.response) {
+ console.error("Error Response Status:", error.response.status);
+ console.error("Error Response Body:", error.response.data);
+ }
+ }
+}
+
+sendTestRequest();
diff --git a/wecom-api.js b/wecom-api.js
index 0dd9508..feab1ca 100755
--- a/wecom-api.js
+++ b/wecom-api.js
@@ -184,6 +184,10 @@
title: "AI Agent",
desc: text,
},
+ card_action: {
+ type: "url",
+ url: "#",
+ },
},
}),
});