Skip to content

Instantly share code, notes, and snippets.

@Lupeipei
Last active April 14, 2018 09:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lupeipei/d8fcb48b588c2c0fb217052baa482eed to your computer and use it in GitHub Desktop.
Save Lupeipei/d8fcb48b588c2c0fb217052baa482eed to your computer and use it in GitHub Desktop.
rails对接微信后完成手机验证
<script src="http:res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<%= wechat_config_js debug: false, api: %w(closeWindow) -%>
<style>
.disappear {
display: none;
}
</style>
<% unless @user.errors.empty? %>
<div id="error_dialog">
<div class="weui-mask"></div>
<div class="weui-dialog">
<div class="weui-dialog__hd"><strong class="weui-dialog__title">Demo</strong></div>
<ul>
<% @user.errors.messages.values.flatten.each do |error| %>
<div class="weui-dialog__bd"><%= error %></div>
<% end %>
</ul>
<div class="weui-dialog__ft">
<a href="" id="error_dialog_button" class="weui-dialog__btn weui-dialog__btn_primary">确定</a>
</div>
</div>
</div>
<% end %>
<div class="weui-msg">
<div class="weui-msg__text-area">
<h1 class="weui-msg__title">会员登录</h1>
</div>
</div>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<div class="weui-cells_title">&nbsp;&nbsp;&nbsp;&nbsp;请输入您的手机号,绑定会员</div>
<div class="weui-cells weui-cells_form">
<div class="weui-cell weui-cell_vcode" style="height: 45px;">
<div class="weui-cell__hd">
<%= f.label :手机号, class: 'weui-label' %>
</div>
<div class="weui-cell__bd weui-cell_primary">
<%= f.text_field :phone, class: 'weui-input',id: 'user_cellphone',type: "tel", placeholder: '请输入手机号' %>
</div>
<div class="weui-cell__ft">
<input type="button" style="background: none; border: none " value="获取验证码" class="weui-vcode-btn" id="token_btn">获取验证码</input>
</div>
</div>
<div class="weui-cell weui-cell_vcode" style="height: 45px;">
<div class="weui-cell__hd">
<%= f.label :验证码, class: 'weui-label' %>
</div>
<div class="weui-cell__bd weui-cell_primary">
<%= f.text_field :token, class:"weui-input", type: "number", placeholder: "请输入验证码" %>
</div>
</div>
</div>
<label for="weuiAgree" class="weui-agree">
<input id="weuiAgree" type="checkbox" checked="checked" class="weui-agree__checkbox">
<span class="weui-agree__text">
获得您的公开信息(昵称,头像等)
</span>
</label>
<div class="weui-btn-area">
<%= f.submit "确认", class: 'weui-btn weui-btn_primary' %>
<a href="javascript:wx.closeWindow();" class="weui-btn weui-btn_plain-default">关闭</a>
</div>
<% end %>
<%= content_for :javascripts do %>
<script>
(function(){
//手机验证码
var CELLPHONE_RE = /^1[3|4|5|6|7|8][0-9]{9}$/;
var token_wait = 60, token_interval;
var $token_btn = $('#token_btn');
$token_btn.click(function () {
var $this = $(this), cellphone = $('#user_cellphone').val();
$.ajax({
url: "/phone_tokens?phone=" + cellphone,
method: 'post',
beforeSend: function () {
if (!CELLPHONE_RE.test(cellphone)) {
$("#messages").text("手机号码格式错误,请重填!");
$("#alert_message").show();
$('#user_cellphone').val("");
return false;
}
$this.attr('value',"已发送").prop('disabled', true);
},
success: function (data) {
if (data.status == 'error') {
alert(data.message);
$token_btn.attr('value','获取验证码').prop('disabled', false);
}else if(data.status == 'repeated'){
$("#messages").text("您的手机号已经验证过,无需验证");
$("#alert_message").show();
}else
{
$token_btn.attr('value','已发送').prop('disabled', true);
$this.trigger('start_token_timer');
}
}
})
})
.on('start_token_timer', function () {
token_interval = setInterval(function () {
$token_btn.trigger('token_timer');
}, 1000);
})
.on('token_timer', function () {
token_wait--;
if (token_wait <= 0) {
clearInterval(token_interval);
$token_btn.attr('value','获取验证码').prop('disabled', false);
token_wait = 60;
} else {
$token_btn.attr('value','重新发送 ' + token_wait + ' 秒').prop('disabled', true);
}
})
})()
</script>
<% end %>
<div style="display: none;" id="alert_message">
<div class="weui-mask"></div>
<div class="weui-dialog">
<div class="weui-dialog__hd"><strong class="weui-dialog__title">Demo</strong></div>
<div class="weui-dialog__bd" id="messages">提醒信息</div>
<div class="weui-dialog__ft">
<a href="" id="alert_message_button" class="weui-dialog__btn weui-dialog__btn_primary">确定</a>
</div>
</div>
</div>
<script>
$("#error_dialog_button").click(function() {
$("#error_dialog").addClass('disappear');
});
$("#alert_message_button").click(function() {
$("#alert_message").addClass('disappear');
});
</script>
class PhoneToken < ApplicationRecord
validates_presence_of :token
validates_presence_of :phone
def self.add_or_update(phone, token)
record = find_by(phone: phone)
if record
record.update_attributes token: token, expired_at: Time.now + 10.minutes
else
create phone: phone, token: token, expired_at: Time.now + 10.minutes
end
end
end
require_relative '../../lib/sms'
class PhoneTokensController < ApplicationController
before_action :verify_phone_unrepeated
def create
unless params[:phone] =~ User::CELLPHONE_RE
render json: {status: 'error', message: '手机号格式不正确!'}
return
end
if session[:token_created_at] && session[:token_created_at] + 60 > Time.now.to_i
render json: {status: 'error', message: '您已经申请过验证码,请60s后再试!'}
return
end
token = sms_send(params[:phone])
PhoneToken.add_or_update params[:phone], token
session[:token_created_at] = Time.now.to_i
render json: {status: 'ok'}
end
private
def verify_phone_unrepeated
phone = User.find_by(phone: params[:phone])
render :json => { status: 'repeated'} if phone.present?
end
end
module Send
module Sms
def sms_send(phone)
template_code = "your template code"
code = rand(100000..999999)
template_param = {"code" => code.to_s}.to_json
Aliyun::Sms.send(phone, template_code, template_param)
code
end
end
end
class Object
include Send::Sms
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
attr_accessor :token
CELLPHONE_RE = /^1[3|4|5|6|7|8][0-9]{9}$/
before_validation :set_password
validates_presence_of :phone
validate :validate_phone, on: :create
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_initialize do |user|
user.nickname = auth.info.nickname
user.sex = auth.info.sex
user.avatar = auth.info.headimgurl
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session['devise.wechat_data']
user.provider = data['provider']
user.uid = data['uid']
user.nickname = data['info']['nickname']
user.sex = data['info']['sex']
user.avatar = data['info']['headimgurl']
end
end
end
def email_required?
false
end
def is_member?
Customer.find_by(phone: phone).present?
end
private
def set_password
self.password ||= Devise.friendly_token[0, 20]
end
def validate_phone
if phone.nil?
errors.add :base, '手机号不能为空'
elsif !PhoneToken.find_by(phone: phone, token: token)
errors.add :phone, '手机验证码不正确或者已过期'
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment