鍍金池/ 教程/ Java/ Java 微信公眾平臺(tái)開發(fā)(十三)--微信 JSSDK 中 Config 配置
Java 微信公眾平臺(tái)開發(fā)(八)--多媒體消息回復(fù)
Java 微信公眾平臺(tái)開發(fā)(四)--回復(fù)消息的分類及實(shí)體的創(chuàng)建
Mybatis 工具 Generator
Java 微信公眾平臺(tái)開發(fā)(十一)--開發(fā)中微信公眾平臺(tái)/開放平臺(tái)/商戶平臺(tái)的關(guān)聯(lián)
微信開發(fā)準(zhǔn)備(二)--springmvc+mybatis 項(xiàng)目結(jié)構(gòu)的搭建
 Java 微信公眾平臺(tái)開發(fā)(十二)--微信用戶信息的獲取
Java 微信公眾平臺(tái)開發(fā)(十五)--微信 JSSDK 的使用
微信開發(fā)準(zhǔn)備(三)--框架以及工具的基本使用
Java 微信公眾平臺(tái)開發(fā)(十三)--微信 JSSDK 中 Config 配置
Java 微信公眾平臺(tái)開發(fā)(一)--接入微信公眾平臺(tái)
Java 微信公眾平臺(tái)開發(fā)(十四)【番外篇】--微信 web 開發(fā)者工具使用
Java 微信公眾平臺(tái)開發(fā)【番外篇】(七)--公眾平臺(tái)測(cè)試帳號(hào)的申請(qǐng)
微信開發(fā)準(zhǔn)備(一)--Maven 倉(cāng)庫(kù)管理新建 WEB 項(xiàng)目
Java 微信公眾平臺(tái)開發(fā)(三)--接收消息的分類及實(shí)體的創(chuàng)建
Java 微信公眾平臺(tái)開發(fā)(九)--關(guān)鍵字回復(fù)以及客服接口實(shí)現(xiàn)(該公眾號(hào)暫時(shí)無(wú)法提供服務(wù)解決方案)
微信開發(fā)準(zhǔn)備(四)--nat123 內(nèi)網(wǎng)地址公網(wǎng)映射實(shí)現(xiàn)
Java 微信公眾平臺(tái)開發(fā)(五)--文本及圖文消息回復(fù)的實(shí)現(xiàn)
Java 微信公眾平臺(tái)開發(fā)(十)--微信自定義菜單的創(chuàng)建實(shí)現(xiàn)
Java 微信公眾平臺(tái)開發(fā)(六)--微信開發(fā)中的 token 獲取
Java 微信公眾平臺(tái)開發(fā)(二)--微信服務(wù)器 post 消息體的接收

Java 微信公眾平臺(tái)開發(fā)(十三)--微信 JSSDK 中 Config 配置

前端開發(fā)工程師和關(guān)注前端開發(fā)的開發(fā)者們?cè)?2015 年中肯定被騰訊的 JSSDk 引爆過(guò),搞 APP 的、搞前端的甚至是是搞后端的都跑過(guò)來(lái)湊熱鬧,一時(shí)之間也把微信 JSSDK 捧得特別牛逼,但是在我們的技術(shù)眼里它的實(shí)現(xiàn)原理和根本是不能夠被改變的,這篇文章就不對(duì)其 js 的實(shí)現(xiàn)做任何評(píng)價(jià)和解說(shuō)了(因?yàn)槲乙膊皇呛芏?,哈哈),這里要說(shuō)的是它的 config 配置實(shí)現(xiàn),參考文檔:http://mp.weixin.qq.com/wiki/11/74ad127cc054f6b80759c40f77ec03db.html

微信 JS-SDK 是微信公眾平臺(tái)面向網(wǎng)頁(yè)開發(fā)者提供的基于微信內(nèi)的網(wǎng)頁(yè)開發(fā)工具包,通過(guò)使用微信 JS-SDK,網(wǎng)頁(yè)開發(fā)者可借助微信高效地使用拍照、選圖、語(yǔ)音、位置等手機(jī)系統(tǒng)的能力,同時(shí)可以直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,為微信用戶提供更優(yōu)質(zhì)的網(wǎng)頁(yè)體驗(yàn);本篇將面向網(wǎng)頁(yè)開發(fā)者介紹微信 JS-SDK 如何使用及相關(guān)注意事項(xiàng)!JSSDK 使用步驟:

步驟一:在微信公眾平臺(tái)綁定安全域名 步驟二:后端接口實(shí)現(xiàn) JS-SDK 配置需要的參數(shù) 步驟三:頁(yè)面實(shí)現(xiàn) JS-SDk 中 config 的注入配置,并實(shí)現(xiàn)對(duì)成功和失敗的處理

(一)在微信公眾平臺(tái)綁定安全域名

先登錄微信公眾平臺(tái)進(jìn)入“公眾號(hào)設(shè)置”的“功能設(shè)置”里填寫“JS 接口安全域名”(如下圖),如果需要使用支付類接口,需要確保支付目錄在支付的安全域名下,否則將無(wú)法完成支付?。ㄗⅲ旱卿浐罂稍凇伴_發(fā)者中心”查看對(duì)應(yīng)的接口權(quán)限)

