Mercadopago

Hex.pmDocumentationLicense

Elixir client for Mercado Pago API. Provides a comprehensive interface for integrating payments, customers, subscriptions, and webhooks.

Features

Installation

Add mercadopago to your list of dependencies in mix.exs:

def deps do
  [
    {:mercadopago, "~> 0.1.0"}
  ]
end

Configuration

Add your Mercado Pago credentials to your application config:

# config/config.exs
config :mercadopago,
  access_token: "YOUR_ACCESS_TOKEN",
  sandbox: true  # Set to false in production

For production, use environment variables:

# config/runtime.exs
config :mercadopago,
  access_token: System.get_env("MERCADOPAGO_ACCESS_TOKEN"),
  sandbox: false

Usage

Creating a Payment

# Card payment
{:ok, payment} = Mercadopago.Resources.Payment.create(%{
  transaction_amount: 150.00,
  token: "card_token_from_js_sdk",
  description: "Blue shirt",
  payment_method_id: "visa",
  installments: 1,
  payer: %{
    email: "buyer@email.com",
    identification: %{type: "RFC", number: "ABC123456789"}
  }
})

# Cash payment (OXXO)
{:ok, payment} = Mercadopago.Resources.Payment.create(%{
  transaction_amount: 100.00,
  description: "Product",
  payment_method_id: "oxxo",
  payer: %{email: "buyer@email.com"}
})

# Get the OXXO reference
oxxo_reference = payment.transaction_details.payment_method_reference_id

Using Bang Functions

# Raises on error
payment = Mercadopago.Resources.Payment.create!(%{...})

Multi-tenant Applications

# Per-request credentials
Mercadopago.Resources.Payment.create(params, access_token: "tenant_token")

# Or create a client explicitly
client = Mercadopago.client(access_token: "tenant_token", sandbox: false)
Mercadopago.Resources.Payment.create(params, client: client)

Managing Customers

# Create a customer
{:ok, customer} = Mercadopago.Resources.Customer.create(%{
  email: "customer@email.com",
  first_name: "John",
  last_name: "Doe"
})

# Save a card for the customer
{:ok, card} = Mercadopago.Resources.Card.create(customer.id, %{
  token: "card_token"
})

# Charge a saved card
{:ok, payment} = Mercadopago.Resources.Payment.create(%{
  transaction_amount: 100.00,
  token: card.id,
  description: "Recurring charge",
  payment_method_id: "visa",
  payer: %{id: customer.id}
})

Checkout Preferences

{:ok, preference} = Mercadopago.Resources.Preference.create(%{
  items: [
    %{
      title: "Product Name",
      quantity: 1,
      currency_id: "MXN",
      unit_price: 100.00
    }
  ],
  back_urls: %{
    success: "https://example.com/success",
    failure: "https://example.com/failure",
    pending: "https://example.com/pending"
  },
  external_reference: "ORDER-123"
})

# Redirect user to checkout
redirect_url = preference.init_point

Refunds

# Full refund
{:ok, refund} = Mercadopago.Resources.Refund.create(payment_id)

# Partial refund
{:ok, refund} = Mercadopago.Resources.Refund.create(payment_id, amount: 50.00)

Webhooks

# In your Phoenix controller or LiveView
def handle_webhook(conn, params) do
  # Extract required values for signature verification
  data_id = conn.query_params["data.id"]  # From query params (lowercased if alphanumeric)
  x_request_id = Plug.Conn.get_req_header(conn, "x-request-id") |> List.first()
  signature_header = Plug.Conn.get_req_header(conn, "x-signature") |> List.first()
  secret = Application.get_env(:mercadopago, :webhook_secret)

  case Mercadopago.Webhook.parse_and_verify(params, data_id, x_request_id, signature_header, secret) do
    {:ok, %{topic: :payment, id: payment_id}} ->
      {:ok, payment} = Mercadopago.Resources.Payment.get(payment_id)
      # Handle payment update...

    {:ok, %{topic: :subscription_preapproval}} ->
      # Handle subscription update...

    {:error, :invalid_signature} ->
      # Reject

    {:error, _} ->
      # Invalid notification format
  end
end

Testing

Run the tests:

mix test

Using Bypass for Integration Tests

setup do
  bypass = Bypass.open()
  Application.put_env(:mercadopago, :base_url, "http://localhost:#{bypass.port}")
  on_exit(fn -> Bypass.down(bypass) end)
  {:ok, bypass: bypass}
end

test "creates a payment", %{bypass: bypass} do
  Bypass.expect_once(bypass, "POST", "/v1/payments", fn conn ->
    Plug.Conn.resp(conn, 200, ~s({"id": 123456, "status": "approved"}))
  end)

  {:ok, payment} = Mercadopago.Resources.Payment.create(%{...})
  assert payment.status == :approved
end

Supported Payment Methods

Mexico (MLM)

Documentation

Full documentation is available at HexDocs.

License

MIT License. See LICENSE for details.

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Merge Request