Zepto
Elixir client for the Zepto Payments API.
Installation
Add zepto to your list of dependencies in mix.exs:
def deps do
[
{:zepto, "~> 0.1.0"}
]
endConfiguration
1. Add Zepto configuration
In your config/config.exs or environment-specific config:
config :zepto,
environments: [
sandbox: [
base_url: "https://api.sandbox.zeptopayments.com",
oauth_url: "https://go.sandbox.zeptopayments.com",
client_id: System.get_env("ZEPTO_SANDBOX_CLIENT_ID"),
client_secret: System.get_env("ZEPTO_SANDBOX_CLIENT_SECRET"),
redirect_uri: "https://yourapp.com/zepto/sandbox/callback"
],
prod: [
base_url: "https://api.zeptopayments.com",
oauth_url: "https://go.zeptopayments.com",
client_id: System.get_env("ZEPTO_CLIENT_ID"),
client_secret: System.get_env("ZEPTO_CLIENT_SECRET"),
redirect_uri: "https://yourapp.com/zepto/callback"
]
]2. Set up the OAuth callback routes
Zepto uses OAuth2 Authorization Code flow. Add the callback plug to your Phoenix router:
# In lib/my_app_web/router.ex
defmodule MyAppWeb.Router do
use MyAppWeb, :router
# ... your other pipelines and routes ...
scope "/zepto" do
# Production callback
forward "/callback", Zepto.Plug.OAuthCallback,
environment: :prod,
on_success: &MyAppWeb.ZeptoController.on_oauth_success/2,
on_error: &MyAppWeb.ZeptoController.on_oauth_error/2
# Sandbox callback
forward "/sandbox/callback", Zepto.Plug.OAuthCallback,
environment: :sandbox,
on_success: &MyAppWeb.ZeptoController.on_oauth_success/2,
on_error: &MyAppWeb.ZeptoController.on_oauth_error/2
end
end3. Create callback handlers
# In lib/my_app_web/controllers/zepto_controller.ex
defmodule MyAppWeb.ZeptoController do
use MyAppWeb, :controller
def on_oauth_success(conn, _tokens) do
conn
|> put_flash(:info, "Successfully connected to Zepto!")
|> redirect(to: "/settings")
end
def on_oauth_error(conn, error) do
conn
|> put_flash(:error, "Failed to connect to Zepto: #{inspect(error)}")
|> redirect(to: "/settings")
end
end4. Initiate the OAuth flow
Create a link or button that redirects users to Zepto's authorization page:
# Generate the authorization URL
def zepto_auth_url(environment \\ :sandbox) do
config = Application.get_env(:zepto, :environments)[environment]
client_id = config[:client_id]
redirect_uri = URI.encode_www_form(config[:redirect_uri])
scope = "public+agreements+bank_accounts+contacts+open_agreements+payments+payment_requests+refunds+transfers+transactions+offline_access+webhooks"
oauth_url = config[:oauth_url]
"#{oauth_url}/authorize?client_id=#{client_id}&redirect_uri=#{redirect_uri}&response_type=code&scope=#{scope}"
endIn your template:
<a href={zepto_auth_url(:sandbox)}>Connect to Zepto (Sandbox)</a>Usage
Once authenticated, you can use the API:
# Create a client for the sandbox environment
client = Zepto.client(:sandbox)
# List contacts
{:ok, contacts} = Zepto.Contacts.list(client)
# Get a specific contact
{:ok, contact} = Zepto.Contacts.get(client, "contact_id")
# Create a payment
{:ok, payment} = Zepto.Payments.create(client, %{
description: "Payment for invoice #123",
matures_at: "2024-01-15T00:00:00Z",
your_bank_account_id: "your_bank_account_id",
payouts: [
%{
amount: 10000,
description: "Invoice payment",
recipient_contact_id: "contact_id"
}
]
})
# List transactions
{:ok, transactions} = Zepto.Transactions.list(client)API Resources
The following API resources are available:
Zepto.Agreements- Payment agreementsZepto.BankAccounts- Bank account managementZepto.Contacts- Contact managementZepto.Payments- Payment processingZepto.PaymentRequests- Payment request managementZepto.Refunds- Refund processingZepto.Transactions- Transaction historyZepto.Transfers- Transfer managementZepto.User- Current user infoZepto.Webhooks- Webhook managementZepto.Sandbox- Sandbox testing utilities
Token Management
The library manages OAuth tokens automatically:
- Access tokens are refreshed automatically when they expire (every 2 hours)
- Refresh tokens are stored in the TokenManager process state
- Each configured environment gets its own TokenManager process
Checking Authorization Status
# Check if we have a refresh token
Zepto.Client.TokenManager.has_refresh_token?(Zepto.TokenManager.Sandbox)
# => true or false
# Get the current refresh token (for debugging)
{:ok, token} = Zepto.Client.TokenManager.get_refresh_token(Zepto.TokenManager.Sandbox)Persisting Tokens
By default, tokens are stored in memory and will be lost on application restart. To persist tokens across restarts, implement the Zepto.TokenCallback behaviour:
defmodule MyApp.ZeptoTokenStore do
@behaviour Zepto.TokenCallback
alias MyApp.Repo
alias MyApp.ZeptoToken
@impl true
def save_tokens(environment, tokens) do
attrs = %{
environment: to_string(environment),
refresh_token: tokens.refresh_token,
access_token: tokens[:access_token],
expires_at: tokens[:expires_at]
}
%ZeptoToken{}
|> ZeptoToken.changeset(attrs)
|> Repo.insert(on_conflict: :replace_all, conflict_target: :environment)
|> case do
{:ok, _} -> :ok
{:error, changeset} -> {:error, changeset}
end
end
@impl true
def load_tokens(environment) do
case Repo.get_by(ZeptoToken, environment: to_string(environment)) do
nil ->
{:ok, nil}
token ->
{:ok, %{
refresh_token: token.refresh_token,
access_token: token.access_token,
expires_at: token.expires_at
}}
end
end
endThen add it to your config:
config :zepto,
environments: [
sandbox: [
# ... other config ...
token_callback: MyApp.ZeptoTokenStore
]
]The callbacks are called:
load_tokens/1- Lazily on first API call (to restore tokens)save_tokens/2- After each token refresh and after OAuth authorization
Note: Tokens are loaded lazily to avoid startup ordering issues with your Repo.
License
MIT