Skip to content

ygunayer/craftgate-elixir-client

Repository files navigation

Hex pm Coverage Status

Craftgate

This repo contains the Elixir client for Craftgate API.

Requirements

  • Elixir 1.12 or newer

Dependencies

  • HTTPoison to execute requests
  • Jason for JSON serialization/deserialization
  • Construct to provide a concise interface for representing request/response payloads as Elixir structs while also having them converted automatically by Jason
  • Decimal to represent monetary values
  • Recase to convert between Craftgate API's camelCase and Elixir's snake_case

Note: To keep the correct precision without losing any information, all decimals are serialized into strings. Since Craftgate API uses Java's BigDecimal to process these values it has no trouble parsing them, and likewise, by using Construct, Jason and Decimal in conjunction we're able to parse both numerical and string representations of decimals.

Installation

Add the :craftgate dependency to your mix.exs file

def deps do
  ...
  {:craftgate, "~> 1.0.42"}
  ...
end

Configuration

To access the Craftgate API you'll first need to obtain a set of API credentials. If you don't already have a Craftgate account, you can signup at https://craftgate.io, and after the onboarding process you will be able to access your API credentials from the merchant panel.

Once you've obtained your API credentials, you can configure Craftgate through the :craftgate on your config.exs file.

config :craftgate,
  api_key: "<YOUR API KEY>",
  secret_key: "<YOUR SECRET KEY>"

By default, Craftgate will run in sandbox mode and connect to the sandbox API at https://sandbox-api.craftgate.io.

Once you're confident with your implementation you can swap out the base_url parameter with the live production URL at https://api.craftgate.io

config :craftgate,
  api_key: "<YOUR API KEY>",
  secret_key: "<YOUR SECRET KEY>",
  base_url: "https://api.craftgate.io"

Additionally, Craftgate will use English as the default locale ("en") when contacting the Craftgate API, and also set a few request options to disable redirections and set particular request and receive timeouts. You can override these configurations by changing the lang and request_options keys respectively.

Do note, however, that by overriding request_options, you will be losing the default request options, so don't forget to include them if you only wish to add more parameters. For a list of all available options, see the documentation for HTTPoison.Request

Below is the list of default request options:

[
  timeout: 10_000,
  recv_timeout: 150_000,
  max_redirect: 0,
  follow_redirect: false
]

