socialforge/app/controllers/wechats_controller.rb

570 lines
21 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#coding=utf-8
require 'base64'
class WechatsController < ActionController::Base
wechat_responder
include ApplicationHelper
ROOT_URL = ENV["wechat_url"] || "#{Setting.protocol}://#{Setting.host_name}"
#ROOT_URL = "http://www.trustie.net"
# default text responder when no other match
on :text do |request, content|
#邀请码
# 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群373967360\n我们会认真聆听您的意见和建议。"
# 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|
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?
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
on :click, with: 'DEV' do |request, key|
uw = user_binded?(request[:FromUserName])
unless uw
sendBind(request)
else
request.reply.text "此功能正在开发中,很快就会上线,谢谢!"
end
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|
unBind(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群373967360直接互动。\n3、登录网站www.trustie.net给我们留言。\n\n如您有合作事宜洽谈,请联系:\n王林春 老师\n手机13467631747\nQQ494496321"
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|
# request.reply.text "该功能将在近日开放,敬请期待!"
uw = user_binded?(request[:FromUserName])
unless uw
sendBind(request)
else
request.reply.text "请直接回复6位项目邀请码\n(不区分大小写):"
end
end
on :click, with: 'JOIN_CLASS' do |request, key|
uw = user_binded?(request[:FromUserName])
unless uw
sendBind(request)
else
request.reply.text "请直接回复5位班级邀请码\n(不区分大小写):"
end
end
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]
wl = WechatLog.where("openid = '#{openid}' and request_raw like '%\"Event\":\"click\"%'").order('id desc').first
wl && JSON(wl.request_raw)["EventKey"] == 'JOIN_CLASS'
end
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
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
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
raise "该二维码已失效"
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 unBind(request)
uw = user_binded?(request[:FromUserName])
uw.try(:subscribe!)
end
def sendBind(request)
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
news = (1..1).each_with_object([]) { |n, memo| memo << { title: '绑定登录', content: "欢迎使用Trustie创新实践服务平台
在这里您可以随时了解您的课程和项目动态,随时点赞和回复。交作业、代码提交等更多功能,请前往 www.trustie.net
我们将会与微信不断结合,为您提供更有价值的服务。
您还未绑定确实的用户,请先绑定,谢谢!" } }
request.reply.news(news) do |article, n, index| # article is return object
url = tmpurl
pic_url = "#{ROOT_URL}/images/weixin_pic.jpg"
article.item title: "#{n[:title]}",
description: n[:content],
pic_url: pic_url,
url: url
end
end
def join_class(params, user, request)
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]
raise "班级不存在,请确认您的邀请码是否输入正确,谢谢!" unless course
#取出用户角色类型
role = 10
cs = CoursesService.new
status = cs.join_course({invite_code: course.invite_code}, user)
logger.info status
if status[:state] != 0
raise CoursesService::JoinCourseError.message(status[:state])
end
news = (1..1).each_with_object([]) { |n, memo| memo << { title: '恭喜您成功加入班级,开始学习吧!',
content: "课程名称:#{course.syllabus.title}\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#/class?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
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)
if status != 0
raise ProjectsService::JoinProjectError.message(status)
end
creator = User.find(project.user_id)
news = (1..1).each_with_object([]) { |n, memo| memo << { title: '恭喜您成功加入项目,开始研发吧!',
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"
pic_url = "#{ROOT_URL}/images/wechat/project.jpg"
article.item title: "#{n[:title]}",
description: n[:content],
pic_url: pic_url,
url: url
end
end
### controller method
module Controllers
def get_bind
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
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}
rescue Exception=>e
render :json => {status: -1, message: e.message}
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
def bind
begin
code = params[:code] || session[:wechat_code]
openid = get_openid_from_code(code)
# raise "无法获取到openid请在微信中打开本页面" unless openid
raise "请在微信中关注Trustie创新实践平台后再打开本页面" 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.show_name+"("+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/user_activities', layout: nil
end
def user_activities
@appid = Wechat.config.appid
## sign
@sign_params = wechat.jsapi_ticket.signature(current_url)
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
logger.info "user_activities!!!!!!!!!!!!!!"
logger.info params
#保证下面的redirect_to "/wechat/user_activities##{@path}?id=...不会往下走
if params[:state] == nil
return
end
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")
@path = '/login'
else
if params[:state] == 'myclass'
@course_id = params[:id];
elsif params[:state] == 'myproject'
@project_id = params[:id];
end
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
@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
end
end
end
render 'wechats/user_activities', layout: nil
end
# 用于权限跳转
def auth
state = params[:state]
url = "#{ROOT_URL}/wechat/auth_callback"
authorize_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{url}&response_type=code&scope=snsapi_base&state=#{state}&connect_redirect=1#wechat_redirect"
redirect_to authorize_url
end
def auth_callback
path = Base64.urlsafe_decode64(params[:state])
open_id = get_openid_from_code(params[:code])
unless open_id
render 'wechats/open_wechat', layout: nil and return
end
redirect_to "/wechat/user_activities##{path}"
end
private
def get_openid_from_code(code)
if code =='test'
openid = 'orgVLv8TlS6e7FDiI6xdTGHRaaRo'
session[:wechat_openid] = openid
return openid
end
openid = session[:wechat_openid]
unless openid
if code
#不能联系调两次web_access_token 否则会提示请在微信客户端打开次链接
info = wechat.web_access_token(code)
openid =info["openid"]
access_token =info["access_token"]
if access_token
session[:access_token] = access_token
end
refresh_token = info["refresh_token"]
if refresh_token
session[:refresh_token] = refresh_token
end
end
end
if openid
session[:wechat_openid] = openid
end
return openid
end
## 能进来的就是已关注
## 因为取消订阅的记录被删除了
def user_binded?(openid)
uw = UserWechat.where(openid: openid).first
if uw && uw.bindtype == 0
uw
else
nil
end
end
def current_url
"#{request.protocol}#{request.host_with_port}#{request.fullpath}"
end
end
include Controllers
end