Skip to content

Commit 27e3ffb

Browse files
authored
Rename paymentToken to paymentRequestToken (#33)
1 parent 6fc3247 commit 27e3ffb

37 files changed

+472
-434
lines changed

.changeset/afraid-clocks-greet.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"agentcommercekit": minor
3+
"@agentcommercekit/ack-pay": minor
4+
---
5+
6+
- Deprecate `createPaymentRequestBody` in favor of `createSignedPaymentRequest`
7+
- Rename `paymentToken` to `paymentRequestToken` in payment requests and receipts
8+
- Remove `createPaymentRequestResponse`, which only built a `Response` object in a demo

demos/e2e/src/agent.ts

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
createDidPkhDocument,
44
createDidWebDocumentFromKeypair,
55
createJwtSigner,
6-
createPaymentRequestBody,
6+
createSignedPaymentRequest,
77
curveToJwtAlgorithm,
88
generateKeypair
99
} from "agentcommercekit"
@@ -205,45 +205,46 @@ ${colors.bold(otherAgent.did)}
205205

206206
// If no receipt provided, generate payment request
207207
if (!receipt) {
208-
const { paymentRequest, paymentToken } = await createPaymentRequestBody(
209-
{
210-
id: crypto.randomUUID(),
211-
expiresAt: new Date(Date.now() + 3600000), // 1 hour from now
212-
paymentOptions: [
213-
{
214-
id: crypto.randomUUID(),
215-
amount: BigInt(500).toString(),
216-
decimals: 2,
217-
currency: "USD",
218-
recipient: this.walletDid
219-
}
220-
]
221-
},
222-
{
223-
issuer: this.did,
224-
signer: this.signer,
225-
algorithm: curveToJwtAlgorithm(this.keypair.curve)
226-
}
227-
)
228-
229-
// Optional: Store the pending payment tokens.
230-
this.pendingRequests[paymentToken] = paymentRequest
231-
232-
throw new PaymentRequiredError(paymentRequest, paymentToken)
208+
const { paymentRequest, paymentRequestToken } =
209+
await createSignedPaymentRequest(
210+
{
211+
id: crypto.randomUUID(),
212+
expiresAt: new Date(Date.now() + 3600000), // 1 hour from now
213+
paymentOptions: [
214+
{
215+
id: crypto.randomUUID(),
216+
amount: BigInt(500).toString(),
217+
decimals: 2,
218+
currency: "USD",
219+
recipient: this.walletDid
220+
}
221+
]
222+
},
223+
{
224+
issuer: this.did,
225+
signer: this.signer,
226+
algorithm: curveToJwtAlgorithm(this.keypair.curve)
227+
}
228+
)
229+
230+
// Optional: Store the pending payment request tokens.
231+
this.pendingRequests[paymentRequestToken] = paymentRequest
232+
233+
throw new PaymentRequiredError(paymentRequest, paymentRequestToken)
233234
}
234235

