weixin_rails_middleware 基於 Rails 10分鐘跑起一個微信應用

WeixinRailsMiddleware,顧名思義,是供 Rails 使用的微信中間件。幫助你方便地在 Rails 應用中添加微信功能。html

安裝: bundle intall

安裝最新的版本git

gem 'weixin_rails_middleware'

或者安裝master最新的代碼庫更新,注意:可能不穩定github

gem 'weixin_rails_middleware', git: "https://github.com/lanrion/weixin_rails_middleware.git"

執行 rails generate weixin_rails_middleware:install, 會生成:數據庫

  • config/initializers/weixin_rails_middleware.rb
  • app/decorators/controllers/weixin_rails_middleware/weixin_controller_decorator.rb

適用場合

第一種場合:支持多個公衆帳號,相似微盟的狀況:

前往 config/initializers/weixin_rails_middleware.rbsegmentfault

config.public_account_class = "PublicAccount"

注意 PublicAccount 是你保存公衆帳號的Model名字。api

查看在線例子:https://github.com/lanrion/weixin_rails_middleware_example/blob/master/config/initializers/weixin_rails_middleware.rb#L10安全

若是使用了第一種場合,則須要跑以下命令:ruby

rails generate weixin_rails_middleware:migration public_account_model_name

例子:rails generate weixin_rails_middleware:migration PublicAccount服務器

會生成以下的Migration:微信

class AddWeixinSecretKeyAndWeixinTokenToPublicAccounts < ActiveRecord::Migration
  def self.up
    change_table(:public_accounts) do |t|
      t.string :weixin_secret_key
      t.string :weixin_token
    end
    add_index :public_accounts, :weixin_secret_key
    add_index :public_accounts, :weixin_token
  end

  def self.down
    # By default, we don't want to make any assumption about how to roll back a migration when your
    # model already existed. Please edit below which fields you would like to remove in this migration.
    raise ActiveRecord::IrreversibleMigration
  end
end

而後執行 rake db:migrate,生成兩個字段到數據庫。

另一方面,同時會向你的 app/models/public_accounts.rb 添加一行代碼:

include WeixinRailsMiddleware::AutoGenerateWeixinTokenSecretKey

這行代碼的做用在於自動生成 weixin_secret_keyweixin_token 兩個字段的值,建議不要讓用戶去填寫這兩個字段的值,讓程序自動生成,若是你想本身定製weixin_secret_keyweixin_token 兩個字段的值,刪除include WeixinRailsMiddleware::AutoGenerateWeixinTokenSecretKey 這行代碼便可。

查看在線例子:https://github.com/lanrion/weixin_rails_middleware_example/blob/master/db/migrate/20140324070325_add_weixin_secret_key_and_weixin_token_to_users.rb

第二種場合:只支持我的公衆帳號,即不須要把公衆帳號保存到數據庫中:

前往 config/initializers/weixin_rails_middleware.rb

config.weixin_token_string  = 'c06a2a40256fdeb47ff0c7cc'
config.weixin_secret_string = 'J92Eba24yRpG-s9LGYOA03FcnULHYFYs'
  • weixin_token_string: 微信Token值;

  • weixin_secret_string: 微信服務URL配置中,此值用來避免真正使用的Token值暴露在URL上,提升安全性。

默認狀況下,在生成 weixin_rails_middleware.rb時,會使用SecureRandom自動生成 weixin_token_stringweixin_secret_string 的值

因此上述的例子,會生成以下的方案:

URL:http://2e13a461.ngrok.com/weixin/J92Eba24yRpG-s9LGYOA03FcnULHYFYs
Token:c06a2a40256fdeb47ff0c7cc

路由

  • 生成微信服務器URL
weixin_engine.weixin_server_url(public_account.weixin_secret_key)
  • 舉個生成微信服務URL與Token的例子:

@public_account 是你保存的其中一個公衆帳號的實例:

網站的地址爲: http://2e13a461.ngrok.com

weixin_secret_key 的值爲 J92Eba24yRpG-s9LGYOA03FcnULHYFYs

weixin_token 的值爲 c06a2a40256fdeb47ff0c7cc

則在app/views/public_accounts/show.html.erb中:

URL:<%= weixin_engine.weixin_server_url(@public_account.weixin_secret_key) %>
Token:<%= @public_account.weixin_token %>

則會生成:

URL:http://2e13a461.ngrok.com/weixin/J92Eba24yRpG-s9LGYOA03FcnULHYFYs
Token:c06a2a40256fdeb47ff0c7cc

便可複製使用到微信服務器配置中。

查看在線例子:https://github.com/lanrion/weixin_rails_middleware_example/blob/master/app/views/users/index.html.erb#L16

配置注意事項

注意: 第一種場合和第二種場合,只能任選一種,若是兩種同時配置,會默認使用第二種場合。

業務邏輯實現

前往

app/decorators/controllers/weixin_rails_middleware/weixin_controller_decorator.rb

即爲:

