Chinaunix首页 | 论坛 | 博客
  • 博客访问: 266456
  • 博文数量: 62
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 740
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-10 21:59
个人简介

付出,终有回报!

文章分类

全部博文(62)

文章存档

2018年(6)

2017年(24)

2016年(6)

2015年(26)

分类: Java

2017-03-28 22:41:48

虽然微信公众平台的文档已经很详细了,网上相关的资料也很多但是在网上很难搜到免费的完整代码。我初次在网页端使用微信扫一扫时,就遇到了很多问题,现分享出我的完整代码。

步骤一:绑定域名


先登录
微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。

备注:登录后可在“开发者中心”查看对应的接口权限。

这里注意域名不要带http:// 等前缀。(顺便推荐做微信开发测试时,使用花生壳账号,映射出公网ip。)比如网址:http://test.wicp.net 那么它的域名就是 test.wicp.net。
如果Js安全域名配置错误,扫一扫时会报错:config:invalid url domain

步骤二:引入JS文件


在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js

请注意,如果你的页面启用了https,务必引入 https://res.wx.qq.com/open/js/jweixin-1.0.0.js ,否则将无法在iOS9.0以上系统中成功使用JSSDK

如需使用摇一摇周边功能,请引入 jweixin-1.1.0.js

备注:支持使用 AMD/CMD 标准模块加载方法加载

这个就是jsp页面直接引入即可


步骤三:通过config接口注入权限验证配置


wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名,见附录1
    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

直接贴出前端的代码:
1、weixin.html

点击(此处)折叠或打开

  1. <!DOCTYPE html>
  2. <html>

  3.     <head>
  4.         <meta charset="UTF-8">
  5.         <title>Insert title here</title>

  6.         <script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
  7.         <script type="text/javascript" src="js/jquery.mobile-1.4.5.min.js"></script>
  8.         <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
  9.         <script type="text/javascript" src="js/weixin.js"></script>

  10.     </head>

  11.     <body>
  12.         <button id="scanQRCode">扫描二维码</button>
  13.     </body>

  14. </html>

2、weixin.js

点击(此处)折叠或打开

  1. //调用微信扫一扫功能所在的页面
  2. var url = window.location.href;

  3. //服务端提供的接口。HOST是服务器的地址,在项目中定义为全局变量;
  4. var url11 = HOST + "/tiaoma.do";

  5.     //ajax注入权限验证
  6.     $.ajax({
  7.         //与服务器交互
  8.         url:url11,
  9.         dataType: 'json',
  10.         data: {"url" : url},
  11.         complete: function(XMLHttpRequest, textStatus){
  12.               
  13.         },
  14.         error: function(XMLHttpRequest, textStatus, errorThrown){
  15.             alert("发生错误:"+errorThrown);
  16.         },
  17.         success: function(res){
  18.             var appId = res.appId;
  19.             var noncestr = res.noncestr;
  20.             var jsapi_ticket = res.jsapi_ticket;
  21.             var timestamp = res.timestamp;
  22.             var signature = res.signature;
  23.                       
  24.             wx.config({
  25.                 debug: true, //开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  26.                 appId: appId, //必填,公众号的唯一标识
  27.                 timestamp: timestamp, // 必填,生成签名的时间戳
  28.                 nonceStr: noncestr, //必填,生成签名的随机串
  29.                 signature: signature,// 必填,签名,见附录1
  30.                 jsApiList: ['checkJsApi', 'scanQRCode'] //必填,需要使用的JS接口列表,所有JS接口列表 见附录2
  31.             });
  32.         }
  33.     });

  34. wx.error(function(res) {
  35.     alert("出错了:" + res.errMsg);
  36. });

  37. //通过ready接口处理成功验证
  38. wx.ready(function() {
  39. // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,
  40. //config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,
  41. //则须把相关接口放在ready函数中调用来确保正确执行。
  42. //对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。

  43.     wx.checkJsApi({
  44.         jsApiList: ['scanQRCode'],
  45.         success: function(res) {
  46.              alert(JSON.stringify(res));
  47.         }
  48.     });

  49.     //扫描二维码
  50.     document.querySelector('#scanQRCode').onclick = function() {
  51.         wx.scanQRCode({
  52.             needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
  53.             scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
  54.             success: function(res) {
  55.                 var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
  56.                 //document.getElementById("wm_id").value = result; //将扫描的结果赋予到jsp对应值上
  57.                 alert("扫描成功::扫描码=" + result);
  58.             }
  59.         });
  60.     }; //end_document_scanQRCode
  61. });


