メインコンテンツへスキップ

Elixirライブラリ(omise-elixir)

omise-elixirライブラリは、パターンマッチング、OTP機能、優れたPhoenix統合を備えた、Omise APIへの慣用的なElixirインターフェースを提供します。

インストール

Mixの使用

mix.exsに追加:

def deps do
[
{:omise, "~> 0.11"}
]
end

次に実行:

mix deps.get

要件

  • Elixir 1.10以上(Elixir 1.14+を含む)
  • Erlang/OTP 22+(OTP 25+を含む)
  • 依存関係管理にMix
  • Phoenix 1.6+(オプション、Phoenixアプリケーション用)

クイックスタート

基本的な構成

# APIキーを構成
Omise.configure(
public_key: "pkey_test_123456789",
secret_key: "skey_test_123456789",
api_version: "2019-05-29"
)

Phoenix構成

# config/config.exs
config :omise,
public_key: System.get_env("OMISE_PUBLIC_KEY"),
secret_key: System.get_env("OMISE_SECRET_KEY"),
api_version: "2019-05-29"

# config/runtime.exs (Phoenix 1.6+)
import Config

config :omise,
public_key: System.fetch_env!("OMISE_PUBLIC_KEY"),
secret_key: System.fetch_env!("OMISE_SECRET_KEY")

環境変数

# 開発/テスト
export OMISE_SECRET_KEY=skey_test_123456789
export OMISE_PUBLIC_KEY=pkey_test_123456789

# 本番環境
# export OMISE_SECRET_KEY=skey_live_123456789
# export OMISE_PUBLIC_KEY=pkey_live_123456789

一般的な操作

チャージの作成

# カードトークンでチャージを作成
{:ok, charge} = Omise.Charge.create(
amount: 100_000, # 1,000.00 THB(最小通貨単位)
currency: "THB",
card: "tokn_test_123",
description: "注文 #1234",
metadata: %{
order_id: "1234",
customer_name: "John Doe"
}
)

case charge do
%{paid: true} ->
IO.puts("チャージ成功: #{charge.id}")
%{paid: false} ->
IO.puts("チャージ失敗: #{charge.failure_message}")
end

パターンマッチングを使用

defmodule PaymentService do
def create_charge(token, amount) do
case Omise.Charge.create(amount: amount, currency: "THB", card: token) do
{:ok, %{paid: true} = charge} ->
{:ok, charge}

{:ok, %{paid: false, failure_message: message}} ->
{:error, message}

{:error, error} ->
{:error, error}
end
end
end

3Dセキュアで

def create_secure_charge(token, amount, return_uri) do
case Omise.Charge.create(
amount: amount,
currency: "THB",
card: token,
return_uri: return_uri
) do
{:ok, %{authorized: true, authorize_uri: uri} = charge} when not is_nil(uri) ->
{:redirect, uri}

{:ok, %{authorized: true, paid: true} = charge} ->
{:success, charge}

{:ok, %{failure_message: message}} ->
{:error, message}

{:error, error} ->
{:error, error}
end
end

チャージの取得

case Omise.Charge.retrieve("chrg_test_123") do
{:ok, charge} ->
IO.puts("金額: #{charge.amount}")
IO.puts("通貨: #{charge.currency}")
IO.puts("ステータス: #{charge.status}")
IO.puts("支払い済み: #{charge.paid}")

{:error, error} ->
IO.puts("エラー: #{inspect(error)}")
end

チャージのリスト表示

# ページネーション付きですべてのチャージをリスト表示
{:ok, charges} = Omise.Charge.list(
limit: 20,
offset: 0,
order: "reverse_chronological"
)

charges.data
|> Enum.filter(&(&1.paid))
|> Enum.each(fn charge ->
IO.puts("#{charge.id}: #{charge.amount} #{charge.currency}")
end)

# 日付フィルターを使用してチャージをリスト表示
week_ago = DateTime.utc_now() |> DateTime.add(-7, :day) |> DateTime.to_date()
today = Date.utc_today()

{:ok, recent_charges} = Omise.Charge.list(
from: week_ago,
to: today
)

顧客の作成

{:ok, customer} = Omise.Customer.create(
email: "customer@example.com",
description: "John Doe",
metadata: %{
user_id: "12345",
account_type: "premium"
}
)

IO.puts("顧客作成: #{customer.id}")

