学习微信开发公众号的第一天(根据文字自动回复文字)

本文详细介绍了微信公众号服务器验证的过程,包括通过ngrok实现内网穿透,使用Express接收微信接口信息,验证消息来源,以及模块化封装获取access_token的方法。同时,讲解了如何处理用户发送的数据,包括获取XML数据,解析XML并格式化,以及实现简单的自动回复功能。整个过程涵盖了微信公众号开发的关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.验证服务器的有效性

1.安装ngrok实现内网穿透

2.将最外层的包拖拽到控制台使用npm init初始化

3.安装express模块 使用npm i express命令

4.将ngrok的数据写入微信接口信息 使用Webstorm接受消息

//引入express模块
const express = require("express");
//创建app应用对象
const app = express();
//验证服务器有效性
// ngrok http 3000
app.use((req,res,next) =>{
console.log(req.query);
})
//监听端口号
app.listen(3000,() => console.log('服务器启动成功'));

5.验证消息是否来自微信服务器

//  1.验证消息是否来自微信服务器
//  目的:计算得出signature与微信传过来的值相比较
//  1.1将微信加密签名的三个参数(timestamp,nonce,token)按照字典序排序组合在一起成一个数组
//  1.2将数组里面所有参数拼接成一个字符串,进行sha1加密
//  1.3加密完成生成signature,与微信服务器发过来的进行比较
//  如果一样 返回echostr给微信服务器
//  如果不一样说明不是来自微信服务器 返回error

5.1 将定义的配置对象写出来

const config={  //定义配置对象
    token:'abc',
    appID:'wxb4fd0fa596cad699',
    appsecret:'49ebd101f6825cc60f5525975dda960f'
}
//  1.1将微信加密签名的三个参数(timestamp,nonce,token)按照字典序排序组合在一起成一个数组
const arr = {timestamp,nonce,token};
const arrSort=arr.sort();   //字典排序方法
    console.log(arrSort);

打开终端窗口安装sha1  再引入sha1模块

 // 1.2将数组里面所有参数拼接成一个字符串,进行sha1加密

const str = arr.join(''); //  字符串拼接
    console.log(str);
    const arrStr = sha1(str); //进行加密
    console.log(arrStr);

 // 1.3加密完成生成signature,与微信服务器发过来的进行比较

  if(arrStr===signature){
        //  如果一样 返回echostr给微信服务器
        res.send(echostr);
    }else{
        //  如果不一样说明不是来自微信服务器 返回error
        res.end('error');
    }

第一步完成效果

//引入express模块
const express = require("express");
//引入sha1模块
const sha1 = require("sha1");
//创建app应用对象
const app = express();
//验证服务器有效性
// ngrok http 3000
const config={  //定义配置对象
    token:'abc',
    appID:'wxb4fd0fa596cad699',
    appsecret:'49ebd101f6825cc60f5525975dda960f'
}
app.use((req,res,next) =>{
// console.log(req.query);
    /*{
        signature: '964a71830c1839fd177b02b3cf9681f4611c3550',   //微信的加密签名
        echostr: '8895758246790034999',                         //微信的随机字符串
        timestamp: '1654859299',                                 //微信发送请求的时间戳
        nonce: '373056014'                                      //微信的随机数字
    }*/
    const {signature,echostr,timestamp,nonce}=req.query;    //解构赋值
    const {token}=config;
//  1.验证消息是否来自微信服务器
//  1.1将微信加密签名的三个参数(timestamp,nonce,token)按照字典序排序组合在一起成一个数组
const arr = [timestamp,nonce,token];
const arrSort=arr.sort();   //字典排序方法
    console.log(arrSort);
    //  1.2将数组里面所有参数拼接成一个字符串,进行sha1加密
const str = arr.join(''); //  字符串拼接
    console.log(str);
    const arrStr = sha1(str); //进行加密
    console.log(arrStr);
    //  1.3加密完成生成signature,与微信服务器发过来的进行比较
    if(arrStr===signature){
        //  如果一样 返回echostr给微信服务器
        res.send(echostr);
    }else{
        //  如果不一样说明不是来自微信服务器 返回error
        res.end('error');
    }
})