步骤四:通过ready接口处理成功验证

参考官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=876521668&lang=zh_CN 通过后台获取js权限签名jsapi_ticket

直接给出后台相关的代码:

1、Token.java

点击(此处)折叠或打开



  1. /**
  2.  * 凭证
  3.  *
  4.  */
  5. public class Token {
  6.     
  7.     // 接口访问凭证
  8.     private String accessToken;
  9.     // 凭证有效期,单位:秒
  10.     private int expiresIn;

  11.     public String getAccessToken() {
  12.         return accessToken;
  13.     }

  14.     public void setAccessToken(String accessToken) {
  15.         this.accessToken = accessToken;
  16.     }

  17.     public int getExpiresIn() {
  18.         return expiresIn;
  19.     }

  20.     public void setExpiresIn(int expiresIn) {
  21.         this.expiresIn = expiresIn;
  22.     }

  23. }
2、JsapiTicket.java

点击(此处)折叠或打开


  1. public class JsapiTicket {
  2.     
  3.     // 获取到的凭证
  4.     private String ticket;
  5.     // 凭证有效期,单位:秒
  6.     private int expiresIn;
  7.     
  8.     public String getTicket() {
  9.         return ticket;
  10.     }
  11.     
  12.     public void setTicket(String ticket) {
  13.         this.ticket = ticket;
  14.     }
  15.     
  16.     public int getExpiresIn() {
  17.         return expiresIn;
  18.     }
  19.     
  20.     public void setExpiresIn(int expiresIn) {
  21.         this.expiresIn = expiresIn;
  22.     }
  23.     
  24. }

3、TokenUtil.java

