Current section

Files

Jump to
ex_wechat lib wechat plugs wechat_website.ex
Raw

lib/wechat/plugs/wechat_website.ex

defmodule Wechat.Plugs.WechatWebsite do
@moduledoc """
Plug use for wechat site. A lot helper method.
"""
import Plug.Conn
alias Wechat.Http
@open_endpoint "https://open.weixin.qq.com"
@open_path "/connect/oauth2/authorize"
@api_endpoint "https://api.weixin.qq.com"
@api_path "/sns/oauth2/access_token"
@userinfo_path "/sns/userinfo"
def init(options) do
options
|> Keyword.put_new(:scope, "snsapi_base")
end
def call(conn, options) do
if conn |> fetch_session |> get_session(:openid) do
conn
else
case conn do
%Plug.Conn{params: %{"code" => code}} ->
get_wechat_info(conn, code, options)
_ ->
scope = options[:scope] || "snsapi_base"
conn
|> put_resp_header("location", request_code_url(conn, scope, options))
|> send_resp(302, "redirect")
|> halt
end
end
end
def state do
"ex_wechat_state"
end
defp get_wechat_info(conn, code, options) do
wechat_site_case = Application.get_env(:ex_wechat, :wechat_site_case)
callback = &Http.parse_wechat_site/1
result =
cond do
is_function(wechat_site_case) ->
wechat_site_case.()
true ->
Http.get(request_auth_opts(code, options), callback)
end
if options[:scope] == "snsapi_base" do
conn
|> assign(:wechat_result, result)
|> put_session(:openid, result.openid)
else
options = [url: userinfo_url(), params: [access_token: result.access_token,
openid: result.openid, lang: "zh_CN"]]
conn
|> assign(:wechat_result, Http.get(options, callback))
|> put_session(:openid, result.openid)
end
after
Application.delete_env(:ex_wechat, :wechat_site_case)
end
defp request_auth_opts(code, options) do
api = options[:api] || Wechat.Api
appid = apply(api, :appid, [])
secret = apply(api, :secret, [])
[url: api_url(), params: [appid: appid, secret: secret,
code: code, grant_type: "authorization_code"]]
end
defp request_code_url(conn, scope, options) do
current_path = current_path(conn)
host = options[:host] || raise "You did not set the host."
api = options[:api] || Wechat.Api
module = options[:state] || __MODULE__
url = host <> current_path
appid = apply(api, :appid, [])
state = apply(module, :state, [])
"#{open_url()}?appid=#{appid}&redirect_uri=#{redirect_uri(url)}" <>
"&response_type=code&scope=#{scope}&state=#{state}#wechat_redirect"
end
# Phoenix 1.3
# we should use Phoenix.Controller.current_path
defp current_path(%Plug.Conn{query_params: params} = conn) do
current_path(conn, params)
end
defp current_path(%Plug.Conn{} = conn, params) when params == %{} do
conn.request_path
end
defp current_path(%Plug.Conn{} = conn, params) do
conn.request_path <> "?" <> URI.encode_query(params)
end
defp redirect_uri(url) do
URI.encode_www_form url
end
defp api_url do
@api_endpoint <> @api_path
end
defp open_url do
@open_endpoint <> @open_path
end
defp userinfo_url do
@api_endpoint <> @userinfo_path
end
end