同意フローを参照してください。
NuPay および PayPal Wallet の承認、追跡、およびウォレットの同意を管理します。
このページで
同意とは、サポートされているウォレットが DEUNA が支払いオプションを取得したり、アカウントを保存したり、購入を完了したりするために要求する、顧客による承認です。DEUNA は、この同意に関する 1 つの公開契約を公開し、その背後にあるプロバイダー固有のフローを調整します。
サポートされているプロバイダと動作#
| プロバイダ | 同意の取得元 | 承認プロセス | ステータスの取得元 | 再利用 |
|---|---|---|---|---|
| NuPay | ゲストまたは認証済み顧客、接続時に有効化されている場合 | 顧客はNubankの環境で承認 | プロバイダのWebhook; GET /merchants/orders/{order_token}/consent 最新のDEUNAの状態を返却 | 注文と顧客のIDに関連付けられており、サポートされている場合は、期限切れの承認を更新可能 |
| PayPal Wallet | PayPal Vaultを使用する認証済み顧客 | 顧客を返されたページにリダイレクトする redirect_url | DEUNAは、同意が検証可能になったときにPayPalに問い合わせる | 承認されたPayPalアカウントは、後で使用するために保存された支払い方法として登録されます。 |
他の支払い方法では、リダイレクト、OTP、または3DSを使用するが、この同意APIを使用しない。同意エンドポイントを呼び出すのは、選択されたウォレット接続が同意用に構成されている場合にのみ行う。
ライフサイクル#
通常の状態遷移は pending ~ success。 failed および expired を終了として扱う。認識されない、または拒否された状態を失敗として扱い、それを使用して購入を送信しない。
始める前に#
- NuPayまたはPayPalウォレット接続を、正しいストアと環境に合わせて構成する。
- 注文を作成する および、その設定を保持する。
order_token. - 再利用可能なPayPalアカウントの場合、顧客を認証し、同意リクエストでユーザーにベアラートークンを送信する。
- 支払い方法の応答を読み取る。PayPal Vaultの場合、
authorization.required: trueおよびauthorization.flow: "consent"顧客が同意を得る必要があることを示しています。返されたポーリングフィールドを使用し、固定されたタイミングを使用しないでください。 - を構成する
order.webhook_urls.notify_orderそのため、バックエンドで同意状態の変更を認識できます。
同意の作成#
POST /merchants/orders/{order_token}/consent
公開されているAPIゲートウェイのルートは、意図的に内部 /api/v1 サービスプレフィックス。
curl --request POST \
--url 'https://api.sandbox.deuna.io/merchants/orders/ORDER_TOKEN/consent' \
--header 'X-API-KEY: YOUR_PRIVATE_API_KEY' \
--header 'X-Store-Code: all' \
--header 'Authorization: Bearer USER_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"payment_method": "wallet",
"payment_method_id": "MERCHANT_PAYMENT_METHOD_ID",
"identity_document": "58188896454",
"identity_document_type": "CPF"
}'const response = await fetch("https://api.sandbox.deuna.io/merchants/orders/ORDER_TOKEN/consent", {
method: "POST",
headers: {
"X-API-KEY": "YOUR_PRIVATE_API_KEY",
"X-Store-Code": "all",
"Authorization": "Bearer USER_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"payment_method": "wallet",
"payment_method_id": "MERCHANT_PAYMENT_METHOD_ID",
"identity_document": "58188896454",
"identity_document_type": "CPF"
})
});
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/merchants/orders/ORDER_TOKEN/consent",
headers={
"X-API-KEY": "YOUR_PRIVATE_API_KEY",
"X-Store-Code": "all",
"Authorization": "Bearer USER_TOKEN",
"Content-Type": "application/json"
},
json={
"payment_method": "wallet",
"payment_method_id": "MERCHANT_PAYMENT_METHOD_ID",
"identity_document": "58188896454",
"identity_document_type": "CPF"
},
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.deuna.io/merchants/orders/ORDER_TOKEN/consent",
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-API-KEY: YOUR_PRIVATE_API_KEY",
"X-Store-Code: all",
"Authorization: Bearer USER_TOKEN",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode([
"payment_method" => "wallet",
"payment_method_id" => "MERCHANT_PAYMENT_METHOD_ID",
"identity_document" => "58188896454",
"identity_document_type" => "CPF"
])
]);
$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/merchants/orders/ORDER_TOKEN/consent"))
.header("X-API-KEY", "YOUR_PRIVATE_API_KEY")
.header("X-Store-Code", "all")
.header("Authorization", "Bearer USER_TOKEN")
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\n \"payment_method\": \"wallet\",\n \"payment_method_id\": \"MERCHANT_PAYMENT_METHOD_ID\",\n \"identity_document\": \"58188896454\",\n \"identity_document_type\": \"CPF\"\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/merchants/orders/ORDER_TOKEN/consent", strings.NewReader("{\n \"payment_method\": \"wallet\",\n \"payment_method_id\": \"MERCHANT_PAYMENT_METHOD_ID\",\n \"identity_document\": \"58188896454\",\n \"identity_document_type\": \"CPF\"\n }"))
if err != nil { panic(err) }
request.Header.Set("X-API-KEY", "YOUR_PRIVATE_API_KEY")
request.Header.Set("X-Store-Code", "all")
request.Header.Set("Authorization", "Bearer USER_TOKEN")
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_method | 推奨 | 使用する wallet. もし省略された場合、DEUNAは注文に対してその支払い方法を使用します。 |
payment_method_id | 推奨 | 注文の支払い方法応答で返される接続識別子。複数のウォレット接続が有効になっている場合に、曖昧さを回避します。 |
identity_document | NuPay | 顧客の身分証明書。存在しない場合は、注文の住所から推測できます。 |
identity_document_type | NuPay | ドキュメントの種類、例: CPF。存在しない場合は、注文の住所から推測できます。 |
認証されたユーザーの場合、ベアラートークンは、DEUNAが成功した同意をそのユーザーと接続に関連付けることを可能にします。ゲストの同意は注文に紐づきます。
応答エンベロープ
{
"id": "1625a32a-df4c-4d9b-aec1-4510b3625865",
"type": "transaction.authentication.pending",
"created": "1740608931",
"data": {
"request_id": "req_01JQ7X",
"order": {
"order_token": "7e975d44-a061-4d70-af0f-673f6ee56445",
"transaction_id": "merchant-order-1042",
"external_transaction_id": ""
},
"consent": {
"id": "6fe9a045-9a46-4b25-8b60-d5a9586494c5",
"status": "pending",
"expires_at": "2026-10-02T18:30:00Z",
"authorization_id": "provider-authorization-id",
"redirect_url": "https://provider.example/approve"
}
}
}ストア data.consent.idから制御します。 data.consent.status. 開く redirect_url NuPayは、プロバイダのアプリ内で承認を要求し、ブラウザのリダイレクトなしで処理を完了できます。
プロバイダーの承認完了#
PayPal Walletの場合、顧客を以下に誘導します。 data.consent.redirect_urlプロバイダーは、DEUNAの同意リダイレクトルートを通じて応答し、DEUNAは最終的なプロバイダーの状態を確認します。顧客がキャンセルした場合、同意は失敗としてマークされ、購入に使用してはなりません。
NuPay の場合、顧客に Nubank のインターフェースで承認を依頼してください。プロバイダーの Webhook は、DEUNA が保存している承認情報を更新します。
プロバイダーの承認 URL や DEUNA のリダイレクト URL を自分で作成しないでください。レスポンスに含まれる URL を使用してください。
最新のステータスを確認してください。#
GET /merchants/orders/{order_token}/consent
curl --request GET \
--url 'https://api.sandbox.deuna.io/merchants/orders/ORDER_TOKEN/consent?payment_method=wallet&payment_method_id=MERCHANT_PAYMENT_METHOD_ID' \
--header 'X-API-KEY: YOUR_PRIVATE_API_KEY' \
--header 'X-Store-Code: all' \
--header 'Authorization: Bearer USER_TOKEN'const response = await fetch("https://api.sandbox.deuna.io/merchants/orders/ORDER_TOKEN/consent?payment_method=wallet&payment_method_id=MERCHANT_PAYMENT_METHOD_ID", {
method: "GET",
headers: {
"X-API-KEY": "YOUR_PRIVATE_API_KEY",
"X-Store-Code": "all",
"Authorization": "Bearer USER_TOKEN"
}
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const data = await response.json();import requests
response = requests.request(
"GET",
"https://api.sandbox.deuna.io/merchants/orders/ORDER_TOKEN/consent?payment_method=wallet&payment_method_id=MERCHANT_PAYMENT_METHOD_ID",
headers={
"X-API-KEY": "YOUR_PRIVATE_API_KEY",
"X-Store-Code": "all",
"Authorization": "Bearer USER_TOKEN"
},
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.deuna.io/merchants/orders/ORDER_TOKEN/consent?payment_method=wallet&payment_method_id=MERCHANT_PAYMENT_METHOD_ID",
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-API-KEY: YOUR_PRIVATE_API_KEY",
"X-Store-Code: all",
"Authorization: Bearer USER_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/merchants/orders/ORDER_TOKEN/consent?payment_method=wallet&payment_method_id=MERCHANT_PAYMENT_METHOD_ID"))
.header("X-API-KEY", "YOUR_PRIVATE_API_KEY")
.header("X-Store-Code", "all")
.header("Authorization", "Bearer USER_TOKEN")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
)
func main() {
request, err := http.NewRequest("GET", "https://api.sandbox.deuna.io/merchants/orders/ORDER_TOKEN/consent?payment_method=wallet&payment_method_id=MERCHANT_PAYMENT_METHOD_ID", nil)
if err != nil { panic(err) }
request.Header.Set("X-API-KEY", "YOUR_PRIVATE_API_KEY")
request.Header.Set("X-Store-Code", "all")
request.Header.Set("Authorization", "Bearer USER_TOKEN")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}使用する authorization.start_polling_after_in_seconds および authorization.polling_interval_in_seconds します。ステータスが「完了」になった時点で、ポーリングを停止してください。 pending, 時に expires_at トランザクションが完了したとき、または顧客がフローを離れたときに、
GETリクエストは、create consentと同じ形式を使用します。常に両方を検査してください data.consent.status および data.error; ビジネスレベルのトランザクション結果は、HTTPリクエストが成功したとしても、エンベロープ内に表現できます。
同意 Webhook の処理#
DEUNA は、注文に対して同意の更新を送信します。 webhook_urls.notify_order URL。以下のイベントタイプを処理してください:
| イベントタイプ | 意味 |
|---|---|
transaction.authentication.pending | 認証が作成され、顧客またはプロバイダーによるアクションが必要です。 |
transaction.authentication.updated | 認証が成功し、同意を使用できます。 |
transaction.authentication.failed | 認証が失敗した場合、または顧客がキャンセルした場合。 |
transaction.authentication.expired | 同意が使用される前に期限切れになりました。 |
以下の内容で応答してください。 2xx 迅速に、イベントを重複処理 id、そして、現在の状態に依存する場合は、最新の同意を取得してください。ウェブフックの配信とGETポーリングは互いに補完し合います。チェックアウトは、どちらか一方の到着を許容する必要があります。詳細は、 Webhooks.
承認された同意を取得する#
NuPay
その後、 successをリクエストし、NuPayの分割払いオプションを取得します。DEUNAは、これらのオプションを取得し、ウォレットの購入を処理する際に、有効な同意認証を使用します。認証が期限切れで、プロバイダがリフレッシュをサポートしている場合、DEUNAは認証をリフレッシュを試みます。
PayPal Wallet
認証されたユーザーに対して、承認されたPayPalアカウントは、 stored_payment_methods. 以前に保存したメソッド識別子を、購入処理の際に送信してください。 payment_method; DEUNAは、利用、加盟店、およびPayPalとの連携が同一のユーザーに関連していることを確認してから、それを使用します。
保存されたウォレットの支払い方法を削除すると、関連する再利用可能な同意も削除されます。
再利用可能なPayPalアカウントを削除する
DELETE /users/payment-methods/{payment_method_id}/tokens/{payment_method}
使用する payment_method_id PayPal接続の識別子と、 payment_method および、 stored_payment_methodsで返される保存された方法の識別子を削除します。このユーザー認証されたエンドポイントは、プロバイダー上のウォレットアカウントを削除し、対応する再利用可能な同意をDEUNAで削除します。
curl --request DELETE \
--url 'https://api.sandbox.deuna.io/users/payment-methods/MERCHANT_PAYMENT_METHOD_ID/tokens/STORED_PAYMENT_METHOD_ID' \
--header 'Authorization: Bearer USER_TOKEN' \
--header 'X-Merchant-ID: MERCHANT_ID'const response = await fetch("https://api.sandbox.deuna.io/users/payment-methods/MERCHANT_PAYMENT_METHOD_ID/tokens/STORED_PAYMENT_METHOD_ID", {
method: "DELETE",
headers: {
"Authorization": "Bearer USER_TOKEN",
"X-Merchant-ID": "MERCHANT_ID"
}
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const data = await response.json();import requests
response = requests.request(
"DELETE",
"https://api.sandbox.deuna.io/users/payment-methods/MERCHANT_PAYMENT_METHOD_ID/tokens/STORED_PAYMENT_METHOD_ID",
headers={
"Authorization": "Bearer USER_TOKEN",
"X-Merchant-ID": "MERCHANT_ID"
},
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.deuna.io/users/payment-methods/MERCHANT_PAYMENT_METHOD_ID/tokens/STORED_PAYMENT_METHOD_ID",
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer USER_TOKEN",
"X-Merchant-ID: MERCHANT_ID"
]
]);
$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/users/payment-methods/MERCHANT_PAYMENT_METHOD_ID/tokens/STORED_PAYMENT_METHOD_ID"))
.header("Authorization", "Bearer USER_TOKEN")
.header("X-Merchant-ID", "MERCHANT_ID")
.method("DELETE", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
)
func main() {
request, err := http.NewRequest("DELETE", "https://api.sandbox.deuna.io/users/payment-methods/MERCHANT_PAYMENT_METHOD_ID/tokens/STORED_PAYMENT_METHOD_ID", nil)
if err != nil { panic(err) }
request.Header.Set("Authorization", "Bearer USER_TOKEN")
request.Header.Set("X-Merchant-ID", "MERCHANT_ID")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}正常な削除は以下の結果をもたらします。 204 No Contentもし、プロバイダーが購入時に保存されたアカウントが無効であると報告した場合、DEUNAも無効な再利用可能な同意を削除し、再度提示されないようにします。
安全な再試行の動作#
- 新しい同意を作成する前に、前の応答が失われた場合に現在の状態を確認します。
- 有効な
pendingまたはsuccess同意を再利用し、別のプロバイダーの認証を作成するのではなく、再利用します。 - 再試行しない
failedまたはexpired無期限に。原因を解決した後、新しい顧客主導の試行を開始してください。 - A
404とは、DEUNAが注文またはユーザーコンテキストに対する同意を得られないことを意味します。 - A
400は、無効なフィールド、サポートされていない接続、無効なゲストフロー、またはターミナルプロバイダーの結果を示す可能性があります。 - APIキーとユーザートークンを信頼できる場所に保管してください。リクエストヘッダーまたはプロバイダーの認証データをログに記録しないでください。
統合チェックリスト#
- 注文、接続、通貨、店舗、および環境が一致している。
- NuPayでは、身分証明書と種類が利用可能。
- 再利用可能なPayPalの同意を作成する前に、顧客が認証されている。
- アプリは、プロバイダによるリダイレクトとアプリによる承認の体験をサポート。
- ポーリングは、DEUNAによって返される頻度を使用し、ターミナル状態に到達すると停止。
notify_orderacepta y duplica los eventos de autenticación.- 購入は、以下の条件を満たした後に開始。
data.consent.status経由で提供されます。success. - 失敗、期限切れ、キャンセル、および再試行パスは、サンドボックスでテスト。