微信开发

微信开发现在用的比较多,大致讲一下微信公众号开发的流程,官方资料可查看微信公众号开发

一:java后台获取微信接口访问权限

1、获取开发公众号的openId(这里需要说明一下,一个用户对应不同的公众号有不同的openId,但是都可以唯一标识)

public String getOpenId(HttpServletRequest httprequest,
        HttpServletResponse response) {
    logger.info("开始获取用户openId");
    String code = httprequest.getParameter("code");
    String openId="";
    if(StringUtils.checkStringEmpty(code)){
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
        HttpRequestUtility httpRequestUtility = new HttpRequestUtility();
        List<NameValuePair> params = new ArrayList<NameValuePair>();            
        params.add(new BasicNameValuePair("appid",
                SysConstantsConfig.WECHAT_APPID));
        params.add(new BasicNameValuePair("secret",
                SysConstantsConfig.WECHAT_APPSECRET)); 
        params.add(new BasicNameValuePair("code",
                code));
        params.add(new BasicNameValuePair("grant_type",
                "authorization_code"));            
        String result = httpRequestUtility.getResponsebyGet(url, params);
        if (StringUtils.checkStringEmpty(result)) {
            String errorCode = JsonUtility.getVauleFromJson("errcode", result);
            String errorMessage = JsonUtility.getVauleFromJson("errmsg", result);
            if (StringUtils.checkStringEmpty(errorCode)
                    && !StringUtils.checkStringEmpty(errorMessage)) {
                logger.info("开始获取用户openId失败,返回错误码为 :" + errorCode
                        + " 错误消息为 :" + errorMessage);
            } else {
                openId = JsonUtility.getVauleFromJson("openid",
                        result);
                logger.info("开始获取用户openId成功,openId  :" + openId);
            }
        }
    }
    return openId;
}

Http请求发送:

public class HttpRequestUtility {
    private static final Logger logger = Logger
            .getLogger(HttpRequestUtility.class);

    public static String getResponsebyGet(String url, List<NameValuePair> params) {
        logger.info("开始执行HttpClient get 请求,请求URL为: "+url);
        String result = "";
        HttpClient httpClient = new DefaultHttpClient();
        // 连接时间
        httpClient.getParams().setParameter(
                CoreConnectionPNames.CONNECTION_TIMEOUT, 3000);
        // 数据传输时间
        httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
                2000);
        // Get请求
        HttpGet httpget = new HttpGet(url);
        try {
            // 设置参数
            String str = EntityUtils.toString(new UrlEncodedFormEntity(params,
                    "UTF-8"));
            httpget.setURI(new URI(httpget.getURI().toString() + "?" + str));
            // 发送请求
            HttpResponse httpResponse = httpClient.execute(httpget);

            int statusCode = httpResponse.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                logger.error("执行HttpClient get 请求报错,statusCode为 : "+statusCode);
            }
            // 获取返回数据
            HttpEntity entity = httpResponse.getEntity();
            String body = EntityUtils.toString(entity, "utf-8");
            result = body;
            if (entity != null) {
                EntityUtils.consume(entity);
            }
        } catch (Exception e) {
        } finally {
            httpClient.getConnectionManager().shutdown();
        }
        logger.info("结束执行HttpClient get 请求,返回结果为: "+result);
        return result;
    }
}

2、获取access_token

/**
 * 动态生成微信API access_token 调用微信提供的接口必须要这个属性
 */
public String getaccessToken() {
    logger.info("开始动态生成access_token");
    String accessToken = "";
    String errorCode = "";
    String errorMessage = "";
    String url = "https://api.weixin.qq.com/cgi-bin/token";
    HttpRequestUtility httpRequestUtility = new HttpRequestUtility();
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("grant_type", "client_credential"));
    params.add(new BasicNameValuePair("appid",
            SysConstantsConfig.WECHAT_APPID));
    params.add(new BasicNameValuePair("secret",
            SysConstantsConfig.WECHAT_APPSECRET));
    String response = httpRequestUtility.getResponsebyGet(url, params);
    if (StringUtils.checkStringEmpty(response)) {
        errorCode = JsonUtility.getVauleFromJson("errcode", response);
        errorMessage = JsonUtility.getVauleFromJson("errmsg", response);
        if (StringUtils.checkStringEmpty(errorCode)
                && !StringUtils.checkStringEmpty(errorMessage)) {
            logger.info("开始动态生成access_token失败,返回错误码为 :" + errorCode
                    + " 错误消息为 :" + errorMessage);
        } else {
            accessToken = JsonUtility.getVauleFromJson("access_token",
                    response);
            logger.info("开始动态生成access_token成功,accessToken  :" + accessToken);
        }
    }
    return accessToken;
}

3、获取jsapi_ticket(jsapi_ticket是公众号用于调用微信JS接口的临时票据)

/**
 * 动态生成微信API jsapi_ticket 调用微信JS提供的接口必须要这个属性
 */
public String getjsapi_ticket(String accessToken) {
    logger.info("开始动态生成jsapi_ticket");
    String ticket = "";
    String errorCode = "";
    String errorMessage = "";
    String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    HttpRequestUtility httpRequestUtility = new HttpRequestUtility();
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("access_token", accessToken));
    params.add(new BasicNameValuePair("type","jsapi"));        
    String response = httpRequestUtility.getResponsebyGet(url, params);
    if (StringUtils.checkStringEmpty(response)) {
        errorCode = JsonUtility.getVauleFromJson("errcode", response);
        errorMessage = JsonUtility.getVauleFromJson("errmsg", response);
        if (StringUtils.checkStringEmpty(errorCode)    &&!"0".equalsIgnoreCase(errorCode)) {
            logger.info("开始动态生成jsapi_ticket失败,返回错误码为 :" + errorCode
                    + " 错误消息为 :" + errorMessage);
        } else {
            ticket = JsonUtility.getVauleFromJson("ticket",response);
            logger.info("开始动态生成jsapi_ticket成功,jsapi_ticket  :" + ticket);
        }
    }
    return ticket;
}