http://wiki.jikexueyuan.com/project/java-wechat/images/43.png" alt="" />

(二)后端接口實(shí)現(xiàn) JS-SDK 配置需要的參數(shù)

wx.config({
    debug: true, // 開啟調(diào)試模式,調(diào)用的所有 api 的返回值會(huì)在客戶端 alert 出來(lái),若要查看傳入的參數(shù),可以在 pc 端打開,參數(shù)信息會(huì)通過(guò) log 打出,僅在 pc 端時(shí)才會(huì)打印。
    appId: '', // 必填,公眾號(hào)的唯一標(biāo)識(shí)
    timestamp: , // 必填,生成簽名的時(shí)間戳
    nonceStr: '', // 必填,生成簽名的隨機(jī)串
    signature: '',// 必填,簽名,見附錄 1
    jsApiList: [] // 必填,需要使用的 JS 接口列表,所有 JS 接口列表見附錄 2
});

我們查看 js-sdk 的配置文檔和以上的代碼可以發(fā)現(xiàn) config 的配置需要 4 個(gè)必不可少的參數(shù) appId、timestamp、nonceStr、signature,這里的 signature 就是我們生成的簽名!

生成簽名之前必須先了解一下 jsapi_ticket,jsapi_ticket 是公眾號(hào)用于調(diào)用微信 JS 接口的臨時(shí)票據(jù)。正常情況下,jsapi_ticket 的有效期為 7200 秒,通過(guò) access_token 來(lái)獲取。由于獲取 jsapi_ticket 的 api 調(diào)用次數(shù)非常有限,頻繁刷新 jsapi_ticket 會(huì)導(dǎo)致 api 調(diào)用受限,影響自身業(yè)務(wù),開發(fā)者必須在自己的服務(wù)全局緩存 jsapi_ticket ,所以這里我們將 jsapi_ticket 的獲取放到定時(shí)任務(wù)中,因?yàn)樗?token 的生命周期是一致的,所以在這里我們將他們放到一起,將原有的定時(shí)任務(wù)中獲取 token 的代碼做如下修改:

package com.cuiyongzhi.wechat.common;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import net.sf.json.JSONObject;

import com.cuiyongzhi.web.util.GlobalConstants;
import com.cuiyongzhi.wechat.util.HttpUtils;

/**
 * ClassName: WeChatTask
 * @Description: 微信兩小時(shí)定時(shí)任務(wù)體
 * @author dapengniao
 * @date 2016 年 3 月 10 日 下午 1:42:29
 */
public class WeChatTask {
    /**
     * @Description: 任務(wù)執(zhí)行體
     * @param @throws Exception
     * @author dapengniao
     * @date 2016 年 3 月 10 日 下午 2:04:37
     */
    public void getToken_getTicket() throws Exception {
        Map<String, String> params = new HashMap<String, String>();
        //獲取 token 執(zhí)行體
        params.put("grant_type", "client_credential");
        params.put("appid", GlobalConstants.getInterfaceUrl("appid"));
        params.put("secret", GlobalConstants.getInterfaceUrl("AppSecret"));
        String jstoken = HttpUtils.sendGet(
                GlobalConstants.getInterfaceUrl("tokenUrl"), params);
        String access_token = JSONObject.fromObject(jstoken).getString(
                "access_token"); // 獲取到 token 并賦值保存
        GlobalConstants.interfaceUrlProperties.put("access_token", access_token);

        //獲取 jsticket 的執(zhí)行體
        params.clear();
        params.put("access_token", access_token);
        params.put("type", "jsapi");
        String jsticket = HttpUtils.sendGet(
                GlobalConstants.getInterfaceUrl("ticketUrl"), params);
        String jsapi_ticket = JSONObject.fromObject(jsticket).getString(
                "ticket"); 
        GlobalConstants.interfaceUrlProperties
        .put("jsapi_ticket", jsapi_ticket); // 獲取到 js-SDK 的 ticket 并賦值保存

        System.out.println("jsapi_ticket================================================" + jsapi_ticket);
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"token 為=============================="+access_token);

    }

}

然后我們根據(jù)【JS-SDK 使用權(quán)限簽名算法】對(duì)參數(shù)進(jìn)行簽名得到 signature,這里的 url 必須采用前端傳遞到后端,因?yàn)槊看蔚?url 會(huì)有所變化,如下:

package com.cuiyongzhi.wechat.common;

import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.UUID;
import com.cuiyongzhi.web.util.GlobalConstants;

/**
 * ClassName: JSSDK_Config
 * @Description: 用戶微信前端頁(yè)面的 jssdk 配置使用
 * @author dapengniao
 * @date 2016 年 3 月 19 日 下午 3:53:23
 */
public class JSSDK_Config {

