微信扫一扫_微信扫一扫登录 - CSDN
精华内容
参与话题
  • 微信开放实战--扫一扫功能(详细)

    万次阅读 2017-12-14 23:44:27
    大概流程: 1.根据appId和app...进入微信公众平台码登录测试号公众号:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login public static JSONObject getTokenTool(String appId,String appSecr
    大概流程:
    1.根据appId和appSecret获取access_token(使用凭证)
    进入微信公众平台扫码登录测试号公众号:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

    public static JSONObject getTokenTool(String appId,String appSecret){
    String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;
    System.out.println(HttpRequestUtil.httpRequest(url, "GET", ""));
    return HttpRequestUtil.httpRequest(url, "GET", "");
    }

    这是测试号获取access_token的接口,普通公众号接口地址请查看微信官方文档。



    2.根据access_token获取jsapi_ticket
    public static JSONObject getTicketTool(String access_token){
    String url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
    System.out.println(HttpRequestUtil.httpRequest(url, "GET", ""));
    return HttpRequestUtil.httpRequest(url, "GET", "");
    }





    3.在微信获取签名算法(具体如下)
    public static Map<String, String> sign(String url) {
    String appId="wxcc42f613dbf7299f";
    String appSecret="e59e10c74c70b1c042b5ecaf454052ac";
    String access_token=getTokenTool(appId, appSecret).getString("access_token");
    JSONObject ticketJson=getTicketTool(access_token);
    System.out.println(ticketJson.toString());
    String jsapi_ticket = ticketJson.getString("ticket");
    Map<String, String> ret = new HashMap<String, String>();
    //这里的jsapi_ticket是获取的jsapi_ticket。
    String nonce_str = create_nonce_str();
    String timestamp = create_timestamp();
    String string1;
    String signature = "";
    System.out.println(2);

    //注意这里参数名必须全部小写,且必须有序
    string1 = "jsapi_ticket=" + jsapi_ticket +
    "&noncestr=" + nonce_str +
    "&timestamp=" + timestamp +
    "&url=" + url;

    try
    {
    MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    crypt.reset();
    crypt.update(string1.getBytes("UTF-8"));
    signature = byteToHex(crypt.digest());
    System.out.println("crypt="+crypt.toString());
    System.out.println("string1="+string1);
    System.out.println("signature="+signature);
    }
    catch (NoSuchAlgorithmException e)
    {
    e.printStackTrace();
    }
    catch (UnsupportedEncodingException e)
    {
    e.printStackTrace();
    }

    ret.put("url", url);
    ret.put("jsapi_ticket", jsapi_ticket);
    ret.put("nonceStr", nonce_str);
    ret.put("timestamp", timestamp);
    ret.put("signature", signature);

    return ret;
    }

    private static String byteToHex(final byte[] hash) {
    Formatter formatter = new Formatter();
    for (byte b : hash)
    {
    formatter.format("%02x", b);
    }
    String result = formatter.toString();
    formatter.close();
    return result;
    }

    private static String create_nonce_str() {
    return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
    return Long.toString(System.currentTimeMillis() / 1000);
    }

    4.获取一个js安全域名接口(如:gstz.imwork.net
    一般使用花生壳进行内网穿透,使内网地址映射到一个花生壳提供的公网的地址,适合用来测试,花生壳内网穿透如何使用可到花生壳官网查看。





    5.把域名和action的地址拼接起来成url,放入签名方法中


    @Controller
    @SuppressWarnings("serial")
    public class WeixinAction{
    /**
    * 获取签名算法
    */
    @RequestMapping("getSign")
    @ResponseBody
    public JSONObject getSign(){
    JSONObject jsonObject=new JSONObject();
    String url="http://17j62137x0.imwork.net/ssm_d1/index.jsp";
    Map<String, String> ret =WxJSUtil.sign(url);
    System.out.println("map="+ret.toString());
    jsonObject.put("weixin", ret);
    System.out.println("json="+jsonObject.toString());
    return jsonObject;
    }
    }
    6.在JSP页面初始化时异步获取签名action传来3个参数,JSP内容如下




    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!DOCTYPE>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>微信扫一扫</title>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="js/weixin.js"></script>
    </head>
    <body>
    <input id="timestamp" type="hidden" value="${timestamp}" />
    <input id="noncestr" type="hidden" value="${nonceStr}" />
    <input id="signature" type="hidden" value="${signature}" />
    <input id="id_securityCode_input">
    <button id="scanQRCode" οnclick="getWeixinResult()">扫码</button>
    </body>
    <script type="text/javascript">
    </script>
    </html>
    7.通过签名算法获取wx.config的4个重要参数:jsapi_ticket、noncestr、timestamp、url
    wx.config({ debug: true,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:'',// 必填,公众号的唯一标识 timestamp: ,// 必填,生成签名的时间戳 nonceStr:'',// 必填,生成签名的随机串 signature:'',// 必填,签名,见附录1 jsApiList: []// 必填,需要使用的JS接口列表,所有JS接口列表见附录2});



    8.告诉微信选择调用的接口名称



    9.把获取的结果result进行处理getWeixinResultCallBack(param)


    10.给按钮添加 getWeixinResult事件,就可以通过按钮调用扫一扫功能。(记得用微信浏览器点开)


    这是DEMO的下载地址(博主本想免费分享这个资源的,无奈CSDN最少也要2点资源分才能下载):下载DEMO
    展开全文
  • 参考微信JS-SDK说明文档 尽管作用不是很大1.首先在JSP页面引入http://res.wx.qq.com/open/js/jweixin-1.1.0.js2.通过config接口注入权限验证配置

    参考微信JS-SDK说明文档 看到网上很多都说微信的说明文档很坑,在我看来,仔细阅读的话,介绍还是很全的。

    1.首先在JSP页面引入http://res.wx.qq.com/open/js/jweixin-1.1.0.js

    2.通过config接口注入权限验证配置

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

    3.通过ready接口处理成功验证

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

    4.通过error接口处理失败验证

    wx.error(function(res){
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    });

    5.调起微信扫一扫

    wx.scanQRCode({
        desc: 'scanQRCode desc',
        needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
        scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
        success: function (res) {
           // 回调
        }
        error: function(res){
              if(res.errMsg.indexOf('function_not_exist') > 0){
                   alert('版本过低请升级')
                }
         }
    });

    具体代码实现如下:

    scanBarcode.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html lang="zh-CN">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
    <head>
        <link rel="stylesheet" href="http://203.195.235.76/jssdk/css/style.css"/>
        <script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
        <link rel="stylesheet" href="../../../resources/css/example.css"/>
        <link rel="stylesheet" href="../../../resources/css/weui.min.css"/>
        <link rel="stylesheet" href="../../../resources/css/borrowScan.css"/>
    </head>
    <body>
    <div class="container" style="text-align: center;">
        <div class="body_bd body_fd">
            <a class="weui-btn weui-btn-primary weui-btn-zdy" id="scanQRCode1">
                <p>扫描条码</p>
            </a>
        </div>
    </div>
    <script type="text/javascript">
        $.ajax({
            url: "${pageContext.request.contextPath}/wechat/jsapisign",
            type: "post",
            data: {
                url: location.href.split('#')[0]
            },
            contentType: 'application/x-www-form-urlencoded;charset=utf-8',
            async: true,
            success: function (data) {
                wx.config({
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: data.appid, // 必填,公众号的唯一标识
                    timestamp: data.timestamp, // 必填,生成签名的时间戳
                    nonceStr: data.nonceStr, // 必填,生成签名的随机串
                    signature: data.signature,// 必填,签名,见附录1
                    jsApiList: ["scanQRCode"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });
            }
        });
    
        wx.ready(function () {
            // 9.1.2 扫描二维码并返回结果
            document.querySelector('#scanQRCode1').onclick = function () {
                wx.scanQRCode({
                    needResult: 1,
                    desc: 'scanQRCode desc',
                    success: function (res) {
                        //扫码后获取结果参数赋值给Input
                        var url = res.resultStr;
                        //商品条形码,取","后面的
                        if (url.indexOf(",") >= 0) {
                            var tempArray = url.split(',');
                            var barCode = tempArray[1];
                            window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${basePath}/wechat/toBookDetail?barCode=" + barCode + "&response_type=code&scope=snsapi_base&state=BINDFACE#wechat_redirect";
                        } else {
                            alert("请对准条形码扫码!");
                        }
                    }
                });
            };
        });
    
        //初始化jsapi接口 状态
        wx.error(function (res) {
            alert("调用微信jsapi返回的状态:" + res.errMsg);
        });
    </script>
    </body>
    </html>

    微信验签代码 WxController.java

      /**
         * 微信验签
         * @param url
         * @return
         */
        @RequestMapping(value = "/jsapisign", method = {RequestMethod.GET, RequestMethod.POST}, produces = MEDIATYPE_CHARSET_JSON_UTF8)
        @ResponseBody
        public String jsApiSign(String url) {
            //添加微信js签名信息
            Map<String, String> signMap = WXJsapiticket.jsApiSign(url);
            return JSON.toJSONString(signMap);
        }

    用到的方法类

    WXJsapiticket.java

    public class WXJsapiticket {
        private static Logger logger = LoggerFactory.getLogger(WxController.class);
        /**
         * 微信jsapi验签
         * @param url
         * @return
         */
        public static Map<String, String> jsApiSign(String url) {
            Map<String, String> ret = new HashMap<String, String>();
            String nonce_str = CheckUtil.create_nonce_str();
            String timestamp = CheckUtil.create_timestamp();
            String jsapi_ticket = getJsApiTicket();
            String string1 = CheckUtil.getString1(nonce_str,timestamp,jsapi_ticket,url);
            String signature = CheckUtil.getSha1(string1);
            ret.put("appid", WXConstants.APPID);//取你自己的公众号appid
            ret.put("url", url);
            ret.put("jsapi_ticket", jsapi_ticket);
            ret.put("nonceStr", nonce_str);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
            logger.info("jsApiSign------url=" + url + "-----jsapi_ticket=" + jsapi_ticket + "--------nonceStr=" + nonce_str + "--------timestamp=" + timestamp + "-------signature=" + signature);
            return ret;
        }
        public static String getJsApiTicket(){
            Map<String,Object> map = JsApiTicketCache.getInstance().getJsApiTicketAndExpiresIn();
            return (String) map.get("jsapi_ticket");
        }
    }

    CheckUtil.java

    public class CheckUtil {
        public static final String  token = "xiaodou"; //开发者自行定义Token
        /**
         * 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成字符串string1
         * @param nonce_str
         * @param timestamp
         * @param jsapi_ticket
         * @param url
         * @return
         */
        public static String getString1(String nonce_str,String timestamp,String jsapi_ticket,String url){
            //1.定义数组存放nonce_str,timestamp,jsapi_ticket,url
            String[] arr = {"noncestr="+nonce_str,"timestamp="+timestamp,"jsapi_ticket="+jsapi_ticket,"url="+url};
            //2.对数组进行排序
            Arrays.sort(arr);
            //3.生成字符串
            StringBuffer sb = new StringBuffer();
            for(String s : arr){
                sb.append(s);
                sb.append("&");
            }
            sb.deleteCharAt(sb.length()-1);
            return sb.toString();
        }
        public static String getSha1(String str){
            if(str==null||str.length()==0){
                return null;
            }
            char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9',
                    'a','b','c','d','e','f'};
            try {
                MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
                mdTemp.update(str.getBytes("UTF-8"));
                byte[] md = mdTemp.digest();
                int j = md.length;
                char buf[] = new char[j*2];
                int k = 0;
                for (int i = 0; i < j; i++) {
                    byte byte0 = md[i];
                    buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                    buf[k++] = hexDigits[byte0 & 0xf];
                }
                return new String(buf);
            } catch (Exception e) {
                // TODO: handle exception
                return null;
            }
        }
        public static String create_nonce_str() {
            return UUID.randomUUID().toString();
        }
        public static String create_timestamp() {
            return Long.toString(System.currentTimeMillis() / 1000);
        }
    }

    JsApiTicketCatch.java(对jsapi_ticket的缓存可自行设置,redis或者存到数据库都是可行的)

    /**
     * 缓存ticket
     */
    public class JsApiTicketCache {
        //缓存jsapi_ticket的Map,map中包含jsapiTicket,expiresIn和缓存的时间戳time
        private Map<String, String> map = new HashMap<String,String>();
        private static JsApiTicketCache jsApiTicketCache = null;
        private JsApiTicketCache() { }
        // 静态工厂方法
        public static JsApiTicketCache getInstance() {
            if (jsApiTicketCache == null) {
                jsApiTicketCache = new JsApiTicketCache();
            }
            return jsApiTicketCache;
        }
        public Map<String, String> getMap() {
            return map;
        }
        public void setMap(Map<String, String> map) {
            this.map = map;
        }
        /**
         * 获取 jsapi_ticket expires_in
         * @return
         */
        public Map<String,Object> getJsApiTicketAndExpiresIn() {
            Map<String,Object> result = new HashMap<String,Object>();
            JsApiTicketCache jsApiTicketCache = JsApiTicketCache.getInstance();
            Map<String, String> map = jsApiTicketCache.getMap();
            String time = map.get("time");
            String jsapiTicket = map.get("jsapi_ticket");
            String expiresIn = map.get("expires_in");
            Long nowDate = new Date().getTime();
            if (jsapiTicket != null && time != null && expiresIn!=null) {
                //这里设置过期时间为微信规定的过期时间减去5分钟
                int outTime = (Integer.parseInt(expiresIn)-300) * 1000;
                if (nowDate - Long.parseLong(time) < outTime) {
                    System.out.println("-----从缓存读取jsapi_ticket:" + jsapiTicket);
                    //从缓存中拿数据为返回结果赋值
                    result.put("jsapi_ticket", jsapiTicket);
                    result.put("expires_in", expiresIn);
                }
            } else {
                JsapiTicket info = WeiXinUtil.getjsapiTicket();//实际中这里要改为你自己调用微信接口去获取jsapi_ticket和expires_in
                System.out.println("-----通过调用微信接口获取jsapi_ticket:" + info.getJsapiTicket());
                //将信息放置缓存中
                map.put("time", nowDate + "");
                map.put("jsapi_ticket", info.getJsapiTicket());
                map.put("expires_in", info.getExpiresIn()+"");
                //为返回结果赋值
                result.put("jsapi_ticket", info.getJsapiTicket());
                result.put("expires_in", info.getExpiresIn());
            }
            return result;
        }
    
    }

    WeiXinUtil.java

    jsapi_ticket_url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";//GET方式请求获得jsapi_ticket
     /**
         * 获取jsapi_ticket
         * @return
         */
        public static JsapiTicket getjsapiTicket() {
            JsapiTicket jsapiTicket = null ;
            String accessToken = (String) AccessTokenCache.getInstance().getAcessTokenAndExpiresIn().get("access_token");
            String requestUrl = WXConstants.jsapi_ticket_url.replace("ACCESS_TOKEN", accessToken);
            JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
            // 如果请求成功
            if (null != jsonObject) {
                try {
                    jsapiTicket = new JsapiTicket();
                    jsapiTicket.setJsapiTicket(jsonObject.getString("ticket"));
                    jsapiTicket.setExpiresIn(jsonObject.getInt("expires_in"));
                } catch (JSONException e) {
                    jsapiTicket = null;
                    // 获取token失败
                    log.error("获取ticket失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
                }
            }
            return jsapiTicket;
        }

    accessToken的获取参照微信公众号开发之获取access_token,也可根据自己的定义获取。

    JsapiTicket.java

    public class JsapiTicket {
        private String id;
        private String jsapiTicket;
        private int expiresIn;
    
        public String getJsapiTicket() {
            return jsapiTicket;
        }
    
        public void setJsapiTicket(String jsapiTicket) {
            this.jsapiTicket = jsapiTicket;
        }
    
        public int getExpiresIn() {
            return expiresIn;
        }
    
        public void setExpiresIn(int expiresIn) {
            this.expiresIn = expiresIn;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    }

    在这里总结一下开发中需要注意的地方(我遇到的坑):

    1.确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。

    2.在生成string1时,拼接的参数均为小写,特别注意noncestr,而在jsp页面中为nonceStr(所有的参数一定要根据微信接口中的定义,否则会导致验签失败)。

    3.验证签名是否正确,可在 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign页面工具进行校验。

    展开全文
  • 微信扫一扫

    2018-12-20 16:47:33
    主要是调用微信接口比较简单,难点在于签名的验证 前端: &lt;% String openid=null; openid=request.getParameter("openid"); String url="http://cubm67.natappfree.c...

    研究时间:2 day
    主要是调用微信接口比较简单,难点在于签名的验证

    前端:

                <% 
          
            String openid=null;
            openid=request.getParameter("openid");
            
          
          String url="http://cubm67.natappfree.cc//Weixin/test.do";
                  
           Map<String,String> map=JsSignUtil.sign(url); 
               	  
            String username=null;
            String password=null;
          
             String appid="appid";
             String secret="secret"; 
              
             if(openid!=null){
              username=Update.query_loginname(openid);
              if(username==null){
                     response.sendRedirect("login.do"); 
                 }
    		  password=Update.query_password(openid);
             }
    		   
            if(username==null||password==null){
                System.out.println("over_wxsys");
            }                              
                  %>
                  
    <html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <meta charset="UTF-8">
        <title>扫一扫</title>
        
     <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
        <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
        <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
        <script  type="text/javascript">
       /*   var signature= document.getElementById('signature').value; */
           
            wx.config({
                debug: false,
                appId: "<%=map.get("appId")%>",
                timestamp:"<%=map.get("timestamp")%>",
                nonceStr:"<%=map.get("nonceStr")%>",
                signature:"<%=map.get("signature")%>",
                jsApiList : ['checkJsApi','scanQRCode']
            });//end_config
            //步骤五
            wx.error(function(res) {
                alert("出错了:" + res.errMsg);
            });
            //步骤四
          wx.ready(function(){
                wx.checkJsApi({
                    jsApiList : ['scanQRCode'],
                    success : function(res) {
                    if(res.checkResult.scanQRCode != true){
                     alert('抱歉,当前客户端版本不支持扫一扫');
                    }
                    }
                });
     
                //扫描二维码
                var url=location.href.split('#')[0];
                //alert(url)
                document.querySelector('#scanQRCode').onclick=function(){ 
                    wx.scanQRCode({
                        needResult : 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
                        scanType : [ "qrCode", "barCode" ], // 可以指定扫二维码还是一维码,默认二者都有
                        success : function(res) {
                            var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
                            //document.getElementById("wm_id").value = result;//将扫描的结果赋予到jsp对应值上
                            //alert("扫描成功::扫描码=" + result);
                                                 
                             var obj = JSON.parse(result);       
                             var username="<%=username%>"
                             var password="<%=password%>"  
                                          
                           self.location="http:"+obj.systemCode+
                          "&terminalCode="+obj.terminalCode+
                          "&username="+username+
                          "&password="+password+"";                                    
                        }
                    });
                };    //end_document_scanQRCode
            });//end_ready 
            
            // alert(location.href.split('#')[0]);
        </script>
    </body>
         <div style="margin-top:20px;text-align: center;">
     <button id="scanQRCode" style="border-radius:5px;margin:20px auto;width:80%;height:40px;line-height:40px;text-align:center;background:#66FF66;color:#000;">
           <font size=4>扫描二维码</font></button>
    </body>
    </html>
    

    签名方法:

    import net.sf.json.JSONObject;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Formatter;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
     
    /**
     * 官方给的使用js的验证工具
     * @author Gang_Luo
     *
     */
    
    public class JsSignUtil {
        public static String accessToken = null;
        
     
        public static void main(String[] args) throws IOException {
    		
        	
        	// Map<String, String> map=sign("sy7sqz.natappfree.cc"); 
    
    	}
       
        public static String  getAccessToken() {
        	 JSONObject accesTokenObject;
        	 String accesToken=null;
    		try {
    			 accesTokenObject = AuthUtil.doGetJson(Constants.ACCESS_TOKEN_URL);
    			 accesToken=(String) accesTokenObject.get("access_token");
    		      System.out.println("微信返回accesTokenObject"+accesTokenObject);
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
           
    	
         	 return accesToken;
        }
        
        public static String  getTicket(String accesToken)  {
             accesToken=getAccessToken();
            JSONObject jsapiTicketObject;
             String jsapiTicket=null;
    		try {
    			 jsapiTicketObject = AuthUtil.doGetJson("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accesToken + "&type=jsapi");
    		     jsapiTicket = (String) jsapiTicketObject.get("ticket"); 
    		     System.out.println("微信返回jsapiTicketObject"+jsapiTicketObject);
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
           
    	
        	 return  jsapiTicket;
       }
        
        public static Map<String, String> sign(String url) throws IOException {
       
        	
        	 TokenSingleton tokenSingleton=TokenSingleton.getInstance();
        	 Map<String, String> map=tokenSingleton.getMap();
    
        	
             String jsapiTicket =map.get("jsapi_token"); 
          
            Map<String, String> ret = new HashMap<String, String>();
            String nonce_str =create_nonce_str();
            String timestamp =create_timestamp();
            String string1;
            String signature ="";
     
            //注意这里参数名必须全部小写,且必须有序
            string1="jsapi_ticket=" + jsapiTicket +
                    "&noncestr=" + nonce_str +
                    "&timestamp=" + timestamp +
                    "&url=" +url;
            try
            {
                MessageDigest crypt = MessageDigest.getInstance("SHA-1");
                crypt.reset();
                crypt.update(string1.getBytes("UTF-8"));
                signature = byteToHex(crypt.digest());
            }
            catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            }
            catch (UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }
     
            ret.put("url", url);
            ret.put("jsapi_ticket",jsapiTicket);
            ret.put("nonceStr", nonce_str);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
            ret.put("appId", "appId");
     
     
           //System.out.println("JsSignUtil.url="+ret.get("url"));
         /*  
          *  System.out.println("1.ticket(原始)="+jsapiTicket);
            System.out.println("4.nonceStr="+ret.get("nonceStr"));
            System.out.println("5.signature="+ret.get("signature"));
            System.out.println("6.timestamp="+ret.get("timestamp"));*/
    
            return ret;
        }
     
     
        /**
         * 随机加密
         * @param hash
         * @return
         */
        private static String byteToHex(final byte[] hash) {
            Formatter formatter = new Formatter();
            for (byte b : hash)
            {
                formatter.format("%02x", b);
            }
            String result = formatter.toString();
            formatter.close();
            return result;
        }
     
        /**
         * 产生随机串--由程序自己随机产生
         * @return
         */
        private static String create_nonce_str() {
            return UUID.randomUUID().toString();
        }
     
        /**
         * 由程序自己获取当前时间
         * @return
         */
        private static String create_timestamp(){
            return Long.toString(System.currentTimeMillis() / 1000);
        }
    }
    
    

    注意:

      **签名url与调用接口的url必须完全一样!!!!在这里卡了一个下午!!!**
    

    服务器配置:

    服务器地址:servlet 令牌(Token):god
    签名校验

      public static boolean checkSignature(String signature, String timestamp, String nonce)
      {
        String[] arr = { "god", timestamp, nonce };
        if ((timestamp != null) && (nonce != null)) {
          Arrays.sort(arr);
        }
    
        StringBuffer content = new StringBuffer();
        for (int i = 0; i < arr.length; i++)
        {
          content.append(arr[i]);
        }
    
        String temp = getSha1(content.toString());
    
        return temp.equals(signature);
      }
    

    微信后台操作:

    import com.imooc.util.CheckUtil;
    import com.imooc.util.MesssageUtil;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Map;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class WeixinServlet extends HttpServlet
    {
      private static final long serialVersionUID = 1L;
    
      protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
      {
        String signature = req.getParameter("signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        String echostr = req.getParameter("echostr");
    
        PrintWriter out = resp.getWriter();
        if (CheckUtil.checkSignature(signature, timestamp, nonce))
          out.print(echostr);
      }
    
      protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
      {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        PrintWriter out = resp.getWriter();
    
        Map map = MesssageUtil.xmlToMap(req);
    
        String toUserName = (String)map.get("ToUserName");
        String fromUserName = (String)map.get("FromUserName");
        String msgType = (String)map.get("MsgType");
        String content = (String)map.get("Content");
    
        String msg = "";
        if ("text".equals(msgType))
        {
          if ("1".equals(content)) {
            msg = MesssageUtil.initText(fromUserName, toUserName, MesssageUtil.firstmenu());
          }
        }
        else if ("event".equals(msgType))
        {
          String eventTpye = (String)map.get("Event");
          if ("subscribe".equals(eventTpye))
          {
            msg = MesssageUtil.initText(fromUserName, toUserName, MesssageUtil.menuText());
          } else if ("CLICK".equals(eventTpye)) {
            String eventKey = (String)map.get("EventKey");
    
            if (eventKey.equals("zzzzzzzzzzzzz"))
            {
              msg = MesssageUtil.initText(fromUserName, toUserName, MesssageUtil.firstmenu());
            }
          }
        }
        out.print(msg);
        out.close();
      }
    }
    
    展开全文
  • 微信扫一扫揭秘

    2016-09-19 15:26:26
    该文章Wie转载 前言 要探索二维码的秘密之前,我们首先需要简单了解下什么是二维码。 ...二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形...

    该文章Wie转载

    前言
    要探索二维码的秘密之前,我们首先需要简单了解下什么是二维码。


    什么是二维码
    二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理。


    其实简单的说二维码就是一段简单的字符串图形化的展示,它可能是一个url,一段文字,或者是一首唐诗也不错哦


    微信二维码,网页打开app,扫一扫

    微信二维码,网页打开app,扫一扫
    微信二维码,网页打开app,扫一扫


    为什么要使用二维码
    二维码的诞生可以说是真正的促进这移动互联网的发展。


    1、信息获取(名片、地图、WIFI密码、资料)
    2、网站跳转(跳转到微博、手机网站、网站)
    3、广告推送(用户扫码,直接浏览商家推送的视频、音频广告)
    4、手机电商(用户扫码、手机直接购物下单)
    5、防伪溯源(用户扫码、即可查看生产地;同时后台可以获取最终消费地)
    6、优惠促销(用户扫码,下载电子优惠券,抽奖)
    7、会员管理(用户手机上获取电子会员信息、VIP服务)
    8、手机支付(扫描商品二维码,通过银行或第三方支付提供的手机端通道完成支付)


    在不同的领域,不同的行业二维码都可以用来简化原来的工作流程,那么我们为什么不来试试二维码呢?


    二维码的生成
    通过对上面的了解相信大家对二维码已经有了一定的了解,那么二维码是怎么生成的呢?


    维码一共有40个尺寸。官方叫版本Version。Version 1是21 x 21的矩阵,Version 2是 25 x
    25的矩阵,Version 3是29的尺寸,每增加一个version,就会增加4的尺寸,公式是:(V-1)4 + 21(V是版本号) 最高Version
    40,(40-1)4+21 = 177,所以最高是177 x 177 的正方形。


    二维码的基本结构如下:


    微信二维码,网页打开app,扫一扫


    二维码一般由定位点图案、功能性数据、数据码和纠错码组成,生成的算法是固定的有需要的同学可以了解


    二维码的生成原理
    二维码生成原理解析


    如今,基本上各个语言都有了比较好的二维码生成与解码的开源项目,有需要的同学可以自行google,本次我们呢不做具体介绍,因为不是重点啊 。


    微信二维码揭秘


    微信的二维码有哪些
    在平时的使用中我们可以发现微信在很多的场景中都有二维码的使用在,名片,联系人,支付等尤为明显,可以说二维码已经成为微信不可或缺的设计呢功能了。


    那么微信的二维码到底有哪些是呢?


    以二维码扫描结果和功能区分
    1、http(s)://www.*.com http链接
    2、weixin://qr/××× 微信二维码
    3、http://weixin.qq.com/r/××× 微信二维码名片
    4、https://login.weixin.qq.com/l/××× 网页登陆二维码
    5、https://login.wechatapp.com/l/××× 国际部网页登陆二维码
    6、weixin://wxpay/bizpayurl/××× 微信支付
    7、http://weixin.qq.com/g/××× 微信群二维码


    其实在上面的二维码例子中大体上可以分为两类,1,4,5未一类,其他的为一类。第一类主要是普通类型和涉及登录相关的逻辑,第二类中的逻辑就是我们本次要谈论的逻辑。


    第二类流程如下:


    微信二维码,网页打开app,扫一扫


    实现微信二维码逻辑
    由上面的介绍我们很清楚的知道,我们想要实现上面的功能我们生成的二维码肯定是一个url,然后对本本地是否安装有app的判断也是在服务端实现的(其实就是个js而已,不要怕),当然在客户端也需要对自己的代码做相应的配置。


    客户端配置
    由于本人系Android开发工程师,对ios的了解也不是太多,所以本次配置主要是对android端而言的。


    首先在manifest文件中配置扫描后需要跳转activity的intent-filter


    还需要制定对应的host、pathPrefix、scheme


    至于host、pathPrefix、scheme是什么,大家可以自己去google下,其实只要了解Url的组成原理就ok了。


    服务端返回数据处理
    在对应的Acticity里处理传递回来的参数,并做相应的处理,如微信名片二维码的功能,返回给相应页面用户id,当然这个用户的userId可以是经过加密的(别我问我怎么加密,你们这么加密我也不想知道)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class FromUrlActicity extends AppCompatActivity {
    private TextView tvUserid;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qrcode_acticity);
        tvUserid = (TextView) findViewById(R.id.userid);
        Uri uriData = this.getIntent().getData();
        String userId = uriData.getQueryParameter("userId");
        tvUserid.setText("我是来自服务器的UserId:"+userId);
        }
    }



    扫描二维码
    自己或者使用第三方工具生成二维码如下

    微信二维码,网页打开app,扫一扫



    二维码对应字符串:http:\henu.flyou.ren/scan?userId=553274238
    在手机上使用浏览器扫一扫扫描二维码即可进入如下界面,并获得服务端传来的参数,完成相应的逻辑

    微信二维码,网页打开app,扫一扫



    当然,二维码可以向服务器传递多个数据,服务器也可以向客户端返回多个数据,分别定义获取即可。明白了上述的流程想要实现微信的上述流程也是很容易的。


    后记
    当然,二维码的功能并不仅仅局限于上面的逻辑,二维码可以应用在多个行业和领域,那么快快发动你的才智来发现新的大陆吧。





    展开全文
  • 微信扫一扫支付

    2020-07-21 09:59:33
    微信扫一扫支付,只需要自己注册或在微信平台公众测试号申请测试号,自己注册商户号
  • 这里先大概概述一下主要的流程,首先,使用微信扫一扫需要一个已经通过认证的公众号;其次,需要知道公众号的APPID以及APPSecrect,以便获取Access_Token和Ticket;再有就是需要了解.NET内部的SHA1的加密类;最后...
  • 微信扫一扫登录网站

    千次阅读 2019-04-26 10:22:43
    微信网站扫一扫登录 标签(空格分隔): wechat 科普微信授权原理 Created with Raphaël 2.1.2微信用户微信用户第三方应用第三方应用微信开发平台微信开发平台第三方应用第三方应用微信开发平台微信开发...
  • 调用范例完整代码下载: ... csdn的这个博文写的有点啰嗦,建议移步...在网页上点一个按钮或者链接调用微信扫一扫然后返回结果我们继续处理,很多人应该都会有这样的需求,不过微信对这个空子比较严格,需要你的网页...
  • 最近在做公司的个项目,通过微信或企业微信扫码登录PC管理后台,替代传统的账号、密码登录。 ...看网站应用模块即可,开发技术跟微信开发差不多,这种方式只能是微信扫码,不支持企业微信扫码。
  • 仔细读了遍文档,这个API只是调起了客户端码界面,码成功后返回对应的结果.  微信小程序中并没有提供打开链接的API.那么这个码是做什么用的呢?不可能像我一样个文字玩玩.  想象空间很大啊.  API实在...
  • 在自己的应用中打开微信扫一扫代码: private void toWeChatScan() { try { //利用Intent打开微信 Uri uri = Uri.parse("weixin://dl/scan"); Intent intent = new Intent(Intent.ACTION_VIEW, uri);
  • 微信扫描二维码后无法打开网页

    万次阅读 2019-01-16 18:14:53
    1. 如果是局域网内的网页,手机和电脑必须得连个ip。 (这样才是联通的) 2. 如果是不是局域网,用流量就可以打开。
  • 判断微信和支付宝

    万次阅读 2017-12-13 14:38:57
    //判断微信还是支付宝码 public function haha(){ //获取用户信息 //dump($_SERVER['HTTP_USER_AGENT']); //判断是不是微信 if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false ) {
  • Android调用微信扫一扫

    万次阅读 热门讨论 2016-08-01 11:30:11
    在自己的应用中打开微信扫一扫代码: private void toWeChatScan() { try { //利用Intent打开微信 Uri uri = Uri.parse("weixin://dl/scan"); Intent intent = new Intent(Intent.ACTION_VIE
  • 我是做Java开发,公司有个网站需要用微信做三方登录,这个微信开放平台上都有,但还有个要求是用户码登录之后手机端微信自动跳转到公司的公众号上的篇文章去,其实就是个网页嘛,现在不知道怎么做这个自动跳转...
  • 微信扫描二维码实现自动跳转

    万次阅读 2017-08-15 13:20:45
    如:www.xiangzimomo.cn,用微信扫一扫的功能,只能扫描出www.xiangzimomo.cn连接,需要点击才能完成跳转,如图: 解决方案:只需要将内容改为 http://www.xiangzimomo.cn,既可以完成自动跳转
  • 今天遇到一个问题,做的网站,通过安卓手机微信扫一扫二维码或者识别二维码链接无法跳转,显示白屏,但是ios的微信扫码就没有问题,一开始认为是安卓版微信做了限制,后来分析了下扫码后跳转的链接,发现了这个问题...
  • IOS 调用微信扫码二维码

    千次阅读 2019-09-02 16:37:01
    ios 开发中时常需要调用相关微信功能,码二维码等 1.info.plist 添加白名单 ***LSApplicationQueriesSchemes***,如下图 2.代码实现 if let tmpurl = URL(string: "weixin://scanqrcode"){ ...
  • 微信扫码跳转小程序任意页面------前提:小程序必须上线废话少说直接进入正题:点击进入微信公众平台接口调试工具:https://mp.weixin.qq.com/debug/如以下页面: 填写上线的小程序的APPid 和 Secret 点击检查问题...
  • 最近着手开发了微信网页码登录和公众号授权登录收获颇丰,两者的开发很类似。以下是我个人摸索过程中发现的两者的异同: 两者都可以通过微信客户端码授权的方式,让第三方页面获得微信用户的一些基本信息(昵称...
1 2 3 4 5 ... 20
收藏数 71,573
精华内容 28,629
关键字:

微信扫一扫