4、JS-SDK权限签名算法(获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了)

签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

注意事项:

1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。

2.签名用的url必须是调用JS接口页面的完整URL。

3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。

/**
 * 获取签名
 * @param ticket
 * @return
 */
public WechatConfig getSingnature(String ticket,String url){
    SHA1 sha1=new SHA1();
    WechatConfig wechatConfig=new WechatConfig();
    String signature="";
    String timestamp = System.currentTimeMillis()/1000+""; //获取时间戳
    String noncestr = getRandomString(16); //获取随机字符串
    signature = "jsapi_ticket="+ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;
    signature = sha1.getDigestOfString(signature.getBytes()); //进行sha1加密
    wechatConfig.setAppid(SysConstantsConfig.WECHAT_APPID);
    wechatConfig.setNonceStr(noncestr);
    wechatConfig.setSignature(signature);
    wechatConfig.setTimestamp(timestamp);
    return wechatConfig;
}

/**
 * 生成随机字符串
 * @param length
 * @return
 */
public static String getRandomString(int length) { //length表示生成字符串的长度
    String base = "abcdefghijklmnopqrstuvwxyz0123456789";   
    Random random = new Random();   
    StringBuffer sb = new StringBuffer();   
    for (int i = 0; i < length; i++) {   
        int number = random.nextInt(base.length());   
        sb.append(base.charAt(number));   
    }   
    return sb.toString();   
} 

二:使用微信接口

1、前台JS调用

var iswechatBrowser;
$(document).ready(function(){
    var ua = window.navigator.userAgent.toLowerCase(); //识别微信浏览器
    if(ua.match(/MicroMessenger/i) == 'micromessenger'){
        iswechatBrowser=true;
    }else{
        iswechatBrowser=false;
    }
    
    if(iswechatBrowser){ //如果是微信浏览器就去配置微信JS接口
        var currenturl = location.href.split('#')[0];
        var sharedTitle = "慧英保险";
        var imageUrl;
        $.ajax({  
            type: "POST",  
            url: getPath()+"/WechatLogin/getWechatJSAccess.do",  
            data:currenturl ,//将对象序列化成JSON字符串  
            dataType:"json",  
            contentType:'application/json;charset=utf-8', //设置请求头信息          
            success: function(data){ 
                var sharedLink = data.sharedLink;
                wx.config({
                    debug: false, 
                    appId: data.appid, // 必填,公众号的唯一标识
                    timestamp:data.timestamp , // 必填,生成签名的时间戳
                    nonceStr: data.nonceStr,   // 必填,生成签名的随机串
                    signature: data.signature.toLowerCase(), // 必填,签名,见附录1
                    jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'] // 必填,需要使用的JS接口列表
                });
                wx.ready(function(){ 
                    //实现JS分享功能
                    wx.onMenuShareTimeline({//1.获取“分享到朋友圈”按钮点击状态及自定义分享内容接口
                        title: sharedTitle, // 分享标题
                        link: sharedLink, // 分享链接
                        imgUrl: imageUrl, // 分享图标
                        success: function () { 
                            // 用户确认分享后执行的回调函数
                        },
                        cancel: function () { 
                            // 用户取消分享后执行的回调函数
                        }
                    });
                    wx.onMenuShareAppMessage({//2.获取“分享给朋友”按钮点击状态及自定义分享内容接口
                        title: sharedTitle, // 分享标题
                        desc: "http://m.quicksure.com/ludiquickSureMobileServer", // 分享描述
                        link: sharedLink, // 分享链接
                        imgUrl: imageUrl, // 分享图标
                        type: '', // 分享类型,music、video或link,不填默认为link
                        dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                        success: function () { 
                            // 用户确认分享后执行的回调函数
                        },
                        cancel: function () { 
                            // 用户取消分享后执行的回调函数
                        }
                    });
                });
            },  
            error: function(res){
                 $("#pop").hide();
                  $("#Message").html("微信登录失败");
                  $('.errorhei').show();
                  $('.beijing').hide();
            }  
        });    
    }
});

注意:wx.ready(function(){

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

});

2、后台生成权限签名

@RequestMapping("/getWechatJSAccess.do")
public @ResponseBody WechatConfig getWechatJSAccess(@RequestBody String url,
        HttpServletRequest httprequest,HttpServletResponse response,ModelMap modelMap){
    logger.info("get URL is:"+url);
    HttpSession session = httprequest.getSession();
    WechatConfig wechatConfig = null;
    String ticket="";
    String token="";
    if(session!=null&&session.getAttribute("token")!=null){
        token=(String) session.getAttribute("token");
        session.setAttribute("token", token);
    }else{
        token=wechatLoginServiceImpl.getaccessToken();
    }
    if(session!=null&&session.getAttribute("ticket")!=null){
        ticket=(String)session.getAttribute("ticket");
    }else{
        if(StringUtils.checkStringEmpty(token)){
            ticket=wechatLoginServiceImpl.getjsapi_ticket(token);
            session.setAttribute("ticket", ticket);        
        }
    }
    if(StringUtils.checkStringEmpty(ticket)){
         wechatConfig = wechatLoginServiceImpl.getSingnature(ticket,url);
    }
    return wechatConfig;
}

 微信链接分享开发可以参考:http://blog.csdn.net/zhengyangzkr/article/details/70187486

posted @ 2017-07-04 16:36  编码龟  阅读(313)  评论(0)    收藏  举报