    /**
     * @Description: 前端 jssdk 頁(yè)面配置需要用到的配置參數(shù)
     * @param @return hashmap {appid,timestamp,nonceStr,signature}
     * @param @throws Exception   
     * @author dapengniao
     * @date 2016 年 3 月 19 日 下午 3:53:23
     */
    public static HashMap<String, String> jsSDK_Sign(String url) throws Exception {
        String nonce_str = create_nonce_str();
        String timestamp=GlobalConstants.getInterfaceUrl("timestamp");
        String jsapi_ticket=GlobalConstants.getInterfaceUrl("jsapi_ticket");
        // 注意這里參數(shù)名必須全部小寫,且必須有序
        String  string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str
                + "&timestamp=" + timestamp  + "&url=" + url;
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(string1.getBytes("UTF-8"));
        String signature = byteToHex(crypt.digest());
        HashMap<String, String> jssdk=new HashMap<String, String>();
        jssdk.put("appId", GlobalConstants.getInterfaceUrl("appid"));
        jssdk.put("timestamp", timestamp);
        jssdk.put("nonceStr", nonce_str);
        jssdk.put("signature", signature);
        return jssdk;

    }

    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();
    }

}

然后我們將后端簽名的方法集成到 Controller 層,形成代碼如下:

package com.cuiyongzhi.wechat.controller;

import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.cuiyongzhi.Message;
import com.cuiyongzhi.wechat.common.JSSDK_Config;

/**
 * ClassName: WeChatController
 * @Description: 前端用戶微信配置獲取
 * @author dapengniao
 * @date 2016 年 3 月 19 日 下午 5:57:36
 */
@Controller
@RequestMapping("/wechatconfig")
public class WeChatController {

    /**
     * @Description: 前端獲取微信 JSSDK 的配置參數(shù)
     * @param @param response
     * @param @param request
     * @param @param url
     * @param @throws Exception
     * @author dapengniao
     * @date 2016 年 3 月 19 日 下午 5:57:52
     */
    @RequestMapping("jssdk")
    public Message JSSDK_config(
            @RequestParam(value = "url", required = true) String url) {
        try {
            System.out.println(url);
            Map<String, String> configMap = JSSDK_Config.jsSDK_Sign(url);
            return Message.success(configMap);
        } catch (Exception e) {
            return Message.error();
        }

    }

}

到這里我們后端對(duì) jssdk 的簽名參數(shù)的封裝就基本完成了,下一步就只需要我們前端調(diào)用就可以了!

(三)頁(yè)面實(shí)現(xiàn) JS-SDk 中 config 的注入配置,并實(shí)現(xiàn)對(duì)成功和失敗的處理

在第二步中我們將后端接口代碼完成了,這里新建 jssdkconfig.jsp,在 jsp 頁(yè)面用 ajax 方式獲取并進(jìn)行配置,并開啟 debug 模式,打開之后就可以看到配置是否成功的提示,簡(jiǎn)單代碼如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width" />
<title>JSSDk 配置</title>
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
    function jssdk() {
        $.ajax({
            url : "http://wechat.cuiyongzhi.com/wechatconfig/jssdk",
            type : 'post',
            dataType : 'json',
            contentType : "application/x-www-form-urlencoded; charset=utf-8",
            data : {
                'url' : location.href.split('#')[0]
            },
            success : function(data) {
                wx.config({
                    debug : true,
                    appId : data.data.appId,
                    timestamp : data.data.timestamp,
                    nonceStr : data.data.nonceStr,
                    signature : data.data.signature,
                    jsApiList : [ 'checkJsApi', 'onMenuShareTimeline',
                            'onMenuShareAppMessage', 'onMenuShareQQ',
                            'onMenuShareWeibo', 'hideMenuItems',
                            'showMenuItems', 'hideAllNonBaseMenuItem',
                            'showAllNonBaseMenuItem', 'translateVoice',
                            'startRecord', 'stopRecord', 'onRecordEnd',
                            'playVoice', 'pauseVoice', 'stopVoice',
                            'uploadVoice', 'downloadVoice', 'chooseImage',
                            'previewImage', 'uploadImage', 'downloadImage',
                            'getNetworkType', 'openLocation', 'getLocation',
                            'hideOptionMenu', 'showOptionMenu', 'closeWindow',
                            'scanQRCode', 'chooseWXPay',
                            'openProductSpecificView', 'addCard', 'chooseCard',
                            'openCard' ]
                });
            }
        });
    }

    function isWeiXin5() {
        var ua = window.navigator.userAgent.toLowerCase();
        var reg = /MicroMessenger\/[5-9]/i;
        return reg.test(ua);
    }

    window.onload = function() {
        //     if (isWeiXin5() == false) {
        //           alert("您的微信版本低于 5.0,無(wú)法使用微信支付功能,請(qǐng)先升級(jí)!");
        //         }
        jssdk();
    };
</script>
</head>
<body>
</body>
</html>

最后我們運(yùn)行代碼,查看運(yùn)行結(jié)果:

http://wiki.jikexueyuan.com/project/java-wechat/images/44.png" alt="" />

如果提示是這樣,那么標(biāo)識(shí)我們的配置是成功的,那么到這里微信 jssdk 的配置就基本完成了,下一篇講述【微信 web 開發(fā)者工具】的使用,歡迎你的翻閱,如有疑問(wèn)可以留言討論!