顧客へのカード保存

# カードトークンで顧客を更新
{:ok, customer} = Omise.Customer.update(
"cust_test_123",
card: "tokn_test_456"
)

IO.puts("カード保存: #{customer.default_card}")

# または1ステップでカード付き顧客を作成
{:ok, customer} = Omise.Customer.create(
email: "customer@example.com",
description: "John Doe",
card: "tokn_test_123"
)

顧客カードのリスト表示

{:ok, customer} = Omise.Customer.retrieve("cust_test_123")

customer.cards.data
|> Enum.each(fn card ->
IO.puts("#{card.brand} 末尾 #{card.last_digits}")
IO.puts("有効期限: #{card.expiration_month}/#{card.expiration_year}")
end)

払い戻しの作成

# 全額返金
{:ok, refund} = Omise.Refund.create(
"chrg_test_123",
%{}
)

# 部分払い戻し
{:ok, refund} = Omise.Refund.create(
"chrg_test_123",
%{
amount: 25_000, # 250.00 THB
metadata: %{
reason: "customer_request",
ticket_id: "TICKET-123"
}
}
)

IO.puts("払い戻し #{refund.id}: #{refund.amount} #{refund.currency}")

転送の作成

{:ok, transfer} = Omise.Transfer.create(
amount: 500_000, # 5,000.00 THB
recipient: "recp_test_123",
metadata: %{
payout_id: "PAYOUT-456"
}
)

IO.puts("転送 #{transfer.id}: #{transfer.amount}")

代替決済方法

ソースの作成

# PromptPay QR
{:ok, source} = Omise.Source.create(
type: "promptpay",
amount: 100_000,
currency: "THB"
)

IO.puts("QRコードURL: #{source.scannable_code.image.download_uri}")

# ソースを使用してチャージを作成
{:ok, charge} = Omise.Charge.create(
amount: 100_000,
currency: "THB",
source: source.id,
return_uri: "https://example.com/payment/callback"
)

インターネットバンキング

{:ok, source} = Omise.Source.create(
type: "internet_banking_scb",
amount: 100_000,
currency: "THB"
)

{:ok, charge} = Omise.Charge.create(
amount: 100_000,
currency: "THB",
source: source.id,
return_uri: "https://example.com/payment/callback"
)

# 顧客をcharge.authorize_uriにリダイレクト

モバイルバンキング

{:ok, source} = Omise.Source.create(
type: "mobile_banking_scb",
amount: 100_000,
currency: "THB"
)

{:ok, charge} = Omise.Charge.create(
amount: 100_000,
currency: "THB",
source: source.id,
return_uri: "https://example.com/payment/callback"
)

インストール

{:ok, source} = Omise.Source.create(
type: "installment_kbank",
amount: 100_000,
currency: "THB",
installment_term: 6 # 6ヶ月
)

{:ok, charge} = Omise.Charge.create(
amount: 100_000,
currency: "THB",
source: source.id,
return_uri: "https://example.com/payment/callback"
)

エラーハンドリング

defmodule PaymentService do
def create_charge_with_error_handling(params) do
case Omise.Charge.create(params) do
{:ok, charge} ->
{:ok, charge}

{:error, %{code: "authentication_failure"}} ->
{:error, "無効なAPIキー"}

{:error, %{code: "invalid_card"}} ->
{:error, "カードが拒否されました"}

{:error, %{code: "insufficient_fund"}} ->
{:error, "残高不足"}

{:error, error} ->
{:error, "支払いが失敗しました: #{inspect(error)}"}
end
end
end

カスタムエラーハンドラー

defmodule PaymentErrorHandler do
@error_messages %{
"insufficient_fund" => "カードの残高不足",
"stolen_or_lost_card" => "カードが盗難または紛失として報告されています",
"invalid_security_code" => "無効なCVVコード",
"payment_cancelled" => "支払いがキャンセルされました"
}

def get_error_message({:error, %{code: code}}), do: Map.get(@error_messages, code, "不明なエラー")
def get_error_message({:error, error}), do: "エラー: #{inspect(error)}"
def get_error_message(_), do: "不明なエラー"
end

Phoenix統合

コントローラーの例

defmodule MyAppWeb.PaymentController do
use MyAppWeb, :controller

alias MyApp.Payments
alias MyApp.Orders