//监听端口号
app.listen(3000,() => console.log('服务器启动成功'));

二.模块化封装处理

 

 

三.获取accessToken

// 整理思路:
//     读取本地文件( readAccessToken)
//     -本地有文件
// 判断它是否过期(isValidAccessToken)
// -过期了
// -重新请求获取access_ token(getAccessToken), 保存下来覆盖之前的文件(保证文件是唯一 -的) (saveAccess Token)
// -没有过期
// -直接使用
// -本地没有文件
// -发送请求获取access_ token(getAccessToken), 保存下来(本地文件) (saveAccessToken), 直接使用
// get方式请求地址https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

安装request和request-promise-native库(只需要引入request-promise-native库)

 1.1模拟测试



//引入config
const {appID,appsecret} = require('../config/config');
//引入request-promise-native库
const rp=require('request-promise-native');

class Wechat{
    constructor() {
    }
    getAccessToken() {         //获取access_token
        //定义请求地址
        const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`;
        //发送请求
        rp({method: 'GET', url:url, json: true})
        .then(res => {      //成功时的回调
            console.log(res);
            console.log('成功');
        })
            .catch(err => {     //失败时的回调
                 console.log(err);
            })
    }
}
//模拟测试
const test = new Wechat();
test.getAccessToken();

1.2getAccessToken完整设置方法

//引入config
const {appID,appsecret} = require('../config/config');
//引入request-promise-native库
const rp=require('request-promise-native');

class Wechat{
    constructor() {
    }
    getAccessToken() {         //获取access_token
        //定义请求地址
        const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`;
      return new Promise((resolve,reject) =>{
           //发送请求
           rp({method: 'GET', url:url, json: true})
               .then(res => {      //成功时的回调
                   console.log(res);
                   console.log('成功');
                   // access_token: '57_ZQgtMRumuV5zTyEujjT8K86Xn7eds3CSRmKFEaSHQL7r2xHNpcDWb5-760xWom3He4e_SaPWO00UxE0AAjdmlpDv77P6FrPybFXWGaef4ovG3jZTW1fb
                   // ZhulAWYG56Bou7Qoh7vLLkddAh3uUYPaABANRI',
                   // expires_in: 7200     过期时间

                   //设置access_token的过期时间 -300是提前五分钟 单位是秒所以乘以1000
                   res.expire_in = Date.now() + (res.expire_in - 300) * 1000;
                   //将Promise的状态改为成功的状态
                   resolve(res);
               })
               .catch(err => {     //失败时的回调
                   console.log(err);
                   //将Promise的状态改为失败的状态
                   reject('getAccessToken请求出现了问题'+err);
               })
       })

    }
}
//模拟测试
const test = new Wechat();
test.getAccessToken();

引入fs库模块

完整代码:

// 整理思路:
//     读取本地文件( readAccessToken)
//     -本地有文件
// 判断它是否过期(isValidAccessToken)
// -过期了
// -重新请求获取access_ token(getAccessToken), 保存下来覆盖之前的文件(保证文件是唯一 -的) (saveAccess Token)
// -没有过期
// -直接使用
// -本地没有文件
// -发送请求获取access_ token(getAccessToken), 保存下来(本地文件) (saveAccessToken), 直接使用
// get方式请求地址https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

//引入request-promise-native库
const rp=require('request-promise-native');
//引入fs模块
const {writeFile,readFile} = require('fs');
//引入config
const {appID,appsecret} = require('../config/config');