# encoding: utf-8
# 1: get weixin xml params
# @weixin_message
# 2: public_account_class instance if you setup, otherwise return nil
# @weixin_public_account
WeixinRailsMiddleware::WeixinController.class_eval do
  before_filter :set_keyword, only: :reply

  def reply
    render xml: send("response_#{@weixin_message.MsgType}_message", {})
  end

  private

    def response_text_message(options={})
      reply_text_message("Your Message: #{@keyword}")
    end

    # <Location_X>23.134521</Location_X>
    # <Location_Y>113.358803</Location_Y>
    # <Scale>20</Scale>
    # <Label><![CDATA[位置信息]]></Label>
    def response_location_message(options={})
      @lx    = @weixin_message.Location_X
      @ly    = @weixin_message.Location_Y
      @scale = @weixin_message.Scale
      @label = @weixin_message.Label
      reply_text_message("Your Location: #{@lx}, #{@ly}, #{@scale}, #{@label}")
    end

    # <PicUrl><![CDATA[this is a url]]></PicUrl>
    # <MediaId><![CDATA[media_id]]></MediaId>
    def response_image_message(options={})
      @pic_url  = @weixin_message.PicUrl
      @media_id = @weixin_message.MediaId # 能夠調用多媒體文件下載接口拉取數據。
      reply_text_message("回覆圖片信息")
    end

    # <Title><![CDATA[公衆平臺官網連接]]></Title>
    # <Description><![CDATA[公衆平臺官網連接]]></Description>
    # <Url><![CDATA[url]]></Url>
    def response_link_message(options={})
      @title = @weixin_message.Title
      @desc  = @weixin_message.Description
      @url   = @weixin_message.Url
      reply_text_message("回覆連接信息")
    end

    def response_event_message(options={})
      event_type = @weixin_message.Event
      case event_type
      when "subscribe"   # 關注公衆帳號
        if @keyword.present?
          # 掃描帶參數二維碼事件: 1. 用戶未關注時,進行關注後的事件推送
          return reply_text_message("掃描帶參數二維碼事件: 1. 用戶未關注時,進行關注後的事件推送, keyword: #{@keyword}")
        end
        reply_text_message("關注公衆帳號")
      when "unsubscribe" # 取消關注
        reply_text_message("取消關注")
      when "SCAN"        # 掃描帶參數二維碼事件: 2用戶已關注時的事件推送
        reply_text_message("掃描帶參數二維碼事件: 2用戶已關注時的事件推送, keyword: #{@keyword}")
      when "LOCATION"    # 上報地理位置事件
        @lat = @weixin_message.Latitude
        @lgt = @weixin_message.Longitude
        @precision = @weixin_message.Precision
        reply_text_message("Your Location: #{@lat}, #{@lgt}, #{@precision}")
      when "CLICK"       # 點擊菜單拉取消息時的事件推送
        reply_text_message("你點擊了: #{@keyword}")
      when "VIEW"        # 點擊菜單跳轉連接時的事件推送
        reply_text_message("你點擊了: #{@keyword}")
      else
        reply_text_message("處理沒法識別的事件")
      end

    end

    # <MediaId><![CDATA[media_id]]></MediaId>
    # <Format><![CDATA[Format]]></Format>
    def response_voice_message(options={})
      @media_id = @weixin_message.MediaId # 能夠調用多媒體文件下載接口拉取數據。
      @format   = @weixin_message.Format
      reply_text_message("回覆語音信息: #{@keyword}")
    end

    # <MediaId><![CDATA[media_id]]></MediaId>
    # <ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
    def response_video_message(options={})
      @media_id = @weixin_message.MediaId # 能夠調用多媒體文件下載接口拉取數據。
      # 視頻消息縮略圖的媒體id,能夠調用多媒體文件下載接口拉取數據。
      @thumb_media_id = @weixin_message.ThumbMediaId
      reply_text_message("回覆視頻信息")
    end

    def set_keyword
      @keyword = @weixin_message.Content    || # 文本消息
                 @weixin_message.EventKey   || # 事件推送
                 @weixin_message.Recognition # 接收語音識別結果
    end

    # http://apidock.com/rails/ActionController/Base/default_url_options
    def default_url_options(options={})
      { weichat_id: @weixin_message.FromUserName }
    end
end

或者猛擊, 最新如下面連接內容爲主: https://github.com/lanrion/weixin_rails_middleware/blob/master/lib/generators/templates/weixin_controller.rb
裏面已經作好了微信全部信息類型的邏輯判斷,請再結合微信開發文檔來使用。

項目主頁

https://github.com/lanrion/weixin_rails_middleware

做者介紹

做者 lanrion,目前專一於雲計算中,Paas 平臺 Cloud Foundry,分佈式架構,數據庫。少許業餘時間會嘗試作一些產品。

喜歡鑽牛角尖的傢伙,喜歡研究亂七八糟的東西。有任何有關 Ruby and Rails、微信開發、PHP、Java、Nodejs的問題,均可以發郵件一塊兒探討。微信號:dht_ruby


編輯 SegmentFault

相關文章
相關標籤/搜索