|  |  | #coding=utf-8
 | 
						
						
						
							|  |  | class WechatsController < ActionController::Base
 | 
						
						
						
							|  |  |   wechat_responder
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   include ApplicationHelper
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # default text responder when no other match
 | 
						
						
						
							|  |  |   on :text do |request, content|
 | 
						
						
						
							|  |  |     request.reply.text "您的意见已收到,感谢您的反馈!" # Just echo
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When receive 'help', will trigger this responder
 | 
						
						
						
							|  |  |   on :text, with: 'help' do |request|
 | 
						
						
						
							|  |  |     request.reply.text 'help content'
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When receive '<n>news', will match and will got count as <n> as parameter
 | 
						
						
						
							|  |  |   on :text, with: /^(\d+) news$/ do |request, count|
 | 
						
						
						
							|  |  |     # Wechat article can only contain max 10 items, large than 10 will dropped.
 | 
						
						
						
							|  |  |     news = (1..count.to_i).each_with_object([]) { |n, memo| memo << { title: 'News title', content: "No. #{n} news content" } }
 | 
						
						
						
							|  |  |     request.reply.news(news) do |article, n, index| # article is return object
 | 
						
						
						
							|  |  |       article.item title: "#{index} #{n[:title]}", description: n[:content], pic_url: 'http://www.baidu.com/img/bdlogo.gif', url: 'http://www.baidu.com/'
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   on :event, with: 'subscribe' do |request|
 | 
						
						
						
							|  |  |     default_msg(request)
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When unsubscribe user scan qrcode qrscene_xxxxxx to subscribe in public account
 | 
						
						
						
							|  |  |   # notice user will subscribe public account at same time, so wechat won't trigger subscribe event any more
 | 
						
						
						
							|  |  |   on :scan, with: 'qrscene_xxxxxx' do |request, ticket|
 | 
						
						
						
							|  |  |     request.reply.text "Unsubscribe user #{request[:FromUserName]} Ticket #{ticket}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When subscribe user scan scene_id in public account
 | 
						
						
						
							|  |  |   on :scan, with: 'scene_id' do |request, ticket|
 | 
						
						
						
							|  |  |     request.reply.text "Subscribe user #{request[:FromUserName]} Ticket #{ticket}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When no any on :scan responder can match subscribe user scaned scene_id
 | 
						
						
						
							|  |  |   on :event, with: 'scan' do |request|
 | 
						
						
						
							|  |  |     if request[:EventKey].present?
 | 
						
						
						
							|  |  |       request.reply.text "event scan got EventKey #{request[:EventKey]} Ticket #{request[:Ticket]}"
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When enterprise user press menu BINDING_QR_CODE and success to scan bar code
 | 
						
						
						
							|  |  |   on :scan, with: 'BINDING_QR_CODE' do |request, scan_result, scan_type|
 | 
						
						
						
							|  |  |     request.reply.text "User #{request[:FromUserName]} ScanResult #{scan_result} ScanType #{scan_type}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # Except QR code, wechat can also scan CODE_39 bar code in enterprise account
 | 
						
						
						
							|  |  |   on :scan, with: 'BINDING_BARCODE' do |message, scan_result|
 | 
						
						
						
							|  |  |     if scan_result.start_with? 'CODE_39,'
 | 
						
						
						
							|  |  |       message.reply.text "User: #{message[:FromUserName]} scan barcode, result is #{scan_result.split(',')[1]}"
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When user click the menu button
 | 
						
						
						
							|  |  |   on :click, with: 'BOOK_LUNCH' do |request, key|
 | 
						
						
						
							|  |  |     request.reply.text "User: #{request[:FromUserName]} click #{key}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When user view URL in the menu button
 | 
						
						
						
							|  |  |   on :view, with: 'http://wechat.somewhere.com/view_url' do |request, view|
 | 
						
						
						
							|  |  |     request.reply.text "#{request[:FromUserName]} view #{view}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When user sent the imsage
 | 
						
						
						
							|  |  |   on :image do |request|
 | 
						
						
						
							|  |  |     request.reply.image(request[:MediaId]) # Echo the sent image to user
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When user sent the voice
 | 
						
						
						
							|  |  |   on :voice do |request|
 | 
						
						
						
							|  |  |     request.reply.voice(request[:MediaId]) # Echo the sent voice to user
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When user sent the video
 | 
						
						
						
							|  |  |   on :video do |request|
 | 
						
						
						
							|  |  |     nickname = wechat.user(request[:FromUserName])['nickname'] # Call wechat api to get sender nickname
 | 
						
						
						
							|  |  |     request.reply.video(request[:MediaId], title: 'Echo', description: "Got #{nickname} sent video") # Echo the sent video to user
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When user sent location
 | 
						
						
						
							|  |  |   on :location do |request|
 | 
						
						
						
							|  |  |     request.reply.text("Latitude: #{message[:Latitude]} Longitude: #{message[:Longitude]} Precision: #{message[:Precision]}")
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   on :event, with: 'unsubscribe' do |request|
 | 
						
						
						
							|  |  |     request.reply.success # user can not receive this message
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When user enter the app / agent app
 | 
						
						
						
							|  |  |   on :event, with: 'enter_agent' do |request|
 | 
						
						
						
							|  |  |     request.reply.text "#{request[:FromUserName]} enter agent app now"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When batch job create/update user (incremental) finished.
 | 
						
						
						
							|  |  |   on :batch_job, with: 'sync_user' do |request, batch_job|
 | 
						
						
						
							|  |  |     request.reply.text "sync_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When batch job replace user (full sync) finished.
 | 
						
						
						
							|  |  |   on :batch_job, with: 'replace_user' do |request, batch_job|
 | 
						
						
						
							|  |  |     request.reply.text "replace_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When batch job invent user finished.
 | 
						
						
						
							|  |  |   on :batch_job, with: 'invite_user' do |request, batch_job|
 | 
						
						
						
							|  |  |     request.reply.text "invite_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # When batch job replace department (full sync) finished.
 | 
						
						
						
							|  |  |   on :batch_job, with: 'replace_party' do |request, batch_job|
 | 
						
						
						
							|  |  |     request.reply.text "replace_party job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # Any not match above will fail to below
 | 
						
						
						
							|  |  |   on :fallback, respond: 'fallback message'
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   on :click, with: 'FEEDBACK' do |request, key|
 | 
						
						
						
							|  |  |     request.reply.text "如有反馈问题,请直接切换至输入框,发微信给我们即可"
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   on :click, with: 'MY_NEWS' do |request, key|
 | 
						
						
						
							|  |  |     default_msg(request)
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   def default_msg(request)
 | 
						
						
						
							|  |  |     uw = user_binded?(request[:FromUserName])
 | 
						
						
						
							|  |  |     if uw && uw.user
 | 
						
						
						
							|  |  |       request.reply.text "欢迎回来, #{uw.user.show_name}"
 | 
						
						
						
							|  |  |     else
 | 
						
						
						
							|  |  |       request.reply.text "欢迎关注Trustie创新实践社区"
 | 
						
						
						
							|  |  |       sendBind(request)
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   def sendBind(request)
 | 
						
						
						
							|  |  |     news = (1..1).each_with_object([]) { |n, memo| memo << { title: '绑定登录', content: "欢迎使用Trustie创新实践服务平台!
 | 
						
						
						
							|  |  | 在这里您可以随时了解您的课程和项目动态,随时点赞和回复。
 | 
						
						
						
							|  |  | 我们将会与微信不断结合,为您提供更有价值的服务。
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 您还未绑定确实的用户,请先绑定,谢谢!" } }
 | 
						
						
						
							|  |  |     request.reply.news(news) do |article, n, index| # article is return object
 | 
						
						
						
							|  |  |       url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{login_wechat_url}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"
 | 
						
						
						
							|  |  |       pic_url = "#{Setting.protocol}://#{Setting.host_name}/images/weixin_pic.jpg"
 | 
						
						
						
							|  |  |       article.item title: "#{n[:title]}",
 | 
						
						
						
							|  |  |                    description: n[:content],
 | 
						
						
						
							|  |  |                    pic_url: pic_url,
 | 
						
						
						
							|  |  |                    url: url
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   ###  controller method
 | 
						
						
						
							|  |  |   module Controllers
 | 
						
						
						
							|  |  |     def get_open_id
 | 
						
						
						
							|  |  |       begin
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         code = params[:code] || session[:wechat_code]
 | 
						
						
						
							|  |  |         openid = get_openid_from_code(code)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         raise "无法获取到微信openid" unless openid
 | 
						
						
						
							|  |  |         render :json => {status:0, openid: openid}
 | 
						
						
						
							|  |  |       rescue Exception=>e
 | 
						
						
						
							|  |  |         render :json => {status: -1, msg: e.message}
 | 
						
						
						
							|  |  |       end
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     def bind
 | 
						
						
						
							|  |  |       begin
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         code = params[:code] || session[:wechat_code]
 | 
						
						
						
							|  |  |         openid = get_openid_from_code(code)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         raise "无法获取到openid" unless openid
 | 
						
						
						
							|  |  |         raise "此微信号已绑定用户, 不能重复绑定" if user_binded?(openid)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         user, last_login_on = User.try_to_login(params[:username], params[:password])
 | 
						
						
						
							|  |  |         raise "用户名或密码错误,请重新输入" unless user
 | 
						
						
						
							|  |  |         #补全用户信息
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         raise "此用户已经绑定过公众号, 请换一个帐户试试" if user.user_wechat
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         UserWechat.create!(
 | 
						
						
						
							|  |  |             openid: openid,
 | 
						
						
						
							|  |  |             user: user
 | 
						
						
						
							|  |  |         )
 | 
						
						
						
							|  |  |         ws = WechatService.new
 | 
						
						
						
							|  |  |         ws.binding_succ_notice(user.id, "您已成功绑定Trustie平台", user.login, format_time(Time.now))
 | 
						
						
						
							|  |  |         render :json => {status:0, msg: "绑定成功"}
 | 
						
						
						
							|  |  |       rescue Exception=>e
 | 
						
						
						
							|  |  |         render :json => {status: -1, msg: e.message}
 | 
						
						
						
							|  |  |       end
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     def login
 | 
						
						
						
							|  |  |       session[:wechat_code] = params[:code] if params[:code]
 | 
						
						
						
							|  |  |       openid = get_openid_from_code(params[:code])
 | 
						
						
						
							|  |  |       @wechat_user = user_binded?(openid)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |       render 'wechats/login', layout: 'base_wechat'
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     def user_activities
 | 
						
						
						
							|  |  |       session[:wechat_code] = params[:code] if params[:code]
 | 
						
						
						
							|  |  |       code = params[:code] || session[:wechat_code]
 | 
						
						
						
							|  |  |       openid = get_openid_from_code(code)
 | 
						
						
						
							|  |  |       @wechat_user = user_binded?(openid)
 | 
						
						
						
							|  |  |       unless @wechat_user
 | 
						
						
						
							|  |  |         redirect_to login_wechat_path
 | 
						
						
						
							|  |  |         return
 | 
						
						
						
							|  |  |       end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |       render 'wechats/user_activities', layout: nil
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     private
 | 
						
						
						
							|  |  |     def get_openid_from_code(code)
 | 
						
						
						
							|  |  |       openid = session[:wechat_openid]
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |       unless openid
 | 
						
						
						
							|  |  |         if code
 | 
						
						
						
							|  |  |           openid = wechat.web_access_token(code)["openid"]
 | 
						
						
						
							|  |  |         end
 | 
						
						
						
							|  |  |       end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |       if openid
 | 
						
						
						
							|  |  |         session[:wechat_openid] = openid
 | 
						
						
						
							|  |  |       end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |       return openid
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     def user_binded?(openid)
 | 
						
						
						
							|  |  |       uw = UserWechat.where(openid: openid).first
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   include Controllers
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | end
 |