Newer
Older
WeComCompanyPlugin / test_webhook.js

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 = `<xml><ToUserName><![CDATA[${corpId}]]></ToUserName><FromUserName><![CDATA[${user}]]></FromUserName><CreateTime>${timestamp}</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[Hello from test script]]></Content><MsgId>msg_${nonce}</MsgId><AgentID>1000002</AgentID></xml>`;

    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}&timestamp=${timestamp}&nonce=${nonce}`;
    const postBody = `<xml><ToUserName><![CDATA[${corpId}]]></ToUserName><Encrypt><![CDATA[${encryptedMsg}]]></Encrypt></xml>`;

    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();