精华内容
下载资源
问答
  • 微信官方提供生成二维码接口...临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量,主要用于帐号绑定等不要求二维码永久保存业务场景永久二维码,是

    转自:http://blog.csdn.net/phil_jing/article/details/53910083

    微信官方提供的生成二维码接口得到的是当前公众号的二维码,官方文档

    目前有2种类型的二维码:
    • 临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量,主要用于帐号绑定等不要求二维码永久保存的业务场景
    • 永久二维码,是无过期时间的,但数量较少(目前为最多10万个),主要用于适用于帐号绑定、用户来源统计等场景

    获取带参数的二维码有两种方法

    • 先获取二维码ticket,然后凭借ticket通过接口换取二维码图片,但是得到ticket之前首先得获取微信全局唯一接口调用凭据
    • 根据微信返回二维码中url参数自行生成二维码

    一、获取微信全局接口调用凭证

    调用接口时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,否则将无法调用成功

    Java微信公众平台开发之AccessToken获取

    二、获取二维码的Ticket

    1. /** 
    2.  * 创建临时带参数二维码 
    3.  *  
    4.  * @param accessToken 
    5.  * @expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。 
    6.  * @param sceneId 场景Id 
    7.  * @return 
    8.  */  
    9. public String createTempTicket(String accessToken, String expireSeconds, int sceneId) {  
    10.     WechatQRCode wechatQRCode = null;  
    11.     TreeMap<String, String> params = new TreeMap<String, String>();  
    12.     params.put("access_token", accessToken);  
    13.     Map<String, Integer> intMap = new HashMap<String, Integer>();  
    14.     intMap.put("scene_id", sceneId);  
    15.     Map<String, Map<String, Integer>> mapMap = new HashMap<String, Map<String, Integer>>();  
    16.     mapMap.put("scene", intMap);  
    17.     //  
    18.     Map<String, Object> paramsMap = new HashMap<String, Object>();  
    19.     paramsMap.put("expire_seconds", expireSeconds);  
    20.     paramsMap.put("action_name", WeChatConfig.QR_SCENE);  
    21.     paramsMap.put("action_info", mapMap);  
    22.     Gson gson = new Gson();  
    23.     String data = gson.toJson(paramsMap);  
    24.     data = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.POST_METHOD, WeChatConfig.CREATE_TICKET_PATH, params, data);  
    25.     try {  
    26.         wechatQRCode = gson.fromJson(data, WechatQRCode.class);  
    27.         gson = null;  
    28.     } catch (JsonSyntaxException e) {  
    29.         e.printStackTrace();  
    30.     }  
    31.     return wechatQRCode == null ? null : wechatQRCode.getTicket();  
    32.   
    33. }  
    34.   
    35. /** 
    36.  * 创建永久二维码(数字) 
    37.  *  
    38.  * @param accessToken 
    39.  * @param sceneId 场景Id 
    40.  * @return 
    41.  */  
    42. public String createForeverTicket(String accessToken, int sceneId) {  
    43.     TreeMap<String, String> params = new TreeMap<String, String>();  
    44.     params.put("access_token", accessToken);  
    45.     // output data  
    46.     Map<String, Integer> intMap = new HashMap<String, Integer>();  
    47.     intMap.put("scene_id", sceneId);  
    48.     Map<String, Map<String, Integer>> mapMap = new HashMap<String, Map<String, Integer>>();  
    49.     mapMap.put("scene", intMap);  
    50.     //  
    51.     Map<String, Object> paramsMap = new HashMap<String, Object>();  
    52.     paramsMap.put("action_name", WeChatConfig.QR_LIMIT_SCENE);  
    53.     paramsMap.put("action_info", mapMap);  
    54.     Gson gson = new Gson();  
    55.     String data = gson.toJson(paramsMap);  
    56.     data = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.POST_METHOD, WeChatConfig.CREATE_TICKET_PATH, params, data);  
    57.     WechatQRCode wechatQRCode = null;  
    58.     try {  
    59.         wechatQRCode = gson.fromJson(data, WechatQRCode.class);  
    60.         gson = null;  
    61.     } catch (JsonSyntaxException e) {  
    62.         e.printStackTrace();  
    63.     }  
    64.     return wechatQRCode == null ? null : wechatQRCode.getTicket();  
    65. }  
    66.   
    67. /** 
    68.  * 创建永久二维码(字符串) 
    69.  *  
    70.  * @param accessToken 
    71.  * @param sceneStr 场景str 
    72.  * @return 
    73.  */  
    74. public String createForeverStrTicket(String accessToken, String sceneStr) {  
    75.     TreeMap<String, String> params = new TreeMap<String, String>();  
    76.     params.put("access_token", accessToken);  
    77.     // output data  
    78.     Map<String, String> intMap = new HashMap<String, String>();  
    79.     intMap.put("scene_str", sceneStr);  
    80.     Map<String, Map<String, String>> mapMap = new HashMap<String, Map<String, String>>();  
    81.     mapMap.put("scene", intMap);  
    82.     Map<String, Object> paramsMap = new HashMap<String, Object>();  
    83.     paramsMap.put("action_name", WeChatConfig.QR_LIMIT_STR_SCENE);  
    84.     paramsMap.put("action_info", mapMap);  
    85.     Gson gson = new Gson();  
    86.     String data = gson.toJson(paramsMap);  
    87.     data = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.POST_METHOD, WeChatConfig.CREATE_TICKET_PATH, params, data);  
    88.     WechatQRCode wechatQRCode = null;  
    89.     try {  
    90.         wechatQRCode = gson.fromJson(data, WechatQRCode.class);  
    91.         gson = null;  
    92.     } catch (JsonSyntaxException e) {  
    93.         e.printStackTrace();  
    94.     }  
    95.     return wechatQRCode == null ? null : wechatQRCode.getTicket();  
    96. }  
    强烈建议用测试号生成永久的,正式的会占用使用数量

    三、二维码长链接转成短链接

    微信返回正确的二维码的结果,参数有个url,即二维码图片解析后的地址,也可以根据此URL生成需要的二维码图片,而不需要通过ticket去换取图片了
    1. /** 
    2.  * 长链接转短链接 
    3.  * @param accessToken  
    4.  * @param longUrl 长链接 
    5.  * @return 
    6.  */  
    7. public String shortQRCodeurl(String accessToken, String longUrl){  
    8.     TreeMap<String, String> params = new TreeMap<String, String>();  
    9.     params.put("access_token", accessToken);  
    10.     Map<String, Object> paramsMap = new HashMap<String, Object>();  
    11.     paramsMap.put("action""long2short");  
    12.     paramsMap.put("long_url", longUrl);  
    13.     Gson gson = new Gson();  
    14.     String data = gson.toJson(paramsMap);  
    15.     String result = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.POST_METHOD, WeChatConfig.WECHAT_SHORT_QRCODE_URL, params, data);  
    16.     WechatQRCodeShortUrl wechatQRCodeShortUrl = gson.fromJson(result, WechatQRCodeShortUrl.class);  
    17.     gson = null;  
    18.     return wechatQRCodeShortUrl.getShort_url();  
    19. }  

    四、通过ticket凭证直接获取二维码

    1. /** 
    2.  * 获取二维码ticket后,通过ticket换取二维码图片展示 
    3.  * @param ticket 
    4.  * @return 二维码图片地址 
    5.  * @throws Exception 
    6.  */  
    7. public String showQrcode(String ticket) throws Exception {  
    8.     return HttpReqUtil.setParmas(params(ticket), WeChatConfig.SHOW_QRCODE_PATH, null);  
    9. }  
    10.   
    11. /** 
    12.  * 下载二维码 
    13.  *  
    14.  * @param ticket 
    15.  * @param savePath 保存的路径,例如 F:\\phil\phil.jpg 
    16.  * @return Result.success = true 表示下载图片下载成功 
    17.  */  
    18. public WechatResult showQrcode(String ticket, String savePath) throws Exception {  
    19.     return HttpReqUtil.downMeaterMetod(params(ticket), HttpReqUtil.GET_METHOD, WeChatConfig.SHOW_QRCODE_PATH, savePath);  
    20. }  
    21.   
    22. private TreeMap<String, String> params(String ticket) {  
    23.     TreeMap<String, String> params = new TreeMap<String, String>();  
    24.     params.put("ticket", HttpReqUtil.urlEncode(ticket, SystemConfig.CHARACTER_ENCODING));  
    25.     return params;  
    26. }  

    五、扫描带参数二维码事件推送

    这个推送的XML信息通过之前开发者中心处设置的服务器地址获得,故得先接入

    已关注推送XML示例

    1. <xml><ToUserName><![CDATA[toUser]]></ToUserName>  
    2. <FromUserName><![CDATA[FromUser]]></FromUserName>  
    3. <CreateTime>123456789</CreateTime>  
    4. <MsgType><![CDATA[event]]></MsgType>  
    5. <Event><![CDATA[subscribe]]></Event>  
    6. <EventKey><![CDATA[qrscene_123123]]></EventKey>  
    7. <Ticket><![CDATA[TICKET]]></Ticket>  
    8. </xml>  
    EventKey 事件KEY值,qrscene_为前缀,后面为二维码的参数值

    未关注推送XML示例

    1. <xml>  
    2. <ToUserName><![CDATA[toUser]]></ToUserName>  
    3. <FromUserName><![CDATA[FromUser]]></FromUserName>  
    4. <CreateTime>123456789</CreateTime>  
    5. <MsgType><![CDATA[event]]></MsgType>  
    6. <Event><![CDATA[SCAN]]></Event>  
    7. <EventKey><![CDATA[SCENE_VALUE]]></EventKey>  
    8. <Ticket><![CDATA[TICKET]]></Ticket>  
    9. </xml>  
    EventKey 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_idxml处理方式

    六、附

    2017.9.19 工具类不再提供
    展开全文
  • 目前2种类型的二维码: 1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量,主要用于帐号绑定等不要求二维码永久保存业务场景 2、永久二维码,是无...

    一定说明,这种方法我还没有测试,如果有疑问欢迎在评论区域讨论.

    ....................

    ...................

    谢谢.



    微信官方提供的生成二维码接口得到的是当前公众号的二维码。


    目前有2种类型的二维码:
    1、临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量,主要用于帐号绑定等不要求二维码永久保存的业务场景
    2、永久二维码,是无过期时间的,但数量较少(目前为最多10万个),主要用于适用于帐号绑定、用户来源统计等场景


    参考文档详见https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542&token=&lang=zh_CN


    获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码,但是得到ticket之前首先获取到access_token。

    1.创建access_token的bean

    可以不写,因为我是每小时定时获取一次token存储到数据库或者直接存到application

    [java] view plain copy
     
    1. public class AccessToken {    
    2.     // 获取到的凭证    
    3.     private String token;    
    4.     // 凭证有效时间,单位:秒    
    5.     private int expiresIn;  
    6.       
    7.     public String getToken() {  
    8.         return token;  
    9.     }  
    10.     public void setToken(String token) {  
    11.         this.token = token;  
    12.     }  
    13.     public int getExpiresIn() {  
    14.         return expiresIn;  
    15.     }  
    16.     public void setExpiresIn(int expiresIn) {  
    17.         this.expiresIn = expiresIn;  
    18.     }  
    19.   
    20. }  

    2.创建获取accessToken的方法

    调用接口时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,否则将无法调用成功

    [java] view plain copy
     
    1. /** 
    2.  * 获取access_token 
    3.  * @param appid 凭证 
    4.  * @param appsecret 密钥 
    5.  * @return 
    6.  */  
    7. public static String getAccessToken(String appid, String appsecret) {  
    8.     String result = HttpRequestUtil.getAccessToken(appid,appsecret);  
    9.     JSONObject jsonObject = JSONObject.fromObject(result);  
    10.     if (null != jsonObject) {  
    11.         try {  
    12.             result = jsonObject.getString("access_token");  
    13.         } catch (JSONException e) {  
    14.            logger.info("获取token失败 errcode:"+jsonObject.getInt("errcode") +",errmsg:"+ jsonObject.getString("errmsg"));                
    15.         }  
    16.     }  
    17.     return result;  
    18. }  

    3.获取二维码的Ticket

    [java] view plain copy
     
    1. // 临时二维码  
    2. private final static String QR_SCENE = "QR_SCENE";  
    3. // 永久二维码  
    4. private final static String QR_LIMIT_SCENE = "QR_LIMIT_SCENE";  
    5. // 永久二维码(字符串)  
    6. private final static String QR_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE";   
    7. // 创建二维码  
    8. private String create_ticket_path = "https://api.weixin.qq.com/cgi-bin/qrcode/create";  
    9. // 通过ticket换取二维码  
    10. private String showqrcode_path = "https://mp.weixin.qq.com/cgi-bin/showqrcode";  
    11.   
    12. /** 
    13.  * 创建临时带参数二维码 
    14.  * @param accessToken 
    15.  * @expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。 
    16.  * @param sceneId 场景Id 
    17.  * @return 
    18.  */  
    19. public String createTempTicket(String accessToken, String expireSeconds, int sceneId) {  
    20.     WeiXinQRCode wxQRCode = null;  
    21.       
    22.     TreeMap<String,String> params = new TreeMap<String,String>();  
    23.     params.put("access_token", accessToken);  
    24.     Map<String,Integer> intMap = new HashMap<String,Integer>();  
    25.     intMap.put("scene_id",sceneId);  
    26.     Map<String,Map<String,Integer>> mapMap = new HashMap<String,Map<String,Integer>>();  
    27.     mapMap.put("scene", intMap);  
    28.     //  
    29.     Map<String,Object> paramsMap = new HashMap<String,Object>();  
    30.     paramsMap.put("expire_seconds", expireSeconds);  
    31.     paramsMap.put("action_name", QR_SCENE);  
    32.     paramsMap.put("action_info", mapMap);  
    33.     String data = new Gson().toJson(paramsMap);  
    34.     data = HttpRequestUtil.HttpsDefaultExecute(HttpRequestUtil.POST_METHOD,create_ticket_path,params,data);  
    35.     try {  
    36.         wxQRCode = new Gson().fromJson(data, WeiXinQRCode.class);  
    37.     } catch (JsonSyntaxException e) {  
    38.         wxQRCode = null;  
    39.         e.printStackTrace();  
    40.     }  
    41.     return wxQRCode==null?null:wxQRCode.getTicket();  
    42.   
    43. }  
    44.   
    45. /** 
    46.  * 创建永久二维码(数字) 
    47.  * @param accessToken 
    48.  * @param sceneId 场景Id 
    49.  * @return 
    50.  */  
    51. public String createForeverTicket(String accessToken, int sceneId) {  
    52.       
    53.     TreeMap<String,String> params = new TreeMap<String,String>();  
    54.     params.put("access_token", accessToken);  
    55.     //output data  
    56.     Map<String,Integer> intMap = new HashMap<String,Integer>();  
    57.     intMap.put("scene_id",sceneId);  
    58.     Map<String,Map<String,Integer>> mapMap = new HashMap<String,Map<String,Integer>>();  
    59.     mapMap.put("scene", intMap);  
    60.     //  
    61.     Map<String,Object> paramsMap = new HashMap<String,Object>();  
    62.     paramsMap.put("action_name", QR_LIMIT_SCENE);  
    63.     paramsMap.put("action_info", mapMap);  
    64.     String data = new Gson().toJson(paramsMap);  
    65.     data =  HttpRequestUtil.HttpsDefaultExecute(HttpRequestUtil.POST_METHOD,create_ticket_path,params,data);  
    66.     WeiXinQRCode wxQRCode = null;  
    67.     try {  
    68.         wxQRCode = new Gson().fromJson(data, WeiXinQRCode.class);  
    69.     } catch (JsonSyntaxException e) {  
    70.         wxQRCode = null;  
    71.         e.printStackTrace();  
    72.     }  
    73.     return wxQRCode==null?null:wxQRCode.getTicket();  
    74. }  
    75.   
    76. /** 
    77.  * 创建永久二维码(字符串) 
    78.  *  
    79.  * @param accessToken 
    80.  * @param sceneStr 场景str 
    81.  * @return 
    82.  */  
    83. public String createForeverStrTicket(String accessToken, String sceneStr){        
    84.     TreeMap<String,String> params = new TreeMap<String,String>();  
    85.     params.put("access_token", accessToken);  
    86.     //output data  
    87.     Map<String,String> intMap = new HashMap<String,String>();  
    88.     intMap.put("scene_str",sceneStr);  
    89.     Map<String,Map<String,String>> mapMap = new HashMap<String,Map<String,String>>();  
    90.     mapMap.put("scene", intMap);  
    91.       
    92.     Map<String,Object> paramsMap = new HashMap<String,Object>();  
    93.     paramsMap.put("action_name", QR_LIMIT_STR_SCENE);  
    94.     paramsMap.put("action_info", mapMap);  
    95.     String data = new Gson().toJson(paramsMap);  
    96.     data =  HttpRequestUtil.HttpsDefaultExecute(HttpRequestUtil.POST_METHOD,create_ticket_path,params,data);  
    97.     WeiXinQRCode wxQRCode = null;  
    98.     try {  
    99.         wxQRCode = new Gson().fromJson(data, WeiXinQRCode.class);  
    100.     } catch (JsonSyntaxException e) {  
    101.         wxQRCode = null;  
    102.     }  
    103.     return wxQRCode==null?null:wxQRCode.getTicket();  
    104. }  

    强烈建议用测试号生成永久的

    4.通过ticket凭证直接获取二维码

    [java] view plain copy
     
    1. /** 
    2.  * 获取二维码ticket后,通过ticket换取二维码图片展示 
    3.  * @param ticket 
    4.  * @return 
    5.  */  
    6. public String showQrcode(String ticket){  
    7.     Map<String,String> params = new TreeMap<String,String>();  
    8.     params.put("ticket", HttpRequestUtil.urlEncode(ticket, HttpRequestUtil.DEFAULT_CHARSET));  
    9.     try {  
    10.         showqrcode_path = HttpRequestUtil.setParmas(params,showqrcode_path,"");  
    11.     } catch (Exception e) {  
    12.         e.printStackTrace();  
    13.     }  
    14.     return showqrcode_path;  
    15. }  
    16.   
    17. /** 
    18.  * 获取二维码ticket后,通过ticket换取二维码图片 
    19.  * @param ticket 
    20.  * @param savePath  保存的路径,例如 F:\\test\test.jpg 
    21.  * @return      Result.success = true 表示下载图片下载成功 
    22.  */  
    23. public WeiXinResult showQrcode(String ticket,String savePath) throws Exception{  
    24.     TreeMap<String,String> params = new TreeMap<String,String>();  
    25.     params.put("ticket", HttpRequestUtil.urlEncode(ticket, HttpRequestUtil.DEFAULT_CHARSET));  
    26.     WeiXinResult result = HttpRequestUtil.downMeaterMetod(params,HttpRequestUtil.GET_METHOD,showqrcode_path,savePath);  
    27.     return result;  
    28. }  

    5.用户扫描带参数的二维码的处理

    如果没有关注的话,用户可以关注公众号,并且会这个场景值就是所谓的参数推送给开发者,参数是EventKey,直接用request获取即可,注意qrscene_的之后才是二维码的参数值

    如果已经关注,微信会直接把场景值的扫描事件直接推送给开发者


    6.参考类

    WeiXinResult.Java

    [java] view plain copy
     
    1. /** 
    2.  * 返回的结果对象 
    3.  * @author fjing 
    4.  *  
    5.  */  
    6. public class WeiXinResult {  
    7.       
    8.     public static final int NEWSMSG = 1;            //图文消息  
    9.     private boolean isSuccess;  
    10.     private Object obj;  
    11.     private int type;  
    12.     private String msg;  
    13.   
    14.     public String getMsg() {  
    15.         return msg;  
    16.     }  
    17.   
    18.     public void setMsg(String msg) {  
    19.         this.msg = msg;  
    20.     }  
    21.   
    22.     public int getType() {  
    23.         return type;  
    24.     }  
    25.   
    26.     public void setType(int type) {  
    27.         this.type = type;  
    28.     }  
    29.   
    30.     public boolean isSuccess() {  
    31.         return isSuccess;  
    32.     }  
    33.   
    34.     public void setSuccess(boolean isSuccess) {  
    35.         this.isSuccess = isSuccess;  
    36.     }  
    37.   
    38.     public Object getObj() {  
    39.         return obj;  
    40.     }  
    41.   
    42.     public void setObj(Object obj) {  
    43.         this.obj = obj;  
    44.     }  
    45. }  

    HttpRequestUtil.java

    [java] view plain copy
     
    1. import java.io.File;  
    2. import java.io.FileNotFoundException;  
    3. import java.io.FileOutputStream;  
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6. import java.io.OutputStream;  
    7. import java.io.UnsupportedEncodingException;  
    8. import java.net.HttpURLConnection;  
    9. import java.net.MalformedURLException;  
    10. import java.net.URL;  
    11. import java.net.URLEncoder;  
    12. import java.util.Map;  
    13. import java.util.Map.Entry;  
    14. import java.util.Set;  
    15. import java.util.TreeMap;  
    16.   
    17. import javax.net.ssl.HostnameVerifier;  
    18. import javax.net.ssl.HttpsURLConnection;  
    19. import javax.net.ssl.KeyManager;  
    20. import javax.net.ssl.SSLContext;  
    21. import javax.net.ssl.SSLSession;  
    22. import javax.net.ssl.TrustManager;  
    23.   
    24. import com.dingshu.model.result.WeiXinResult;  
    25.   
    26. public class HttpRequestUtil {  
    27.   
    28.     //private static Logger logger = Logger.getLogger(HttpRequestUtil.class);  
    29.   
    30.     public static final String GET_METHOD = "GET";  
    31.   
    32.     public static final String POST_METHOD = "POST";  
    33.   
    34.     public static final String DEFAULT_CHARSET = "utf-8";  
    35.   
    36.     private static int DEFAULT_CONNTIME = 5000;  
    37.       
    38.     private static int DEFAULT_READTIME = 5000;  
    39.     // 获取access_token的路径  
    40.     private static String token_path = "https://api.weixin.qq.com/cgi-bin/token";  
    41.   
    42.     /** 
    43.      * http请求 
    44.      *  
    45.      * @param method 
    46.      *            请求方法GET/POST 
    47.      * @param path 
    48.      *            请求路径 
    49.      * @param timeout 
    50.      *            连接超时时间 默认为5000 
    51.      * @param readTimeout 
    52.      *            读取超时时间 默认为5000 
    53.      * @param data  数据 
    54.      * @return 
    55.      */  
    56.     public static String defaultConnection(String method, String path, int timeout, int readTimeout, String data)  
    57.             throws Exception {  
    58.         String result = "";  
    59.         URL url = new URL(path);  
    60.         if (url != null) {  
    61.             HttpURLConnection conn = getConnection(method, url);  
    62.             conn.setConnectTimeout(timeout == 0 ? DEFAULT_CONNTIME : timeout);  
    63.             conn.setReadTimeout(readTimeout == 0 ? DEFAULT_READTIME : readTimeout);  
    64.             if (data != null && !"".equals(data)) {  
    65.                 OutputStream output = conn.getOutputStream();  
    66.                 output.write(data.getBytes(DEFAULT_CHARSET));  
    67.                 output.flush();  
    68.                 output.close();  
    69.             }  
    70.             if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {  
    71.                 InputStream input = conn.getInputStream();  
    72.                 result = inputToStr(input);  
    73.                 input.close();  
    74.                 conn.disconnect();  
    75.             }  
    76.         }  
    77.         return result;  
    78.     }  
    79.   
    80.     /** 
    81.      * 根据url的协议选择对应的请求方式 例如 http://www.baidu.com 则使用http请求,https://www.baidu.com 
    82.      * 则使用https请求 
    83.      *  
    84.      * @param method 
    85.      *            请求的方法 
    86.      * @return 
    87.      * @throws IOException 
    88.      */  
    89.     private static HttpURLConnection getConnection(String method, URL url) throws IOException {  
    90.         HttpURLConnection conn = null;  
    91.         if ("https".equals(url.getProtocol())) {  
    92.             SSLContext context = null;  
    93.             try {  
    94.                 context = SSLContext.getInstance("SSL""SunJSSE");  
    95.                 context.init(new KeyManager[0], new TrustManager[] { new MyX509TrustManager() },  
    96.                         new java.security.SecureRandom());  
    97.             } catch (Exception e) {  
    98.                 throw new IOException(e);  
    99.             }  
    100.             HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection();  
    101.             connHttps.setSSLSocketFactory(context.getSocketFactory());  
    102.             connHttps.setHostnameVerifier(new HostnameVerifier() {  
    103.   
    104.                 @Override  
    105.                 public boolean verify(String arg0, SSLSession arg1) {  
    106.                     return true;  
    107.                 }  
    108.             });  
    109.             conn = connHttps;  
    110.         } else {  
    111.             conn = (HttpURLConnection) url.openConnection();  
    112.         }  
    113.         conn.setRequestMethod(method);  
    114.         conn.setUseCaches(false);  
    115.         conn.setDoInput(true);  
    116.         conn.setDoOutput(true);  
    117.         return conn;  
    118.     }  
    119.   
    120.     /** 
    121.      * 将输入流转换为字符串 
    122.      *  
    123.      * @param input 
    124.      *            输入流 
    125.      * @return 转换后的字符串 
    126.      */  
    127.     public static String inputToStr(InputStream input) {  
    128.         String result = "";  
    129.         if (input != null) {  
    130.             byte[] array = new byte[1024];  
    131.             StringBuffer buffer = new StringBuffer();  
    132.             try {  
    133.                 for (int index; (index = (input.read(array))) > -1;) {  
    134.                     buffer.append(new String(array, 0, index, DEFAULT_CHARSET));  
    135.                 }  
    136.                 result = buffer.toString();  
    137.             } catch (IOException e) {  
    138.                 e.printStackTrace();  
    139.                 result = "";  
    140.             }  
    141.         }  
    142.         return result;  
    143.     }  
    144.   
    145.     /** 
    146.      * 设置参数 
    147.      *  
    148.      * @param map 
    149.      *            参数map 
    150.      * @param path 
    151.      *            需要赋值的path 
    152.      * @param charset 
    153.      *            编码格式 默认编码为utf-8(取消默认) 
    154.      * @return 已经赋值好的url 只需要访问即可 
    155.      */  
    156.     public static String setParmas(Map<String, String> map, String path, String charset) throws Exception {  
    157.         String result = "";  
    158.         boolean hasParams = false;  
    159.         if (path != null && !"".equals(path)) {  
    160.             if (map != null && map.size() > 0) {  
    161.                 StringBuilder builder = new StringBuilder();  
    162.                 Set<Entry<String, String>> params = map.entrySet();  
    163.                 for (Entry<String, String> entry : params) {  
    164.                     String key = entry.getKey().trim();  
    165.                     String value = entry.getValue().trim();  
    166.                     if (hasParams) {  
    167.                         builder.append("&");  
    168.                     } else {  
    169.                         hasParams = true;  
    170.                     }  
    171.                     if(charset != null && !"".equals(charset)){  
    172.                         //builder.append(key).append("=").append(URLDecoder.(value, charset));    
    173.                         builder.append(key).append("=").append(urlEncode(value, charset));  
    174.                     }else{  
    175.                         builder.append(key).append("=").append(value);  
    176.                     }  
    177.                 }  
    178.                 result = builder.toString();  
    179.             }  
    180.         }  
    181.         return doUrlPath(path, result).toString();  
    182.     }  
    183.   
    184.     /** 
    185.      * 设置连接参数 
    186.      *  
    187.      * @param path 
    188.      *            路径 
    189.      * @return 
    190.      */  
    191.     private static URL doUrlPath(String path, String query) throws Exception {  
    192.         URL url = new URL(path);  
    193.         if (org.apache.commons.lang.StringUtils.isEmpty(path)) {  
    194.             return url;  
    195.         }  
    196.         if (org.apache.commons.lang.StringUtils.isEmpty(url.getQuery())) {  
    197.             if (path.endsWith("?")) {  
    198.                 path += query;  
    199.             } else {  
    200.                 path = path + "?" + query;  
    201.             }  
    202.         } else {  
    203.             if (path.endsWith("&")) {  
    204.                 path += query;  
    205.             } else {  
    206.                 path = path + "&" + query;  
    207.             }  
    208.         }  
    209.         return new URL(path);  
    210.     }  
    211.   
    212.     /** 
    213.      * 默认的http请求执行方法,返回 
    214.      *  
    215.      * @param method 
    216.      *            请求的方法 POST/GET 
    217.      * @param path 
    218.      *            请求path 路径 
    219.      * @param map 
    220.      *            请求参数集合 
    221.      * @param data 
    222.      *            输入的数据 允许为空 
    223.      * @return 
    224.      */  
    225.     public static String HttpDefaultExecute(String method, String path, Map<String, String> map, String data) {  
    226.         String result = "";  
    227.         try {  
    228.             String url = setParmas((TreeMap<String, String>) map, path, "");  
    229.             result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data);  
    230.         } catch (Exception e) {  
    231.             e.printStackTrace();  
    232.         }  
    233.         return result;  
    234.     }  
    235.   
    236.     /** 
    237.      * 默认的https执行方法,返回 
    238.      *  
    239.      * @param method 
    240.      *            请求的方法 POST/GET 
    241.      * @param path 
    242.      *            请求path 路径 
    243.      * @param map 
    244.      *            请求参数集合 
    245.      * @param data 
    246.      *            输入的数据 允许为空 
    247.      * @return 
    248.      */  
    249.     public static String HttpsDefaultExecute(String method, String path, Map<String, String> map, String data) {  
    250.         String result = "";  
    251.         try {  
    252.             String url = setParmas((TreeMap<String, String>) map, path, "");  
    253.             result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data);  
    254.         } catch (Exception e) {  
    255.             e.printStackTrace();  
    256.         }  
    257.         return result;  
    258.     }  
    259.   
    260.     /** 
    261.      * 获取授权token 
    262.      *  
    263.      * @param key 应用key 
    264.      * @param secret 应用密匙 
    265.      * @return json格式的字符串 
    266.      */  
    267.     public static String getAccessToken(String key, String secret) {  
    268.         TreeMap<String, String> map = new TreeMap<String, String>();  
    269.         map.put("grant_type""client_credential");  
    270.         map.put("appid", key);  
    271.         map.put("secret", secret);  
    272.         String result = HttpDefaultExecute(GET_METHOD, token_path, map, "");  
    273.         return result;  
    274.     }  
    275.   
    276.     /** 
    277.      * 默认的下载素材方法 
    278.      *  
    279.      * @param method  http方法 POST/GET 
    280.      * @param apiPath api路径 
    281.      * @param savePath 素材需要保存的路径 
    282.      * @return 是否下载成功 Reuslt.success==true 表示下载成功 
    283.      */  
    284.     public static WeiXinResult downMeaterMetod(TreeMap<String, String> params, String method, String apiPath, String savePath) {  
    285.         WeiXinResult result = new WeiXinResult();  
    286.         try {  
    287.             apiPath = setParmas(params, apiPath, "");  
    288.             URL url = new URL(apiPath);  
    289.             HttpURLConnection conn = getConnection(method, url);  
    290.             if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {  
    291.                 String contentType = conn.getContentType();  
    292.                 result = ContentType(contentType, conn, savePath);  
    293.             } else {  
    294.                 result.setObj(conn.getResponseCode() + " " + conn.getResponseMessage());  
    295.             }  
    296.         } catch (MalformedURLException e) {  
    297.             e.printStackTrace();  
    298.         } catch (IOException e) {  
    299.             e.printStackTrace();  
    300.         } catch (Exception e) {  
    301.             e.printStackTrace();  
    302.         }  
    303.         return result;  
    304.     }  
    305.   
    306.     /** 
    307.      * 根据返回的头信息返回具体信息 
    308.      *  
    309.      * @param contentType 
    310.      *            ContentType请求头信息 
    311.      * @return Result.type==1 表示文本消息, 
    312.      */  
    313.     private static WeiXinResult ContentType(String contentType, HttpURLConnection conn, String savePath) {  
    314.         WeiXinResult result = new WeiXinResult();  
    315.         try {  
    316.             if (conn != null) {  
    317.                 InputStream input = conn.getInputStream();  
    318.                 if (contentType.equals("image/gif")) { // gif图片  
    319.                     result = InputStreamToMedia(input, savePath, "gif");  
    320.                 } else if (contentType.equals("image/jpeg")) { // jpg图片  
    321.                     result = InputStreamToMedia(input, savePath, "jpg");  
    322.                 } else if (contentType.equals("image/jpg")) { // jpg图片  
    323.                     result = InputStreamToMedia(input, savePath, "jpg");  
    324.                 } else if (contentType.equals("image/png")) { // png图片  
    325.                     result = InputStreamToMedia(input, savePath, "png");  
    326.                 } else if (contentType.equals("image/bmp")) { // bmp图片  
    327.                     result = InputStreamToMedia(input, savePath, "bmp");  
    328.                 } else if (contentType.equals("audio/x-wav")) { // wav语音  
    329.                     result = InputStreamToMedia(input, savePath, "wav");  
    330.                 } else if (contentType.equals("audio/x-ms-wma")) { // wma语言  
    331.                     result = InputStreamToMedia(input, savePath, "wma");  
    332.                 } else if (contentType.equals("audio/mpeg")) { // mp3语言  
    333.                     result = InputStreamToMedia(input, savePath, "mp3");  
    334.                 } else if (contentType.equals("text/plain")) { // 文本信息  
    335.                     String str = inputToStr(input);  
    336.                     result.setObj(str);  
    337.                 } else if (contentType.equals("application/json")) { // 返回json格式的数据  
    338.                     String str = inputToStr(input);  
    339.                     result.setObj(str);  
    340.                 } else { // 此处有问题  
    341.                     String str = inputToStr(input);  
    342.                     result.setObj(str);  
    343.                 }  
    344.             } else {  
    345.                 result.setObj("conn is null!");  
    346.             }  
    347.         } catch (Exception ex) {  
    348.             ex.printStackTrace();  
    349.         }  
    350.         return result;  
    351.     }  
    352.   
    353.     /** 
    354.      * 将字符流转换为图片文件 
    355.      *  
    356.      * @param input 字符流 
    357.      * @param savePath 图片需要保存的路径 
    358.      * @param 类型 jpg/png等 
    359.      * @return 
    360.      */  
    361.     private static WeiXinResult InputStreamToMedia(InputStream input, String savePath, String type) {  
    362.         WeiXinResult result = new WeiXinResult();  
    363.         try {  
    364.             File file = null;  
    365.             file = new File(savePath);  
    366.             String paramPath = file.getParent(); // 路径  
    367.             String fileName = file.getName(); //  
    368.             String newName = fileName.substring(0, fileName.lastIndexOf(".")) + "." + type;// 根据实际返回的文件类型后缀  
    369.             savePath = paramPath + "\\" + newName;  
    370.             if (!file.exists()) {  
    371.                 File dirFile = new File(paramPath);  
    372.                 dirFile.mkdirs();  
    373.             }  
    374.             file = new File(savePath);  
    375.             FileOutputStream output = new FileOutputStream(file);  
    376.             int len = 0;  
    377.             byte[] array = new byte[1024];  
    378.             while ((len = input.read(array)) != -1) {  
    379.                 output.write(array, 0, len);  
    380.             }  
    381.             output.flush();  
    382.             output.close();  
    383.             result.setSuccess(true);  
    384.             result.setObj("save success!");  
    385.         } catch (FileNotFoundException e) {  
    386.             e.printStackTrace();  
    387.             result.setSuccess(false);  
    388.             result.setObj(e.getMessage());  
    389.         } catch (IOException e) {  
    390.             e.printStackTrace();  
    391.             result.setSuccess(false);  
    392.             result.setObj(e.getMessage());  
    393.         }  
    394.         return result;  
    395.     }  
    396.   
    397.     public static String urlEncode(String source, String encode) {  
    398.         String result = source;  
    399.         try {  
    400.             result = URLEncoder.encode(source, encode);  
    401.         } catch (UnsupportedEncodingException e) {  
    402.             e.printStackTrace();  
    403.         }  
    404.         return result;  
    405.     }  
    406. }  
    信任管理器MyX509TrustManager,实现方法自己定义(反正我没写)

    [java] view plain copy
     
    1. /** 
    2.  * 信任管理器 
    3.  * @author fjing 
    4.  * 
    5.  */  
    6. public class MyX509TrustManager implements X509TrustManager {  
    7.   
    8.     @Override  
    9.     public void checkClientTrusted(X509Certificate[] arg0, String arg1)  
    10.             throws CertificateException {  
    11.   
    12.     }  
    13.   
    14.     @Override  
    15.     public void checkServerTrusted(X509Certificate[] arg0, String arg1)  
    16.             throws CertificateException {  
    17.   
    18.     }  
    19.   
    20.     @Override  
    21.     public X509Certificate[] getAcceptedIssuers() {  
    22.         return null;  
    23.     }  
    24.   
    25. }  

    展开全文
  • 生成带参数的二维码

    千次阅读 2019-01-04 18:26:44
    为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: 1...

    为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。

    目前有2种类型的二维码:

    1、临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景
    2、永久二维码,是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。

    用户扫描带场景值二维码时,可能推送以下两种事件:

    如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。

    如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。

    获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。

    创建二维码ticket

    每次创建二维码ticket需要提供一个开发者自行设定的参数(scene_id),分别介绍临时二维码和永久二维码的创建二维码ticket过程。

    临时二维码请求说明

    http请求方式: POST
    URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKENPOST数据格式:json
    POST数据例子:{"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}

    永久二维码请求说明

    http请求方式: POST
    URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKENPOST数据格式:json
    POST数据例子:{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}
    或者也可以使用以下POST数据创建字符串形式的二维码参数:
    {"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "123"}}}

    参数说明

    参数 说明
    expire_seconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。
    action_name 二维码类型,QR_SCENE为临时,QR_LIMIT_SCENE为永久,QR_LIMIT_STR_SCENE为永久的字符串参数值
    action_info 二维码详细信息
    scene_id 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)
    scene_str 场景值ID(字符串形式的ID),字符串类型,长度限制为1到64,仅永久二维码支持此字段   

     

    返回说明

    正确的Json返回结果:

    {"ticket":"gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm

    3sUw==","expire_seconds":60,"url":"http:\/\/weixin.qq.com\/q\/kZgfwMTm72WWPkovabbI"}

     

    参数 说明
    ticket 获取的二维码ticket,凭借此ticket可以在有效时间内换取二维码。
    expire_seconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天)。
    url 二维码图片解析后的地址,开发者可根据该地址自行生成需要的二维码图片

    通过ticket换取二维码

    获取二维码ticket后,开发者可用ticket换取二维码图片。请注意,本接口无须登录态即可调用。

    请求说明

    HTTP GET请求(请使用https协议)https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET提醒:TICKET记得进行UrlEncode

    返回说明

    ticket正确情况下,http 返回码是200,是一张图片,可以直接展示或者下载。

    HTTP头(示例)如下:
    Accept-Ranges:bytes
    Cache-control:max-age=604800
    Connection:keep-alive
    Content-Length:28026
    Content-Type:image/jpg
    Date:Wed, 16 Oct 2013 06:37:10 GMT
    Expires:Wed, 23 Oct 2013 14:37:10 +0800
    Server:nginx/1.4.1

    错误情况下(如ticket非法)返回HTTP错误码404。

     

     

     

    扫描带参数二维码事件

    用户扫描带场景值二维码时,可能推送以下两种事件:

    如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。

    如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。

    1. 用户未关注时,进行关注后的事件推送

    复制代码

    <xml>
    <ToUserName><![CDATA[gh_45072270791c]]></ToUserName>
    <FromUserName><![CDATA[o7Lp5t6n59DeX3U0C7Kric9qEx-Q]]></FromUserName>
    <CreateTime>1389684286</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[subscribe]]></Event>
    <EventKey><![CDATA[qrscene_1000]]></EventKey>
    <Ticket><![CDATA[gQHi8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0UweTNxNi1sdlA3RklyRnNKbUFvAAIELdnUUgMEAAAAAA==]]></Ticket>
    </xml>

    复制代码

    参数说明

    2. 用户已关注时的事件推送

    复制代码

    <xml>
    <ToUserName><![CDATA[gh_45072270791c]]></ToUserName>
    <FromUserName><![CDATA[o7Lp5t6n59DeX3U0C7Kric9qEx-Q]]></FromUserName>
    <CreateTime>1389684184</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[SCAN]]></Event>
    <EventKey><![CDATA[1000]]></EventKey>
    <Ticket><![CDATA[gQHi8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0UweTNxNi1sdlA3RklyRnNKbUFvAAIELdnUUgMEAAAAAA==]]></Ticket>
    </xml>

    复制代码

    参数说明

    事件代码:

    以下代码判定了扫描带参数二维码的两种情形

    复制代码

    private function receiveEvent($object)
    {
        $contentStr = "";
        switch ($object->Event)
        {
            case "subscribe":
                $contentStr = "欢迎关注方倍工作室 ";
                if (isset($object->EventKey)){
                    $contentStr = "关注二维码场景 ".$object->EventKey;
                }
                break;
            case "SCAN":
                $contentStr = "扫描 ".$object->EventKey;
                 //要实现统计分析,则需要扫描事件写入数据库,这里可以记录 EventKey及用户OpenID,扫描时间
                break;
            default:
                break;      
     
        }
        $resultStr = $this->transmitText($object, $contentStr);
        return $resultStr;
    }

    复制代码

     

    展开全文
  • 目前2种类型的二维码:1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存业务场景2、永久...

    目前有2种类型的二维码:

    1、临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景
    2、永久二维码,是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。

    用户扫描带场景值二维码时,可能推送以下两种事件:

    如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。

    如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。

    获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。



    生成临时二维码

    package com.b505.QRcode;
    
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.net.URL;
    
    import javax.net.ssl.HttpsURLConnection;
    
    import com.b505.entity.WechatQRCode;
    import com.b505.util.Tool;
    import com.b505.util.WeixinConstants;
    import com.b505.util.WeixinUtil;
    
    import net.sf.json.JSONObject;
    
    /***
     * 
     * 创建临时二维码
     * 
     * @author 
     *
     */
    public class TemporaryQRcode
    {
    	/**
    	 * 
    	 * @param accessToken    接口访问凭证 
    	 * @param expireSeconds    二维码有效时间   单位为秒   最长 1800秒 (30天)
    	 * @param sceneId     场景id   临时二维码场景值Id为32位非0整数      永久二维码的场景值ID取1~10000 
    	 *                              也就是说永久二维码一共可以创建10000个    临时的多
    	 * @return
    	 */
    	public static WechatQRCode createForeverTicket(String accessToken, int expireSeconds, int sceneId)
    	{
    		WechatQRCode wechatQRCode = null;
    
    		// 拼接请求地址
    		String requestUrl = " https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
    		requestUrl = requestUrl.replace("TOKEN", accessToken);
    
    		// 需要提交json数据
    		String jsonmsg = "{\"expire_seconds\":%d,\"action_name\": \"QR_SCENE\",\"action_info\":{\"scene\":{\"scene_id\":%d}}}";
    
    		// 创建永久带参二维码
    		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "POST", String.format(jsonmsg,expireSeconds, sceneId));
    		if (null != jsonObject)
    		{
    			System.out.println(jsonObject);
    
    			try
    			{
    				wechatQRCode=new WechatQRCode();
    				System.out.println(1);
    				wechatQRCode.setTicket(jsonObject.getString("ticket"));
    				wechatQRCode.setExpire_seconds(jsonObject.getInt("expire_seconds"));
    				System.out.println(2);
    				System.out.println("永久带参二维码ticket成功=" + wechatQRCode.getTicket()+"Expire_seconds="+wechatQRCode.getExpire_seconds());
    			} catch (Exception e)
    			{
    				wechatQRCode =null;
    				int err = jsonObject.getInt("errcode");
    				String errormsg = jsonObject.getString("errmsg");
    				System.out.println("永久带参二维码ticket失败失败errcode=" + err + "errmsg=" + errormsg);
    				}
    		}
    		return wechatQRCode;
    	}
    	public static void main(String[] args)
    	{       //获得token不再说明
    		String assesstoken = WeixinUtil.getAccessToken(WeixinConstants.APPID, WeixinConstants.APPSECRET).getToken();
    		WechatQRCode wechatQRCode =createForeverTicket(assesstoken, 900, 111111);
    		//临时二维码的  ticket
    		System.out.println(wechatQRCode.getTicket());
    		//临时二维码有效时间
    		System.out.println(wechatQRCode.getExpire_seconds());
    		
    		String path = "d:/QRcode";
    		getRQcode(wechatQRCode.getTicket(), path);
    	}
    	
    	public static String getRQcode(String ticket, String savepath)
    	{
    		String filepath = null;
    		String requestUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
    		requestUrl = requestUrl.replace("TICKET", Tool.urlencodeutf8(ticket));
    
    		try
    		{
    			URL url = new URL(requestUrl);
    			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    			conn.setDoInput(true);
    			conn.setRequestMethod("GET");
    
    			if (!savepath.endsWith("/"))
    			{
    				savepath += "/";
    			}
    			// 将ticket 作为文件名
    			filepath = savepath + ticket + ".jpg";
    
    			// 将微信服务器返回的输入流写入文件
    
    			BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
    			FileOutputStream fos = new FileOutputStream(new File(filepath));
    
    			byte[] buf = new byte[8096];
    			int size = 0;
    			while ((size = bis.read(buf)) != -1)
    				fos.write(buf, 0, size);
    			fos.close();
    			bis.close();
    
    			System.out.println(conn);
    			conn.disconnect();
    			System.out.println("根据ticket换取二维码成功");
    		} catch (Exception e)
    		{
    			filepath = null;
    			System.out.println("根据ticket换取二维码失败" + e);
    		}
    
    		return filepath;
    
    	}
    }
    
    附加httpRequest()方法
    package com.b505.util;
    import java.awt.Menu;
    import java.io.BufferedReader;  
    import java.io.InputStream;  
    import java.io.InputStreamReader;  
    import java.io.OutputStream;  
    import java.net.ConnectException;  
    import java.net.URL;  
      
    import javax.net.ssl.HttpsURLConnection;  
    import javax.net.ssl.SSLContext;  
    import javax.net.ssl.SSLSocketFactory;  
    import javax.net.ssl.TrustManager;
    import net.sf.json.JSONException;
    import net.sf.json.JSONObject;  
    import org.slf4j.Logger;  
    import org.slf4j.LoggerFactory;
    import com.b505.pojo.*;
    /**
     * 
     * 公众平台通用接口工具类
     * @author 
     *
     */
    public class WeixinUtil
    {
    	    private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);  
    	    /** 
    	     * 发起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 JEEWeiXinX509TrustManager() };  
    	            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;  
    	    } }

    createForeverTicket()方法返回值是WechatQRCode对象,他封装了ticket和expire_seconds参数。WechatQRCode类代码如下:

    package com.b505.entity;
    
    
    public class WechatQRCode
    {
    	 // 获取的二维码  
        private String ticket;  
        // 二维码的有效时间,单位为秒,最大不超过2592000(即30天)  
        private int expire_seconds;  
        set get ...省}

    返回结果   创建成功


    永久带参数二维码创建

    跟上面大致一样,少的就是没有时间限制,

    直接写出代码

    package com.b505.QRcode;
    
    
    
    import net.sf.json.JSONObject;
    
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    
    import com.b505.util.Tool;
    import com.b505.util.WeixinConstants;
    import com.b505.util.WeixinUtil;
    import java.net.URL;
    import javax.net.ssl.HttpsURLConnection;
    
    
    /**
     * 二维码生成和读的工具类
     * 
     */
    public class QRcode
    {
    	/**
    	 * 永久二维码
    	 * @param accessToken  
    	 * @param sceneId场景iD    1~10000
    	 * @return
    	 */
    	public static String createForeverTicket(String accessToken, int sceneId)
    	{
    
    		String ticke = null;
    
    		// 拼接请求地址
    		String requestUrl = " https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
    		requestUrl = requestUrl.replace("TOKEN", accessToken);
    		
    		// 需要提交json数据
    		String jsonmsg = "{\"action_name\": \"QR_LIMIT_SCENE\",\"action_info\":{\"scene\":{\"scene_id\":%d}}}";
    
    		// 创建永久带参二维码
    		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "POST", String.format(jsonmsg, sceneId));
    		if (null != jsonObject)
    		{
    			System.out.println(jsonObject);
    
    			try
    			{
    				ticke = jsonObject.getString("ticket");
    				System.out.println("永久带参二维码ticket成功=" + ticke);
    			} catch (Exception e)
    			{
    				int err = jsonObject.getInt("errcode");
    				String errormsg = jsonObject.getString("errmsg");
    				System.out.println("永久带参二维码ticket失败失败errcode=" + err + "errmsg=" + errormsg);
    			}
    		}
    		return ticke;
    	}
    
    	public static void main(String[] args)
    	{
    		String assesstoken = WeixinUtil.getAccessToken(WeixinConstants.APPID, WeixinConstants.APPSECRET).getToken();
    
    		String ticket = createForeverTicket(assesstoken, 617);
    		String path = "d:/QRcode";
    		getRQcode(ticket, path);
    
    	}
    
    	public static String getRQcode(String ticket, String savepath)
    	{
    		String filepath = null;
    		String requestUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
    		requestUrl = requestUrl.replace("TICKET", Tool.urlencodeutf8(ticket));
    
    		try
    		{
    			URL url = new URL(requestUrl);
    			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    			conn.setDoInput(true);
    			conn.setRequestMethod("GET");
    
    			if (!savepath.endsWith("/"))
    			{
    				savepath += "/";
    			}
    			// 将ticket 作为文件名
    			filepath = savepath + ticket + ".jpg";
    
    			// 将微信服务器返回的输入流写入文件
    
    			BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
    			FileOutputStream fos = new FileOutputStream(new File(filepath));
    
    			byte[] buf = new byte[8096];
    			int size = 0;
    			while ((size = bis.read(buf)) != -1)
    				fos.write(buf, 0, size);
    			fos.close();
    			bis.close();
    
    			System.out.println(conn);
    			conn.disconnect();
    			System.out.println("根据ticket换取二维码成功");
    		} catch (Exception e)
    		{
    			filepath = null;
    			System.out.println("根据ticket换取二维码失败" + e);
    		}
    
    		return filepath;
    
    	}
    
    }

    运行结果   可见成功


    扫描带参数二维码事件

    官方文档说过

    如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。

    如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。

    有人可能会问该怎么样才能执行这个时间呢?

    用户扫描带场景值二维码时,可能推送以下两种事件:

    1. 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
    2. 如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。  


    实现代码如下      本人使用的是永久带参数二维码测试的,我设置的场景值ID为617 

     用户未关注时,进行关注后的事件推送    扫二维码,并关注,这个是事件类型是 subscribe ,之后传来的事件key值为"qrscene_617" ,就是 在ID前面加上了前缀   

    用户已关注时的事件推送     他发生的事件类型是SCAN  ,之后直接传来事件key值为 "617"  


    下面代码看不懂的话那就去柳峰的博客学习学习。

                 // 事件推送  
                else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {  
                    // 事件类型  
                    String eventType = requestMap.get("Event");  
                    // 订阅   当用户未关注该公众号 则先关注
                    if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {                     
                    	//
                    	String eventKey = requestMap.get("EventKey");  
                    	System.out.println(eventKey);
                         //判断场景ID是否为qrscene_617   
                    	if(eventKey.equals("qrscene_617"))
                        {
                            	respContent ="借书请扫书上二维码!!";
                        	textMessage.setContent(respContent);  
                            respMessage = MessageUtil.textMessageToXml(textMessage);  
                            return respMessage;
                        }
    
                    }  
                    
                    else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
                    	String eventKey = requestMap.get("EventKey");  
                    	System.out.println("AAAAAAAAAA="+eventKey);
                    	if(Integer.parseInt(eventKey)==617)
                        {
                        	respContent ="借书请扫书上二维码!!";
                        }
                    	textMessage.setContent(respContent);  
                        respMessage = MessageUtil.textMessageToXml(textMessage);  
                    	}
    				}

    刚接触微信开发,欢迎各位前来交流。

    本文章是从《微信公众平台应用开发》柳峰老师总结学习学的,老师的博客,书籍对我帮助很大,在此向老师表达谢意,谢谢老师!!!!

    展开全文
  • 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: 1...
  • 微信公众号生成带参数的二维码

    千次阅读 2017-07-16 14:15:57
    微信公众号生成带参数的二维码有两种类型:临时二维码和永久二维码。 1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号...
  • 目前2种类型的二维码:1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存业务场景2、永久...
  • 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: 1...
  • 带参数二维码

    2018-05-08 18:32:57
    公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: 1、临时二维码,是过期时间的,最长可以设置为在二维码...
  • 2种类型的二维码:1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存业务场景2、永久二维码,...
  • 目前2种类型的二维码: 1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存业务场景 2、永久...
  • 二维码又称QR Code,QR全称Quick ...生成二维码的方式很多,比较常用的草料二维码就用的比较多,这里主要想用python进行批量生成二维码。1:系统环境:windows 7 python2.7版本我用的是python2.7版本,python3.6版...
  • 生成带参数的二维码目前2种类型的二维码:1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存...
  • 场景二维码分类• 目前2种类型的二维码:• 1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久...
  • 目前2种类型的二维码: 临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒) 永久二维码,是无过期时间,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、...
  • 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: 1、...
  • 首先了解下二维码的类型:1、临时二维码,是过期时间的,最长二维码生成后的30天(即2592000秒)后过期,能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景。2、永久二维码,是无...
  • 微信带参二维码

    2020-11-03 16:12:28
    目前2种类型的二维码: 1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存业务场景 2、永久...
  • 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: 1...
  • 生成带参数二维码

    2019-05-15 20:44:56
    公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: 1、临时二维码,是过期时间的,最长可以设置为在二维码...
  • 微信创建永久二维码

    2017-05-18 10:58:00
    目前2种类型的二维码: 1、临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存业务场景2、永久...
  • 1.1、目前2种类型的二维码: 1. 临时二维码:临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量,主要用于帐号绑定等不要求二维码永久保存业务场景2....
  • 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: ...
  • 为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。目前2种类型的二维码:1、...
  • Java微信公众平台开发之生成带参二维码

    万次阅读 多人点赞 2016-12-28 17:22:31
    目前2种类型的二维码: 临时二维码,是过期时间,最长可以设置为在二维码生成后30天(即2592000秒)后过期,但能够生成较多数量,主要用于帐号绑定等不要求二维码永久保存业务场景 永久二维码,是无过期...
  • 微信服务号开发-推广二维码

    千次阅读 2018-03-05 11:44:02
    扫码加群:微信公众平台技术文档二维码部分如下:生成带参数的二维码为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,...
  • 公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码: 1、临时二维码,是过期时间的,最长可以设置为在...
  • 微信服务号生成带参数二维码

    千次阅读 2017-07-14 11:21:04
    为了满足用户渠道推广分析和用户帐号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码:1、...
  • 微信公众号平台提供了生成带参数二维码的接口,使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前2种类型的二维码,分别是临时二维码和永久二维码,前者过期时间,...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 325
精华内容 130
关键字:

二维码的类型主要有