class Wechat{
    constructor() {
    }
    //获取access_token
    getAccessToken() {
        const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`;
      return new Promise((resolve,reject) =>{
           //发送请求
           rp({method: 'GET', url:url, json: true})
               .then(res => {      //成功时的回调
                   console.log('获取access_token成功');
                   // access_token: '57_ZQgtMRumuV5zTyEujjT8K86Xn7eds3CSRmKFEaSHQL7r2xHNpcDWb5-760xWom3He4e_SaPWO00UxE0AAjdmlpDv77P6FrPybFXWGaef4ovG3jZTW1fb
                   // ZhulAWYG56Bou7Qoh7vLLkddAh3uUYPaABANRI',
                   // expires_in: 7200     过期时间

                   //设置access_token的过期时间 -300是提前五分钟 单位是秒所以乘以1000
                   res.expire_in = Date.now() + (res.expire_in - 300) * 1000;
                   //将Promise的状态改为成功的状态
                   resolve(res);
               })
               .catch(err => {     //失败时的回调
                   console.log(err);
                   //将Promise的状态改为失败的状态
                   reject('getAccessToken请求出现了问题'+err);
               })
       })
    }

    //保存accesstoken
    saveAcessToken(accessToken){
        return new Promise((resolve,reject) => {
            accessToken = JSON.stringify(accessToken)        //将对象保存成JSON字符串
            //将access保存成一个文件
            writeFile("./accessToken",accessToken,err => {
                if(!err){
                    console.log("文件保存成功");
                    resolve();
                }else{
                    console.log("文件保存失败")
                    reject("getAccessToken方法出了问题"+err);
                }
            })
        })
    }

    //读取accesstoken
    readAcessToken(){
        return new Promise((resolve,reject) => {
            readFile("./accessToken",(err,data) => {
                if(!err){
                    console.log("文件读取成功");
                    //将JSON字符串转化为js对象
                    data = JSON.parse(data);
                    resolve(data);
                }else{
                    console.log("文件读取失败")
                    reject("readAccessToken方法出了问题"+err);
                }
            })
        })
    }

    //检查accessToken是不是有效的
    isValidaccesstoken(data){
        //检查传入的参数是否有效
        if(!data && !data.accessToken && !data.expire_in){
        //代表access_token无效
            return false;
        }
        //检查access_token是否在有效期内
        // if(data.expire_in < Date.now()){
        //     //过期
        //     return false;
        // }else{
        //     return true;
        // }
        return data.expire_in > Date.now();
    }
}
//模拟测试
const test = new Wechat();
//     读取本地文件( readAccessToken)
//     -本地有文件
// 判断它是否过期(isValidAccessToken)
// -过期了
// -重新请求获取access_ token(getAccessToken), 保存下来覆盖之前的文件(保证文件是唯一 -的) (saveAccess Token)
// -没有过期
// -直接使用
// -本地没有文件
// -发送请求获取access_ token(getAccessToken), 保存下来(本地文件) (saveAccessToken), 直接使用
// get方式请求地址https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

new Promise((resolve,reject) => {
    test.readAcessToken()
        .then(res => {
            //本地有文件
            // 判断它是否过期(isValidAccessToken)
            if(test.isValidaccesstoken(res)){
            //有效的
                resolve(res);
            }else{
                //过期了
                test.getAccessToken()
                    .then(res => {
                        // 保存下来(本地文件) (saveAccessToken), 直接使用
                        test.saveAcessToken(res)
                        .then(() => {
                            resolve(res);
                        })
                    })
            }
        })
        .catch(err => {
            //本地没有文件
            //-发送请求获取access_ token(getAccessToken)
            test.getAccessToken()
                .then(res => {
                    // 保存下来(本地文件) (saveAccessToken), 直接使用
                    test.saveAcessToken(res)
                        .then(() => {
                            resolve(res);
                        })
                })
        })
})
    .then(res => {
        console.log("获取成功")
         console.log(res);
    })


添加fetchAccessToken方法优化代码

// 整理思路:
//     读取本地文件( readAccessToken)
//     -本地有文件
// 判断它是否过期(isValidAccessToken)
// -过期了
// -重新请求获取access_ token(getAccessToken), 保存下来覆盖之前的文件(保证文件是唯一 -的) (saveAccess Token)
// -没有过期
// -直接使用
// -本地没有文件
// -发送请求获取access_ token(getAccessToken), 保存下来(本地文件) (saveAccessToken), 直接使用
// get方式请求地址https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

//引入request-promise-native库
const rp=require('request-promise-native');
//引入fs模块
const {writeFile,readFile} = require('fs');
//引入config
const {appID,appsecret} = require('../config/config');


class Wechat{
    constructor() {
    }
    //获取access_token
    getAccessToken() {
        const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`;
      return new Promise((resolve,reject) =>{
           //发送请求
           rp({method: 'GET', url:url, json: true})
               .then(res => {      //成功时的回调
                   console.log('获取access_token成功');
                   // access_token: '57_ZQgtMRumuV5zTyEujjT8K86Xn7eds3CSRmKFEaSHQL7r2xHNpcDWb5-760xWom3He4e_SaPWO00UxE0AAjdmlpDv77P6FrPybFXWGaef4ovG3jZTW1fb
                   // ZhulAWYG56Bou7Qoh7vLLkddAh3uUYPaABANRI',
                   // expires_in: 7200     过期时间

                   //设置access_token的过期时间 -300是提前五分钟 单位是秒所以乘以1000
                   res.expire_in = Date.now() + (res.expire_in - 300) * 1000;
                   //将Promise的状态改为成功的状态
                   resolve(res);
               })
               .catch(err => {     //失败时的回调
                   console.log(err);
                   //将Promise的状态改为失败的状态
                   reject('getAccessToken请求出现了问题'+err);
               })
       })
    }

