最初のサンドボックス決済処理
商社のバックエンドからサンドボックスでの注文決済を行い、検証された Webhook を通じて最終結果を確認する。
0の4の完了
このクイックスタートは、商社のバックエンドの購入エンドポイントを使用します。開始する前に、以下の手順を完了してください。 アカウントのセットアップ, 統合の選択、および、サンドボックスの商社が以下のものを持っていることを確認してください。
- サーバー上に保存されたプライベート API キー。
- 少なくとも1つのアクティブな支払い接続とルーティング戦略。
- 注文トークンと、選択したクライアント統合によって作成された支払い方法のトークン。
- DEUNAのウェブフックを受信できる、公開のHTTPSエンドポイント。
サーバー側のリクエストの準備#
サンドボックス環境のプライベートキーを、サーバーの秘密保管場所に読み込みます。 同じサンドボックスフローによって生成された注文トークンと支払い方法のトークンを、リクエストボディで使用できるようにします。
.envShell
DEUNA_PRIVATE_API_KEY=YOUR_SANDBOX_PRIVATE_API_KEY注文の支払処理#
注文とトークン化された支払い方法を、検証済みの加盟店向け購入エンドポイントに送信します。同じ X-Idempotency-Key および、ネットワークタイムアウトにより結果が不確実な場合に、リクエストボディを送信します。
curl --request POST \
--url https://api.sandbox.deuna.io/v2/merchants/orders/purchase \
--header "X-Api-Key: ${DEUNA_PRIVATE_API_KEY}" \
--header "X-Idempotency-Key: order_1042-attempt_1" \
--header "Content-Type: application/json" \
--data '{
"order_token": "YOUR_SANDBOX_ORDER_TOKEN",
"payer_info": {
"email": "buyer@example.com",
"external_user_id": "customer_1042"
},
"payment_source": {
"method_type": "credit_card",
"payment_method": "YOUR_PAYMENT_METHOD_TOKEN"
}
}'const response = await fetch("https://api.sandbox.deuna.io/v2/merchants/orders/purchase", {
method: "POST",
headers: {
"X-Api-Key": "${DEUNA_PRIVATE_API_KEY}",
"X-Idempotency-Key": "order_1042-attempt_1",
"Content-Type": "application/json"
},
body: JSON.stringify({
"order_token": "YOUR_SANDBOX_ORDER_TOKEN",
"payer_info": {
"email": "buyer@example.com",
"external_user_id": "customer_1042"
},
"payment_source": {
"method_type": "credit_card",
"payment_method": "YOUR_PAYMENT_METHOD_TOKEN"
}
})
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const data = await response.json();import requests
response = requests.request(
"POST",
"https://api.sandbox.deuna.io/v2/merchants/orders/purchase",
headers={
"X-Api-Key": "${DEUNA_PRIVATE_API_KEY}",
"X-Idempotency-Key": "order_1042-attempt_1",
"Content-Type": "application/json"
},
json={
"order_token": "YOUR_SANDBOX_ORDER_TOKEN",
"payer_info": {
"email": "buyer@example.com",
"external_user_id": "customer_1042"
},
"payment_source": {
"method_type": "credit_card",
"payment_method": "YOUR_PAYMENT_METHOD_TOKEN"
}
},
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.deuna.io/v2/merchants/orders/purchase",
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-Api-Key: ${DEUNA_PRIVATE_API_KEY}",
"X-Idempotency-Key: order_1042-attempt_1",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode([
"order_token" => "YOUR_SANDBOX_ORDER_TOKEN",
"payer_info" => [
"email" => "buyer@example.com",
"external_user_id" => "customer_1042"
],
"payment_source" => [
"method_type" => "credit_card",
"payment_method" => "YOUR_PAYMENT_METHOD_TOKEN"
]
])
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.sandbox.deuna.io/v2/merchants/orders/purchase"))
.header("X-Api-Key", "${DEUNA_PRIVATE_API_KEY}")
.header("X-Idempotency-Key", "order_1042-attempt_1")
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\n \"order_token\": \"YOUR_SANDBOX_ORDER_TOKEN\",\n \"payer_info\": {\n \"email\": \"buyer@example.com\",\n \"external_user_id\": \"customer_1042\"\n },\n \"payment_source\": {\n \"method_type\": \"credit_card\",\n \"payment_method\": \"YOUR_PAYMENT_METHOD_TOKEN\"\n }\n }"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
request, err := http.NewRequest("POST", "https://api.sandbox.deuna.io/v2/merchants/orders/purchase", strings.NewReader("{\n \"order_token\": \"YOUR_SANDBOX_ORDER_TOKEN\",\n \"payer_info\": {\n \"email\": \"buyer@example.com\",\n \"external_user_id\": \"customer_1042\"\n },\n \"payment_source\": {\n \"method_type\": \"credit_card\",\n \"payment_method\": \"YOUR_PAYMENT_METHOD_TOKEN\"\n }\n }"))
if err != nil { panic(err) }
request.Header.Set("X-Api-Key", "${DEUNA_PRIVATE_API_KEY}")
request.Header.Set("X-Idempotency-Key", "order_1042-attempt_1")
request.Header.Set("Content-Type", "application/json")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}正確な payment_source および、それらすべて specific_fields 選択された支払い方法とプロバイダーによって異なります。詳細については、 注文の支払い処理 を参照してください。
即時結果を処理#
読み取り order.payment.data.status および、返却された注文に必要な次のアクション。HTTP 2xx は、DEUNAがリクエストを受け入れた、または処理したことを意味します。これは、実際に資金が移動したことを証明するものではありません。
- 成功状態が確認された場合にのみ、処理を続行してください。 支払いワークフローとステータス.
- 3DS認証などの顧客のアクションを、再試行する前に必ず実行してください。
- 保留中または不確実な結果の場合、重複した試行を作成するのではなく、元の注文を取得してください。
- 同一性キーは、実質的に新しい支払い試行に対してのみ使用してください。
最終状態を確認してください。#
同期された応答を使用して顧客体験を更新しますが、履行の決定は、最新の検証された状態に基づいて行ってください。商人のWebhookを設定し、その署名を検証し、イベントを重複なく処理し、注文を調整してください。
server.jsJavaScript
app.post('/webhooks/deuna', express.raw({type: 'application/json'}), async (request, response) => {
const event = verifyDeunaSignature(request.body, request.headers);
await storeEventOnce(event.id);
await reconcileOrder(event.data.order_token);
response.sendStatus(200);
});