Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
60 changes: 60 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Check application

on:
- push
- pull_request

permissions:
contents: read

jobs:
check:
runs-on: ubuntu-latest

strategy:
matrix:
include:
- otp: "26.0.2"
elixir: "1.15.4"
- otp: "28.3"
elixir: "1.19.5"

steps:
- uses: actions/checkout@v3
- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}

- name: Restore dependencies cache
uses: actions/cache@v3
with:
path: deps
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}-deps

- name: Install dependencies
run: mix deps.get && mix deps.unlock --check-unused

- name: Restore PLT
uses: actions/cache@v4
id: cache-plt
with:
path: priv/plts
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}-plt

- name: Create PLTs
if: steps.cache-plt.outputs.cache-hit != 'true'
run: mix dialyzer --plt

- name: Check format
run: mix format --check-formatted

- name: Run credo
run: mix credo

- name: Run tests
run: mix test

- name: Run dialyzer
run: mix dialyzer --format github
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ erl_crash.dump
*.ez

# Ignore package tarball (built via "mix hex.build").
abacate_pay-*.tar
abacatepay-*.tar

# Temporary files, for example, from tests.
/tmp/
# VSCode Elixir LS Extension
.elixir_ls/

# Environment variables
.env
# Priv
/priv/
19 changes: 14 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Adds detailed documentation for each supported resource (Customer and Billing)

