获取code码碰到了这个问题
网页微信第三方登录-redirect_uri参数错误
通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)
目录
1 第一步:用户同意授权,获取code
2 第二步:通过code换取网页授权access_token
3 第三步:刷新access_token(如果需要)
4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
5 附:检验授权凭证(access_token)是否有效
第一步:用户同意授权,获取code
在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面:
尤其注意:由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问
尤其注意:跳转回调redirect_uri,应当使用https链接来确保授权code的安全性。
参数说明
参数 | 是否必须 | 说明 |
appid | 是 | 公众号的唯一标识 |
redirect_uri | 是 | 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理 |
response_type | 是 | 返回类型,请填写code |
scope | 是 | 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 ) |
state | 否 | 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 |
#wechat_redirect | 是 | 无论直接打开还是做页面302重定向时候,必须带此参数 |
如果跳转的请求是action或者别的(控制层)方法参数不能加载方法体中接收参数值就可以
用户同意授权后
如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。
发送到微信点开第一步
然后参数到了后台
其中addPeople213这个方法不能带参数否则会报错,然后在方法体中接收code码就ok了
到此code码就获取到了
wechatUtil.java工具类
package com.tlzn.util.Tencent;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import org.apache.struts2.ServletActionContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.JSONObject;
import com.tlzn.util.base.Constants;
import com.tlzn.util.base.DateFormatTools;
import com.tlzn.util.base.Util;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
/**
* 发送微信消息工具类
* @author wjy
*
*/
public class WechatUtil {
static Util util=Util.getInstance();
static DateFormatTools DateUtil=DateFormatTools.getInstance();
/**
* 服务类目为:“IT科技 > 软件服务提供商 > 服务完成通知”的模板ID
*/
private static String SERVICE_CATEGORY_IT_SOFTWARE_SERVICE_SUCCESS = "fEM1jg0ZOWZ9LfVVSzmKI7iIcJpJdiM5TTnuq1qQXSA";
/**
* 用于存放所有学校的access_token信息,便于统一管理,并且每2小时需要重新刷新一次
*/
public static Map<String, Object> allAccessTokenMap = new HashMap<String, Object>();
private static final String REQUEST_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
/**
* 获取/刷新accessToken url地址
*/
private static final String REQUEST_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code";
/**
* 网页端引用微信js请求授权url
*/
private static final String REQUEST_JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=";
/**
* 微信发送客服消息接口url
*/
private static final String SEND_MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=";
/**
* 微信公众号发送订阅通知
*/
private static final String SEND_MSG_SUBSCRIBE_BIZSEND_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/bizsend?access_token=";
private static final String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=";
private static final String REQUEST_WECHAT_USERINFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?lang=zh_CN";
private static final String REQUEST_WECHAT_FACEINFO_URL = "https://api.weixin.qq.com/cityservice/face/identify/getinfo?access_token=";
private static final String REQUEST_WECHAT_FACEIMG_URL = "https://api.weixin.qq.com/cityservice/face/identify/getimage?access_token=";
/**https://api.weixin.qq.com/cityservice/face/identify/getimage?access_token=
* 请求微信服务器返回token信息后获取指定字符串常量
*/
private static final String ACCESS_TOKEN_CONST = "access_token";
/**
* 用于存放指定appid的accesstoken的有效时间
*/
private static final String ACCESS_TOKEN_TIME_CONST = "ACCESS_TOKEN_TIME";
/**
* 网页端使用微信js时用到的关键字
*/
private static final String JSAPI_TICKET_CONST = "ticket";
/**
* js授权有效时间
*/
private static final String JSAPI_TICKET_TIME_CONST = "JSAPI_TICKET_TIME";
/**
* 发送文本信息
* @param openId 用户openId(关注公众号后的公众平台自动生成的唯一编码)
* @param msgContent 消息内容
* @param appId 微信公众号appid
* @param secert 微信公众号密钥
* @param accessToken 发消息所需的令牌
* @param openIdList 要发送微信消息的人员openid
* @param msgContent 要发送的信息内容
* @return
*/
public static Map<String, String> sendTextMsg(String appId, String secert, String accessToken, List<String> openIdList, String msgContent){
Map<String, String> resultMap = new HashMap<String, String>();
// String accessToken = getToken();
// if(accessToken == null){
// resultMap.put(SendStatus.GET_ACCESS_TOKEN_FAILD.getCode(), SendStatus.GET_ACCESS_TOKEN_FAILD.getName());
// return resultMap;
// }
// 组装文本信息
SimplMsg sm = new SimplMsg(MsgTypeEnum.TEXT.getCode());
sm.addData("content", msgContent);
for (String openId : openIdList) {
String msgBody = toSimplJson(openId, sm);
send(accessToken, msgBody);
}
return null;
}
/**
* 发送多图文消息
* @param appId 微信公众号appid
* @param secert 微信公众号密钥
* @param accessToken 发消息所需的令牌
* @param openIdList 要发送微信消息的人员openid
* @param msgBody 图文消息封装类
* @return
*/
public static Map<String, String> sendPicTextMsg(String appId, String secert, String accessToken, List<String> openIdList, PicInfo msgBody){
Map<String, String> resultMap = new HashMap<String, String>();
// String accessToken = getToken();
// if(accessToken == null){
// resultMap.put(SendStatus.GET_ACCESS_TOKEN_FAILD.getCode(), SendStatus.GET_ACCESS_TOKEN_FAILD.getName());
// return resultMap;
// }
/* 发送多图文消息*/
PicWithTextMsg pics = new PicWithTextMsg(MsgTypeEnum.NEWS.getCode());
List<Map<String, String>> bodyList = new ArrayList<Map<String,String>>();
pics.data = bodyList;
Map<String, String> bodyMap = new HashMap<String, String>();
bodyList.add(bodyMap);
bodyMap.put("title", msgBody.getTitle());
bodyMap.put("description", msgBody.getDescription());
bodyMap.put("url", msgBody.getUrl());
bodyMap.put("picurl", msgBody.getPicurl());
for (String openId : openIdList) {
String msgBodyStr = toImagesJson(openId, pics);
send(accessToken, msgBodyStr);
}
return null;
}
/**
* 获取指定公众号的access_token
* @return
* @throws Exception
*/
public static String getAccessToken(String appId, String secert) throws Exception{
System.out.println("开始获取wechat accessToke...."+ "&appid=" + appId + "&secret=" + secert);
String req_token_url = REQUEST_TOKEN_URL + "&appid=" + appId + "&secret=" + secert;
StringBuilder tokenSbd = null;
InputStreamReader isr = null;
HttpsURLConnection httpsConn = null;
// 先从缓存中去token
if(allAccessTokenMap.containsKey(ACCESS_TOKEN_CONST + appId)){
String effectiveTime = (String) allAccessTokenMap.get(ACCESS_TOKEN_TIME_CONST + appId);
if(DateUtil.compareDateTime(effectiveTime, util.getFormatDate(new Date(),"YYYY-MM-DD HH:mm:ss"))){
// 有效时间大于当前时间,则access_token有效
return (String) allAccessTokenMap.get(ACCESS_TOKEN_CONST + appId);
}
}
try {
URL reqURL = new URL(req_token_url);
httpsConn = (HttpsURLConnection) reqURL.openConnection();
isr = new InputStreamReader(httpsConn.getInputStream());
char[] chars = new char[1024];
int len;
tokenSbd = new StringBuilder();
while ((len = isr.read(chars)) != -1) {
tokenSbd.append(new String(chars, 0, len));
}
System.out.println("获取到的tokenSbd:" + tokenSbd.toString());
JSONObject jsonObj = JSONObject.parseObject(tokenSbd.toString());
String accessToken = jsonObj.get(ACCESS_TOKEN_CONST).toString();
// 将当前时间+2小时后的时间存入map中
//allAccessTokenMap.put(ACCESS_TOKEN_TIME_CONST + appId, DateUtil.getAddMinuteDate(new Date(),120));
allAccessTokenMap.put(ACCESS_TOKEN_TIME_CONST + appId, DateUtil.format("YYYY-MM-DD HH:mm:ss", DateUtil.getAddMinuteDate(new Date(),120)));
System.out.println("获取到公众号ACCESS_TOKEN:" + accessToken);
allAccessTokenMap.put(ACCESS_TOKEN_CONST + appId, accessToken);
return accessToken;
} catch (IOException e) {
e.printStackTrace();
} finally{
if(isr != null){
try {
isr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(httpsConn != null){
httpsConn.disconnect();
}
}
return null;
}
/**
* 获取指定公众号的JsapiTicket
* @return
* @throws Exception
*/
public static String getJsapiTicket(String appId, String secert) throws Exception{
StringBuilder tokenSbd = null;
InputStreamReader isr = null;
HttpsURLConnection httpsConn = null;
// 先从缓存中去token
if(allAccessTokenMap.containsKey(JSAPI_TICKET_CONST + appId)){
System.out.println("JSAPI_TICKET_TIME_CONST="+allAccessTokenMap.get(JSAPI_TICKET_TIME_CONST + appId));
String effectiveTime = (String) allAccessTokenMap.get(JSAPI_TICKET_TIME_CONST + appId);
if(DateUtil.compareDateTime(effectiveTime, util.getFormatDate(new Date(),"YYYY-MM-DD HH:mm:ss"))){
// 有效时间大于当前时间,则access_token有效
return (String) allAccessTokenMap.get(JSAPI_TICKET_CONST + appId);
}
}
String accessToken = getAccessToken(appId, secert);
try {
URL reqURL = new URL(REQUEST_JSAPI_TICKET_URL + accessToken);
httpsConn = (HttpsURLConnection) reqURL.openConnection();
isr = new InputStreamReader(httpsConn.getInputStream());
char[] chars = new char[1024];
int len;
tokenSbd = new StringBuilder();
while ((len = isr.read(chars)) != -1) {
tokenSbd.append(new String(chars, 0, len));
}
JSONObject jsonObj = JSONObject.parseObject(tokenSbd.toString());
String jsApiTicket = jsonObj.get(JSAPI_TICKET_CONST).toString();
// 将当前时间+2小时后的时间存入map中
allAccessTokenMap.put(JSAPI_TICKET_TIME_CONST + appId, DateUtil.format("YYYY-MM-DD HH:mm:ss", DateUtil.getAddMinuteDate(new Date(),120)));
System.out.println("获取到公众号jsApiTicket:" + jsApiTicket);
allAccessTokenMap.put(JSAPI_TICKET_CONST + appId, jsApiTicket);
return jsApiTicket;
} catch (IOException e) {
e.printStackTrace();
} finally{
if(isr != null){
try {
isr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(httpsConn != null){
httpsConn.disconnect();
}
}
return null;
}
/**
* 生成微信权限验证的参数
* @param appId
* @param secert
* @param url
* @return
* @throws Exception
*/
public static Map<String, String> createWXTicket(String appId, String secert, String url) throws Exception {
Map<String, String> ret = new HashMap<String, String>();
String nonceStr = util.getUUID();
String timestamp = createTimestamp();
String jsApiTicket = getJsapiTicket(appId, secert);
//注意这里参数名必须全部小写,且必须有序
String signature = SignUtil.createSignature(jsApiTicket, nonceStr, timestamp, url);
ret.put("url", url);
ret.put("jsapi_ticket", jsApiTicket);
ret.put("nonceStr", nonceStr);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
ret.put("appid", appId);
System.out.println("===========jsapi_ticket:" + jsApiTicket);
System.out.println("===========signature:" + signature);
System.out.println("===========nonceStr:" + nonceStr);
System.out.println("===========timestamp:" + timestamp);
System.out.println("===========appid:" + appId);
System.out.println("===========url:" + url);
return ret;
}
/**
* 拉取微信用户人脸验证信息
* @param code
* @return
* @throws Exception
*/
public static Map<String, String> getWxFaceInfo(String appId, String secert, String msgBody) {
Map<String, String> resultMap = new HashMap<String, String>();
HttpURLConnection httpURLConnection = null;
OutputStream os = null;
InputStream in = null;
try {
//创建URL
String accessToken = getAccessToken(appId, secert);
URL url = new URL(REQUEST_WECHAT_FACEINFO_URL + accessToken);
//由URL的openConnection方法得到一个HttpURLConnection(需要强转)
httpURLConnection =
(HttpURLConnection) url.openConnection();
//设置post提交
httpURLConnection.setRequestMethod("POST");
//设置超时时间
httpURLConnection.setConnectTimeout(30000);
httpURLConnection.setReadTimeout(30000);
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
//把请求正文通过OutputStream发出去
os =httpURLConnection.getOutputStream();
os.write(msgBody.getBytes("utf-8"));
os.flush();
//判断响应码 200 代表成功
if(httpURLConnection.getResponseCode()==200){
//由HttpURLConnection拿到输入流
in = httpURLConnection.getInputStream();
StringBuffer sb = new StringBuffer();
//根据输入流做一些IO操作
byte [] buff =new byte[1024];
int len=-1;
while((len=in.read(buff))!=-1){
sb.append(new String(buff,0,len,"utf-8"));
}
//System.out.println("微信消息已发送:" + msgBody);
//System.out.println("微信平台回执:" + sb.toString());
/*JSONObject jsonObj = JSONObject.parseObject(sb.toString());*/
resultMap.put("obj", sb.toString());
}else{
resultMap.put(SendStatus.HTTP_CONNECT_FAILD.getCode(), SendStatus.HTTP_CONNECT_FAILD.getName());
}
return resultMap;
}catch (Exception e){
e.printStackTrace();
}finally{
try {
if(os != null){
os.close();
}
if(in != null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if(httpURLConnection != null){
httpURLConnection.disconnect();
}
}
resultMap.put(SendStatus.HTTP_CONNECT_FAILD.getCode(), SendStatus.HTTP_CONNECT_FAILD.getName());
return resultMap;
}
/**
* 拉取微信用户人脸验证照片
* @param code
* @return
* @throws Exception
*/
public static Map<String, String> getWxFaceImg(String appId, String secert, String msgBody) {
Map<String, String> resultMap = new HashMap<String, String>();
HttpURLConnection httpURLConnection = null;
OutputStream os = null;
InputStream in = null;
try {
//创建URL
String accessToken = getAccessToken(appId, secert);
URL url = new URL(REQUEST_WECHAT_FACEIMG_URL + accessToken);
//由URL的openConnection方法得到一个HttpURLConnection(需要强转)
httpURLConnection =
(HttpURLConnection) url.openConnection();
//设置post提交
httpURLConnection.setRequestMethod("POST");
//设置超时时间
httpURLConnection.setConnectTimeout(30000);
httpURLConnection.setReadTimeout(30000);
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
//把请求正文通过OutputStream发出去
os =httpURLConnection.getOutputStream();
os.write(msgBody.getBytes("utf-8"));
os.flush();
//判断响应码 200 代表成功
if(httpURLConnection.getResponseCode()==200){
//由HttpURLConnection拿到输入流
in = httpURLConnection.getInputStream();
byte[] data = readInputStream(in);
//new一个文件对象用来保存图片,默认保存当前工程根目录
String path = ServletActionContext.getServletContext().getRealPath(Constants.IMGPATH);
File dir = new File(path);
String fileFileName=new Date().getTime()+".jpg";
System.out.println("fileFileName="+fileFileName);
File imageFile = new File(dir,fileFileName);
//创建输出流
FileOutputStream outStream = new FileOutputStream(imageFile);
//写入数据
outStream.write(data);
//关闭输出流
outStream.close();
resultMap.put("fileFileName", fileFileName);
}else{
resultMap.put(SendStatus.HTTP_CONNECT_FAILD.getCode(), SendStatus.HTTP_CONNECT_FAILD.getName());
}
return resultMap;
}catch (Exception e){
e.printStackTrace();
}finally{
try {
if(os != null){
os.close();
}
if(in != null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if(httpURLConnection != null){
httpURLConnection.disconnect();
}
}
resultMap.put(SendStatus.HTTP_CONNECT_FAILD.getCode(), SendStatus.HTTP_CONNECT_FAILD.getName());
return resultMap;
}
public static byte[] readInputStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//创建一个Buffer字符串
byte[] buffer = new byte[1024];
//每次读取的字符串长度,如果为-1,代表全部读取完毕
int len = 0;
//使用一个输入流从buffer里把数据读取出来
while( (len=inStream.read(buffer)) != -1 ){
//用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
outStream.write(buffer, 0, len);
}
//关闭输入流
inStream.close();
//把outStream里的数据写入内存
return outStream.toByteArray();
}
/**
* 生成时间戳
* @return
*/
private static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
/**
* 创建菜单
* @param accessToken
* @param menuJson
* @throws Exception
*/
public static void createWechatMenu(String accessToken, String menuJson) throws Exception{
System.out.println("开始创建微信菜单>>>");
URL url = null;
try {
url = new URL(MENU_CREATE_URL + accessToken);
} catch (MalformedURLException e) {
throw new Exception("URL初始化失败!", e);
}
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setRequestMethod("POST");
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");//连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); //读取超时30秒
http.connect();
OutputStream os= http.getOutputStream();
os.write(menuJson.getBytes("UTF-8"));//传入参数
os.flush();
os.close();
System.out.println("完成创建微信菜单>>>");
}
/**
* 拉取微信用户信息
* @param code
* @return
* @throws Exception
*/
public static JSONObject getWechatUserInfo(String appId, String secert, String openId) throws Exception{
StringBuilder rstSbd = null;
InputStreamReader isr = null;
HttpsURLConnection httpsConn = null;
String accessToken = getAccessToken(appId, secert);
System.out.println("++++++++++++开始获取微信头像信息...");
String reqUserInfoUrl = REQUEST_WECHAT_USERINFO_URL + "&access_token=" + accessToken + "&openid=" + openId;
try {
URL reqURL = new URL(reqUserInfoUrl);
httpsConn = (HttpsURLConnection) reqURL.openConnection();
isr = new InputStreamReader(httpsConn.getInputStream(),"UTF-8");
char[] chars = new char[1024];
int len;
rstSbd = new StringBuilder();
while ((len = isr.read(chars)) != -1) {
rstSbd.append(new String(chars, 0, len));
}
//String jsonZhcnStr = new String(rstSbd.toString().getBytes("ISO-8859-1"), "UTF-8");
JSONObject jsonObj = JSONObject.parseObject(rstSbd.toString());
//String nickName = jsonObj.get("nickname") == null ? "" : jsonObj.get("nickname").toString();
//String headImgUrl = jsonObj.get("headimgurl") == null ? "" : jsonObj.get("headimgurl").toString();
return jsonObj;
} catch (IOException e) {
e.printStackTrace();
} finally{
if(isr != null){
try {
isr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(httpsConn != null){
httpsConn.disconnect();
}
}
return null;
}
/**
* 根据微信授权码获取openId等信息
* @param code
* @return
*/
public static String getAccessTokenByCode(String appId, String secert, String code){
String req_token_url = REQUEST_ACCESS_TOKEN_URL + "&appid=" + appId + "&secret=" + secert + "&code=" + code;
StringBuilder tokenSbd = null;
InputStreamReader isr = null;
HttpsURLConnection httpsConn = null;
System.out.println("开始根据code获取accessToken...发送http请求。"+ "&appid=" + appId + "&secret=" + secert + "&code=" + code);
try {
URL reqURL = new URL(req_token_url);
httpsConn = (HttpsURLConnection) reqURL.openConnection();
isr = new InputStreamReader(httpsConn.getInputStream());
char[] chars = new char[1024];
int len;
tokenSbd = new StringBuilder();
while ((len = isr.read(chars)) != -1) {
tokenSbd.append(new String(chars, 0, len));
}
//System.out.println("获取到的数据信息:" + tokenSbd.toString());
JSONObject jsonObj = JSONObject.parseObject(tokenSbd.toString());
//System.out.println(jsonObj.toJSONString());
System.out.println("获取openId:" + jsonObj.get("openid"));
String openId = jsonObj.get("openid") == null ? "" : jsonObj.get("openid").toString();
System.out.println(">>>根据code["+ code +"]获取openID["+ openId +"]");
return openId;
} catch (IOException e) {
e.printStackTrace();
} finally{
if(isr != null){
try {
isr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(httpsConn != null){
httpsConn.disconnect();
}
}
return null;
}
/**
* send发送订阅通知
* @param appId
* @param secert
* @param templateData 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }
* @return
*/
private static Map<String, String> sendSubscribeBizsend(String appId, String secert, JSONObject templateData){
Map<String, String> resultMap = new HashMap<String, String>();
HttpURLConnection httpURLConnection = null;
OutputStream os = null;
InputStream in = null;
try {
String accessToken = WechatUtil.getAccessToken(appId, secert);
//创建URL
URL url = new URL(SEND_MSG_SUBSCRIBE_BIZSEND_URL + accessToken);
//由URL的openConnection方法得到一个HttpURLConnection(需要强转)
httpURLConnection =
(HttpURLConnection) url.openConnection();
//设置post提交
httpURLConnection.setRequestMethod("POST");
//设置超时时间
httpURLConnection.setConnectTimeout(30000);
httpURLConnection.setReadTimeout(30000);
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
//把请求正文通过OutputStream发出去
os =httpURLConnection.getOutputStream();
os.write(templateData.toJSONString().getBytes("utf-8"));
os.flush();
//判断响应码 200 代表成功
if(httpURLConnection.getResponseCode()==200){
//由HttpURLConnection拿到输入流
in = httpURLConnection.getInputStream();
StringBuffer sb = new StringBuffer();
//根据输入流做一些IO操作
byte [] buff =new byte[1024];
int len=-1;
while((len=in.read(buff))!=-1){
sb.append(new String(buff,0,len,"utf-8"));
}
System.out.println("微信消息已发送:");
System.out.println("微信平台回执:" + sb.toString());
resultMap.put(SendStatus.SUCCESS.getCode(), SendStatus.SUCCESS.getName());
}else{
resultMap.put(SendStatus.HTTP_CONNECT_FAILD.getCode(), SendStatus.HTTP_CONNECT_FAILD.getName());
}
return resultMap;
}catch (Exception e){
e.printStackTrace();
}finally{
try {
if(os != null){
os.close();
}
if(in != null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if(httpURLConnection != null){
httpURLConnection.disconnect();
}
}
resultMap.put(SendStatus.HTTP_CONNECT_FAILD.getCode(), SendStatus.HTTP_CONNECT_FAILD.getName());
return resultMap;
}
/**
* 发起http请求
* @param accessToken
* @param msgBody
* @return
*/
private static Map<String, String> send(String accessToken, String msgBody){
Map<String, String> resultMap = new HashMap<String, String>();
HttpURLConnection httpURLConnection = null;
OutputStream os = null;
InputStream in = null;
try {
//创建URL
URL url = new URL(SEND_MSG_URL + accessToken);
//由URL的openConnection方法得到一个HttpURLConnection(需要强转)
httpURLConnection =
(HttpURLConnection) url.openConnection();
//设置post提交
httpURLConnection.setRequestMethod("POST");
//设置超时时间
httpURLConnection.setConnectTimeout(30000);
httpURLConnection.setReadTimeout(30000);
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
//把请求正文通过OutputStream发出去
os =httpURLConnection.getOutputStream();
os.write(msgBody.getBytes("utf-8"));
os.flush();
//判断响应码 200 代表成功
if(httpURLConnection.getResponseCode()==200){
//由HttpURLConnection拿到输入流
in = httpURLConnection.getInputStream();
StringBuffer sb = new StringBuffer();
//根据输入流做一些IO操作
byte [] buff =new byte[1024];
int len=-1;
while((len=in.read(buff))!=-1){
sb.append(new String(buff,0,len,"utf-8"));
}
System.out.println("微信消息已发送:" + msgBody);
System.out.println("微信平台回执:" + sb.toString());
resultMap.put(SendStatus.SUCCESS.getCode(), SendStatus.SUCCESS.getName());
}else{
resultMap.put(SendStatus.HTTP_CONNECT_FAILD.getCode(), SendStatus.HTTP_CONNECT_FAILD.getName());
}
return resultMap;
}catch (Exception e){
e.printStackTrace();
}finally{
try {
if(os != null){
os.close();
}
if(in != null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if(httpURLConnection != null){
httpURLConnection.disconnect();
}
}
resultMap.put(SendStatus.HTTP_CONNECT_FAILD.getCode(), SendStatus.HTTP_CONNECT_FAILD.getName());
return resultMap;
}
/**
* 普通消息实体转换为json对象工具类
* @param openid
* @param msg
* @return
*/
private static String toSimplJson(String openId, SimplMsg msgContext) {
JSONObject json = new JSONObject();
json.put("touser", openId);
json.put("msgtype", msgContext.getMsgtype());
json.put(msgContext.getMsgtype(), msgContext.getData());
return json.toString();
}
/**
* 多图文消息转换为json对象工具类
* @param openId
* @param msg
* @return
*/
private static String toImagesJson(String openId, PicWithTextMsg msg){
JSONObject j = new JSONObject();
j.put("articles", msg.getData());
JSONObject json = new JSONObject();
json.put("touser", openId);
json.put("msgtype", msg.getMsgType());
json.put(msg.getMsgType(), j);
return json.toString();
}
/**
* 发送消息类型枚举类
* @author wjy
*
*/
public enum MsgTypeEnum{
TEXT("text", "文本消息"),
NEWS("news", "图文消息");
private String code;
private String name;
MsgTypeEnum(String code, String name){
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
public void setCode(String code) {
this.code = code;
}
public void setName(String name) {
this.name = name;
}
};
/**
* 发送消息状态枚举内部类
* @author wjy
*
*/
public enum SendStatus{
SUCCESS("1", "成功"),
GET_ACCESS_TOKEN_FAILD("2", "获取token信息失败"),
HTTP_CONNECT_FAILD("3", "http链接失败"),
UNKNOW_ERROR("-1", "未知错误");
private String code;
private String name;
SendStatus(String code, String name){
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
public void setCode(String code) {
this.code = code;
}
public void setName(String name) {
this.name = name;
}
};
/**
* 简单消息内部类
* @author wjy
*
*/
static class SimplMsg{
/**
* 发送消息类型
*/
private String msgtype;
private Map<String,String> data = new HashMap<String,String>();
public Map<String,String> getData(){
return data;
}
public String getMsgtype() {
return msgtype;
}
/**
* 实例化指定类型的消息
* */
public SimplMsg(String msgtype){
this.msgtype = msgtype;
}
/**
* 添加消息内容
*/
public SimplMsg addData(String key,String value){
data.put(key, value);
return this;
}
}
/**
* 图文消息内部封装类
* @author wjy
*
*/
static class PicWithTextMsg{
private String msgType;
private List<Map<String,String>> data = new ArrayList<Map<String,String>>();
public List<Map<String,String>> getData(){
return data;
}
public String getMsgType() {
return msgType;
}
/**
* 实例化指定类型的消息
* */
public PicWithTextMsg(String msgType){
this.msgType = msgType;
}
/**
* 添加消息内容
*/
public PicWithTextMsg addData(Map<String,String> map){
data.add(map);
return this;
}
}
/**
* 图文信息实体类
* @author wjy
*
*/
public static class PicInfo{
private String title;
private String description;
private String url;
private String picurl;
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public String getUrl() {
return url;
}
public String getPicurl() {
return picurl;
}
public void setTitle(String title) {
this.title = title;
}
public void setDescription(String description) {
this.description = description;
}
/**
* 外链url(即点击图文时的链接)
* @param url
*/
public void setUrl(String url) {
this.url = url;
}
/**
* 要展示的图片的url
* @param picurl
*/
public void setPicurl(String picurl) {
this.picurl = picurl;
}
}
// ****************************************************************
/*
public void doSend() {
List<CdptsArticle> toSendNewsList = new ArrayList<>();
// 1.获取新闻列表
toSendNewsList = getArticleListFromCdpts();
// 再去获取一次,有时候第一次获取不到,不知道为什么
if (toSendNewsList.size() == 0) {
toSendNewsList = getArticleListFromCdpts();
}
// 2.移除已发送的新闻
toSendNewsList = removeAlreadySentArticle(toSendNewsList);
if (toSendNewsList.size() == 0) {
//logger.info("----------没有文章需要群发----------");
return;
}
// 最多群发8条消息
if (toSendNewsList.size() > 8) {
toSendNewsList = toSendNewsList.subList(0, 8);
}
//logger.info("----------群发的消息----------");
for (CdptsArticle article : toSendNewsList) {
logger.info("----------{}----------", article.getTitle());
}
// 3.上传并设置封面图片
toSendNewsList = setCoverImage(toSendNewsList);
// 4.群发图文消息json封装
String groupSendMessageJsonStr = getGroupSendMessageJsonStr(toSendNewsList);
// 5.上传群发图文消息
String mediaId = uploadGroupSendMessage(groupSendMessageJsonStr);
// 5.群发
if (StringUtils.isNotEmpty(mediaId)) {
String mode = prop.get("active");
if (StringUtils.isNotBlank(mode) && mode.equals("dev")) {
logger.info("测试环境,预览");
String openId = "你的测试openid";
sendToPreview(toSendNewsList, openId, mediaId);
} else {
logger.info("正式环境,群发");
sendToAll(toSendNewsList, mediaId);
}
}
}
*/
/**
* 设置图文消息的封面图片
*
* @param newsList
* @return
*/
/*
private List<CdptsArticle> setCoverImage(List<CdptsArticle> newsList) {
String accessToken = accessTokenUtil.getAccessToken();
// 3.将待发送的新闻填充
List<CdptsArticle> detialArticleList = new ArrayList<>();
// 4.封装新闻详情,并得到新闻列表
for (CdptsArticle article : newsList) {
CdptsArticle articleWithDetial = getArticleDetialAndReplaceImage(article.getUrl());
try {
// 下载封面图片到本地
String localImage = imageService.saveImageToDisk(articleWithDetial.getImageUrl(), imageSavePath);
ImageUtil.thumbImage(localImage);
// 上传封面到微信
String jsonStr = HttpUtil.sendPost(postImageMediaUrl.replace("ACCESS_TOKEN", accessToken),
new File(localImage));
logger.info("----------上传封面图片返回结果:{}----------" + jsonStr);
try {
JSONObject object = new JSONObject(jsonStr);
logger.info("----------得到的封面图片media_id:{}----------", object.get("media_id"));
articleWithDetial.setImageMediaId((String) object.get("media_id"));
} catch (Exception e) {
logger.error("----------上传封面发生错误:{}", e.getMessage());
}
} catch (Exception e) {
logger.error("----------下载封面,上传封面到微信过程发生错误:{}", e.getMessage());
}
detialArticleList.add(articleWithDetial);
}
logger.info("----------最终群发图文列表:{}----------", detialArticleList);
return detialArticleList;
}
private String getGroupSendMessageJsonStr(List<CdptsArticle> toSendNewsList) {
List<GroupSendMessage> groupSendMessageList = new ArrayList<>();
for (CdptsArticle cdptsArticle : toSendNewsList) {
GroupSendMessage groupSendMessage = new GroupSendMessage();
groupSendMessage.setThumb_media_id(cdptsArticle.getImageMediaId());
groupSendMessage.setAuthor(cdptsArticle.getAuthor());
groupSendMessage.setTitle(cdptsArticle.getTitle());
groupSendMessage.setContent_source_url(cdptsArticle.getUrl());
groupSendMessage.setContent(cdptsArticle.getContent());
groupSendMessage.setShow_cover_pic(0);
groupSendMessageList.add(groupSendMessage);
}
logger.info("----------最终封装的图文消息列表:{}----------", groupSendMessageList);
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("articles", groupSendMessageList);
String groupSendMessageJsonStr = gson.toJson(jsonMap);
logger.info("----------最终要发送的图文消息json数据:{}----------", groupSendMessageJsonStr);
return groupSendMessageJsonStr;
}
private String uploadGroupSendMessage(String groupSendMessageJsonStr) {
String accessToken = accessTokenUtil.getAccessToken();
String postNewsResult = HttpUtil.sendPost(postNewsUrl.replace("ACCESS_TOKEN", accessToken),
groupSendMessageJsonStr);
logger.info("----------上传群发图文消息的返回结果:{}----------", postNewsResult);
String mediaId = "";
try {
JSONObject object = new JSONObject(postNewsResult);
mediaId = (String) object.get("media_id");
} catch (JSONException e) {
logger.error("上传群发图文消息发生错误{}", postNewsResult);
}
return mediaId;
}
public void sendToPreview(List<CdptsArticle> toSendNewsList, String openId, String mediaId) {
String accessToken = accessTokenUtil.getAccessToken();
SendToOpenIdPreview sendToPreview = new SendToOpenIdPreview(openId, mediaId);
String sendToPreviewJsonStr = gson.toJson(sendToPreview);
logger.info("----------预览的的json:{}----------", sendToPreviewJsonStr);
String sentToPreviewResult = HttpUtil.sendPost(sendToPreviewUrl.replace("ACCESS_TOKEN", accessToken),
sendToPreviewJsonStr);
logger.info("----------预览发送结果:{}----------", sentToPreviewResult);
checkSendResult(toSendNewsList, sentToPreviewResult);
}
*/
/**
* 根据openid 获取Unionid
*
* @param token
* @param openid
* @return
*/
public static String getUnionid(String token, String openid) {
System.out.println(token+"----------"+openid);
String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + token + "&openid=" + openid + "&lang=zh_CN";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url, String.class);
if (StringUtils.isNotBlank(result)) {
return JSONObject.parseObject(result).getString("unionid");
}
return null;
}
/**
* 服务类目为:“IT科技 > 软件服务提供商 > 服务完成通知”的模板数据结构
* @param toUserOpenId
* @param templateId
* @param serviceItem
* @param submitUser
* @return
*/
public static JSONObject dataJsonObjectForITSoftwareServiceSuccess(String toUserOpenId, String serviceItem, String submitUser, String page, String miniProgram) {
JSONObject jsonData = new JSONObject();
jsonData.put("touser", toUserOpenId);
jsonData.put("template_id", SERVICE_CATEGORY_IT_SOFTWARE_SERVICE_SUCCESS);
JSONObject paramData = new JSONObject();
JSONObject paramData1 = new JSONObject();
paramData1.put("value", serviceItem);
paramData.put("thing1", paramData1);
JSONObject paramData2 = new JSONObject();
paramData2.put("value", submitUser);
paramData.put("thing18", paramData2);
jsonData.put("data", paramData);
return jsonData;
}
public static void sendWechatMessage(String appId, // 微信公众号appId
String secret, // 微信公众号秘钥
String templateId, // 微信公众号消息模板ID
String openId, // 微信公众号openId
String url, // 微信公众号消息跳转链接
String first, // 微信公众号消息模板first字段
String keyword1, // 微信公众号消息模板keyword1字段
String keyword2, // 微信公众号消息模板keyword2字段
String keyword3, // 微信公众号消息模板keyword3字段
String keyword4, // 微信公众号消息模板keyword4字段
String remark // 微信公众号消息模板remark字段
) {
WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();
wxStorage.setAppId(appId);
wxStorage.setSecret(secret);
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxStorage);
// 2.模板配置信息赋值
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder().toUser(openId).templateId(templateId)
.url(url).build();
// 模板内容添加
Util util = Util.getInstance();
if (!util.isEmpty(first))
templateMessage.addData(new WxMpTemplateData("first", first, "#FF00FF"));
if (!util.isEmpty(keyword1))
templateMessage.addData(new WxMpTemplateData("keyword1", keyword1, "#000000"));
if (!util.isEmpty(keyword2))
templateMessage.addData(new WxMpTemplateData("keyword2", keyword2, "#000000"));
if (!util.isEmpty(keyword3))
templateMessage.addData(new WxMpTemplateData("keyword3", keyword3, "#000000"));
if (!util.isEmpty(keyword4))
templateMessage.addData(new WxMpTemplateData("keyword4", keyword4, "#000000"));
if (!util.isEmpty(remark))
templateMessage.addData(new WxMpTemplateData("remark", remark, "#000000"));
try {
// 模板消息发送
wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
} catch (Exception e) {
System.out.println("推送失败:" + e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
String toOpenId = "odjhD5gAPivi73RMWnzsSCgLrRyg";
String serviceItem = "高龄验证成功";
String submitUser = "民政局";
JSONObject templateData = dataJsonObjectForITSoftwareServiceSuccess(toOpenId, serviceItem, submitUser, "", "");
sendSubscribeBizsend(Constants.WECHAT_APPID_BMTG, Constants.WECHAT_SECERT_BMTG, templateData);
}
}