def create(conn, %{"order_id" => order_id, "omise_token" => token}) do
with {:ok, order} <- Orders.get_order(order_id),
{:ok, charge} <- create_charge(order, token),
{:ok, payment} <- Payments.save_payment(charge, order) do

handle_charge_result(conn, charge, order)
else
{:error, :not_found} ->
conn
|> put_flash(:error, "注文が見つかりません")
|> redirect(to: Routes.order_path(conn, :index))

{:error, reason} ->
conn
|> put_flash(:error, "支払いが失敗しました: #{reason}")
|> redirect(to: Routes.payment_path(conn, :new, order_id))
end
end

defp create_charge(order, token) do
Omise.Charge.create(
amount: round(order.total * 100),
currency: "THB",
card: token,
description: "注文 ##{order.id}",
metadata: %{
order_id: order.id,
customer_email: order.email
},
return_uri: Routes.payment_url(MyAppWeb.Endpoint, :callback)
)
end

defp handle_charge_result(conn, %{paid: true} = charge, order) do
Orders.mark_paid(order)

conn
|> put_flash(:info, "支払いが成功しました!")
|> redirect(to: Routes.order_path(conn, :show, order))
end

defp handle_charge_result(conn, %{authorize_uri: uri} = _charge, _order) when not is_nil(uri) do
redirect(conn, external: uri)
end

defp handle_charge_result(conn, %{failure_message: message}, order) do
conn
|> put_flash(:error, message)
|> redirect(to: Routes.payment_path(conn, :new, order))
end

def callback(conn, %{"id" => charge_id}) do
with {:ok, charge} <- Omise.Charge.retrieve(charge_id),
{:ok, payment} <- Payments.get_by_charge_id(charge_id),
{:ok, _payment} <- Payments.update_status(payment, charge) do

if charge.paid do
conn
|> put_flash(:info, "支払いが成功しました!")
|> redirect(to: Routes.order_path(conn, :show, payment.order_id))
else
conn
|> put_flash(:error, charge.failure_message)
|> redirect(to: Routes.payment_path(conn, :new, payment.order_id))
end
else
{:error, _reason} ->
conn
|> put_flash(:error, "支払い検証が失敗しました")
|> redirect(to: Routes.page_path(conn, :index))
end
end
end

コンテキストモジュール

defmodule MyApp.Payments do
import Ecto.Query
alias MyApp.Repo
alias MyApp.Payments.Payment

def save_payment(charge, order) do
%Payment{}
|> Payment.changeset(%{
order_id: order.id,
charge_id: charge.id,
amount: Decimal.div(charge.amount, 100),
currency: charge.currency,
status: charge.status,
paid: charge.paid
})
|> Repo.insert()
end

def get_by_charge_id(charge_id) do
case Repo.get_by(Payment, charge_id: charge_id) do
nil -> {:error, :not_found}
payment -> {:ok, payment}
end
end

def update_status(payment, charge) do
payment
|> Payment.changeset(%{
status: charge.status,
paid: charge.paid,
failure_code: charge.failure_code,
failure_message: charge.failure_message
})
|> Repo.update()
end

def charge_customer(customer_id, amount) do
Omise.Charge.create(
amount: round(amount * 100),
currency: "THB",
customer: customer_id
)
end

def refund_charge(charge_id, amount \\ nil) do
params = if amount, do: %{amount: round(amount * 100)}, else: %{}
Omise.Refund.create(charge_id, params)
end
end

スキーマ

defmodule MyApp.Payments.Payment do
use Ecto.Schema
import Ecto.Changeset

schema "payments" do
field :order_id, :id
field :charge_id, :string
field :amount, :decimal
field :currency, :string, default: "THB"
field :status, :string
field :paid, :boolean, default: false
field :failure_code, :string
field :failure_message, :string
field :refund_id, :string
field :refund_amount, :decimal

timestamps()
end

def changeset(payment, attrs) do
payment
|> cast(attrs, [
:order_id, :charge_id, :amount, :currency, :status,
:paid, :failure_code, :failure_message, :refund_id, :refund_amount
])
|> validate_required([:order_id, :amount, :currency, :status])
|> validate_number(:amount, greater_than: 0)
|> unique_constraint(:charge_id)
end
end

バックグラウンド処理用のGenServer

決済プロセッサ

defmodule MyApp.PaymentProcessor do
use GenServer
require Logger

def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end

