JAVA微信公众号开发之二维码的创建与获取
微信文档说明
两种二维码:
1、临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景
2、永久二维码,是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。
用户扫描带场景值二维码时,可能推送以下两种事件:
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。
获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.liaofang.mapper.AccessTokenMapper;
import com.liaofang.po.AccessTokenPO;
import com.liaofang.po.WeiXinResult;
import com.liaofang.service.AccessTokenServiceImp;
import com.liaofang.util.ConfigUtil;
import com.liaofang.util.GetMapSign;
import com.liaofang.util.HttpRequestUtil;
import com.liaofang.util.SignUtil;
import net.sf.json.JSONObject;@Servicepublic class WxQRCodeServiceImp implements WxQRCodeService {@Autowiredprivate AccessTokenMapper atMapper;/*** 创建临时二维码* @MethodName:createTempTicket*@author:maliran*@ReturnType:String*@param accessToken*@param expireSeconds*@param sceneId*@return* @throws Exception */public String createTempTicket(String expireSeconds, int sceneId) throws Exception { Map<String,String> map = new HashMap<String,String>();AccessTokenPO atPO = new AccessTokenPO();List<AccessTokenPO> list = new ArrayList<AccessTokenPO>();String accessToken = "";String jsapi_ticket="";String ticket="";list = atMapper.selectToken();System.out.println(list.size());if(list.size()!=0){System.out.println(list.get(0));if((new Date().getTime()/1000-list.get(0).getCurrentTime().getTime()/1000)>6000){//access_token过期map = GetMapSign.getTicket();accessToken = map.get("access_token");atPO.setAccess_token(accessToken);atPO.setCurrentTime(new Date());atPO.setExpires_in(Integer.parseInt(map.get("expires_in")));jsapi_ticket=map.get("ticket");atPO.setTicket(jsapi_ticket);atMapper.updateToken(atPO);}else{list = atMapper.selectToken();jsapi_ticket=list.get(0).getTicket();accessToken = list.get(0).getAccess_token();}}else{map = GetMapSign.getTicket();accessToken = map.get("access_token");atPO.setAccess_token(accessToken);atPO.setCurrentTime(new Date());atPO.setExpires_in(Integer.parseInt(map.get("expires_in")));jsapi_ticket=map.get("ticket");atPO.setTicket(jsapi_ticket);atMapper.insertToken(atPO);}TreeMap<String,String> params = new TreeMap<String,String>(); params.put("access_token", accessToken); Map<String,Integer> intMap = new HashMap<String,Integer>(); intMap.put("scene_id",sceneId); Map<String,Map<String,Integer>> mapMap = new HashMap<String,Map<String,Integer>>(); mapMap.put("scene", intMap); // Map<String,Object> paramsMap = new HashMap<String,Object>(); paramsMap.put("expire_seconds", expireSeconds); paramsMap.put("action_name", ConfigUtil.QR_SCENE); paramsMap.put("action_info", mapMap); String data = JSONObject.fromObject(paramsMap).toString(); JSONObject jsonObject = SignUtil.doPostStr(ConfigUtil.CREATE_TICKET_PATH, data);if(jsonObject!=null){ticket = jsonObject.optString("ticket");}return ticket;} /** * 创建永久二维码(数字) * @param accessToken * @param sceneId 场景Id * @return * @throws Exception */ public String createForeverTicket(int sceneId) throws Exception { Map<String,String> map = new HashMap<String,String>();AccessTokenPO atPO = new AccessTokenPO();List<AccessTokenPO> list = new ArrayList<AccessTokenPO>();String accessToken = "";String jsapi_ticket="";String ticket="";list = atMapper.selectToken();System.out.println(list.size());if(list.size()!=0){System.out.println(list.get(0));if((new Date().getTime()/1000-list.get(0).getCurrentTime().getTime()/1000)>6000){//access_token过期map = GetMapSign.getTicket();accessToken = map.get("access_token");atPO.setAccess_token(accessToken);atPO.setCurrentTime(new Date());atPO.setExpires_in(Integer.parseInt(map.get("expires_in")));jsapi_ticket=map.get("ticket");atPO.setTicket(jsapi_ticket);atMapper.updateToken(atPO);}else{list =atMapper.selectToken();jsapi_ticket=list.get(0).getTicket();accessToken = list.get(0).getAccess_token();}}else{map = GetMapSign.getTicket();accessToken = map.get("access_token");atPO.setAccess_token(accessToken);atPO.setCurrentTime(new Date());atPO.setExpires_in(Integer.parseInt(map.get("expires_in")));jsapi_ticket=map.get("ticket");atPO.setTicket(jsapi_ticket);atMapper.insertToken(atPO);}TreeMap<String,String> params = new TreeMap<String,String>(); params.put("access_token", accessToken); Map<String,Integer> intMap = new HashMap<String,Integer>(); intMap.put("scene_id",sceneId); Map<String,Map<String,Integer>> mapMap = new HashMap<String,Map<String,Integer>>(); mapMap.put("scene", intMap); Map<String,Object> paramsMap = new HashMap<String,Object>(); paramsMap.put("action_name", ConfigUtil.QR_LIMIT_SCENE); paramsMap.put("action_info", mapMap); String data =JSONObject.fromObject(paramsMap).toString(); JSONObject jsonObject = SignUtil.doPostStr(ConfigUtil.CREATE_TICKET_PATH, data);if(jsonObject!=null){ticket = jsonObject.optString("ticket");}return ticket;} /** * 创建永久二维码(字符串) * * @param accessToken * @param sceneStr 场景str * @return * @throws Exception */ public String createForeverStrTicket(String sceneStr) throws Exception{ Map<String,String> map = new HashMap<String,String>();AccessTokenPO atPO = new AccessTokenPO();List<AccessTokenPO> list = new ArrayList<AccessTokenPO>();String accessToken = "";String jsapi_ticket="";String ticket="";list = atMapper.selectToken();System.out.println(list.size());if(list.size()!=0){System.out.println(list.get(0));if((new Date().getTime()/1000-list.get(0).getCurrentTime().getTime()/1000)>6000){//access_token过期map = GetMapSign.getTicket();accessToken = map.get("access_token");atPO.setAccess_token(accessToken);atPO.setCurrentTime(new Date());atPO.setExpires_in(Integer.parseInt(map.get("expires_in")));jsapi_ticket=map.get("ticket");atPO.setTicket(jsapi_ticket);atMapper.updateToken(atPO);}else{list = atMapper.selectToken();jsapi_ticket=list.get(0).getTicket();accessToken = list.get(0).getAccess_token();}}else{map = GetMapSign.getTicket();accessToken = map.get("access_token");atPO.setAccess_token(accessToken);atPO.setCurrentTime(new Date());atPO.setExpires_in(Integer.parseInt(map.get("expires_in")));jsapi_ticket=map.get("ticket");atPO.setTicket(jsapi_ticket);atMapper.insertToken(atPO);}TreeMap<String,String> params = new TreeMap<String,String>(); params.put("access_token", accessToken); String url = ConfigUtil.CREATE_TICKET_PATH.replace("ACCESS_TOKEN", accessToken);Map<String,String> intMap = new HashMap<String,String>(); intMap.put("scene_str",sceneStr); Map<String,Map<String,String>> mapMap = new HashMap<String,Map<String,String>>(); mapMap.put("scene", intMap); Map<String,Object> paramsMap = new HashMap<String,Object>(); paramsMap.put("action_name", ConfigUtil.QR_LIMIT_STR_SCENE); paramsMap.put("action_info", mapMap); String data =JSONObject.fromObject(paramsMap).toString(); JSONObject jsonObject = SignUtil.doPostStr(url, data);if(jsonObject!=null){ticket = jsonObject.optString("ticket");}return ticket;} /** * 获取二维码ticket后,通过ticket换取二维码图片展示 * @param ticket * @return */ public String showQrcode(String ticket){ String showqrcode_path = "";Map<String,String> params = new TreeMap<String,String>(); params.put("ticket", HttpRequestUtil.urlEncode(ticket, HttpRequestUtil.DEFAULT_CHARSET)); try { showqrcode_path = HttpRequestUtil.setParmas(params,ConfigUtil.SHOWCODE_PATH,""); } catch (Exception e) { e.printStackTrace(); } return showqrcode_path; } /** * 获取二维码ticket后,通过ticket换取二维码图片 * @param ticket * @param savePath 保存的路径,例如 F:\\test\test.jpg * @return Result.success = true 表示下载图片下载成功 */ public WeiXinResult showQrcode(String ticket,String savePath) throws Exception{ TreeMap<String,String> params = new TreeMap<String,String>(); params.put("ticket", HttpRequestUtil.urlEncode(ticket, HttpRequestUtil.DEFAULT_CHARSET)); WeiXinResult result = HttpRequestUtil.downMeaterMetod(params,HttpRequestUtil.GET_METHOD,ConfigUtil.
SHOWCODE_PATH,savePath);
return result; } }
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager; import com.liaofang.po.WeiXinResult; public class HttpRequestUtil { //private static Logger logger = Logger.getLogger(HttpRequestUtil.class); public static final String GET_METHOD = "GET"; public static final String POST_METHOD = "POST"; public static final String DEFAULT_CHARSET = "utf-8"; private static int DEFAULT_CONNTIME = 5000; private static int DEFAULT_READTIME = 5000; // 获取access_token的路径 private static String token_path = "https://api.weixin.qq.com/cgi-bin/token"; /** * http请求 * * @param method * 请求方法GET/POST * @param path * 请求路径 * @param timeout * 连接超时时间 默认为5000 * @param readTimeout * 读取超时时间 默认为5000 * @param data 数据 * @return */ public static String defaultConnection(String method, String path, int timeout, int readTimeout, String data) throws Exception { String result = ""; URL url = new URL(path); if (url != null) { HttpURLConnection conn = getConnection(method, url); conn.setConnectTimeout(timeout == 0 ? DEFAULT_CONNTIME : timeout); conn.setReadTimeout(readTimeout == 0 ? DEFAULT_READTIME : readTimeout); if (data != null && !"".equals(data)) { OutputStream output = conn.getOutputStream(); output.write(data.getBytes(DEFAULT_CHARSET)); output.flush(); output.close(); } if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { InputStream input = conn.getInputStream(); result = inputToStr(input); input.close(); conn.disconnect(); } } return result; } /** * 根据url的协议选择对应的请求方式 例如 http://www.baidu.com 则使用http请求,https://www.baidu.com * 则使用https请求 * * @param method * 请求的方法 * @return * @throws IOException */ private static HttpURLConnection getConnection(String method, URL url) throws IOException { HttpURLConnection conn = null; if ("https".equals(url.getProtocol())) { SSLContext context = null; try { context = SSLContext.getInstance("SSL", "SunJSSE"); context.init(new KeyManager[0], new TrustManager[] { new MyX509TrustManager() },
new java.security.SecureRandom()); } catch (Exception e) { throw new IOException(e); } HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection(); connHttps.setSSLSocketFactory(context.getSocketFactory()); connHttps.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); conn = connHttps; } else { conn = (HttpURLConnection) url.openConnection(); } conn.setRequestMethod(method); conn.setUseCaches(false); conn.setDoInput(true); conn.setDoOutput(true); return conn; } /** * 将输入流转换为字符串 * * @param input * 输入流 * @return 转换后的字符串 */ public static String inputToStr(InputStream input) { String result = ""; if (input != null) { byte[] array = new byte[1024]; StringBuffer buffer = new StringBuffer(); try { for (int index; (index = (input.read(array))) > -1;) { buffer.append(new String(array, 0, index, DEFAULT_CHARSET)); } result = buffer.toString(); } catch (IOException e) { e.printStackTrace(); result = ""; } } return result; } /** * 设置参数 * * @param map * 参数map * @param path * 需要赋值的path * @param charset * 编码格式 默认编码为utf-8(取消默认) * @return 已经赋值好的url 只需要访问即可 */ public static String setParmas(Map<String, String> map, String path, String charset) throws Exception { String result = ""; boolean hasParams = false; if (path != null && !"".equals(path)) { if (map != null && map.size() > 0) { StringBuilder builder = new StringBuilder(); Set<Entry<String, String>> params = map.entrySet(); for (Entry<String, String> entry : params) { String key = entry.getKey().trim(); String value = entry.getValue().trim(); if (hasParams) { builder.append("&"); } else { hasParams = true; } if(charset != null && !"".equals(charset)){ //builder.append(key).append("=").append(URLDecoder.(value, charset)); builder.append(key).append("=").append(urlEncode(value, charset)); }else{ builder.append(key).append("=").append(value); } } result = builder.toString(); } } return doUrlPath(path, result).toString(); } /** * 设置连接参数 * * @param path * 路径 * @return */ private static URL doUrlPath(String path, String query) throws Exception { URL url = new URL(path); if (org.apache.commons.lang.StringUtils.isEmpty(path)) { return url; } if (org.apache.commons.lang.StringUtils.isEmpty(url.getQuery())) { if (path.endsWith("?")) { path += query; } else { path = path + "?" + query; } } else { if (path.endsWith("&")) { path += query; } else { path = path + "&" + query; } } return new URL(path); } /** * 默认的http请求执行方法,返回 * * @param method * 请求的方法 POST/GET * @param path * 请求path 路径 * @param map * 请求参数集合 * @param data * 输入的数据 允许为空 * @return */ public static String HttpDefaultExecute(String method, String path, Map<String, String> map, String data) { String result = ""; try { String url = setParmas((TreeMap<String, String>) map, path, ""); result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data); } catch (Exception e) { e.printStackTrace(); } return result; } /** * 默认的https执行方法,返回 * * @param method * 请求的方法 POST/GET * @param path * 请求path 路径 * @param map * 请求参数集合 * @param data * 输入的数据 允许为空 * @return */ public static String HttpsDefaultExecute(String method, String path, Map<String, String> map, String data) { String result = ""; try { String url = setParmas((TreeMap<String, String>) map, path, ""); result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data); } catch (Exception e) { e.printStackTrace(); } return result; } /** * 默认的下载素材方法 * * @param method http方法 POST/GET * @param apiPath api路径 * @param savePath 素材需要保存的路径 * @return 是否下载成功 Reuslt.success==true 表示下载成功 */ public static WeiXinResult downMeaterMetod(TreeMap<String, String> params, String method, String apiPath, String savePath) { WeiXinResult result = new WeiXinResult(); try { apiPath = setParmas(params, apiPath, ""); URL url = new URL(apiPath); HttpURLConnection conn = getConnection(method, url); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { String contentType = conn.getContentType(); result = ContentType(contentType, conn, savePath); } else { result.setObj(conn.getResponseCode() + " " + conn.getResponseMessage()); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return result; } /** * 根据返回的头信息返回具体信息 * * @param contentType * ContentType请求头信息 * @return Result.type==1 表示文本消息, */ private static WeiXinResult ContentType(String contentType, HttpURLConnection conn, String savePath) { WeiXinResult result = new WeiXinResult(); try { if (conn != null) { InputStream input = conn.getInputStream(); if (contentType.equals("image/gif")) { // gif图片 result = InputStreamToMedia(input, savePath, "gif"); } else if (contentType.equals("image/jpeg")) { // jpg图片 result = InputStreamToMedia(input, savePath, "jpg"); } else if (contentType.equals("image/jpg")) { // jpg图片 result = InputStreamToMedia(input, savePath, "jpg"); } else if (contentType.equals("image/png")) { // png图片 result = InputStreamToMedia(input, savePath, "png"); } else if (contentType.equals("image/bmp")) { // bmp图片 result = InputStreamToMedia(input, savePath, "bmp"); } else if (contentType.equals("audio/x-wav")) { // wav语音 result = InputStreamToMedia(input, savePath, "wav"); } else if (contentType.equals("audio/x-ms-wma")) { // wma语言 result = InputStreamToMedia(input, savePath, "wma"); } else if (contentType.equals("audio/mpeg")) { // mp3语言 result = InputStreamToMedia(input, savePath, "mp3"); } else if (contentType.equals("text/plain")) { // 文本信息 String str = inputToStr(input); result.setObj(str); } else if (contentType.equals("application/json")) { // 返回json格式的数据 String str = inputToStr(input); result.setObj(str); } else { // 此处有问题 String str = inputToStr(input); result.setObj(str); } } else { result.setObj("conn is null!"); } } catch (Exception ex) { ex.printStackTrace(); } return result; } /** * 将字符流转换为图片文件 * * @param input 字符流 * @param savePath 图片需要保存的路径 * @param 类型 jpg/png等 * @return */ private static WeiXinResult InputStreamToMedia(InputStream input, String savePath, String type) { WeiXinResult result = new WeiXinResult(); try { File file = null; file = new File(savePath); String paramPath = file.getParent(); // 路径 String fileName = file.getName(); // String newName = fileName.substring(0, fileName.lastIndexOf(".")) + "." + type;// 根据实际返回的文件类型后缀 savePath = paramPath + "\\" + newName; if (!file.exists()) { File dirFile = new File(paramPath); dirFile.mkdirs(); } file = new File(savePath); FileOutputStream output = new FileOutputStream(file); int len = 0; byte[] array = new byte[1024]; while ((len = input.read(array)) != -1) { output.write(array, 0, len); } output.flush(); output.close(); result.setSuccess(true); result.setObj("save success!"); } catch (FileNotFoundException e) { e.printStackTrace(); result.setSuccess(false); result.setObj(e.getMessage()); } catch (IOException e) { e.printStackTrace(); result.setSuccess(false); result.setObj(e.getMessage()); } return result; } public static String urlEncode(String source, String encode) { String result = source; try { result = URLEncoder.encode(source, encode); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return result; }
}
/*** post请求*/public static JSONObject doPostStr(String url,String outStr){DefaultHttpClient httpClient = new DefaultHttpClient();HttpPost httpPost = new HttpPost(url);JSONObject jsonObject = null;String result="";try {httpPost.setEntity(new StringEntity(outStr,"utf-8"));HttpResponse response = httpClient.execute(httpPost);result = EntityUtils.toString(response.getEntity(),"utf-8");} catch (Exception e) {} jsonObject = JSONObject.fromObject(result);return jsonObject;}
最近在整理一些资源工具,放在网站分享 http://tools.maqway.com
欢迎关注公众号:麻雀唯伊 , 不定时更新资源文章,生活优惠,或许有你想看的
JAVA微信公众号开发之二维码的创建与获取相关推荐
- 微信公众号生成临时二维码
微信公众号生成临时二维码 微信公众平台生成带参数的二维码官方文档 分为三个部分: 获取access_token.通过ticket换取二维码.生成带参数的二维码 特别注意:需要有生成二维码的权限. 整个 ...
- 怎么实现微信公众号生成专属二维码推广来源统计
为了实现微信公众号生成专属二维码推广来源统计功能,第三方平台微号帮提供了渠道二维码生成功能实现,可以给微信公众号在线生成专属推广二维码,统计公众号各个渠道来源的粉丝,一个渠道对应一个推广二维码,可以生 ...
- java_微信公众号扫码绑定个人信息(微信公众号场景值二维码的使用)
看了一下网上关于公众号场景值二维码这方面的教程,基本上是微信官方开发文档的复制,没有具体实例.这里给出实例,并附加二维码url转文件流的方法. 思路: 1.后台传入个人信息保存,以个人信息的" ...
- 微信公众号带参数二维码的几个使用场景
微信公众号官方开放了 "带参数二维码" 的功能,根据官网文档的描述,有如下的特点: 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口. 通过 ...
- Java微信公众号开发(附源码!!!)
笔者最近在为一个艺考服务团队开发手机端的服务,由于开发app需要的时间较长,所以选择开发微信公众号.本人比较擅长Java开发,所以本文是基于Java语言的公众号开发.话不多说,直接进入正题. 准备工作 ...
- 【黄啊码】PHP配合微信公众号生成推广二维码
前言 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口.使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送. 1.目前有2种类型的 ...
- 微信公众号带参二维码的生成以及后台Java的处理
1.生成带参二维码 有两种方式,一是通过微信公众平台来生成,二是通过java代码生成 一:微信平台生成 首先进入公众平台,找到接口权限进入 进入后找到获取access_tocken接口,获取acces ...
- laravel生成微信公众号带参数二维码并响应扫描带参数二维码
微信公众号后台ip白名单.网页接口域名之类的配置就不多说了,这里主要配置的是开发->基本配置->服务器配置(注:一旦启用改配置,公众号自动回复就会失效): 1.服务器地址(URL):这里要 ...
- Yii实现微信公众号的场景二维码
在Yii中实现场景二维码这里我使用的是easywechat插件,安装easywechat插件 composer require jianyan74/yii2-easy-wechat github地址: ...
最新文章
- 【面试】吃透了这些Redis知识点,面试官一定觉得你很NB
- python中字符串的rstrip()方法
- vim使用帮助命令的方法
- 排队问题解题思路_三大策略、5个技巧,完美解决超市收银排队难题
- 32 | 答疑(四):阻塞、非阻塞 I/O 与同步、异步 I/O 的区别和联系
- c语言printf函数很长时间,C语言学习之printf()函数特别注意事项
- HDU2519 新生晚会【组合计算】
- Linux sudo一些命令出现 command not found 的原因
- Mac上翻译不在 Safari 中网站的方法
- renpy-视觉小说转换器-编程零基础写视觉小说
- SPDY协议 - v3
- android通过webview调起支付宝app支付
- 悠悠web(1)-HTML基本结构
- envi与arcgis文件转换_[转载]ArcGIS、MapInfo、ENVI、MapGIS等矢量格式相互转换
- 解密保存Mac版微信聊天记录的数据库文件并导出聊天记录
- 达梦数据库统计模式下所有表记录数
- outlook邮件路径更改_如何在Outlook中更改电子邮件的“答复”地址
- 青岛啤酒12星座铝瓶星耀公开 啤酒也有自己的朋友圈
- 如何监控Windows进程的句柄资源
- 数字工厂生产监控可视化决策平台,打造智能制造新时代