1. 程式人生 > >微信公眾號開發--微信JS-SDK掃一掃功能

微信公眾號開發--微信JS-SDK掃一掃功能

首先請閱讀微信JS-SDK說明文件,瞭解微信JS的相關說明。
根據官方的使用步驟,關鍵的有以下幾步

  1. 繫結域名(很關鍵
  2. 引入JS檔案(很簡單)
  3. 通過config介面注入許可權驗證配置(很重要
  4. 通過ready介面處理成功驗證(還沒用到)
  5. 通過error介面處理失敗驗證(還沒用到)

繫結域名

繫結域名
如果域名繫結有誤,會出現如下錯誤提示
錯誤的域名配置示例:

`http://gwchsk.imwork.net/wechat/order/test.html`

域名配置錯誤的提示資訊:
{“errMsg”:”config:invalid url domain”}

這裡寫圖片描述

所以,域名配置的時候一定要注意
1. 域名不要以http:開頭


2. 域名不要配置到具體的頁面
配置成功的提示如下

這裡寫圖片描述

引入JS檔案

一行程式碼就可以了

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

通過config介面注入許可權驗證配置

這一步非常重要,也是最關鍵的一步,這一部分
先看官方的示例

wx.config({
    debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
    appId: ''
, // 必填,公眾號的唯一標識 timestamp: , // 必填,生成簽名的時間戳 nonceStr: '', // 必填,生成簽名的隨機串 signature: '',// 必填,簽名,見附錄1 jsApiList: [] // 必填,需要使用的JS介面列表,所有JS介面列表見附錄2 });

這裡需要從伺服器端網頁面傳遞的引數有timestamp、nonceStr和signature而appId和jsApiList都是固定的,這裡直接寫在頁面中。

首先,編寫伺服器端程式碼,生成timestampnonceStrsignature
在生成timestamp、nonceStr和signature的時候有兩個引數需要獲取
一個是access_token

,另一個是jsapi_ticket

access_token的獲取需要AppIdAppSecret,獲取地址如下,傳送GET請求

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

得到access_token之後,採用http GET方式請求獲得jsapi_ticket

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

注意,access_token和jsapi_ticket得有效期為7200秒,開發者必須在自己的服務全域性快取

獲得jsapi_ticket之後,就可以生成JS-SDK許可權驗證的簽名了。

簽名演算法

簽名生成規則如下:參與簽名的欄位包括noncestr(隨機字串), 有效的jsapi_ticket, timestamp(時間戳), url(當前網頁的URL,不包含#及其後面部分) 。對所有待簽名引數按照欄位名的ASCII 碼從小到大排序(字典序)後,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字串string1。這裡需要注意的是所有引數名均為小寫字元。對string1作sha1加密,欄位名和欄位值都採用原始值,不進行URL 轉義。

簽名演算法的實現

最難的就是簽名演算法的實現部分,幸好微信給了demo,網上好多人都在找,這裡我把簽名演算法的實現貼出來,程式碼來自微信demo
這裡寫圖片描述
下載地址
java程式碼如下,做了一點點修改

package com.gwc.wechat.utils.wechat;

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;

public class WxJSUtil {
    public static void main(String[] args) {

        // 注意 URL 一定要動態獲取,不能 hardcode
        String url = "http://gwchsk.imwork.net/wechat/order/test.html";
        Map<String, String> ret = sign(url);
        for (Map.Entry entry : ret.entrySet()) {
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    };

    public static Map<String, String> sign(String url) {
        Map<String, String> ret = new HashMap<String, String>();
        //這裡的jsapi_ticket是獲取的jsapi_ticket。
        String jsapi_ticket = JSAPITicketTool.getTicket();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意這裡引數名必須全部小寫,且必須有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                  "&noncestr=" + nonce_str +
                  "&timestamp=" + timestamp +
                  "&url=" + url;
       // System.out.println(string1);

        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", 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);
    }
}

Controller的程式碼

@Controller
@RequestMapping(value = "/order")
public class OrderController {
@RequestMapping(value = "/test.html", method = RequestMethod.GET)
    public String testPage(Model model) {

        String url = Constant.AppURL + "/order/test.html";
        Map<String, String> ret = WxJSUtil.sign(url);
         for (Map.Entry entry : ret.entrySet()) {
                System.out.println(entry.getKey() + "=" + entry.getValue());
                model.addAttribute(entry.getKey().toString(), entry.getValue());
            }
        return "jqueryMobile";
    }
}

在Controller中將如下引數寫進了jsp頁面

    timestamp=1449132293
    nonceStr=fb4eaa58-6d53-40a8-a8fa-7033e9768a8a
    signature=7ad32da3f82cb36492de935a60727d3053d33f4b

其次編寫jsp頁面的程式碼
在jsp頁面中需要將wx.config重的引數進行配置

wx.config({
    debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
    appId: '', // 必填,公眾號的唯一標識
    timestamp: , // 必填,生成簽名的時間戳
    nonceStr: '', // 必填,生成簽名的隨機串
    signature: '',// 必填,簽名,見附錄1
    jsApiList: [] // 必填,需要使用的JS介面列表,所有JS介面列表見附錄2
});

在頁面中讀值

    <input id="timestamp" type="hidden" value="${timestamp}" />
    <input id="noncestr" type="hidden" value="${nonceStr}" />
    <input id="signature" type="hidden" value="${signature}" />

然後賦值

    <script type="text/javascript">
        $(function() {
            var timestamp = $("#timestamp").val();//時間戳
            var nonceStr = $("#noncestr").val();//隨機串
            var signature = $("#signature").val();//簽名
            wx.config({
                debug : true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
                appId : 'wx622ca8545e5c354b', // 必填,公眾號的唯一標識
                timestamp : timestamp, // 必填,生成簽名的時間戳
                nonceStr : nonceStr, // 必填,生成簽名的隨機串
                signature : signature,// 必填,簽名,見附錄1
                jsApiList : [ 'scanQRCode' ]
            // 必填,需要使用的JS介面列表,所有JS介面列表見附錄2
            });
        });
    </script>

寫一個按鈕和輸入框,將掃描的結果放進輸入框

<input id="id_securityCode_input">
<button id="scanQRCode">掃碼</button>

給按鈕繫結事件,並執行微信掃碼

$("#scanQRCode").click(function() {
            wx.scanQRCode({
                // 預設為0,掃描結果由微信處理,1則直接返回掃描結果
                needResult : 1,
                desc : 'scanQRCode desc',
                success : function(res) {
                    //掃碼後獲取結果引數賦值給Input
                    var url = res.resultStr;
                    //商品條形碼,取","後面的
                    if(url.indexOf(",")>=0){
                        var tempArray = url.split(',');
                        var tempNum = tempArray[1];
                        $("#id_securityCode_input").val(tempNum);
                    }else{
                        $("#id_securityCode_input").val(url);
                    }
                }
            });
        });

執行結果如圖
掃一包抽紙

抽紙

掃描結果

放進input

掃網址

這裡寫圖片描述

這裡寫圖片描述

微信JS-SDK中的掃一掃就基本實現了。

參考文獻