def process_charge(token, amount, metadata) do
GenServer.call(__MODULE__, {:process_charge, token, amount, metadata})
end

@impl true
def init(_opts) do
{:ok, %{}}
end

@impl true
def handle_call({:process_charge, token, amount, metadata}, _from, state) do
result = case Omise.Charge.create(
amount: amount,
currency: "THB",
card: token,
metadata: metadata
) do
{:ok, %{paid: true} = charge} ->
Logger.info("チャージ成功: #{charge.id}")
{:ok, charge}

{:ok, %{paid: false, failure_message: message} = charge} ->
Logger.error("チャージ失敗: #{message}")
{:error, message}

{:error, error} ->
Logger.error("チャージエラー: #{inspect(error)}")
{:error, error}
end

{:reply, result, state}
end
end

サブスクリプションマネージャー

defmodule MyApp.SubscriptionManager do
use GenServer
require Logger

alias MyApp.Repo
alias MyApp.Subscriptions.Subscription

def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end

@impl true
def init(_opts) do
schedule_work()
{:ok, %{}}
end

@impl true
def handle_info(:charge_subscriptions, state) do
charge_all_subscriptions()
schedule_work()
{:noreply, state}
end

defp schedule_work do
# 翌日の深夜にスケジュール
next_run = calculate_next_midnight()
Process.send_after(self(), :charge_subscriptions, next_run)
end

defp charge_all_subscriptions do
Subscription
|> where([s], s.status == "active")
|> Repo.all()
|> Enum.each(&charge_subscription/1)
end

defp charge_subscription(subscription) do
case Omise.Charge.create(
amount: subscription.plan_amount,
currency: "THB",
customer: subscription.customer_id,
description: "サブスクリプション #{Date.utc_today()}"
) do
{:ok, %{paid: true}} ->
subscription
|> Ecto.Changeset.change(last_charge_date: DateTime.utc_now())
|> Repo.update()

Logger.info("サブスクリプション #{subscription.id} に課金しました")

{:error, error} ->
Logger.error("サブスクリプション #{subscription.id} の課金失敗: #{inspect(error)}")
end
end

defp calculate_next_midnight do
now = DateTime.utc_now()
tomorrow = DateTime.add(now, 1, :day)
midnight = %{tomorrow | hour: 0, minute: 0, second: 0, microsecond: {0, 0}}
DateTime.diff(midnight, now, :millisecond)
end
end

非同期操作用のTask

defmodule MyApp.AsyncPayment do
def process_charges_async(charge_params_list) do
charge_params_list
|> Enum.map(fn params ->
Task.async(fn -> create_charge(params) end)
end)
|> Enum.map(&Task.await/1)
end

defp create_charge(params) do
case Omise.Charge.create(params) do
{:ok, charge} -> {:ok, charge}
{:error, error} -> {:error, error}
end
end
end

# 使用方法
charge_params = [
%{amount: 100_000, currency: "THB", card: "tokn_test_1"},
%{amount: 200_000, currency: "THB", card: "tokn_test_2"}
]

results = MyApp.AsyncPayment.process_charges_async(charge_params)

ベストプラクティス

1. パターンマッチングの使用

def process_payment(token, amount) do
case Omise.Charge.create(amount: amount, currency: "THB", card: token) do
{:ok, %{paid: true, id: charge_id}} ->
# 成功した支払いを処理
{:ok, charge_id}

{:ok, %{authorize_uri: uri}} when not is_nil(uri) ->
# 3Dセキュアリダイレクトを処理
{:redirect, uri}

{:ok, %{failure_message: message}} ->
# 失敗した支払いを処理
{:error, message}

{:error, %{code: code, message: message}} ->
# APIエラーを処理
{:error, "#{code}: #{message}"}
end
end

2. データ変換にパイプの使用

def list_paid_charges do
{:ok, charges} = Omise.Charge.list(limit: 100)

charges.data
|> Enum.filter(&(&1.paid))
|> Enum.map(&extract_charge_info/1)
|> Enum.sort_by(& &1.created, :desc)
end

defp extract_charge_info(charge) do
%{
id: charge.id,
amount: charge.amount / 100,
currency: charge.currency,
created: charge.created
}
end

3. 型安全性のための構造体の使用

defmodule MyApp.Money do
defstruct amount: 0, currency: "THB"

