Rails 中的微信 API、命令和消息处理
Wechat is a Chinese multi-purpose messaging, social media and mobile payment app developed by Tencent. It was first released in 2011, and by 2018 it was one of the world's largest standalone mobile apps by monthly active users, with over 1 billion monthly active users (902 million daily active users). (According to wiki)
WeChat gem helps Rails developers integrate WeChat Official Accounts Platform or Wechat mini program easily, including features:
wechat command shares the same API in console, so you can interact with wechat server quickly without starting up web environment/code.
A responder DSL can be used in Rails controller, which gives an event based interface to handle messages sent by end users.
If Wechat OAuth 2.0 is required by your app, omniauth-wechat-oauth2 is recommended in order to apply devise authentication.
If tencent's weui UI style is adoped in your project, gem weui-rails is available for you.
For web page only wechat application, please use wechat_api, which only contains web features, compared with traditional message type wechat_responder.
There is a more complete wechat-starter demo available, which futher includes the payment SDK feature.
Use gem install
gem install "wechat"
# If your ruby version 0.12.4'Run the following command to install it:
bundle installRun the generator:
rails generate wechat:installrails g wechat:install will generate the initial wechat.yml configuration file, including an sample wechat controller and corresponding routes.
Enable session record:
rails g wechat:session
rake db:migrateEnabling session will generate two files in Rails folder, you can add more columns to wechat_session table and add declaration to link to users table, it's also possible to store data directly in hash_store. If you are using PostgreSQL, using hstore/json maybe better, but the best way is to add a dedicated column to record the data (the Rails way).
Using Redis to store wechat token and ticket:
rails g wechat:redis_storeRedis storage supports Rails application running in multiple servers. It is recommended to use default file storage if there is only one single server. Besides that, wechat command won't read token/ticket stored in Redis.
Enable database wechat configurations:
rails g wechat:config
rake db:migrateAfter running the migration, a wechat_configs table will be created that allows storage of multiple wechat accounts.
Make sure to finish all the setup on rails side first, then submit those setting to Tencent wechat management website. Otherwise, wechat will raise error.
URL address for wechat created by running rails g wechat:install is http://your-server.com/wechat
How to setup appid/corpid and secret see below section.
Make sure the record attributes include access_token, token_expires_in, got_token_at.
def client
@client ||= Wechat::Api.new(app_id, app_secret, token_file, network_setting, jsapi_ticket_file, record)
endTo use standalone wechat command, you need to create configuration file ~/.wechat.yml and include content below for public account. The access_token will be written to file /var/tmp/wechat_access_token.
appid: "my_appid"
secret: "my_secret"
access_token: "/var/tmp/wechat_access_token"For enterprise account, you need to use corpid instead of appid as enterprise account supports multiply application (Tencent calls them agents) in one enterprise account. Obtaining the corpsecret is a little bit tricky, must be created at management mode->privilege setting and create any of management group to obtain. Due to Tencent currently only providing Chinese interface for their management console, it's highly recommended you find a colleague knowing Mandarin to help you to obtain the corpsecret.
Windows users need to store .wechat.yml at C:/Users/[user_name]/ (replace with your user name), also pay attention to the direction of folder separator.
corpid: "my_appid"
corpsecret: "my_secret"
agentid: 1 # Integer, which can be obtained from application settings
access_token: "C:/Users/[user_name]/wechat_access_token"Rails configuration file supports different environment similar to database.yml, after running rails generate wechat:install you can find configuration file at config/wechat.yml
Public account configuration example:
default: &default
appid: "app_id"
secret: "app_secret"
token: "app_token"
access_token: "/var/tmp/wechat_access_token"
jsapi_ticket: "/var/tmp/wechat_jsapi_ticket"
production:
appid:
secret:
token:
access_token:
jsapi_ticket:
oauth2_cookie_duration: # seconds
development:
one of the agent application -> Mode selection, select callback mode and get/set.
default: &default corpid: "corpid" corpsecret: "corpsecret" agentid: 1 access_token: "C:/Users/[user_name]/wechat_access_token" token: "" encoding_aes_key: "" jsapi_ticket: "C:/Users/[user_name]/wechat_jsapi_ticket"
production:
corpid:
corpsecret:
agentid:
access_token:
token:
timeout: 30,
skip_verify_ssl: true # not recommend
encoding_aes_key:
jsapi_ticket:
oauth2_cookie_duration:
development:
Close
Configure the `trusted_domain_fullname` if you are in development mode and app is running behind a reverse proxy server, otherwise wechat gem won't be able to get the correct url to be signed later.
#### OAuth2.0 authentication
For public account, code below will get following user's info.
```ruby
class CartController 4, "count"=>4, "data"=>{"openid"=>["oCfEht9***********", "oCfEhtwqa***********", "oCfEht9oMCqGo***********", "oCfEht_81H5o2***********"]}, "next_openid"=>"oCfEht_81H5o2***********"}
$ wechat user "oCfEht9***********"
{"subscribe"=>1, "openid"=>"oCfEht9***********", "nickname"=>"Nickname", "sex"=>1, "language"=>"zh_CN", "city"=>"徐汇", "province"=>"上海", "country"=>"中国", "headimgurl"=>"http://wx.qlogo.cn/mmopen/ajNVdqHZLLBd0SG8NjV3UpXZuiaGGPDcaKHebTKiaTyof*********/0", "subscribe_time"=>1395715239}
$ wechat menu
{"menu"=>{"button"=>[{"type"=>"view", "name"=>"保护的", "url"=>"http://***/protected", "sub_button"=>[]}, {"type"=>"view", "name"=>"公开的", "url"=>"http://***", "sub_button"=>[]}]}}
Running command rails g wechat:menu to generate a menu definition yaml file:
button:
-
name: "Want"
sub_button:
-
type: "scancode_waitmsg"
name: "绑定用餐二维码"
key: "BINDING_QR_CODE"
-
type: "click"
name: "预订午餐"
key: "BOOK_LUNCH"
-
type: "miniprogram"
name: "小程序示例"
url: "http://ericguo.com/"
appid: "wx1234567890"
pagepath: "pages/index"
-
name: "Query"
sub_button:
-
type: "click"
name: "进出记录"
key: "BADGE_IN_OUT"
-
type: "click"
name: "年假余额"
key: "ANNUAL_LEAVE"
-
type: "view"
name: "About"
url: "http://blog.cloud-mes.com/"Running command below to upload the menu:
$ wechat menu_create menu.yamlCaution: make sure you have management privilege for this application, otherwise you will get 60011 error.
Sending custom_news should also be defined as a yaml file, like articles.yml
articles:
-
title: "习近平在布鲁日欧洲学院演讲"
description: "新华网比利时布鲁日 4 月 1 日电 国家主席习近平 1 日在比利时布鲁日欧洲学院发表重要演讲"
url: "http://news.sina.com.cn/c/2014-04-01/232629843387.shtml"
pic_url: "http://i3.sinaimg.cn/dy/c/2014-04-01/1396366518_bYays1.jpg"After that, you can run this command:
$ wechat custom_news oCfEht9oM*********** articles.yml
Sending template message via yaml file is similar, too, define template.yml and content is just the template content.
template:
template_id: "o64KQ62_xxxxxxxxxxxxxxx-Qz-MlNcRKteq8"
url: "http://weixin.qq.com/download"
topcolor: "#FF0000"
data:
first:
value: "Hello, you successfully registered"
color: "#0A0A0A"
keynote1:
value: "5km Health Running"
color: "#CCCCCC"
keynote2:
value: "2014-09-16"
color: "#CCCCCC"
keynote3:
value: "Centry Park, Pudong, Shanghai"
color: "#CCCCCC"
remark:
value: "Welcome back"
color: "#173177"
After that, you can run this command:
$ wechat template_message oCfEht9oM*********** template.ymlIn code:
template = YAML.load(File.read(template_yaml_path))
Wechat.api.template_message_send Wechat::Message.to(openid).template(template["template"])If using wechat_api or wechat_responder in controller, can also use wechat as shortcut (supports multi account):
template = YAML.load(File.read(template_yaml_path))
wechat.template_message_send Wechat::Message.to(openid).template(template["template"])Although user can always access all wechat features via Wechat.api, but it's highly recommended to use wechat directly in the controller. It's not only mandatory required if you plan to support multi-account, it also helps to separate the wechat specific logic from the model layer.
class WechatReportsController news', will match and will get count as as parameter
on :text, with: /^(\d+) news$/ do |request, count|
# Wechat article can only contain max 8 items, large than 8 will be dropped.
news = (1..count.to_i).each_with_object([]) { |n, memo| memo do |message|
message.reply.text "some text"
end
…
ruby
class WechatsController = 1.week.ago
images_path = Rails.root.join("public", "images", "default_help.jpg")
media_id = Wechat.api.media_create("image", images_path)["media_id"]
if session.present? && session.reload
# generate migration: add_column :wechat_sessions, :greating_time, :datetime
session.update(greating_time: Time.current)
end
message.reply.image(media_id)
end
endwechat.responder.after_create data includes request and response .Example:
ActiveSupport::Notifications.subscribe('wechat.responder.after_create') do |name, started, finished, unique_id, data|
WechatLog.create request: data[:request], response: data[:response]
end暂无开放 Issues,或尚未同步最近议题。