From 96e0da9af9f6586d3a1eb912bc5f0ff61938c77e Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Thu, 4 Sep 2025 13:26:23 -0400 Subject: [PATCH 1/8] docs: update split payments page --- .../content/docs/guides/split-payments.mdx | 408 +++++++++++++----- docs/src/partials/code-snippets-template.mdx | 50 --- .../src/partials/grant-finish-interaction.mdx | 2 +- docs/src/partials/grant-start-interaction.mdx | 18 +- 4 files changed, 296 insertions(+), 182 deletions(-) delete mode 100644 docs/src/partials/code-snippets-template.mdx diff --git a/docs/src/content/docs/guides/split-payments.mdx b/docs/src/content/docs/guides/split-payments.mdx index 4ae85627..6882c877 100644 --- a/docs/src/content/docs/guides/split-payments.mdx +++ b/docs/src/content/docs/guides/split-payments.mdx @@ -12,11 +12,13 @@ import FinishInteraction from '/src/partials/grant-finish-interaction.mdx' Learn how to take a single payment and split the value between multiple recipients. ::: -Imagine making a purchase from an online marketplace. From your perspective, you’re sending a single payment to a merchant in exchange for a good. Behind the scenes, the marketplace receives a portion of the payment as a service fee. +Imagine making a purchase from an online marketplace. From your perspective, you're sending a single payment to a merchant in exchange for a good. Behind the scenes, the marketplace receives a portion of the payment as a service fee. There's a few ways for the marketplace to collect their fee. For example, it could receive the full amount, deduct the fee, then send the rest to the merchant. However, holding funds for the merchant, even for a second, requires compliance with certain financial rules and regulations. A better way is to ensure both parties only receive the amount they're supposed to receive, directly from the user. -Remember, Open Payments doesn't execute payments or touch money in any way. It's used to issue payment instructions before any money movement occurs. Examples of payment instructions are, "of the $6 purchase, pay the marketplace $1 and the merchant $5." This way, funds meant for one party never pass through the other party. +Remember, Open Payments doesn't execute payments or touch money in any way. It's used to issue payment instructions before any money movement occurs. An example of a payment instruction is, "of the $6 purchase, pay the marketplace $1 and the merchant $5." This way, funds meant for one party never pass through the other party. + +## Scenario For this guide, you'll assume the role of a platform operator of an online marketplace. The guide explains how to split a customer's $100 USD payment into two incoming payments. The merchant will receive 99% of the payment while you keep 1% as a fee. @@ -50,7 +52,7 @@ The three parties involved in the transaction are the: When a customer initiates a payment, your platform must get wallet address information for the customer, the merchant, and you, as the operator. -Let's assume your wallet address already saved to your platform, as is the merchant's. Let's also assume the customer provided their wallet address at the beginning of the checkout flow. +Let's assume your wallet address is already saved to your platform, as is the merchant's. Let's also assume the customer provided their wallet address at the beginning of the checkout flow. Call the [Get Wallet Address API](/apis/wallet-address-server/operations/get-wallet-address) for each address. @@ -60,52 +62,60 @@ Call the [Get Wallet Address API](/apis/wallet-address-server/operations/get-wal const customerWalletAddress = await client.walletAddress.get({ url: 'https://cloudninebank.example.com/customer' }) - -const merchantWalletAddress = await client.walletAddress.get({ -url: 'https://happylifebank.example.com/merchant' -}) - -const platformWalletAddress = await client.walletAddress.get({ -url: 'https://coolwallet.example.com/platform' -}) - -```` + const merchantWalletAddress = await client.walletAddress.get({ + url: 'https://happylifebank.example.com/merchant' + }) + const platformWalletAddress = await client.walletAddress.get({ + url: 'https://coolwallet.example.com/platform' + }) +``` +
+Example response +The following shows an example response from the customer's wallet provider. Similar responses will be returned from the merchant's and platform's wallet provider. +```json wrap +{ + "id": "https://cloudninebank.example.com/customer", + "assetCode": "USD", + "assetScale": 2, + "authServer": "https://auth.cloudninebank.example.com/", + "resourceServer": "https://cloudninebank.example.com/op" +} +``` +
+ ### 2. Request incoming payment grants Use the merchant and platform `authServer` details, received in the previous step, to call the [Grant Request API](/apis/auth-server/operations/post-request). -The purpose of these calls is to obtain access tokens that allow your platform to request an incoming payment resource be created on the merchant's wallet account and your wallet account. +These calls obtain access tokens that allow your platform to request an incoming payment resource be created on the merchant's wallet account and your wallet account. :::note[Alternate scenario] If you and the merchant use the same account servicing entity, and the authorization server information received is the same for you both, you only need one `incomingPayment` grant. ::: - -```ts wrap -const merchantIncomingPaymentGrant = await client.grant.request( - { - url: merchantWalletAddress.authServer - }, - { - access_token: { - access: [ - { - type: "incoming-payment", - actions: ["read", "create"], - }, - ], - }, - }, -); -```` - - - + ```ts wrap + // Merchant + const merchantIncomingPaymentGrant = await client.grant.request( + { + url: merchantWalletAddress.authServer + }, + { + access_token: { + access: [ + { + type: "incoming-payment", + actions: ["read", "create"], + }, + ], + }, + }, + ); + // Platform const platformIncomingPaymentGrant = await client.grant.request( { url: platformWalletAddress.authServer @@ -121,30 +131,49 @@ const merchantIncomingPaymentGrant = await client.grant.request( }, }, ); - ``` +```` -### 3. Request the creation of incoming payment resources - -Use the access tokens returned in the previous responses to call the [Create Incoming Payment API](/apis/resource-server/operations/create-incoming-payment). +
+Example response +The following shows an example response from the merchant's wallet provider. A similar response will be returned from your wallet provider. + +```json wrap +{ + "access_token": { + "value": "...", // access token value for incoming payment grant + "manage": "https://happylifebank.example.com/token/{...}", // management uri for access token + "access": [ + { + "type": "incoming-payment", + "actions": ["create", "read"] + } + ] + }, + "continue": { + "access_token": { + "value": "..." // access token for continuing the request + }, + "uri": "https://happylifebank.example.com/continue/{...}" // continuation request uri + } +} +``` -The purpose of these calls is to request an incoming payment resource be created on the merchant's wallet account and your wallet account. +
-Remember that you're retaining 1% of the customer's $100 USD payment as a fee. +### 3. Request the creation of incoming payment resources -Include the following in both requests, along with any other required parameters. +Use the access tokens returned in the previous responses to call the [Create Incoming Payment API](/apis/resource-server/operations/create-incoming-payment). -- `incomingAmount` object - - `value` - The maximum amount to pay into a given wallet address. - - `assetCode` - The code used by the wallet account, provided in the Get Wallet Address API's response. - - `assetScale` - The scale used by the wallet account, provided in the Get Wallet Address API's response. +This call requests an incoming payment resource be created on the merchant's wallet account and your wallet account. -The full `value` of $100 is `10000`. The merchant will receive 99% (`9900`) and you will receive 1% (`100`). +Remember that the merchant is receiving 99% of the payment ($99.00 or `9900`) while you are keeping 1% as a fee ($1.00 or `100`). - + ```ts wrap + // Merchant const merchantIncomingPayment = await client.incomingPayment.create( { url: merchantWalletAddress.resourceServer, @@ -159,10 +188,7 @@ The full `value` of $100 is `10000`. The merchant will receive 99% (`9900`) and }, }, ) - ``` - - - ```ts wrap + // Platform const platformIncomingPayment = await client.incomingPayment.create( { url: platformWalletAddress.resourceServer, @@ -177,51 +203,110 @@ The full `value` of $100 is `10000`. The merchant will receive 99% (`9900`) and }, }, ) - ``` +``` +
+Example response +The following shows an example response from the merchant's wallet provider. A similar response will be returned from your wallet provider, but your incoming amount `value` will be `100`. + +```json wrap +{ + "id": "https://happylifebank.example.com/incoming-payments/{...}", // url identifying the incoming payment + "walletAddress": "https://happylifebank.example.com/merchant", + "incomingAmount": { + "value": "9900", + "assetCode": "USD", + "assetScale": 2 + }, + "receivedAmount": { + "value": "0", + "assetCode": "USD", + "assetScale": 2 + }, + "completed": false, + "createdAt": "2025-03-12T23:20:50.52Z", + "methods": [ + { + "type": "ilp", + "ilpAddress": "...", // ilp address to use when establishing a STREAM connection + "sharedSecret": "..." // base64 url-encoded shared secret to use when establishing a STREAM connection + } + ] +} +``` + +
+ ### 4. Request a quote grant Use the customer's `authServer` details, received in Step 1, to call the [Grant Request API](/apis/auth-server/operations/post-request). -The purpose of this call is to obtain an access token that allows your platform to request quote resources be created on the customer's wallet account. +This call obtains an access token that allows your platform to request quote resources be created on the customer's wallet account. - - ```ts wrap - const customerQuoteGrant = await client.grant.request( - { - url: customerWalletAddress.authServer - }, - { - access_token: { - access: [ - { - type: 'quote', - actions: ['create', 'read'] - } - ] + + ```ts wrap + const customerQuoteGrant = await client.grant.request( + { + url: customerWalletAddress.authServer + }, + { + access_token: { + access: [ + { + type: 'quote', + actions: ['create', 'read'] + } + ] + } } - } - ) - ``` - + ) + ``` + +
+ Example response + +```json wrap +{ + "access_token": { + "value": "...", // access token value for quote grant + "manage": "https:/cloudninebank.example.com/token/{...}", // management uri for access token + "access": [ + { + "type": "quote", + "actions": ["create", "read"] + } + ] + }, + "continue": { + "access_token": { + "value": "..." // access token for continuing the request + }, + "uri": "https://auth.cloudninebank.example.com/continue/{...}" // continuation request uri + } +} +``` + +
+ ### 5. Request the creation of quote resources Use the access token, received in the previous step, to call the [Create Quote API](/apis/resource-server/operations/create-quote). -The purpose of this call is to request a quote resource be created on the customer's wallet account. Since the customer needs a quote resource for the merchant and the platform, we'll call the API twice using the same access token. +This call requests a quote resource be created on the customer's wallet account. Since the customer needs a quote resource for the merchant and the platform, we'll call the API twice using the same access token. First, let's request a quote resource associated with the merchant. The request must contain the `receiver`, which is the merchant's incoming payment `id`, along with any other required parameters. The `id` was returned in the Create an Incoming Payment API response in Step 3. Next, call the Create Quote API again and request a quote resource associated with the platform's incoming payment `id`. - + ```ts wrap + // Merchant const merchantQuote = await client.quote.create( { url: customerWalletAddress.resourceServer, @@ -233,10 +318,7 @@ Next, call the Create Quote API again and request a quote resource associated wi receiver: merchantIncomingPayment.id } ) - ``` - - - ```ts wrap + // Platform const platformQuote = await client.quote.create( { url: customerWalletAddress.resourceServer, @@ -248,34 +330,55 @@ Next, call the Create Quote API again and request a quote resource associated wi receiver: platformIncomingPayment.id } ) - ``` +``` Each response returns a `receiveAmount`, a `debitAmount`, and other required information. -- `receiveAmount` - The `incomingAmount` value from the incoming payment resource - `debitAmount` - The amount the customer must pay toward the incoming payment resource (`receiveAmount` plus any applicable fees) +- `receiveAmount` - The `incomingAmount` value from the incoming payment resource + +
+Example response + The following shows an example response from the merchant's wallet provider. A similar response will be returned from your wallet provider. + +```json wrap +{ + "id": "https://cloudninebank.example.com/quotes/{...}", // url identifying the quote + "walletAddress": "https://cloudninebank.example.com/customer", + "receiver": "https://happylifebank.example.com/incoming-payments/{...}", // url of the incoming payment the quote is created for + "debitAmount": { + "value": "9900", + "assetCode": "USD", + "assetScale": 2 + }, + "receiveAmount": { + "value": "9900", + "assetCode": "USD", + "assetScale": 2 + }, + "method": "ilp", + "createdAt": "2025-03-12T23:22:51.50Z" +} +``` + +
### 6. Request an interactive outgoing payment grant Use the customer's `authServer` information received in Step 1 to call the [Grant Request API](/apis/auth-server/operations/post-request). -The purpose of this call is to obtain an access token that allows your platform to request outgoing payment resources be created on the customer's wallet account. +This call obtains an access token that allows your platform to request outgoing payment resources be created on the customer's wallet account. -Include the following in the request, along with any other required parameters. - -- `limits` object - - `receiveAmount` object - - `value` - The total amount the customer has agreed to pay. - - `assetCode` - The code used by the wallet account, provided in the Get Wallet Address API’s response. - - `assetScale` - The scale used by the wallet account, provided in the Get Wallet Address API’s response. - ```ts wrap + const combinedQuoteAmount = quote1.debitAmount.value + // '9900' + quote2.debitAmount.value // '100' + const pendingCustomerOutgoingPaymentGrant = await client.grant.request( { url: customerWalletAddress.authServer @@ -291,7 +394,7 @@ Include the following in the request, along with any other required parameters. receiveAmount: { assetCode: 'USD', assetScale: 2, - value: '10000' + value: 'combinedQuoteAmount', } } } @@ -301,7 +404,7 @@ Include the following in the request, along with any other required parameters. start: ['redirect'], finish: { method: 'redirect', - uri: 'http://localhost:3344', + uri: 'https://paymentplatform.example/finish/{...}', // finish uri of the customer wallet address' auth server nonce: NONCE } } @@ -311,6 +414,27 @@ Include the following in the request, along with any other required parameters. +
+ Example response + +```json wrap +{ + "interact": { + "redirect": "https://auth.interledger-test.dev/{...}", // uri to redirect the customer to, to begin interaction + "finish": "..." // unique key to secure the callback + }, + "continue": { + "access_token": { + "value": "..." // access token for continuing the outgoing payment grant request + }, + "uri": "https://auth.interledger-test.dev/continue/{...}", // uri for continuing the outgoing payment grant request + "wait": 30 + } +} +``` + +
+ ### 7. Start interaction with the customer @@ -327,30 +451,58 @@ In our example, we're assuming the IdP the customer interacted with has a user i In a scenario where a user interface isn't available, consider implementing a polling mechanism to check for the completion of the interaction. ::: -Call the [Grant Continuation Request API](/apis/auth-server/operations/post-continue). The purpose of this call is to request an access token that allows your platform to request outgoing payment resources be created on the customer's wallet account. - -Issue the request to the `continue uri` provided in the initial outgoing payment grant response (Step 6). For example: +Call the [Grant Continuation Request API](/apis/auth-server/operations/post-continue). This call requests an access token that allows your platform to request outgoing payment resources be created on the customer's wallet account. -`POST https://auth.interledger-test.dev/continue/4CF492MLVMSW9MKMXKHQ` +Issue the request to the `continue.uri` provided in the initial outgoing payment grant response (Step 6). Include the `interact_ref` returned in the redirect URI's query parameters. - - ```ts wrap - const customerOutgoingPaymentGrant = await client.grant.continue( - { - url: pendingCustomerOutgoingPaymentGrant.continue.uri, - accessToken: pendingCustomerOutgoingPaymentGrant.continue.access_token.value - }, - { - interact_ref: interactRef - } - ) - ``` - + + ```ts wrap + const customerOutgoingPaymentGrant = await client.grant.continue( + { + url: pendingCustomerOutgoingPaymentGrant.continue.uri, + accessToken: pendingCustomerOutgoingPaymentGrant.continue.access_token.value + }, + { + interact_ref: interactRef + } + ) + ``` + +
+ Example response + +```json wrap +{ + "access_token": { + "value": "...", // access token value for the outgoing payment grant continuation + "manage": "https://auth.cloudninebank.example.com/token/{...}", // management uri for access token + "access": [ + { + "type": "outgoing-payment", + "actions": ["create", "read"], + "identifier": "https://cloudninebank.example.com/customer", + "limits": { + "receiver": "https://happylifebank.example.com/incoming-payments/{...}" // url of the incoming payment that's being paid + } + } + ] + }, + "continue": { + "access_token": { + "value": "..." // access token for continuing the request + }, + "uri": "https://auth.cloudninebank.example.com/continue/{...}" // continuation request uri + } +} +``` + +
+ ### 10. Request the creation of outgoing payment resources Recall that the Create Quote API responses for the merchant and your platform (Step 5) both included a `debitAmount` and a `receiveAmount`. The responses also included an `id` which is a URL to identify each quote. @@ -362,8 +514,9 @@ Use the access tokens returned in Step 5 to call the [Create Outgoing Payment AP The purpose of these calls is to request an outgoing payment resource be created on the customer's wallet account: one for the merchant and one for your platform. Include the appropriate `quoteId` in each request. - + ```ts wrap + // Merchant const customerOutgoingPayment = await client.outgoingPayment.create( { url: customerWalletAddress.resourceServer, @@ -374,10 +527,7 @@ The purpose of these calls is to request an outgoing payment resource be created quoteId: merchantQuote.id } ) - ``` - - - ```ts wrap + // Platform const customerOutgoingPayment = await client.outgoingPayment.create( { url: customerWalletAddress.resourceServer, @@ -388,6 +538,36 @@ The purpose of these calls is to request an outgoing payment resource be created quoteId: platformQuote.id } ) - ``` +``` + +
+Example response +The following shows an example response when an outgoing payment resource is created on the customer's account for the merchant. A similar response will be returned when an outgoing payment resource is created for you, as the wallet provider. + +```json wrap +{ + "id": "https://cloudninebank.example.com/outgoing-payments/{...}", // url identifying the outgoing payment + "walletAddress": "https://cloudninebank.example.com/customer", + "receiver": "https://happylifebank.example.com/incoming-payments/{...}", // url of the incoming payment being paid + "debitAmount": { + "value": "9900", + "assetCode": "USD", + "assetScale": 2 + }, + "receiveAmount": { + "value": "9900", + "assetCode": "USD", + "assetScale": 2 + }, + "sentAmount": { + "value": "0", + "assetCode": "USD", + "assetScale": 2 + }, + "createdAt": "2022-03-12T23:20:54.52Z" +} +``` + +
diff --git a/docs/src/partials/code-snippets-template.mdx b/docs/src/partials/code-snippets-template.mdx deleted file mode 100644 index eb2a05d4..00000000 --- a/docs/src/partials/code-snippets-template.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Change this title ---- - -import { CodeBlock } from '@interledger/docs-design-system' -import { Tabs, TabItem } from '@astrojs/starlight/components' -import FullSnippet from '/src/components/FullSnippet.astro' -import ChunkedSnippet from '/src/components/ChunkedSnippet.astro' -import Global from '/src/partials/global-prerequisites.mdx' -import Ts from '/src/partials/ts-import-initialize.mdx' - -

