@yosle/tropipayjs 0.2.1 → 0.2.2

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.
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@yosle/tropipayjs",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Javascript / Typescript SDK for the Tropipay API",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -12,7 +12,10 @@
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",
@@ -0,0 +1 @@
1
+ declare function sum(a: number, b: number): number;
@@ -15,6 +15,7 @@ import {
15
15
  MediationPaymentCardConfig,
16
16
  LoginResponse,
17
17
  AccountDeposits,
18
+ RefundResponse,
18
19
  } from "../interfaces";
19
20
  type ServerMode = "Development" | "Production";
20
21
  import TropipayHooks from "../hooks/TropipayHooks";
@@ -22,13 +23,11 @@ import PaymentCard from "../paymentcard/PaymentCard";
22
23
  import MediationPaymentCard from "../mediationPaymentCard/MediationPaymentCard";
23
24
  import DepositAccounts from "../depositAccount/depositAccounts";
24
25
  import { TropipayJSException, handleExceptions } from "../utils/errors";
25
- import Accounts from "../accounts/accounts";
26
26
  export class Tropipay {
27
27
  readonly clientId: string;
28
28
  readonly clientSecret: string;
29
29
  readonly scopes: String[];
30
30
  public request: Axios;
31
- public loginRequest: Axios;
32
31
  public static accessToken: string | null;
33
32
  public static refreshToken: string | null;
34
33
  public static expiresIn: number | null;
@@ -37,7 +36,6 @@ export class Tropipay {
37
36
  public paymentCards: PaymentCard;
38
37
  public depositAccounts: DepositAccounts;
39
38
  public mediationPaymentCard: MediationPaymentCard;
40
- public accounts: Accounts;
41
39
 
42
40
  /**
43
41
  * Initializes a new instance of the Tropipay class.
@@ -58,6 +56,7 @@ export class Tropipay {
58
56
  "ALLOW_GET_BALANCE",
59
57
  "ALLOW_GET_MOVEMENT_LIST",
60
58
  "ALLOW_GET_CREDENTIAL",
59
+ "ALLOW_REFUND",
61
60
  ];
62
61
  } else {
63
62
  this.scopes = config.scopes;
@@ -75,12 +74,11 @@ export class Tropipay {
75
74
  this.clientSecret = config.clientSecret;
76
75
  this.serverMode = config.serverMode || "Development";
77
76
 
78
- const tpp_env =
79
- this.serverMode === "Production"
80
- ? "https://www.tropipay.com"
81
- : "https://sandbox.tropipay.me";
77
+ const tpp_env = this.serverMode === "Production"
78
+ ? "https://www.tropipay.com"
79
+ : "https://tropipay-dev.herokuapp.com";
82
80
  this.request = axios.create({
83
- baseURL: config.customTropipayUrl || tpp_env,
81
+ baseURL: config.customTropipayUrl || tpp_env,
84
82
  headers: {
85
83
  "Content-Type": "application/json",
86
84
  Accept: "application/json",
@@ -88,33 +86,27 @@ export class Tropipay {
88
86
  },
89
87
  });
90
88
 
91
- // Create a separate instance for login requests
92
- this.loginRequest = axios.create({
93
- baseURL: config.customTropipayUrl || tpp_env,
94
- headers: {
95
- "Content-Type": "application/json",
96
- Accept: "application/json",
97
- },
98
- });
99
89
 
100
- // Add request interceptor for Token expired
101
- this.request.interceptors.request.use(
102
- async (config) => {
103
- const currentTimestamp = Math.floor(Date.now() / 1000);
90
+ // Add request interceptor for Token expired
91
+ this.request.interceptors.request.use(
92
+ async (config: any) => {
93
+ const currentTimestamp = Math.floor(Date.now() / 1000); // Current time in seconds
104
94
 
105
95
  if (Tropipay.expiresIn && Tropipay.expiresIn < currentTimestamp) {
106
- console.debug("Token expired, attempting to log in");
96
+ // Token has expired, attempt to refresh it
107
97
  try {
108
- await this.login();
98
+ await this.login();
109
99
  } catch (error) {
110
- throw handleExceptions(error as Error);
100
+ // Handle token refresh error
101
+ Tropipay.accessToken = null;
102
+ Tropipay.refreshToken = null;
103
+ throw handleExceptions(error as any);
111
104
  }
112
105
  }
113
- // Update the Authorization header in the config
114
- config.headers.Authorization = `Bearer ${Tropipay.accessToken}`;
106
+
115
107
  return config;
116
108
  },
117
- (error) => {
109
+ (error: AxiosError) => {
118
110
  return Promise.reject(error);
119
111
  }
120
112
  );
@@ -124,14 +116,34 @@ export class Tropipay {
124
116
  this.mediationPaymentCard = new MediationPaymentCard(this);
125
117
 
126
118
  this.depositAccounts = new DepositAccounts(this);
127
- this.accounts = new Accounts(this)
119
+
120
+
128
121
  }
129
122
 
130
123
  public async login() {
131
124
  try {
125
+ if (Tropipay.refreshToken) {
126
+ const { data } = await this.request.post<LoginResponse>(
127
+ "/api/v2/access/token",
128
+ {
129
+ client_id: this.clientId,
130
+ client_secret: this.clientSecret,
131
+ grant_type: "refresh_token",
132
+ refresh_token: Tropipay.refreshToken,
133
+ },
134
+ {
135
+ headers: {
136
+ "Content-Type": "application/json",
137
+ Accept: "application/json",
138
+ },
139
+ }
140
+ );
141
+ return data;
142
+ }
143
+
132
144
  // normal credetials login
133
- const { data } = await this.loginRequest.post<LoginResponse>(
134
- "/api/v3/access/token",
145
+ const { data } = await this.request.post<LoginResponse>(
146
+ "/api/v2/access/token",
135
147
  {
136
148
  client_id: this.clientId,
137
149
  client_secret: this.clientSecret,
@@ -147,13 +159,13 @@ export class Tropipay {
147
159
  );
148
160
 
149
161
  Tropipay.accessToken = data.access_token;
162
+ Tropipay.refreshToken = data.refresh_token;
150
163
  Tropipay.expiresIn = data.expires_in;
151
164
  return data;
152
165
  } catch (error) {
153
166
  Tropipay.accessToken = null;
154
167
  Tropipay.refreshToken = null;
155
168
  Tropipay.expiresIn = null;
156
- Tropipay.expiresIn = null;
157
169
  throw handleExceptions(error as any);
158
170
  }
159
171
  }
@@ -316,6 +328,7 @@ export class Tropipay {
316
328
  * belonging or not to the TropiPay platform with the particularity
317
329
  * that the payment will be held in custody or retained until it is
318
330
  * released with the approval of the payer.
331
+ * @deprecated This method is no longer supported and may be removed in a future release.
319
332
  * @see https://tpp.stoplight.io/docs/tropipay-api-doc/12a128ff971e4-creating-a-mediation-payment-card
320
333
  * @param config Payload with the payment details
321
334
  */
@@ -340,6 +353,91 @@ export class Tropipay {
340
353
  throw handleExceptions(error as any);
341
354
  }
342
355
  }
356
+
357
+ /**
358
+ * Refund a completed transaction.
359
+ * Requires 2FA enabled and ALLOW_REFUND permission on the Tropipay account.
360
+ *
361
+ * In Development mode, `securityCode` defaults to `"123456"` when omitted.
362
+ * In Production mode, you must first call `requestSecurityCode()` to receive
363
+ * the 2FA code via SMS, then pass it as the `securityCode` parameter.
364
+ *
365
+ * @see https://doc.tropipay.com/docs/api-reference/movements#refund-a-transaction
366
+ * @param orderCode Code of the order/transaction to refund (e.g. "ORD-123456")
367
+ * @param amount Amount to refund in cents (e.g. 5000 = 50.00 USD/EUR)
368
+ * @param securityCode 2FA confirmation code. Use "123456" in Development or
369
+ * the code received via SMS in Production (obtained via requestSecurityCode()).
370
+ */
371
+ async refundMovement(
372
+ orderCode: string,
373
+ amount: number,
374
+ securityCode: string
375
+ ): Promise<RefundResponse> {
376
+ if (!Tropipay.accessToken) {
377
+ await this.login();
378
+ }
379
+
380
+ if (!this.scopes.includes("ALLOW_REFUND")) {
381
+ throw new TropipayJSException(
382
+ "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.",
383
+ 403,
384
+ null
385
+ );
386
+ }
387
+
388
+ try {
389
+ const response = await this.request.post(
390
+ "/api/v3/movements/in/refund",
391
+ { orderCode, amount, securityCode },
392
+ {
393
+ headers: {
394
+ "Content-Type": "application/json",
395
+ Accept: "application/json",
396
+ Authorization: `Bearer ${Tropipay.accessToken}`,
397
+ },
398
+ }
399
+ );
400
+ return response.data as RefundResponse;
401
+ } catch (error) {
402
+ throw handleExceptions(error as any);
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Request a 2FA security code to be sent via SMS for confirming sensitive
408
+ * operations like refunds.
409
+ *
410
+ * In Production mode, you must call this method first to trigger an SMS with
411
+ * the code, then use the received code when calling `refundMovement()`.
412
+ * In Development mode this is not required as the default code "123456"
413
+ * is used automatically.
414
+ *
415
+ * @see https://doc.tropipay.com/docs/api-reference/movements#refund-a-transaction
416
+ * @returns The API response confirming the code was sent
417
+ */
418
+ async requestSecurityCode(type: "sms" | "email" = "sms"): Promise<any> {
419
+ if (!Tropipay.accessToken) {
420
+ await this.login();
421
+ }
422
+
423
+ try {
424
+ const response = await this.request.post(
425
+ "/api/v3/users/sendSecurityCode",
426
+ { type },
427
+ {
428
+ headers: {
429
+ "Content-Type": "application/json",
430
+ Accept: "application/json",
431
+ Authorization: `Bearer ${Tropipay.accessToken}`,
432
+ },
433
+ }
434
+ );
435
+ return response.data;
436
+ } catch (error) {
437
+ throw handleExceptions(error as any);
438
+ }
439
+ }
440
+
343
441
  }
344
442
 
345
443
  export class ClientSideUtils {
@@ -357,4 +455,5 @@ export const Scopes = {
357
455
  ALLOW_GET_BALANCE: "ALLOW_GET_BALANCE",
358
456
  ALLOW_GET_MOVEMENT_LIST: "ALLOW_GET_MOVEMENT_LIST",
359
457
  ALLOW_GET_CREDENTIAL: "ALLOW_GET_CREDENTIAL",
458
+ ALLOW_REFUND: "ALLOW_REFUND",
360
459
  };
@@ -18,7 +18,7 @@ export default class DepositAccounts {
18
18
  }
19
19
  try {
20
20
  const deposit = await this.tropipay.request.get(
21
- `/api/v3/deposit_accounts`,
21
+ `/api/v2/deposit_accounts`,
22
22
  {
23
23
  headers: {
24
24
  "Content-Type": "application/json",
@@ -43,7 +43,7 @@ export default class DepositAccounts {
43
43
  }
44
44
  try {
45
45
  const deposit = await this.tropipay.request.post(
46
- "/api/v3/deposit_accounts",
46
+ "/api/v2/deposit_accounts",
47
47
  depositAccountObj,
48
48
  {
49
49
  headers: {
@@ -70,7 +70,7 @@ export default class DepositAccounts {
70
70
  }
71
71
  try {
72
72
  const deposit = await this.tropipay.request.get(
73
- `/api/v3/deposit_accounts/${id}`,
73
+ `/api/v2/deposit_accounts/${id}`,
74
74
  {
75
75
  headers: {
76
76
  "Content-Type": "application/json",
@@ -96,7 +96,7 @@ export default class DepositAccounts {
96
96
  }
97
97
  try {
98
98
  const deposit = await this.tropipay.request.put(
99
- `/api/v3/deposit_accounts/`,
99
+ `/api/v2/deposit_accounts/`,
100
100
  {
101
101
  headers: {
102
102
  "Content-Type": "application/json",
@@ -122,7 +122,7 @@ export default class DepositAccounts {
122
122
  }
123
123
  try {
124
124
  const deposit = await this.tropipay.request.delete(
125
- `/api/v3/deposit_accounts/${id}`,
125
+ `/api/v2/deposit_accounts/${id}`,
126
126
  {
127
127
  headers: {
128
128
  "Content-Type": "application/json",
package/src/index.ts CHANGED
@@ -26,3 +26,4 @@ export * from "./depositAccount/depositAccounts";
26
26
  export * from "./interfaces/index";
27
27
  export { SERVER_MODE } from "./config/TropipayConfig";
28
28
  export * from "./constants/TropipayConstants";
29
+ export type { RefundResponse } from "./interfaces/index";