lane-sdk 0.3.11 → 0.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/crewai/index.cjs +12 -14
- package/dist/adapters/crewai/index.d.cts +1 -1
- package/dist/adapters/crewai/index.d.ts +1 -1
- package/dist/adapters/crewai/index.js +12 -14
- package/dist/adapters/langchain/index.cjs +12 -14
- package/dist/adapters/langchain/index.d.cts +1 -1
- package/dist/adapters/langchain/index.d.ts +1 -1
- package/dist/adapters/langchain/index.js +12 -14
- package/dist/adapters/openai/index.cjs +12 -14
- package/dist/adapters/openai/index.d.cts +1 -1
- package/dist/adapters/openai/index.d.ts +1 -1
- package/dist/adapters/openai/index.js +12 -14
- package/dist/adapters/vercel-ai/index.cjs +12 -14
- package/dist/adapters/vercel-ai/index.d.cts +1 -1
- package/dist/adapters/vercel-ai/index.d.ts +1 -1
- package/dist/adapters/vercel-ai/index.js +12 -14
- package/dist/cli/index.js +6 -7
- package/dist/cli/postinstall.js +0 -1
- package/dist/index.cjs +12 -936
- package/dist/index.d.cts +3 -354
- package/dist/index.d.ts +3 -354
- package/dist/index.js +13 -928
- package/dist/{lane-CATn69s2.d.cts → lane-BgdqOeXo.d.cts} +5 -5
- package/dist/{lane-CATn69s2.d.ts → lane-BgdqOeXo.d.ts} +5 -5
- package/dist/server-http.cjs +12 -14
- package/dist/server-http.js +12 -14
- package/dist/server-stdio.cjs +12 -14
- package/dist/server-stdio.js +12 -14
- package/dist/skills/lane.md +5 -5
- package/package.json +5 -2
- package/plugin/skills/commerce-agent/SKILL.md +2 -2
- package/dist/adapters/crewai/index.cjs.map +0 -1
- package/dist/adapters/crewai/index.js.map +0 -1
- package/dist/adapters/langchain/index.cjs.map +0 -1
- package/dist/adapters/langchain/index.js.map +0 -1
- package/dist/adapters/openai/index.cjs.map +0 -1
- package/dist/adapters/openai/index.js.map +0 -1
- package/dist/adapters/vercel-ai/index.cjs.map +0 -1
- package/dist/adapters/vercel-ai/index.js.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/postinstall.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/server-http.cjs.map +0 -1
- package/dist/server-http.js.map +0 -1
- package/dist/server-stdio.cjs.map +0 -1
- package/dist/server-stdio.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -5152,7 +5152,7 @@ var ConfirmInstructionTool = class extends LaneTool {
|
|
|
5152
5152
|
}
|
|
5153
5153
|
};
|
|
5154
5154
|
var inputSchema27 = zod.z.object({
|
|
5155
|
-
platform: zod.z.
|
|
5155
|
+
platform: zod.z.string().describe("Commerce platform to query. The server resolves available platforms.")
|
|
5156
5156
|
});
|
|
5157
5157
|
var CommerceGetLocationsTool = class extends LaneTool {
|
|
5158
5158
|
get definition() {
|
|
@@ -5167,7 +5167,7 @@ var CommerceGetLocationsTool = class extends LaneTool {
|
|
|
5167
5167
|
}
|
|
5168
5168
|
};
|
|
5169
5169
|
var inputSchema28 = zod.z.object({
|
|
5170
|
-
platform: zod.z.
|
|
5170
|
+
platform: zod.z.string().describe("Commerce platform. The server resolves available platforms."),
|
|
5171
5171
|
locationId: zod.z.string().describe("Location ID to fetch the menu for.")
|
|
5172
5172
|
});
|
|
5173
5173
|
var CommerceGetMenuTool = class extends LaneTool {
|
|
@@ -5183,7 +5183,7 @@ var CommerceGetMenuTool = class extends LaneTool {
|
|
|
5183
5183
|
}
|
|
5184
5184
|
};
|
|
5185
5185
|
var inputSchema29 = zod.z.object({
|
|
5186
|
-
platform: zod.z.
|
|
5186
|
+
platform: zod.z.string().describe("Commerce platform. The server resolves available platforms."),
|
|
5187
5187
|
itemId: zod.z.string().describe("Item ID to fetch modifiers for.")
|
|
5188
5188
|
});
|
|
5189
5189
|
var CommerceGetModifiersTool = class extends LaneTool {
|
|
@@ -5210,7 +5210,7 @@ var inputSchema30 = zod.z.object({
|
|
|
5210
5210
|
text: zod.z.string().optional().describe('Natural language order request (e.g., "4 cold brews for pickup at Equator tomorrow 2pm"). If provided, server auto-resolves item, quantity, location, time, and modifiers.'),
|
|
5211
5211
|
// Option B: structured params (agent already resolved from menu)
|
|
5212
5212
|
description: zod.z.string().optional().describe("Order summary (required if text not provided)."),
|
|
5213
|
-
platform: zod.z.
|
|
5213
|
+
platform: zod.z.string().optional().describe("Auto-detected by the server if omitted."),
|
|
5214
5214
|
merchant: zod.z.string().optional().describe("Merchant name (auto-detected from text if provided)."),
|
|
5215
5215
|
walletId: zod.z.string().default("default").describe("Wallet ID."),
|
|
5216
5216
|
locationId: zod.z.string().optional().describe("Location ID (auto-resolved from text if provided)."),
|
|
@@ -5243,7 +5243,7 @@ var CommerceOrderIntentTool = class extends LaneTool {
|
|
|
5243
5243
|
};
|
|
5244
5244
|
}
|
|
5245
5245
|
async run(input) {
|
|
5246
|
-
const platform2 = input.platform ??
|
|
5246
|
+
const platform2 = input.platform ?? "auto";
|
|
5247
5247
|
return this.getLane().commerce.orders.createIntent(platform2, {
|
|
5248
5248
|
...input,
|
|
5249
5249
|
description: input.description ?? input.text ?? "",
|
|
@@ -5254,7 +5254,7 @@ var CommerceOrderIntentTool = class extends LaneTool {
|
|
|
5254
5254
|
}
|
|
5255
5255
|
};
|
|
5256
5256
|
var inputSchema31 = zod.z.object({
|
|
5257
|
-
platform: zod.z.
|
|
5257
|
+
platform: zod.z.string().optional().describe("Auto-detected from instruction if omitted."),
|
|
5258
5258
|
instructionId: zod.z.string().describe("Instruction ID from order intent."),
|
|
5259
5259
|
mandateId: zod.z.string().describe("Mandate ID from order intent.")
|
|
5260
5260
|
});
|
|
@@ -5267,7 +5267,7 @@ var CommerceExecuteOrderTool = class extends LaneTool {
|
|
|
5267
5267
|
};
|
|
5268
5268
|
}
|
|
5269
5269
|
async run(input) {
|
|
5270
|
-
const platform2 = input.platform ?? "
|
|
5270
|
+
const platform2 = input.platform ?? "auto";
|
|
5271
5271
|
return this.getLane().commerce.orders.executeIntent(
|
|
5272
5272
|
platform2,
|
|
5273
5273
|
input.instructionId,
|
|
@@ -5276,7 +5276,7 @@ var CommerceExecuteOrderTool = class extends LaneTool {
|
|
|
5276
5276
|
}
|
|
5277
5277
|
};
|
|
5278
5278
|
var inputSchema32 = zod.z.object({
|
|
5279
|
-
platform: zod.z.
|
|
5279
|
+
platform: zod.z.string().describe("Commerce platform to connect. The server resolves available platforms."),
|
|
5280
5280
|
walletId: zod.z.string().optional().describe("Wallet ID to associate."),
|
|
5281
5281
|
userEmail: zod.z.string().optional().describe("User email for the platform."),
|
|
5282
5282
|
displayName: zod.z.string().optional().describe("Display name for the connection.")
|
|
@@ -5309,7 +5309,7 @@ var CommerceProviderStatusTool = class extends LaneTool {
|
|
|
5309
5309
|
}
|
|
5310
5310
|
};
|
|
5311
5311
|
var inputSchema34 = zod.z.object({
|
|
5312
|
-
platform: zod.z.
|
|
5312
|
+
platform: zod.z.string().optional().describe("Auto-detected from instruction if omitted."),
|
|
5313
5313
|
orderId: zod.z.string().describe("Order ID from the create order step."),
|
|
5314
5314
|
instructionId: zod.z.string().describe("Instruction ID from order intent."),
|
|
5315
5315
|
cardId: zod.z.string().optional().describe("Payment card ID. If omitted, server resolves first saved card."),
|
|
@@ -5325,7 +5325,7 @@ var CommerceCheckoutConfigTool = class extends LaneTool {
|
|
|
5325
5325
|
};
|
|
5326
5326
|
}
|
|
5327
5327
|
async run(input) {
|
|
5328
|
-
const platform2 = input.platform ?? "
|
|
5328
|
+
const platform2 = input.platform ?? "auto";
|
|
5329
5329
|
return this.getLane().commerce.orders.configureCheckout(platform2, input.orderId, {
|
|
5330
5330
|
instructionId: input.instructionId,
|
|
5331
5331
|
cardId: input.cardId,
|
|
@@ -5335,7 +5335,7 @@ var CommerceCheckoutConfigTool = class extends LaneTool {
|
|
|
5335
5335
|
}
|
|
5336
5336
|
};
|
|
5337
5337
|
var inputSchema35 = zod.z.object({
|
|
5338
|
-
platform: zod.z.
|
|
5338
|
+
platform: zod.z.string().optional().describe("Auto-detected from instruction if omitted."),
|
|
5339
5339
|
orderId: zod.z.string().describe("Order ID to submit."),
|
|
5340
5340
|
instructionId: zod.z.string().describe("Instruction ID from order intent."),
|
|
5341
5341
|
mandateId: zod.z.string().describe("Mandate ID from order intent.")
|
|
@@ -5349,7 +5349,7 @@ var CommerceSubmitOrderTool = class extends LaneTool {
|
|
|
5349
5349
|
};
|
|
5350
5350
|
}
|
|
5351
5351
|
async run(input) {
|
|
5352
|
-
const platform2 = input.platform ?? "
|
|
5352
|
+
const platform2 = input.platform ?? "auto";
|
|
5353
5353
|
return this.getLane().commerce.orders.submit(platform2, input.orderId, {
|
|
5354
5354
|
instructionId: input.instructionId,
|
|
5355
5355
|
mandateId: input.mandateId
|
|
@@ -5476,139 +5476,6 @@ var LaneMCPServer = class {
|
|
|
5476
5476
|
}
|
|
5477
5477
|
};
|
|
5478
5478
|
|
|
5479
|
-
// src/vgs/token.ts
|
|
5480
|
-
var TOKEN_REFRESH_MARGIN_MS = 6e4;
|
|
5481
|
-
var VGSTokenManager = class {
|
|
5482
|
-
constructor(config) {
|
|
5483
|
-
this.config = config;
|
|
5484
|
-
}
|
|
5485
|
-
cached = null;
|
|
5486
|
-
clearTimer = null;
|
|
5487
|
-
/**
|
|
5488
|
-
* Get a valid access token, refreshing if expired or near-expiry.
|
|
5489
|
-
*/
|
|
5490
|
-
async getAccessToken() {
|
|
5491
|
-
if (this.cached && Date.now() < this.cached.expiresAt - TOKEN_REFRESH_MARGIN_MS) {
|
|
5492
|
-
return this.cached.accessToken;
|
|
5493
|
-
}
|
|
5494
|
-
return this.refresh();
|
|
5495
|
-
}
|
|
5496
|
-
/**
|
|
5497
|
-
* Force-refresh the token.
|
|
5498
|
-
*/
|
|
5499
|
-
async refresh() {
|
|
5500
|
-
const tokenUrl = this.getTokenUrl();
|
|
5501
|
-
const body = new URLSearchParams({
|
|
5502
|
-
grant_type: "client_credentials",
|
|
5503
|
-
client_id: this.config.clientId,
|
|
5504
|
-
client_secret: this.config.clientSecret
|
|
5505
|
-
});
|
|
5506
|
-
const response = await fetch(tokenUrl, {
|
|
5507
|
-
method: "POST",
|
|
5508
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
5509
|
-
body: body.toString()
|
|
5510
|
-
});
|
|
5511
|
-
if (!response.ok) {
|
|
5512
|
-
throw LaneAuthError.invalidApiKey(
|
|
5513
|
-
`VGS token exchange failed: ${response.status} ${response.statusText}`
|
|
5514
|
-
);
|
|
5515
|
-
}
|
|
5516
|
-
const data = await response.json();
|
|
5517
|
-
this.clearCachedToken();
|
|
5518
|
-
this.cached = {
|
|
5519
|
-
accessToken: data.access_token,
|
|
5520
|
-
expiresAt: Date.now() + data.expires_in * 1e3
|
|
5521
|
-
};
|
|
5522
|
-
this.clearTimer = setTimeout(() => {
|
|
5523
|
-
this.clearCachedToken();
|
|
5524
|
-
}, data.expires_in * 1e3);
|
|
5525
|
-
this.clearTimer.unref();
|
|
5526
|
-
return this.cached.accessToken;
|
|
5527
|
-
}
|
|
5528
|
-
/**
|
|
5529
|
-
* Invalidate the cached token.
|
|
5530
|
-
*/
|
|
5531
|
-
invalidate() {
|
|
5532
|
-
this.clearCachedToken();
|
|
5533
|
-
}
|
|
5534
|
-
/**
|
|
5535
|
-
* Overwrite and release the cached token from memory.
|
|
5536
|
-
*/
|
|
5537
|
-
clearCachedToken() {
|
|
5538
|
-
if (this.clearTimer) {
|
|
5539
|
-
clearTimeout(this.clearTimer);
|
|
5540
|
-
this.clearTimer = null;
|
|
5541
|
-
}
|
|
5542
|
-
if (this.cached) {
|
|
5543
|
-
this.cached.accessToken = "";
|
|
5544
|
-
this.cached = null;
|
|
5545
|
-
}
|
|
5546
|
-
}
|
|
5547
|
-
getTokenUrl() {
|
|
5548
|
-
const env = this.config.environment === "live" ? "live" : "sandbox";
|
|
5549
|
-
return `https://auth.verygoodsecurity.com/vaults/${this.config.vaultId}/tokens?env=${env}`;
|
|
5550
|
-
}
|
|
5551
|
-
};
|
|
5552
|
-
|
|
5553
|
-
// src/vgs/proxy.ts
|
|
5554
|
-
var VGSOutboundProxy = class {
|
|
5555
|
-
constructor(config) {
|
|
5556
|
-
this.config = config;
|
|
5557
|
-
this.tokenManager = new VGSTokenManager(config);
|
|
5558
|
-
}
|
|
5559
|
-
tokenManager;
|
|
5560
|
-
/**
|
|
5561
|
-
* Send a request through the VGS outbound proxy.
|
|
5562
|
-
* VGS aliases in the body are de-tokenized and revealed to the target PSP.
|
|
5563
|
-
*/
|
|
5564
|
-
async forward(request) {
|
|
5565
|
-
const accessToken = await this.tokenManager.getAccessToken();
|
|
5566
|
-
const proxyUrl = this.getProxyUrl();
|
|
5567
|
-
const response = await fetch(proxyUrl, {
|
|
5568
|
-
method: request.method,
|
|
5569
|
-
headers: {
|
|
5570
|
-
...request.headers,
|
|
5571
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
5572
|
-
"X-VGS-Route-Id": this.config.routeId,
|
|
5573
|
-
"X-VGS-Upstream-Url": request.url,
|
|
5574
|
-
"Content-Type": "application/json"
|
|
5575
|
-
},
|
|
5576
|
-
body: JSON.stringify(request.body)
|
|
5577
|
-
});
|
|
5578
|
-
const responseBody = await response.json().catch(() => null);
|
|
5579
|
-
if (!response.ok) {
|
|
5580
|
-
throw new LanePaymentError(
|
|
5581
|
-
`VGS proxy request failed: ${response.status}`,
|
|
5582
|
-
{
|
|
5583
|
-
code: "vgs_proxy_error",
|
|
5584
|
-
statusCode: response.status,
|
|
5585
|
-
retryable: response.status >= 500,
|
|
5586
|
-
suggestedAction: "Check VGS vault configuration and PSP endpoint whitelist."
|
|
5587
|
-
}
|
|
5588
|
-
);
|
|
5589
|
-
}
|
|
5590
|
-
const responseHeaders = {};
|
|
5591
|
-
response.headers.forEach((value, key) => {
|
|
5592
|
-
responseHeaders[key] = value;
|
|
5593
|
-
});
|
|
5594
|
-
return {
|
|
5595
|
-
status: response.status,
|
|
5596
|
-
headers: responseHeaders,
|
|
5597
|
-
body: responseBody
|
|
5598
|
-
};
|
|
5599
|
-
}
|
|
5600
|
-
/**
|
|
5601
|
-
* Invalidate the cached VGS access token.
|
|
5602
|
-
*/
|
|
5603
|
-
invalidateToken() {
|
|
5604
|
-
this.tokenManager.invalidate();
|
|
5605
|
-
}
|
|
5606
|
-
getProxyUrl() {
|
|
5607
|
-
const env = this.config.environment === "live" ? "live" : "sandbox";
|
|
5608
|
-
return `https://${this.config.vaultId}.${env}.verygoodproxy.com`;
|
|
5609
|
-
}
|
|
5610
|
-
};
|
|
5611
|
-
|
|
5612
5479
|
// src/vgs/card-types.ts
|
|
5613
5480
|
var BIN_RANGES = [
|
|
5614
5481
|
{ brand: "visa", prefixes: ["4"], lengths: [13, 16, 19] },
|
|
@@ -5652,638 +5519,6 @@ function maskCardNumber(cardNumber) {
|
|
|
5652
5519
|
return `****${digits.slice(-4)}`;
|
|
5653
5520
|
}
|
|
5654
5521
|
|
|
5655
|
-
// src/vgs/collect.ts
|
|
5656
|
-
function generateCollectPage(config) {
|
|
5657
|
-
const vgsEnv = config.environment === "live" ? "live" : "sandbox";
|
|
5658
|
-
`https://${config.vaultId}.${vgsEnv}.verygoodproxy.com`;
|
|
5659
|
-
return `<!DOCTYPE html>
|
|
5660
|
-
<html lang="en">
|
|
5661
|
-
<head>
|
|
5662
|
-
<meta charset="UTF-8">
|
|
5663
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5664
|
-
<title>Lane \u2014 Add Payment Method</title>
|
|
5665
|
-
<script src="https://js.verygoodvault.com/vgs-collect/2.18.0/vgs-collect.js"></script>
|
|
5666
|
-
<style>
|
|
5667
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
5668
|
-
body {
|
|
5669
|
-
font-family: 'At Aero', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
5670
|
-
background: #0A0A0A;
|
|
5671
|
-
color: #FFFFFF;
|
|
5672
|
-
display: flex;
|
|
5673
|
-
justify-content: center;
|
|
5674
|
-
align-items: center;
|
|
5675
|
-
min-height: 100vh;
|
|
5676
|
-
}
|
|
5677
|
-
.container {
|
|
5678
|
-
width: 100%;
|
|
5679
|
-
max-width: 440px;
|
|
5680
|
-
padding: 40px 32px;
|
|
5681
|
-
background: #141414;
|
|
5682
|
-
border: 1px solid #2A2A2A;
|
|
5683
|
-
border-radius: 16px;
|
|
5684
|
-
}
|
|
5685
|
-
.logo {
|
|
5686
|
-
font-size: 24px;
|
|
5687
|
-
font-weight: 700;
|
|
5688
|
-
color: #1201FF;
|
|
5689
|
-
letter-spacing: -0.5px;
|
|
5690
|
-
margin-bottom: 8px;
|
|
5691
|
-
}
|
|
5692
|
-
.subtitle {
|
|
5693
|
-
color: #888;
|
|
5694
|
-
font-size: 14px;
|
|
5695
|
-
margin-bottom: 32px;
|
|
5696
|
-
}
|
|
5697
|
-
.field-group {
|
|
5698
|
-
margin-bottom: 20px;
|
|
5699
|
-
}
|
|
5700
|
-
.field-group label {
|
|
5701
|
-
display: block;
|
|
5702
|
-
font-size: 12px;
|
|
5703
|
-
font-weight: 600;
|
|
5704
|
-
color: #888;
|
|
5705
|
-
text-transform: uppercase;
|
|
5706
|
-
letter-spacing: 0.5px;
|
|
5707
|
-
margin-bottom: 8px;
|
|
5708
|
-
}
|
|
5709
|
-
.field-wrapper {
|
|
5710
|
-
background: #1A1A1A;
|
|
5711
|
-
border: 1px solid #333;
|
|
5712
|
-
border-radius: 8px;
|
|
5713
|
-
padding: 0;
|
|
5714
|
-
height: 48px;
|
|
5715
|
-
transition: border-color 0.2s;
|
|
5716
|
-
}
|
|
5717
|
-
.field-wrapper:focus-within {
|
|
5718
|
-
border-color: #1201FF;
|
|
5719
|
-
}
|
|
5720
|
-
.field-wrapper iframe {
|
|
5721
|
-
height: 48px !important;
|
|
5722
|
-
}
|
|
5723
|
-
.row {
|
|
5724
|
-
display: flex;
|
|
5725
|
-
gap: 12px;
|
|
5726
|
-
}
|
|
5727
|
-
.row .field-group {
|
|
5728
|
-
flex: 1;
|
|
5729
|
-
}
|
|
5730
|
-
.submit-btn {
|
|
5731
|
-
width: 100%;
|
|
5732
|
-
height: 48px;
|
|
5733
|
-
background: #1201FF;
|
|
5734
|
-
color: #FFFFFF;
|
|
5735
|
-
border: none;
|
|
5736
|
-
border-radius: 8px;
|
|
5737
|
-
font-size: 16px;
|
|
5738
|
-
font-weight: 600;
|
|
5739
|
-
cursor: pointer;
|
|
5740
|
-
margin-top: 24px;
|
|
5741
|
-
transition: background 0.2s;
|
|
5742
|
-
}
|
|
5743
|
-
.submit-btn:hover { background: #0E01CC; }
|
|
5744
|
-
.submit-btn:disabled {
|
|
5745
|
-
background: #333;
|
|
5746
|
-
cursor: not-allowed;
|
|
5747
|
-
}
|
|
5748
|
-
.security-note {
|
|
5749
|
-
text-align: center;
|
|
5750
|
-
margin-top: 16px;
|
|
5751
|
-
font-size: 12px;
|
|
5752
|
-
color: #555;
|
|
5753
|
-
}
|
|
5754
|
-
.security-note svg {
|
|
5755
|
-
vertical-align: middle;
|
|
5756
|
-
margin-right: 4px;
|
|
5757
|
-
}
|
|
5758
|
-
.error-msg {
|
|
5759
|
-
color: #FF4444;
|
|
5760
|
-
font-size: 13px;
|
|
5761
|
-
margin-top: 8px;
|
|
5762
|
-
display: none;
|
|
5763
|
-
}
|
|
5764
|
-
.success-container {
|
|
5765
|
-
text-align: center;
|
|
5766
|
-
display: none;
|
|
5767
|
-
}
|
|
5768
|
-
.success-container .check {
|
|
5769
|
-
font-size: 48px;
|
|
5770
|
-
margin-bottom: 16px;
|
|
5771
|
-
}
|
|
5772
|
-
</style>
|
|
5773
|
-
</head>
|
|
5774
|
-
<body>
|
|
5775
|
-
<div class="container">
|
|
5776
|
-
<div id="form-view">
|
|
5777
|
-
<div class="logo">Lane</div>
|
|
5778
|
-
<div class="subtitle">Add a payment method. Your card data goes directly to our PCI Level 1 vault.</div>
|
|
5779
|
-
|
|
5780
|
-
<form id="card-form">
|
|
5781
|
-
<div class="field-group">
|
|
5782
|
-
<label>Card Number</label>
|
|
5783
|
-
<div id="cc-number" class="field-wrapper"></div>
|
|
5784
|
-
</div>
|
|
5785
|
-
|
|
5786
|
-
<div class="row">
|
|
5787
|
-
<div class="field-group">
|
|
5788
|
-
<label>Expiry</label>
|
|
5789
|
-
<div id="cc-expiry" class="field-wrapper"></div>
|
|
5790
|
-
</div>
|
|
5791
|
-
<div class="field-group">
|
|
5792
|
-
<label>CVC</label>
|
|
5793
|
-
<div id="cc-cvc" class="field-wrapper"></div>
|
|
5794
|
-
</div>
|
|
5795
|
-
</div>
|
|
5796
|
-
|
|
5797
|
-
<div class="field-group">
|
|
5798
|
-
<label>Cardholder Name</label>
|
|
5799
|
-
<div id="cc-name" class="field-wrapper"></div>
|
|
5800
|
-
</div>
|
|
5801
|
-
|
|
5802
|
-
<div id="error-msg" class="error-msg"></div>
|
|
5803
|
-
|
|
5804
|
-
<button type="submit" id="submit-btn" class="submit-btn" disabled>
|
|
5805
|
-
Add Card
|
|
5806
|
-
</button>
|
|
5807
|
-
</form>
|
|
5808
|
-
|
|
5809
|
-
<div class="security-note">
|
|
5810
|
-
<svg width="12" height="12" viewBox="0 0 12 12" fill="#555"><path d="M6 1a3 3 0 0 0-3 3v1H2.5A.5.5 0 0 0 2 5.5v5a.5.5 0 0 0 .5.5h7a.5.5 0 0 0 .5-.5v-5A.5.5 0 0 0 9.5 5H9V4a3 3 0 0 0-3-3zm2 4H4V4a2 2 0 1 1 4 0v1z"/></svg>
|
|
5811
|
-
Secured by VGS. Lane never sees your card number.
|
|
5812
|
-
</div>
|
|
5813
|
-
</div>
|
|
5814
|
-
|
|
5815
|
-
<div id="success-view" class="success-container">
|
|
5816
|
-
<div class="check">✓</div>
|
|
5817
|
-
<div class="logo">Card Added</div>
|
|
5818
|
-
<div class="subtitle">You can close this window and return to your terminal.</div>
|
|
5819
|
-
</div>
|
|
5820
|
-
</div>
|
|
5821
|
-
|
|
5822
|
-
<script>
|
|
5823
|
-
const form = VGSCollect.create('${config.vaultId}', '${vgsEnv}', function(state) {});
|
|
5824
|
-
const css = {
|
|
5825
|
-
'font-family': '"JetBrains Mono", monospace',
|
|
5826
|
-
'font-size': '16px',
|
|
5827
|
-
'color': '#FFFFFF',
|
|
5828
|
-
'padding': '12px 16px',
|
|
5829
|
-
'&::placeholder': { color: '#555' },
|
|
5830
|
-
};
|
|
5831
|
-
|
|
5832
|
-
form.field('#cc-number', {
|
|
5833
|
-
type: 'card-number',
|
|
5834
|
-
name: 'card_number',
|
|
5835
|
-
placeholder: '4242 4242 4242 4242',
|
|
5836
|
-
validations: ['required', 'validCardNumber'],
|
|
5837
|
-
css: css,
|
|
5838
|
-
});
|
|
5839
|
-
|
|
5840
|
-
form.field('#cc-expiry', {
|
|
5841
|
-
type: 'card-expiration-date',
|
|
5842
|
-
name: 'card_exp',
|
|
5843
|
-
placeholder: 'MM / YY',
|
|
5844
|
-
validations: ['required', 'validCardExpirationDate'],
|
|
5845
|
-
css: css,
|
|
5846
|
-
});
|
|
5847
|
-
|
|
5848
|
-
form.field('#cc-cvc', {
|
|
5849
|
-
type: 'card-security-code',
|
|
5850
|
-
name: 'card_cvc',
|
|
5851
|
-
placeholder: 'CVC',
|
|
5852
|
-
validations: ['required', 'validCardSecurityCode'],
|
|
5853
|
-
css: css,
|
|
5854
|
-
});
|
|
5855
|
-
|
|
5856
|
-
form.field('#cc-name', {
|
|
5857
|
-
type: 'text',
|
|
5858
|
-
name: 'card_name',
|
|
5859
|
-
placeholder: 'Name on card',
|
|
5860
|
-
validations: ['required'],
|
|
5861
|
-
css: css,
|
|
5862
|
-
});
|
|
5863
|
-
|
|
5864
|
-
// Enable submit when all fields are valid
|
|
5865
|
-
let fieldStates = {};
|
|
5866
|
-
form.on('change', function(state) {
|
|
5867
|
-
fieldStates = state;
|
|
5868
|
-
const allValid = Object.values(state).every(function(f) { return f.isValid; });
|
|
5869
|
-
document.getElementById('submit-btn').disabled = !allValid;
|
|
5870
|
-
});
|
|
5871
|
-
|
|
5872
|
-
document.getElementById('card-form').addEventListener('submit', function(e) {
|
|
5873
|
-
e.preventDefault();
|
|
5874
|
-
var btn = document.getElementById('submit-btn');
|
|
5875
|
-
btn.disabled = true;
|
|
5876
|
-
btn.textContent = 'Processing...';
|
|
5877
|
-
document.getElementById('error-msg').style.display = 'none';
|
|
5878
|
-
|
|
5879
|
-
form.submit(
|
|
5880
|
-
'/post',
|
|
5881
|
-
{
|
|
5882
|
-
headers: { 'Content-Type': 'application/json' },
|
|
5883
|
-
data: function(fields) {
|
|
5884
|
-
return {
|
|
5885
|
-
card_number: fields.card_number,
|
|
5886
|
-
card_exp: fields.card_exp,
|
|
5887
|
-
card_cvc: fields.card_cvc,
|
|
5888
|
-
card_name: fields.card_name,
|
|
5889
|
-
developer_id: '${config.developerId}',
|
|
5890
|
-
};
|
|
5891
|
-
},
|
|
5892
|
-
},
|
|
5893
|
-
function(status, data) {
|
|
5894
|
-
if (status >= 200 && status < 300) {
|
|
5895
|
-
document.getElementById('form-view').style.display = 'none';
|
|
5896
|
-
document.getElementById('success-view').style.display = 'block';
|
|
5897
|
-
// Notify callback
|
|
5898
|
-
fetch('${config.callbackUrl}', {
|
|
5899
|
-
method: 'POST',
|
|
5900
|
-
headers: { 'Content-Type': 'application/json' },
|
|
5901
|
-
body: JSON.stringify({
|
|
5902
|
-
alias: data.card_number,
|
|
5903
|
-
last4: data.last4 || 'xxxx',
|
|
5904
|
-
brand: data.brand || 'unknown',
|
|
5905
|
-
}),
|
|
5906
|
-
});
|
|
5907
|
-
} else {
|
|
5908
|
-
var errEl = document.getElementById('error-msg');
|
|
5909
|
-
errEl.textContent = 'Card could not be saved. Please check your details and try again.';
|
|
5910
|
-
errEl.style.display = 'block';
|
|
5911
|
-
btn.disabled = false;
|
|
5912
|
-
btn.textContent = 'Add Card';
|
|
5913
|
-
}
|
|
5914
|
-
},
|
|
5915
|
-
function(errors) {
|
|
5916
|
-
var errEl = document.getElementById('error-msg');
|
|
5917
|
-
errEl.textContent = 'Validation failed. Please check all fields.';
|
|
5918
|
-
errEl.style.display = 'block';
|
|
5919
|
-
btn.disabled = false;
|
|
5920
|
-
btn.textContent = 'Add Card';
|
|
5921
|
-
}
|
|
5922
|
-
);
|
|
5923
|
-
});
|
|
5924
|
-
</script>
|
|
5925
|
-
</body>
|
|
5926
|
-
</html>`;
|
|
5927
|
-
}
|
|
5928
|
-
|
|
5929
|
-
// src/psp/registry.ts
|
|
5930
|
-
var PSPRegistry = class {
|
|
5931
|
-
adapters = /* @__PURE__ */ new Map();
|
|
5932
|
-
/**
|
|
5933
|
-
* Register an adapter with a priority (lower = higher priority).
|
|
5934
|
-
*/
|
|
5935
|
-
register(adapter, priority = 100) {
|
|
5936
|
-
this.adapters.set(adapter.name, { adapter, priority });
|
|
5937
|
-
}
|
|
5938
|
-
/**
|
|
5939
|
-
* Remove an adapter from the registry.
|
|
5940
|
-
*/
|
|
5941
|
-
unregister(name) {
|
|
5942
|
-
this.adapters.delete(name);
|
|
5943
|
-
}
|
|
5944
|
-
/**
|
|
5945
|
-
* Get a specific adapter by name.
|
|
5946
|
-
*/
|
|
5947
|
-
get(name) {
|
|
5948
|
-
return this.adapters.get(name)?.adapter;
|
|
5949
|
-
}
|
|
5950
|
-
/**
|
|
5951
|
-
* Get the highest-priority adapter (lowest priority number).
|
|
5952
|
-
* Optionally exclude specific adapters (e.g., after a failure).
|
|
5953
|
-
*/
|
|
5954
|
-
getPrimary(exclude) {
|
|
5955
|
-
let best;
|
|
5956
|
-
for (const [name, entry] of this.adapters) {
|
|
5957
|
-
if (exclude?.has(name)) continue;
|
|
5958
|
-
if (!best || entry.priority < best.priority) {
|
|
5959
|
-
best = entry;
|
|
5960
|
-
}
|
|
5961
|
-
}
|
|
5962
|
-
return best?.adapter;
|
|
5963
|
-
}
|
|
5964
|
-
/**
|
|
5965
|
-
* Get all registered adapters sorted by priority.
|
|
5966
|
-
*/
|
|
5967
|
-
getAll() {
|
|
5968
|
-
return Array.from(this.adapters.values()).sort((a, b) => a.priority - b.priority).map((entry) => entry.adapter);
|
|
5969
|
-
}
|
|
5970
|
-
/**
|
|
5971
|
-
* Run health checks on all adapters. Returns names of healthy adapters.
|
|
5972
|
-
*/
|
|
5973
|
-
async healthCheckAll() {
|
|
5974
|
-
const results = await Promise.allSettled(
|
|
5975
|
-
Array.from(this.adapters.entries()).map(async ([name, { adapter }]) => {
|
|
5976
|
-
const ok = await adapter.healthCheck();
|
|
5977
|
-
return ok ? name : null;
|
|
5978
|
-
})
|
|
5979
|
-
);
|
|
5980
|
-
return results.filter((r) => r.status === "fulfilled" && r.value !== null).map((r) => r.value);
|
|
5981
|
-
}
|
|
5982
|
-
};
|
|
5983
|
-
|
|
5984
|
-
// src/psp/adapters/stripe.ts
|
|
5985
|
-
var StripeAdapter = class {
|
|
5986
|
-
name = "stripe";
|
|
5987
|
-
config;
|
|
5988
|
-
constructor(config) {
|
|
5989
|
-
this.config = config;
|
|
5990
|
-
}
|
|
5991
|
-
async charge(params) {
|
|
5992
|
-
const now = /* @__PURE__ */ new Date();
|
|
5993
|
-
const expiryDate = new Date(params.expYear, params.expMonth);
|
|
5994
|
-
if (expiryDate <= now) {
|
|
5995
|
-
return {
|
|
5996
|
-
pspTransactionId: "",
|
|
5997
|
-
status: "failed",
|
|
5998
|
-
declineReason: "Card has expired",
|
|
5999
|
-
rawResponse: { error: "card_expired", expMonth: params.expMonth, expYear: params.expYear }
|
|
6000
|
-
};
|
|
6001
|
-
}
|
|
6002
|
-
const body = {
|
|
6003
|
-
amount: params.amount,
|
|
6004
|
-
currency: params.currency.toLowerCase(),
|
|
6005
|
-
source: {
|
|
6006
|
-
object: "card",
|
|
6007
|
-
number: params.cardAlias,
|
|
6008
|
-
// VGS reveals this to Stripe
|
|
6009
|
-
exp_month: params.expMonth,
|
|
6010
|
-
exp_year: params.expYear,
|
|
6011
|
-
cvc: params.cvvAlias
|
|
6012
|
-
},
|
|
6013
|
-
description: params.merchantDescriptor,
|
|
6014
|
-
metadata: params.metadata ?? {}
|
|
6015
|
-
};
|
|
6016
|
-
const response = await this.config.proxy.forward({
|
|
6017
|
-
url: "https://api.stripe.com/v1/charges",
|
|
6018
|
-
method: "POST",
|
|
6019
|
-
headers: {
|
|
6020
|
-
"Authorization": `Bearer ${this.config.secretKey}`,
|
|
6021
|
-
"Stripe-Version": this.config.apiVersion ?? "2024-12-18.acacia",
|
|
6022
|
-
...params.idempotencyKey ? { "Idempotency-Key": params.idempotencyKey } : {}
|
|
6023
|
-
},
|
|
6024
|
-
body
|
|
6025
|
-
});
|
|
6026
|
-
const data = response.body;
|
|
6027
|
-
const status = data["status"] === "succeeded" ? "succeeded" : data["status"] === "pending" ? "pending" : "failed";
|
|
6028
|
-
return {
|
|
6029
|
-
pspTransactionId: String(data["id"] ?? ""),
|
|
6030
|
-
status,
|
|
6031
|
-
authorizationCode: data["authorization_code"],
|
|
6032
|
-
declineReason: status === "failed" ? String(data["failure_message"] ?? "unknown") : void 0,
|
|
6033
|
-
rawResponse: data
|
|
6034
|
-
};
|
|
6035
|
-
}
|
|
6036
|
-
async refund(params) {
|
|
6037
|
-
const body = {
|
|
6038
|
-
charge: params.pspTransactionId,
|
|
6039
|
-
...params.amount !== void 0 ? { amount: params.amount } : {},
|
|
6040
|
-
...params.reason ? { reason: params.reason } : {}
|
|
6041
|
-
};
|
|
6042
|
-
const response = await this.config.proxy.forward({
|
|
6043
|
-
url: "https://api.stripe.com/v1/refunds",
|
|
6044
|
-
method: "POST",
|
|
6045
|
-
headers: {
|
|
6046
|
-
"Authorization": `Bearer ${this.config.secretKey}`,
|
|
6047
|
-
"Stripe-Version": this.config.apiVersion ?? "2024-12-18.acacia",
|
|
6048
|
-
...params.idempotencyKey ? { "Idempotency-Key": params.idempotencyKey } : {}
|
|
6049
|
-
},
|
|
6050
|
-
body
|
|
6051
|
-
});
|
|
6052
|
-
const data = response.body;
|
|
6053
|
-
const status = data["status"] === "succeeded" ? "succeeded" : data["status"] === "pending" ? "pending" : "failed";
|
|
6054
|
-
return {
|
|
6055
|
-
pspRefundId: String(data["id"] ?? ""),
|
|
6056
|
-
status,
|
|
6057
|
-
amount: Number(data["amount"] ?? 0),
|
|
6058
|
-
rawResponse: data
|
|
6059
|
-
};
|
|
6060
|
-
}
|
|
6061
|
-
async healthCheck() {
|
|
6062
|
-
try {
|
|
6063
|
-
const response = await fetch("https://api.stripe.com/v1/balance", {
|
|
6064
|
-
headers: { "Authorization": `Bearer ${this.config.secretKey}` }
|
|
6065
|
-
});
|
|
6066
|
-
return response.ok;
|
|
6067
|
-
} catch {
|
|
6068
|
-
return false;
|
|
6069
|
-
}
|
|
6070
|
-
}
|
|
6071
|
-
};
|
|
6072
|
-
|
|
6073
|
-
// src/psp/adapters/worldpay.ts
|
|
6074
|
-
var WorldpayAdapter = class {
|
|
6075
|
-
name = "worldpay";
|
|
6076
|
-
config;
|
|
6077
|
-
constructor(config) {
|
|
6078
|
-
this.config = config;
|
|
6079
|
-
}
|
|
6080
|
-
async charge(params) {
|
|
6081
|
-
const now = /* @__PURE__ */ new Date();
|
|
6082
|
-
const expiryDate = new Date(params.expYear, params.expMonth);
|
|
6083
|
-
if (expiryDate <= now) {
|
|
6084
|
-
return {
|
|
6085
|
-
pspTransactionId: "",
|
|
6086
|
-
status: "failed",
|
|
6087
|
-
declineReason: "Card has expired",
|
|
6088
|
-
rawResponse: { error: "card_expired", expMonth: params.expMonth, expYear: params.expYear }
|
|
6089
|
-
};
|
|
6090
|
-
}
|
|
6091
|
-
const body = {
|
|
6092
|
-
transactionType: "sale",
|
|
6093
|
-
amount: {
|
|
6094
|
-
value: params.amount,
|
|
6095
|
-
currencyCode: params.currency.toUpperCase()
|
|
6096
|
-
},
|
|
6097
|
-
paymentInstrument: {
|
|
6098
|
-
type: "card/plain",
|
|
6099
|
-
cardNumber: params.cardAlias,
|
|
6100
|
-
// VGS reveals to Worldpay
|
|
6101
|
-
expiryDate: {
|
|
6102
|
-
month: params.expMonth,
|
|
6103
|
-
year: params.expYear
|
|
6104
|
-
},
|
|
6105
|
-
cvc: params.cvvAlias
|
|
6106
|
-
},
|
|
6107
|
-
merchant: {
|
|
6108
|
-
entity: this.config.merchantId
|
|
6109
|
-
},
|
|
6110
|
-
narrative: {
|
|
6111
|
-
line1: params.merchantDescriptor
|
|
6112
|
-
}
|
|
6113
|
-
};
|
|
6114
|
-
const response = await this.config.proxy.forward({
|
|
6115
|
-
url: `${this.config.baseUrl}/payments/authorizations`,
|
|
6116
|
-
method: "POST",
|
|
6117
|
-
headers: {
|
|
6118
|
-
"Authorization": `Bearer ${this.config.apiKey}`,
|
|
6119
|
-
...params.idempotencyKey ? { "Idempotency-Key": params.idempotencyKey } : {}
|
|
6120
|
-
},
|
|
6121
|
-
body
|
|
6122
|
-
});
|
|
6123
|
-
const data = response.body;
|
|
6124
|
-
const outcome = data["outcome"];
|
|
6125
|
-
const status = outcome === "approved" ? "succeeded" : outcome === "pending" ? "pending" : "failed";
|
|
6126
|
-
return {
|
|
6127
|
-
pspTransactionId: String(data["_links"] && data["_links"]["self"] || ""),
|
|
6128
|
-
status,
|
|
6129
|
-
authorizationCode: data["authorizationCode"],
|
|
6130
|
-
declineReason: status === "failed" ? String(data["description"] ?? "declined") : void 0,
|
|
6131
|
-
rawResponse: data
|
|
6132
|
-
};
|
|
6133
|
-
}
|
|
6134
|
-
async refund(params) {
|
|
6135
|
-
const body = {
|
|
6136
|
-
...params.amount !== void 0 ? { value: { amount: params.amount, currencyCode: "USD" } } : {},
|
|
6137
|
-
...params.reason ? { reference: params.reason } : {}
|
|
6138
|
-
};
|
|
6139
|
-
const response = await this.config.proxy.forward({
|
|
6140
|
-
url: `${this.config.baseUrl}/payments/${params.pspTransactionId}/refunds`,
|
|
6141
|
-
method: "POST",
|
|
6142
|
-
headers: {
|
|
6143
|
-
"Authorization": `Bearer ${this.config.apiKey}`,
|
|
6144
|
-
...params.idempotencyKey ? { "Idempotency-Key": params.idempotencyKey } : {}
|
|
6145
|
-
},
|
|
6146
|
-
body
|
|
6147
|
-
});
|
|
6148
|
-
const data = response.body;
|
|
6149
|
-
const outcome = data["outcome"];
|
|
6150
|
-
const refundStatus = outcome === "failed" ? "failed" : outcome === "pending" ? "pending" : "succeeded";
|
|
6151
|
-
return {
|
|
6152
|
-
pspRefundId: String(data["refundId"] ?? ""),
|
|
6153
|
-
status: refundStatus,
|
|
6154
|
-
amount: params.amount ?? 0,
|
|
6155
|
-
rawResponse: data
|
|
6156
|
-
};
|
|
6157
|
-
}
|
|
6158
|
-
async healthCheck() {
|
|
6159
|
-
try {
|
|
6160
|
-
const response = await fetch(`${this.config.baseUrl}/health`, {
|
|
6161
|
-
headers: { "Authorization": `Bearer ${this.config.apiKey}` }
|
|
6162
|
-
});
|
|
6163
|
-
return response.ok;
|
|
6164
|
-
} catch {
|
|
6165
|
-
return false;
|
|
6166
|
-
}
|
|
6167
|
-
}
|
|
6168
|
-
};
|
|
6169
|
-
|
|
6170
|
-
// src/psp/adapters/cybersource.ts
|
|
6171
|
-
var CyberSourceAdapter = class {
|
|
6172
|
-
name = "cybersource";
|
|
6173
|
-
config;
|
|
6174
|
-
constructor(config) {
|
|
6175
|
-
this.config = config;
|
|
6176
|
-
}
|
|
6177
|
-
async charge(params) {
|
|
6178
|
-
const now = /* @__PURE__ */ new Date();
|
|
6179
|
-
const expiryDate = new Date(params.expYear, params.expMonth);
|
|
6180
|
-
if (expiryDate <= now) {
|
|
6181
|
-
return {
|
|
6182
|
-
pspTransactionId: "",
|
|
6183
|
-
status: "failed",
|
|
6184
|
-
declineReason: "Card has expired",
|
|
6185
|
-
rawResponse: { error: "card_expired", expMonth: params.expMonth, expYear: params.expYear }
|
|
6186
|
-
};
|
|
6187
|
-
}
|
|
6188
|
-
const csParams = params;
|
|
6189
|
-
const paymentInformation = csParams.isNetworkToken ? {
|
|
6190
|
-
tokenizedCard: {
|
|
6191
|
-
number: params.cardAlias,
|
|
6192
|
-
// VGS reveals to CyberSource
|
|
6193
|
-
expirationMonth: String(params.expMonth).padStart(2, "0"),
|
|
6194
|
-
expirationYear: String(params.expYear),
|
|
6195
|
-
cryptogram: csParams.cryptogram,
|
|
6196
|
-
type: "001"
|
|
6197
|
-
// Visa network token
|
|
6198
|
-
}
|
|
6199
|
-
} : {
|
|
6200
|
-
card: {
|
|
6201
|
-
number: params.cardAlias,
|
|
6202
|
-
// VGS reveals to CyberSource
|
|
6203
|
-
expirationMonth: String(params.expMonth).padStart(2, "0"),
|
|
6204
|
-
expirationYear: String(params.expYear),
|
|
6205
|
-
securityCode: params.cvvAlias
|
|
6206
|
-
}
|
|
6207
|
-
};
|
|
6208
|
-
const body = {
|
|
6209
|
-
clientReferenceInformation: {
|
|
6210
|
-
code: params.idempotencyKey ?? `lane_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`
|
|
6211
|
-
},
|
|
6212
|
-
processingInformation: {
|
|
6213
|
-
capture: true,
|
|
6214
|
-
...csParams.isNetworkToken ? { paymentSolution: "015" } : {},
|
|
6215
|
-
...csParams.eci ? { commerceIndicator: csParams.eci } : {}
|
|
6216
|
-
},
|
|
6217
|
-
orderInformation: {
|
|
6218
|
-
amountDetails: {
|
|
6219
|
-
totalAmount: (params.amount / 100).toFixed(2),
|
|
6220
|
-
currency: params.currency.toUpperCase()
|
|
6221
|
-
}
|
|
6222
|
-
},
|
|
6223
|
-
paymentInformation
|
|
6224
|
-
};
|
|
6225
|
-
const response = await this.config.proxy.forward({
|
|
6226
|
-
url: `${this.config.baseUrl}/pts/v2/payments`,
|
|
6227
|
-
method: "POST",
|
|
6228
|
-
headers: {
|
|
6229
|
-
"v-c-merchant-id": this.config.merchantId,
|
|
6230
|
-
"Content-Type": "application/json"
|
|
6231
|
-
},
|
|
6232
|
-
body
|
|
6233
|
-
});
|
|
6234
|
-
const data = response.body;
|
|
6235
|
-
const csStatus = data["status"];
|
|
6236
|
-
const status = csStatus === "AUTHORIZED" || csStatus === "PENDING" ? csStatus === "AUTHORIZED" ? "succeeded" : "pending" : "failed";
|
|
6237
|
-
return {
|
|
6238
|
-
pspTransactionId: String(data["id"] ?? ""),
|
|
6239
|
-
status,
|
|
6240
|
-
authorizationCode: data["processorInformation"]?.["approvalCode"],
|
|
6241
|
-
declineReason: status === "failed" ? String(data["errorInformation"]?.["message"] ?? "declined") : void 0,
|
|
6242
|
-
rawResponse: data
|
|
6243
|
-
};
|
|
6244
|
-
}
|
|
6245
|
-
async refund(params) {
|
|
6246
|
-
const body = {
|
|
6247
|
-
clientReferenceInformation: {
|
|
6248
|
-
code: params.idempotencyKey ?? `lane_ref_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`
|
|
6249
|
-
},
|
|
6250
|
-
orderInformation: {
|
|
6251
|
-
amountDetails: {
|
|
6252
|
-
...params.amount !== void 0 ? { totalAmount: (params.amount / 100).toFixed(2) } : {},
|
|
6253
|
-
currency: "USD"
|
|
6254
|
-
}
|
|
6255
|
-
}
|
|
6256
|
-
};
|
|
6257
|
-
const response = await this.config.proxy.forward({
|
|
6258
|
-
url: `${this.config.baseUrl}/pts/v2/payments/${params.pspTransactionId}/refunds`,
|
|
6259
|
-
method: "POST",
|
|
6260
|
-
headers: {
|
|
6261
|
-
"v-c-merchant-id": this.config.merchantId,
|
|
6262
|
-
"Content-Type": "application/json"
|
|
6263
|
-
},
|
|
6264
|
-
body
|
|
6265
|
-
});
|
|
6266
|
-
const data = response.body;
|
|
6267
|
-
const csStatus = data["status"];
|
|
6268
|
-
return {
|
|
6269
|
-
pspRefundId: String(data["id"] ?? ""),
|
|
6270
|
-
status: csStatus === "PENDING" ? "pending" : "succeeded",
|
|
6271
|
-
amount: params.amount ?? 0,
|
|
6272
|
-
rawResponse: data
|
|
6273
|
-
};
|
|
6274
|
-
}
|
|
6275
|
-
async healthCheck() {
|
|
6276
|
-
try {
|
|
6277
|
-
const response = await fetch(`${this.config.baseUrl}/reporting/v3/report-definitions`, {
|
|
6278
|
-
headers: { "v-c-merchant-id": this.config.merchantId }
|
|
6279
|
-
});
|
|
6280
|
-
return response.status !== 500;
|
|
6281
|
-
} catch {
|
|
6282
|
-
return false;
|
|
6283
|
-
}
|
|
6284
|
-
}
|
|
6285
|
-
};
|
|
6286
|
-
|
|
6287
5522
|
// src/merchants/billing-api-directory.ts
|
|
6288
5523
|
var BILLING_API_MERCHANTS = Object.freeze([
|
|
6289
5524
|
{
|
|
@@ -6323,154 +5558,6 @@ new Map(
|
|
|
6323
5558
|
...m.aliases.map((a) => [a.toLowerCase(), m])
|
|
6324
5559
|
])
|
|
6325
5560
|
);
|
|
6326
|
-
function toBillingAPICapabilities() {
|
|
6327
|
-
return BILLING_API_MERCHANTS.map((m) => ({
|
|
6328
|
-
merchantId: m.domain,
|
|
6329
|
-
hasBillingAPI: true,
|
|
6330
|
-
supportsACP: false,
|
|
6331
|
-
supportsUCP: false,
|
|
6332
|
-
supportsX402: false,
|
|
6333
|
-
supportsVIC: true,
|
|
6334
|
-
supportsRye: false,
|
|
6335
|
-
acceptsVisa: true,
|
|
6336
|
-
acceptsMastercard: true,
|
|
6337
|
-
mccs: m.mccs
|
|
6338
|
-
}));
|
|
6339
|
-
}
|
|
6340
|
-
|
|
6341
|
-
// src/routing/engine.ts
|
|
6342
|
-
var MerchantRegistry = class _MerchantRegistry {
|
|
6343
|
-
merchants = /* @__PURE__ */ new Map();
|
|
6344
|
-
register(capabilities) {
|
|
6345
|
-
this.merchants.set(capabilities.merchantId, capabilities);
|
|
6346
|
-
}
|
|
6347
|
-
get(merchantId) {
|
|
6348
|
-
return this.merchants.get(merchantId);
|
|
6349
|
-
}
|
|
6350
|
-
registerBatch(merchants) {
|
|
6351
|
-
for (const m of merchants) {
|
|
6352
|
-
this.merchants.set(m.merchantId, m);
|
|
6353
|
-
}
|
|
6354
|
-
}
|
|
6355
|
-
/** Create a registry pre-populated from directory capabilities. */
|
|
6356
|
-
static fromDirectory(capabilities) {
|
|
6357
|
-
const registry = new _MerchantRegistry();
|
|
6358
|
-
registry.registerBatch(capabilities);
|
|
6359
|
-
return registry;
|
|
6360
|
-
}
|
|
6361
|
-
/** Clear and repopulate with new capabilities. */
|
|
6362
|
-
reload(capabilities) {
|
|
6363
|
-
this.merchants.clear();
|
|
6364
|
-
this.registerBatch(capabilities);
|
|
6365
|
-
}
|
|
6366
|
-
/** Number of registered merchants. */
|
|
6367
|
-
get size() {
|
|
6368
|
-
return this.merchants.size;
|
|
6369
|
-
}
|
|
6370
|
-
/** List all registered merchant IDs. */
|
|
6371
|
-
listIds() {
|
|
6372
|
-
return Array.from(this.merchants.keys());
|
|
6373
|
-
}
|
|
6374
|
-
/**
|
|
6375
|
-
* Create a registry pre-seeded with the built-in UCP merchant directory.
|
|
6376
|
-
*
|
|
6377
|
-
* These merchants have verified `/.well-known/ucp` endpoints, so the
|
|
6378
|
-
* routing engine can immediately route to Tier 3 (UCP) without a server
|
|
6379
|
-
* round-trip for discovery. Additional merchants from the Lane backend
|
|
6380
|
-
* can be merged in later via `register()` or `registerBatch()`.
|
|
6381
|
-
*/
|
|
6382
|
-
static withUCPDirectory() {
|
|
6383
|
-
return _MerchantRegistry.fromDirectory(toMerchantCapabilities());
|
|
6384
|
-
}
|
|
6385
|
-
/**
|
|
6386
|
-
* Create a registry pre-seeded with ALL built-in merchant directories:
|
|
6387
|
-
* - Billing API merchants (Tier 1) — SaaS/API merchants with direct endpoints
|
|
6388
|
-
* - UCP merchants (Tier 3) — ecommerce merchants with /.well-known/ucp
|
|
6389
|
-
*
|
|
6390
|
-
* This gives agents instant routing for known merchants without any server
|
|
6391
|
-
* round-trip. Use this for the best out-of-the-box experience.
|
|
6392
|
-
*/
|
|
6393
|
-
static withBuiltinDirectory() {
|
|
6394
|
-
return _MerchantRegistry.fromDirectory([
|
|
6395
|
-
...toBillingAPICapabilities(),
|
|
6396
|
-
...toMerchantCapabilities()
|
|
6397
|
-
]);
|
|
6398
|
-
}
|
|
6399
|
-
};
|
|
6400
|
-
var PaymentRouter = class {
|
|
6401
|
-
constructor(registry) {
|
|
6402
|
-
this.registry = registry;
|
|
6403
|
-
}
|
|
6404
|
-
/**
|
|
6405
|
-
* Decide the payment route for a transaction.
|
|
6406
|
-
*/
|
|
6407
|
-
route(context) {
|
|
6408
|
-
const merchant = this.registry.get(context.merchantId);
|
|
6409
|
-
const fallbacks = [];
|
|
6410
|
-
if (context.budget && context.currentSpend !== void 0) {
|
|
6411
|
-
const limit = context.budget.perTaskLimit ?? context.budget.dailyLimit;
|
|
6412
|
-
if (limit !== void 0 && context.amount > limit - context.currentSpend) {
|
|
6413
|
-
return {
|
|
6414
|
-
route: "fallback",
|
|
6415
|
-
merchantId: context.merchantId,
|
|
6416
|
-
reason: "Transaction would exceed budget limits.",
|
|
6417
|
-
fallbacks: []
|
|
6418
|
-
};
|
|
6419
|
-
}
|
|
6420
|
-
}
|
|
6421
|
-
if (merchant?.hasBillingAPI) {
|
|
6422
|
-
fallbacks.push("acp", "ucp", "x402", "fallback");
|
|
6423
|
-
return {
|
|
6424
|
-
route: "billing_api",
|
|
6425
|
-
merchantId: context.merchantId,
|
|
6426
|
-
reason: "Merchant has direct billing API integration (cheapest path).",
|
|
6427
|
-
fallbacks: this.filterFallbacks(fallbacks, merchant)
|
|
6428
|
-
};
|
|
6429
|
-
}
|
|
6430
|
-
if (merchant?.supportsACP) {
|
|
6431
|
-
fallbacks.push("ucp", "x402", "fallback");
|
|
6432
|
-
return {
|
|
6433
|
-
route: "acp",
|
|
6434
|
-
merchantId: context.merchantId,
|
|
6435
|
-
reason: "Merchant supports Agent Commerce Protocol checkout.",
|
|
6436
|
-
fallbacks: this.filterFallbacks(fallbacks, merchant)
|
|
6437
|
-
};
|
|
6438
|
-
}
|
|
6439
|
-
if (merchant?.supportsUCP) {
|
|
6440
|
-
fallbacks.push("x402", "fallback");
|
|
6441
|
-
return {
|
|
6442
|
-
route: "ucp",
|
|
6443
|
-
merchantId: context.merchantId,
|
|
6444
|
-
reason: "Merchant supports Universal Checkout Protocol.",
|
|
6445
|
-
fallbacks: this.filterFallbacks(fallbacks, merchant)
|
|
6446
|
-
};
|
|
6447
|
-
}
|
|
6448
|
-
if (merchant?.supportsX402) {
|
|
6449
|
-
fallbacks.push("fallback");
|
|
6450
|
-
return {
|
|
6451
|
-
route: "x402",
|
|
6452
|
-
merchantId: context.merchantId,
|
|
6453
|
-
reason: "Merchant supports x402 HTTP payment protocol.",
|
|
6454
|
-
fallbacks
|
|
6455
|
-
};
|
|
6456
|
-
}
|
|
6457
|
-
const fallbackStrategies = ["rye", "browser_use", "vgs_proxy"];
|
|
6458
|
-
return {
|
|
6459
|
-
route: "fallback",
|
|
6460
|
-
merchantId: context.merchantId,
|
|
6461
|
-
reason: merchant ? "No preferred protocol available; using fallback strategies (Rye \u2192 browser use \u2192 VGS proxy)." : "Unknown merchant; using fallback strategies (Rye \u2192 browser use \u2192 VGS proxy).",
|
|
6462
|
-
fallbacks: fallbackStrategies
|
|
6463
|
-
};
|
|
6464
|
-
}
|
|
6465
|
-
filterFallbacks(routes, merchant) {
|
|
6466
|
-
return routes.filter((r) => {
|
|
6467
|
-
if (r === "acp") return merchant.supportsACP;
|
|
6468
|
-
if (r === "ucp") return merchant.supportsUCP;
|
|
6469
|
-
if (r === "x402") return merchant.supportsX402;
|
|
6470
|
-
return true;
|
|
6471
|
-
});
|
|
6472
|
-
}
|
|
6473
|
-
};
|
|
6474
5561
|
|
|
6475
5562
|
// src/index.ts
|
|
6476
5563
|
var index_default = Lane;
|
|
@@ -6487,7 +5574,6 @@ exports.Commerce = Commerce;
|
|
|
6487
5574
|
exports.CommerceCatalog = CommerceCatalog;
|
|
6488
5575
|
exports.CommerceOrders = CommerceOrders;
|
|
6489
5576
|
exports.CommerceProviders = CommerceProviders;
|
|
6490
|
-
exports.CyberSourceAdapter = CyberSourceAdapter;
|
|
6491
5577
|
exports.FileTokenStore = FileTokenStore;
|
|
6492
5578
|
exports.Fleet = Fleet;
|
|
6493
5579
|
exports.HMACSignature = HMACSignature;
|
|
@@ -6504,32 +5590,24 @@ exports.LaneNotFoundError = LaneNotFoundError;
|
|
|
6504
5590
|
exports.LanePaymentError = LanePaymentError;
|
|
6505
5591
|
exports.LaneRateLimitError = LaneRateLimitError;
|
|
6506
5592
|
exports.LaneValidationError = LaneValidationError;
|
|
6507
|
-
exports.MerchantRegistry = MerchantRegistry;
|
|
6508
5593
|
exports.Merchants = Merchants;
|
|
6509
5594
|
exports.Metering = Metering;
|
|
6510
|
-
exports.PSPRegistry = PSPRegistry;
|
|
6511
5595
|
exports.Pay = Pay;
|
|
6512
|
-
exports.PaymentRouter = PaymentRouter;
|
|
6513
5596
|
exports.Payouts = Payouts;
|
|
6514
5597
|
exports.Products = Products;
|
|
6515
5598
|
exports.Resource = Resource;
|
|
6516
5599
|
exports.Sell = Sell;
|
|
6517
|
-
exports.StripeAdapter = StripeAdapter;
|
|
6518
5600
|
exports.Subscriptions = Subscriptions;
|
|
6519
5601
|
exports.Teams = Teams;
|
|
6520
5602
|
exports.Tokens = Tokens;
|
|
6521
5603
|
exports.Transactions = Transactions;
|
|
6522
5604
|
exports.Users = Users;
|
|
6523
|
-
exports.VGSOutboundProxy = VGSOutboundProxy;
|
|
6524
|
-
exports.VGSTokenManager = VGSTokenManager;
|
|
6525
5605
|
exports.VIC = VIC;
|
|
6526
5606
|
exports.Wallets = Wallets;
|
|
6527
5607
|
exports.Webhooks = Webhooks;
|
|
6528
|
-
exports.WorldpayAdapter = WorldpayAdapter;
|
|
6529
5608
|
exports.createErrorFromResponse = createErrorFromResponse;
|
|
6530
5609
|
exports.default = index_default;
|
|
6531
5610
|
exports.detectCardBrand = detectCardBrand;
|
|
6532
|
-
exports.generateCollectPage = generateCollectPage;
|
|
6533
5611
|
exports.getLaneInstructions = getLaneInstructions;
|
|
6534
5612
|
exports.listUCPByVertical = listUCPByVertical;
|
|
6535
5613
|
exports.listUCPMerchants = listUCPMerchants;
|
|
@@ -6542,5 +5620,3 @@ exports.resolveUCPByDomain = resolveUCPByDomain;
|
|
|
6542
5620
|
exports.toUCPEndpoint = toUCPEndpoint;
|
|
6543
5621
|
exports.toUCPMerchantCapabilities = toMerchantCapabilities;
|
|
6544
5622
|
exports.verifyWebhookSignature = verifyWebhookSignature;
|
|
6545
|
-
//# sourceMappingURL=index.cjs.map
|
|
6546
|
-
//# sourceMappingURL=index.cjs.map
|