- Overview paragraph(s) -

- -## Before you begin - - - -## H2 - - - - - -```html - -``` - - - - -
-View full source - -Delete the contents of this details tag and replace it with a link to the raw source -file like so: - -```html - -``` - -
- -## References - -- [Link to concept page(s)]() -- [API specification]() diff --git a/docs/src/partials/grant-finish-interaction.mdx b/docs/src/partials/grant-finish-interaction.mdx index 163dfa06..f93539e0 100644 --- a/docs/src/partials/grant-finish-interaction.mdx +++ b/docs/src/partials/grant-finish-interaction.mdx @@ -2,5 +2,5 @@ The user interacts with the authorization server through the server’s interfac Provided the user approves the grant, the authorization server: -- Sends the user to your client’s previously defined `finish.uri`. The means by which the server sends the user to the URI is out of scope, but common options include redirecting the user from a web page and launching the system browser with the target URI. +- Sends the user to the `finish.uri` provided in the interactive ougoing payment grant request. The means by which the server sends the user to the URI is out of scope, but common options include redirecting the user from a web page and launching the system browser with the target URI. - Secures the redirect by adding a unique hash, allowing your client to validate the `finish` call, and an interaction reference as query parameters to the URI. diff --git a/docs/src/partials/grant-start-interaction.mdx b/docs/src/partials/grant-start-interaction.mdx index 9efe04a8..3f21f012 100644 --- a/docs/src/partials/grant-start-interaction.mdx +++ b/docs/src/partials/grant-start-interaction.mdx @@ -1,19 +1,3 @@ -Once your client receives the authorization server’s response, it must send the user to the `interact.redirect` URI contained in the response. This starts the interaction flow. +Once the client receives the authorization server’s response, it must send the user to the `interact.redirect` URI contained in the response. This starts the interaction flow. The response also includes a `continue` object, which is essential for managing the interaction and obtaining explicit user consent for outgoing payment grants. The `continue` object contains an access token and a URI that the client will use to finalize the grant request after the user has completed their interaction with the identity provider (IdP). This ensures that the client can securely obtain the necessary permissions to proceed with the payment process. - -```json title="Example response" wrap -{ - "interact": { - "redirect": "https://auth.interledger-test.dev/4CF492MLVMSW9MKMXKHQ", - "finish": "4105340a-05eb-4290-8739-f9e2b463bfa7" - }, - "continue": { - "access_token": { - "value": "33OMUKMKSKU80UPRY5NM" - }, - "uri": "https://auth.interledger-test.dev/continue/4CF492MLVMSW9MKMXKHQ", - "wait": 30 - } -} -``` From b4507d21f1d20fd1246671edbd874e1ae47a58da Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Mon, 8 Sep 2025 08:22:25 -0400 Subject: [PATCH 2/8] Update docs/src/content/docs/guides/split-payments.mdx Co-authored-by: Max Kurapov --- docs/src/content/docs/guides/split-payments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/split-payments.mdx b/docs/src/content/docs/guides/split-payments.mdx index 6882c877..912597ad 100644 --- a/docs/src/content/docs/guides/split-payments.mdx +++ b/docs/src/content/docs/guides/split-payments.mdx @@ -297,7 +297,7 @@ This call obtains an access token that allows your platform to request quote res Use the access token, received in the previous step, to call the [Create Quote API](/apis/resource-server/operations/create-quote). -This call requests a quote resource be created on the customer's wallet account. Since the customer needs a quote resource for the merchant and the platform, we'll call the API twice using the same access token. +This call requests a quote resource be created on the customer's wallet account. Since the customer needs to get a quote for both of the incoming payments at the merchant and the platform, we'll call the API twice using the same access token. First, let's request a quote resource associated with the merchant. The request must contain the `receiver`, which is the merchant's incoming payment `id`, along with any other required parameters. The `id` was returned in the Create an Incoming Payment API response in Step 3. From 54d8c7f2f9552a87a745dc39e47acfb97021c1cb Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Mon, 8 Sep 2025 08:23:11 -0400 Subject: [PATCH 3/8] Update docs/src/content/docs/guides/split-payments.mdx Co-authored-by: Max Kurapov --- docs/src/content/docs/guides/split-payments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/split-payments.mdx b/docs/src/content/docs/guides/split-payments.mdx index 912597ad..b44b113a 100644 --- a/docs/src/content/docs/guides/split-payments.mdx +++ b/docs/src/content/docs/guides/split-payments.mdx @@ -394,7 +394,7 @@ This call obtains an access token that allows your platform to request outgoing receiveAmount: { assetCode: 'USD', assetScale: 2, - value: 'combinedQuoteAmount', + value: combinedQuoteAmount, } } } From e25865f4b34ef771bcb9d75abaa66ac2d8282a88 Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Mon, 8 Sep 2025 08:25:17 -0400 Subject: [PATCH 4/8] Apply suggestion from @mkurapov Co-authored-by: Max Kurapov --- docs/src/content/docs/guides/split-payments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/split-payments.mdx b/docs/src/content/docs/guides/split-payments.mdx index b44b113a..35137ba3 100644 --- a/docs/src/content/docs/guides/split-payments.mdx +++ b/docs/src/content/docs/guides/split-payments.mdx @@ -391,7 +391,7 @@ This call obtains an access token that allows your platform to request outgoing type: 'outgoing-payment', actions: ['read', 'create'], limits: { - receiveAmount: { + debitAmount: { assetCode: 'USD', assetScale: 2, value: combinedQuoteAmount, From 8ecb3a44cfbbfc1f3b13bdcda8bb875055763b00 Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Mon, 8 Sep 2025 08:25:40 -0400 Subject: [PATCH 5/8] Apply suggestion from @mkurapov Co-authored-by: Max Kurapov --- docs/src/content/docs/guides/split-payments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/split-payments.mdx b/docs/src/content/docs/guides/split-payments.mdx index 35137ba3..90766d2d 100644 --- a/docs/src/content/docs/guides/split-payments.mdx +++ b/docs/src/content/docs/guides/split-payments.mdx @@ -404,7 +404,7 @@ This call obtains an access token that allows your platform to request outgoing start: ['redirect'], finish: { method: 'redirect', - uri: 'https://paymentplatform.example/finish/{...}', // finish uri of the customer wallet address' auth server + uri: 'https://paymentplatform.example/finish/{...}', // where to redirect the customer after they've completed interaction nonce: NONCE } } From 36d221154f6cd28471d305a7f4dc53b2efafa6eb Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Mon, 8 Sep 2025 08:35:02 -0400 Subject: [PATCH 6/8] docs: updates based on feedback --- docs/src/content/docs/guides/split-payments.mdx | 10 +++++----- docs/src/partials/grant-finish-interaction.mdx | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/src/content/docs/guides/split-payments.mdx b/docs/src/content/docs/guides/split-payments.mdx index 9f2a28ce..96be799c 100644 --- a/docs/src/content/docs/guides/split-payments.mdx +++ b/docs/src/content/docs/guides/split-payments.mdx @@ -83,7 +83,7 @@ Use the merchant and platform `authServer` details, received in the previous ste These calls obtain access tokens that allow your platform to request an incoming payment resource be created on the merchant's wallet account and your wallet account. :::note[Alternate scenario] -If you and the merchant use the same account servicing entity, and the authorization server information received is the same for you both, you only need one `incomingPayment` grant. +If you and the merchant use the same account servicing entity, and as a result, the same authorization server, you only need one `incomingPayment` grant. ::: @@ -203,7 +203,7 @@ The following shows an example response from the merchant's wallet provider. A s ```json wrap { - "id": "https://happylifebank.example.com/incoming-payments/{...}", // url identifying the incoming payment + "id": "https://happylifebank.example.com/incoming-payments/{...}", "walletAddress": "https://happylifebank.example.com/merchant", "incomingAmount": { "value": "9900", @@ -220,8 +220,8 @@ The following shows an example response from the merchant's wallet provider. A s "methods": [ { "type": "ilp", - "ilpAddress": "...", // ilp address to use when establishing a STREAM connection - "sharedSecret": "..." // base64 url-encoded shared secret to use when establishing a STREAM connection + "ilpAddress": "...", + "sharedSecret": "..." } ] } @@ -469,7 +469,7 @@ Include the `interact_ref` returned in the redirect URI's query parameters. ```json wrap { "access_token": { - "value": "...", // access token value for the outgoing payment grant continuation + "value": "...", // final access token required before creating outgoing payments "manage": "https://auth.cloudninebank.example.com/token/{...}", // management uri for access token "access": [ { diff --git a/docs/src/partials/grant-finish-interaction.mdx b/docs/src/partials/grant-finish-interaction.mdx index f93539e0..7ff2f59f 100644 --- a/docs/src/partials/grant-finish-interaction.mdx +++ b/docs/src/partials/grant-finish-interaction.mdx @@ -2,5 +2,5 @@ The user interacts with the authorization server through the server’s interfac Provided the user approves the grant, the authorization server: -- Sends the user to the `finish.uri` provided in the interactive ougoing payment grant request. The means by which the server sends the user to the URI is out of scope, but common options include redirecting the user from a web page and launching the system browser with the target URI. -- Secures the redirect by adding a unique hash, allowing your client to validate the `finish` call, and an interaction reference as query parameters to the URI. +- Sends the user to the `finish.uri` provided in the interactive outgoing payment grant request. The means by which the server sends the user to the URI is out of scope, but common options include redirecting the user from a web page and launching the system browser with the target URI. +- Secures the redirect by adding a [unique hash](/identity/hash-verification), allowing your client to validate the `finish` call, and an interaction reference as query parameters to the URI. From 72a95a335d023de19878a177da4901e3054911cc Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Mon, 8 Sep 2025 08:35:39 -0400 Subject: [PATCH 7/8] docs: prettier --- docs/src/content/docs/sdk/before-you-begin.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/sdk/before-you-begin.mdx b/docs/src/content/docs/sdk/before-you-begin.mdx index d92fad4e..7f7924bc 100644 --- a/docs/src/content/docs/sdk/before-you-begin.mdx +++ b/docs/src/content/docs/sdk/before-you-begin.mdx @@ -82,7 +82,7 @@ Before you can initialize an authenticated Open Payments client, you must obtain Developer keys tab with account expanded, showing the upload key and the generate public and private key buttons 4. Click **Generate public & private key**. 5. Enter any **nickname** for the key pair, then click **Generate keys**. A file named `private.key` automatically downloads to your machine - Generate public and private key screen with nickname field + Generate public and private key screen with nickname field Key pair generation success screen 6. Click **Close**. Your key ID appears on the screen, along with a **Show/Hide** option for your public key. Developer keys tab with account expanded, showing the newly generated key id and an option to show the public key From 1b096f3e21ffb7acb548360c42b55a0788250faf Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:34:29 -0400 Subject: [PATCH 8/8] docs: addtl feedback --- docs/src/content/docs/guides/split-payments.mdx | 10 ++++------ docs/src/content/docs/sdk/before-you-begin.mdx | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/src/content/docs/guides/split-payments.mdx b/docs/src/content/docs/guides/split-payments.mdx index b9bbd31d..ecce5f37 100644 --- a/docs/src/content/docs/guides/split-payments.mdx +++ b/docs/src/content/docs/guides/split-payments.mdx @@ -497,17 +497,15 @@ Include the `interact_ref` returned in the redirect URI's query parameters. Recall that the Create Quote API responses for the merchant and your platform (Step 5) both included a `debitAmount` and a `receiveAmount`. The responses also included an `id` which is a URL to identify each quote. -Because the quotes contain debit and receive amounts, we won't specify any other amounts when making a Create Outgoing Payment API request. Instead, we will specify a `quoteId`. +Because the quotes contain debit and receive amounts, we won't specify any other amounts when setting up the outgoing payments. Instead, we will specify a `quoteId`. -Use the access tokens returned in Step 5 to call the [Create Outgoing Payment API](/apis/resource-server/operations/create-outgoing-payment). - -The purpose of these calls is to request an outgoing payment resource be created on the customer's wallet account: one for the merchant and one for your platform. Include the appropriate `quoteId` in each request. +Use the access token returned in Step 5 that's associated with the merchant to call the [Create Outgoing Payment API](/apis/resource-server/operations/create-outgoing-payment). Include the appropriate `quoteId` in the request. Now, do the same with the access token associated with your platform. ```ts wrap // Merchant - const customerOutgoingPayment = await client.outgoingPayment.create( + const customerOutgoingPaymentToMerchant = await client.outgoingPayment.create( { url: customerWalletAddress.resourceServer, accessToken: customerOutgoingPaymentGrant.access_token.value @@ -518,7 +516,7 @@ The purpose of these calls is to request an outgoing payment resource be created } ) // Platform - const customerOutgoingPayment = await client.outgoingPayment.create( + const customerOutgoingPaymentToPlatform = await client.outgoingPayment.create( { url: customerWalletAddress.resourceServer, accessToken: customerOutgoingPaymentGrant.access_token.value diff --git a/docs/src/content/docs/sdk/before-you-begin.mdx b/docs/src/content/docs/sdk/before-you-begin.mdx index 7f7924bc..a4ac19f9 100644 --- a/docs/src/content/docs/sdk/before-you-begin.mdx +++ b/docs/src/content/docs/sdk/before-you-begin.mdx @@ -82,8 +82,8 @@ Before you can initialize an authenticated Open Payments client, you must obtain Developer keys tab with account expanded, showing the upload key and the generate public and private key buttons 4. Click **Generate public & private key**. 5. Enter any **nickname** for the key pair, then click **Generate keys**. A file named `private.key` automatically downloads to your machine - Generate public and private key screen with nickname field -Key pair generation success screen + Generate public and private key screen with nickname field + Key pair generation success screen 6. Click **Close**. Your key ID appears on the screen, along with a **Show/Hide** option for your public key. Developer keys tab with account expanded, showing the newly generated key id and an option to show the public key