def new(amount, currency \\ "THB") do
%__MODULE__{amount: round(amount * 100), currency: currency}
end

def to_baht(%__MODULE__{amount: amount}), do: amount / 100
end

# 使用方法
money = MyApp.Money.new(1000.00)
{:ok, charge} = Omise.Charge.create(
amount: money.amount,
currency: money.currency,
card: token
)

4. 冪等性の実装

def create_idempotent_charge(params, order_id) do
idempotency_key = "order-#{order_id}-#{:os.system_time(:millisecond)}"

Omise.Charge.create(
params,
headers: [{"Idempotency-Key", idempotency_key}]
)
end

5. フォールトトレランスのためのスーパーバイザーの使用

defmodule MyApp.Application do
use Application

def start(_type, _args) do
children = [
MyApp.Repo,
MyAppWeb.Endpoint,
MyApp.PaymentProcessor,
MyApp.SubscriptionManager
]

opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end

6. 監視のためのTelemetryの使用

defmodule MyApp.PaymentTelemetry do
def handle_event([:omise, :charge, :create], measurements, metadata, _config) do
Logger.info("チャージ作成済み",
charge_id: metadata.charge_id,
amount: metadata.amount,
duration: measurements.duration
)
end
end

# ハンドラーをアタッチ
:telemetry.attach(
"payment-handler",
[:omise, :charge, :create],
&MyApp.PaymentTelemetry.handle_event/4,
nil
)

テスト

ExUnitテスト

defmodule MyApp.PaymentsTest do
use MyApp.DataCase

alias MyApp.Payments

import Mox

setup :verify_on_exit!

describe "create_charge/2" do
test "成功したチャージを作成" do
expect(OmiseMock, :create_charge, fn _params ->
{:ok, %{
id: "chrg_test_123",
amount: 100_000,
currency: "THB",
paid: true,
status: "successful"
}}
end)

assert {:ok, charge} = Payments.create_charge("tokn_test_123", 1000.00)
assert charge.id == "chrg_test_123"
assert charge.paid == true
end

test "チャージの失敗を処理" do
expect(OmiseMock, :create_charge, fn _params ->
{:error, %{code: "insufficient_fund", message: "残高不足"}}
end)

assert {:error, error} = Payments.create_charge("tokn_test_123", 1000.00)
assert error.code == "insufficient_fund"
end
end
end

統合テスト

defmodule MyAppWeb.PaymentControllerTest do
use MyAppWeb.ConnCase

alias MyApp.Orders

setup do
order = Orders.create_order!(%{total: 1000.00, email: "test@example.com"})
{:ok, order: order}
end

describe "POST /payment/:order_id" do
@tag :integration
test "支払いが正常に作成される", %{conn: conn, order: order} do
# テストトークンを使用
token = "tokn_test_5086xl7ddjbases4sq3i"

conn = post(conn, Routes.payment_path(conn, :create, order.id), %{
"omise_token" => token
})

assert redirected_to(conn) == Routes.order_path(conn, :show, order)
assert get_flash(conn, :info) == "支払いが成功しました!"
end
end
end

テスト用のモック

# test/support/mocks.ex
Mox.defmock(OmiseMock, for: MyApp.PaymentBehaviour)

# lib/my_app/payment_behaviour.ex
defmodule MyApp.PaymentBehaviour do
@callback create_charge(map()) :: {:ok, map()} | {:error, map()}
@callback retrieve_charge(String.t()) :: {:ok, map()} | {:error, map()}
end

# アプリケーションで使用
defmodule MyApp.Payments do
@payment_client Application.compile_env(:my_app, :payment_client, Omise)

def create_charge(params) do
@payment_client.Charge.create(params)
end
end

# テスト構成で
config :my_app, payment_client: OmiseMock

トラブルシューティング

接続タイムアウト

# HTTPクライアントタイムアウトを構成
config :omise,
http_options: [timeout: 60_000, recv_timeout: 60_000]

デバッグログ

# デバッグログを有効化
config :logger, level: :debug

config :omise, debug: true

ウェブフック署名検証

defmodule MyAppWeb.WebhookController do
use MyAppWeb, :controller

def omise(conn, _params) do
with {:ok, payload} <- read_body(conn),
{:ok, signature} <- get_signature(conn),
true <- verify_signature(payload, signature) do

payload
|> Jason.decode!()
|> handle_webhook()