235236
// Verify the receipt
236-
const { paymentToken } = await this.receiptVerifier.verifyReceipt(
237+
const { paymentRequestToken } = await this.receiptVerifier.verifyReceipt(
237238
receipt,
238239
this.did
239240
)
240241

241-
// Optional: Ensure the payment token was for this same type of request.
242+
// Optional: Ensure the payment request token was for this same type of request.
242243
// Payment requests and receipts are designed to allow for stateless
243244
// operation, but it can be useful to map a given request to a specific
244245
// action on the server.
245-
if (!this.pendingRequests[paymentToken]) {
246-
throw new Error("Payment token not found")
246+
if (!this.pendingRequests[paymentRequestToken]) {
247+
throw new Error("Payment Request token not found")
247248
}
248249

249250
// Provide the service

demos/e2e/src/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,11 @@ If identity is verified, Agent 2 will then respond with a 402 Payment Required e
198198

199199
const message = "What's the current price of AAPL stock?"
200200

201-
const { paymentRequest, paymentToken } = await chat(agent1, agent2, message)
201+
const { paymentRequest, paymentRequestToken } = await chat(
202+
agent1,
203+
agent2,
204+
message
205+
)
202206

203207
log(
204208
colors.dim(`
@@ -217,7 +221,7 @@ Next, we will perform the payment and fetch a Receipt.
217221
log(
218222
colors.dim(`
219223
Payment must be made using token:
220-
${paymentToken}
224+
${paymentRequestToken}
221225
222226
`)
223227
)
@@ -241,7 +245,7 @@ ${paymentToken}
241245
const receipt = await receiptIssuer.issueReceipt({
242246
payerDid: agent1.walletDid,
243247
txHash,
244-
paymentToken
248+
paymentRequestToken
245249
})
246250
log(successMessage("Payment Receipt VC Issued!"))
247251
logJson(await parseJwtCredential(receipt, resolver))
@@ -291,7 +295,7 @@ async function chat(agent1: Agent, agent2: Agent, message: string) {
291295
if (error instanceof PaymentRequiredError) {
292296
return {
293297
paymentRequest: error.paymentRequest,
294-
paymentToken: error.paymentToken
298+
paymentRequestToken: error.paymentRequestToken
295299
}
296300
}
297301

demos/e2e/src/payment-required-error.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import type { PaymentRequest } from "agentcommercekit"
55
*/
66
export class PaymentRequiredError extends Error {
77
paymentRequest: PaymentRequest
8-
paymentToken: string
8+
paymentRequestToken: string
99

10-
constructor(paymentRequest: PaymentRequest, paymentToken: string) {
10+
constructor(paymentRequest: PaymentRequest, paymentRequestToken: string) {
1111
super("402 Payment Required")
1212
this.name = "PaymentRequiredError"
1313
this.paymentRequest = paymentRequest
14-
this.paymentToken = paymentToken
14+
this.paymentRequestToken = paymentRequestToken
1515
}
1616
}

demos/e2e/src/receipt-issuer.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
createPaymentReceipt,
55
generateKeypair,
66
signCredential,
7-
verifyPaymentToken
7+
verifyPaymentRequestToken
88
} from "agentcommercekit"
99
import type {
1010
DidDocument,
@@ -65,15 +65,18 @@ export class ReceiptIssuer {
6565
async issueReceipt({
6666
payerDid,
6767
txHash,
68-
paymentToken
68+
paymentRequestToken
6969
}: {
7070
payerDid: DidUri
7171
txHash: string
72-
paymentToken: string
72+
paymentRequestToken: string
7373
}): Promise<JwtString> {
74-
const { paymentRequest } = await verifyPaymentToken(paymentToken, {
75-
resolver: this.resolver
76-
})
74+
const { paymentRequest } = await verifyPaymentRequestToken(
75+
paymentRequestToken,
76+
{
77+
resolver: this.resolver
78+
}
79+
)
7780

7881
// Verify the payment on-chain
7982
const paymentVerified = await this.verifyPaymentOnChain(
@@ -86,7 +89,7 @@ export class ReceiptIssuer {
8689

8790
// Create and sign the receipt credential
8891
const credential = createPaymentReceipt({
89-
paymentToken,
92+
paymentRequestToken,
9093
paymentOptionId: paymentRequest.paymentOptions[0].id,
9194
issuer: this.did,
9295
payerDid

demos/e2e/src/receipt-verifier.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export class ReceiptVerifier {
6767
resolver: this.resolver,
6868
trustedReceiptIssuers: this.trustedIssuers,
6969
paymentRequestIssuer: paymentRequestIssuer,
70-
verifyPaymentTokenJwt: true
70+
verifyPaymentRequestTokenJwt: true
7171
})
7272
}
7373
}

demos/payments/src/index.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import {
2020
isJwtString,
2121
parseJwtCredential
2222
} from "agentcommercekit"
23-
import { paymentRequestBodySchema } from "agentcommercekit/schemas/valibot"
23+
import {
24+
jwtStringSchema,
25+
paymentRequestSchema
26+
} from "agentcommercekit/schemas/valibot"
2427
import * as v from "valibot"
2528
import { isAddress } from "viem"
2629
import {
@@ -118,14 +121,17 @@ The Client attempts to access a protected resource on the Server. Since no valid
118121
throw new Error("Server did not respond with 402")
119122
}
120123

121-
const { paymentToken, paymentRequest } = v.parse(
122-
paymentRequestBodySchema,
124+
const { paymentRequestToken, paymentRequest } = v.parse(
125+
v.object({
126+
paymentRequestToken: jwtStringSchema,
127+
paymentRequest: paymentRequestSchema
128+
}),
123129
await response1.json()
124130
)
125131

126-
// This demo uses JWT strings for the payment token, but this is not a requirement of the protocol.
127-
if (!isJwtString(paymentToken)) {
128-
throw new Error(errorMessage("Invalid payment token"))
132+
// This demo uses JWT strings for the payment request token, but this is not a requirement of the protocol.
133+
if (!isJwtString(paymentRequestToken)) {
134+
throw new Error(errorMessage("Invalid payment request token"))
129135
}
130136

131137
log(
@@ -138,7 +144,7 @@ The Client attempts to access a protected resource on the Server. Since no valid
138144
log(
139145
colors.magenta(
140146
wordWrap(
141-
"\n💡 The 'paymentToken' is a JWT signed by the Server, ensuring the integrity and authenticity of the payment request. The Client will include this token when requesting a receipt, along with the payment option id and metadata."
147+
"\n💡 The 'paymentRequestToken' is a JWT signed by the Server, ensuring the integrity and authenticity of the payment request. The Client will include this token when requesting a receipt, along with the payment option id and metadata."
142148
)
143149
)
144150
)
@@ -168,15 +174,15 @@ The Client attempts to access a protected resource on the Server. Since no valid
168174
const paymentResult = await performStripePayment(
169175
clientKeypairInfo,
170176
selectedPaymentOption,
171-
paymentToken
177+
paymentRequestToken
172178
)
173179
receipt = paymentResult.receipt
174180
details = paymentResult.details
175181
} else if (selectedPaymentOption.network === chainId) {
176182
const paymentResult = await performOnChainPayment(
177183
clientKeypairInfo,
178184
selectedPaymentOption,
179-
paymentToken
185+
paymentRequestToken
180186
)
181187
receipt = paymentResult.receipt
182188
details = paymentResult.details
@@ -215,7 +221,7 @@ The Client Agent now retries the original request to the Server Agent, this time
215221
216222
${colors.bold("The Server Agent then performs its own verifications:")}
217223
1. Validates the receipt's signature (ensuring it was issued by a trusted Receipt Service and hasn't been tampered with).
218-
2. Checks the receipt's claims: Confirms the receipt is for the correct payment (e.g., matches the 'paymentToken' it originally issued), is not expired, and meets any other criteria for accessing the resource.
224+
2. Checks the receipt's claims: Confirms the receipt is for the correct payment (e.g., matches the 'paymentRequestToken' it originally issued), is not expired, and meets any other criteria for accessing the resource.
219225
220226
If the receipt is valid, the Server grants access to the protected resource.`
221227
)
@@ -262,7 +268,7 @@ If the receipt is valid, the Server grants access to the protected resource.`
262268
async function performOnChainPayment(
263269
client: KeypairInfo,
264270
paymentOption: PaymentRequest["paymentOptions"][number],
265-
paymentToken: JwtString
271+
paymentRequestToken: JwtString
266272
) {
267273
const receiptServiceUrl = paymentOption.receiptService
268274
if (!receiptServiceUrl) {
@@ -346,11 +352,11 @@ The Client Agent now uses the details from the Payment Request to make the payme
346352
colors.dim(
347353
`${colors.bold("Client Agent 👤 -> Receipt Service 🧾")}
348354
349-
With the payment confirmed, the Client Agent now requests a formal, cryptographically verifiable payment receipt from the Receipt Service. The Client sends the original 'paymentToken' (received from the Server in Step 1) and the transaction hash (as metadata) to the Receipt Service. The Client also signs this request with its own DID to prove it's the one who made the payment.
355+
With the payment confirmed, the Client Agent now requests a formal, cryptographically verifiable payment receipt from the Receipt Service. The Client sends the original 'paymentRequestToken' (received from the Server in Step 1) and the transaction hash (as metadata) to the Receipt Service. The Client also signs this request with its own DID to prove it's the one who made the payment.
350356
351357
${colors.bold("The Receipt Service then performs several crucial verifications:")}
352-
1. Validates the 'paymentToken' (e.g., signature, expiry, ensuring it was issued by a trusted server for the expected payment context).
353-
2. Verifies the on-chain transaction: Confirms that the transaction hash is valid, the correct amount of the specified currency was transferred to the correct recipient address as per the 'paymentToken'.
358+
1. Validates the 'paymentRequestToken' (e.g., signature, expiry, ensuring it was issued by a trusted server for the expected payment context).
359+
2. Verifies the on-chain transaction: Confirms that the transaction hash is valid, the correct amount of the specified currency was transferred to the correct recipient address as per the 'paymentRequestToken'.
354360
3. Verifies the Client's signature on the request, ensuring the payer is who they claim to be (linking the payment action to the Client's DID).
355361
356362
If all checks pass, the Receipt Service issues a Verifiable Credential (VC) serving as the payment receipt.`
@@ -364,7 +370,7 @@ If all checks pass, the Receipt Service issues a Verifiable Credential (VC) serv
364370
)
365371

366372
const payload = {
367-
paymentToken,
373+
paymentRequestToken,
368374
paymentOptionId: paymentOption.id,
369375
metadata: {
370376
txHash: hash,
@@ -397,7 +403,7 @@ If all checks pass, the Receipt Service issues a Verifiable Credential (VC) serv
397403
async function performStripePayment(
398404
_client: KeypairInfo,
399405
paymentOption: PaymentRequest["paymentOptions"][number],
400-
paymentToken: JwtString
406+
paymentRequestToken: JwtString
401407
) {
402408
const paymentServiceUrl = paymentOption.paymentService
403409
if (!paymentServiceUrl) {
@@ -429,7 +435,7 @@ This flow is simulated in this example.
429435
method: "POST",
430436
body: JSON.stringify({
431437
paymentOptionId: paymentOption.id,
432-
paymentToken
438+
paymentRequestToken
433439
})
434440
})
435441

@@ -468,7 +474,7 @@ This flow is simulated in this example.
468474
method: "POST",
469475
body: JSON.stringify({
470476
paymentOptionId: paymentOption.id,
471-
paymentToken,
477+
paymentRequestToken,
472478
metadata: {
473479
eventId: "evt_" + Math.random().toString(36).substring(7) // Simulated Stripe event ID
474480
}

0 commit comments

Comments
 (0)