node-wechat 微信實踐

node-wechat

從去年開始微信開發愈來愈火了,體如今sdk和h5上(h5若是你們想聽,能夠回覆),這裏就簡單介紹一下sdk開發html

既然是noder,那確定要用nodejs寫,否則會被鄙視的。node

輸入圖片說明

node-webot簡介

node-webot是老樸幾我的建的org,主要開發微信sdk相關的node modulesgit

地址 https://github.com/node-webot/github

  • wechat 微信公共平臺消息接口服務中間件
  • weixin-robot 微信公共賬號自動回覆機器人 A Node.js robot for wechat.
  • wechat-oauth 受權
  • wechat-api Wechat API/主動調用API

wechat sdk開發經常使用包

  • wechat-oauth
  • wechat-api(菜單,消息回覆等)
  • wx_jsapi_sign(js-sdk)

建立菜單

wxapi.jsweb

var API = require('wechat-api');
var config = require('config');

var menu_config = config.get('wx.wx_menu');
var app_id      = config.get('wx.app_id');
var app_secret  = config.get('wx.app_secret');

//配置
var api = new API(app_id, app_secret);

//測試
function app(){
  api.createMenu(menu_config, function(err, result){
    console.log(result);
  });
}

module.exports = app;

把數據放到配置文件中redis

config/default.jsonmongodb

{
  "domain": "xxxxxxxx.com",
  "is_debug": true,
  "mongodb": {
    "host": "127.0.0.1",
    "port": "27017",
    "db": "node-webot"
  },
  "sms": {
    "host": "127.0.0.1",
    "port": "5001"
  },
  "wx": {
    "app_id": "wx04014b02asdsfdsfsf",
    "app_secret": "cc4c224b50fkjlksdafkldfsakljsdfk",
    "wx_menu": {
      "button": [
        {
          "name": "菜單",
          "sub_button": [
            {
              "type": "view",
              "name": "資訊菜單",
              "url": "http://ip:port/all"
            }
          ]
        },
        {
          "name": "菜單2",
          "sub_button": [
            {
              "type": "view",
              "name": "個人11",
              "url": "http://ip:port/all"
            }
          ]
        },
        {
          "name": "助理",
          "sub_button": [
            {
              "type": "view",
              "name": "大學",
              "url": "http://ip:port/all"
            },
            {
              "type": "view",
              "name": "社區",
              "url": "http://ip:port/all"
            }
          ]
        }
      ]
    }
  }
}

oauth

使用微信的用戶,或者綁定微信帳號npm

微信有一個惟一的id是openid,它是辨別的惟一標識。json

routes/weixin.jsapi

// 微信受權和回調
var client = new OAuth(app_id, app_secret);

// 主頁,主要是負責OAuth認真
router.get('/', function(req, res) {
  var url = client.getAuthorizeURL('http://' + domain + '/weixin/callback','','snsapi_userinfo');
  res.redirect(url) 
})

/**
 * 認證受權後回調函數
 *
 * 根據openid判斷是否用戶已經存在
 * - 若是是新用戶,註冊並綁定,而後跳轉到手機號驗證界面
 * - 若是是老用戶,跳轉到主頁
 */
router.get('/callback', function(req, res) {
  console.log('----weixin callback -----')
  var code = req.query.code;
  
  var User = req.model.UserModel;

  client.getAccessToken(code, function (err, result) {
    console.dir(err)
    console.dir(result)
    var accessToken = result.data.access_token;
    var openid = result.data.openid;
    
    console.log('token=' + accessToken);
    console.log('openid=' + openid);

    User.find_by_openid(openid, function(err, user){
      console.log('微信回調後,User.find_by_openid(openid) 返回的user = ' + user)
      if(err || user == null){
        console.log('user is not exist.')
        client.getUser(openid, function (err, result) {
          console.log('use weixin api get user: '+ err)
          console.log(result)
          var oauth_user = result;
          
          var _user = new User(oauth_user);
          _user.username = oauth_user.nickname;
          _user.nickname = oauth_user.nickname;
          
          _user.save(function(err, user) {
            if (err) {
              console.log('User save error ....' + err);
            } else {
              console.log('User save sucess ....' + err);
              req.session.current_user = void 0;
              res.redirect('/user/' + user._id + '/verify');
            }
          });
          
        });
      }else{
        console.log('根據openid查詢,用戶已經存在')
        // if phone_number exist,go home page
        if(user.is_valid == true){
          req.session.current_user = user;
          res.redirect('/mobile')
        }else{
          //if phone_number exist,go to user detail page to fill it
          req.session.current_user = void 0;
          res.redirect('/users/' + user._id + '/verify');
        }
      }
    });
  });
});