json(conn, %{status: "ok"})
else
false ->
conn
|> put_status(:unauthorized)
|> json(%{error: "無効な署名"})

{:error, _reason} ->
conn
|> put_status(:bad_request)
|> json(%{error: "無効なリクエスト"})
end
end

defp get_signature(conn) do
case get_req_header(conn, "omise-signature") do
[signature] -> {:ok, signature}
_ -> {:error, :no_signature}
end
end

defp verify_signature(payload, signature) do
secret = Application.get_env(:omise, :webhook_secret)
expected = :crypto.mac(:hmac, :sha256, secret, payload) |> Base.encode16(case: :lower)
Plug.Crypto.secure_compare(signature, expected)
end

defp handle_webhook(%{"key" => "charge.complete", "data" => data}) do
# チャージ完了を処理
end

defp handle_webhook(%{"key" => "refund.create", "data" => data}) do
# 払い戻し作成を処理
end

defp handle_webhook(_), do: :ok
end

よくある質問

Phoenixでウェブフックを処理する方法は?

defmodule MyAppWeb.WebhookController do
use MyAppWeb, :controller

def omise(conn, _params) do
{:ok, body, conn} = read_body(conn)
event = Jason.decode!(body)

case event["key"] do
"charge.complete" ->
handle_charge_complete(event["data"])
"refund.create" ->
handle_refund_create(event["data"])
end

json(conn, %{status: "ok"})
end

defp handle_charge_complete(%{"id" => charge_id}) do
{:ok, charge} = Omise.Charge.retrieve(charge_id)
MyApp.Payments.update_charge_status(charge)
end
end

実際の課金なしでテストする方法は?

# config/test.exsでテストAPIキーを使用
config :omise,
public_key: "pkey_test_123456789",
secret_key: "skey_test_123456789"

# テストトークンを使用
{:ok, charge} = Omise.Charge.create(
amount: 100_000,
currency: "THB",
card: "tokn_test_5086xl7ddjbases4sq3i"
)

# テストモードを検証
assert charge.livemode == false

部分払い戻しを処理する方法は?

def refund_charge(charge_id, refund_amount \\ nil) do
with {:ok, charge} <- Omise.Charge.retrieve(charge_id) do
refundable = charge.amount - charge.refunded

params = case refund_amount do
nil -> %{}
amount when amount <= refundable -> %{amount: round(amount * 100)}
_ -> {:error, :amount_exceeds_refundable}
end

case params do
{:error, reason} -> {:error, reason}
_ -> Omise.Refund.create(charge_id, params)
end
end
end

顧客に複数のカードを保存する方法は?

def add_card_to_customer(customer_id, token) do
Omise.Customer.update(customer_id, card: token)
end

def list_customer_cards(customer_id) do
with {:ok, customer} <- Omise.Customer.retrieve(customer_id) do
{:ok, customer.cards.data}
end
end

def charge_specific_card(customer_id, card_id, amount) do
Omise.Charge.create(
amount: round(amount * 100),
currency: "THB",
customer: customer_id,
card: card_id
)
end

サブスクリプション請求を実装する方法は?

defmodule MyApp.SubscriptionBilling do
def charge_monthly(customer_id, plan_amount) do
Omise.Charge.create(
amount: plan_amount,
currency: "THB",
customer: customer_id,
description: "サブスクリプション #{Date.utc_today()}"
)
end
end

# スケジューリングにQuantumを使用
config :my_app, MyApp.Scheduler,
jobs: [
{"0 0 1 * *", {MyApp.SubscriptionBilling, :charge_all, []}}
]

リトライロジックを実装する方法は?

def create_charge_with_retry(params, retries \\ 3) do
case Omise.Charge.create(params) do
{:ok, charge} ->
{:ok, charge}

{:error, _error} when retries > 0 ->
:timer.sleep(:math.pow(2, 3 - retries) * 1000 |> round())
create_charge_with_retry(params, retries - 1)

{:error, error} ->
{:error, error}
end
end

関連リソース

次のステップ

サポート

Elixirライブラリで問題が発生した場合:

  1. GitHub Issuesを確認してください
  2. APIドキュメントを確認してください
  3. support@omise.coに以下の情報をご連絡ください:
    • Elixirバージョン
    • omise-elixirライブラリバージョン
    • エラーメッセージとスタックトレース
    • 再現手順