@solvapay/server 1.3.0 → 1.4.0-preview-e2cd9bda9dee33e68f6bba7098f7d683e6f1b742
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/edge.d.ts +118 -1
- package/dist/edge.js +83 -0
- package/dist/fetch/index.cjs +50 -16
- package/dist/fetch/index.d.cts +31 -0
- package/dist/fetch/index.d.ts +31 -0
- package/dist/fetch/index.js +36 -0
- package/dist/index.cjs +99 -17
- package/dist/index.d.cts +118 -1
- package/dist/index.d.ts +118 -1
- package/dist/index.js +83 -0
- package/package.json +2 -2
package/dist/edge.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import * as _solvapay_core from '@solvapay/core';
|
|
2
|
+
import { BusinessDetailsInput, TaxBreakdown } from '@solvapay/core';
|
|
3
|
+
|
|
1
4
|
interface components {
|
|
2
5
|
schemas: {
|
|
3
6
|
SdkMerchantResponseDto: {
|
|
@@ -243,6 +246,28 @@ interface components {
|
|
|
243
246
|
customerRef: string;
|
|
244
247
|
planRef?: string;
|
|
245
248
|
};
|
|
249
|
+
BusinessDetailsDto: {
|
|
250
|
+
/** Whether the purchase is on behalf of a business */
|
|
251
|
+
isBusiness: boolean;
|
|
252
|
+
/** Legal business name */
|
|
253
|
+
businessName?: string;
|
|
254
|
+
/** ISO 3166-1 alpha-2 country code */
|
|
255
|
+
country?: string;
|
|
256
|
+
/** Tax / VAT identification number */
|
|
257
|
+
taxId?: string;
|
|
258
|
+
};
|
|
259
|
+
TaxBreakdownResponse: {
|
|
260
|
+
subtotal: number;
|
|
261
|
+
taxAmount: number;
|
|
262
|
+
taxRate: number;
|
|
263
|
+
treatment: "reverse_charge" | "standard" | "none" | "not_collecting";
|
|
264
|
+
total: number;
|
|
265
|
+
currency: string;
|
|
266
|
+
inclusive: boolean;
|
|
267
|
+
};
|
|
268
|
+
AttachBusinessDetailsResponse: {
|
|
269
|
+
taxBreakdown: components["schemas"]["TaxBreakdownResponse"];
|
|
270
|
+
};
|
|
246
271
|
CreateCheckoutSessionResponse: {
|
|
247
272
|
/**
|
|
248
273
|
* Checkout session ID/token
|
|
@@ -403,6 +428,11 @@ interface components {
|
|
|
403
428
|
createdAt: string;
|
|
404
429
|
/** @description Last update timestamp */
|
|
405
430
|
updatedAt: string;
|
|
431
|
+
/**
|
|
432
|
+
* Tax inclusion behavior for business checkout
|
|
433
|
+
* @enum {string}
|
|
434
|
+
*/
|
|
435
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
406
436
|
};
|
|
407
437
|
CreatePlanRequest: {
|
|
408
438
|
name: string;
|
|
@@ -450,6 +480,8 @@ interface components {
|
|
|
450
480
|
maxActiveUsers?: number;
|
|
451
481
|
accessExpiryDays?: number;
|
|
452
482
|
default?: boolean;
|
|
483
|
+
/** @enum {string} */
|
|
484
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
453
485
|
};
|
|
454
486
|
UpdatePlanRequest: {
|
|
455
487
|
name?: string;
|
|
@@ -484,6 +516,8 @@ interface components {
|
|
|
484
516
|
[key: string]: unknown;
|
|
485
517
|
};
|
|
486
518
|
default?: boolean;
|
|
519
|
+
/** @enum {string} */
|
|
520
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
487
521
|
};
|
|
488
522
|
CreateProductRequest: {
|
|
489
523
|
name: string;
|
|
@@ -1673,6 +1707,51 @@ interface operations {
|
|
|
1673
1707
|
};
|
|
1674
1708
|
};
|
|
1675
1709
|
};
|
|
1710
|
+
PaymentIntentSdkController_attachBusinessDetails: {
|
|
1711
|
+
parameters: {
|
|
1712
|
+
query?: never;
|
|
1713
|
+
header?: never;
|
|
1714
|
+
path: {
|
|
1715
|
+
/** @description Stripe payment intent ID */
|
|
1716
|
+
processorPaymentId: string;
|
|
1717
|
+
};
|
|
1718
|
+
cookie?: never;
|
|
1719
|
+
};
|
|
1720
|
+
requestBody: {
|
|
1721
|
+
content: {
|
|
1722
|
+
"application/json": components["schemas"]["BusinessDetailsDto"];
|
|
1723
|
+
};
|
|
1724
|
+
};
|
|
1725
|
+
responses: {
|
|
1726
|
+
/** @description Tax breakdown after applying business details */
|
|
1727
|
+
200: {
|
|
1728
|
+
headers: {
|
|
1729
|
+
[name: string]: unknown;
|
|
1730
|
+
};
|
|
1731
|
+
content: {
|
|
1732
|
+
"application/json": components["schemas"]["AttachBusinessDetailsResponse"];
|
|
1733
|
+
};
|
|
1734
|
+
};
|
|
1735
|
+
/** @description Invalid business details or payment intent state */
|
|
1736
|
+
400: {
|
|
1737
|
+
headers: {
|
|
1738
|
+
[name: string]: unknown;
|
|
1739
|
+
};
|
|
1740
|
+
content: {
|
|
1741
|
+
"application/json": unknown;
|
|
1742
|
+
};
|
|
1743
|
+
};
|
|
1744
|
+
/** @description Payment intent not found */
|
|
1745
|
+
404: {
|
|
1746
|
+
headers: {
|
|
1747
|
+
[name: string]: unknown;
|
|
1748
|
+
};
|
|
1749
|
+
content: {
|
|
1750
|
+
"application/json": unknown;
|
|
1751
|
+
};
|
|
1752
|
+
};
|
|
1753
|
+
};
|
|
1754
|
+
};
|
|
1676
1755
|
CheckoutSessionSdkController_createCheckoutSession: {
|
|
1677
1756
|
parameters: {
|
|
1678
1757
|
query?: never;
|
|
@@ -2999,6 +3078,13 @@ type WebhookEvent = {
|
|
|
2999
3078
|
* Types related to the SolvaPay API client and backend communication.
|
|
3000
3079
|
*/
|
|
3001
3080
|
|
|
3081
|
+
type AttachBusinessDetailsParams = {
|
|
3082
|
+
paymentIntentId: string;
|
|
3083
|
+
customerRef?: string;
|
|
3084
|
+
} & BusinessDetailsInput;
|
|
3085
|
+
type AttachBusinessDetailsResult = {
|
|
3086
|
+
taxBreakdown: TaxBreakdown;
|
|
3087
|
+
};
|
|
3002
3088
|
type CheckLimitsRequest = components['schemas']['CheckLimitRequest'] & {
|
|
3003
3089
|
/**
|
|
3004
3090
|
* When `true`, the backend mints a checkout session (or customer
|
|
@@ -3381,6 +3467,7 @@ interface SolvaPayClient {
|
|
|
3381
3467
|
customerRef: string;
|
|
3382
3468
|
planRef?: string;
|
|
3383
3469
|
}): Promise<ProcessPaymentResult>;
|
|
3470
|
+
attachBusinessDetails?(params: AttachBusinessDetailsParams): Promise<AttachBusinessDetailsResult>;
|
|
3384
3471
|
getUserInfo?(params: {
|
|
3385
3472
|
customerRef: string;
|
|
3386
3473
|
productRef: string;
|
|
@@ -4174,6 +4261,21 @@ interface SolvaPay {
|
|
|
4174
4261
|
customerRef: string;
|
|
4175
4262
|
planRef?: string;
|
|
4176
4263
|
}): Promise<ProcessPaymentResult>;
|
|
4264
|
+
/**
|
|
4265
|
+
* Attach business purchase details to a payment intent
|
|
4266
|
+
* and retrieve the computed tax breakdown.
|
|
4267
|
+
*/
|
|
4268
|
+
attachBusinessDetails(params: {
|
|
4269
|
+
paymentIntentId: string;
|
|
4270
|
+
customerRef?: string;
|
|
4271
|
+
isBusiness: boolean;
|
|
4272
|
+
businessName?: string;
|
|
4273
|
+
country?: string;
|
|
4274
|
+
taxId?: string;
|
|
4275
|
+
taxIdType?: _solvapay_core.TaxIdType;
|
|
4276
|
+
}): Promise<{
|
|
4277
|
+
taxBreakdown: _solvapay_core.TaxBreakdown;
|
|
4278
|
+
}>;
|
|
4177
4279
|
/**
|
|
4178
4280
|
* Check if customer is within usage limits for a product.
|
|
4179
4281
|
*
|
|
@@ -5103,6 +5205,21 @@ declare function processPaymentIntentCore(request: Request, body: {
|
|
|
5103
5205
|
* }
|
|
5104
5206
|
* ```
|
|
5105
5207
|
*/
|
|
5208
|
+
/**
|
|
5209
|
+
* Attach business purchase details to a credit-topup payment intent and
|
|
5210
|
+
* retrieve the computed tax breakdown.
|
|
5211
|
+
*
|
|
5212
|
+
* Validates business fields client-side via `@solvapay/core` before
|
|
5213
|
+
* forwarding to the SolvaPay backend.
|
|
5214
|
+
*/
|
|
5215
|
+
declare function attachBusinessDetailsCore(request: Request, body: {
|
|
5216
|
+
paymentIntentId: string;
|
|
5217
|
+
customerRef?: string;
|
|
5218
|
+
} & BusinessDetailsInput, options?: {
|
|
5219
|
+
solvaPay?: SolvaPay;
|
|
5220
|
+
}): Promise<{
|
|
5221
|
+
taxBreakdown: TaxBreakdown;
|
|
5222
|
+
} | ErrorResult>;
|
|
5106
5223
|
declare function processTopupPaymentIntentCore(request: Request, body: {
|
|
5107
5224
|
paymentIntentId: string;
|
|
5108
5225
|
}, options?: {
|
|
@@ -5384,4 +5501,4 @@ declare function verifyWebhook({ body, signature, secret, }: {
|
|
|
5384
5501
|
secret: string;
|
|
5385
5502
|
}): Promise<WebhookEvent>;
|
|
5386
5503
|
|
|
5387
|
-
export { type ActivatePlanResult, type AuthenticatedUser, type ConfigureMcpPlansRequest, type ConfigureMcpPlansResponse, type CreateSolvaPayConfig, type CustomerBalanceResult, type CustomerResponseMapped, type CustomerWebhookObject, type ErrorResult, type GetUsageResult, type HttpAdapterOptions, type LimitActivationBalance, type LimitActivationProduct, type LimitPlanSummary, type LimitResponseWithPlan, type McpBootstrapPlanInput, type McpBootstrapRequest, type McpBootstrapResponse, type McpToolPlanMappingInput, type NextAdapterOptions, type OneTimePurchaseInfo, type PayableAllowResult, type PayableFunction, type PayableGateOptions, type PayableGateResult, type PayableOptions, type PayablePaywallResult, type PaymentMethodInfo, type PaywallArgs, type PaywallDecision, PaywallError, type PaywallMetadata, type PaywallState, type PaywallStructuredContent, type ProcessPaymentResult, type PurchaseCheckResult, type RetryOptions, type SdkMerchantResponse, type SdkProductResponse, type ServerClientOptions, type SolvaPay, type SolvaPayClient, type ToolPlanMappingInput, type TopupProcessResult, type WebhookEvent, type WebhookEventForType, type WebhookEventObjectMap, type WebhookEventType, type WebhookProduct, activatePlanCore, buildGateMessage, buildNudgeMessage, buildPaywallGate, cancelPurchaseCore, checkLimitsCore, checkPurchaseCore, classifyPaywallState, type components, createCheckoutSessionCore, createCustomerSessionCore, createPaymentIntentCore, createSolvaPay, createSolvaPayClient, createTopupPaymentIntentCore, disableAutoRechargeCore, getAuthenticatedUserCore, getAutoRechargeCore, getCustomerBalanceCore, getMerchantCore, getPaymentMethodCore, getProductCore, getUsageCore, handleRouteError, isErrorResult, isPaywallStructuredContent, listPlansCore, paywallErrorToClientPayload, processPaymentIntentCore, processTopupPaymentIntentCore, reactivatePurchaseCore, saveAutoRechargeCore, syncCustomerCore, trackUsageCore, verifyWebhook, withRetry };
|
|
5504
|
+
export { type ActivatePlanResult, type AuthenticatedUser, type ConfigureMcpPlansRequest, type ConfigureMcpPlansResponse, type CreateSolvaPayConfig, type CustomerBalanceResult, type CustomerResponseMapped, type CustomerWebhookObject, type ErrorResult, type GetUsageResult, type HttpAdapterOptions, type LimitActivationBalance, type LimitActivationProduct, type LimitPlanSummary, type LimitResponseWithPlan, type McpBootstrapPlanInput, type McpBootstrapRequest, type McpBootstrapResponse, type McpToolPlanMappingInput, type NextAdapterOptions, type OneTimePurchaseInfo, type PayableAllowResult, type PayableFunction, type PayableGateOptions, type PayableGateResult, type PayableOptions, type PayablePaywallResult, type PaymentMethodInfo, type PaywallArgs, type PaywallDecision, PaywallError, type PaywallMetadata, type PaywallState, type PaywallStructuredContent, type ProcessPaymentResult, type PurchaseCheckResult, type RetryOptions, type SdkMerchantResponse, type SdkProductResponse, type ServerClientOptions, type SolvaPay, type SolvaPayClient, type ToolPlanMappingInput, type TopupProcessResult, type WebhookEvent, type WebhookEventForType, type WebhookEventObjectMap, type WebhookEventType, type WebhookProduct, activatePlanCore, attachBusinessDetailsCore, buildGateMessage, buildNudgeMessage, buildPaywallGate, cancelPurchaseCore, checkLimitsCore, checkPurchaseCore, classifyPaywallState, type components, createCheckoutSessionCore, createCustomerSessionCore, createPaymentIntentCore, createSolvaPay, createSolvaPayClient, createTopupPaymentIntentCore, disableAutoRechargeCore, getAuthenticatedUserCore, getAutoRechargeCore, getCustomerBalanceCore, getMerchantCore, getPaymentMethodCore, getProductCore, getUsageCore, handleRouteError, isErrorResult, isPaywallStructuredContent, listPlansCore, paywallErrorToClientPayload, processPaymentIntentCore, processTopupPaymentIntentCore, reactivatePurchaseCore, saveAutoRechargeCore, syncCustomerCore, trackUsageCore, verifyWebhook, withRetry };
|
package/dist/edge.js
CHANGED
|
@@ -489,6 +489,31 @@ function createSolvaPayClient(opts) {
|
|
|
489
489
|
const result = await res.json();
|
|
490
490
|
return result;
|
|
491
491
|
},
|
|
492
|
+
// POST: /v1/sdk/payment-intents/{paymentIntentId}/business-details
|
|
493
|
+
async attachBusinessDetails(params) {
|
|
494
|
+
const url = `${base}/v1/sdk/payment-intents/${params.paymentIntentId}/business-details`;
|
|
495
|
+
const res = await fetch(url, {
|
|
496
|
+
method: "POST",
|
|
497
|
+
headers,
|
|
498
|
+
body: JSON.stringify({
|
|
499
|
+
isBusiness: params.isBusiness,
|
|
500
|
+
...params.businessName !== void 0 && { businessName: params.businessName },
|
|
501
|
+
...params.country !== void 0 && { country: params.country },
|
|
502
|
+
...params.taxId !== void 0 && { taxId: params.taxId },
|
|
503
|
+
...params.taxIdType !== void 0 && { taxIdType: params.taxIdType },
|
|
504
|
+
...params.customerRef !== void 0 && { customerRef: params.customerRef }
|
|
505
|
+
})
|
|
506
|
+
});
|
|
507
|
+
if (!res.ok) {
|
|
508
|
+
const error = await res.text();
|
|
509
|
+
log(`\u274C API Error: ${res.status} - ${error}`);
|
|
510
|
+
throw new SolvaPayError(
|
|
511
|
+
`Attach business details failed (${res.status}): ${error}`,
|
|
512
|
+
{ status: res.status }
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
return await res.json();
|
|
516
|
+
},
|
|
492
517
|
// POST: /v1/sdk/purchases/{purchaseRef}/cancel
|
|
493
518
|
async cancelPurchase(params) {
|
|
494
519
|
const url = `${base}/v1/sdk/purchases/${params.purchaseRef}/cancel`;
|
|
@@ -2011,6 +2036,14 @@ function createSolvaPay(config) {
|
|
|
2011
2036
|
}
|
|
2012
2037
|
return apiClient.processPaymentIntent(params);
|
|
2013
2038
|
},
|
|
2039
|
+
attachBusinessDetails(params) {
|
|
2040
|
+
if (!apiClient.attachBusinessDetails) {
|
|
2041
|
+
throw new SolvaPayError2(
|
|
2042
|
+
"attachBusinessDetails is not available on this API client"
|
|
2043
|
+
);
|
|
2044
|
+
}
|
|
2045
|
+
return apiClient.attachBusinessDetails(params);
|
|
2046
|
+
},
|
|
2014
2047
|
checkLimits(params) {
|
|
2015
2048
|
return apiClient.checkLimits(params);
|
|
2016
2049
|
},
|
|
@@ -2412,6 +2445,11 @@ async function getCustomerBalanceCore(request, options = {}) {
|
|
|
2412
2445
|
}
|
|
2413
2446
|
}
|
|
2414
2447
|
|
|
2448
|
+
// src/helpers/payment.ts
|
|
2449
|
+
import {
|
|
2450
|
+
validateBusinessDetails
|
|
2451
|
+
} from "@solvapay/core";
|
|
2452
|
+
|
|
2415
2453
|
// src/helpers/balance-poll.ts
|
|
2416
2454
|
var TOPUP_BALANCE_POLL_DELAYS_MS = [500, 1e3, 2e3, 4e3];
|
|
2417
2455
|
var BALANCE_RECONCILE_DELAYS_MS = [500, 1e3, 2e3, 4e3, 8e3, 16e3];
|
|
@@ -2544,6 +2582,50 @@ async function processPaymentIntentCore(request, body, options = {}) {
|
|
|
2544
2582
|
return handleRouteError(error, "Process payment intent", "Payment processing failed");
|
|
2545
2583
|
}
|
|
2546
2584
|
}
|
|
2585
|
+
async function attachBusinessDetailsCore(request, body, options = {}) {
|
|
2586
|
+
try {
|
|
2587
|
+
if (!body.paymentIntentId) {
|
|
2588
|
+
return {
|
|
2589
|
+
error: "paymentIntentId is required",
|
|
2590
|
+
status: 400
|
|
2591
|
+
};
|
|
2592
|
+
}
|
|
2593
|
+
const validation = validateBusinessDetails({
|
|
2594
|
+
isBusiness: body.isBusiness,
|
|
2595
|
+
businessName: body.businessName,
|
|
2596
|
+
country: body.country,
|
|
2597
|
+
taxId: body.taxId,
|
|
2598
|
+
taxIdType: body.taxIdType
|
|
2599
|
+
});
|
|
2600
|
+
if (!validation.success) {
|
|
2601
|
+
const firstIssue = validation.error.issues[0];
|
|
2602
|
+
return {
|
|
2603
|
+
error: firstIssue?.message ?? "Invalid business details",
|
|
2604
|
+
status: 400
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
const solvaPay = options.solvaPay || createSolvaPay();
|
|
2608
|
+
if (typeof solvaPay.attachBusinessDetails !== "function") {
|
|
2609
|
+
return {
|
|
2610
|
+
error: "attachBusinessDetails is not available on this SolvaPay client",
|
|
2611
|
+
status: 501
|
|
2612
|
+
};
|
|
2613
|
+
}
|
|
2614
|
+
const details = validation.data;
|
|
2615
|
+
const result = await solvaPay.attachBusinessDetails({
|
|
2616
|
+
paymentIntentId: body.paymentIntentId,
|
|
2617
|
+
...body.customerRef !== void 0 && { customerRef: body.customerRef },
|
|
2618
|
+
...details
|
|
2619
|
+
});
|
|
2620
|
+
return result;
|
|
2621
|
+
} catch (error) {
|
|
2622
|
+
return handleRouteError(
|
|
2623
|
+
error,
|
|
2624
|
+
"Attach business details",
|
|
2625
|
+
"Failed to attach business details"
|
|
2626
|
+
);
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2547
2629
|
async function processTopupPaymentIntentCore(request, body, options = {}) {
|
|
2548
2630
|
try {
|
|
2549
2631
|
if (!body.paymentIntentId) {
|
|
@@ -3224,6 +3306,7 @@ async function verifyWebhook({
|
|
|
3224
3306
|
export {
|
|
3225
3307
|
PaywallError,
|
|
3226
3308
|
activatePlanCore,
|
|
3309
|
+
attachBusinessDetailsCore,
|
|
3227
3310
|
buildGateMessage,
|
|
3228
3311
|
buildNudgeMessage,
|
|
3229
3312
|
buildPaywallGate,
|
package/dist/fetch/index.cjs
CHANGED
|
@@ -693,6 +693,31 @@ function createSolvaPayClient(opts) {
|
|
|
693
693
|
const result = await res.json();
|
|
694
694
|
return result;
|
|
695
695
|
},
|
|
696
|
+
// POST: /v1/sdk/payment-intents/{paymentIntentId}/business-details
|
|
697
|
+
async attachBusinessDetails(params) {
|
|
698
|
+
const url = `${base}/v1/sdk/payment-intents/${params.paymentIntentId}/business-details`;
|
|
699
|
+
const res = await fetch(url, {
|
|
700
|
+
method: "POST",
|
|
701
|
+
headers,
|
|
702
|
+
body: JSON.stringify({
|
|
703
|
+
isBusiness: params.isBusiness,
|
|
704
|
+
...params.businessName !== void 0 && { businessName: params.businessName },
|
|
705
|
+
...params.country !== void 0 && { country: params.country },
|
|
706
|
+
...params.taxId !== void 0 && { taxId: params.taxId },
|
|
707
|
+
...params.taxIdType !== void 0 && { taxIdType: params.taxIdType },
|
|
708
|
+
...params.customerRef !== void 0 && { customerRef: params.customerRef }
|
|
709
|
+
})
|
|
710
|
+
});
|
|
711
|
+
if (!res.ok) {
|
|
712
|
+
const error = await res.text();
|
|
713
|
+
log(`\u274C API Error: ${res.status} - ${error}`);
|
|
714
|
+
throw new import_core2.SolvaPayError(
|
|
715
|
+
`Attach business details failed (${res.status}): ${error}`,
|
|
716
|
+
{ status: res.status }
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
return await res.json();
|
|
720
|
+
},
|
|
696
721
|
// POST: /v1/sdk/purchases/{purchaseRef}/cancel
|
|
697
722
|
async cancelPurchase(params) {
|
|
698
723
|
const url = `${base}/v1/sdk/purchases/${params.purchaseRef}/cancel`;
|
|
@@ -2201,6 +2226,14 @@ function createSolvaPay(config) {
|
|
|
2201
2226
|
}
|
|
2202
2227
|
return apiClient.processPaymentIntent(params);
|
|
2203
2228
|
},
|
|
2229
|
+
attachBusinessDetails(params) {
|
|
2230
|
+
if (!apiClient.attachBusinessDetails) {
|
|
2231
|
+
throw new import_core3.SolvaPayError(
|
|
2232
|
+
"attachBusinessDetails is not available on this API client"
|
|
2233
|
+
);
|
|
2234
|
+
}
|
|
2235
|
+
return apiClient.attachBusinessDetails(params);
|
|
2236
|
+
},
|
|
2204
2237
|
checkLimits(params) {
|
|
2205
2238
|
return apiClient.checkLimits(params);
|
|
2206
2239
|
},
|
|
@@ -2440,6 +2473,7 @@ async function getCustomerBalanceCore(request, options = {}) {
|
|
|
2440
2473
|
}
|
|
2441
2474
|
|
|
2442
2475
|
// src/helpers/payment.ts
|
|
2476
|
+
var import_core4 = require("@solvapay/core");
|
|
2443
2477
|
async function createPaymentIntentCore(request, body, options = {}) {
|
|
2444
2478
|
try {
|
|
2445
2479
|
if (!body.planRef || !body.productRef) {
|
|
@@ -2618,7 +2652,7 @@ async function createCustomerSessionCore(request, options = {}) {
|
|
|
2618
2652
|
}
|
|
2619
2653
|
|
|
2620
2654
|
// src/helpers/renewal.ts
|
|
2621
|
-
var
|
|
2655
|
+
var import_core5 = require("@solvapay/core");
|
|
2622
2656
|
async function cancelPurchaseCore(request, body, options = {}) {
|
|
2623
2657
|
try {
|
|
2624
2658
|
if (!body.purchaseRef) {
|
|
@@ -2664,7 +2698,7 @@ async function cancelPurchaseCore(request, body, options = {}) {
|
|
|
2664
2698
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
2665
2699
|
return cancelledPurchase;
|
|
2666
2700
|
} catch (error) {
|
|
2667
|
-
if (error instanceof
|
|
2701
|
+
if (error instanceof import_core5.SolvaPayError) {
|
|
2668
2702
|
const errorMessage = error.message;
|
|
2669
2703
|
if (errorMessage.includes("not found")) {
|
|
2670
2704
|
return {
|
|
@@ -2732,7 +2766,7 @@ async function reactivatePurchaseCore(request, body, options = {}) {
|
|
|
2732
2766
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
2733
2767
|
return reactivatedPurchase;
|
|
2734
2768
|
} catch (error) {
|
|
2735
|
-
if (error instanceof
|
|
2769
|
+
if (error instanceof import_core5.SolvaPayError) {
|
|
2736
2770
|
const errorMessage = error.message;
|
|
2737
2771
|
if (errorMessage.includes("not found")) {
|
|
2738
2772
|
return {
|
|
@@ -2813,7 +2847,7 @@ async function getPaymentMethodCore(request, options = {}) {
|
|
|
2813
2847
|
}
|
|
2814
2848
|
|
|
2815
2849
|
// src/helpers/plans.ts
|
|
2816
|
-
var
|
|
2850
|
+
var import_core6 = require("@solvapay/core");
|
|
2817
2851
|
async function listPlansCore(request, options = {}) {
|
|
2818
2852
|
try {
|
|
2819
2853
|
const url = new URL(request.url);
|
|
@@ -2825,7 +2859,7 @@ async function listPlansCore(request, options = {}) {
|
|
|
2825
2859
|
};
|
|
2826
2860
|
}
|
|
2827
2861
|
const apiClient = options.solvaPay?.apiClient ?? (() => {
|
|
2828
|
-
const config = (0,
|
|
2862
|
+
const config = (0, import_core6.getSolvaPayConfig)();
|
|
2829
2863
|
if (!config.apiKey) return null;
|
|
2830
2864
|
return createSolvaPayClient({
|
|
2831
2865
|
apiKey: config.apiKey,
|
|
@@ -2855,11 +2889,11 @@ async function listPlansCore(request, options = {}) {
|
|
|
2855
2889
|
}
|
|
2856
2890
|
|
|
2857
2891
|
// src/helpers/merchant.ts
|
|
2858
|
-
var
|
|
2892
|
+
var import_core7 = require("@solvapay/core");
|
|
2859
2893
|
async function getMerchantCore(_request, options = {}) {
|
|
2860
2894
|
try {
|
|
2861
2895
|
const apiClient = options.solvaPay?.apiClient ?? (() => {
|
|
2862
|
-
const config = (0,
|
|
2896
|
+
const config = (0, import_core7.getSolvaPayConfig)();
|
|
2863
2897
|
if (!config.apiKey) return null;
|
|
2864
2898
|
return createSolvaPayClient({
|
|
2865
2899
|
apiKey: config.apiKey,
|
|
@@ -2886,7 +2920,7 @@ async function getMerchantCore(_request, options = {}) {
|
|
|
2886
2920
|
}
|
|
2887
2921
|
|
|
2888
2922
|
// src/helpers/product.ts
|
|
2889
|
-
var
|
|
2923
|
+
var import_core8 = require("@solvapay/core");
|
|
2890
2924
|
async function getProductCore(request, options = {}) {
|
|
2891
2925
|
try {
|
|
2892
2926
|
const url = new URL(request.url);
|
|
@@ -2898,7 +2932,7 @@ async function getProductCore(request, options = {}) {
|
|
|
2898
2932
|
};
|
|
2899
2933
|
}
|
|
2900
2934
|
const apiClient = options.solvaPay?.apiClient ?? (() => {
|
|
2901
|
-
const config = (0,
|
|
2935
|
+
const config = (0, import_core8.getSolvaPayConfig)();
|
|
2902
2936
|
if (!config.apiKey) return null;
|
|
2903
2937
|
return createSolvaPayClient({
|
|
2904
2938
|
apiKey: config.apiKey,
|
|
@@ -3009,7 +3043,7 @@ async function trackUsageCore(request, body, options = {}) {
|
|
|
3009
3043
|
}
|
|
3010
3044
|
|
|
3011
3045
|
// src/edge.ts
|
|
3012
|
-
var
|
|
3046
|
+
var import_core9 = require("@solvapay/core");
|
|
3013
3047
|
function timingSafeEqual(a, b) {
|
|
3014
3048
|
if (a.length !== b.length) return false;
|
|
3015
3049
|
let mismatch = 0;
|
|
@@ -3024,22 +3058,22 @@ async function verifyWebhook({
|
|
|
3024
3058
|
secret
|
|
3025
3059
|
}) {
|
|
3026
3060
|
const toleranceSec = 300;
|
|
3027
|
-
if (!signature) throw new
|
|
3061
|
+
if (!signature) throw new import_core9.SolvaPayError("Missing webhook signature");
|
|
3028
3062
|
const parts = signature.split(",");
|
|
3029
3063
|
const tPart = parts.find((p) => p.startsWith("t="));
|
|
3030
3064
|
const v1Part = parts.find((p) => p.startsWith("v1="));
|
|
3031
3065
|
if (!tPart || !v1Part) {
|
|
3032
|
-
throw new
|
|
3066
|
+
throw new import_core9.SolvaPayError("Malformed webhook signature");
|
|
3033
3067
|
}
|
|
3034
3068
|
const timestamp = parseInt(tPart.slice(2), 10);
|
|
3035
3069
|
const receivedHmac = v1Part.slice(3);
|
|
3036
3070
|
if (Number.isNaN(timestamp) || !receivedHmac) {
|
|
3037
|
-
throw new
|
|
3071
|
+
throw new import_core9.SolvaPayError("Malformed webhook signature");
|
|
3038
3072
|
}
|
|
3039
3073
|
if (toleranceSec > 0) {
|
|
3040
3074
|
const age = Math.abs(Math.floor(Date.now() / 1e3) - timestamp);
|
|
3041
3075
|
if (age > toleranceSec) {
|
|
3042
|
-
throw new
|
|
3076
|
+
throw new import_core9.SolvaPayError("Webhook signature timestamp too old");
|
|
3043
3077
|
}
|
|
3044
3078
|
}
|
|
3045
3079
|
const enc = new TextEncoder();
|
|
@@ -3053,12 +3087,12 @@ async function verifyWebhook({
|
|
|
3053
3087
|
const sigBuf = await crypto.subtle.sign("HMAC", key, enc.encode(`${timestamp}.${body}`));
|
|
3054
3088
|
const expectedHmac = Array.from(new Uint8Array(sigBuf)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3055
3089
|
if (!timingSafeEqual(expectedHmac, receivedHmac)) {
|
|
3056
|
-
throw new
|
|
3090
|
+
throw new import_core9.SolvaPayError("Invalid webhook signature");
|
|
3057
3091
|
}
|
|
3058
3092
|
try {
|
|
3059
3093
|
return JSON.parse(body);
|
|
3060
3094
|
} catch {
|
|
3061
|
-
throw new
|
|
3095
|
+
throw new import_core9.SolvaPayError("Invalid webhook payload: body is not valid JSON");
|
|
3062
3096
|
}
|
|
3063
3097
|
}
|
|
3064
3098
|
|
package/dist/fetch/index.d.cts
CHANGED
|
@@ -243,6 +243,28 @@ interface components {
|
|
|
243
243
|
customerRef: string;
|
|
244
244
|
planRef?: string;
|
|
245
245
|
};
|
|
246
|
+
BusinessDetailsDto: {
|
|
247
|
+
/** Whether the purchase is on behalf of a business */
|
|
248
|
+
isBusiness: boolean;
|
|
249
|
+
/** Legal business name */
|
|
250
|
+
businessName?: string;
|
|
251
|
+
/** ISO 3166-1 alpha-2 country code */
|
|
252
|
+
country?: string;
|
|
253
|
+
/** Tax / VAT identification number */
|
|
254
|
+
taxId?: string;
|
|
255
|
+
};
|
|
256
|
+
TaxBreakdownResponse: {
|
|
257
|
+
subtotal: number;
|
|
258
|
+
taxAmount: number;
|
|
259
|
+
taxRate: number;
|
|
260
|
+
treatment: "reverse_charge" | "standard" | "none" | "not_collecting";
|
|
261
|
+
total: number;
|
|
262
|
+
currency: string;
|
|
263
|
+
inclusive: boolean;
|
|
264
|
+
};
|
|
265
|
+
AttachBusinessDetailsResponse: {
|
|
266
|
+
taxBreakdown: components["schemas"]["TaxBreakdownResponse"];
|
|
267
|
+
};
|
|
246
268
|
CreateCheckoutSessionResponse: {
|
|
247
269
|
/**
|
|
248
270
|
* Checkout session ID/token
|
|
@@ -403,6 +425,11 @@ interface components {
|
|
|
403
425
|
createdAt: string;
|
|
404
426
|
/** @description Last update timestamp */
|
|
405
427
|
updatedAt: string;
|
|
428
|
+
/**
|
|
429
|
+
* Tax inclusion behavior for business checkout
|
|
430
|
+
* @enum {string}
|
|
431
|
+
*/
|
|
432
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
406
433
|
};
|
|
407
434
|
CreatePlanRequest: {
|
|
408
435
|
name: string;
|
|
@@ -450,6 +477,8 @@ interface components {
|
|
|
450
477
|
maxActiveUsers?: number;
|
|
451
478
|
accessExpiryDays?: number;
|
|
452
479
|
default?: boolean;
|
|
480
|
+
/** @enum {string} */
|
|
481
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
453
482
|
};
|
|
454
483
|
UpdatePlanRequest: {
|
|
455
484
|
name?: string;
|
|
@@ -484,6 +513,8 @@ interface components {
|
|
|
484
513
|
[key: string]: unknown;
|
|
485
514
|
};
|
|
486
515
|
default?: boolean;
|
|
516
|
+
/** @enum {string} */
|
|
517
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
487
518
|
};
|
|
488
519
|
CreateProductRequest: {
|
|
489
520
|
name: string;
|
package/dist/fetch/index.d.ts
CHANGED
|
@@ -243,6 +243,28 @@ interface components {
|
|
|
243
243
|
customerRef: string;
|
|
244
244
|
planRef?: string;
|
|
245
245
|
};
|
|
246
|
+
BusinessDetailsDto: {
|
|
247
|
+
/** Whether the purchase is on behalf of a business */
|
|
248
|
+
isBusiness: boolean;
|
|
249
|
+
/** Legal business name */
|
|
250
|
+
businessName?: string;
|
|
251
|
+
/** ISO 3166-1 alpha-2 country code */
|
|
252
|
+
country?: string;
|
|
253
|
+
/** Tax / VAT identification number */
|
|
254
|
+
taxId?: string;
|
|
255
|
+
};
|
|
256
|
+
TaxBreakdownResponse: {
|
|
257
|
+
subtotal: number;
|
|
258
|
+
taxAmount: number;
|
|
259
|
+
taxRate: number;
|
|
260
|
+
treatment: "reverse_charge" | "standard" | "none" | "not_collecting";
|
|
261
|
+
total: number;
|
|
262
|
+
currency: string;
|
|
263
|
+
inclusive: boolean;
|
|
264
|
+
};
|
|
265
|
+
AttachBusinessDetailsResponse: {
|
|
266
|
+
taxBreakdown: components["schemas"]["TaxBreakdownResponse"];
|
|
267
|
+
};
|
|
246
268
|
CreateCheckoutSessionResponse: {
|
|
247
269
|
/**
|
|
248
270
|
* Checkout session ID/token
|
|
@@ -403,6 +425,11 @@ interface components {
|
|
|
403
425
|
createdAt: string;
|
|
404
426
|
/** @description Last update timestamp */
|
|
405
427
|
updatedAt: string;
|
|
428
|
+
/**
|
|
429
|
+
* Tax inclusion behavior for business checkout
|
|
430
|
+
* @enum {string}
|
|
431
|
+
*/
|
|
432
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
406
433
|
};
|
|
407
434
|
CreatePlanRequest: {
|
|
408
435
|
name: string;
|
|
@@ -450,6 +477,8 @@ interface components {
|
|
|
450
477
|
maxActiveUsers?: number;
|
|
451
478
|
accessExpiryDays?: number;
|
|
452
479
|
default?: boolean;
|
|
480
|
+
/** @enum {string} */
|
|
481
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
453
482
|
};
|
|
454
483
|
UpdatePlanRequest: {
|
|
455
484
|
name?: string;
|
|
@@ -484,6 +513,8 @@ interface components {
|
|
|
484
513
|
[key: string]: unknown;
|
|
485
514
|
};
|
|
486
515
|
default?: boolean;
|
|
516
|
+
/** @enum {string} */
|
|
517
|
+
taxBehavior?: "auto" | "inclusive" | "exclusive";
|
|
487
518
|
};
|
|
488
519
|
CreateProductRequest: {
|
|
489
520
|
name: string;
|
package/dist/fetch/index.js
CHANGED
|
@@ -640,6 +640,31 @@ function createSolvaPayClient(opts) {
|
|
|
640
640
|
const result = await res.json();
|
|
641
641
|
return result;
|
|
642
642
|
},
|
|
643
|
+
// POST: /v1/sdk/payment-intents/{paymentIntentId}/business-details
|
|
644
|
+
async attachBusinessDetails(params) {
|
|
645
|
+
const url = `${base}/v1/sdk/payment-intents/${params.paymentIntentId}/business-details`;
|
|
646
|
+
const res = await fetch(url, {
|
|
647
|
+
method: "POST",
|
|
648
|
+
headers,
|
|
649
|
+
body: JSON.stringify({
|
|
650
|
+
isBusiness: params.isBusiness,
|
|
651
|
+
...params.businessName !== void 0 && { businessName: params.businessName },
|
|
652
|
+
...params.country !== void 0 && { country: params.country },
|
|
653
|
+
...params.taxId !== void 0 && { taxId: params.taxId },
|
|
654
|
+
...params.taxIdType !== void 0 && { taxIdType: params.taxIdType },
|
|
655
|
+
...params.customerRef !== void 0 && { customerRef: params.customerRef }
|
|
656
|
+
})
|
|
657
|
+
});
|
|
658
|
+
if (!res.ok) {
|
|
659
|
+
const error = await res.text();
|
|
660
|
+
log(`\u274C API Error: ${res.status} - ${error}`);
|
|
661
|
+
throw new SolvaPayError2(
|
|
662
|
+
`Attach business details failed (${res.status}): ${error}`,
|
|
663
|
+
{ status: res.status }
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
return await res.json();
|
|
667
|
+
},
|
|
643
668
|
// POST: /v1/sdk/purchases/{purchaseRef}/cancel
|
|
644
669
|
async cancelPurchase(params) {
|
|
645
670
|
const url = `${base}/v1/sdk/purchases/${params.purchaseRef}/cancel`;
|
|
@@ -2148,6 +2173,14 @@ function createSolvaPay(config) {
|
|
|
2148
2173
|
}
|
|
2149
2174
|
return apiClient.processPaymentIntent(params);
|
|
2150
2175
|
},
|
|
2176
|
+
attachBusinessDetails(params) {
|
|
2177
|
+
if (!apiClient.attachBusinessDetails) {
|
|
2178
|
+
throw new SolvaPayError3(
|
|
2179
|
+
"attachBusinessDetails is not available on this API client"
|
|
2180
|
+
);
|
|
2181
|
+
}
|
|
2182
|
+
return apiClient.attachBusinessDetails(params);
|
|
2183
|
+
},
|
|
2151
2184
|
checkLimits(params) {
|
|
2152
2185
|
return apiClient.checkLimits(params);
|
|
2153
2186
|
},
|
|
@@ -2387,6 +2420,9 @@ async function getCustomerBalanceCore(request, options = {}) {
|
|
|
2387
2420
|
}
|
|
2388
2421
|
|
|
2389
2422
|
// src/helpers/payment.ts
|
|
2423
|
+
import {
|
|
2424
|
+
validateBusinessDetails
|
|
2425
|
+
} from "@solvapay/core";
|
|
2390
2426
|
async function createPaymentIntentCore(request, body, options = {}) {
|
|
2391
2427
|
try {
|
|
2392
2428
|
if (!body.planRef || !body.productRef) {
|