    //保存accesstoken
    saveAcessToken(accessToken){
        return new Promise((resolve,reject) => {
            accessToken = JSON.stringify(accessToken)        //将对象保存成JSON字符串
            //将access保存成一个文件
            writeFile("./accessToken",accessToken,err => {
                if(!err){
                    console.log("文件保存成功");
                    resolve();
                }else{
                    console.log("文件保存失败")
                    reject("getAccessToken方法出了问题"+err);
                }
            })
        })
    }

    //读取accesstoken
    readAcessToken(){
        return new Promise((resolve,reject) => {
            readFile("./accessToken",(err,data) => {
                if(!err){
                    console.log("文件读取成功");
                    //将JSON字符串转化为js对象
                    data = JSON.parse(data);
                    resolve(data);
                }else{
                    console.log("文件读取失败")
                    reject("readAccessToken方法出了问题"+err);
                }
            })
        })
    }

    //检查accessToken是不是有效的
    isValidAccesstoken(dta){
        //检查传入的参数是否有效
        if(!data && !data.accessToken && !data.expire_in){
        //代表access_token无效
            return false;
        }
        //检查access_token是否在有效期内
        // if(data.expire_in < Date.now()){
        //     //过期
        //     return false;
        // }else{
        //     return true;
        // }
        return data.expire_in > Date.now();
    }

    //获取没有过期的AccessToken
    fetchAccessToken() {
        if(this.accesss_token && this.expires_in && this.isValidAccesstoken(this)) {
//说明之前保存过access_token,并且他是有效的,直接使用
            return Promise.resolve({
        access_token:this.accesss_token,
                expires_in:this.expires_in
            })
        }
        return this.readAcessToken()
                .then(async res => {
                    //本地有文件
                    // 判断它是否过期(isValidAccessToken)
                    if (this.isValidAccesstoken(res)) {
                        //有效的
                        // resolve(res);
                        return Promise.resolve(res);
                    } else {
                        //过期了
                        //-发送请求获取access_ token(getAccessToken)
                        const res = await this.getAccessToken()
                        // 保存下来(本地文件) (saveAccessToken), 直接使用
                        await this.saveAcessToken(res)
                        //将请求回来的access_token返回出去
                        //   resolve(res);
                        return Promise.resolve(res);
                    }
                })
                .catch(async err => {
                    //本地没有文件
                    //-发送请求获取access_ token(getAccessToken)
                    const res = await this.getAccessToken()
                    // 保存下来(本地文件) (saveAccessToken), 直接使用
                    await this.saveAcessToken(res)
                    //将请求回来的access_token返回出去
                    // resolve(res);
                    return Promise.resolve(res);
                })
                .then(res => {
                    //将access_token挂载到this上
                    this.accesss_token = res.accesss_token;
                    this.expires_in=res.expire_in;
                    //返回res包装了一层promise对象(此对象为成功的状态)
                    return Promise.resolve(res);
                })
    }
}
    //模拟测试
    const test = new Wechat();