点击(此处)折叠或打开



  1. import java.io.BufferedReader;
  2. import java.io.InputStream;
  3. import java.io.InputStreamReader;
  4. import java.io.OutputStream;
  5. import java.net.ConnectException;
  6. import java.net.URL;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. import javax.net.ssl.HttpsURLConnection;
  10. import javax.net.ssl.SSLContext;
  11. import javax.net.ssl.SSLSocketFactory;
  12. import javax.net.ssl.TrustManager;
  13. import net.sf.json.JSONException;
  14. import net.sf.json.JSONObject;
  15. import com.TourGuide.model.JsapiTicket;
  16. import com.TourGuide.model.Token;
  17. import com.google.gson.Gson;
  18. import com.google.gson.JsonObject;
  19. import com.google.gson.JsonParser;


  20. public class TokenUtil {
  21.     
  22.     public final static String appid = "****************";
  23.     public final static String secret = "****************************";
  24.     
  25.     // 凭证获取(GET),token_url获取凭证接口的请求地址
  26.     public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?"
  27.             + "grant_type=client_credential&"
  28.             + "appid=" + appid + "&"
  29.             + "secret=" + secret;
  30.     
  31.     
  32.     /**
  33.      * 发送https请求.定义了一个通用的HTTPS请求方法,用于发送HTTPS GET和POST请求
  34.      * 当调用公众平台的开发接口时,都需要传入接口访问凭证access_token
  35.      *
  36.      * @param requestUrl 请求地址
  37.      * @param requestMethod 请求方式(GET、POST)
  38.      * @param outputStr 提交的数据
  39.      * @return
  40.      */
  41.     public static JSONObject getTokenJsonObject(String requestUrl, String requestMethod, String outputStr){
  42.         
  43.         JSONObject returnData = null;
  44.         
  45.         try {
  46.             
  47.             // 创建SSLContext对象,并使用我们指定的信任管理器初始化
  48.             TrustManager[] tm = {new MyX509TrustManager()};
  49.             SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
  50.             sslContext.init(null, tm, new java.security.SecureRandom());
  51.             // 从上述SSLContext对象中得到SSLSocketFactory对象
  52.             SSLSocketFactory ssf = sslContext.getSocketFactory();
  53.             
  54.             URL url = new URL(requestUrl);
  55.             HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
  56.             conn.setSSLSocketFactory(ssf);
  57.             
  58.             conn.setDoOutput(true);
  59.             conn.setDoInput(true);
  60.             conn.setUseCaches(false);
  61.             // 设置请求方式(GET/POST)
  62.             conn.setRequestMethod(requestMethod);
  63.             
  64.             // 当outputStr不为null时向输出流写数据
  65.             if (null != outputStr) {
  66.                 OutputStream outputStream = conn.getOutputStream();
  67.                 // 注意编码格式
  68.                 outputStream.write(outputStr.getBytes("UTF-8"));
  69.                 outputStream.close();
  70.             }
  71.             
  72.             // 从输入流读取返回内容
  73.             InputStream inputStream = conn.getInputStream();
  74.             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
  75.             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
  76.             String str = null;
  77.             StringBuffer buffer = new StringBuffer();
  78.             while ((str = bufferedReader.readLine()) != null) {
  79.                 buffer.append(str);
  80.             }
  81.             
  82.             // 释放资源
  83.             bufferedReader.close();
  84.             inputStreamReader.close();
  85.             inputStream.close();
  86.             inputStream = null;
  87.             conn.disconnect();

  88.             returnData = JSONObject.fromObject(buffer.toString());
  89.         } catch (ConnectException ce) {
  90.             System.out.printf("连接超时:{}", ce);
  91.         } catch (Exception e) {
  92.             System.out.printf("https请求异常:{}", e);
  93.         }
  94.         
  95.         return returnData;
  96.     }
  97.     
  98.     
  99.     /**
  100.      * 获取接口访问凭证。将得到的json结果转为Token对象
  101.      * @return
  102.      */
  103.     public static Token getToken(){
  104.         
  105.         Token token = null;
  106.         String requestUrl = token_url;
  107.         // 发起GET请求获取凭证
  108.         JSONObject returnData = getTokenJsonObject(requestUrl, "GET", null);
  109.         
  110.         if(null != returnData){

  111.             try {
  112.                 token = new Token();
  113.                 token.setAccessToken(returnData.getString("access_token"));
  114.                 token.setExpiresIn(Integer.parseInt(returnData.getString("expires_in")));

  115.             } catch (Exception e) {
  116.                 token = null;
  117.                 // 获取token失败
  118.                 System.out.printf("获取token失败 errcode:{} errmsg:{}", returnData.get("errcode"),
  119.                         returnData.get("errmsg"));
  120.             }
  121.         }
  122.         
  123.         return token;
  124.     }
  125.     
  126.     
  127.     /**
  128.      * 获取jsapi_ticket
  129.      *
  130.      * @param appid 凭证
  131.      * @param appsecret 密钥
  132.      * @return
  133.      */
  134.     public static JsapiTicket getJsapiTicket(String accessToken) {
  135.         
  136.         //获取公众号jsapi_ticket的链接
  137.         String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?"
  138.                 + "access_token=ACCESS_TOKEN&type=jsapi";
  139.         
  140.         //ticket分享值
  141.         JsapiTicket jsapiticket = null;
  142.         
  143.         if(accessToken != null){
  144.              String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", accessToken);
  145.              JSONObject jsonObject = getTokenJsonObject(requestUrl, "GET", null);
  146.              // 如果请求成功
  147.              if (null != jsonObject) {
  148.                  try {
  149.                      jsapiticket = new JsapiTicket();
  150.                      jsapiticket.setTicket(jsonObject.getString("ticket"));
  151.                      jsapiticket.setExpiresIn(jsonObject.getInt("expires_in"));
  152.                  } catch (JSONException e) {
  153.                      jsapiticket = null;
  154.                      // 获取ticket失败
  155.                     System.out.printf("获取ticket失败 errcode:{} errmsg:{}",
  156.                             jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
  157.                  }
  158.          }
  159.         }else{
  160.             System.out.println("*****token为空 获取ticket失败******");
  161.         }
  162.        
  163.         return jsapiticket;
  164.     }

  165. }

4、JsSignUtil.java

点击(此处)折叠或打开


  1. import java.io.UnsupportedEncodingException;
  2. import java.security.MessageDigest;
  3. import java.security.NoSuchAlgorithmException;
  4. import java.util.Formatter;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7. import java.util.UUID;

  8. /** 
     * 官方给的使用js的验证工具 
     * 
     */ 
  9. public class JsSignUtil {
  10.     
  11.     public static String accessToken = null;
  12.     
  13.     public static Map<String, String> sign(String url){
  14.         
  15.         //获取accessToken
  16.         accessToken = TokenUtil.getToken().getAccessToken();
  17.         //获取JsapiTicket
  18.         String jsapi_ticket =TokenUtil.getJsapiTicket(accessToken).getTicket();
  19.         
  20.         Map<String, String> ret = new HashMap<String, String>();
  21.         String nonce_str = create_nonce_str();
  22.         String timestamp = create_timestamp();
  23.         String string1;
  24.         String signature = "";
  25.   
  26.         //注意这里参数名必须全部小写,且必须有序
  27.         string1 = "jsapi_ticket=" + jsapi_ticket +
  28.                   "&noncestr=" + nonce_str +
  29.                   "×tamp=" + timestamp +
  30.                   "&url=" + url;
  31. // System.out.println("string1="+string1);
  32.   
  33.         try
  34.         {
  35.             MessageDigest crypt = MessageDigest.getInstance("SHA-1");
  36.             crypt.reset();
  37.             crypt.update(string1.getBytes("UTF-8"));
  38.             signature = byteToHex(crypt.digest());
  39.         }
  40.         catch (NoSuchAlgorithmException e)
  41.         {
  42.             e.printStackTrace();
  43.         }
  44.         catch (UnsupportedEncodingException e)
  45.         {
  46.             e.printStackTrace();
  47.         }
  48.   
  49.         ret.put("url", url);
  50.         ret.put("jsapi_ticket", jsapi_ticket);
  51.         ret.put("nonceStr", nonce_str);
  52.         ret.put("timestamp", timestamp);
  53.         ret.put("signature", signature);
  54.         ret.put("appId", "wxd3bda909c7fb1467");
  55.   
  56. // System.out.println("1.ticket(原始)="+jsapi_ticket);
  57. // System.out.println("2.url="+ret.get("url"));
  58. // System.out.println("3.jsapi_ticket(处理后)="+ret.get("jsapi_ticket"));
  59. // System.out.println("4.nonceStr="+ret.get("nonceStr"));
  60. // System.out.println("5.signature="+ret.get("signature"));
  61. // System.out.println("6.timestamp="+ret.get("timestamp"));
  62.           
  63.         return ret;
  64.     }

  65.     
  66.     /**
  67.      * 随机加密
  68.      * @param hash
  69.      * @return
  70.      */
  71.     private static String byteToHex(final byte[] hash) {
  72.         Formatter formatter = new Formatter();
  73.         for (byte b : hash)
  74.         {
  75.             formatter.format("%02x", b);
  76.         }
  77.         String result = formatter.toString();
  78.         formatter.close();
  79.         return result;
  80.     }
  81.   
  82.     /**
  83.      * 产生随机串--由程序自己随机产生
  84.      * @return
  85.      */
  86.     private static String create_nonce_str() {
  87.         return UUID.randomUUID().toString();
  88.     }
  89.   
  90.     /**
  91.      * 由程序自己获取当前时间
  92.      * @return
  93.      */
  94.     private static String create_timestamp() {
  95.         return Long.toString(System.currentTimeMillis() / 1000);
  96.     }
  97. }

5、weixinScanController.java

点击(此处)折叠或打开

  1. import java.util.HashMap;
  2. import java.util.Map;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8. import com.TourGuide.weixin.util.JsSignUtil;

  9. @Controller
  10. public class weixinScanController {
  11.     
  12.     /**
  13.      * 微信扫一扫接口的后台处理程序
  14.      * @param request
  15.      * @param response
  16.      * @return
  17.      * @throws Exception
  18.      */
  19.     @RequestMapping(value = "/weixinScan.do")
  20.      @ResponseBody
  21.      public Object weixinScan( HttpServletRequest request,
  22.              HttpServletResponse response) throws Exception {

  23.          String weburl = request.getParameter("url");

  24.      Map<String, String> resMap = new HashMap<String, String>();
  25.      resMap = JsSignUtil.sign(weburl);
  26.     
  27.      return resMap;
  28.      }

  29. }

水平有限,如有错误,多多指正

参考:http://blog.csdn.net/u013589542/article/details/54864477
http://blog.csdn.net/f429629227/article/details/53809577
http://www.2cto.com/weixin/201505/400450.html

阅读(3703) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~