前言
上篇学习了微信公众号开发的基本配置和消息的接受和回复,这篇学习微信公众号token的获取和自定义菜单栏以及微信用户信息的获取和消息模板使用。
一、token获取
参考文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
接口调用请求说明
https请求方式:
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数说明:
grant_type 是 获取access_token填写client_credential
appid 是 第三方用户唯一凭证
secret 是 第三方用户唯一凭证密钥,即appsecret
java实现
Http请求工具包:HttpUtils
/**
* @Description: http get请求共用方法
*/
@SuppressWarnings ( "resource" )
public static String sendGet(String reqUrl, Map<String, String> params)
throws Exception {
InputStream inputStream = null ;
HttpGet request = new HttpGet();
try {
//构造GET方式的请求URL
String url = buildUrl(reqUrl, params);
HttpClient client = new DefaultHttpClient();
request.setHeader( "Accept-Encoding" , "gzip" );
request.setURI( new URI(url));
HttpResponse response = client.execute(request);
inputStream = response.getEntity().getContent();
String result = getJsonStringFromGZIP(inputStream);
return result;
} finally {
if (inputStream != null ) {
inputStream.close();
}
request.releaseConnection();
}
/**
* 构建get方式的url
*
* @param reqUrl
* 基础的url地址
* @param params
* 查询参数
* @return 构建好的url
*/
public static String buildUrl(String reqUrl, Map<String, String> params) {
StringBuilder query = new StringBuilder();
Set<String> set = params.keySet();
for (String key : set) {
query.append(String.format( "%s=%s&" , key, params.get(key)));
}
return reqUrl + "?" + query.toString();
}
token请求方法:
final String FILC_PATH = "C:\\IdeaProjects\\MyWeChat\\src\\main\\resources\\Token.properties";
public void getToken_getTicket() throws Exception {
Map<String, String> params = new HashMap<String, String>();
params.put( "grant_type" , "client_credential" );
params.put( "appid" , "wx7c7b66c25b481607");
params.put( "secret" , "1847504b42c3ba60cac679eea2d256f5");
String jstoken = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/token", params);
System.out.println(jstoken);
String access_token = JSONObject.parseObject(jstoken).getString("access_token");//获取access_token;
System.out.println(access_token);
// 获取到token并赋值保存
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(new File(FILC_PATH)));
bufferedWriter.write("access_token="+access_token);
bufferedWriter.close();
}
定时请求:
@Configuration //1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling // 2.开启定时任务
public class timedTask {
@Scheduled(fixedRate=6900000)//指定间隔时间一小时55分钟
private void configureTasks() {
WeChatTask weChatTask = new WeChatTask();
try {
weChatTask.getToken_getTicket();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Token获取:
public class TokenUtit {
public static String getToken()throws Exception{
final String FILC_PATH = "C:\\IdeaProjects\\MyWeChat\\src\\main\\resources\\Token.properties";
File file = new File(FILC_PATH);
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String access = bufferedReader.readLine();
String access_token = access.substring(access.indexOf("=") + 1, access.length());
bufferedReader.close();
return access_token;
}
}
二、自定义菜单
参考文档:
https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html
自定义菜单采用微信公众号接口调试工具
https://mp.weixin.qq.com/debug/cgi-bin/apiinfo?t=index&type=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95&form=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3%20/menu/creat
接口调用请求说明
http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
click和view的请求示例
```xml
{
"button":[
{
"type":"click",
"name":"今日歌曲",
"key":"V1001_TODAY_MUSIC"
},
{
"name":"菜单",
"sub_button":[
{
"type":"view",
"name":"搜索",
"url":"http://www.soso.com/"
},
{
"type":"miniprogram",
"name":"wxa",
"url":"http://mp.weixin.qq.com",
"appid":"wx286b93c14bbf93aa",
"pagepath":"pages/lunar/index"
},
{
"type":"click",
"name":"赞一下我们",
"key":"V1001_GOOD"
}]
}]
}
参数说明
参数 是否必须 说明
button 是 一级菜单数组,个数应为1~3个
sub_button 否 二级菜单数组,个数应为1~5个
type 是 菜单的响应动作类型,view表示网页类型,click表示点击类型,miniprogram表示小程序类型
name 是 菜单标题,不超过16个字节,子菜单不超过60个字节
key click等点击类型必须 菜单KEY值,用于消息接口推送,不超过128字节
url view、miniprogram类型必须 网页 链接,用户点击菜单可打开链接,不超过1024字节。 type为miniprogram时,不支持小程序的老版本客户端将打开本url。
media_id media_id类型和view_limited类型必须 调用新增永久素材接口返回的合法media_id
appid miniprogram类型必须 小程序的appid(仅认证公众号可配置)
pagepath miniprogram类型必须 小程序的页面路径
article_id article_id类型和article_view_limited类型必须 发布后获得的合法 article_id
三、用户信息获取
参考文档:
https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId
数据返回
参数说明
access_token 是 调用接口凭证
openid 是 普通用户的标识,对当前公众号唯一
lang 否 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语
返回说明
正常情况下,微信会返回下述JSON数据包给公众号:
{
“subscribe”: 1,
“openid”: “o6_bmjrPTlm6_2sgVt7hMZOPfL2M”,
“nickname”: “Band”,
“sex”: 1,
“language”: “zh_CN”,
“city”: “广州”,
“province”: “广东”,
“country”: “中国”,
“headimgurl”:“http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0”,
“subscribe_time”: 1382694957,
“unionid”: " o6_bmasdasdsad6_2sgVt7hMZOPfL",
“remark”: “”,
“groupid”: 0,
“tagid_list”:[128,2],
“subscribe_scene”: “ADD_SCENE_QR_CODE”,
“qr_scene”: 98765,
“qr_scene_str”: “”
}
参数说明
subscribe 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
openid 用户的标识,对当前公众号唯一
nickname 用户的昵称
sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
city 用户所在城市
country 用户所在国家
province 用户所在省份
language 用户的语言,简体中文为zh_CN
headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
subscribe_time 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
remark 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
groupid 用户所在的分组ID(兼容旧的用户分组接口)
tagid_list 用户被打上的标签ID列表
subscribe_scene 返回用户关注的渠道来源,ADD_SCENE_SEARCH 公众号 搜索,ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移, ADD_SCENE_PROFILE_CARD 名片分享,ADD_SCENE_QR_CODE 扫描二维码,ADD_SCENE_PROFILE_LINK 图文页内名称点击,ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,ADD_SCENE_PAID 支付后关注,ADD_SCENE_WECHAT_ADVERTISEMENT 微信广告,ADD_SCENE_OTHERS 其他
qr_scene 二维码扫码场景(开发者自定义)
qr_scene_str 二维码扫码场景描述(开发者自定义)
java实现
public class GetUser {
/**
* @Description: 通过openid获取用户微信信息
*/
public static HashMap<String, String> Openid_userinfo(String openid)
throws Exception {
HashMap<String, String> params = new HashMap<String, String>();
params.put( "access_token" , TokenUtit.getToken()); //定时器中获取到的token
params.put( "openid" , openid); //需要获取的用户的openid
params.put( "lang" , "zh_CN" );
String subscribers = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/user/info", params);
params.clear();
//这里返回参数只取了昵称、头像、和性别
params.put( "nickname" ,
JSONObject.parseObject(subscribers).getString( "nickname" )); //昵称
params.put( "headimgurl" ,
JSONObject.parseObject(subscribers).getString( "headimgurl" )); //头像
params.put( "sex" , JSONObject.parseObject(subscribers).getString( "sex" )); //性别
return params;
}
}
四、模板消息回复
参考文档:
https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html
模板id获取
这里我使用的是微信公众号测试号
测试号可以直接设置模板内容生成模板ID,正常情况按照微信公众开发文档步骤获取
发生模板消息
接口调用请求说明
http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
POST数据说明
POST数据示例如下:
{
"touser":"OPENID",
"template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
"url":"http://weixin.qq.com/download",
"miniprogram":{
"appid":"xiaochengxuappid12345",
"pagepath":"index?foo=bar"
},
"data":{
"first": {
"value":"恭喜你购买成功!",
"color":"#173177"
},
"keyword1":{
"value":"巧克力",
"color":"#173177"
},
"keyword2": {
"value":"39.8元",
"color":"#173177"
},
"keyword3": {
"value":"2014年9月22日",
"color":"#173177"
},
"remark":{
"value":"欢迎再次购买!",
"color":"#173177"
}
}
}
参数说明
touser 是 接收者openid
template_id 是 模板ID
url 否 模板跳转链接(海外帐号没有跳转能力)
miniprogram 否 跳小程序所需数据,不需跳小程序可不用传该数据
appid 是 所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)
pagepath 否 所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏
data 是 模板数据
color 否 模板内容字体颜色,不填默认为黑色
注:url和miniprogram都是非必填字段,若都不传则模板无跳转;若都传,会优先跳转至小程序。开发者可根据实际需要选择其中一种跳转方式即可。当用户的微信客户端版本不支持跳小程序时,将会跳转至url。
java实现
内容实体
@Data
public class TemplateInfo{
private String value; //内容
private String color; //颜色
public TemplateInfo(String value,String color){
this.value = value;
this.color = color;
}
}
发生内容实体
@Data
public class TemplateMessage {
private String touser;//目标客户
private String template_id;//模板id
Map<String,TemplateInfo> data; //模板内容
}
HttpPost请求工具
/**
* @Description: http post请求json数据
*/
public static String sendPostBuffer(String urls, String params)
throws ClientProtocolException, IOException {
HttpPost request = new HttpPost(urls);
StringEntity se = new StringEntity(params, HTTP.UTF_8);
request.setEntity(se);
// 发送请求
@SuppressWarnings ( "resource" )
HttpResponse httpResponse = new DefaultHttpClient().execute(request);
// 得到应答的字符串,这也是一个 JSON 格式保存的数据
String retSrc = EntityUtils.toString(httpResponse.getEntity());
request.releaseConnection();
return retSrc;
}
模板消息发送
public class Template {
public static void sendTemplate(String touser,String template_id,HashMap<String, String> userMap){
TemplateMessage templateMessage = new TemplateMessage();
templateMessage.setTemplate_id(template_id);
templateMessage.setTouser(touser);
HashMap<String, TemplateInfo> dataMap = new HashMap<>();
TemplateInfo first = new TemplateInfo("您好,谢谢关注","#DC143C");
dataMap.put("first",first);
TemplateInfo keyword1 = new TemplateInfo(userMap.get("nickname"),"#173177");
dataMap.put("keyword1",keyword1);
TemplateInfo keyword2 = new TemplateInfo(userMap.get("sex"),"#173177");
dataMap.put("keyword2",keyword2);
TemplateInfo remark = new TemplateInfo("\n再次欢迎你","#DC143C");
dataMap.put("remark",remark);
templateMessage.setData(dataMap);
String json = JSONArray.toJSON(templateMessage).toString();
try {
String s = HttpUtils.sendPostBuffer("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + TokenUtit.getToken(), json);
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}
}
整体框架