上面的簡單介紹一下

wx_jsapi_sign(nodejs)

wx_jsapi_sign = wechat(微信) js-api signature implement.

  • 支持集羣,將得到的前面寫到cache.json裏
  • 使用cache.json保存,好比用redis省事,更省內存
  • 足夠小巧,便於集成

Install

npm install --save wx_jsapi_sign

Usage

copy config file

cp node_modules/wx_jsapi_sign/config.example.js config.js

change appId && appSecret

then mount a route in app.js

var signature = require('wx_jsapi_sign');
var config = require('./config')();

....

app.post('/getsignature', function(req, res){
  var url = req.body.url;
  console.log(url);
  signature.getSignature(config)(url, function(error, result) {
        if (error) {
            res.json({
                'error': error
            });
        } else {
            res.json(result);
        }
    });
});

more usages see test/public/test.html

Test

微信訪問網址 http://yourserver.com:1342/test

原做者博客

http://blog.xinshangshangxin.com/2015/04/22/%E4%BD%BF%E7%94%A8nodejs-%E8%B8%A9%E5%9D%91%E5%BE%AE%E4%BF%A1JS-SDK%E8%AE%B0%E5%BD%95/

我爲何要重寫這個模塊?

微信簽名7200秒能夠查看一次,因此就要考慮緩存問題

  • wx_jsapi_sign是一個開源項目,使用redis做爲緩存,思路挺好,但依賴redis,仍是有點重,不必
  • xinshangshangxin寫的模塊使用cache.json作緩存,而後把獲取的時間保存到配置文件裏,每次請求只要讀取文件便可。這個思路很是好,依賴少,省內存,簡單,支持集羣

那哥們寫的已經很不錯了,可是有幾個問題

  • 他不太瞭解如何寫通用模塊(複用程度比較低)
  • 代碼比較亂(抽取了配置,很好,但想art-template之類的都混在裏面看的人頓時頭大)
  • 沒有發佈到npm上

若是各位想了解是如何作的,請移步http://www.github.com/i5ting/wx_jsapi_sign

  • 依賴管理(區分模塊依賴的,仍是開發階段依賴的)
  • npmjs.org上如何發佈模塊

配置文件實際

上面的微信的菜單,db鏈接,仍是wx_jsapi_sign都是基於配置的,使用配置文件會有一些問題

好比config.json做爲配置文件,你須要在版本控制裏放一個config.example.json,而後把config.json放到.gitinore裏。

而後每一個使用的人,須要先拷貝一個config.example.json爲config.json。

這樣作的好處

  • 敏感信息不能提交上去
  • 部署服務器的時候,不會衝突(好比配置文件裏有一個is_debug選項,服務器上必須是false,而開發階段是要用true的)

另外配置文件格式,推薦json和yaml,而不是js,不要在配置文件了寫邏輯,雖然沒問題,但實爲陋習。

糾正一下價值觀

不少人都認爲如今啥模塊都有了,隨便找一個用就能夠了,但這種想法是危險的

  • 第一件事兒是思考,而不是想找一個隨便xx
  • 不要造重複的輪子,除非必要(先到github或相關網站上找對應模塊,要有能夠修改對應模塊源碼的能力)
  • 反身而誠,樂莫大焉

全文完

歡迎提問,歡迎分享

歡迎關注個人公衆號【node全棧】 node全棧.png

相關文章
相關標籤/搜索