socialforge/app/controllers/wechats_controller.rb

535 lines
20 KiB
Ruby
Raw Normal View History

#coding=utf-8
class WechatsController < ActionController::Base
wechat_responder
include ApplicationHelper
2016-06-28 11:33:54 +08:00
ROOT_URL = ENV["wechat_url"] || "#{Setting.protocol}://#{Setting.host_name}"
2016-06-28 11:30:06 +08:00
#ROOT_URL = "http://www.trustie.net"
# default text responder when no other match
on :text do |request, content|
2016-06-20 17:26:29 +08:00
#邀请码
2016-09-14 10:26:18 +08:00
# if join_class_request(request)
# sendBindClass(request, {invite_code: content})
# elsif join_project_request(request)
# sendBindProject(request, {invite_code: content})
# else
request.reply.text "您的意见已收到,非常感谢~ \n更多问题可以通过以下方式联系我们:\n官方QQ群173184401\n我们会认真聆听您的意见和建议。"
2016-09-14 10:26:18 +08:00
# end
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})
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-08-01 15:50:21 +08:00
checkTicket(request, {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
2016-06-24 17:35:55 +08:00
on :click, with: 'DEV' do |request, key|
uw = user_binded?(request[:FromUserName])
unless uw
sendBind(request)
else
request.reply.text "此功能正在开发中,很快就会上线,谢谢!"
end
2016-06-24 17:35:55 +08:00
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 "如有问题反馈,请您:\n1、直接切换至输入框发微信给我们。\n2、加入QQ群173184401我们直接互动。\n欢迎大家积极反馈,谢谢啦!"
end
on :click, with: 'MY_NEWS' do |request, key|
default_msg(request)
end
on :click, with: 'PROJECT' do |request, key|
request.reply.text "该功能将在近日开放,敬请期待!"
end
on :click, with: 'JOIN_PROJECT' do |request, key|
2016-08-01 11:24:27 +08:00
# request.reply.text "该功能将在近日开放,敬请期待!"
uw = user_binded?(request[:FromUserName])
unless uw
sendBind(request)
else
request.reply.text "请直接回复6位项目邀请码\n(不区分大小写):"
end
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)
2016-06-20 17:12:53 +08:00
else
2016-06-27 11:09:25 +08:00
request.reply.text "请直接回复5位班级邀请码\n(不区分大小写):"
2016-06-20 17:12:53 +08:00
end
2016-06-20 17:04:42 +08:00
end
2016-09-05 11:02:34 +08:00
on :click, with: 'UNBIND' do |request, key|
uw = user_binded?(request[:FromUserName])
unless uw
request.reply.text "您还未绑定帐号"
else
#解除绑定
us = UsersService.new
us.wechat_unbind uw
tmpurl = "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&connect_redirect=1#wechat_redirect"
news = (1..1).each_with_object([]) { |n, memo| memo << { title: '重新绑定提醒',
content: "尊敬的用户,您已解除绑定。\n解除时间:#{format_time(Time.now)}\n点击进入重新绑定!"} }
request.reply.news(news) do |article, n, index| # article is return object
url = tmpurl
article.item title: "#{n[:title]}",
description: n[:content],
url: url
end
end
end
def join_class_request(request)
openid = request[:FromUserName]
2016-07-09 10:34:05 +08:00
wl = WechatLog.where("openid = '#{openid}' and request_raw like '%\"Event\":\"click\"%'").order('id desc').first
wl && JSON(wl.request_raw)["EventKey"] == 'JOIN_CLASS'
end
2016-06-24 16:35:27 +08:00
def join_project_request(request)
openid = request[:FromUserName]
wl = WechatLog.where("openid = '#{openid}' and request_raw like '%\"Event\":\"click\"%'").order('id desc').first
wl && JSON(wl.request_raw)["EventKey"] == 'JOIN_PROJECT'
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
def sendBindProject(request, params)
begin
uw = user_binded?(request[:FromUserName])
if !uw
return sendBind(request)
else
return join_project(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-08-01 15:09:36 +08:00
def checkTicket(request,params)
begin
uw = user_binded?(request[:FromUserName])
if !uw
return sendBind(request)
end
course = nil
course = Course.where(qrcode: params[:ticket]).first if params[:ticket]
course = Course.where(invite_code: params[:invite_code]).first if params[:invite_code]
if course
return join_class(params, uw.user, request)
else
project = nil
project = Project.where(qrcode: params[:ticket]).first if params[:ticket]
project = Project.where(invite_code: params[:invite_code]).first if params[:invite_code]
if project
return join_project(params, uw.user, request)
end
end
2016-08-01 15:35:29 +08:00
raise "该二维码已失效"
2016-08-01 15:09:36 +08:00
rescue => e
logger.error e.inspect
logger.error e.backtrace.join("\n")
return request.reply.text e
end
end
def default_msg(request)
uw = user_binded?(request[:FromUserName])
if uw && uw.user
request.reply.text "欢迎回来, #{uw.user.show_name}"
else
sendBind(request)
end
end
def sendBind(request)
2016-08-14 10:28:46 +08:00
tmpurl = "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&connect_redirect=1#wechat_redirect"
logger.info "tmpurl!!!!!!!!!!!!!!"
logger.info tmpurl
2016-05-26 17:14:52 +08:00
news = (1..1).each_with_object([]) { |n, memo| memo << { title: '绑定登录', content: "欢迎使用Trustie创新实践服务平台
" } }
request.reply.news(news) do |article, n, index| # article is return object
2016-08-14 10:28:46 +08:00
url = tmpurl
2016-06-22 12:52:26 +08:00
pic_url = "#{ROOT_URL}/images/weixin_pic.jpg"
article.item title: "#{n[:title]}",
description: n[:content],
2016-05-27 11:07:27 +08:00
pic_url: pic_url,
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]
2016-06-27 11:09:25 +08:00
raise "班级不存在,请确认您的邀请码是否输入正确,谢谢!" unless course
2016-06-24 14:59:50 +08:00
#取出用户角色类型
role = 10
2016-06-22 16:42:20 +08:00
cs = CoursesService.new
2016-07-15 09:48:10 +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: '恭喜您成功加入班级,开始学习吧!',
2016-08-11 10:33:22 +08:00
content: "课程名称:#{course.syllabus.title}\n班级名称:#{course.name}\n任课老师:#{course.teacher.show_name}\n进入班级,和小伙伴愉快的学习吧!"} }
2016-06-24 14:59:50 +08:00
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#/class?id='+course.id.to_s}&response_type=code&scope=snsapi_base&state=myclass#wechat_redirect"
2016-06-24 14:59:50 +08:00
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
def join_project(params, user, request)
project = nil
project = Project.where(qrcode: params[:ticket]).first if params[:ticket]
project = Project.where(invite_code: params[:invite_code]).first if params[:invite_code]
raise "项目不存在,请确认您的邀请码是否输入正确,谢谢!" unless project
#取出用户角色类型
role = 5
ps = ProjectsService.new
status = ps.join_project({role:5, invite_code: project.invite_code}, user)
2016-08-01 15:35:29 +08:00
if status != 0
2016-08-01 11:18:01 +08:00
raise ProjectsService::JoinProjectError.message(status)
end
creator = User.find(project.user_id)
news = (1..1).each_with_object([]) { |n, memo| memo << { title: '恭喜您成功加入项目,开始研发吧!',
2016-08-11 11:00:52 +08:00
content: "项目名称:#{project.name}\n发起人:#{creator.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#/project?id='+project.id.to_s}&response_type=code&scope=snsapi_base&state=myproject#wechat_redirect"
2016-08-01 11:14:03 +08:00
pic_url = "#{ROOT_URL}/images/wechat/project.jpg"
article.item title: "#{n[:title]}",
description: n[:content],
pic_url: pic_url,
url: url
end
end
2016-05-26 12:59:15 +08:00
### controller method
module Controllers
def get_bind
2016-05-26 12:59:15 +08:00
begin
code = params[:code] || session[:wechat_code]
openid = get_openid_from_code(code)
# raise "无法获取到微信openid" unless openid
raise "请在微信中关注Trustie创新实践平台后再打开本页面" unless openid
uw = UserWechat.where(openid: openid).first
2016-08-12 14:41:56 +08:00
raise "还未绑定trustie帐户" unless (uw && uw.bindtype == 0)
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
end
def is_bind
begin
code = params[:code] || session[:wechat_code]
open_id = get_openid_from_code(code)
raise "还未绑定trustie帐户" unless user_binded?(open_id)
render :json => {status: 0}
rescue Exception=>e
render :json => {status: -1, message: e.message}
end
end
2016-05-26 12:59:15 +08:00
def bind
begin
2016-05-26 12:59:15 +08:00
code = params[:code] || session[:wechat_code]
openid = get_openid_from_code(code)
# raise "无法获取到openid请在微信中打开本页面" unless openid
raise "请在微信中关注Trustie创新实践平台后再打开本页面" unless openid
2016-06-27 11:09:25 +08:00
raise "此微信号已绑定用户,不能重复绑定" if user_binded?(openid)
2016-05-26 12:59:15 +08:00
user, last_login_on = User.try_to_login(params[:username], params[:password])
2016-06-27 11:09:25 +08:00
raise "用户名或密码错误,请重新输入" unless user
2016-05-26 12:59:15 +08:00
#补全用户信息
2016-06-27 11:09:25 +08:00
raise "此用户已经绑定过公众号,请换一个帐户试试" if user.user_wechat
2016-05-26 12:59:15 +08:00
UserWechat.create!(
openid: openid,
user: user
)
ws = WechatService.new
2016-08-14 15:25:46 +08:00
ws.binding_succ_notice(user.id, "您已成功绑定Trustie平台", user.show_name+"("+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-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)
render 'wechats/user_activities', layout: nil
2016-05-26 12:59:15 +08:00
end
2016-08-02 17:01:10 +08:00
def user_activities
2016-08-02 17:01:10 +08:00
@appid = Wechat.config.appid
## sign
@sign_params = wechat.jsapi_ticket.signature(current_url)
2016-06-20 15:21:13 +08:00
session[:wechat_code] = params[:code] if params[:code]
@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-08-14 16:20:53 +08:00
logger.info "user_activities!!!!!!!!!!!!!!"
logger.info params
2016-08-22 15:44:20 +08:00
#保证下面的redirect_to "/wechat/user_activities##{@path}?id=...不会往下走
if params[:state] == nil
return
end
2016-08-22 13:52:40 +08:00
unless (user_binded?(open_id) || params[:state] == "invite_code" || params[:state] == "project_invite_code" || params[:state] == "blog_comment" || params[:state] == "course_notice" || params[:state] == "project_discussion" || params[:state] == "course_discussion" || params[:state] == "homework" || params[:state] == "issues" || params[:state] == "journal_for_message")
2016-08-22 15:23:34 +08:00
@path = '/login'
2016-08-22 13:52:40 +08:00
else
if params[:state] == 'myclass'
@course_id = params[:id];
elsif params[:state] == 'myproject'
@project_id = params[:id];
end
2016-06-24 09:01:12 +08:00
session[:wechat_openid] = open_id
if params[:code]
if !(params[:state] == "invite_code" || params[:state] == "project_invite_code" || params[:state] == "blog_comment" || params[:state] == "course_notice" || params[:state] == "project_discussion" || params[:state] == "course_discussion" || params[:state] == "homework" || params[:state] == "issues" || params[:state] == "journal_for_message")
uw = user_binded?(open_id)
if uw
user = uw.user
lastname = user.lastname
end
end
if lastname && lastname == ""
@path = '/edit_userinfo'
else
2016-08-24 09:30:28 +08:00
@path = params[:state].split('/')[0]
useridstr = params[:state].split('/')[1]
if useridstr
redirect_to "/wechat/user_activities##{@path}?id=#{params[:id]}&#{useridstr}" and return
elsif params[:id]
redirect_to "/wechat/user_activities##{@path}?id=#{params[:id]}" and return
else
redirect_to "/wechat/user_activities##{@path}" and return
end
# redirect_to "/wechat/user_activities##{@path}?id=#{params[:id]}" and return
2016-08-12 14:17:50 +08:00
end
end
2016-08-22 13:52:40 +08:00
end
2016-05-31 20:19:45 +08:00
render 'wechats/user_activities', layout: nil
end
2016-05-26 12:59:15 +08:00
private
def get_openid_from_code(code)
return 'oCnvgvz8R7QheXE-R9Kkr39j8Ndg' if code =='only-for-test'
2016-05-26 12:59:15 +08:00
openid = session[:wechat_openid]
unless openid
if code
2016-08-12 14:25:45 +08:00
#不能联系调两次web_access_token 否则会提示请在微信客户端打开次链接
2016-08-12 14:13:53 +08:00
info = wechat.web_access_token(code)
openid =info["openid"]
access_token =info["access_token"]
if access_token
session[:access_token] = access_token
end
2016-08-12 17:30:48 +08:00
refresh_token = info["refresh_token"]
if refresh_token
session[:refresh_token] = refresh_token
end
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
2016-08-14 11:59:26 +08:00
if uw && uw.bindtype == 0
2016-08-14 11:50:31 +08:00
uw
else
nil
end
2016-05-26 12:59:15 +08:00
end
2016-08-02 17:01:10 +08:00
def current_url
"#{request.protocol}#{request.host_with_port}#{request.fullpath}"
end
2016-05-26 12:59:15 +08:00
end
2016-05-26 12:59:15 +08:00
2016-05-26 13:02:27 +08:00
include Controllers
end