Skip to content

Commit 195f2f6

Browse files
committed
algorithms: add the 'create incoming payment request' section
1 parent cf7e2bd commit 195f2f6

File tree

2 files changed

+133
-10
lines changed

2 files changed

+133
-10
lines changed

index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@
6464
title: "Open Payments Auth Server",
6565
href: "https://openpayments.dev/apis/auth-server/",
6666
},
67+
oprs: {
68+
title: "Open Payments Resource Server",
69+
href: "https://openpayments.dev/apis/resource-server/",
70+
},
6771
GNAP: {
6872
title: "GNAP",
6973
href: "https://datatracker.ietf.org/doc/html/draft-ietf-gnap-core-protocol",

section/algorithms.html

Lines changed: 129 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ <h4>Wallet address request</h4>
1111
<ol>
1212
<li>
1313
Let |walletAddressUrl:URL| be the result of running [=URL parser=] with |walletAddress|.
14-
</li>
15-
<li>
1614
If |walletAddressUrl| [=url/scheme=] is not `https`, return failure.
1715
</li>
1816
<li>
@@ -83,11 +81,7 @@ <h4>Outgoing payment and quote grant request</h4>
8381
and |interval:DOMString| perform the following steps.
8482
<ol>
8583
<li>
86-
Let |authServer:URL| be the result of running [=URL parser=]
87-
with |walletAddressDetails|'s {{WalletAddressDetails/authServer}} property.
88-
</li>
89-
<li>
90-
If |authServer| [=url/scheme=] is not `https`, return failure.
84+
Let |authServer:URL| be the result of running [=URL parser=] with |walletAddressDetails|'s {{WalletAddressDetails/authServer}} property.
9185
</li>
9286
<li>
9387
<p>Construct a {{ GrantRequest }} |grantRequest: GrantRequest| as follows:</p>
@@ -262,9 +256,6 @@ <h4>Incoming payment grant request</h4>
262256
<li>
263257
Let |authServer:URL| be the result of running [=URL parser=] with |websiteWalletAddressDetails|'s {{WalletAddressDetails/authServer}} property.
264258
</li>
265-
<li>
266-
If |authServer| [=url/scheme=] is not `https`, return failure.
267-
</li>
268259
<li>
269260
<p>Construct a {{ GrantRequest }} |grantRequest: GrantRequest| as follows:</p>
270261
<ol>
@@ -503,6 +494,134 @@ <h4>Cancel grant request</h4>
503494
</section>
504495
</section>
505496

497+
<section>
498+
<h3>Resource server operations (RS)</h3>
499+
<section>
500+
<h4>Create incoming payment</h4>
501+
<p>The create incoming payment request refers
502+
to the <a data-cite="oprs/operations/create-incoming-payment#">Open Payments create incoming payment</a>.</p>
503+
<div class="algorithm">
504+
When asked to <dfn>send a create incoming payment request</dfn>,
505+
given |websiteWalletAddressDetails:WalletAddressDetails|,
506+
|incomingPaymentGrant:Grant|, perform the following steps.
507+
<ol>
508+
<li>
509+
Let |resourceServer:URL| be the result of running [=URL parser=] with
510+
|websiteWalletAddressDetails|'s {{WalletAddressDetails/resourceServer}} property.
511+
</li>
512+
<li>
513+
Let |incomingPaymentsUrl:URL| be the result of running [=URL parser=] with the string formed by
514+
concatenating |resourceServer| and "/incoming-payments".
515+
</li>
516+
<li>
517+
Let |expiresAt:DOMString| be the current date-time plus 10 minutes, formatted as an ISO 8601 string.
518+
<p class="note">The `expiresAt` field is set to the current date plus 10 minutes.
519+
We assume users typically spend about 5 minutes on a website, making it unnecessary to keep the session active longer.
520+
Ideally, the browser should terminate the session when the user navigates away from the site.
521+
However, if that doesn’t happen for any reason, the expiration date will ensure the session is ended.
522+
If the session expires before the user leaves the website, the browser should reinitialize the session.
523+
</p>
524+
</li>
525+
<li>
526+
<p>Let |body| be a new JavaScript object constructed as follows:</p>
527+
<ul>
528+
<li>Set |body|.walletAddress to |websiteWalletAddressDetails|'s {{WalletAddressDetails/id}}.</li>
529+
<li>Set |body|.expiresAt to |expiresAt|.</li>
530+
</ul>
531+
<p class="note">`incomingAmount` is not set, as the amount is not fixed
532+
and the same incoming payment is reused for the session duration.</p>
533+
</li>
534+
<li>
535+
<p>Let |request| be a new [=request=] as follows:</p>
536+
<dl>
537+
<dt>[=request/URL=]</dt>
538+
<dd>|incomingPaymentsUrl|</dd>
539+
<dt>[=request/method=]</dt>
540+
<dd>"POST"</dd>
541+
<dt>[=request/body=]</dt>
542+
<dd>the result of running [=serialize a JavaScript value to a JSON string=] on |body|</dd>
543+
<dt>[=request/redirect mode=]</dt>
544+
<dd>"follow"</dd>
545+
<dt>[=request/client=]</dt>
546+
<dd>null</dd>
547+
<dt>{{RequestInit/window}}</dt>
548+
<dd>null</dd>
549+
<dt>[=request/service-workers mode=]</dt>
550+
<dd>"none"</dd>
551+
<dt>[=request/destination=]</dt>
552+
<dd>"monetization"</dd>
553+
<dt>[=request/header list=]</dt>
554+
<dd>a list containing a single header with name set to <code>Content-Type</code> and value set to <code>application/json</code>.</dd>
555+
<dt>[=request/mode=]</dt>
556+
<dd>"cors"</dd>
557+
</dl>
558+
</li>
559+
<li>
560+
Run the [=generate an HTTP message signature=] algorithm on |request| with |incomingPaymentGrant|.{{Grant/access_token}}.{{AccessToken/value}}.
561+
</li>
562+
<li>
563+
Let |incomingPaymentId:DOMString| be null.
564+
</li>
565+
<li>
566+
Perform a [=fetch request=] with |request| and with |processResponseConsumeBody| set to the following steps,
567+
given a [=response=] and |response|'s [=request/body=] |responseBody|:
568+
<ol>
569+
<li>
570+
Let |json| be the result of [=extract the JSON fetch response=] from |response| and |responseBody|.
571+
</li>
572+
<li>
573+
If |json| does not have an <code>id</code> property whose value is a string, return failure.
574+
</li>
575+
<li>
576+
Set |incomingPaymentId| to |json|.id.
577+
</li>
578+
</ol>
579+
</li>
580+
<li>
581+
Return |incomingPaymentId|.
582+
</li>
583+
</ol>
584+
</div>
585+
586+
<aside class="example" title="Create incoming payment JSON payload">
587+
<p>This payload is sent to the resource server.</p>
588+
<pre class="json">
589+
{
590+
"walletAddress": "https://wallet.example/website",
591+
"expiresAt": "2025-10-01T12:10:00Z"
592+
}
593+
</pre>
594+
</aside>
595+
<aside class="example" title="Incoming payment response JSON payload">
596+
<pre class="json">
597+
{
598+
"id": "https://rs.wallet.example/incoming-payments/08394f02-7b7b-45e2-b645-51d04e7c330c",
599+
"walletAddress": "https://wallet.example/website",
600+
"incomingAmount": {
601+
"value": "2500",
602+
"assetCode": "USD",
603+
"assetScale": 2
604+
},
605+
"receivedAmount": {
606+
"value": "0",
607+
"assetCode": "USD",
608+
"assetScale": 2
609+
},
610+
"completed": false,
611+
"createdAt": "2025-10-01T12:00:00Z",
612+
"methods": [
613+
{
614+
"type": "ilp",
615+
"ilpAddress": "g.example.abcd1234",
616+
"sharedSecret": "czVjcmV0Ig=="
617+
}
618+
]
619+
}
620+
</pre>
621+
</aside>
622+
</section>
623+
</section>
624+
506625
<section>
507626
<h3>Helper algorithms</h3>
508627
<section>

0 commit comments

Comments
 (0)