new Promise((resolve,reject) => {
    test.readAcessToken()
        .then(res => {
            //本地有文件
            // 判断它是否过期(isValidAccessToken)
            if(test.isValidaccesstoken(res)){
                //有效的
                resolve(res);
            }else{
                //过期了
                test.getAccessToken()
                    .then(res => {
                        // 保存下来(本地文件) (saveAccessToken), 直接使用
                        test.saveAcessToken(res)
                            .then(() => {
                                resolve(res);
                            })
                    })
            }
        })
        .catch(err => {
            //本地没有文件
            //-发送请求获取access_ token(getAccessToken)
            test.getAccessToken()
                .then(res => {
                    // 保存下来(本地文件) (saveAccessToken), 直接使用
                    test.saveAcessToken(res)
                        .then(() => {
                            resolve(res);
                        })
                })
        })
})
.then(res => {
    console.log("获取成功");
    console.log(res);
})



四.获取用户发送的数据

4.1获取到用户发送的xml数据

新建tool工具包js文件

//工具包函数
module.exports={
    getUserDataAsync(req){
        return new Promise((resolve,reject) => {
            let xmlData = '';
            req.on('data',data=>{
                //当流式数据传递过来时,会将数据注入回调函数中
                console.log(data);
                //读取的数据是buffer类型  需要转换成字符串
                xmlData += data.toString();
            })
                .on('end',() => {
                    //数据接受完毕触发
                    resolve(xmlData);
                })
        })
    }
}

4.2完善auth模块

//验证服务器的有效性模块

//引入sha1模块
const sha1 = require("sha1");
//引入tool模块
const {getUserDataAsync} = require('../utils/tool');
//引入config模块
const config=require('../config/config');

module.exports= () => {
    return async (req, res, next) => {
        const {signature, echostr, timestamp, nonce} = req.query;    //解构赋值
        const {token} = config;
        const sha1Str = sha1([timestamp, nonce, token].sort().join(''));
        //微信服务器会发送两种类型的消息给开发服务器
        //1.get请求 - 验证服务器的有效性
        //2.post请求 -  微信服务器会将用户发送的数据以post请求的方式转发到开发者服务器上
        if (req.method === 'GET') {
            //  1.3加密完成生成signature,与微信服务器发过来的进行比较
            if (sha1Str === signature) {
                //  如果一样 返回echostr给微信服务器
                res.send(echostr);
            } else {
                //  如果不一样说明不是来自微信服务器 返回error
                res.end('error');
            }
        } else if (req.method === 'POST') {
//微信服务器会将用户发送的数据以post请求的方式转发到开发者服务器上
            if (sha1Str != signature) {
                //说明消息不是来自微信服务器
                res.end('error');
            }
//接受请求体中的数据,流式数据
            const xmlData = await getUserDataAsync(req);
            console.log(xmlData);
            //如果开发者服务器没有返回响应给微信服务器,微信服务器会发送三次请求过来
            res.end('');
        } else {
            res.end('error');
        }
    }
}

完整代码(进一步完善tool和auth模块)

//验证服务器的有效性模块

//引入sha1模块
const sha1 = require("sha1");
//引入tool模块
const {getUserDataAsync,parseXMLAsync,formatMessage} = require('../utils/tool');
//引入config模块
const config=require('../config/config');

