2016-03-28 14:47:11 +08:00
|
|
|
|
#coding=utf-8
|
|
|
|
|
class WechatsController < ActionController::Base
|
|
|
|
|
wechat_responder
|
|
|
|
|
|
|
|
|
|
include ApplicationHelper
|
2016-06-22 12:52:26 +08:00
|
|
|
|
# ROOT_URL = "#{Setting.protocol}://#{Setting.host_name}/"
|
|
|
|
|
ROOT_URL = "http://wechat.trustie.net"
|
2016-03-28 14:47:11 +08:00
|
|
|
|
# default text responder when no other match
|
|
|
|
|
on :text do |request, content|
|
2016-06-20 17:26:29 +08:00
|
|
|
|
#邀请码
|
2016-06-24 16:35:27 +08:00
|
|
|
|
sendBindClass(request, {invite_code: content})
|
2016-03-28 14:47:11 +08:00
|
|
|
|
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|
|
2016-06-24 16:35:27 +08:00
|
|
|
|
sendBindClass(request, {ticket: ticket})
|
2016-03-28 14:47:11 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# When no any on :scan responder can match subscribe user scaned scene_id
|
|
|
|
|
on :event, with: 'scan' do |request|
|
|
|
|
|
if request[:EventKey].present?
|
2016-06-24 16:35:27 +08:00
|
|
|
|
sendBindClass(request, {ticket: request[:Ticket]})
|
2016-03-28 14:47:11 +08:00
|
|
|
|
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|
|
2016-06-06 11:13:35 +08:00
|
|
|
|
request.reply.text "如有反馈问题,请直接切换至输入框,发微信给我们即可"
|
2016-03-28 14:47:11 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
on :click, with: 'MY_NEWS' do |request, key|
|
|
|
|
|
default_msg(request)
|
|
|
|
|
end
|
|
|
|
|
|
2016-06-20 17:12:53 +08:00
|
|
|
|
on :click, with: 'JOIN_CLASS' do |request, key|
|
|
|
|
|
uw = user_binded?(request[:FromUserName])
|
|
|
|
|
unless uw
|
|
|
|
|
sendBind(request)
|
|
|
|
|
else
|
2016-06-20 17:26:29 +08:00
|
|
|
|
request.reply.text "请直接回复6位班级邀请码\n(不区分大小写):"
|
2016-06-20 17:12:53 +08:00
|
|
|
|
end
|
2016-06-20 17:04:42 +08:00
|
|
|
|
end
|
|
|
|
|
|
2016-06-24 16:35:27 +08:00
|
|
|
|
|
|
|
|
|
def sendBindClass(request, params)
|
|
|
|
|
begin
|
|
|
|
|
uw = user_binded?(request[:FromUserName])
|
|
|
|
|
if !uw
|
|
|
|
|
return sendBind(request)
|
|
|
|
|
else
|
|
|
|
|
return join_class(params, uw.user, request)
|
|
|
|
|
end
|
|
|
|
|
rescue => e
|
|
|
|
|
logger.error e.inspect
|
|
|
|
|
logger.error e.backtrace.join("\n")
|
|
|
|
|
return request.reply.text e
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2016-03-28 14:47:11 +08:00
|
|
|
|
def default_msg(request)
|
|
|
|
|
uw = user_binded?(request[:FromUserName])
|
|
|
|
|
if uw && uw.user
|
2016-04-08 10:50:05 +08:00
|
|
|
|
request.reply.text "欢迎回来, #{uw.user.show_name}"
|
2016-03-28 14:47:11 +08:00
|
|
|
|
else
|
2016-04-26 09:03:01 +08:00
|
|
|
|
request.reply.text "欢迎关注Trustie创新实践社区"
|
2016-03-28 14:47:11 +08:00
|
|
|
|
sendBind(request)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def sendBind(request)
|
2016-05-26 17:14:52 +08:00
|
|
|
|
news = (1..1).each_with_object([]) { |n, memo| memo << { title: '绑定登录', content: "欢迎使用Trustie创新实践服务平台!
|
|
|
|
|
在这里您可以随时了解您的课程和项目动态,随时点赞和回复。
|
|
|
|
|
我们将会与微信不断结合,为您提供更有价值的服务。
|
|
|
|
|
|
|
|
|
|
您还未绑定确实的用户,请先绑定,谢谢!" } }
|
2016-03-28 14:47:11 +08:00
|
|
|
|
request.reply.news(news) do |article, n, index| # article is return object
|
2016-06-22 12:52:26 +08:00
|
|
|
|
url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{ROOT_URL+'/wechat/user_activities'}&response_type=code&scope=snsapi_base&state=login#wechat_redirect"
|
|
|
|
|
pic_url = "#{ROOT_URL}/images/weixin_pic.jpg"
|
2016-03-28 14:47:11 +08:00
|
|
|
|
article.item title: "#{n[:title]}",
|
|
|
|
|
description: n[:content],
|
2016-05-27 11:07:27 +08:00
|
|
|
|
pic_url: pic_url,
|
2016-03-28 14:47:11 +08:00
|
|
|
|
url: url
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2016-06-24 15:42:00 +08:00
|
|
|
|
def join_class(params, user, request)
|
2016-06-24 14:59:50 +08:00
|
|
|
|
course = nil
|
2016-06-24 15:38:46 +08:00
|
|
|
|
course = Course.where(qrcode: params[:ticket]).first if params[:ticket]
|
|
|
|
|
course = Course.where(invite_code: params[:invite_code]).first if params[:invite_code]
|
|
|
|
|
raise "课程不存在" unless course
|
2016-06-24 14:59:50 +08:00
|
|
|
|
|
2016-06-22 16:42:20 +08:00
|
|
|
|
cs = CoursesService.new
|
2016-06-24 15:40:27 +08:00
|
|
|
|
status = cs.join_course({invite_code: course.invite_code}, user)
|
2016-06-22 16:42:20 +08:00
|
|
|
|
logger.info status
|
2016-06-22 16:57:01 +08:00
|
|
|
|
if status[:state] != 0
|
|
|
|
|
raise CoursesService::JoinCourseError.message(status[:state])
|
|
|
|
|
end
|
2016-06-24 14:59:50 +08:00
|
|
|
|
|
|
|
|
|
news = (1..1).each_with_object([]) { |n, memo| memo << { title: '恭喜您成功加入班级,开始学习吧!',
|
|
|
|
|
content: "课程名称: #{course.name}\n班级名称: #{course.name}\n任课老师: #{course.teacher.show_name}\n进入班级,和小伙伴愉快的学习吧!"} }
|
|
|
|
|
return 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=#{ROOT_URL+'/wechat/user_activities?id='+course.id.to_s}&response_type=code&scope=snsapi_base&state=myclass#wechat_redirect"
|
|
|
|
|
pic_url = "#{ROOT_URL}/images/wechat/class.jpg"
|
|
|
|
|
article.item title: "#{n[:title]}",
|
|
|
|
|
description: n[:content],
|
|
|
|
|
pic_url: pic_url,
|
|
|
|
|
url: url
|
|
|
|
|
end
|
|
|
|
|
|
2016-06-20 17:26:29 +08:00
|
|
|
|
end
|
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
### controller method
|
|
|
|
|
module Controllers
|
2016-06-22 12:11:34 +08:00
|
|
|
|
def get_bind
|
2016-05-26 12:59:15 +08:00
|
|
|
|
begin
|
|
|
|
|
code = params[:code] || session[:wechat_code]
|
|
|
|
|
openid = get_openid_from_code(code)
|
2016-03-28 14:47:11 +08:00
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
raise "无法获取到微信openid" unless openid
|
2016-06-22 12:11:34 +08:00
|
|
|
|
|
|
|
|
|
uw = UserWechat.where(openid: openid).first
|
|
|
|
|
raise "还未绑定trustie帐户" unless uw
|
|
|
|
|
logger.debug "get_bind ============= #{uw}"
|
|
|
|
|
|
|
|
|
|
user = uw.user
|
|
|
|
|
::ApiKey.delete_all(user_id: user.id)
|
|
|
|
|
key = ::ApiKey.create!(user_id: user.id)
|
|
|
|
|
|
|
|
|
|
render :json =>{status: 0, token: key.access_token}
|
2016-05-26 12:59:15 +08:00
|
|
|
|
rescue Exception=>e
|
2016-06-17 18:48:27 +08:00
|
|
|
|
render :json => {status: -1, message: e.message}
|
2016-05-26 12:59:15 +08:00
|
|
|
|
end
|
2016-03-28 14:47:11 +08:00
|
|
|
|
end
|
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
def bind
|
|
|
|
|
begin
|
2016-03-28 14:47:11 +08:00
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
code = params[:code] || session[:wechat_code]
|
|
|
|
|
openid = get_openid_from_code(code)
|
2016-03-28 14:47:11 +08:00
|
|
|
|
|
2016-06-17 18:18:03 +08:00
|
|
|
|
raise "无法获取到openid,请在微信中打开本页面" unless openid
|
2016-05-26 12:59:15 +08:00
|
|
|
|
raise "此微信号已绑定用户, 不能重复绑定" if user_binded?(openid)
|
|
|
|
|
|
|
|
|
|
user, last_login_on = User.try_to_login(params[:username], params[:password])
|
2016-06-07 16:15:25 +08:00
|
|
|
|
raise "用户名或密码错误,请重新输入" unless user
|
2016-05-26 12:59:15 +08:00
|
|
|
|
#补全用户信息
|
2016-03-28 14:47:11 +08:00
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
raise "此用户已经绑定过公众号, 请换一个帐户试试" if user.user_wechat
|
2016-03-28 14:47:11 +08:00
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
UserWechat.create!(
|
|
|
|
|
openid: openid,
|
|
|
|
|
user: user
|
|
|
|
|
)
|
2016-06-02 10:39:11 +08:00
|
|
|
|
ws = WechatService.new
|
|
|
|
|
ws.binding_succ_notice(user.id, "您已成功绑定Trustie平台", user.login, format_time(Time.now))
|
2016-05-26 12:59:15 +08:00
|
|
|
|
render :json => {status:0, msg: "绑定成功"}
|
|
|
|
|
rescue Exception=>e
|
|
|
|
|
render :json => {status: -1, msg: e.message}
|
|
|
|
|
end
|
|
|
|
|
end
|
2016-03-28 14:47:11 +08:00
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
def login
|
|
|
|
|
session[:wechat_code] = params[:code] if params[:code]
|
2016-05-27 22:18:03 +08:00
|
|
|
|
openid = get_openid_from_code(params[:code])
|
2016-05-27 22:14:41 +08:00
|
|
|
|
@wechat_user = user_binded?(openid)
|
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
render 'wechats/login', layout: 'base_wechat'
|
|
|
|
|
end
|
2016-03-28 14:47:11 +08:00
|
|
|
|
|
2016-05-31 19:40:54 +08:00
|
|
|
|
def user_activities
|
2016-06-20 15:21:13 +08:00
|
|
|
|
session[:wechat_code] = params[:code] if params[:code]
|
2016-06-22 12:11:34 +08:00
|
|
|
|
@path = '/'+(params[:state] || '')
|
|
|
|
|
open_id = get_openid_from_code(params[:code]) rescue
|
|
|
|
|
unless open_id
|
|
|
|
|
render 'wechats/open_wechat', layout: nil and return
|
|
|
|
|
end
|
2016-06-24 09:01:12 +08:00
|
|
|
|
if params[:state] == 'myclass'
|
|
|
|
|
@course_id = params[:id];
|
|
|
|
|
end
|
|
|
|
|
|
2016-06-22 12:11:34 +08:00
|
|
|
|
session[:wechat_openid] = open_id
|
2016-06-24 09:01:12 +08:00
|
|
|
|
if params[:code]
|
|
|
|
|
redirect_to "/wechat/user_activities##{@path}?id=#{params[:id]}" and return
|
|
|
|
|
end
|
2016-05-31 20:19:45 +08:00
|
|
|
|
render 'wechats/user_activities', layout: nil
|
2016-05-31 19:40:54 +08:00
|
|
|
|
end
|
|
|
|
|
|
2016-06-22 12:11:34 +08:00
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
private
|
|
|
|
|
def get_openid_from_code(code)
|
2016-06-22 12:11:34 +08:00
|
|
|
|
return 'oCnvgvz8R7QheXE-R9Kkr39j8Ndg' if code =='only-for-test'
|
2016-05-26 12:59:15 +08:00
|
|
|
|
openid = session[:wechat_openid]
|
2016-03-28 14:47:11 +08:00
|
|
|
|
|
2016-05-26 12:59:15 +08:00
|
|
|
|
unless openid
|
|
|
|
|
if code
|
|
|
|
|
openid = wechat.web_access_token(code)["openid"]
|
2016-03-28 14:47:11 +08:00
|
|
|
|
end
|
2016-05-26 12:59:15 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if openid
|
|
|
|
|
session[:wechat_openid] = openid
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return openid
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def user_binded?(openid)
|
|
|
|
|
uw = UserWechat.where(openid: openid).first
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-03-28 14:47:11 +08:00
|
|
|
|
end
|
2016-05-26 12:59:15 +08:00
|
|
|
|
|
2016-05-26 13:02:27 +08:00
|
|
|
|
|
|
|
|
|
include Controllers
|
|
|
|
|
|
2016-03-28 14:47:11 +08:00
|
|
|
|
end
|