@yosle/tropipayjs 0.2.1 → 0.2.3

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/index.js CHANGED
@@ -1,15 +1,10 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var axios = require('axios');
6
4
  var crypto = require('crypto');
7
5
  var fs = require('fs/promises');
8
6
 
9
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
-
11
- function _interopNamespace(e) {
12
- if (e && e.__esModule) return e;
7
+ function _interopNamespaceDefault(e) {
13
8
  var n = Object.create(null);
14
9
  if (e) {
15
10
  Object.keys(e).forEach(function (k) {
@@ -22,13 +17,11 @@ function _interopNamespace(e) {
22
17
  }
23
18
  });
24
19
  }
25
- n["default"] = e;
20
+ n.default = e;
26
21
  return Object.freeze(n);
27
22
  }
28
23
 
29
- var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
30
- var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
31
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
24
+ var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto);
32
25
 
33
26
  function handleExceptions(error) {
34
27
  if (error instanceof axios.AxiosError) {
@@ -220,7 +213,7 @@ class PaymentCard {
220
213
  await this.tropipay.login();
221
214
  }
222
215
  try {
223
- const paylink = await this.tropipay.request.post("/api/v3/paymentcards", payload, {
216
+ const paylink = await this.tropipay.request.post("/api/v2/paymentcards", payload, {
224
217
  headers: {
225
218
  "Content-Type": "application/json",
226
219
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -243,7 +236,7 @@ class PaymentCard {
243
236
  await this.tropipay.login();
244
237
  }
245
238
  try {
246
- const paymentcards = await this.tropipay.request.get(`/api/v3/paymentcards`, {
239
+ const paymentcards = await this.tropipay.request.get(`/api/v2/paymentcards`, {
247
240
  headers: {
248
241
  "Content-Type": "application/json",
249
242
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -268,7 +261,7 @@ class PaymentCard {
268
261
  await this.tropipay.login();
269
262
  }
270
263
  try {
271
- const paymentcard = await this.tropipay.request.get(`/api/v3/paymentcards/${id}`, {
264
+ const paymentcard = await this.tropipay.request.get(`/api/v2/paymentcards/${id}`, {
272
265
  headers: {
273
266
  "Content-Type": "application/json",
274
267
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -294,7 +287,7 @@ class PaymentCard {
294
287
  await this.tropipay.login();
295
288
  }
296
289
  try {
297
- const paymentcard = await this.tropipay.request.delete(`/api/v3/paymentcards/`, {
290
+ const paymentcard = await this.tropipay.request.delete(`/api/v2/paymentcards/`, {
298
291
  headers: {
299
292
  "Content-Type": "application/json",
300
293
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -360,7 +353,7 @@ class DepositAccounts {
360
353
  await this.tropipay.login();
361
354
  }
362
355
  try {
363
- const deposit = await this.tropipay.request.get(`/api/v3/deposit_accounts`, {
356
+ const deposit = await this.tropipay.request.get(`/api/v2/deposit_accounts`, {
364
357
  headers: {
365
358
  "Content-Type": "application/json",
366
359
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -383,7 +376,7 @@ class DepositAccounts {
383
376
  await this.tropipay.login();
384
377
  }
385
378
  try {
386
- const deposit = await this.tropipay.request.post("/api/v3/deposit_accounts", depositAccountObj, {
379
+ const deposit = await this.tropipay.request.post("/api/v2/deposit_accounts", depositAccountObj, {
387
380
  headers: {
388
381
  "Content-Type": "application/json",
389
382
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -407,7 +400,7 @@ class DepositAccounts {
407
400
  await this.tropipay.login();
408
401
  }
409
402
  try {
410
- const deposit = await this.tropipay.request.get(`/api/v3/deposit_accounts/${id}`, {
403
+ const deposit = await this.tropipay.request.get(`/api/v2/deposit_accounts/${id}`, {
411
404
  headers: {
412
405
  "Content-Type": "application/json",
413
406
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -430,7 +423,7 @@ class DepositAccounts {
430
423
  await this.tropipay.login();
431
424
  }
432
425
  try {
433
- const deposit = await this.tropipay.request.put(`/api/v3/deposit_accounts/`, {
426
+ const deposit = await this.tropipay.request.put(`/api/v2/deposit_accounts/`, {
434
427
  headers: {
435
428
  "Content-Type": "application/json",
436
429
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -453,7 +446,7 @@ class DepositAccounts {
453
446
  await this.tropipay.login();
454
447
  }
455
448
  try {
456
- const deposit = await this.tropipay.request.delete(`/api/v3/deposit_accounts/${id}`, {
449
+ const deposit = await this.tropipay.request.delete(`/api/v2/deposit_accounts/${id}`, {
457
450
  headers: {
458
451
  "Content-Type": "application/json",
459
452
  Authorization: `Bearer ${Tropipay.accessToken}`,
@@ -468,35 +461,6 @@ class DepositAccounts {
468
461
  }
469
462
  }
470
463
 
471
- class Accounts {
472
- tropipay;
473
- constructor(tropipayInstance) {
474
- this.tropipay = tropipayInstance;
475
- }
476
- /**
477
- * List all accounts of the authenticated user
478
- * @returns Array of Account objects
479
- */
480
- async list() {
481
- if (!Tropipay.accessToken) {
482
- await this.tropipay.login();
483
- }
484
- try {
485
- const accounts = await this.tropipay.request.get(`/api/v3/accounts/`, {
486
- headers: {
487
- "Content-Type": "application/json",
488
- Authorization: `Bearer ${Tropipay.accessToken}`,
489
- Accept: "application/json",
490
- },
491
- });
492
- return accounts.data;
493
- }
494
- catch (error) {
495
- throw handleExceptions(error);
496
- }
497
- }
498
- }
499
-
500
464
  /**
501
465
  * Tropipayjs is a Typescript/Javascript library for the Tropipay API.
502
466
  *
@@ -508,7 +472,6 @@ class Tropipay {
508
472
  clientSecret;
509
473
  scopes;
510
474
  request;
511
- loginRequest;
512
475
  static accessToken;
513
476
  static refreshToken;
514
477
  static expiresIn;
@@ -517,7 +480,6 @@ class Tropipay {
517
480
  paymentCards;
518
481
  depositAccounts;
519
482
  mediationPaymentCard;
520
- accounts;
521
483
  /**
522
484
  * Initializes a new instance of the Tropipay class.
523
485
  *
@@ -536,6 +498,7 @@ class Tropipay {
536
498
  "ALLOW_GET_BALANCE",
537
499
  "ALLOW_GET_MOVEMENT_LIST",
538
500
  "ALLOW_GET_CREDENTIAL",
501
+ "ALLOW_REFUND",
539
502
  ];
540
503
  }
541
504
  else {
@@ -549,8 +512,8 @@ class Tropipay {
549
512
  this.serverMode = config.serverMode || "Development";
550
513
  const tpp_env = this.serverMode === "Production"
551
514
  ? "https://www.tropipay.com"
552
- : "https://sandbox.tropipay.me";
553
- this.request = axios__default["default"].create({
515
+ : "https://tropipay-dev.herokuapp.com";
516
+ this.request = axios.create({
554
517
  baseURL: config.customTropipayUrl || tpp_env,
555
518
  headers: {
556
519
  "Content-Type": "application/json",
@@ -558,28 +521,21 @@ class Tropipay {
558
521
  Authorization: `Bearer ${Tropipay.accessToken}`,
559
522
  },
560
523
  });
561
- // Create a separate instance for login requests
562
- this.loginRequest = axios__default["default"].create({
563
- baseURL: config.customTropipayUrl || tpp_env,
564
- headers: {
565
- "Content-Type": "application/json",
566
- Accept: "application/json",
567
- },
568
- });
569
524
  // Add request interceptor for Token expired
570
525
  this.request.interceptors.request.use(async (config) => {
571
- const currentTimestamp = Math.floor(Date.now() / 1000);
526
+ const currentTimestamp = Math.floor(Date.now() / 1000); // Current time in seconds
572
527
  if (Tropipay.expiresIn && Tropipay.expiresIn < currentTimestamp) {
573
- console.debug("Token expired, attempting to log in");
528
+ // Token has expired, attempt to refresh it
574
529
  try {
575
530
  await this.login();
576
531
  }
577
532
  catch (error) {
533
+ // Handle token refresh error
534
+ Tropipay.accessToken = null;
535
+ Tropipay.refreshToken = null;
578
536
  throw handleExceptions(error);
579
537
  }
580
538
  }
581
- // Update the Authorization header in the config
582
- config.headers.Authorization = `Bearer ${Tropipay.accessToken}`;
583
539
  return config;
584
540
  }, (error) => {
585
541
  return Promise.reject(error);
@@ -588,12 +544,25 @@ class Tropipay {
588
544
  this.paymentCards = new PaymentCard(this);
589
545
  this.mediationPaymentCard = new MediationPaymentCard(this);
590
546
  this.depositAccounts = new DepositAccounts(this);
591
- this.accounts = new Accounts(this);
592
547
  }
593
548
  async login() {
594
549
  try {
550
+ if (Tropipay.refreshToken) {
551
+ const { data } = await this.request.post("/api/v2/access/token", {
552
+ client_id: this.clientId,
553
+ client_secret: this.clientSecret,
554
+ grant_type: "refresh_token",
555
+ refresh_token: Tropipay.refreshToken,
556
+ }, {
557
+ headers: {
558
+ "Content-Type": "application/json",
559
+ Accept: "application/json",
560
+ },
561
+ });
562
+ return data;
563
+ }
595
564
  // normal credetials login
596
- const { data } = await this.loginRequest.post("/api/v3/access/token", {
565
+ const { data } = await this.request.post("/api/v2/access/token", {
597
566
  client_id: this.clientId,
598
567
  client_secret: this.clientSecret,
599
568
  grant_type: "client_credentials",
@@ -605,6 +574,7 @@ class Tropipay {
605
574
  },
606
575
  });
607
576
  Tropipay.accessToken = data.access_token;
577
+ Tropipay.refreshToken = data.refresh_token;
608
578
  Tropipay.expiresIn = data.expires_in;
609
579
  return data;
610
580
  }
@@ -612,7 +582,6 @@ class Tropipay {
612
582
  Tropipay.accessToken = null;
613
583
  Tropipay.refreshToken = null;
614
584
  Tropipay.expiresIn = null;
615
- Tropipay.expiresIn = null;
616
585
  throw handleExceptions(error);
617
586
  }
618
587
  }
@@ -764,6 +733,7 @@ class Tropipay {
764
733
  * belonging or not to the TropiPay platform with the particularity
765
734
  * that the payment will be held in custody or retained until it is
766
735
  * released with the approval of the payer.
736
+ * @deprecated This method is no longer supported and may be removed in a future release.
767
737
  * @see https://tpp.stoplight.io/docs/tropipay-api-doc/12a128ff971e4-creating-a-mediation-payment-card
768
738
  * @param config Payload with the payment details
769
739
  */
@@ -784,6 +754,71 @@ class Tropipay {
784
754
  throw handleExceptions(error);
785
755
  }
786
756
  }
757
+ /**
758
+ * Refund a completed transaction.
759
+ * Requires 2FA enabled and ALLOW_REFUND permission on the Tropipay account.
760
+ *
761
+ * In Development mode, `securityCode` defaults to `"123456"` when omitted.
762
+ * In Production mode, you must first call `requestSecurityCode()` to receive
763
+ * the 2FA code via SMS, then pass it as the `securityCode` parameter.
764
+ *
765
+ * @see https://doc.tropipay.com/docs/api-reference/movements#refund-a-transaction
766
+ * @param orderCode Code of the order/transaction to refund (e.g. "ORD-123456")
767
+ * @param amount Amount to refund in cents (e.g. 5000 = 50.00 USD/EUR)
768
+ * @param securityCode 2FA confirmation code. Use "123456" in Development or
769
+ * the code received via SMS in Production (obtained via requestSecurityCode()).
770
+ */
771
+ async refundMovement(orderCode, amount, securityCode) {
772
+ if (!Tropipay.accessToken) {
773
+ await this.login();
774
+ }
775
+ if (!this.scopes.includes("ALLOW_REFUND")) {
776
+ throw new TropipayJSException("The credential does not have the ALLOW_REFUND scope required to perform refunds. If you believe your account should have this permission, please contact Tropipay support.", 403, null);
777
+ }
778
+ try {
779
+ const response = await this.request.post("/api/v3/movements/in/refund", { orderCode, amount, securityCode }, {
780
+ headers: {
781
+ "Content-Type": "application/json",
782
+ Accept: "application/json",
783
+ Authorization: `Bearer ${Tropipay.accessToken}`,
784
+ },
785
+ });
786
+ return response.data;
787
+ }
788
+ catch (error) {
789
+ throw handleExceptions(error);
790
+ }
791
+ }
792
+ /**
793
+ * Request a 2FA security code to be sent via SMS for confirming sensitive
794
+ * operations like refunds.
795
+ *
796
+ * In Production mode, you must call this method first to trigger an SMS with
797
+ * the code, then use the received code when calling `refundMovement()`.
798
+ * In Development mode this is not required as the default code "123456"
799
+ * is used automatically.
800
+ *
801
+ * @see https://doc.tropipay.com/docs/api-reference/movements#refund-a-transaction
802
+ * @returns The API response confirming the code was sent
803
+ */
804
+ async requestSecurityCode(type = "sms") {
805
+ if (!Tropipay.accessToken) {
806
+ await this.login();
807
+ }
808
+ try {
809
+ const response = await this.request.post("/api/v3/users/sendSecurityCode", { type }, {
810
+ headers: {
811
+ "Content-Type": "application/json",
812
+ Accept: "application/json",
813
+ Authorization: `Bearer ${Tropipay.accessToken}`,
814
+ },
815
+ });
816
+ return response.data;
817
+ }
818
+ catch (error) {
819
+ throw handleExceptions(error);
820
+ }
821
+ }
787
822
  }
788
823
  class ClientSideUtils {
789
824
  constructor(tropipayInstance) {
@@ -799,9 +834,7 @@ class ServerSideUtils {
799
834
  this.tropipay = tropipayInstance;
800
835
  }
801
836
  /**
802
- * DEPRECATED Verify Topipay's signature on API V2 webhooks.
803
- * @deprecated This method is deprecated and will be removed in future versions.
804
- * Use the `verifySignatureV3` method from the `ServerSideUtils` class instead.
837
+ * Verify Topipay's signature on webhooks.
805
838
  * @param credentials Credential object or Tropipay instance
806
839
  * @param {String} originalCurrencyAmount
807
840
  * @param bankOrderCode
@@ -845,7 +878,7 @@ class ServerSideUtils {
845
878
  * @return {Promise<string>} a Promise that resolves to the base64 representation of the file content
846
879
  */
847
880
  static async fileToBase64(filepath) {
848
- const contents = await fs__default["default"].readFile(filepath);
881
+ const contents = await fs.readFile(filepath);
849
882
  let base64content = contents.toString("base64");
850
883
  const ext = filepath.split(".").pop();
851
884
  return `data:image/${ext};base64,` + base64content;
@@ -857,7 +890,7 @@ class ServerSideUtils {
857
890
  * @return {Promise<string>} the base64 representation of the file
858
891
  */
859
892
  static async getBase64FromFileUrl(url) {
860
- const response = await axios__default["default"].get(url, {
893
+ const response = await axios.get(url, {
861
894
  responseType: "arraybuffer",
862
895
  maxRedirects: 5,
863
896
  });
@@ -891,28 +924,6 @@ class ServerSideUtils {
891
924
  throw new Error(`Error checking base64 image`);
892
925
  }
893
926
  }
894
- /**
895
- * Verify Topipay's signature on API V3 webhooks.
896
- * @param {string} originalCurrencyAmount
897
- * @param {string} bankOrderCode
898
- * @param {string} signature signaturev3 field to be verified
899
- * @returns {boolean}
900
- */
901
- static verifySignatureV3(credentials, originalCurrencyAmount, bankOrderCode, signature) {
902
- const sha1Secret = crypto__namespace
903
- .createHash("sha1")
904
- .update(credentials.clientSecret)
905
- .digest("hex");
906
- const dataToHash = bankOrderCode +
907
- credentials.clientId +
908
- sha1Secret +
909
- originalCurrencyAmount;
910
- const localSignature = crypto__namespace
911
- .createHash("sha256")
912
- .update(dataToHash)
913
- .digest("hex");
914
- return localSignature === signature;
915
- }
916
927
  }
917
928
 
918
929
  const SERVER_MODE = "Development"; // Move the constant here
@@ -35,71 +35,36 @@ export interface UserHookSubscribed extends UserHook {
35
35
  createdAt: string;
36
36
  updatedAt: string;
37
37
  }
38
- /**
39
- * Interface for creating payment links/cards
40
- * @see https://tpp.stoplight.io/docs/tropipay-api-doc/b3A6ODgyNTM3OQ-create-a-new-pay-link-charge
41
- */
42
38
  export interface PaymentLinkPayload {
43
- /** Account ID where the funds will be received if compatible */
44
- accountId?: number;
45
- /** Reference code for the payment, preferred to be unique */
46
39
  reference: string;
47
- /** Short description of the payment */
48
40
  concept: string;
49
- /** Whether to mark this payment link as favorite */
50
41
  favorite: boolean;
51
- /** Amount to charge in the specified currency */
52
42
  amount: number;
53
- /** Currency code (EUR, USD, etc.) */
54
43
  currency: string;
55
- /** Detailed description of the payment */
56
44
  description: string;
57
- /** If true, the payment link can only be used once */
58
45
  singleUse: boolean;
59
- /** Reason ID for the payment */
60
46
  reasonId: number;
61
- /** Number of days until the payment link expires */
62
47
  expirationDays: number;
63
- /** Language code for the payment page (en, es, etc.) */
64
48
  lang: string;
65
- /** URL to redirect after successful payment */
66
49
  urlSuccess: string;
67
- /** URL to redirect after failed payment */
68
50
  urlFailed: string;
69
- /** Webhook URL for payment notifications */
70
51
  urlNotification: string;
71
- /** Date when the service will be provided (ISO format) */
72
52
  serviceDate: string;
73
- /** Client information for the payment */
74
53
  client?: {
75
- /** Client's first name */
76
54
  name?: string;
77
- /** Client's last name */
78
55
  lastName?: string;
79
- /** Client's address */
80
56
  address?: string;
81
- /** Client's phone number */
82
57
  phone?: string;
83
- /** Client's email address */
84
58
  email?: string;
85
- /** Client's country ID */
86
59
  countryId?: number;
87
- /** Client's country ISO code */
88
60
  countryIso?: string;
89
- /** Client's city */
90
61
  city: string;
91
- /** Client's postal code */
92
62
  postCode: string;
93
- /** Whether client accepted terms and conditions */
94
63
  termsAndConditions: boolean;
95
64
  } | null;
96
- /** @deprecated If true, redirects directly to payment page */
97
65
  directPayment: boolean;
98
- /** List of allowed payment methods */
99
66
  paymentMethods?: string[];
100
- /** Base64 encoded image for the payment page */
101
67
  imageBase?: string;
102
- /** Whether to save the payment token for future use */
103
68
  saveToken?: boolean;
104
69
  }
105
70
  export interface PaymentLink extends PaymentLinkPayload {
@@ -199,3 +164,13 @@ export type AccountDeposits = {
199
164
  count: number;
200
165
  rows: Deposit[];
201
166
  };
167
+ export type RefundResponse = {
168
+ id: number;
169
+ orderCode: string;
170
+ amount: number;
171
+ currency: string;
172
+ state: string;
173
+ type: string;
174
+ createdAt: string;
175
+ completedAt: string;
176
+ };
@@ -46,7 +46,6 @@ declare enum Reasons {
46
46
  SENDING_YOU_A_KISS = 80
47
47
  }
48
48
  export interface PaymentLinkPayload {
49
- accountId: number;
50
49
  reference: string;
51
50
  concept: string;
52
51
  favorite: boolean;
@@ -61,6 +60,9 @@ export interface PaymentLinkPayload {
61
60
  urlFailed: string;
62
61
  urlNotification: string;
63
62
  serviceDate: string;
63
+ /**
64
+ * fgfsgdfgdfgd
65
+ */
64
66
  client?: {
65
67
  name: string;
66
68
  lastName: string;
package/package.json CHANGED
@@ -1,18 +1,21 @@
1
1
  {
2
2
  "name": "@yosle/tropipayjs",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Javascript / Typescript SDK for the Tropipay API",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "jest --passWithNoTests --updateSnapshot --coverage",
8
- "_clear": "rimraf src/dist/*",
8
+ "_clear": "rimraf src/dist",
9
9
  "_tsc": "tsc",
10
10
  "_make-bundle": "rollup --config",
11
11
  "build": "npm run _clear && npm run _tsc && npm run _make-bundle"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
15
- "url": "https://github.com/yosle/tropipayjs"
15
+ "url": "git+https://github.com/yosle/tropipayjs.git"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
16
19
  },
17
20
  "keywords": [
18
21
  "Javascript",
@@ -25,22 +28,21 @@
25
28
  "author": "Yosleivy Baez Acosta <yosle007@gmail.com>",
26
29
  "license": "MIT",
27
30
  "dependencies": {
28
- "axios": "^1.6.0",
29
- "tslib": "^2.4.0"
31
+ "axios": "^1.18.1",
32
+ "tslib": "^2.8.1"
30
33
  },
31
34
  "devDependencies": {
32
- "@rollup/plugin-typescript": "^8.5.0",
35
+ "@rollup/plugin-typescript": "^12.3.0",
33
36
  "@types/jest": "^29.5.12",
34
37
  "@types/node": "^20.12.7",
35
38
  "@types/tough-cookie": "^4.0.5",
36
39
  "babel-jest": "^29.7.0",
37
40
  "jest": "^29.7.0",
38
- "rimraf": "^3.0.2",
39
- "rollup": "^2.79.1",
40
- "rollup-plugin-dts": "^4.2.2",
41
- "run-s": "^0.0.0",
42
- "ts-jest": "^29.1.2",
43
- "typescript": "^5.4.5"
41
+ "rimraf": "^6.1.3",
42
+ "rollup": "^4.62.2",
43
+ "rollup-plugin-dts": "^6.4.1",
44
+ "ts-jest": "^29.4.11",
45
+ "typescript": "^6.0.3"
44
46
  },
45
47
  "funding": {
46
48
  "type": "individual",
@@ -0,0 +1 @@
1
+ declare function sum(a: number, b: number): number;
package/rollup.config.js CHANGED
@@ -1,6 +1,5 @@
1
- // Contents of the file /rollup.config.js
2
- import typescript from "@rollup/plugin-typescript";
3
- import dts from "rollup-plugin-dts";
1
+ import { dts } from "rollup-plugin-dts";
2
+
4
3
  const config = [
5
4
  {
6
5
  input: "dist/index.js",
@@ -10,7 +9,6 @@ const config = [
10
9
  sourcemap: true,
11
10
  },
12
11
  external: ["axios", "crypto", "fs/promises"],
13
- plugins: [typescript()],
14
12
  },
15
13
  {
16
14
  input: "dist/index.d.ts",
@@ -21,4 +19,5 @@ const config = [
21
19
  plugins: [dts()],
22
20
  },
23
21
  ];
22
+
24
23
  export default config;