competitions
p31729568 5 years ago
parent c52f960832
commit 7125e71563

@ -0,0 +1,34 @@
class Weapps::BaseController < ApplicationController
private
def require_wechat_login!
return if session_unionid.present?
render_error('请先进行微信授权')
end
def weapp_session_key
Wechat::Weapp.session_key(session_openid)
end
def set_weapp_session_key(session_key)
Wechat::Weapp.write_session_key(session_openid, session_key)
end
def session_openid
session[:openid]
end
def set_session_openid(openid)
session[:openid] = openid
end
def session_unionid
session[:unionid]
end
def set_session_unionid(unionid)
session[:unionid] = unionid
end
end

@ -0,0 +1,24 @@
class Weapps::CodeSessionsController < Weapps::BaseController
def create
return render_error('code不能为空') if params[:code].blank?
result = Wechat::Weapp.jscode2session(params[:code])
set_session_openid(result['openid'])
set_weapp_session_key(result['session_key']) # weapp session_key写入缓存 后续解密需要
# 已授权,绑定过账号
open_user = OpenUser::Wechat.find_by(uid: result['unionid'])
if open_user.present? && open_user.user
set_session_unionid(result['unionid'])
successful_authentication(open_user.user)
else
# 新用户
user_info = Wechat::Weapp.decrypt(result['session_key'], params[:encrypted_data], params[:iv])
set_session_unionid(user_info['unionId'])
end
render_ok(openid: result['openid'])
end
end

@ -0,0 +1,63 @@
class Weapps::RegistersController < Weapps::BaseController
before_action :require_wechat_login!
def create
# 查询验证码是否正确;type只可能是1或者8
type = phone_mail_type(params[:login].strip)
code = params[:code].strip
if type == 1
uid_logger("start register by phone: type is #{type}")
pre = 'p'
email = nil
phone = params[:login]
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
else
uid_logger("start register by email: type is #{type}")
pre = 'm'
email = params[:login]
phone = nil
verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
end
uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
# todo 上线前请删除万能验证码"513231"
unless code == "513231" && request.subdomain == "test-newweb"
return render_error('验证码不正确') if verifi_code.try(:code) != code.strip
return render_error('验证码已失效') if !verifi_code&.effective?
end
login = User.generate_login(pre)
@user = User.new(admin: false, login: login, mail: email, phone: phone, type: 'User')
@user.password = params[:password]
# 现在因为是验证码,所以在注册的时候就可以激活
@user.activate
# 必须要用save操作密码的保存是在users中
ActiveRecord::Base.transaction do
@user.save!
UserExtension.create!(user_id: @user.id)
# 绑定微信号
OpenUsers::Wechat.create!(user: @user, uid: session_unionid)
# 注册完成手机号或邮箱想可以奖励500金币
RewardGradeService.call(
@user,
container_id: @user.id,
container_type: pre == 'p' ? 'Phone' : 'Mail',
score: 500
)
end
successful_authentication(@user)
session[:user_id] = @user.id
render_ok
end
private
# 1 手机类型0 邮箱类型
# 注意新版的login是自动名生成的
def phone_mail_type value
value =~ /^1\d{10}$/ ? 1 : 0
end
end

@ -0,0 +1,24 @@
class Weapps::SessionsController < Weapps::BaseController
before_action :require_wechat_login!
def create
return render_error('重复登录') if current_user.present? && current_user.logged?
user = User.try_to_login(params[:login], params[:password])
return render_error('错误的账号或密码') if user.blank?
return render_error('违反平台使用规范,账号已被锁定') if user.locked?
return render_error('错误的账号或密码') unless user.check_password?(params[:password].to_s)
if user.wechat_open_user && user.wechat_open_user.uid != session_unionid
render_error('该账号已被其它微信号绑定')
return
end
# 绑定微信号
OpenUsers::Wechat.create!(user: user, uid: session_unionid) if user.wechat_open_user.blank?
successful_authentication(user)
render_ok
end
end

@ -0,0 +1,8 @@
class Weapps::VerifiesController < Weapps::BaseController
before_action :require_wechat_login!
def create
valid = Wechat::Weapp.verify?(session_openid, params[:verify_string], params[:signature])
render_ok(valid: valid)
end
end

@ -1,4 +1,4 @@
class Wechat::App
class Wechat::Weapp
class << self
attr_accessor :appid, :secret
@ -7,5 +7,41 @@ class Wechat::App
def client
@_client ||= Wechat::Client.new(appid, secret)
end
def session_key(openid)
Rails.cache.read(session_key_cache_key(openid))
end
def write_session_key(openid, session_key)
Rails.cache.write(session_key_cache_key(openid), session_key)
end
def verify?(openid, str, signature)
session_key = session_key(openid)
Digest::SHA1.hexdigest("#{str}#{session_key}") == signature
end
def decrypt(session_key, encrypted_data, iv)
session_key = Base64.decode64(session_key)
encrypted_data = Base64.decode64(encrypted_data)
iv = Base64.decode64(iv)
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.decrypt
cipher.padding = 0
cipher.key = session_key
cipher.iv = iv
data = cipher.update(encrypted_data) << cipher.final
result = JSON.parse(data[0...-data.last.ord])
raise Wechat::Error, '解密错误' if result.dig('watermark', 'appid') != appid
result
end
private
def session_key_cache_key(openid)
"weapp:#{appid}:#{openid}:session_key"
end
end
end

@ -18,6 +18,9 @@ defaults: &defaults
wechat:
appid: 'test'
secret: 'test'
weapp:
appid: 'test'
secret: 'test'
development:
<<: *defaults

@ -1,9 +1,12 @@
wechat_config = {}
weapp_config = {}
begin
config = Rails.application.config_for(:configuration)
wechat_config = config['wechat']
weapp_config = config['weapp']
raise 'wechat config missing' if wechat_config.blank?
raise 'weapp config missing' if weapp_config.blank?
rescue => ex
raise ex if Rails.env.production?
@ -12,5 +15,10 @@ rescue => ex
wechat_config = {}
end
# 网站应用
Wechat::OfficialAccount.appid = wechat_config['appid']
Wechat::OfficialAccount.secret = wechat_config['secret']
# 小程序
Wechat::Weapp.appid = weapp_config['appid']
Wechat::Weapp.secret = weapp_config['secret']

@ -829,6 +829,13 @@ Rails.application.routes.draw do
get '/auth/qq/callback', to: 'oauth/qq#create'
get '/auth/wechat/callback', to: 'oauth/wechat#create'
resource :bind_user, only: [:create]
namespace :weapps do
resource :session, only: [:create]
resource :register, only: [:create]
resource :code_session, only: [:create]
resource :verify, only: [:create]
end
end
namespace :admins do

Loading…
Cancel
Save