【Shopify.dev和訳】Apps/Payments/Processing a payment
この記事について
この記事は、Apps/Payments/Processing a Paymentの記事を和訳したものです。
記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。
Shopify アプリのご紹介
Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。
Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。
決済処理
支払い処理は、Shopify があなたのペイメントアプリに HTTP コールを行うときに始まります。あなたのアプリは、Shopify があなたのアプリの支払いページに顧客をリダイレクトするために使用するリダイレクト URL で応答します。支払いが確定した後、PaymentSessionResolveまたはPaymentSessionRejectのいずれかを使用して Shopify に結果を伝える必要があります。
決済アプリのフローの仕組み
次の図は、ペイメントアプリと Shopify の間の支払いフローの仕組みを示しています。
- お客様がチェックアウトを完了すると、支払いのリクエストが発生します。
- Shopify はバックエンドリクエストをペイメントアプリに送信し、請求される金額と通貨を指定します。
- 決済アプリは、パートナーのアプリがホストする決済ページのリダイレクト URL で応答します。(200 OK)
- Shopify は顧客をリダイレクト URL にリダイレクトします。
- ペイメントアプリは、購入者の支払い認証情報を収集し、バックエンドリクエストに記載されている通りに支払いを処理します。
- ペイメントアプリは、必要に応じてリトライポリシーを実装しながら、支払い処理の結果を Shopify に伝えます。
- Shopify はリダイレクト URL を返信します。(200 OK)
- アプリは顧客を Shopify にリダイレクトします。(301 リダイレクト)
- お客様はチェックアウトを続けます。
支払い処理では、アップストリームとダウンストリームの両方のリクエストが、payment ID
を使用した冪等キーである必要があります。
非同期通信
決済処理は、Shopify と決済アプリの間の HTTP による非同期通信に依存しています。非同期システムでは、強固な通信戦略を確保するためにリトライポリシーが重要となります。
要求事項
- Getting started building payments apps ガイドを完了しました。
- 一般的な取引要件を理解している。
- ペイメントアプリを構築するには、ペイメントアプリの要件を満たす必要があります。
スコープ
GraphQL ミューテーションを使用するには、アプリが決済アプリのアクセススコープを認識している必要があります。
決済フローの開始
支払いの流れは、Shopify からアプリ拡張機能の設定時に提供されたプロバイダの支払いセッション URL に送られる HTTP リクエストから始まります。このリクエストには、顧客と注文に関する情報が含まれています。
リクエストボディ
{
"id": "8BLFxjEHP5PkA1kNsb6iRKX9",
"gid": "gid://shopify/PaymentSession/8BLFxjEHP5PkA1kNsb6iRKX9",
"group": "W_CUXwaUd69aOjMMlWOui7eK",
"amount": "123.00",
"currency": "CAD",
"test": false,
"merchant_locale": "en",
"payment_method": {
"type": "offsite",
"data": {
"cancel_url": "https://my-test-shop.com/1/checkouts/4c94d6f5b93f726a82dadfe45cdde432"
}
},
"proposed_at": "2020-07-13T00:00:00Z",
"customer": {
"billing_address": {
"given_name": "Alice",
"family_name": "Smith",
"line1": "123 Street",
"line2": "Suite B",
"city": "Montreal",
"postal_code": "H2Z 0B3",
"province": "Quebec",
"country_code": "CAN",
"company": ""
},
"shipping_address": {
"given_name": "Alice",
"family_name": "Smith",
"line1": "123 Street",
"line2": "Suite B",
"city": "Montreal",
"postal_code": "H2Z 0B3",
"province": "Quebec",
"country_code": "CAN",
"company": ""
},
"email": "buyer@example.com",
"phone_number": "5555555555",
"locale": "fr"
},
"kind": "sale"
}
属性 | 詳細 | タイプ |
---|---|---|
id required
|
支払いの試みのための一意の識別子。idempotency key として使用されます。ある ID を持つリクエストは、以前に受け取った同じ ID を持つリクエストと同一であると仮定することができます。マーチャントが Shopify の注文とパートナーアプリで管理されている支払いを関連付けることができるように、この ID をマーチャントに表示する必要があります。 | String |
gid required
|
Shopify との通信時(GraphQL ミューテーションなどで)に支払いを識別します。 | String |
group required
|
お客様は、ある注文のためにブラウザで複数のタブを開くことがあります。それらのタブはすべて、同じグループに関連付けられます。その結果、Shopify は同じ id とgroup に対して複数の支払いフローを開始することができ、そのたびにお客様のアプリにリダイレクトされます。アプリは、id とgroup ごとに 1 回だけPaymentSessionResolve を呼び出す必要があります。 |
String |
amount required
|
課金される金額です。ロケールにかかわらず、値は常に小数点をセパレータとして使用して送信されます。 | Numeric |
cancel_url required
|
顧客が決済フローを終了してマーチャントのウェブサイトに戻る際にリダイレクトする URL です。cancel_url 属性は、顧客がプロバイダのページにいて、支払いをキャンセルして Shopify に戻ることを決めた場合にのみ使用してください。 |
String |
proposed_at required
|
同じグループの一部である支払試行を注文するために使用できます。 | String (ISO-8601) |
test required
|
ペイメントがテストモードかライブモードかを示します。詳細は、テストモードを参照してください。 | Boolean |
customer |
customer が含まれる場合は、customer.email またはcustomer.phone のいずれかが存在しなければなりませんが、両方ではありません。shipping_address とbilling_address には、line2 、province 、postal_code 、company の各フィールドがありますが、これらは顧客の居住地域に応じてオプションとなります。 |
Hash |
kind required
|
sale またはauthorization のいずれかです。支払いの承認をサポートしている場合、この値はマーチャントの設定に基づいて設定されます。オーソリとキャプチャを別々にサポートしていない場合、値は常に sale となります。sale 取引の場合は、このリクエストで即座に資金を捕捉する必要があります。authorization 取引の場合は、資金を保留しておき、後で Shopify がキャプチャリクエストを送信したときにキャプチャする必要があります。 |
String |
リクエストヘッダー
Shopify-Shop-Domain: my-test-shop.myshopify.com
Shopify-Request-Id: 94169f7e-ac8d-4ef4-9fd2-90f0791daddf
ヘッダー | 詳細 |
---|---|
Shopify-Shop-Domain required
|
マーチャントのパーマネントドメイン。どのマーチャントが支払いを開始したかを特定するために使用できます。 |
Shopify-Request-Id required
|
リクエストごとにユニークです。トラブルシューティングのための特定のリクエストを追跡するために使用できます。 |
レスポンス
Shopify は、支払いセッションの作成が成功するために、HTTP 2xx レスポンスを受信する必要があります。リクエストが失敗した場合は、何度も再試行され、最終的に「中止」状態に移行します。その時点で、購入者は Shopify のチェックアウトで支払いをやり直さなければなりません。レスポンスには、Shopify が買い手をリダイレクトするパートナーページの URL を含まなければなりません。
決済アプリ側でエラーが発生した場合、2xx で応答してはいけません。代わりに適切なエラーステータスコードを使ってください。
ペイロード例
{
"redirect_url": "https://buyer-payment-page.com/12345"
}
お支払い方法の変更
買い手が支払いのプロセスを正常に行った後に、PaymentSessionResolveミューテーションを呼び出す必要があります。
POST https://{shop_domain}/payments_apps/api/2021-07/graphql.json
mutation paymentSessionResolve($id: ID!, $expires: DateTime) {
paymentSessionResolve(id: $id, authorizationExpiresAt: $expires) {
paymentSession {
id
status {
code
}
nextAction {
action
context {
... on PaymentSessionActionsRedirect {
redirectUrl
}
}
}
}
userErrors {
field
message
}
}
}
id
引数は、ペイメントの gid
に相当します。
Varibales:
{
"id": "gid://shopify/PaymentSession/u0nwmSrNntjIWozmNslK5Tlq",
"expires": "2021-07-03T20:47:55Z"
}
JSON response:
redirectUrl
フィールドは、パートナーが買い手をリダイレクトするための URL です。
{
"data": {
"paymentSessionResolve": {
"paymentSession": {
"id": "gid://shopify/PaymentSession/u0nwmSrNntjIWozmNslK5Tlq",
"status": {
"code": "RESOLVED"
},
"nextAction": {
"action": "REDIRECT",
"context": {
"redirectUrl": "https://store-domain.myshopify.com/14376108/checkouts/c55510fa974f3ec73f9879d672880d9c/processing"
}
}
},
"userErrors": []
}
},
...
}
}
}
決済の拒否
買い手がプロバイダーとの支払いを完了できない場合、支払いは拒否されるべきです。これは Shopify にチェックアウトプロセスが停止することを知らせるものです。
PaymentSessionRejectミューテーションを使用して、支払いを拒否することができます。
POST https://{shop_domain}/payments_apps/api/2021-07/graphql.json
mutation PaymentSessionReject($id: ID!, $reason: PaymentSessionRejectionReasonInput!) {
paymentSessionReject(id: $id, reason: $reason) {
paymentSession {
id
status
nextAction {
action
context {
... on PaymentSessionActionsRedirect {
redirectUrl
}
}
}
}
userErrors {
field
message
}
}
}
Variables:
{
"id": "gid://shopify/PaymentSession/4DxXBdw1z3W47wOk8f2-A2ZP",
"reason": {
"code": "PROCESSING_ERROR",
"merchantMessage": "the payment didn't work"
}
}
response
{
"data": {
"paymentSessionReject": {
"paymentSession": {
"id": "gid://shopify/PaymentSession/4DxXBdw1z3W47wOk8f2-A2ZP",
"status": {
"code": "REJECTED"
}
},
"userErrors": []
}
}
}
拒絶には、支払いが拒絶された理由に関する情報が必要です。この情報は、PaymentSessionRejectionReasonInputでカプセル化されます。
PaymentSessionRejectionReasonInput.code
は、標準化されたエラーコードの列挙であるPaymentSessionStatusReasonRejectionCode
です。
PaymentSessionRejectionReasonInput.merchantMessage
引数は、支払いが拒否された理由を説明する、マーチャントに提示されるローカライズされたエラーメッセージです。
リトライポリシー
もし Shopify のサービスに障害が発生した場合(または 5xx ステータスコードが返された場合)、リクエストは再試行されなければなりません。リトライポリシーのセクションに記載されているガイドラインに従うことをお勧めします。
GraphQL リクエストの確認応答が届かない場合は、リトライポリシーを導入する必要があります。この間、お客様に「支払いは処理されたが、Shopify にアクセスできない」と通知することができます。注文が処理されたときに Shopify から通知を受け取ることを顧客に知らせることができます。さらに、推奨されるリトライの最大数が確認されずに経過した場合、顧客はマーチャントに直接連絡する必要があります。
次のアクション
PaymentSessionResolveミューテーションまたはPaymentSessionRejectミューテーションのいずれかから応答を受信すると、ペイメントアプリが実行する必要のある次のアクションがnextAction
で指定されます。
nextActionは、nil であるか、2 つのフィールドを含みます。nil の場合、ペイメントアプリには次のアクションが期待されない。
それ以外の場合、フィールドは以下のとおりである。
-
action
: アプリが実行しなければならないアクションのタイプを指定する列挙型。 -
context
: インラインフラグメントを必要とするユニオンタイプで、基礎となるタイプのデータにアクセスします。PaymentSessionActionsRedirectの型を取ります。
次のステップ
追加情報
Shopify アプリのご紹介
Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。
Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。
Discussion