- Improve response handling and struct mapping
- Customer resource with create and list operations
- Billing resource with create and list operations
- Basic HTTP client with authentication
- Type definitions for Customer entities
- Add coupon routes
- Add pix routes
- Add public mrr routes
- Add store routes
- Add withdraw routes
- Add [nimble_options](https://github.com/dashbitco/nimble_options) for validation of function options
- Added CI

### Chores

- Updated dependencies
- Updated documentation
- Switched from HTTPoison to [Finch](https://github.com/sneako/finch). Finch is more minimal and performant.
4 changes: 2 additions & 2 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
MIT License
The MIT License (MIT)

Copyright (c) 2024 Vicente Sanchez

Expand All @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
151 changes: 99 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,43 @@

Official **AbacatePay Elixir** SDK to integrate payments via PIX in a simple, secure and fast way.

![Build Status](https://github.com/AbacatePay/abacatepay-elixir-sdk/actions/workflows/check.yml/badge.svg)
[![Hex.pm](https://img.shields.io/hexpm/v/abacatepay.svg)](https://hex.pm/packages/abacatepay)
[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/abacatepay)

</div>

<div align="center">

## Installation

<!-- Add `abacate_pay` to your list of dependencies in `mix.exs`: -->
The package can be installed by adding `abacatepay` to your list of dependencies in `mix.exs`:

</div>

```elixir
def deps do
[
{:abacatepay, git: "https://github.com/AbacatePay/abacatepay-elixir-sdk", branch: "main", override: true}
]
end
```

<div align="center">

## Configuration

The SDK has a range of configuration options, but most applications will have a configuration that looks like the following:

</div>

```elixir
# config/config.exs
config :abacatepay,
api_key: "abc_dev_pWxM5GhSROzeerqmdkfu6mNN"
```

Not available yet.
<div align="center">

## Features

Expand All @@ -23,14 +55,14 @@ Create a new customer in the AbacatePay system.
</div>

```elixir
customer_data = %{
name: "John Doe",
taxId: "123.456.789-00",
email: "john@example.com",
cellphone: "+5511999999999"
}
{:ok, customer} = AbacatePay.Resources.Customer.create(client, customer_data)
customer_data = [
name: "Daniel Lima",
tax_id: "123.456.789-01",
email: "daniel_lima@abacatepay.com",
cellphone: "+5511999999999"
]

{:ok, customer} = AbacatePay.Customer.create(customer_data)
```

<div align="center">
Expand All @@ -42,7 +74,7 @@ Retrieve a list of all customers.
</div>

```elixir
{:ok, customers} = AbacatePay.Resources.Customer.list(client)
{:ok, customers} = AbacatePay.Customer.list()
```

<div align="center">
Expand All @@ -56,20 +88,43 @@ Create a new billing for a customer.
</div>

```elixir
billing_data = %{
amount: 1000, # Amount in cents
customerId: "cust_123", # Customer ID
methods: ["pix", "credit_card"],
products: [
%{
name: "Product Name",
amount: 1000,
quantity: 1
# The customer associated with the Billing
customer = %AbacatePay.Customer{
id: "cust_aebxkhDZNaMmJeKsy0AHS0FQ",
name: "Daniel Lima",
tax_id: "123.456.789-01",
email: "[email protected]",
cellphone: "+5511999999999"
}

# The products to be included in the Billing
products = [
%AbacatePay.Product{
name: "Product 1",
price: 5000,
quantity: 1
},
%AbacatePay.Product{
name: "Product 2",
price: 3000,
quantity: 2
}
]
}

{:ok, billing} = AbacatePay.Resources.Billing.create(client, billing_data)
billing_data = [
frequency: :one_time,
methods: [:pix, :card],
products: products,
customer: customer,
return_url: "https://example.com/return",
completion_url: "https://example.com/completion",
allow_coupons: true,
coupons: ["DEYVIN_20"],
external_id: "order_0001",
metadata: %{"notes" => "First order"}
]

{:ok, billing} = AbacatePay.Billing.create(billing_data)
```

<div align="center">
Expand All @@ -81,7 +136,7 @@ Retrieve a list of all billings.
</div>

```elixir
{:ok, billings} = AbacatePay.Resources.Billing.list(client)
{:ok, billings} = AbacatePay.Billing.list()
```

<div align="center">
Expand All @@ -93,15 +148,13 @@ Retrieve a list of all billings.
</div>

```elixir
%Customer{
id: "cust_123",
metadata: %{
name: "John Doe",
taxId: "123.456.789-00",
email: "[email protected]",
%AbacatePay.Customer{
id: "cust_aebxkhDZNaMmJeKsy0AHS0FQ",
name: "Daniel Lima",
tax_id: "123.456.789-01",
email: "[email protected]",
cellphone: "+5511999999999"
}
}
```

<div align="center">
Expand All @@ -111,26 +164,20 @@ Retrieve a list of all billings.
</div>

```elixir
%Billing{
id: "bill_123",
url: "https://pay.abacatepay.com/...",
amount: 1000,
devMode: false,
status: :pending,
frequency: :one_time,
metadata: %{},
publicId: "pub_123",
createdAt: "2024-03-20T...",
updatedAt: "2024-03-20T...",
methods: [:pix, :credit_card],
products: [
%{
name: "Product Name",
amount: 1000,
quantity: 1
}
],
customer: %{...},
customerId: "cust_123"
}
%AbacatePay.Billing{
id: "bill_aebxkhDZNaMmJeKsy0AHS0FQ",
frequency: :one_time,
url: "https://app.abacatepay.com/pay/bill_aebxkhDZNaMmJeKsy0AHS0FQ",
status: :pending,
dev_mode: false,
methods: [:pix, :card],
products: [%AbacatePay.Product{name: "Product 1", price: 5000, quantity: 1}, %AbacatePay.Product{name: "Product 2", price: 3000, quantity: 2}],
customer: %AbacatePay.Customer{id: "cust_aebxkhDZNaMmJeKsy0AHS0FQ", name: "Daniel Lima", cellphone: "+5511999999999", email: "[email protected]", tax_id: "123.456.789-01"},
metadata: %{fee: 80, return_url: "https://example.com/return", completion_url: "https://example.com/completion"},
next_billing: nil,
allow_coupons: true,
coupons: ["DEYVIN_20"],
created_at: ~U[2026-01-01T12:00:00Z],
updated_at: ~U[2026-01-02T12:00:00Z]
}
```
37 changes: 37 additions & 0 deletions lib/abacatepay/api/billing.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule AbacatePay.Api.Billing do
@moduledoc ~S"""
Module for handling billing-related endpoints in the API.
"""

alias AbacatePay.{HTTPClient, ApiError}

@doc """
Creates a new billing.

## Examples

iex> AbacatePay.Api.Billing.create_billing(%{...})
{:ok, %{...}}
"""
@spec create_billing(body :: map()) ::
{:ok, map()} | {:error, ApiError.t()} | {:error, any()}
def create_billing(body) do
HTTPClient.post(
"/billing/create",
body
)
end

@doc """
Gets a list of all billings.

## Examples

iex> AbacatePay.Api.Billing.list_billings()
{:ok, [%{...}, ...]}
"""
@spec list_billings() :: {:ok, list(map())} | {:error, ApiError.t()} | {:error, any()}
def list_billings do
HTTPClient.get("/billing/list")
end
end
Loading
Loading