今天关注了@miclle 开发的微信公众帐号:「健康一点」
里面有几个很酷的功能碉堡了,但是我不知道如何实现的,希望作者能剧透一下。
我查看了微信的官方文档,view 类型的自定义菜单是 get 请求,按道理无法获得用户的 openid。拿不到 openid 如何展示用户的基本信息?
不知道作者是如何在微信的浏览器中拿到 openid 的。
微信接口里有的,在花了 300 块通过认证后的高级接口里,‘网页授权获取用户基本信息’这里有提到
通过两次跳转后拿到 openid 然后放到 session 中;要注意的是,我没有通过这个接口去拿用户其他的信息 (因为这个需要弹出授权界面),要获取用户其他信息,可以通过‘获取用户基本信息’这个接口异步去做
def authenticate_openid!
# 当session中没有openid时,则为非登录状态
if session[:weixin_openid].blank?
code = params[:code]
# 如果code参数为空,则为认证第一步,重定向到微信认证
if code.nil?
redirect_to "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Weixin::APP_ID}&redirect_uri=#{request.url}&response_type=code&scope=snsapi_base&state=#{request.url}#wechat_redirect"
end
#如果code参数不为空,则认证到第二步,通过code获取openid,并保存到session中
begin
url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{Weixin::APP_ID}&secret=#{Weixin::APP_SECRET}&code=#{code}&grant_type=authorization_code"
session[:weixin_openid] = JSON.parse(URI.parse(url).read)["openid"]
rescue Exception => e
# ...
end
end
session[:weixin_openid]
end
before_filter :authenticate_openid!
正好这几天在公司也做了这个功能,用了 omniauth,封装好了的~ #2 楼 @miclle 的方案适合熟手。 推荐用@blankyao写的这个,这个也写的比较好,第一次用很方便。 https://github.com/blankyao/omniauth-weixin
我的方法是,在自定义按钮上就带了 2 楼获取 code 的地址,这样实际上进入到自己的网站就带了 code,然后 get openid 就行了。我写了个类 https://github.com/SpecialCyCi/WeixinAdvancedInterface/blob/master/lib/weixin_oauth.rb
配置好 appid,secret 后,获取 code 后,调用
openid = WeixinOauth.instance.get_openid(params[:code]) if params[:code]
就行了
楼上各位,使用 cookie 可以吗?下次调用时,直接从 cookie 中拿数据。
cookies[:openid] = @user.openid
最近在用 Tower (https://tower.im), 如果在它们网站通过关注微信号(不是用户授权)实现账户绑定后,在他们公众号里就可以直接登录网站用户界面了(也没用任何授权提示),所以怀疑它们在整个过程中没有用 auth 机制 (有没有 Tower 的开发人员可以解释一下呢?)。 是不是没有开通 300 块的高级接口认证,就完全没有可能通过链接跳转 (VIEW) 实现微信端用户信息与网站用户的关联 (但是 tower 在微信移动客户端无缝对接网站用户又是如何实现的呢)?
自己尝试了一下,虽然后台在用户点击后可以看到用户 openid, 但是没有办法让跳转的 URL 也知道这个 openid 信息。
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[VIEW]]></Event>
<EventKey><![CDATA[www.qq.com]]></EventKey>
</xml>
# 如果code参数为空,则为认证第一步,重定向到微信认证
if code.nil?
redirect_to "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Weixin::APP_ID}&redirect_uri=#{request.url}&response_type=code&scope=snsapi_base&state=#{request.url}#wechat_redirect"
end
这里的 redirect_to 应该用 return,直接用 redirect_to 貌似无法跳转!
# 如果code参数为空,则为认证第一步,重定向到微信认证
if code.nil?
return request_for_code! request.url
end
#24 楼 @miclle 谢邀; @imconfused 微信获取 openid,主要是授权:oauth2。 场景是任何进入 mobile 页面,都获取 openid,在使用 weixin_authorize 的基础下,我是这么干的:
class ApplicationController < ActionController::Base
before_action :invoke_wx_auth
before_action :get_wechat_sns, if: :is_wechat_brower?
private
# 调用微信授权获取openid
def invoke_wx_auth
if params[:state].present? || !is_weixin_request? \
|| session['openid'].present? || session[:user_id].present?
return # 防止进入死循环授权
end
if params["need_wx_auth"].present?
# 生成授权url,再进行跳转
sns_url = $wechat_client.authorize_url(request.url)
redirect_to sns_url and return
end
end
# 在invoke_wx_auth中做了跳转之后,此方法截取
def get_wechat_sns
# params[:state] 这个参数是微信特定参数,所以可以以此来判断授权成功后微信回调。
if session[:openid].blank? && params[:state].present?
sns_info = $wechat_client.get_oauth_access_token(params[:code])
Rails.logger.debug("Weixin oauth2 response: #{sns_info.result}")
# 重复使用相同一个code调用时:
if sns_info.result["errcode"] != "40029"
session[:openid] = sns_info.result["openid"]
end
end
end
end
这里只负责获取微信的 openid,跟用户绑定,我的建议是用户在登录成功、注册功能后,都进行绑定。