@bloque/payments 0.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/dist/index.cjs ADDED
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ Bloque: ()=>Bloque
28
+ });
29
+ var package_namespaceObject = JSON.parse('{"UU":"@bloque/payments","rE":"0.0.1"}');
30
+ class BloqueError extends Error {
31
+ constructor(message){
32
+ super(message);
33
+ this.name = 'BloqueError';
34
+ Object.setPrototypeOf(this, BloqueError.prototype);
35
+ }
36
+ }
37
+ class APIError extends BloqueError {
38
+ status;
39
+ code;
40
+ constructor(message, status, code){
41
+ super(message), this.status = status, this.code = code;
42
+ this.name = 'APIError';
43
+ Object.setPrototypeOf(this, APIError.prototype);
44
+ }
45
+ }
46
+ class AuthenticationError extends APIError {
47
+ constructor(message, code){
48
+ super(message, 401, code);
49
+ this.name = 'AuthenticationError';
50
+ Object.setPrototypeOf(this, AuthenticationError.prototype);
51
+ }
52
+ }
53
+ class RateLimitError extends APIError {
54
+ constructor(message, code){
55
+ super(message, 429, code);
56
+ this.name = 'RateLimitError';
57
+ Object.setPrototypeOf(this, RateLimitError.prototype);
58
+ }
59
+ }
60
+ const SDK_NAME = package_namespaceObject.UU;
61
+ const SDK_VERSION = package_namespaceObject.rE;
62
+ class HttpClient {
63
+ baseURL;
64
+ apiKey;
65
+ timeout;
66
+ maxRetries;
67
+ userAgent;
68
+ constructor(config){
69
+ this.baseURL = config.baseURL;
70
+ this.apiKey = config.apiKey;
71
+ this.timeout = config.timeout ?? 10000;
72
+ this.maxRetries = config.maxRetries ?? 2;
73
+ this.userAgent = `${SDK_NAME}/${SDK_VERSION}`;
74
+ }
75
+ async request(options) {
76
+ const url = this.buildURL(options.path, options.params);
77
+ const headers = this.buildHeaders(options.headers, options.idempotencyKey);
78
+ let lastError;
79
+ for(let attempt = 0; attempt <= this.maxRetries; attempt++)try {
80
+ const controller = new AbortController();
81
+ const timeoutId = setTimeout(()=>controller.abort(), this.timeout);
82
+ const response = await fetch(url, {
83
+ method: options.method,
84
+ headers,
85
+ body: options.body ? JSON.stringify(options.body) : void 0,
86
+ signal: controller.signal
87
+ });
88
+ clearTimeout(timeoutId);
89
+ if (!response.ok) {
90
+ const error = await this.parseError(response);
91
+ this.isRetryableHttpStatus(response.status);
92
+ throw error;
93
+ }
94
+ if (204 === response.status) return;
95
+ return await response.json();
96
+ } catch (error) {
97
+ lastError = error;
98
+ if (!this.isRetryableError(error)) throw error;
99
+ if (attempt === this.maxRetries) break;
100
+ await this.sleep(this.backoff(attempt));
101
+ }
102
+ throw lastError ?? new BloqueError('Request failed after retries');
103
+ }
104
+ buildURL(path, params) {
105
+ const url = new URL(path, this.baseURL);
106
+ if (params) {
107
+ for (const [key, value] of Object.entries(params))if (null != value) url.searchParams.append(key, String(value));
108
+ }
109
+ return url.toString();
110
+ }
111
+ buildHeaders(customHeaders, idempotencyKey) {
112
+ return {
113
+ Authorization: `Bearer ${this.apiKey}`,
114
+ 'Content-Type': 'application/json',
115
+ 'User-Agent': this.userAgent,
116
+ ...idempotencyKey ? {
117
+ 'Idempotency-Key': idempotencyKey
118
+ } : {},
119
+ ...customHeaders
120
+ };
121
+ }
122
+ async parseError(response) {
123
+ let payload;
124
+ try {
125
+ payload = await response.json();
126
+ } catch {
127
+ payload = {
128
+ message: response.statusText
129
+ };
130
+ }
131
+ const message = payload.message || 'Request failed';
132
+ const code = payload.code;
133
+ switch(response.status){
134
+ case 401:
135
+ return new AuthenticationError(message, code);
136
+ case 429:
137
+ return new RateLimitError(message, code);
138
+ case 400:
139
+ case 404:
140
+ case 409:
141
+ case 422:
142
+ return new APIError(message, response.status, code);
143
+ default:
144
+ return new APIError(message, response.status, code);
145
+ }
146
+ }
147
+ isRetryableHttpStatus(status) {
148
+ return status >= 500 || 429 === status;
149
+ }
150
+ isRetryableError(error) {
151
+ if (error instanceof AuthenticationError || error instanceof APIError || error instanceof BloqueError) return false;
152
+ if (error instanceof RateLimitError) return true;
153
+ error instanceof DOMException && error.name;
154
+ return true;
155
+ }
156
+ backoff(attempt) {
157
+ const base = 300;
158
+ const max = 5000;
159
+ return Math.min(base * 2 ** attempt, max);
160
+ }
161
+ sleep(ms) {
162
+ return new Promise((resolve)=>setTimeout(resolve, ms));
163
+ }
164
+ get(path, params) {
165
+ return this.request({
166
+ method: 'GET',
167
+ path,
168
+ params
169
+ });
170
+ }
171
+ post(path, body, options) {
172
+ return this.request({
173
+ method: 'POST',
174
+ path,
175
+ body,
176
+ idempotencyKey: options?.idempotencyKey
177
+ });
178
+ }
179
+ patch(path, body) {
180
+ return this.request({
181
+ method: 'PATCH',
182
+ path,
183
+ body
184
+ });
185
+ }
186
+ delete(path) {
187
+ return this.request({
188
+ method: 'DELETE',
189
+ path
190
+ });
191
+ }
192
+ }
193
+ class BaseResource {
194
+ http;
195
+ constructor(http){
196
+ this.http = http;
197
+ }
198
+ }
199
+ class CheckoutResource extends BaseResource {
200
+ async create(params) {
201
+ const items = params.items.map((item)=>({
202
+ name: item.name,
203
+ price: item.amount.toString(),
204
+ units: item.quantity,
205
+ image_url: item.image_url
206
+ }));
207
+ const payload = {
208
+ name: params.name,
209
+ description: params.description,
210
+ asset: 'dUSD/6',
211
+ payment_type: 'shopping_cart',
212
+ image_url: params.image_url,
213
+ items: items,
214
+ redirect_url: params.success_url,
215
+ expires_at: params.expires_at,
216
+ metadata: params.metadata
217
+ };
218
+ const response = await this.http.post('/checkout', payload);
219
+ return {
220
+ id: response.payment.urn,
221
+ object: 'checkout',
222
+ url: response.payment.url,
223
+ status: response.payment.summary.status,
224
+ amount_total: response.payment.price,
225
+ amount_subtotal: response.payment.price,
226
+ currency: 'USD',
227
+ items: params.items,
228
+ created_at: response.payment.created_at,
229
+ updated_at: response.payment.updated_at,
230
+ expires_at: response.payment.expires_at,
231
+ metadata: response.payment.metadata
232
+ };
233
+ }
234
+ async retrieve(checkoutId) {
235
+ return this.http.get(`/checkout/${checkoutId}`);
236
+ }
237
+ async cancel(checkoutId) {
238
+ return this.http.post(`/checkout/${checkoutId}/cancel`);
239
+ }
240
+ }
241
+ class PaymentResource extends BaseResource {
242
+ async create(params) {
243
+ const paymentPayload = this.buildPaymentPayload(params.payment);
244
+ const paymentResponse = await this.http.post(`/checkout/${params.checkoutId}/pay/${params.payment.type}`, paymentPayload);
245
+ return paymentResponse;
246
+ }
247
+ buildPaymentPayload(payment) {
248
+ switch(payment.type){
249
+ case 'card':
250
+ return this.buildCardPayload(payment.data);
251
+ case 'pse':
252
+ return this.buildPSEPayload(payment.data);
253
+ case 'cash':
254
+ return this.buildCashPayload(payment.data);
255
+ }
256
+ }
257
+ buildCardPayload(data) {
258
+ return {
259
+ customer_email: data.email || '',
260
+ number: data.cardNumber,
261
+ cvc: data.cvv,
262
+ exp_month: data.expiryMonth,
263
+ exp_year: data.expiryYear,
264
+ card_holder: data.cardholderName
265
+ };
266
+ }
267
+ buildPSEPayload(data) {
268
+ return {
269
+ customer_email: data.email,
270
+ person_type: data.personType,
271
+ document_type: data.documentType,
272
+ document_number: data.documentNumber,
273
+ bank_code: data.bankCode
274
+ };
275
+ }
276
+ buildCashPayload(data) {
277
+ return {
278
+ customer_email: data.email,
279
+ document_type: data.documentType,
280
+ document_number: data.documentNumber,
281
+ full_name: data.fullName
282
+ };
283
+ }
284
+ }
285
+ class Bloque {
286
+ #httpClient;
287
+ #config;
288
+ checkout;
289
+ payments;
290
+ constructor(config){
291
+ if (!config.apiKey) throw new Error('API key is required');
292
+ this.#config = config;
293
+ this.#httpClient = new HttpClient({
294
+ baseURL: 'https: //api.bloque.app/api/payments',
295
+ apiKey: this.#config.apiKey,
296
+ timeout: this.#config.timeout,
297
+ maxRetries: this.#config.maxRetries
298
+ });
299
+ this.initializeResources();
300
+ }
301
+ initializeResources() {
302
+ this.checkout = new CheckoutResource(this.#httpClient);
303
+ this.payments = new PaymentResource(this.#httpClient);
304
+ }
305
+ }
306
+ exports.Bloque = __webpack_exports__.Bloque;
307
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
308
+ "Bloque"
309
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
310
+ Object.defineProperty(exports, '__esModule', {
311
+ value: true
312
+ });
@@ -0,0 +1,3 @@
1
+ export type { CreatePaymentParams, PaymentResponse, PaymentSubmitPayload, } from '@bloque/payments-core';
2
+ export { Bloque, type BloqueConfig } from './client';
3
+ export type { Checkout, CheckoutItem, CheckoutParams, CheckoutStatus, } from './types/checkout';
package/dist/index.js ADDED
@@ -0,0 +1,278 @@
1
+ var package_namespaceObject = JSON.parse('{"UU":"@bloque/payments","rE":"0.0.1"}');
2
+ class BloqueError extends Error {
3
+ constructor(message){
4
+ super(message);
5
+ this.name = 'BloqueError';
6
+ Object.setPrototypeOf(this, BloqueError.prototype);
7
+ }
8
+ }
9
+ class APIError extends BloqueError {
10
+ status;
11
+ code;
12
+ constructor(message, status, code){
13
+ super(message), this.status = status, this.code = code;
14
+ this.name = 'APIError';
15
+ Object.setPrototypeOf(this, APIError.prototype);
16
+ }
17
+ }
18
+ class AuthenticationError extends APIError {
19
+ constructor(message, code){
20
+ super(message, 401, code);
21
+ this.name = 'AuthenticationError';
22
+ Object.setPrototypeOf(this, AuthenticationError.prototype);
23
+ }
24
+ }
25
+ class RateLimitError extends APIError {
26
+ constructor(message, code){
27
+ super(message, 429, code);
28
+ this.name = 'RateLimitError';
29
+ Object.setPrototypeOf(this, RateLimitError.prototype);
30
+ }
31
+ }
32
+ const SDK_NAME = package_namespaceObject.UU;
33
+ const SDK_VERSION = package_namespaceObject.rE;
34
+ class HttpClient {
35
+ baseURL;
36
+ apiKey;
37
+ timeout;
38
+ maxRetries;
39
+ userAgent;
40
+ constructor(config){
41
+ this.baseURL = config.baseURL;
42
+ this.apiKey = config.apiKey;
43
+ this.timeout = config.timeout ?? 10000;
44
+ this.maxRetries = config.maxRetries ?? 2;
45
+ this.userAgent = `${SDK_NAME}/${SDK_VERSION}`;
46
+ }
47
+ async request(options) {
48
+ const url = this.buildURL(options.path, options.params);
49
+ const headers = this.buildHeaders(options.headers, options.idempotencyKey);
50
+ let lastError;
51
+ for(let attempt = 0; attempt <= this.maxRetries; attempt++)try {
52
+ const controller = new AbortController();
53
+ const timeoutId = setTimeout(()=>controller.abort(), this.timeout);
54
+ const response = await fetch(url, {
55
+ method: options.method,
56
+ headers,
57
+ body: options.body ? JSON.stringify(options.body) : void 0,
58
+ signal: controller.signal
59
+ });
60
+ clearTimeout(timeoutId);
61
+ if (!response.ok) {
62
+ const error = await this.parseError(response);
63
+ this.isRetryableHttpStatus(response.status);
64
+ throw error;
65
+ }
66
+ if (204 === response.status) return;
67
+ return await response.json();
68
+ } catch (error) {
69
+ lastError = error;
70
+ if (!this.isRetryableError(error)) throw error;
71
+ if (attempt === this.maxRetries) break;
72
+ await this.sleep(this.backoff(attempt));
73
+ }
74
+ throw lastError ?? new BloqueError('Request failed after retries');
75
+ }
76
+ buildURL(path, params) {
77
+ const url = new URL(path, this.baseURL);
78
+ if (params) {
79
+ for (const [key, value] of Object.entries(params))if (null != value) url.searchParams.append(key, String(value));
80
+ }
81
+ return url.toString();
82
+ }
83
+ buildHeaders(customHeaders, idempotencyKey) {
84
+ return {
85
+ Authorization: `Bearer ${this.apiKey}`,
86
+ 'Content-Type': 'application/json',
87
+ 'User-Agent': this.userAgent,
88
+ ...idempotencyKey ? {
89
+ 'Idempotency-Key': idempotencyKey
90
+ } : {},
91
+ ...customHeaders
92
+ };
93
+ }
94
+ async parseError(response) {
95
+ let payload;
96
+ try {
97
+ payload = await response.json();
98
+ } catch {
99
+ payload = {
100
+ message: response.statusText
101
+ };
102
+ }
103
+ const message = payload.message || 'Request failed';
104
+ const code = payload.code;
105
+ switch(response.status){
106
+ case 401:
107
+ return new AuthenticationError(message, code);
108
+ case 429:
109
+ return new RateLimitError(message, code);
110
+ case 400:
111
+ case 404:
112
+ case 409:
113
+ case 422:
114
+ return new APIError(message, response.status, code);
115
+ default:
116
+ return new APIError(message, response.status, code);
117
+ }
118
+ }
119
+ isRetryableHttpStatus(status) {
120
+ return status >= 500 || 429 === status;
121
+ }
122
+ isRetryableError(error) {
123
+ if (error instanceof AuthenticationError || error instanceof APIError || error instanceof BloqueError) return false;
124
+ if (error instanceof RateLimitError) return true;
125
+ error instanceof DOMException && error.name;
126
+ return true;
127
+ }
128
+ backoff(attempt) {
129
+ const base = 300;
130
+ const max = 5000;
131
+ return Math.min(base * 2 ** attempt, max);
132
+ }
133
+ sleep(ms) {
134
+ return new Promise((resolve)=>setTimeout(resolve, ms));
135
+ }
136
+ get(path, params) {
137
+ return this.request({
138
+ method: 'GET',
139
+ path,
140
+ params
141
+ });
142
+ }
143
+ post(path, body, options) {
144
+ return this.request({
145
+ method: 'POST',
146
+ path,
147
+ body,
148
+ idempotencyKey: options?.idempotencyKey
149
+ });
150
+ }
151
+ patch(path, body) {
152
+ return this.request({
153
+ method: 'PATCH',
154
+ path,
155
+ body
156
+ });
157
+ }
158
+ delete(path) {
159
+ return this.request({
160
+ method: 'DELETE',
161
+ path
162
+ });
163
+ }
164
+ }
165
+ class BaseResource {
166
+ http;
167
+ constructor(http){
168
+ this.http = http;
169
+ }
170
+ }
171
+ class CheckoutResource extends BaseResource {
172
+ async create(params) {
173
+ const items = params.items.map((item)=>({
174
+ name: item.name,
175
+ price: item.amount.toString(),
176
+ units: item.quantity,
177
+ image_url: item.image_url
178
+ }));
179
+ const payload = {
180
+ name: params.name,
181
+ description: params.description,
182
+ asset: 'dUSD/6',
183
+ payment_type: 'shopping_cart',
184
+ image_url: params.image_url,
185
+ items: items,
186
+ redirect_url: params.success_url,
187
+ expires_at: params.expires_at,
188
+ metadata: params.metadata
189
+ };
190
+ const response = await this.http.post('/checkout', payload);
191
+ return {
192
+ id: response.payment.urn,
193
+ object: 'checkout',
194
+ url: response.payment.url,
195
+ status: response.payment.summary.status,
196
+ amount_total: response.payment.price,
197
+ amount_subtotal: response.payment.price,
198
+ currency: 'USD',
199
+ items: params.items,
200
+ created_at: response.payment.created_at,
201
+ updated_at: response.payment.updated_at,
202
+ expires_at: response.payment.expires_at,
203
+ metadata: response.payment.metadata
204
+ };
205
+ }
206
+ async retrieve(checkoutId) {
207
+ return this.http.get(`/checkout/${checkoutId}`);
208
+ }
209
+ async cancel(checkoutId) {
210
+ return this.http.post(`/checkout/${checkoutId}/cancel`);
211
+ }
212
+ }
213
+ class PaymentResource extends BaseResource {
214
+ async create(params) {
215
+ const paymentPayload = this.buildPaymentPayload(params.payment);
216
+ const paymentResponse = await this.http.post(`/checkout/${params.checkoutId}/pay/${params.payment.type}`, paymentPayload);
217
+ return paymentResponse;
218
+ }
219
+ buildPaymentPayload(payment) {
220
+ switch(payment.type){
221
+ case 'card':
222
+ return this.buildCardPayload(payment.data);
223
+ case 'pse':
224
+ return this.buildPSEPayload(payment.data);
225
+ case 'cash':
226
+ return this.buildCashPayload(payment.data);
227
+ }
228
+ }
229
+ buildCardPayload(data) {
230
+ return {
231
+ customer_email: data.email || '',
232
+ number: data.cardNumber,
233
+ cvc: data.cvv,
234
+ exp_month: data.expiryMonth,
235
+ exp_year: data.expiryYear,
236
+ card_holder: data.cardholderName
237
+ };
238
+ }
239
+ buildPSEPayload(data) {
240
+ return {
241
+ customer_email: data.email,
242
+ person_type: data.personType,
243
+ document_type: data.documentType,
244
+ document_number: data.documentNumber,
245
+ bank_code: data.bankCode
246
+ };
247
+ }
248
+ buildCashPayload(data) {
249
+ return {
250
+ customer_email: data.email,
251
+ document_type: data.documentType,
252
+ document_number: data.documentNumber,
253
+ full_name: data.fullName
254
+ };
255
+ }
256
+ }
257
+ class Bloque {
258
+ #httpClient;
259
+ #config;
260
+ checkout;
261
+ payments;
262
+ constructor(config){
263
+ if (!config.apiKey) throw new Error('API key is required');
264
+ this.#config = config;
265
+ this.#httpClient = new HttpClient({
266
+ baseURL: 'https: //api.bloque.app/api/payments',
267
+ apiKey: this.#config.apiKey,
268
+ timeout: this.#config.timeout,
269
+ maxRetries: this.#config.maxRetries
270
+ });
271
+ this.initializeResources();
272
+ }
273
+ initializeResources() {
274
+ this.checkout = new CheckoutResource(this.#httpClient);
275
+ this.payments = new PaymentResource(this.#httpClient);
276
+ }
277
+ }
278
+ export { Bloque };
@@ -0,0 +1,5 @@
1
+ import type { HttpClient } from '../http/http-client';
2
+ export declare abstract class BaseResource {
3
+ protected http: HttpClient;
4
+ constructor(http: HttpClient);
5
+ }
@@ -0,0 +1,7 @@
1
+ import type { Checkout, CheckoutParams } from '../types/checkout';
2
+ import { BaseResource } from './base';
3
+ export declare class CheckoutResource extends BaseResource {
4
+ create(params: CheckoutParams): Promise<Checkout>;
5
+ retrieve(checkoutId: string): Promise<Checkout>;
6
+ cancel(checkoutId: string): Promise<Checkout>;
7
+ }
@@ -0,0 +1,33 @@
1
+ import type { CreatePaymentParams, PaymentResponse } from '@bloque/payments-core';
2
+ import { BaseResource } from './base';
3
+ export declare class PaymentResource extends BaseResource {
4
+ /**
5
+ * Create a payment for an existing checkout session
6
+ *
7
+ * @param params - Checkout ID and payment data
8
+ * @returns Payment response
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const payment = await bloque.payments.create({
13
+ * checkoutId: 'checkout_abc123',
14
+ * payment: {
15
+ * type: 'card',
16
+ * data: {
17
+ * cardNumber: '4111111111111111',
18
+ * cardholderName: 'John Doe',
19
+ * expiryMonth: '12',
20
+ * expiryYear: '2025',
21
+ * cvv: '123',
22
+ * email: 'john@example.com'
23
+ * }
24
+ * }
25
+ * });
26
+ * ```
27
+ */
28
+ create(params: CreatePaymentParams): Promise<PaymentResponse>;
29
+ private buildPaymentPayload;
30
+ private buildCardPayload;
31
+ private buildPSEPayload;
32
+ private buildCashPayload;
33
+ }