@bcc-code/payment-client 1.0.1
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/README.md +51 -0
- package/dist/index.d.mts +109 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +112 -0
- package/dist/index.mjs +85 -0
- package/package.json +35 -0
- package/src/client/PaymentClient.ts +117 -0
- package/src/client/PaymentClientOptions.ts +10 -0
- package/src/client/index.ts +6 -0
- package/src/index.ts +7 -0
- package/src/types/index.ts +5 -0
- package/src/types/payment.ts +99 -0
- package/tsconfig.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# @bcc-code/payment-client
|
|
2
|
+
|
|
3
|
+
Client SDK for BCC Payment Orchestrator API
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @bcc-code/payment-client
|
|
9
|
+
# or
|
|
10
|
+
npm install @bcc-code/payment-client
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { PaymentClient } from '@bcc-code/payment-client'
|
|
17
|
+
|
|
18
|
+
const client = new PaymentClient({
|
|
19
|
+
baseUrl: 'http://localhost:3200',
|
|
20
|
+
tenantId: 'your-tenant-uuid',
|
|
21
|
+
getAuthToken: async () => {
|
|
22
|
+
// Implement your BCC Auth0 token retrieval
|
|
23
|
+
return await getBccAuthToken()
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Create a payment
|
|
28
|
+
const payment = await client.createPayment({
|
|
29
|
+
amount: 99.99,
|
|
30
|
+
currency: 'EUR',
|
|
31
|
+
paymentMethodType: 'stripe',
|
|
32
|
+
returnUrl: 'https://yourapp.com/success',
|
|
33
|
+
lineItems: [
|
|
34
|
+
{
|
|
35
|
+
name: 'Product Name',
|
|
36
|
+
unitPrice: 99.99,
|
|
37
|
+
quantity: 1
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Get payment status
|
|
43
|
+
const status = await client.getPayment(payment.paymentId)
|
|
44
|
+
|
|
45
|
+
// Get receipt
|
|
46
|
+
const receipt = await client.getReceipt(payment.paymentId)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
interface CreatePaymentRequest {
|
|
2
|
+
payerId?: string;
|
|
3
|
+
amount: number;
|
|
4
|
+
currency: string;
|
|
5
|
+
countryCode?: string;
|
|
6
|
+
paymentMethodType: string;
|
|
7
|
+
merchantReference?: string;
|
|
8
|
+
returnUrl: string;
|
|
9
|
+
paymentMethodDetails?: Record<string, any>;
|
|
10
|
+
person?: PersonInfoRequest;
|
|
11
|
+
lineItems?: LineItemRequest[];
|
|
12
|
+
}
|
|
13
|
+
interface PersonInfoRequest {
|
|
14
|
+
payerUid: string;
|
|
15
|
+
firstName?: string;
|
|
16
|
+
lastName?: string;
|
|
17
|
+
email?: string;
|
|
18
|
+
addressLine1?: string;
|
|
19
|
+
addressLine2?: string;
|
|
20
|
+
city?: string;
|
|
21
|
+
postalCode?: string;
|
|
22
|
+
country?: string;
|
|
23
|
+
}
|
|
24
|
+
interface LineItemRequest {
|
|
25
|
+
name: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
unitPrice: number;
|
|
28
|
+
quantity: number;
|
|
29
|
+
taxPercentage?: number;
|
|
30
|
+
taxAmount?: number;
|
|
31
|
+
discountAmount?: number;
|
|
32
|
+
discountPercentage?: number;
|
|
33
|
+
productCode?: string;
|
|
34
|
+
category?: string;
|
|
35
|
+
}
|
|
36
|
+
interface CreatePaymentResponse {
|
|
37
|
+
paymentId: string;
|
|
38
|
+
clientData?: string;
|
|
39
|
+
clientKey?: string;
|
|
40
|
+
}
|
|
41
|
+
interface PaymentResponse {
|
|
42
|
+
uid: string;
|
|
43
|
+
amount: number;
|
|
44
|
+
currency: string;
|
|
45
|
+
status: string;
|
|
46
|
+
payerUid: string;
|
|
47
|
+
orgId: string;
|
|
48
|
+
createdAt: string;
|
|
49
|
+
updatedAt: string;
|
|
50
|
+
lineItems?: LineItemResponse[];
|
|
51
|
+
}
|
|
52
|
+
interface LineItemResponse {
|
|
53
|
+
id: string;
|
|
54
|
+
productId: string;
|
|
55
|
+
name: string;
|
|
56
|
+
description?: string;
|
|
57
|
+
unitPrice: number;
|
|
58
|
+
quantity: number;
|
|
59
|
+
taxPercentage?: number;
|
|
60
|
+
taxAmount?: number;
|
|
61
|
+
discountAmount?: number;
|
|
62
|
+
discountPercentage?: number;
|
|
63
|
+
productCode?: string;
|
|
64
|
+
category?: string;
|
|
65
|
+
createdAt: string;
|
|
66
|
+
updatedAt: string;
|
|
67
|
+
subtotal: number;
|
|
68
|
+
totalTaxAmount: number;
|
|
69
|
+
totalDiscountAmount: number;
|
|
70
|
+
total: number;
|
|
71
|
+
}
|
|
72
|
+
interface PaymentReceiptResponse {
|
|
73
|
+
uid: string;
|
|
74
|
+
amount: number;
|
|
75
|
+
currency: string;
|
|
76
|
+
status: string;
|
|
77
|
+
payerId?: string;
|
|
78
|
+
createdAt: string;
|
|
79
|
+
updatedAt: string;
|
|
80
|
+
lineItems?: LineItemResponse[];
|
|
81
|
+
merchantName?: string;
|
|
82
|
+
merchantContact?: string;
|
|
83
|
+
pspReference?: string;
|
|
84
|
+
buyerName?: string;
|
|
85
|
+
buyerEmail?: string;
|
|
86
|
+
taxAmount?: number;
|
|
87
|
+
discountAmount?: number;
|
|
88
|
+
amountFormatted?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
interface PaymentClientOptions {
|
|
92
|
+
baseUrl: string;
|
|
93
|
+
tenantId: string;
|
|
94
|
+
getAuthToken: () => Promise<string>;
|
|
95
|
+
timeout?: number;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
declare class PaymentClient {
|
|
99
|
+
private baseUrl;
|
|
100
|
+
private tenantId;
|
|
101
|
+
private getAuthToken;
|
|
102
|
+
private timeout?;
|
|
103
|
+
constructor(options: PaymentClientOptions);
|
|
104
|
+
createPayment(request: CreatePaymentRequest): Promise<CreatePaymentResponse>;
|
|
105
|
+
getPayment(paymentId: string): Promise<PaymentResponse | null>;
|
|
106
|
+
getReceipt(paymentId: string): Promise<PaymentReceiptResponse | null>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export { type CreatePaymentRequest, type CreatePaymentResponse, type LineItemRequest, type LineItemResponse, PaymentClient, type PaymentClientOptions, type PaymentReceiptResponse, type PaymentResponse, type PersonInfoRequest };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
interface CreatePaymentRequest {
|
|
2
|
+
payerId?: string;
|
|
3
|
+
amount: number;
|
|
4
|
+
currency: string;
|
|
5
|
+
countryCode?: string;
|
|
6
|
+
paymentMethodType: string;
|
|
7
|
+
merchantReference?: string;
|
|
8
|
+
returnUrl: string;
|
|
9
|
+
paymentMethodDetails?: Record<string, any>;
|
|
10
|
+
person?: PersonInfoRequest;
|
|
11
|
+
lineItems?: LineItemRequest[];
|
|
12
|
+
}
|
|
13
|
+
interface PersonInfoRequest {
|
|
14
|
+
payerUid: string;
|
|
15
|
+
firstName?: string;
|
|
16
|
+
lastName?: string;
|
|
17
|
+
email?: string;
|
|
18
|
+
addressLine1?: string;
|
|
19
|
+
addressLine2?: string;
|
|
20
|
+
city?: string;
|
|
21
|
+
postalCode?: string;
|
|
22
|
+
country?: string;
|
|
23
|
+
}
|
|
24
|
+
interface LineItemRequest {
|
|
25
|
+
name: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
unitPrice: number;
|
|
28
|
+
quantity: number;
|
|
29
|
+
taxPercentage?: number;
|
|
30
|
+
taxAmount?: number;
|
|
31
|
+
discountAmount?: number;
|
|
32
|
+
discountPercentage?: number;
|
|
33
|
+
productCode?: string;
|
|
34
|
+
category?: string;
|
|
35
|
+
}
|
|
36
|
+
interface CreatePaymentResponse {
|
|
37
|
+
paymentId: string;
|
|
38
|
+
clientData?: string;
|
|
39
|
+
clientKey?: string;
|
|
40
|
+
}
|
|
41
|
+
interface PaymentResponse {
|
|
42
|
+
uid: string;
|
|
43
|
+
amount: number;
|
|
44
|
+
currency: string;
|
|
45
|
+
status: string;
|
|
46
|
+
payerUid: string;
|
|
47
|
+
orgId: string;
|
|
48
|
+
createdAt: string;
|
|
49
|
+
updatedAt: string;
|
|
50
|
+
lineItems?: LineItemResponse[];
|
|
51
|
+
}
|
|
52
|
+
interface LineItemResponse {
|
|
53
|
+
id: string;
|
|
54
|
+
productId: string;
|
|
55
|
+
name: string;
|
|
56
|
+
description?: string;
|
|
57
|
+
unitPrice: number;
|
|
58
|
+
quantity: number;
|
|
59
|
+
taxPercentage?: number;
|
|
60
|
+
taxAmount?: number;
|
|
61
|
+
discountAmount?: number;
|
|
62
|
+
discountPercentage?: number;
|
|
63
|
+
productCode?: string;
|
|
64
|
+
category?: string;
|
|
65
|
+
createdAt: string;
|
|
66
|
+
updatedAt: string;
|
|
67
|
+
subtotal: number;
|
|
68
|
+
totalTaxAmount: number;
|
|
69
|
+
totalDiscountAmount: number;
|
|
70
|
+
total: number;
|
|
71
|
+
}
|
|
72
|
+
interface PaymentReceiptResponse {
|
|
73
|
+
uid: string;
|
|
74
|
+
amount: number;
|
|
75
|
+
currency: string;
|
|
76
|
+
status: string;
|
|
77
|
+
payerId?: string;
|
|
78
|
+
createdAt: string;
|
|
79
|
+
updatedAt: string;
|
|
80
|
+
lineItems?: LineItemResponse[];
|
|
81
|
+
merchantName?: string;
|
|
82
|
+
merchantContact?: string;
|
|
83
|
+
pspReference?: string;
|
|
84
|
+
buyerName?: string;
|
|
85
|
+
buyerEmail?: string;
|
|
86
|
+
taxAmount?: number;
|
|
87
|
+
discountAmount?: number;
|
|
88
|
+
amountFormatted?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
interface PaymentClientOptions {
|
|
92
|
+
baseUrl: string;
|
|
93
|
+
tenantId: string;
|
|
94
|
+
getAuthToken: () => Promise<string>;
|
|
95
|
+
timeout?: number;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
declare class PaymentClient {
|
|
99
|
+
private baseUrl;
|
|
100
|
+
private tenantId;
|
|
101
|
+
private getAuthToken;
|
|
102
|
+
private timeout?;
|
|
103
|
+
constructor(options: PaymentClientOptions);
|
|
104
|
+
createPayment(request: CreatePaymentRequest): Promise<CreatePaymentResponse>;
|
|
105
|
+
getPayment(paymentId: string): Promise<PaymentResponse | null>;
|
|
106
|
+
getReceipt(paymentId: string): Promise<PaymentReceiptResponse | null>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export { type CreatePaymentRequest, type CreatePaymentResponse, type LineItemRequest, type LineItemResponse, PaymentClient, type PaymentClientOptions, type PaymentReceiptResponse, type PaymentResponse, type PersonInfoRequest };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
PaymentClient: () => PaymentClient
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/client/PaymentClient.ts
|
|
28
|
+
var PaymentClient = class {
|
|
29
|
+
constructor(options) {
|
|
30
|
+
this.baseUrl = options.baseUrl.trim().replace(/\/$/, "");
|
|
31
|
+
this.tenantId = options.tenantId;
|
|
32
|
+
this.getAuthToken = options.getAuthToken;
|
|
33
|
+
this.timeout = options.timeout;
|
|
34
|
+
}
|
|
35
|
+
async createPayment(request) {
|
|
36
|
+
const token = await this.getAuthToken();
|
|
37
|
+
const controller = new AbortController();
|
|
38
|
+
if (this.timeout) {
|
|
39
|
+
setTimeout(() => controller.abort(), this.timeout);
|
|
40
|
+
}
|
|
41
|
+
const response = await fetch(`${this.baseUrl}/api/v1/payments`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
"Content-Type": "application/json",
|
|
45
|
+
"Authorization": `Bearer ${token}`,
|
|
46
|
+
"X-Tenant-ID": this.tenantId
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify(request),
|
|
49
|
+
signal: controller.signal
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
const errorText = await response.text();
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
return await response.json();
|
|
58
|
+
}
|
|
59
|
+
async getPayment(paymentId) {
|
|
60
|
+
const token = await this.getAuthToken();
|
|
61
|
+
const controller = new AbortController();
|
|
62
|
+
if (this.timeout) {
|
|
63
|
+
setTimeout(() => controller.abort(), this.timeout);
|
|
64
|
+
}
|
|
65
|
+
const response = await fetch(`${this.baseUrl}/api/v1/payments/${paymentId}`, {
|
|
66
|
+
headers: {
|
|
67
|
+
"Authorization": `Bearer ${token}`
|
|
68
|
+
},
|
|
69
|
+
signal: controller.signal
|
|
70
|
+
});
|
|
71
|
+
if (response.status === 404) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
const errorText = await response.text();
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return await response.json();
|
|
81
|
+
}
|
|
82
|
+
async getReceipt(paymentId) {
|
|
83
|
+
const token = await this.getAuthToken();
|
|
84
|
+
const controller = new AbortController();
|
|
85
|
+
if (this.timeout) {
|
|
86
|
+
setTimeout(() => controller.abort(), this.timeout);
|
|
87
|
+
}
|
|
88
|
+
const response = await fetch(
|
|
89
|
+
`${this.baseUrl}/api/v1/payments/${paymentId}/receipt`,
|
|
90
|
+
{
|
|
91
|
+
headers: {
|
|
92
|
+
"Authorization": `Bearer ${token}`
|
|
93
|
+
},
|
|
94
|
+
signal: controller.signal
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
if (response.status === 404) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
const errorText = await response.text();
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
return await response.json();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
110
|
+
0 && (module.exports = {
|
|
111
|
+
PaymentClient
|
|
112
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/client/PaymentClient.ts
|
|
2
|
+
var PaymentClient = class {
|
|
3
|
+
constructor(options) {
|
|
4
|
+
this.baseUrl = options.baseUrl.trim().replace(/\/$/, "");
|
|
5
|
+
this.tenantId = options.tenantId;
|
|
6
|
+
this.getAuthToken = options.getAuthToken;
|
|
7
|
+
this.timeout = options.timeout;
|
|
8
|
+
}
|
|
9
|
+
async createPayment(request) {
|
|
10
|
+
const token = await this.getAuthToken();
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
if (this.timeout) {
|
|
13
|
+
setTimeout(() => controller.abort(), this.timeout);
|
|
14
|
+
}
|
|
15
|
+
const response = await fetch(`${this.baseUrl}/api/v1/payments`, {
|
|
16
|
+
method: "POST",
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
"Authorization": `Bearer ${token}`,
|
|
20
|
+
"X-Tenant-ID": this.tenantId
|
|
21
|
+
},
|
|
22
|
+
body: JSON.stringify(request),
|
|
23
|
+
signal: controller.signal
|
|
24
|
+
});
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
const errorText = await response.text();
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return await response.json();
|
|
32
|
+
}
|
|
33
|
+
async getPayment(paymentId) {
|
|
34
|
+
const token = await this.getAuthToken();
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
if (this.timeout) {
|
|
37
|
+
setTimeout(() => controller.abort(), this.timeout);
|
|
38
|
+
}
|
|
39
|
+
const response = await fetch(`${this.baseUrl}/api/v1/payments/${paymentId}`, {
|
|
40
|
+
headers: {
|
|
41
|
+
"Authorization": `Bearer ${token}`
|
|
42
|
+
},
|
|
43
|
+
signal: controller.signal
|
|
44
|
+
});
|
|
45
|
+
if (response.status === 404) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
const errorText = await response.text();
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
return await response.json();
|
|
55
|
+
}
|
|
56
|
+
async getReceipt(paymentId) {
|
|
57
|
+
const token = await this.getAuthToken();
|
|
58
|
+
const controller = new AbortController();
|
|
59
|
+
if (this.timeout) {
|
|
60
|
+
setTimeout(() => controller.abort(), this.timeout);
|
|
61
|
+
}
|
|
62
|
+
const response = await fetch(
|
|
63
|
+
`${this.baseUrl}/api/v1/payments/${paymentId}/receipt`,
|
|
64
|
+
{
|
|
65
|
+
headers: {
|
|
66
|
+
"Authorization": `Bearer ${token}`
|
|
67
|
+
},
|
|
68
|
+
signal: controller.signal
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
if (response.status === 404) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
const errorText = await response.text();
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return await response.json();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
export {
|
|
84
|
+
PaymentClient
|
|
85
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bcc-code/payment-client",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Client SDK for BCC Payment Orchestrator API",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"payment",
|
|
17
|
+
"bcc",
|
|
18
|
+
"stripe",
|
|
19
|
+
"adyen"
|
|
20
|
+
],
|
|
21
|
+
"author": "BCC Code",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"typescript": "^5.0.0",
|
|
26
|
+
"tsup": "^8.0.0"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"vue": "^3.0.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
33
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CreatePaymentRequest,
|
|
3
|
+
CreatePaymentResponse,
|
|
4
|
+
PaymentResponse,
|
|
5
|
+
PaymentReceiptResponse
|
|
6
|
+
} from '../types'
|
|
7
|
+
import type { PaymentClientOptions } from './PaymentClientOptions'
|
|
8
|
+
|
|
9
|
+
export class PaymentClient {
|
|
10
|
+
private baseUrl: string
|
|
11
|
+
private tenantId: string
|
|
12
|
+
private getAuthToken: () => Promise<string>
|
|
13
|
+
private timeout?: number
|
|
14
|
+
|
|
15
|
+
constructor(options: PaymentClientOptions) {
|
|
16
|
+
this.baseUrl = options.baseUrl.trim().replace(/\/$/, '')
|
|
17
|
+
this.tenantId = options.tenantId
|
|
18
|
+
this.getAuthToken = options.getAuthToken
|
|
19
|
+
this.timeout = options.timeout
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async createPayment(
|
|
23
|
+
request: CreatePaymentRequest
|
|
24
|
+
): Promise<CreatePaymentResponse> {
|
|
25
|
+
const token = await this.getAuthToken()
|
|
26
|
+
|
|
27
|
+
const controller = new AbortController()
|
|
28
|
+
if (this.timeout) {
|
|
29
|
+
setTimeout(() => controller.abort(), this.timeout)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const response = await fetch(`${this.baseUrl}/api/v1/payments`, {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
headers: {
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
'Authorization': `Bearer ${token}`,
|
|
37
|
+
'X-Tenant-ID': this.tenantId
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify(request),
|
|
40
|
+
signal: controller.signal
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
const errorText = await response.text()
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return await response.json()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async getPayment(paymentId: string): Promise<PaymentResponse | null> {
|
|
54
|
+
const token = await this.getAuthToken()
|
|
55
|
+
|
|
56
|
+
const controller = new AbortController()
|
|
57
|
+
if (this.timeout) {
|
|
58
|
+
setTimeout(() => controller.abort(), this.timeout)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const response = await fetch(`${this.baseUrl}/api/v1/payments/${paymentId}`, {
|
|
62
|
+
headers: {
|
|
63
|
+
'Authorization': `Bearer ${token}`
|
|
64
|
+
},
|
|
65
|
+
signal: controller.signal
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
if (response.status === 404) {
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
const errorText = await response.text()
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return await response.json()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async getReceipt(paymentId: string): Promise<PaymentReceiptResponse | null> {
|
|
83
|
+
const token = await this.getAuthToken()
|
|
84
|
+
|
|
85
|
+
const controller = new AbortController()
|
|
86
|
+
if (this.timeout) {
|
|
87
|
+
setTimeout(() => controller.abort(), this.timeout)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const response = await fetch(
|
|
91
|
+
`${this.baseUrl}/api/v1/payments/${paymentId}/receipt`,
|
|
92
|
+
{
|
|
93
|
+
headers: {
|
|
94
|
+
'Authorization': `Bearer ${token}`
|
|
95
|
+
},
|
|
96
|
+
signal: controller.signal
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
if (response.status === 404) {
|
|
101
|
+
return null
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
const errorText = await response.text()
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Payment API request failed: ${response.status} ${response.statusText}. ${errorText}`
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return await response.json()
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export interface CreatePaymentRequest {
|
|
2
|
+
payerId?: string
|
|
3
|
+
amount: number
|
|
4
|
+
currency: string
|
|
5
|
+
countryCode?: string
|
|
6
|
+
paymentMethodType: string
|
|
7
|
+
merchantReference?: string
|
|
8
|
+
returnUrl: string
|
|
9
|
+
paymentMethodDetails?: Record<string, any>
|
|
10
|
+
person?: PersonInfoRequest
|
|
11
|
+
lineItems?: LineItemRequest[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PersonInfoRequest {
|
|
15
|
+
payerUid: string
|
|
16
|
+
firstName?: string
|
|
17
|
+
lastName?: string
|
|
18
|
+
email?: string
|
|
19
|
+
addressLine1?: string
|
|
20
|
+
addressLine2?: string
|
|
21
|
+
city?: string
|
|
22
|
+
postalCode?: string
|
|
23
|
+
country?: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface LineItemRequest {
|
|
27
|
+
name: string
|
|
28
|
+
description?: string
|
|
29
|
+
unitPrice: number
|
|
30
|
+
quantity: number
|
|
31
|
+
taxPercentage?: number
|
|
32
|
+
taxAmount?: number
|
|
33
|
+
discountAmount?: number
|
|
34
|
+
discountPercentage?: number
|
|
35
|
+
productCode?: string
|
|
36
|
+
category?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface CreatePaymentResponse {
|
|
40
|
+
paymentId: string
|
|
41
|
+
clientData?: string
|
|
42
|
+
clientKey?: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface PaymentResponse {
|
|
46
|
+
uid: string
|
|
47
|
+
amount: number
|
|
48
|
+
currency: string
|
|
49
|
+
status: string
|
|
50
|
+
payerUid: string
|
|
51
|
+
orgId: string
|
|
52
|
+
createdAt: string
|
|
53
|
+
updatedAt: string
|
|
54
|
+
lineItems?: LineItemResponse[]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface LineItemResponse {
|
|
58
|
+
id: string
|
|
59
|
+
productId: string
|
|
60
|
+
name: string
|
|
61
|
+
description?: string
|
|
62
|
+
unitPrice: number
|
|
63
|
+
quantity: number
|
|
64
|
+
taxPercentage?: number
|
|
65
|
+
taxAmount?: number
|
|
66
|
+
discountAmount?: number
|
|
67
|
+
discountPercentage?: number
|
|
68
|
+
productCode?: string
|
|
69
|
+
category?: string
|
|
70
|
+
createdAt: string
|
|
71
|
+
updatedAt: string
|
|
72
|
+
subtotal: number
|
|
73
|
+
totalTaxAmount: number
|
|
74
|
+
totalDiscountAmount: number
|
|
75
|
+
total: number
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface PaymentReceiptResponse {
|
|
79
|
+
uid: string
|
|
80
|
+
amount: number
|
|
81
|
+
currency: string
|
|
82
|
+
status: string
|
|
83
|
+
payerId?: string
|
|
84
|
+
createdAt: string
|
|
85
|
+
updatedAt: string
|
|
86
|
+
lineItems?: LineItemResponse[]
|
|
87
|
+
merchantName?: string
|
|
88
|
+
merchantContact?: string
|
|
89
|
+
pspReference?: string
|
|
90
|
+
buyerName?: string
|
|
91
|
+
buyerEmail?: string
|
|
92
|
+
taxAmount?: number
|
|
93
|
+
discountAmount?: number
|
|
94
|
+
amountFormatted?: string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2020", "DOM"],
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationMap": true,
|
|
8
|
+
"sourceMap": true,
|
|
9
|
+
"outDir": "./dist",
|
|
10
|
+
"rootDir": "./src",
|
|
11
|
+
"strict": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"moduleResolution": "node",
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"isolatedModules": true,
|
|
18
|
+
"noEmit": false
|
|
19
|
+
},
|
|
20
|
+
"include": ["src/**/*"],
|
|
21
|
+
"exclude": ["node_modules", "dist"]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|