天天看點

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

WeixinRailsMiddleware

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

安裝: bundle intall

安裝最新的版本

gem 'weixin_rails_middleware'

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

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.rb

config.public_account_class = "PublicAccount"

注意 PublicAccount 是你儲存公衆賬号的Model名字。

檢視線上例子:

https://github.com/lanrion/weixin_rails_middleware_example/blob/master/config/initializers/weixin_rails_middleware.rb#L10

如果使用了第一種場合,則需要跑如下指令:

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

然後執行

rake db:migrate

,生成兩個字段到資料庫。

另外一方面,同時會向你的

app/models/public_accounts.rb

添加一行代碼:

include WeixinRailsMiddleware::AutoGenerateWeixinTokenSecretKey

這行代碼的作用在于自動生成 weixin_secret_key 和 weixin_token 兩個字段的值,建議不要讓使用者去填寫這兩個字段的值,讓程式自動生成,如果你想自己定制weixin_secret_key 和 weixin_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_string 和 weixin_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 %>

則會生成:

即可複制使用到微信伺服器配置中。

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

  private

    def response_text_message(options={})

      reply_text_message("Your Message: #{@keyword}")

    # <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}")

    # <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("回複圖檔資訊")

    # <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("回複連結資訊")

    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"        # 點選菜單跳轉連結時的事件推送

      else

        reply_text_message("處理無法識别的事件")

      end

    # <Format><![CDATA[Format]]></Format>

    def response_voice_message(options={})

      @format   = @weixin_message.Format

      reply_text_message("回複語音資訊: #{@keyword}")

    # <ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>

    def response_video_message(options={})

      # 視訊消息縮略圖的媒體id,可以調用多媒體檔案下載下傳接口拉取資料。

      @thumb_media_id = @weixin_message.ThumbMediaId

      reply_text_message("回複視訊資訊")

    def set_keyword

      @keyword = @weixin_message.Content    || # 文本消息

                 @weixin_message.EventKey   || # 事件推送

                 @weixin_message.Recognition # 接收語音識别結果

    #

http://apidock.com/rails/ActionController/Base/default_url_options

    def default_url_options(options={})

      { weichat_id: @weixin_message.FromUserName }

或者猛擊, 最新以下面連結内容為主:

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