defmodule WeChat.MiniProgram.Auth do
@moduledoc """
小程序 - 权限接口
"""
import WeChat.Utils, only: [doc_link_prefix: 0]
alias WeChat.{Utils, ServerMessage.Encryptor, Storage.Cache}
@doc_link "#{doc_link_prefix()}/miniprogram/dev/api-backend/open-api"
@open_ability_doc_link "#{doc_link_prefix()}/miniprogram/dev/framework/open-ability"
@doc """
服务端获取开放数据 -
[官方文档](#{@open_ability_doc_link}/signature.html){:target="_blank"}
[登录流程](#{@open_ability_doc_link}/login.html)
"""
@spec decode_user_info(
session_key :: String.t(),
raw_data :: String.t(),
signature :: String.t()
) :: {:ok, map()} | {:error, String.t()}
def decode_user_info(session_key, raw_data, signature) do
case Utils.sha1(raw_data <> session_key) do
^signature ->
Jason.decode(raw_data)
_ ->
{:error, "invalid"}
end
end
@doc """
服务端获取开放数据 - 包含敏感数据 -
[官方文档](#{@open_ability_doc_link}/signature.html){:target="_blank"}
* [小程序登录](#{@open_ability_doc_link}/login.html)
* [加密数据解密算法](#{@open_ability_doc_link}/signature.html#加密数据解密算法)
"""
@spec decode_get_user_sensitive_info(
session_key :: String.t(),
encrypted_data :: String.t(),
iv :: String.t()
) :: {:ok, map()} | :error | {:error, any()}
def decode_get_user_sensitive_info(session_key, encrypted_data, iv) do
with {:ok, session_key} <- Base.decode64(session_key),
{:ok, iv} <- Base.decode64(iv),
{:ok, encrypted_data} <- Base.decode64(encrypted_data) do
:crypto.crypto_one_time(:aes_128_cbc, session_key, iv, encrypted_data, false)
|> Encryptor.decode_padding_with_pkcs7()
|> Jason.decode()
end
end
@doc """
小程序登录
[登录流程](#{@open_ability_doc_link}/login.html)
官方文档:
* [Mini Program](#{@doc_link}/login/auth.code2Session.html){:target="_blank"}
* [Component](#{doc_link_prefix()}/doc/oplatform/Third-party_Platforms/Mini_Programs/WeChat_login.html){:target="_blank"}
"""
@spec code2session(WeChat.client(), code :: String.t()) :: WeChat.response()
def code2session(client, code) do
if client.by_component?() do
component_appid = client.component_appid()
client.get("/sns/component/jscode2session",
query: [
appid: client.appid(),
js_code: code,
grant_type: "authorization_code",
component_appid: component_appid,
component_access_token: Cache.get_cache(component_appid, :component_access_token)
]
)
else
client.get("/sns/jscode2session",
query: [
appid: client.appid(),
secret: client.appsecret(),
js_code: code,
grant_type: "authorization_code"
]
)
end
end
@doc """
支付后获取用户的`UnionId` -
[官方文档](#{@doc_link}/user-info/auth.getPaidUnionId.html){:target="_blank"}
用户支付完成后,获取该用户的`UnionId`,无需用户授权.
本接口支持第三方平台代理查询.
**注意:调用前需要用户完成支付,且在支付后的五分钟内有效**
"""
@spec get_paid_unionid(WeChat.client(), WeChat.openid()) :: WeChat.response()
def get_paid_unionid(client, openid) do
client.get("/wxa/getpaidunionid",
query: [
openid: openid,
access_token: client.get_access_token()
]
)
end
@doc """
支付后获取用户的`UnionId` - 微信支付订单号(`transaction_id`) -
[官方文档](#{@doc_link}/user-info/auth.getPaidUnionId.html){:target="_blank"}
用户支付完成后,获取该用户的`UnionId`,无需用户授权.
本接口支持第三方平台代理查询.
**注意:调用前需要用户完成支付,且在支付后的五分钟内有效**
"""
@spec get_paid_unionid(WeChat.client(), WeChat.openid(), transaction_id :: String.t()) ::
WeChat.response()
def get_paid_unionid(client, openid, transaction_id) do
client.get("/wxa/getpaidunionid",
query: [
openid: openid,
transaction_id: transaction_id,
access_token: client.get_access_token()
]
)
end
@doc """
支付后获取用户的`UnionId` - 微信支付商户订单号和微信支付商户号(`out_trade_no`及`mch_id`) -
[官方文档](#{@doc_link}/user-info/auth.getPaidUnionId.html){:target="_blank"}
用户支付完成后,获取该用户的`UnionId`,无需用户授权.
本接口支持第三方平台代理查询.
**注意:调用前需要用户完成支付,且在支付后的五分钟内有效**
"""
@spec get_paid_unionid(
WeChat.client(),
WeChat.openid(),
mch_id :: String.t(),
out_trade_no :: String.t()
) :: WeChat.response()
def get_paid_unionid(client, openid, mch_id, out_trade_no) do
client.get("/wxa/getpaidunionid",
query: [
openid: openid,
mch_id: mch_id,
out_trade_no: out_trade_no,
access_token: client.get_access_token()
]
)
end
@doc """
获取AccessToken -
[官方文档](#{@doc_link}/access-token/auth.getAccessToken.html){:target="_blank"}
"""
@spec get_access_token(WeChat.client()) :: WeChat.response()
def get_access_token(client) do
client.get("/cgi-bin/token",
query: [
grant_type: "client_credential",
appid: client.appid(),
secret: client.appsecret()
]
)
end
end