@wiicode/youcanpay-sdk 1.0.1 → 1.0.5

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 CHANGED
@@ -1,14 +1,31 @@
1
1
  # YouCanPay SDK
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@wiicode/youcanpay-sdk.svg)](https://www.npmjs.com/package/@wiicode/youcanpay-sdk)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@wiicode/youcanpay-sdk.svg)](https://www.npmjs.com/package/@wiicode/youcanpay-sdk)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue.svg)](https://github.com/eeyuub/youcanpay)
7
+
3
8
  Production-ready Node.js SDK for [YouCanPay](https://youcanpay.com) - Morocco's payment gateway.
4
9
 
5
10
  Works with **any Node.js framework** (Express, Fastify, Hapi) and has first-class **NestJS integration**.
6
11
 
12
+ ## Features
13
+
14
+ - **Credit Card Payments** - Redirect to YouCanPay checkout or direct server-side processing
15
+ - **CashPlus Payments** - Generate payment codes for cash payments at 1,800+ CashPlus locations in Morocco
16
+ - **Webhook Handling** - Secure webhook verification and parsing
17
+ - **NestJS Integration** - First-class module, guards, and pipes
18
+ - **TypeScript** - Full type safety and IntelliSense support
19
+ - **Validation** - Built-in input validation and sanitization
20
+
7
21
  ## Table of Contents
8
22
 
9
23
  - [Installation](#installation)
10
24
  - [Environment Setup](#environment-setup)
11
25
  - [Quick Start](#quick-start)
26
+ - [Payment Methods](#payment-methods)
27
+ - [Credit Card](#credit-card-payment)
28
+ - [CashPlus](#cashplus-payment)
12
29
  - [Complete Payment Flow](#complete-payment-flow)
13
30
  - [API Reference](#api-reference)
14
31
  - [Webhook Handling](#webhook-handling)
@@ -82,12 +99,12 @@ const client = new YouCanPayClient({
82
99
  // Create a payment
83
100
  async function createPayment() {
84
101
  const { token } = await client.createToken({
85
- orderId: 'order-123',
86
102
  amount: 50000, // 500.00 MAD (in centimes)
87
103
  currency: CurrencyCode.MAD,
88
104
  customerIp: '192.168.1.1',
89
105
  successUrl: 'https://myapp.com/payment/success',
90
106
  errorUrl: 'https://myapp.com/payment/error',
107
+ // orderId: 'order-123', // Optional - auto-generated UUID if not provided
91
108
  });
92
109
 
93
110
  // Redirect user to YouCanPay checkout
@@ -172,6 +189,62 @@ export class PaymentsService {
172
189
 
173
190
  ---
174
191
 
192
+ ## Payment Methods
193
+
194
+ ### Credit Card Payment
195
+
196
+ Redirect users to YouCanPay's secure checkout page:
197
+
198
+ ```typescript
199
+ // 1. Create token
200
+ const { token } = await client.createToken({
201
+ amount: 50000, // 500.00 MAD
202
+ currency: CurrencyCode.MAD,
203
+ customerIp: '192.168.1.1',
204
+ successUrl: 'https://myapp.com/success',
205
+ errorUrl: 'https://myapp.com/error',
206
+ });
207
+
208
+ // 2. Redirect to checkout
209
+ const paymentUrl = client.getPaymentUrl(token.id);
210
+ // => https://youcanpay.com/payment/token-id?lang=fr
211
+ ```
212
+
213
+ ### CashPlus Payment
214
+
215
+ Generate a payment code for cash payments at 1,800+ CashPlus locations in Morocco:
216
+
217
+ ```typescript
218
+ // 1. Create token (same as card)
219
+ const { token } = await client.createToken({
220
+ amount: 50000,
221
+ currency: CurrencyCode.MAD,
222
+ customerIp: '192.168.1.1',
223
+ successUrl: 'https://myapp.com/success',
224
+ errorUrl: 'https://myapp.com/error',
225
+ });
226
+
227
+ // 2. Initialize CashPlus payment
228
+ const cashplus = await client.payWithCashPlus({
229
+ tokenId: token.id,
230
+ });
231
+
232
+ // 3. Display the code to customer
233
+ console.log('Payment Code:', cashplus.token); // e.g., "cp862603980"
234
+ console.log('Transaction ID:', cashplus.transaction_id);
235
+
236
+ // Customer takes this code to any CashPlus location to pay in cash
237
+ ```
238
+
239
+ **CashPlus Flow:**
240
+ 1. Customer sees payment code (e.g., `cp862603980`)
241
+ 2. Customer visits any CashPlus location in Morocco
242
+ 3. Customer provides the code and pays in cash
243
+ 4. YouCanPay sends webhook notification to your server
244
+ 5. Your app confirms the payment
245
+
246
+ ---
247
+
175
248
  ## Complete Payment Flow
176
249
 
177
250
  ```
@@ -312,11 +385,11 @@ Create a payment token.
312
385
 
313
386
  ```typescript
314
387
  const { token } = await client.createToken({
315
- orderId: string, // Your unique order ID
316
388
  amount: number, // Amount in centimes (5000 = 50.00 MAD)
317
389
  currency: CurrencyCode, // 'MAD' | 'USD' | 'EUR'
318
390
  customerIp: string, // Customer's IP address
319
391
  successUrl: string, // Redirect URL on success
392
+ orderId?: string, // Optional - auto-generated UUID if not provided
320
393
  errorUrl?: string, // Redirect URL on error
321
394
  customer?: { // Optional customer info
322
395
  name?: string,
@@ -366,14 +439,33 @@ const result = await client.payWithCreditCard({
366
439
 
367
440
  #### `payWithCashPlus(params): Promise<CashPlusPaymentResponse>`
368
441
 
369
- Initialize CashPlus payment.
442
+ Initialize CashPlus payment. Returns a payment code that customers can use at any CashPlus location in Morocco.
370
443
 
371
444
  ```typescript
372
445
  const result = await client.payWithCashPlus({
373
- tokenId: string,
446
+ tokenId: string, // Token from createToken()
374
447
  });
448
+
449
+ // Response
450
+ {
451
+ transaction_id: string,
452
+ token: string, // Payment code for CashPlus location (e.g., "cp115705252")
453
+ success?: boolean,
454
+ amount?: number, // Amount in centimes
455
+ currency?: string, // Currency code
456
+ order_id?: string, // Order reference
457
+ expires_at?: string, // Token expiration (ISO date)
458
+ message?: string, // Message from YouCanPay
459
+ }
375
460
  ```
376
461
 
462
+ **CashPlus Payment Flow:**
463
+ 1. Create a payment token with `createToken()`
464
+ 2. Initialize CashPlus payment with `payWithCashPlus()`
465
+ 3. Display the `cashplus_token` to the customer
466
+ 4. Customer visits any CashPlus location and provides the code
467
+ 5. Once paid, YouCanPay sends a webhook notification
468
+
377
469
  ### Standalone Functions
378
470
 
379
471
  #### Webhook Functions
@@ -414,6 +506,13 @@ import {
414
506
  validateOrderId,
415
507
  validateIP,
416
508
  validateEmail,
509
+ validateTokenId,
510
+ validateTimeout,
511
+ validateClientOptions,
512
+ validateCardNumber,
513
+ validateExpiryDate,
514
+ validateCVV,
515
+ validateCardHolderName,
417
516
  validatePaymentInput,
418
517
  } from '@wiicode/youcanpay-sdk';
419
518
 
@@ -427,6 +526,13 @@ validateCurrency('GBP'); // { valid: false, error: 'Currency mus
427
526
 
428
527
  validateRedirectURL('https://app.com'); // { valid: true }
429
528
  validateRedirectURL('javascript:...'); // { valid: false }
529
+ validateTokenId('tok_123'); // { valid: true }
530
+ validateTimeout(30000); // { valid: true }
531
+ validateClientOptions({ privateKey: 'pri_x', publicKey: 'pub_x' }); // { valid: true }
532
+ validateCardNumber('4111111111111111'); // { valid: true }
533
+ validateExpiryDate('12/30'); // { valid: true }
534
+ validateCVV('123'); // { valid: true }
535
+ validateCardHolderName('Jane Doe'); // { valid: true }
430
536
 
431
537
  // Validate all at once
432
538
  const result = validatePaymentInput({
@@ -508,7 +614,7 @@ console.log(webhook.transactionId); // 'txn-uuid'
508
614
  console.log(webhook.orderId); // 'your-order-id'
509
615
  console.log(webhook.amount); // 50000
510
616
  console.log(webhook.isSuccess); // true
511
- console.log(webhook.status); // 'paid' | 'failed' | 'refunded'
617
+ console.log(webhook.status); // 'paid' | 'failed' | 'refunded' | 'unknown'
512
618
  console.log(webhook.eventName); // 'transaction.paid'
513
619
  ```
514
620
 
@@ -525,6 +631,7 @@ import {
525
631
  } from '@nestjs/common';
526
632
  import {
527
633
  ParseWebhookPipe,
634
+ ParsedWebhook,
528
635
  ParsedWebhookPayload,
529
636
  verifyWebhookSecret,
530
637
  } from '@wiicode/youcanpay-sdk';
@@ -554,6 +661,15 @@ export class PaymentsController {
554
661
  }
555
662
  ```
556
663
 
664
+ You can also inject the parsed payload directly:
665
+
666
+ ```typescript
667
+ @Post('webhook')
668
+ handleWebhook(@ParsedWebhook() webhook: ParsedWebhookPayload) {
669
+ return { orderId: webhook.orderId };
670
+ }
671
+ ```
672
+
557
673
  ### Webhook Security Checklist
558
674
 
559
675
  - [ ] Add secret to webhook URL: `https://myapp.com/webhook?secret=xxx`
@@ -620,43 +736,211 @@ const payment = await prisma.payment.create({
620
736
  });
621
737
  ```
622
738
 
623
- ### TypeORM Example
739
+ ### TypeORM Example (Complete NestJS Entity)
624
740
 
625
741
  ```typescript
742
+ // payment-status.enum.ts
743
+ export enum PaymentStatus {
744
+ PENDING = 'PENDING',
745
+ COMPLETED = 'COMPLETED',
746
+ FAILED = 'FAILED',
747
+ REFUNDED = 'REFUNDED',
748
+ }
749
+
750
+ // payment.entity.ts
751
+ import {
752
+ Entity,
753
+ PrimaryGeneratedColumn,
754
+ Column,
755
+ CreateDateColumn,
756
+ UpdateDateColumn,
757
+ ManyToOne,
758
+ JoinColumn,
759
+ } from 'typeorm';
760
+ import { PaymentStatus } from './payment-status.enum';
761
+ import { User } from '../users/user.entity';
762
+
626
763
  @Entity('payments')
627
764
  export class Payment {
628
765
  @PrimaryGeneratedColumn('uuid')
629
766
  id: string;
630
767
 
631
- @Column({ unique: true })
768
+ @Column({ unique: true, name: 'order_id' })
632
769
  orderId: string;
633
770
 
634
- @Column({ nullable: true })
771
+ @Column({ nullable: true, name: 'token_id' })
635
772
  tokenId: string;
636
773
 
637
- @Column({ nullable: true })
774
+ @Column({ nullable: true, name: 'transaction_id' })
638
775
  transactionId: string;
639
776
 
640
- @Column()
641
- amount: number;
777
+ @Column({ type: 'integer' })
778
+ amount: number; // In centimes
642
779
 
643
- @Column()
780
+ @Column({ length: 3 })
644
781
  currency: string;
645
782
 
646
- @Column({ default: 'PENDING' })
647
- status: 'PENDING' | 'COMPLETED' | 'FAILED';
783
+ @Column({
784
+ type: 'enum',
785
+ enum: PaymentStatus,
786
+ default: PaymentStatus.PENDING,
787
+ })
788
+ status: PaymentStatus;
648
789
 
649
- @Column()
790
+ @Column({ name: 'user_id' })
650
791
  userId: string;
651
792
 
652
- @CreateDateColumn()
793
+ @ManyToOne(() => User, { onDelete: 'CASCADE' })
794
+ @JoinColumn({ name: 'user_id' })
795
+ user: User;
796
+
797
+ @Column({ type: 'jsonb', nullable: true })
798
+ metadata: Record<string, any>;
799
+
800
+ @Column({ nullable: true })
801
+ errorMessage: string;
802
+
803
+ @CreateDateColumn({ name: 'created_at' })
653
804
  createdAt: Date;
654
805
 
655
- @UpdateDateColumn()
806
+ @UpdateDateColumn({ name: 'updated_at' })
656
807
  updatedAt: Date;
657
808
  }
658
809
  ```
659
810
 
811
+ ### Complete Payment Service Example
812
+
813
+ ```typescript
814
+ // payments.service.ts
815
+ import { Injectable, NotFoundException } from '@nestjs/common';
816
+ import { InjectRepository } from '@nestjs/typeorm';
817
+ import { Repository } from 'typeorm';
818
+ import { YouCanPayService, CurrencyCode, parseWebhookPayload, ParsedWebhookPayload } from '@wiicode/youcanpay-sdk';
819
+ import { Payment } from './payment.entity';
820
+ import { PaymentStatus } from './payment-status.enum';
821
+ import { v4 as uuidv4 } from 'uuid';
822
+
823
+ @Injectable()
824
+ export class PaymentsService {
825
+ constructor(
826
+ @InjectRepository(Payment)
827
+ private readonly paymentRepo: Repository<Payment>,
828
+ private readonly youcanpay: YouCanPayService,
829
+ ) {}
830
+
831
+ async createPayment(userId: string, amount: number, currency: string, customerIp: string) {
832
+ const orderId = uuidv4();
833
+
834
+ // 1. Save payment to database
835
+ const payment = this.paymentRepo.create({
836
+ orderId,
837
+ amount,
838
+ currency,
839
+ userId,
840
+ status: PaymentStatus.PENDING,
841
+ });
842
+ await this.paymentRepo.save(payment);
843
+
844
+ // 2. Create token with YouCanPay
845
+ const { token } = await this.youcanpay.createToken({
846
+ orderId,
847
+ amount,
848
+ currency: currency as CurrencyCode,
849
+ customerIp,
850
+ successUrl: `${process.env.APP_URL}/payments/success`,
851
+ errorUrl: `${process.env.APP_URL}/payments/error`,
852
+ });
853
+
854
+ // 3. Update payment with token ID
855
+ payment.tokenId = token.id;
856
+ await this.paymentRepo.save(payment);
857
+
858
+ return {
859
+ paymentId: payment.id,
860
+ paymentUrl: this.youcanpay.getPaymentUrl(token.id),
861
+ };
862
+ }
863
+
864
+ async handleWebhook(payload: unknown) {
865
+ const webhook = parseWebhookPayload(payload);
866
+
867
+ const payment = await this.paymentRepo.findOne({
868
+ where: { orderId: webhook.orderId },
869
+ });
870
+
871
+ if (!payment) {
872
+ throw new NotFoundException('Payment not found');
873
+ }
874
+
875
+ // Idempotency check
876
+ if (payment.status === PaymentStatus.COMPLETED) {
877
+ return { received: true, already_processed: true };
878
+ }
879
+
880
+ // Update payment status
881
+ payment.transactionId = webhook.transactionId;
882
+ payment.status = webhook.isSuccess ? PaymentStatus.COMPLETED : PaymentStatus.FAILED;
883
+ await this.paymentRepo.save(payment);
884
+
885
+ return { received: true };
886
+ }
887
+
888
+ async getPaymentByOrderId(orderId: string) {
889
+ return this.paymentRepo.findOne({ where: { orderId } });
890
+ }
891
+
892
+ async getUserPayments(userId: string) {
893
+ return this.paymentRepo.find({
894
+ where: { userId },
895
+ order: { createdAt: 'DESC' },
896
+ });
897
+ }
898
+ }
899
+ ```
900
+
901
+ ### Mongoose Example (MongoDB)
902
+
903
+ ```typescript
904
+ // payment.schema.ts
905
+ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
906
+ import { Document } from 'mongoose';
907
+
908
+ export enum PaymentStatus {
909
+ PENDING = 'PENDING',
910
+ COMPLETED = 'COMPLETED',
911
+ FAILED = 'FAILED',
912
+ }
913
+
914
+ @Schema({ timestamps: true })
915
+ export class Payment extends Document {
916
+ @Prop({ required: true, unique: true })
917
+ orderId: string;
918
+
919
+ @Prop()
920
+ tokenId: string;
921
+
922
+ @Prop()
923
+ transactionId: string;
924
+
925
+ @Prop({ required: true })
926
+ amount: number;
927
+
928
+ @Prop({ required: true })
929
+ currency: string;
930
+
931
+ @Prop({ enum: PaymentStatus, default: PaymentStatus.PENDING })
932
+ status: PaymentStatus;
933
+
934
+ @Prop({ required: true })
935
+ userId: string;
936
+
937
+ @Prop({ type: Object })
938
+ metadata: Record<string, any>;
939
+ }
940
+
941
+ export const PaymentSchema = SchemaFactory.createForClass(Payment);
942
+ ```
943
+
660
944
  ### Status Flow
661
945
 
662
946
  ```
@@ -710,6 +994,15 @@ if (!validation.valid) {
710
994
  6. **HTTPS only** - Never use HTTP in production
711
995
  7. **Sanitize inputs** - Use `sanitizeString()` for user inputs
712
996
  8. **URL whitelist** - Validate redirect URLs against allowed domains
997
+ 9. **Pre-validate outbound requests** - The SDK rejects invalid client, token, and card input before any network call
998
+
999
+ ### Production Checklist
1000
+
1001
+ - Complete a full sandbox checkout plus webhook round-trip before enabling live keys.
1002
+ - Restrict redirect URLs to your own domains with `validateRedirectURL(..., { allowedDomains: [...] })`.
1003
+ - Store webhook event IDs in your application database and enforce idempotency there.
1004
+ - Monitor failed `getTransaction()` and webhook-verification paths.
1005
+ - Rotate API keys and webhook secrets regularly.
713
1006
 
714
1007
  ---
715
1008
 
@@ -725,7 +1018,7 @@ try {
725
1018
  } catch (error) {
726
1019
  if (error instanceof YouCanPayError) {
727
1020
  console.log(error.code); // ErrorCodes.VALIDATION_ERROR
728
- console.log(error.status); // 422
1021
+ console.log(error.statusCode); // 422
729
1022
  console.log(error.message); // "The amount field is required"
730
1023
  console.log(error.details); // { amount: ['required'] }
731
1024
  }
@@ -752,7 +1045,7 @@ export class YouCanPayExceptionFilter implements ExceptionFilter {
752
1045
  catch(exception: YouCanPayError, host: ArgumentsHost) {
753
1046
  const response = host.switchToHttp().getResponse();
754
1047
 
755
- response.status(exception.status || 500).json({
1048
+ response.status(exception.statusCode || 500).json({
756
1049
  error: exception.code,
757
1050
  message: exception.message,
758
1051
  });
@@ -840,9 +1133,15 @@ interface YouCanPayOptions {
840
1133
 
841
1134
  ## Support
842
1135
 
843
- - [YouCanPay Documentation](https://youcanpay.com/docs)
1136
+ - [GitHub Repository](https://github.com/eeyuub/youcanpay)
1137
+ - [Report Issues](https://github.com/eeyuub/youcanpay/issues)
844
1138
  - [npm Package](https://www.npmjs.com/package/@wiicode/youcanpay-sdk)
1139
+ - [YouCanPay Documentation](https://youcanpay.com/docs)
1140
+
1141
+ ## Author
1142
+
1143
+ **WiiCode** - [@eeyuub](https://github.com/eeyuub)
845
1144
 
846
1145
  ## License
847
1146
 
848
- MIT
1147
+ MIT - see [LICENSE](https://github.com/eeyuub/youcanpay/blob/master/LICENSE) for details.
package/dist/client.d.ts CHANGED
@@ -2,6 +2,7 @@ import { Lang } from './enums';
2
2
  import { YouCanPayOptions, CreateTokenParams, TokenResponse, PayCreditCardParams, PaymentResponse, PayCashPlusParams, CashPlusPaymentResponse, Transaction } from './interfaces';
3
3
  export declare class YouCanPayClient {
4
4
  private readonly http;
5
+ private readonly transactionHttp;
5
6
  private readonly sandbox;
6
7
  private readonly privateKey;
7
8
  private readonly publicKey;
@@ -14,4 +15,5 @@ export declare class YouCanPayClient {
14
15
  getTransaction(transactionId: string): Promise<Transaction>;
15
16
  verifyWebhook(payload: unknown): boolean;
16
17
  private handleError;
18
+ private assertValid;
17
19
  }
package/dist/client.js CHANGED
@@ -5,12 +5,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.YouCanPayClient = void 0;
7
7
  const axios_1 = __importDefault(require("axios"));
8
+ const crypto_1 = require("crypto");
8
9
  const constants_1 = require("./constants");
9
10
  const errors_1 = require("./errors");
10
11
  const enums_1 = require("./enums");
11
12
  const logger_1 = require("./logging/logger");
13
+ const webhook_1 = require("./security/webhook");
14
+ const validators_1 = require("./security/validators");
12
15
  class YouCanPayClient {
13
16
  constructor(options) {
17
+ this.assertValid((0, validators_1.validateClientOptions)({
18
+ privateKey: options.privateKey,
19
+ publicKey: options.publicKey,
20
+ timeout: options.timeout,
21
+ }));
14
22
  this.sandbox = options.sandbox ?? false;
15
23
  this.privateKey = options.privateKey;
16
24
  this.publicKey = options.publicKey;
@@ -22,13 +30,27 @@ class YouCanPayClient {
22
30
  'Content-Type': 'application/x-www-form-urlencoded',
23
31
  },
24
32
  });
33
+ this.transactionHttp = axios_1.default.create({
34
+ baseURL: this.sandbox ? constants_1.YOUCANPAY_SANDBOX_TRANSACTION_API_URL : constants_1.YOUCANPAY_TRANSACTION_API_URL,
35
+ timeout: options.timeout ?? 30000,
36
+ });
25
37
  }
26
38
  async createToken(params) {
27
39
  const startTime = Date.now();
40
+ const orderId = params.orderId ?? (0, crypto_1.randomUUID)();
41
+ this.assertValid((0, validators_1.validatePaymentInput)({
42
+ amount: params.amount,
43
+ currency: params.currency,
44
+ orderId,
45
+ customerIp: params.customerIp,
46
+ successUrl: params.successUrl,
47
+ errorUrl: params.errorUrl,
48
+ customerEmail: params.customer?.email,
49
+ }));
28
50
  const body = new URLSearchParams();
29
51
  body.append('pri_key', this.privateKey);
30
52
  body.append('pub_key', this.publicKey);
31
- body.append('order_id', params.orderId);
53
+ body.append('order_id', orderId);
32
54
  body.append('amount', String(params.amount));
33
55
  body.append('currency', params.currency);
34
56
  body.append('customer_ip', params.customerIp);
@@ -62,11 +84,11 @@ class YouCanPayClient {
62
84
  try {
63
85
  const response = await this.http.post('/tokenize', body);
64
86
  const data = response.data;
65
- await this.logger.log('createToken', { orderId: params.orderId, amount: params.amount, currency: params.currency }, data, 'success', Date.now() - startTime, params.metadata);
87
+ await this.logger.log('createToken', { orderId, amount: params.amount, currency: params.currency }, data, 'success', Date.now() - startTime, params.metadata);
66
88
  return data;
67
89
  }
68
90
  catch (error) {
69
- await this.logger.log('createToken', { orderId: params.orderId, amount: params.amount, currency: params.currency }, undefined, 'error', Date.now() - startTime);
91
+ await this.logger.log('createToken', { orderId, amount: params.amount, currency: params.currency }, undefined, 'error', Date.now() - startTime);
70
92
  throw this.handleError(error);
71
93
  }
72
94
  }
@@ -76,6 +98,11 @@ class YouCanPayClient {
76
98
  }
77
99
  async payWithCreditCard(params) {
78
100
  const startTime = Date.now();
101
+ this.assertValid((0, validators_1.validateTokenId)(params.tokenId));
102
+ this.assertValid((0, validators_1.validateCardNumber)(params.creditCard));
103
+ this.assertValid((0, validators_1.validateExpiryDate)(params.expireDate));
104
+ this.assertValid((0, validators_1.validateCVV)(params.cvv));
105
+ this.assertValid((0, validators_1.validateCardHolderName)(params.cardHolderName));
79
106
  const body = new URLSearchParams();
80
107
  body.append('pri_key', this.privateKey);
81
108
  body.append('pub_key', this.publicKey);
@@ -97,13 +124,21 @@ class YouCanPayClient {
97
124
  }
98
125
  async payWithCashPlus(params) {
99
126
  const startTime = Date.now();
127
+ this.assertValid((0, validators_1.validateTokenId)(params.tokenId));
100
128
  const body = new URLSearchParams();
101
129
  body.append('pri_key', this.privateKey);
102
130
  body.append('pub_key', this.publicKey);
103
131
  body.append('token_id', params.tokenId);
132
+ body.append('payment_method[type]', 'cashplus');
104
133
  try {
105
134
  const response = await this.http.post('/cashplus/init', body);
106
- const data = response.data;
135
+ const rawData = response.data;
136
+ const cashplusToken = typeof rawData.token === 'string' ? rawData.token : rawData.token?.id;
137
+ const data = {
138
+ ...rawData,
139
+ token: cashplusToken,
140
+ transaction_id: rawData.transaction_id || '',
141
+ };
107
142
  await this.logger.log('payWithCashPlus', { tokenId: params.tokenId }, data, 'success', Date.now() - startTime);
108
143
  return data;
109
144
  }
@@ -114,8 +149,9 @@ class YouCanPayClient {
114
149
  }
115
150
  async getTransaction(transactionId) {
116
151
  const startTime = Date.now();
152
+ this.assertValid((0, validators_1.validateTokenId)(transactionId));
117
153
  try {
118
- const response = await this.http.get(`/transactions/${transactionId}`, {
154
+ const response = await this.transactionHttp.get(`/transactions/${transactionId}`, {
119
155
  params: { pri_key: this.privateKey },
120
156
  });
121
157
  const data = response.data;
@@ -131,10 +167,16 @@ class YouCanPayClient {
131
167
  if (!payload || typeof payload !== 'object') {
132
168
  return false;
133
169
  }
170
+ try {
171
+ (0, webhook_1.parseWebhookPayload)(payload);
172
+ return true;
173
+ }
174
+ catch {
175
+ }
134
176
  const p = payload;
135
177
  return (typeof p['transaction_id'] === 'string' &&
136
178
  typeof p['order_id'] === 'string' &&
137
- typeof p['amount'] === 'number' &&
179
+ (typeof p['amount'] === 'number' || typeof p['amount'] === 'string') &&
138
180
  typeof p['status'] === 'string');
139
181
  }
140
182
  handleError(error) {
@@ -166,6 +208,11 @@ class YouCanPayClient {
166
208
  const message = error instanceof Error ? error.message : 'An unknown error occurred';
167
209
  return new errors_1.YouCanPayError(message, errors_1.ErrorCodes.UNKNOWN_ERROR);
168
210
  }
211
+ assertValid(result) {
212
+ if (!result.valid) {
213
+ throw new errors_1.YouCanPayError(result.error ?? 'Invalid input', errors_1.ErrorCodes.VALIDATION_ERROR);
214
+ }
215
+ }
169
216
  }
170
217
  exports.YouCanPayClient = YouCanPayClient;
171
218
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA6C;AAC7C,mCAAoC;AACpC,2CAOqB;AACrB,qCAAsD;AACtD,mCAA+B;AAC/B,6CAAmD;AACnD,gDAAyD;AACzD,sDAQ+B;AAa/B,MAAa,eAAe;IAQ1B,YAAY,OAAyB;QACnC,IAAI,CAAC,WAAW,CACd,IAAA,kCAAqB,EAAC;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CACH,CAAC;QAEF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;QACxC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEnD,IAAI,CAAC,IAAI,GAAG,eAAK,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,sCAA0B,CAAC,CAAC,CAAC,8BAAkB;YACvE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK;YACjC,OAAO,EAAE;gBACP,cAAc,EAAE,mCAAmC;aACpD;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,GAAG,eAAK,CAAC,MAAM,CAAC;YAClC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,iDAAqC,CAAC,CAAC,CAAC,yCAA6B;YAC7F,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK;SAClC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAyB;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAA,mBAAU,GAAE,CAAC;QAC/C,IAAI,CAAC,WAAW,CACd,IAAA,iCAAoB,EAAC;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,OAAO;YACP,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,aAAa,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK;SACtC,CAAC,CACH,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,MAAM,CAAC,QAAQ;YAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAE/D,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;YACjC,IAAI,QAAQ,CAAC,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC/D,IAAI,QAAQ,CAAC,KAAK;gBAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClE,IAAI,QAAQ,CAAC,KAAK;gBAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClE,IAAI,QAAQ,CAAC,OAAO;gBAAE,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;YACxE,IAAI,QAAQ,CAAC,QAAQ;gBAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC3E,IAAI,QAAQ,CAAC,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC/D,IAAI,QAAQ,CAAC,KAAK;gBAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClE,IAAI,QAAQ,CAAC,YAAY;gBAAE,IAAI,CAAC,MAAM,CAAC,uBAAuB,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;QACzF,CAAC;QAED,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC3D,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAqB,CAAC;YAC5C,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,aAAa,EACb,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EAC7D,IAA0C,EAC1C,SAAS,EACT,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EACtB,MAAM,CAAC,QAAQ,CAChB,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,aAAa,EACb,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EAC7D,SAAS,EACT,OAAO,EACP,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CACvB,CAAC;YACF,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,aAAa,CAAC,OAAe,EAAE,OAAa,YAAI,CAAC,EAAE;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,yCAA6B,CAAC,CAAC,CAAC,iCAAqB,CAAC;QACrF,OAAO,GAAG,OAAO,IAAI,OAAO,SAAS,IAAI,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,MAA2B;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,WAAW,CAAC,IAAA,4BAAe,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,WAAW,CAAC,IAAA,+BAAkB,EAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,WAAW,CAAC,IAAA,+BAAkB,EAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,WAAW,CAAC,IAAA,wBAAW,EAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,WAAW,CAAC,IAAA,mCAAsB,EAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;QAEvD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAuB,CAAC;YAC9C,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,mBAAmB,EACnB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,EAClE,IAA0C,EAC1C,SAAS,EACT,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CACvB,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,mBAAmB,EACnB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAC3B,SAAS,EACT,OAAO,EACP,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CACvB,CAAC;YACF,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,MAAyB;QAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,WAAW,CAAC,IAAA,4BAAe,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAC;QAEhD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;YAC9D,MAAM,OAAO,GAAG,QAAQ,CAAC,IAA2B,CAAC;YAIrD,MAAM,aAAa,GACjB,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YAExE,MAAM,IAAI,GAA4B;gBACpC,GAAG,OAAO;gBACV,KAAK,EAAE,aAAa;gBACpB,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,EAAE;aAC7C,CAAC;YAEF,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,iBAAiB,EACjB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAC3B,IAA0C,EAC1C,SAAS,EACT,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CACvB,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,iBAAiB,EACjB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAC3B,SAAS,EACT,OAAO,EACP,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CACvB,CAAC;YACF,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,aAAqB;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,WAAW,CAAC,IAAA,4BAAe,EAAC,aAAa,CAAC,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,iBAAiB,aAAa,EAAE,EAAE;gBAChF,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE;aACrC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAmB,CAAC;YAC1C,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,gBAAgB,EAChB,EAAE,aAAa,EAAE,EACjB,IAA0C,EAC1C,SAAS,EACT,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CACvB,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,gBAAgB,EAChB,EAAE,aAAa,EAAE,EACjB,SAAS,EACT,OAAO,EACP,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CACvB,CAAC;YACF,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,aAAa,CAAC,OAAgB;QAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC;YACH,IAAA,6BAAmB,EAAC,OAAO,CAAC,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;QAED,MAAM,CAAC,GAAG,OAAkC,CAAC;QAC7C,OAAO,CACL,OAAO,CAAC,CAAC,gBAAgB,CAAC,KAAK,QAAQ;YACvC,OAAO,CAAC,CAAC,UAAU,CAAC,KAAK,QAAQ;YACjC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC;YACpE,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAChC,CAAC;IACJ,CAAC;IAEO,WAAW,CAAC,KAAc;QAChC,IACE,KAAK,KAAK,IAAI;YACd,OAAO,KAAK,KAAK,QAAQ;YACzB,cAAc,IAAI,KAAK;YACtB,KAAmC,CAAC,YAAY,EACjD,CAAC;YACD,MAAM,UAAU,GAAG,KAKlB,CAAC;YAEF,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;gBACxB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC;gBAC7C,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,uBAAuB,CAAC;gBACzD,MAAM,OAAO,GAAG,IAAI,EAAE,MAAM,CAAC;gBAE7B,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;oBACrC,OAAO,IAAI,uBAAc,CAAC,OAAO,EAAE,mBAAU,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC/E,CAAC;gBACD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;oBACnB,OAAO,IAAI,uBAAc,CAAC,OAAO,EAAE,mBAAU,CAAC,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;gBACnF,CAAC;gBACD,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;oBAClC,OAAO,IAAI,uBAAc,CAAC,OAAO,EAAE,mBAAU,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;gBACjF,CAAC;gBACD,OAAO,IAAI,uBAAc,CAAC,OAAO,EAAE,mBAAU,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAChF,CAAC;YAED,OAAO,IAAI,uBAAc,CAAC,wBAAwB,EAAE,mBAAU,CAAC,aAAa,CAAC,CAAC;QAChF,CAAC;QAED,IAAI,KAAK,YAAY,uBAAc,EAAE,CAAC;YACpC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;QACrF,OAAO,IAAI,uBAAc,CAAC,OAAO,EAAE,mBAAU,CAAC,aAAa,CAAC,CAAC;IAC/D,CAAC;IAEO,WAAW,CAAC,MAA0C;QAC5D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,IAAI,uBAAc,CAAC,MAAM,CAAC,KAAK,IAAI,eAAe,EAAE,mBAAU,CAAC,gBAAgB,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;CACF;AA9RD,0CA8RC"}