Note: You can also override these values by passing them to any Craftgate API call (e.g. Craftgate.Adapter.PaymentReportingAdapter.retrieve_payment(1, request_options: [timeout: 100_000])

So with that, a fully customized Craftgate configuration can look something like below:

config :craftgate,
  api_key: "<YOUR API KEY>",
  secret_key: "<YOUR SECRET KEY>",
  base_url: "https://api.craftgate.io",
  lang: "tr",
  request_options: [
    timeout: 60_000,
    recv_timeout: 120_000,
    max_redirect: 1,
    follow_redirect: true
  ]

Environment-Specific Configuration

As with any Phoenix app you can also make use of the environment-specific files to configure Craftgate for your development and production environments. In fact, we highly recommend inferring the production API credentials from environment variables in production and not have them written out plainly in your codebase.

config/config.exs

...
config :craftgate,
  base_url: "https://sandbox-api.craftgate.io",
  api_key: "<YOUR SANDBOX API KEY>",
  secret_key: "<YOUR SANDBOX SECRET KEY>"
...

config/prod.exs

...
config :craftgate,
  base_url: "https://api.craftgate.io",
  api_key: System.get_env("CRAFTGATE__API_KEY"),
  secret_key: System.get_env("CRAFTGATE__SECRET_KEY")"
...

Non-Phoenix Apps or Manual Configuration

If you're not using Phoenix, or if you can't/don't want to use the Config module you can also configure Craftgate by injecting the same properties into the :craftgate key using Application.put_env/3

Application.put_env(:craftgate, :api_key, "<YOUR API KEY>")
Application.put_env(:craftgate, :secret_key, "<YOUR SECRET KEY>")
Application.put_env(:craftgate, :base_url, "https://sandbox-api.craftgate.io")

Usage

The Craftgate Elixir client is stateless, so unlike its counterparts in other programming languages, you do not have to instantiate any Craftgate client. Instead, you can access specificy adapters directly, either through the adapter module itself, or through the convenience accessors on the Craftgate module itself.

Below is a list of all the adapters that are available:

Module Accessor Responsibilities
Craftgate.Adapter.FileReportingAdapter Craftgate.file_reporting/0 File-based reporting activities like obtaining daily transaction reports
Craftgate.Adapter.FraudAdapter Craftgate.fraud/0 Fraud operations like retrieving potentially fraudulent transactions, marking them as safe, managing fraud values
Craftgate.Adapter.HookAdapter Craftgate.hook/0 Hook-related utility functions like verifying incoming webhooks
Craftgate.Adapter.InstallmentAdapter Craftgate.installment/0 Retrieving per-installment pricing information based on installment count or BIN number
Craftgate.Adapter.OnboardingAdapter Craftgate.onboarding/0 Conducting CRUD operations on buyers and submerchants
Craftgate.Adapter.PayByLinkAdapter Craftgate.pay_by_link/0 Managing and listing products available for the pay-by-link feature
Craftgate.Adapter.PaymentAdapter Craftgate.payment/0 Conducting payments, managing stored cards
Craftgate.Adapter.PaymentReportingAdapter Craftgate.payment_reporting/0 Searching payments, retrieving payment details, retrieving payment transaction records
Craftgate.Adapter.SettlementReportingAdapter Craftgate.settlement_reporting/0 Settlement operations like search payout completed transactions, search bounced payout transactions
Craftgate.Adapter.SettlementAdapter Craftgate.settlement/0 Settlement operations like create instant wallet settlement
Craftgate.Adapter.WalletAdapter Craftgate.wallet/0 Wallet operations like sending and receiving remittance, searching walletes and wallet transactions of members

Once Craftgate is configured, you can use one of these adapters to interact with Craftgate API.

defmodule Orders do
  def refund_order(order_id) do
    with {:ok, order} <- Order.get(order_id),
         {:ok, refund_result} <- Craftgate.Adapter.PaymentAdapter.refund_payment(%Craftgate.Request.RefundPaymentRequest{
            payment_id: order.craftgate_payment_id,
            refund_destination_type: Craftgate.Model.RefundDestinationType.card(),
         }),
         ...
    do
      ...
    else
      ...
    end
  end
end

Running Samples

This project has a set of samples that you can run to interact with the Craftgate API, located at lib/mix/tasks/sample.

These samples are constructed as Mix tasks so you can even run them after adding craftgate-elixir as a dependency to your project.

$ mix sample.payment.create
[lib/mix/tasks/sample/payment/create.ex:45: Mix.Tasks.Sample.Payment.Create.run/1]
result #=> %Craftgate.Response.PaymentResponse{
...
}

Note that by default these samples use the public API keypairs found at https://developer.craftgate.io and target the sandbox environment of Craftgate API at https://sandbox-api.craftgate.io, but they will also try to use any existing configuration you might have. As such, if you run these samples from your own project with Craftgate already configured, you will be access the Craftgate API with your own credentials.

In addition to the Mix tasks, you can also jump into a Mix-enabled interactive Elixir session, put your credentials into the :api_key and :secret_key keys of the :craftgate configuration and run any adapter method.

$ iex -S mix

iex(1)> Application.put_env(:craftgate, :api_key, "<YOUR API KEY>")
:ok
iex(2)> Application.put_env(:craftgate, :secret_key, "<YOUR SECRET KEY>")
:ok
iex(3)> Application.put_env(:craftgate, :base_url, "https://sandbox-api.craftgate.io")
:ok
iex(4)> Craftgate.Adapter.PaymentReportingAdapter.retrieve_payment(1)
{:ok,
 %Craftgate.Response.ReportingPaymentResponse{
   retry_count: 0,
   refundable_price: Decimal.new("100.0"),
   refund_status: :NOT_REFUNDED,
   ...
 }
}

Contributing

For instructions on how to contribute to the project please see CONTRIBUTING.md

License

MIT