在微信公众号开发的最基础的第一步就是获取access_token.
access_token的描述:
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。正常情况下access_token有效期为7200秒,重复获取将导致上次获取的access_token失效。由于获取access_token的api调用次数非常有限,建议开发者全局存储与更新access_token,频繁刷新access_token会导致api调用受限,影响自身业务
链接中有三个参数,分别是grant_type、appid和secret
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
grant_type传固定值client_credential,而appid和secret就是申请完自定义菜单后微信分配给我们的.
首先创建两个工具类;
{"access_token":"ACCESS_TOKEN","expires_in":7200}
/**
* 微信通用接口凭证
*
*/
public class AccessToken {
// 获取到的凭证
private String token;
// 凭证有效时间,单位:秒
private int expiresIn;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
}
/*
* 微信极速发票工具类
*/
public class TokenData {
// 抬头类型
private int title_type;
// 抬头
private String title;
// 联系方式
private String phone;
// 税号
private String tax_no;
// 地址
private String addr;
// 银行类型
private String bank_type;
// 银卡号
private String bank_no;
public int getTitle_type() {
return title_type;
}
public void setTitle_type(int title_type) {
this.title_type = title_type;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getTax_no() {
return tax_no;
}
public void setTax_no(String tax_no) {
this.tax_no = tax_no;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public String getBank_type() {
return bank_type;
}
public void setBank_type(String bank_type) {
this.bank_type = bank_type;
}
public String getBank_no() {
return bank_no;
}
public void setBank_no(String bank_no) {
this.bank_no = bank_no;
}
}
需要进入几个包
com.sun.net.ssl.jar
jsr94-j2ee.rar
slf4j-api-1.7.6.jar
对于https请求,我们还需要一个证书信任管理器,这个管理器类需要自己定义,需要实现X509TrustManager接口即可,代码如下
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* 证书信任管理器(用于https请求)
*
*/
public class MyX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
这个证书管理器的作用就是让它信任我们指定的证书,上面的代码意味着信任所有证书,不管是否权威机构颁发。
证书有了,通用的https请求方法就不难实现了,实现代码如下
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLConnection;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
/**
* 微信公众平台 https://mp.weixin.qq.com/wiki
*
*/
public class WeixinUtil {
private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
public static String appid = "***";
public static String appsecret = "***";
public static String scan ="************";
//获取access_token
public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
/*
* 获取返回参数
* access_token_data_url
* 固定 Scan_test不固定
* https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1496554912_vfWU0
*/
public final static String Scan_test = "https://mp.weixin.qq.com/intp/invoice/usertitlewxa?action=list_auth&invoice_key=Scan_test";
public final static String access_token_data_url = "https://api.weixin.qq.com/card/invoice/scantitle?access_token=AccessToken";
public static void main(String[] args) {
AccessToken accessToken = getAccessToken(appid, appsecret);
String Access_Token = accessToken.getToken();
System.out.println("Access_Token-->"+Access_Token);
String url = access_token_data_url.replace("AccessToken", Access_Token);
System.out.println("url-->"+url);
String scan_test =Scan_test.replace("Scan_test", scan);
System.out.println("scan_test-->"+scan_test);
Bean b = new Bean();
b.scan_test = scan_test;
String body = new Gson().toJson(b);
String result = post(url, body);
System.out.println("result-->"+result);
TokenData tokendata = Access_Token(result);
System.out.println("tokendata-->"+tokendata);
int title_type = tokendata.getTitle_type();
System.out.println("title_type-->"+title_type);
System.out.println("title_type-->"+tokendata.getTax_no());
System.out.println("title_type-->"+tokendata.getBank_no());
System.out.println("title_type-->"+tokendata.getBank_type());
}
/**
* 获取access_token
*
* @param appid
* 凭证
* @param appsecret
* 密钥
* @return
*/
public static AccessToken getAccessToken(String appid, String appsecret) {
AccessToken accessToken = null;
String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
accessToken = new AccessToken();
accessToken.setToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
} catch (JSONException e) {
accessToken = null;
// 获取token失败
log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
}
}
return accessToken;
}
/**
* 发起https请求并获取结果
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpRequest(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 (null != 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 ce) {
log.error("Weixin server connection timed out.");
} catch (Exception e) {
log.error("https request error:{}", e);
}
return jsonObject;
}
/*
*发起https请求并获取结果
*
* @param url
* 请求地址
* @param requestMethod
* 请求方式(POST)
* @param body
* 请求参数
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static String post(String url, String body) {
String result = "";
try {
OutputStreamWriter out = null;
BufferedReader in = null;
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
// 发送请求,将网页以流的形式读回来
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setConnectTimeout(5000);
conn.setReadTimeout(20000);
// 设置字节流
out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
out.write(body);
out.flush();
System.out.println(conn.getInputStream());
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line = "";
boolean firstLine = true;
while ((line = in.readLine()) != null) {
if (firstLine) {
firstLine = false;
} else {
result += System.lineSeparator();
}
result += line;
}
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/*
* 工具类
* 就一个属性就写在这了
*/
public static class Bean {
public String scan_test;
}
public static String getPicBASE64(String picPath) {
String content = "";
try {
FileInputStream fileForInput = new FileInputStream(picPath);
byte[] bytes = new byte[fileForInput.available()];
if (bytes.length < 102400) {
System.out.print(bytes.length);
}
fileForInput.read(bytes);
content = new sun.misc.BASE64Encoder().encode(bytes); // 具体的编码方法
fileForInput.close();
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
/*
* 解析返回参数
*/
private static TokenData Access_Token(String result) {
TokenData tokendata = null;
//result = "{'title':'单位抬头','tax_no':'aaaa123456','addr':'12345688','errcode':0,'bank_type':'银行类型','phone':'123999','title_type':0,'errmsg':'ok','bank_no':'999685',}";
JSONObject jsonObject = JSONObject.fromObject(result);
System.out.println("jsonObject-->"+jsonObject);
// 如果请求成功
if (null != jsonObject) {
try {
tokendata = new TokenData();
tokendata.setTitle_type(jsonObject.getInt("title_type"));
tokendata.setTitle(jsonObject.getString("title"));
tokendata.setPhone(jsonObject.getString("phone"));
tokendata.setTax_no(jsonObject.getString("tax_no"));
tokendata.setAddr(jsonObject.getString("addr"));
tokendata.setBank_type(jsonObject.getString("bank_type"));
tokendata.setBank_no(jsonObject.getString("bank_no"));
} catch (JSONException e) {
tokendata = null;
// 获取token失败
// log.error("获取token失败 errcode:{} errmsg:{}",
jsonObject.getInt("errcode");
jsonObject.getString("errmsg");
System.out.println("null");
}
}
return tokendata;
}
}
注意:使用Gson将对象类转成Json对象时出现\u003d的问题
Gson将对象转成Json对象的方法
Gson gson=new Gson();
String json=gson.toJson(Student.class);
这种情况,如果Student属性中的某个值包含有=,会变为\u003d的
只需将Gson的初始化修改为
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
注意:
因为access_token每天得调用次数有限,建议不要每次的通讯都去获取新的access_token,可以将其用管理器的方式来进行管理,当失效的时候再重新获取。