Current section
Files
Jump to
Current section
Files
lib/storage/adapter/default.ex
defmodule WeChat.Storage.Adapter.DefaultClient do
@moduledoc false
# When uses the `{:default, "MyHubBaseURL"}`, there requires some HTTP API functions are provided by the hub webapp server,
# let's take "MyHubBaseURL" as "http://localhost:4000" for example.
# ### Refresh access token
# ```
# Request
# - method: POST http://localhost:4000/refresh/access_token
# - body: %{"appid" => "MyAppID", "access_token" => "CurrentExpiryAccessToken"}
# - body format: json
# Response
# - success body: %{"access_token" => "..."}
# - error body: any content is acceptable will be return back into `WeChat.Error`
# ```
# ### Fetch access token
# ```
# Request
# - method: GET http://localhost:4000/client/access_token
# - query string: appid="MyAppID"
# Response
# - success body: %{"access_token" => "..."}
# - error body: any error content is acceptable will be return back into `WeChat.Error`
# ```
# ### Fetch jsapi-ticket/card-ticket
# ```
# Request
# - method: GET http://localhost:4000/client/ticket
# - query string: appid="MyAppID"&type=jsapi or appid="MyAppID"&type=wx_card
# Response
# - success body: %{"ticket" => "..."}
# - error body: any error content is acceptable will be return back into `WeChat.Error`
# ```
@behaviour WeChat.Storage.Client
alias WeChat.Storage.DefaultHubConnector, as: Connector
alias WeChat.Error
@impl true
def fetch_access_token(appid, hub_base_url) do
Connector.fetch_access_token(appid, hub_base_url)
end
@impl true
def refresh_access_token(appid, access_token, hub_base_url) do
Connector.refresh_access_token(appid, access_token, hub_base_url)
end
@impl true
def fetch_ticket(appid, type, hub_base_url) do
# currently only support `type` as "jsapi" | "wx_card"
Connector.fetch_ticket(appid, type, hub_base_url)
end
end
defmodule WeChat.Storage.Adapter.DefaultComponentClient do
@moduledoc false
# For `component` application
# ### Refresh authorizer access_token
# ```
# Request
# - method: POST http://localhost:4000/refresh/access_token
# - body: %{"appid" => "Your3rdComponentAppID", "authorizer_appid" => "YourAuthorizerAppID", "access_token" => "CurrentExpiryAccessToken"}
# - body format: json
# Response
# - success body: %{"access_token" => "..."}
# - error body: any content is acceptable will be return back into `WeChat.Error`
# ```
# ### Fetch access_token
# ```
# Request
# - method: GET http://localhost:4000/client/access_token
# - query string: appid="MyAppID"
# Response
# - success body: %{"access_token" => "..."}
# - error body: any error content is acceptable will be return back into `WeChat.Error`
# ```
# ### Fetch jsapi-ticket/card-ticket
# ```
# Request
# - method: GET http://localhost:4000/client/ticket
# - query string: appid="MyAppID"&type=jsapi or appid="MyAppID"&type=wx_card
# Response
# - success body: %{"ticket" => "..."}
# - error body: any error content is acceptable will be return back into `WeChat.Error`
# ```
@behaviour WeChat.Storage.ComponentClient
alias WeChat.Storage.DefaultHubConnector, as: Connector
alias WeChat.Error
@impl true
def fetch_access_token(appid, authorizer_appid, hub_base_url) do
Connector.fetch_access_token(appid, authorizer_appid, hub_base_url)
end
@impl true
def fetch_component_access_token(appid, hub_base_url) do
Connector.fetch_component_access_token(appid, hub_base_url)
end
@impl true
def refresh_access_token(
appid,
authorizer_appid,
access_token,
hub_base_url
) do
Connector.refresh_access_token(appid, authorizer_appid, access_token, hub_base_url)
end
@impl true
def fetch_ticket(appid, authorizer_appid, type, hub_base_url) do
# Currently, `type` supports "jsapi" | "wx_card"
Connector.fetch_ticket(appid, authorizer_appid, type, hub_base_url)
end
end
defmodule WeChat.Storage.DefaultHubConnector do
@moduledoc false
require Logger
alias WeChat.{Error, Url}
def refresh_access_token(appid, access_token, hub_base_url) do
Logger.info(
"send refresh_token request to wechat hub for appid: #{inspect(appid)}, access_token: #{
inspect(access_token)
}"
)
token =
hub_base_url
|> client()
|> Tesla.post(Url.to_refresh_access_token(), %{appid: appid, access_token: access_token})
|> response_to_access_token()
Logger.info(
"received refreshed token from wechat hub: #{inspect(token)} for appid: #{inspect(appid)}"
)
token
end
def refresh_access_token(appid, authorizer_appid, access_token, hub_base_url) do
Logger.info(
"send refresh_token request to wechat hub for appid: #{inspect(appid)} with authorizer_appid: #{
inspect(authorizer_appid)
}, access_token: #{inspect(access_token)}"
)
token =
hub_base_url
|> client()
|> Tesla.post(Url.to_refresh_access_token(), %{
appid: appid,
authorizer_appid: authorizer_appid,
access_token: access_token
})
|> response_to_access_token()
Logger.info(
"received access token from wechat hub: #{inspect(token)} for appid: #{inspect(appid)} with authorizer_appid: #{
inspect(authorizer_appid)
}"
)
token
end
def fetch_access_token(appid, hub_base_url) do
hub_base_url
|> client()
|> Tesla.get(Url.to_fetch_access_token(), query: [appid: appid])
|> response_to_access_token()
end
def fetch_access_token(appid, authorizer_appid, hub_base_url) do
hub_base_url
|> client()
|> Tesla.get(Url.to_fetch_access_token(),
query: [appid: appid, authorizer_appid: authorizer_appid]
)
|> response_to_access_token()
end
def fetch_component_access_token(appid, hub_base_url) do
hub_base_url
|> client()
|> Tesla.get(Url.to_fetch_component_access_token(), query: [appid: appid])
|> response_to_access_token()
end
def fetch_ticket(appid, type, hub_base_url) do
hub_base_url
|> client()
|> Tesla.get(Url.to_fetch_ticket(), query: [appid: appid, type: type])
|> response_to_ticket()
end
def fetch_ticket(appid, authorizer_appid, type, hub_base_url) do
hub_base_url
|> client()
|> Tesla.get(Url.to_fetch_ticket(),
query: [appid: appid, authorizer_appid: authorizer_appid, type: type]
)
|> response_to_ticket()
end
defp client(hub_base_url) do
Tesla.client([
{Tesla.Middleware.BaseUrl, hub_base_url},
{Tesla.Middleware.Retry, delay: 500, max_retries: 10},
Tesla.Middleware.JSON
])
end
defp response_to_access_token({:ok, %{status: 200, body: %{"access_token" => access_token}}})
when access_token != nil and access_token != "" do
{
:ok,
%WeChat.Token{
access_token: access_token
}
}
end
defp response_to_access_token(
{:ok,
%{
body: %{
"errcode" => errcode,
"http_status" => http_status,
"message" => message,
"reason" => reason
}
}}
) do
{
:error,
%Error{
errcode: errcode,
http_status: http_status,
message: message,
reason: reason
}
}
end
defp response_to_access_token({:error, error}) do
{
:error,
%Error{
reason: :fail_fetch_access_token,
errcode: -1,
message: error
}
}
end
defp response_to_ticket({:ok, %{status: 200, body: %{"ticket" => ticket}}})
when ticket != nil and ticket != "" do
{:ok, ticket}
end
defp response_to_ticket({:ok, %{status: status, body: body}}) do
{:error, %Error{reason: :fail_fetch_ticket, errcode: -1, http_status: status, message: body}}
end
defp response_to_ticket({:error, error}) do
{:error, %Error{reason: :fail_fetch_ticket, errcode: -1, message: error}}
end
end