微信公众号开发之生成带参数的二维码
做微信公众号开发的人员都知道用户海报作为公众号吸引用户是常见的渠道,那么我就说说这个海报的生成。
看了好多公众号发现他们的海报都是大同小异,一个漂亮的背景+自己的头像+专属二维码。
背景就不阐述了,用户的头像可以由公众号开发文档提供的方式获取(根据用户的openId),今天主要讲用户的专属二维码
所谓专属即便是一对一的。
二维码分为两种,临时二维码和永久二维码
/*生成永久二维码*/
public static String getPerpetualQR(String account){
//获取数据的地址(微信提供)
String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=access_token (变量)";
//发送给微信服务器的数据
String jsonStr = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\":{\"scene\": {\"scene_id\": "+account+"}}}";
//post请求得到返回数据(这里是封装过的,就是普通的java post请求)
String response = RequestMethod.sendPost(jsonStr, url);
return response.toString();
}
这里解释一下发送的数据:
action_name:可以识别你要获取的二维码是永久性还是临时的(QR_LIMIT_SCENE :永久;QR_SCENE:临时),
scene_id:要传入的参数
服务器的返回数据
{"ticket":"gQHp7zoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0tEc29Sd0xsU2VzdzVHWTA2UmZSAAIEBQ5hVwMEAAAAAA==",
"url":"http:\/\/weixin.qq.com\/q\/KDsoRwLlSesw5GY06RfR"}
ticket:与上面传入的参数是一一对应的,所以上面传入的参数最好是唯一的可以标识的数据,而且用户在扫二维码的时候,如果是扫带有参数的二维码,那么微信服务器会返回这个ticket,具体可以看上一节(用户关注)
url:二维码地址,后台可以根据这个地址将二维码下载到本地,具体的方法我会在下面提供一个。
到这里大家应该会疑问上面的access_token (变量),这个是和微信服务器打交道的识别数据,这个数据必须有效才能进行一切的获取数据操作,去开发文档上看可以了解到这个数据由微信服务器提供,2个小时过期,但是每两个小时之间会有一个过渡期,新老access_token 都可以使用,不过这个过渡期的时间确实个谜,本人也未研究过,只是很多网友说这个过渡期是3-5分钟。这里有个很大的坑,就是token没有过期,但是微信服务器返回token失效,具体的解决方案待我下一节详说。
以上是永久二维码的获取步骤,但是永久二维码有一个缺陷,就是数量有限(目前最多为10万个),临时二维码会更多,但是是否是无限的,这个待定。。。
/*生成临时二维码*/
public static String getTemporaryQR(String scene_id){
//获取数据的地址(微信提供)
String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=access_token (变量) ";
//发送给微信服务器的数据
String jsonStr = "{\"expire_seconds\": 2592000,\"action_name\": \"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": "+scene_id+"}}}";
//将得到的字符串转化成json对象
String response = RequestMethod.sendPost(jsonStr, url);
return response.toString();
}
发送的数据相对永久二维码多了一个expire_seconds,这是设定二维码的有效期,以秒为单位,最多不超过30天,并且action_name需要改成QR_SCENE。
服务器的返回数据
{"ticket":"gQFt7zoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0F6dFktTVhsSV90YXNVX1ZtUlhSAAIE5hxiVwMEPAAAAA==",
"expire_seconds":60,
"url":"http:\/\/weixin.qq.com\/q\/AztY-MXlI_tasU_VmRXR"}
返回的数据相对永久二维码就是多了一个expire_seconds,这个是有效期,过期扫码无效。
现在大家都知道了永久二维码和临时二维码之间的区别了,至于使用哪一种,根据需求变化。
参数与ticket之间是一一对应的,这也就达到了生成用户海报的专属二维码了,至于这个参数的选定,本人可以给一个建议,将用户的openId+当前时间作为参数,返回的ticket和用户就可以达到一一对应的想过了,当二维码过期,数据库更新ticket这个数据就可以了,或者用户每次获取海报的时候就重新更新一个二维码,反正临时的很多。其他用户扫这个二维码的时候微信会将二维码的ticket返回给我们,再根据ticket和openId的对应关系就可以知道当前被扫用户是谁了。
下面提供一些方法:
//post请求
public static String sendPost(String param, String url) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
// out = new PrintWriter(conn.getOutputStream());
out = new PrintWriter(new OutputStreamWriter(
conn.getOutputStream(), "utf-8"));
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
//根据url下载文件,参数(文件网址,存文件的本地地址)
public static Boolean downloadFile(String urlString, String filePath){
// 构造URL
URL url;
try {
url = new URL(urlString);
// 打开连接
URLConnection con;
try {
con = url.openConnection();
// 输入流
InputStream is = con.getInputStream();
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流
OutputStream os = new FileOutputStream(filePath);
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 完毕,关闭所有链接
os.close();
is.close();
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}