module.exports = () => {
    return async (req, res, next) => {
        const {signature, echostr, timestamp, nonce} = req.query;    //解构赋值
        const {token} = config;
        const sha1Str = sha1([timestamp, nonce, token].sort().join(''));
        //微信服务器会发送两种类型的消息给开发服务器
        //1.get请求 - 验证服务器的有效性
        //2.post请求 -  微信服务器会将用户发送的数据以post请求的方式转发到开发者服务器上
        if (req.method === 'GET') {
            //  1.3加密完成生成signature,与微信服务器发过来的进行比较
            if (sha1Str === signature) {
                //  如果一样 返回echostr给微信服务器
                res.send(echostr);
            } else {
                //  如果不一样说明不是来自微信服务器 返回error
                res.end('error');
            }
        } else if (req.method === 'POST') {
//微信服务器会将用户发送的数据以post请求的方式转发到开发者服务器上
            if (sha1Str != signature) {
                //说明消息不是来自微信服务器
                res.end('error');
            }
//接受请求体中的数据,流式数据
            const xmlData = await getUserDataAsync(req);
            // console.log(xmlData);

            // <xml><ToUserName><![CDATA[gh_7b0897f3d224]]></ToUserName>  //开发者id
            //     <FromUserName><![CDATA[o6i1N5jHaJKfi9tOCUYcUvq4ec0U]]></FromUserName>  //用户open的id
            //     <CreateTime>1655124555</CreateTime>   // 发送的时间戳
            //     <MsgType><![CDATA[text]]></MsgType>      //发送的消息类型
            //     <Content><![CDATA[233358]]></Content>     //发送的消息内容
            //     <MsgId>23695683538443223</MsgId>     //消息id 微信默认保存3天
            // </xml>
            //将xml数据解析为js对象

            const jsData = await parseXMLAsync(xmlData);
            console.log(jsData);

            // xml: {
            //     ToUserName: [ 'gh_7b0897f3d224' ],
            //         FromUserName: [ 'o6i1N5jHaJKfi9tOCUYcUvq4ec0U' ],
            //         CreateTime: [ '1655126378' ],
            //         MsgType: [ 'text' ],
            //         Content: [ '突突突' ],
            //         MsgId: [ '23695710413710460' ]
            // }
            //格式化数据
            const message = formatMessage(jsData);
            console.log(message);
            // {
            //     ToUserName: 'gh_7b0897f3d224',
            //         FromUserName: 'o6i1N5jHaJKfi9tOCUYcUvq4ec0U',
            //     CreateTime: '1656656271',
            //     MsgType: 'text',
            //     Content: '哈哈哈',
            //     MsgId: '23717613416201809'
            // }


            //如果开发者服务器没有返回响应给微信服务器,微信服务器会发送三次请求过来
            res.end('');
        } else {
            res.end('error');
        }
    }
}
//工具包函数
const {parseString} = require('xml2js'); //  将xml数据转化为js库   2原本是to
module.exports={
    getUserDataAsync(req){
        return new Promise((resolve,reject) => {
            let xmlData = '';
            req.on('data',data => {
                //当流式数据传递过来时,会将数据注入回调函数中
                // console.log(data);
                //读取的数据是buffer类型  需要转换成字符串
                xmlData += data.toString();
            })
                .on('end',() => {
                    //数据接受完毕触发
                    resolve(xmlData);
                })
        })
    },
    parseXMLAsync(xmlData){
        return new Promise((resolve,reject) => {
            parseString (xmlData,{trim:true},(err,data) => {
                if(!err){
                    resolve(data);
                }else{
                    reject("parseXMLAsync方法出了问题"+err);
                }
            })
        })

    },
    formatMessage(jsData){
        let message = {};
        //获取xml对象
        jsData = jsData.xml;
        //判断数据是不是一个对象
        if(typeof jsData === 'object'){
            for (let key in jsData){
                //获取属性值
                let value = jsData[key];
                //过滤空的数据
                //  if(Array.isArray(value) && value > 0){   官方的过滤方法
                if(Array.isArray(value) && value!=' '){   //自己改写的
                    //将合法的数据复制到message对象上
                    message[key] = value[0];
                 }
            }
        }
        return message;
    }

}

 五.简单的自动回复   根据文字回复文字

1.设置回复内容

let content = '你在说什么,我不知道';
if(message.MsgType === 'text'){  //判断用户发送的消息类型
    if(message.Content === '1'){  //全匹配
        content='请不要扣1';
    }else if(message.Content.match('520')){ //半匹配
        content='520';
    }
}

2.auth模块写入xml语句并   注释掉之前回复的空

let replyMessage='<xml>\n' +
    '  <ToUserName><![CDATA['+message.FromUserName+']]></ToUserName>\n' +  //用户id
    '  <FromUserName><![CDATA['+message.ToUserName+']]></FromUserName>\n' +  //开发者id
    '  <CreateTime>'+Date.now()+'</CreateTime>\n' +    //回复的时间戳
    '  <MsgType><![CDATA[text]]></MsgType>\n' +  //回复的类型
    '  <Content><![CDATA['+content+']]></Content>\n' +   //回复的内容
    '</xml>';
//
res.send(replyMessage);


            //如果开发者服务器没有返回响应给微信服务器,微信服务器会发送三次请求过来
            // res.end('');

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值