这一篇要开始写微信的开发啦~~
关于微信开发这一块的笔记都围绕着我现在做的这个项目为例。
(注:因为公司的平台架构不同,所以代码实现的方式有些不一样,但是,但是,但是,道理还是一样的)
在开发前新建一个WxConstant类,来存放微信配置的常量。
public static final String DOMAIN_URL = "http://域名";
public static final String CONTENT_URL = "/上下文";
public static final String WEB="/ns";//站点
public static final String TOKEN = "wechat";
public static final String APPID = "appid";
public static final String APPSECRET = "appsecret";
public static final String ORIGINID = "gh_xxx";
AppID(应用ID):该参数可用于唯一标识一个公众号。
AppSecret(应用密钥):该参数可重置,重置后系统原先的接口调用将失效。
originid:微信公众号的微信号
1.https请求接口
编写一个接口用来发送微信接口的请求。
(这里直接借用老前辈写的工具类的代码)
/**
* 发起https请求并获取结果
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect();
// 当有数据需要提交时
if (StringUtils.isNotEmpty(outputStr)) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException e) {
} catch (Exception e) {
e.printStackTrace();
}
return jsonObject;
http请求
/**发起http请求post方式*/
public static String sendHttpRequest(String requestUrl,String params)
{
try
{
URL realUrl = new URL(requestUrl);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = null;
StringBuilder sb = new StringBuilder();
while((line = br.readLine())!=null){
sb.append(line);
}
br.close();
return sb.toString();
}
catch (Exception e)
{
LogApp("发起HTTP请求失败:"+e);
return null;
}
}
完成了以上接口开发后就可以发起微信接口的请求了。
接下来编写获取accesstoken的接口请求。
2.获取access_token
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。因为access_token的有效时间是7200秒(也就是2个小时)且获取的次数一天内是有限的(具体看微信公众平台开发文档),所以获取access_token后需要将其妥善保存,可以放在缓存中,也可以存在数据库中。
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
/** 获取access_token
* @param appid 公众号唯一凭证
* @param appsecret 公众号唯一凭证密钥
* @return accessToken 接口调用凭证
*/
public static WxToken getAccessToken(String appid, String appsecret) {
WxToken accessToken = null;
String requestUrl = ACCESS_TOKEN_URL.replace("APPID", appid).replace("APPSECRET", appsecret);
JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
accessToken = new WxToken();
accessToken.setAppId(appid);
accessToken.setToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
String now = NowString_Mi().substring(0, 19);
accessToken.setCreateTime(now);
} catch (JSONException e) {
LogApp(e)
}
}
return accessToken;
}
上面是通过接口去获取access_token,在实际开发中我们需要先去缓存或数据库中查询accessToken是否过期,下面是以存放在数据库中为例:
public static String getAccessToken(String appId, String appSecret) {
String accessToken = null;
try{
//查询数据库,获取最近的凭证
EntityBean bean = searchToken(appId);
if (null != bean) {
accessToken = bean.getString(WxTokenTable.TOKEN);
//如果超过有效期,则重新获取
if (!isTokenValid(bean)) {
accessToken = doAccessToken(appId, appSecret);
LogDebug("凭证已失效,重新获取为:" + accessToken);
}
} else {
accessToken = doAccessToken(appId, appSecret);
LogDebug("第一次获取凭证:" + accessToken);
}
}catch(Exception e){
LogDebug("获取accesstoken失败:" + e.getMessage());
}
return accessToken;
}
/**
* 调用接口获取access_token,并将结果存储数据库
* @return accessToken 接口调用凭证
*/
private static String doAccessToken(String appId, String appSecret) {
String accessToken = null;
//获取接口调用凭证对象
WxToken at = WeixinUtil.getAccessToken(appId, appSecret);
if (null != at) {
addToken(at); //将结果存入数据库
accessToken = at.getToken(); //接口条用凭证
}
return accessToken;
}
/**
* 保存接口调用凭证
* @param at 接口调用凭证
*/
public void addToken(DataSource ds, WxToken at) {
Transaction tran = null;
try {
// 创建事务
tran = ds.createTransaction();
EntityBean bean = new EntityBean(WxTable.WXTOKEN);
bean.set(WxTokenTable.ID, Global.getInstance().GetUUID());
bean.set(WxTokenTable.APPID, at.getAppId());
bean.set(WxTokenTable.TOKEN, at.getToken());
bean.set(WxTokenTable.EXPIRESIN, at.getExpiresIn());
bean.set(WxTokenTable.CREATETIME, at.getCreateTime());
bean.insert(tran);
// 提交事务
tran.commit();
} catch (Exception e) {
tran.rollback();
} finally {
tran.close();
}
最后我们就可以愉快的使用access_token去调用微信公众号平台的各种接口啦辣~~
这篇笔记就到这里了。
备注上开发时常见的一些问题
1. 接口访问异常
l 解决方案:检查服务器网络是否正常,参数是否正确。检查微信公众号后台是否配置了ip白名单。
2. jssdk接口使用异常
l 解决方案:检查地址栏的地址与生成签名的url是否一致,检查appid与appsecret是否正确,检查微信公众号后台是否配置了js安全域名。
3. 网页授权失败
l 解决方案:检查微信后台设置,是否设置了授权域名。检查appid与appsecret是否正确。
4. 消息重复发送
l 解决方案:因为微信公众号在5秒内没有接收到开发者的返回结果会重复发送请求,有时候存在网络延迟的情况下,导致一条信息被公众号重复回复两次,这种情况需要用到msgid排重。(当不需要处理的时候尽量返回success或者空字符串)