node-webot / wechat-api Goto Github PK
View Code? Open in Web Editor NEWWechat API / 主动调用 API
License: Other
Wechat API / 主动调用 API
License: Other
source/node_modules/wechat/node_modules/wechat-api/lib/util.js:12
if (data.errcode) {
^
TypeError: Cannot read property 'errcode' of null
at source/node_modules/wechat/node_modules/wechat-api/lib/util.js:12:13
at done (source/node_modules/wechat/node_modules/wechat-api/node_modules/urllib/lib/urllib.js:346:5)
at source/node_modules/wechat/node_modules/wechat-api/node_modules/urllib/lib/urllib.js:547:9
at decodeContent (source/node_modules/wechat/node_modules/wechat-api/node_modules/urllib/lib/urllib.js:407:14)
at IncomingMessage.<anonymous> (source/node_modules/wechat/node_modules/wechat-api/node_modules/urllib/lib/urllib.js:513:7)
at IncomingMessage.emit (events.js:119:20)
at _stream_readable.js:888:16
at process._tickCallback (node.js:337:11)
对应的是util.js中第12行
exports.wrapper = function (callback) {
return function (err, data, res) {
callback = callback || function () {};
if (err) {
err.name = 'WeChatAPI' + err.name;
return callback(err, data, res);
}
if (data.errcode) { //这一行,data为空进崩溃
err = new Error(data.errmsg);
err.name = 'WeChatAPIError';
err.code = data.errcode;
return callback(err, data, res);
}
callback(null, data, res);
};
};
追查到urllib.js的547行调用,再之前是对data
的处理,不知是否有极端情况没考虑到。
decodeContent(res, body, function (err, data, encoding) {
if (err) {
return done(err, body, res);
}
// if body not decode, dont touch it
if (!encoding && TEXT_DATA_TYPES.indexOf(args.dataType) >= 0) {
// try to decode charset
try {
data = decodeBodyByCharset(data, res);
} catch (_) {
// if error, dont touch it
return done(null, data, res);
}
if (args.dataType === 'json') {
if (responseSize === 0) {
data = null;
} else {
var r = parseJSON(data);
if (r.error) {
err = r.error;
} else {
data = r.data;
}
}
}
}
if (responseAborted) {
// err = new Error('Remote socket was terminated before `response.end()` was called');
// err.name = 'RemoteSocketClosedError';
debug('Request#%d %s: Remote socket was terminated before `response.end()` was called', reqId, url);
}
done(err, data, res); //547行,data为空
});
lib/api_device.js
make(exports, 'getDeviceStatus', function (deviceId, callback) {
// https://api.weixin.qq.com/device/get_stat?access_token=ACCESS_TOKEN&device_id=DEVICE_ID
var url = 'https://api.weixin.qq.com/device/compel_unbind?access_token=' + this.token.accessToken + "&device_id=" + deviceId;
this.request(url, {dataType: 'json'}, wrapper(callback));
});
请改正.
/usr/local/software/node/nodeWechat/node_modules/wechat-api/lib/util.js:12
if (data.errcode) {
^
TypeError: Cannot read property 'errcode' of null
at /usr/local/software/node/nodeWechat/node_modules/wechat-api/lib/util.js:12:13
at done (/usr/local/software/node/nodeWechat/node_modules/wechat-api/node_modules/urllib/lib/urllib.js:346:5)
at /usr/local/software/node/nodeWechat/node_modules/wechat-api/node_modules/urllib/lib/urllib.js:547:9
at decodeContent (/usr/local/software/node/nodeWechat/node_modules/wechat-api/node_modules/urllib/lib/urllib.js:407:14)
at IncomingMessage. (/usr/local/software/node/nodeWechat/node_modules/wechat-api/node_modules/urllib/lib/urllib.js:513:7)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:943:16
at process._tickCallback (node.js:419:13)
error: Forever detected script exited with code: 8
error: Script restart attempt #24
按照代码,调用getLatestToken获取不到token的。像示例一样把access_token写入文件的话,这个文件是要我手动初始化写入内容?
var api = new API('appid', 'secret', function (callback) {
// 传入一个获取全局token的方法
fs.readFile('access_token.txt', 'utf8', function (err, txt) {
if (err) {return callback(err);}
callback(null, JSON.parse(txt));
});
}, function (token, callback) {
// 请将token存储到全局,跨进程、跨机器级别的全局,比如写到数据库、redis等
// 这样才能在cluster模式及多机情况下使用,以下为写入到文件的示例
fs.writeFile('access_token.txt', JSON.stringify(token), callback);
});
1、MP3只有10k
2、临时素材的接口没有问题。
api.uploadMedia("/material/a.mp3", "voice", function(err, result) {
console.log(result);
});
3、永久的报错
{ [WeChatAPIRequestError: socket hang up (req "error"), POST xxxxxXbM&type=voice -1
headers: {}]
code: 'ECONNRESET',
name: 'WeChatAPIRequestError',
data: undefined,
status: -1,
headers: {},
res:
{ status: -1,
statusCode: -1,
headers: {},
size: 0,
aborted: false,
rt: 1467 } }
当前请求永久二维码接口为:api.createLimitQRCode(100, callback);
而腾讯文档中:
永久二维码请求说明
http请求方式: POST
URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
POST数据格式:json
POST数据例子:{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}
或者也可以使用以下POST数据创建字符串形式的二维码参数:
{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "123"}}}
可以创建字符串形式的二维码参数。
Q: I get a buffer result but a json when I use the getMaterial api.
check the file: lib/api_material.js
at the row 253, u just give a opts before request and do not postJSON the opts. this results in the weixin return a buffer result in callback.
u should postJSON opts or set dataType when post with urllib.
微信文档说AccessToken 7200S过期,getLatestToken()获得的AccessToken一定是没有过期的吗?
调用getLatestToken()时会去微信服务器那里更新一次AccessToken还是返回缓存的?
希望在文档里说明一下
var WechatAPI = require('wechat-api');
var api = new WechatAPI(appid, appsecret, );
api.updateRemark('open_id', 'remarked', function (err, data, res) {
// TODO
});
WechatAPI(appid, appsecret, ); 此处是否最后多写了一个 ',' 号
Your examples don't seem to work to get started...
'use strict';
let debug = require('debug')('wechat-api');
let path = require('path');
let fs = require('fs');
let AppConfig = require('../../private/AppConfig');
var WechatAPI = require('wechat-api');
let tokenFilePath = path.join(__dirname, 'access_token.txt');
debug('init', tokenFilePath);
var api = new WechatAPI(AppConfig.APP_ID, AppConfig.APP_SECRET, function (callback) {
// 传入一个获取全局token的方法
fs.readFile(tokenFilePath, 'utf8', function (err, txt) {
debug('read token ', tokenFilePath, txt);
if (err) {return callback(err);}
callback(null, JSON.parse(txt));
});
}, function (token, callback) {
// 请将token存储到全局,跨进程、跨机器级别的全局,比如写到数据库、redis等
// 这样才能在cluster模式及多机情况下使用,以下为写入到文件的示例
debug('write token to ', tokenFilePath, token);
fs.writeFile(tokenFilePath, JSON.stringify(token), callback);
});
// var api = new WechatAPI(AppConfig.APP_ID, AppConfig.APP_SECRET);
api.updateRemark('open_id', 'remarked', function (err, data, res) {
debug('updateRemark', data, res);
});
results:
wechat-api init +56ms /Users/dc/dev/rikai/boteditor/lib/wechat/access_token.txt
wechat-api read token +11ms /Users/dc/dev/rikai/boteditor/lib/wechat/access_token.txt undefined
wechat-api updateRemark +1ms undefined undefined
so no token is being created or read.
README里面给的例子似乎不太对
如果在readFile
时处理按照fs.readFile('access_token.txt', 'utf8', function (err, txt) { if (err) {return callback(err);}
这样处理错误的话,假如刚开始跑,没有access_token.txt
文件就会一直报错,而不是去获取新Token
{"errno":34,"code":"ENOENT","path":"access_token.txt"}
我把它替换为if (err) {return callback(null,null);}
之后就好了(参照默认callback的处理方式,这样会让他去请求一次access token),这样处理对么?
用的是最新的1.22.0,代码也很简单,部署在了heroku上
const WechatAPI = require('wechat-api');
...
...
app.use('/wechat', WechatAPI(config, function (req, res, next) {
res.send('test');
}));
相关的错误log如下:
: > [email protected] start /app
: > node ./bin/www
:
: /app/node_modules/wechat-api/lib/api_common.js:85
: ^
:
: this.registerTicketHandle();
: at API (/app/node_modules/wechat-api/lib/api_common.js:85:8)
: TypeError: this.registerTicketHandle is not a function
: at Object.<anonymous> (/app/app.js:17:20)
: at Function.Module._load (module.js:311:12)
: at Object.Module._extensions..js (module.js:432:10)
: at Module._compile (module.js:425:26)
: at Module.load (module.js:356:32)
: at Object.<anonymous> (/app/bin/www:3:11)
: at Module.require (module.js:366:17)
: at require (module.js:385:17)
: at Module._compile (module.js:425:26)
api_common.js: 85看上去好像也没啥问题,函数是在api_js.js#L46,看了下blame,@xuming314 很久之前commit的,所以估计也不是他那的问题,不知道这个问题究竟出在哪里。小白搞不定:dizzy_face::dizzy_face:
麻烦了,谢谢!:pray::pray::pray:
因为项目的前后台分别在两个不同的node进程,下面是代码
1、 var api = new API(appid, appsecret, function(){....}, function(){....});
2、api.getFollowers(function(){....});
当实际执行时第二行代码总是在第一行还没获取到token就执行了,我想在 new API的回调函数中获取已经初始化完成的api,但是看了源码在调用getToken和saveToken后还要做对prefix等url赋值的操作,因此这时的api并没有初始化完成,我该如何解决这个问题?
就是我需oAuth验证的一些东西,但是我不想在wechat-api使用的情况下再使用wehcat-oauth,请问能否将两个整合在一起?
每次new API的时候,都要写回调吗?
我有多个页面,都有new API(,) 这样貌似很不方便
var api = new API('appid', 'secret', function (callback) {
// 传入一个获取全局token的方法
fs.readFile('access_token.txt', 'utf8', function (err, txt) {
if (err) {return callback(err);}
callback(null, JSON.parse(txt));
});
}, function (token, callback) {
// 请将token存储到全局,跨进程、跨机器级别的全局,比如写到数据库、redis等
// 这样才能在cluster模式及多机情况下使用,以下为写入到文件的示例
fs.writeFile('access_token.txt', JSON.stringify(token), callback);
});
api.registerTicketHandle(function (type, callback) {
console.log(type);
// 传入一个获取全局ticket的方法
fs.readFile('./token/ticketToken.txt', 'utf8', function (err, txt) {
console.log(txt);console.log('read');
//console.log(err,txt);//return;
if (err) {return callback(err);}
callback(null, JSON.parse(txt));
});
}, function (type, _ticketToken, callback) {
console.log(type,_ticketToken);console.log('write');
fs.writeFile('./token/ticketToken.txt', JSON.stringify(_ticketToken), function(err){
if(err) return callack(err);
callback(null)
});
}
)
当我循环调用这个api的时候 发现access_token 在不断的覆盖,很快2000个就用完了,为什么循环调用一个api会出现这个问题呢?
var api = new API('appid', 'secret', function (callback) {
// 传入一个获取全局token的方法
fs.readFile('access_token.txt', 'utf8', function (err, txt) {
if (err) {return callback(err);}
callback(null, JSON.parse(txt));
});
}, function (token, callback) {
// 请将token存储到全局,跨进程、跨机器级别的全局,比如写到数据库、redis等
// 这样才能在cluster模式及多机情况下使用,以下为写入到文件的示例
fs.writeFile('access_token.txt', JSON.stringify(token), callback);
});
只要建个空白文件 access_token.txt 就可以了吗? 首先得把token写入进去吧,后面的writeFile 没看到被调用哦
回退1.10,正常。请大神检查检查吧
我这边的版本 (可能和github上的有差异) , 该文件第 161 行 有时候会报错.
错误的原因是, data 为空
API.prototype.getAccessToken = function (callback) {
var that = this;
var url = this.prefix + 'token?grant_type=client_credential&appid=' + this.appid + '&secret=' + this.appsecret;
this.request(url, {dataType: 'json'}, wrapper(function (err, data) {
if (err) {
return callback(err);
}
// 过期时间,因网络延迟等,将实际过期时间提前10秒,以防止临界点
// *************************** 这里就是 161 行 *************************** //
var expireTime = (new Date().getTime()) + (data.expires_in - 10) * 1000;
// ************************************************************************** //
var token = AccessToken(data.access_token, expireTime);
that.saveToken(token, function (err) {
if (err) {
return callback(err);
}
callback(err, token);
});
}));
return this;
};
建议此处 data如果为空 当做错误处理.
或者是在外层的某个地方生成 err .
微信的token管理有时候和过期时间不一致,在收到40001错误的时候,应该重新获取token。修改api_common.js方式如下,此代码经过验证可行:
API.prototype.preRequest = function (method, args, retryed) {
var that = this;
var callback = args[args.length - 1];
// 调用用户传入的获取token的异步方法,获得token之后使用(并缓存它)。
that.getToken(function (err, token) {
if (err) {
return callback(err);
}
//修改建议,重发时清除token,重新获取
if(retryed){
token = null;
}
var accessToken;
// 有token并且token有效直接调用
if (token && (accessToken = AccessToken(token.accessToken, token.expireTime)).isValid()) {
// 暂时保存token
that.token = accessToken;
if (!retryed) {
var retryHandle = function (err, data, res) {
// 40001 重试
if (data && data.errcode && data.errcode === 40001) {
return that.preRequest(method, args, true);
}
callback(err, data, res);
};
// 替换callback
var newargs = Array.prototype.slice.call(args, 0, -1);
newargs.push(retryHandle);
method.apply(that, newargs);
} else {
method.apply(that, args);
}
} else {
// 使用appid/appsecret获取token
that.getAccessToken(function (err, token) {
// 如遇错误,通过回调函数传出
if (err) {
return callback(err);
}
// 暂时保存token
that.token = token;
method.apply(that, args);
});
}
});
};
能不能加入平台的模拟登陆?
谢谢
第一次可以成功发送,第二次sendTemplate
的error 部分有值,打印了一下是accessToken, 不明白怎么用。。 我看定义,有 callback
和 callback2
, example里面没有讲 callback2 怎么用。
var sendOrderStatus = function sendOrderStatus(wechatUnionId, orderSequence, orderDate, orderStatus, remark) {
var templateId = 'wrFqkJ4S5Neco8ARbFQHaE0ZLI4a9BoPfW7wAG8ayMI';
var url = "http://wash.saltyegg.cn";
var data = {
title: {
value: "下单成功",
color: "#173177"
},
orderId: {
value: orderSequence,
color: "#173177"
},
orderDate: {
value: orderDate,
color: "#173177"
},
orderStatus: {
value: orderStatus,
color: "#173177"
},
remark: {
value: remark,
order: "#173177"
}
};
app.wechatAPI.sendTemplate(wechatUnionId, templateId, url, data, function (err, result) {
console.log('send template');
if (err){
console.error('error in sending template');
console.error(err);
console.log('what this is error');
}
else {
console.log(result);
}
});
};
result 可能为null
NOTICE: This domain name expired on 1/9/2016 and is pending renewal or deletion.
现在的 getCards 接口没有处理 status_list 参数
返回的错误信息是:name: 'WeChatAPIError', code: 44002 ;
感觉是微信那边的问题,我自己用postname手动打请求也是同样的错误信息。
求解?
朴大大,我想锻炼一下自己的node水平,所以没有用您的库。问题是这样的,我先是用https.request ,发送GET请求,拿到access_token,然后再request的end()回调函数中再次发送request POST请求,设置按钮,但是总是报** socket hang up**,调试了老半天了,求朴大大 指教,感激不尽!!!
微信群发预览接口,
微信高级群发预览文档地址,
http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html
exports.updateNewsMaterial = function (news, callback) {
this.preRequest(this._uploadNewsMaterial, arguments);
};
/*!
如题
我看了下以为官方没有提供这个接口呢,是拉下了,还是有其他原因呢?
麻烦大神告下
只有下面这几个
- getGroups
- getWhichGroup
- createGroup
- updateGroup
- moveUserToGroup
oauth2相关的
看晕了
如题,这种情况如何使用 wechat-api ?
is_menu_open 菜单是否开启,0代表未开启,1代表开启
请教一下,在获取用户信息时经常会报WeChatAPIJSONResponseFormatError的错,怎么解决
api_js.js第101行:urllib.request觉得应该改成this.request才对
发送客服 语音消息接口有问题,始终返回 invalid media_id,
我确保,media id 是正确的。
这个你们写单元测试了吗?没看到有啊
我环境时常报错 WeChatAPIError: access_token expired
不知道什么原因,看了一些源码,感觉有对过期token的处理, 不知道是不是我在使用的时候有什么不对的地方,求解答
我的需求是生成带参数的临时二维码。
研究了下官方的文档,好像只能通过sceneId去传整型参数。
场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)。
上面为官方文档的原文,临时二维码支持32位非0整型的场景值ID。
我这边用wechat-api的createTmpQRCode方法测试了下,在服务器后台可以通过req.weixin.EventKey拿到所传的场景值,格式类似为qrscene_1234。
但我发现如果场景值ID超过999999999九位数字后,到了后台会变成qrscene_0。
诚求各路大神指点。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.