cloudcommerce 2.11.2 → 2.12.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.
Files changed (107) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/ecomplus-stores/barradoce/functions/many/package.json +3 -3
  3. package/ecomplus-stores/barradoce/functions/ssr/content/pages/home.json +50 -86
  4. package/ecomplus-stores/barradoce/functions/ssr/package.json +6 -6
  5. package/ecomplus-stores/barradoce/functions/ssr/public/img/uploads/banner-pistache.jpg +0 -0
  6. package/ecomplus-stores/barradoce/functions/ssr/src/components/Banner.vue +7 -8
  7. package/ecomplus-stores/barradoce/functions/with-apps/package.json +3 -3
  8. package/ecomplus-stores/barradoce/package.json +2 -2
  9. package/package.json +4 -4
  10. package/packages/__skeleton/package.json +2 -1
  11. package/packages/api/lib/api.d.ts +1 -4
  12. package/packages/api/package.json +2 -2
  13. package/packages/apps/affiliate-program/lib/affiliate-program.js +1 -1
  14. package/packages/apps/affiliate-program/lib/affiliate-program.js.map +1 -1
  15. package/packages/apps/affiliate-program/package.json +2 -2
  16. package/packages/apps/affiliate-program/src/affiliate-program.ts +1 -1
  17. package/packages/apps/correios/package.json +2 -2
  18. package/packages/apps/custom-payment/package.json +2 -2
  19. package/packages/apps/custom-shipping/package.json +2 -2
  20. package/packages/apps/datafrete/package.json +2 -2
  21. package/packages/apps/discounts/package.json +2 -2
  22. package/packages/apps/emails/package.json +2 -2
  23. package/packages/apps/fb-conversions/package.json +2 -2
  24. package/packages/apps/flash-courier/package.json +2 -2
  25. package/packages/apps/frenet/package.json +2 -2
  26. package/packages/apps/galaxpay/package.json +3 -2
  27. package/packages/apps/google-analytics/package.json +2 -2
  28. package/packages/apps/jadlog/package.json +2 -2
  29. package/packages/apps/loyalty-points/package.json +2 -2
  30. package/packages/apps/mandae/package.json +2 -2
  31. package/packages/apps/melhor-envio/package.json +2 -2
  32. package/packages/apps/mercadopago/package.json +3 -2
  33. package/packages/apps/pagaleve/CHANGELOG.md +1 -0
  34. package/packages/apps/pagaleve/README.md +1 -0
  35. package/packages/apps/pagaleve/lib/index.d.ts +1 -0
  36. package/packages/apps/pagaleve/lib/index.js +3 -0
  37. package/packages/apps/pagaleve/lib/index.js.map +1 -0
  38. package/packages/apps/pagaleve/lib/pagaleve-constructor.d.ts +6 -0
  39. package/packages/apps/pagaleve/lib/pagaleve-constructor.js +78 -0
  40. package/packages/apps/pagaleve/lib/pagaleve-constructor.js.map +1 -0
  41. package/packages/apps/pagaleve/lib/pagaleve-create-transaction.d.ts +7 -0
  42. package/packages/apps/pagaleve/lib/pagaleve-create-transaction.js +148 -0
  43. package/packages/apps/pagaleve/lib/pagaleve-create-transaction.js.map +1 -0
  44. package/packages/apps/pagaleve/lib/pagaleve-list-payments.d.ts +7 -0
  45. package/packages/apps/pagaleve/lib/pagaleve-list-payments.js +113 -0
  46. package/packages/apps/pagaleve/lib/pagaleve-list-payments.js.map +1 -0
  47. package/packages/apps/pagaleve/lib/pagaleve-webhook.d.ts +4 -0
  48. package/packages/apps/pagaleve/lib/pagaleve-webhook.js +135 -0
  49. package/packages/apps/pagaleve/lib/pagaleve-webhook.js.map +1 -0
  50. package/packages/apps/pagaleve/lib/pagaleve.d.ts +12 -0
  51. package/packages/apps/pagaleve/lib/pagaleve.js +12 -0
  52. package/packages/apps/pagaleve/lib/pagaleve.js.map +1 -0
  53. package/packages/apps/pagaleve/package.json +43 -0
  54. package/packages/apps/pagaleve/src/index.ts +2 -0
  55. package/packages/apps/pagaleve/src/pagaleve-constructor.ts +85 -0
  56. package/packages/apps/pagaleve/src/pagaleve-create-transaction.ts +161 -0
  57. package/packages/apps/pagaleve/src/pagaleve-list-payments.ts +122 -0
  58. package/packages/apps/pagaleve/src/pagaleve-webhook.ts +150 -0
  59. package/packages/apps/pagaleve/src/pagaleve.ts +12 -0
  60. package/packages/apps/pagaleve/tsconfig.json +6 -0
  61. package/packages/apps/pagaleve/webhook.js +1 -0
  62. package/packages/apps/pagarme/package.json +3 -2
  63. package/packages/apps/pagarme-v5/lib/pagarme-v5-events.d.ts +1 -1
  64. package/packages/apps/pagarme-v5/lib/pagarme-v5-events.js +2 -2
  65. package/packages/apps/pagarme-v5/lib/pagarme-v5-events.js.map +1 -1
  66. package/packages/apps/pagarme-v5/lib-mjs/{pagarme5-webhooks.mjs → pagarme5-webhook.mjs} +0 -1
  67. package/packages/apps/pagarme-v5/package.json +3 -2
  68. package/packages/apps/pagarme-v5/src/pagarme-v5-events.ts +2 -2
  69. package/packages/apps/paghiper/package.json +2 -2
  70. package/packages/apps/pix/package.json +2 -2
  71. package/packages/apps/tiny-erp/package.json +2 -2
  72. package/packages/apps/webhooks/lib/app-webhooks.js +2 -2
  73. package/packages/apps/webhooks/lib/app-webhooks.js.map +1 -1
  74. package/packages/apps/webhooks/lib/{events-to-webhooks-app.js → events-to-webhooks.js} +1 -1
  75. package/packages/apps/webhooks/lib/events-to-webhooks.js.map +1 -0
  76. package/packages/apps/webhooks/package.json +2 -2
  77. package/packages/apps/webhooks/src/app-webhooks.ts +2 -2
  78. package/packages/cli/package.json +3 -3
  79. package/packages/config/package.json +2 -2
  80. package/packages/emails/package.json +2 -2
  81. package/packages/eslint/package.json +2 -2
  82. package/packages/events/lib/firebase.js +2 -0
  83. package/packages/events/lib/firebase.js.map +1 -1
  84. package/packages/events/package.json +3 -2
  85. package/packages/events/src/firebase.ts +2 -0
  86. package/packages/feeds/package.json +2 -2
  87. package/packages/firebase/lib/config.d.ts +3 -0
  88. package/packages/firebase/lib/config.js +3 -0
  89. package/packages/firebase/lib/config.js.map +1 -1
  90. package/packages/firebase/package.json +2 -2
  91. package/packages/firebase/src/config.ts +3 -0
  92. package/packages/i18n/package.json +2 -2
  93. package/packages/modules/lib/firebase/call-app-module.js +12 -0
  94. package/packages/modules/lib/firebase/call-app-module.js.map +1 -1
  95. package/packages/modules/package.json +3 -2
  96. package/packages/modules/src/firebase/call-app-module.ts +12 -0
  97. package/packages/passport/lib/firebase.js +20 -22
  98. package/packages/passport/lib/firebase.js.map +1 -1
  99. package/packages/passport/package.json +2 -2
  100. package/packages/passport/src/firebase.ts +25 -25
  101. package/packages/ssr/package.json +3 -3
  102. package/packages/storefront/package.json +2 -2
  103. package/packages/test-base/package.json +2 -2
  104. package/packages/types/package.json +2 -2
  105. package/ecomplus-stores/barradoce/functions/ssr/public/img/uploads/banner-forma-decora.jpg +0 -0
  106. package/packages/apps/webhooks/lib/events-to-webhooks-app.js.map +0 -1
  107. /package/packages/apps/webhooks/src/{events-to-webhooks-app.ts → events-to-webhooks.ts} +0 -0
@@ -0,0 +1,85 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ import axios from 'axios';
3
+ import { getFirestore, Timestamp } from 'firebase-admin/firestore';
4
+ import logger from 'firebase-functions/logger';
5
+
6
+ const createAxios = (token?: string | null, isSandbox = false) => {
7
+ const headers = {
8
+ 'Content-Type': 'application/json',
9
+ 'Idempotency-Key': `${Date.now() + Math.random()}`,
10
+ Authorization: token,
11
+ };
12
+ const baseURL = isSandbox
13
+ ? 'https://sandbox-api.pagaleve.io'
14
+ : 'https://api.pagaleve.com.br';
15
+ return axios.create({
16
+ baseURL,
17
+ headers,
18
+ validateStatus(status) {
19
+ return status >= 200 && status <= 301;
20
+ },
21
+ });
22
+ };
23
+
24
+ const createToken = (username: string, password: string, isSandbox = false) => {
25
+ return new Promise((resolve, reject) => {
26
+ // https://api-docs.addi-staging-br.com/#/Authentication/createAuthToken
27
+ const pagaleveAxios = createAxios(null, isSandbox);
28
+ const request = (isRetry = false) => {
29
+ pagaleveAxios.post('/v1/authentication', { username, password })
30
+ .then(({ data }) => resolve(data))
31
+ .catch((err) => {
32
+ if (!isRetry && err.response && err.response.status >= 429) {
33
+ setTimeout(() => request(true), 7000);
34
+ }
35
+ reject(err);
36
+ });
37
+ };
38
+ request();
39
+ });
40
+ };
41
+
42
+ const Pagaleve = function newPagaleve(
43
+ this: { preparing: Promise<void>, axios: AxiosInstance },
44
+ username: string,
45
+ password: string,
46
+ isSandbox = false,
47
+ ) {
48
+ const self = this;
49
+ const documentRef = getFirestore().doc('pagaleve/token');
50
+ this.preparing = new Promise((resolve, reject) => {
51
+ const authenticate = (token: string) => {
52
+ self.axios = createAxios(token, isSandbox);
53
+ resolve();
54
+ };
55
+ const handleAuth = () => {
56
+ createToken(username, password, isSandbox)
57
+ .then((data: any) => {
58
+ authenticate(data.token);
59
+ if (documentRef) {
60
+ documentRef.set({
61
+ ...data,
62
+ isSandbox,
63
+ updatedAt: Timestamp.now(),
64
+ }).catch(logger.error);
65
+ }
66
+ })
67
+ .catch(reject);
68
+ };
69
+ documentRef.get()
70
+ .then((documentSnapshot) => {
71
+ const data = documentSnapshot.data();
72
+ if (data) {
73
+ const updatedAt = (data.updatedAt as Timestamp).toMillis();
74
+ if (updatedAt && Date.now() - updatedAt <= 50 * 60 * 1000) {
75
+ authenticate(data!.token);
76
+ return;
77
+ }
78
+ }
79
+ handleAuth();
80
+ })
81
+ .catch(logger.error);
82
+ });
83
+ };
84
+
85
+ export default Pagaleve;
@@ -0,0 +1,161 @@
1
+ import type {
2
+ AppModuleBody,
3
+ CreateTransactionResponse,
4
+ } from '@cloudcommerce/types';
5
+ import { createHmac } from 'node:crypto';
6
+ import logger from 'firebase-functions/logger';
7
+ import { img as getImg } from '@ecomplus/utils';
8
+ import config from '@cloudcommerce/firebase/lib/config';
9
+ import Pagaleve from './pagaleve-constructor';
10
+
11
+ const { region } = config.get().httpsFunctionOptions;
12
+ const baseUri = `https://${region}-${process.env.GCLOUD_PROJECT}.cloudfunctions.net`;
13
+
14
+ const pagaleveCreateTransaction = async (body: AppModuleBody<'create_transaction'>) => {
15
+ const { params, application } = body;
16
+ const appData = { ...application.data, ...application.hidden_data };
17
+ const {
18
+ PAGALEVE_USERNAME,
19
+ PAGALEVE_PASSWORD,
20
+ PAGALEVE_SANDBOX,
21
+ } = process.env;
22
+ if (PAGALEVE_USERNAME) appData.username = PAGALEVE_USERNAME;
23
+ if (PAGALEVE_PASSWORD) appData.password = PAGALEVE_PASSWORD;
24
+ const isSandbox = !!PAGALEVE_SANDBOX;
25
+ const pagaleve = new Pagaleve(appData.username, appData.password, isSandbox);
26
+
27
+ const orderId = params.order_id || '';
28
+ const orderNumber = params.order_number;
29
+ const { amount, buyer, items } = params;
30
+ const isPix = params.payment_method.code === 'account_deposit';
31
+ const transaction: CreateTransactionResponse['transaction'] = {
32
+ intermediator: {
33
+ payment_method: params.payment_method,
34
+ },
35
+ currency_id: params.currency_id,
36
+ currency_symbol: params.currency_symbol,
37
+ amount: amount.total,
38
+ status: {
39
+ current: 'pending',
40
+ },
41
+ };
42
+ const finalAmount = Math.floor(amount.total * 100);
43
+ const finalFreight = amount.freight ? Math.floor(amount.freight * 100) : 0;
44
+
45
+ const parseAddress = (_to: Exclude<(typeof params)['to'], undefined>) => ({
46
+ name: _to.name,
47
+ city: _to.city,
48
+ state: _to.province_code,
49
+ street: _to.street,
50
+ zip_code: _to.zip,
51
+ neighborhood: _to.borough,
52
+ number: String(_to.number) || 's/n',
53
+ complement: _to.complement || undefined,
54
+ });
55
+ const shippingAddr = params.to && parseAddress(params.to);
56
+ const billingAddr = params.billing_address
57
+ ? parseAddress(params.billing_address)
58
+ : shippingAddr;
59
+
60
+ const hash = createHmac('sha256', appData.password)
61
+ .update(orderId).digest('hex');
62
+ const pagaleveTransaction: Record<string, any> = {
63
+ cancel_url: `https://${params.domain}/app/#/order/${orderNumber}/${orderId}`,
64
+ approve_url: `https://${params.domain}/app/#/order/${orderNumber}/${orderId}`,
65
+ webhook_url: `${baseUri}/pagaleve-webhook?order_id=${orderId}&hash=${hash}`,
66
+ is_pix_upfront: !!isPix,
67
+ order: {
68
+ reference: orderId,
69
+ description: `Order from e-com.plus ${orderNumber}`,
70
+ shipping: {
71
+ amount: finalFreight || 0,
72
+ address: shippingAddr,
73
+ },
74
+ amount: finalAmount,
75
+ items: [],
76
+ timestamp: new Date().toISOString(),
77
+ type: 'ORDINARY',
78
+ },
79
+ shopper: {
80
+ cpf: String(buyer.doc_number),
81
+ first_name: buyer.fullname.replace(/\s.*/, ''),
82
+ last_name: buyer.fullname.replace(/[^\s]+\s/, ''),
83
+ email: buyer.email,
84
+ phone: buyer.phone.number,
85
+ billing_address: billingAddr,
86
+ },
87
+ };
88
+ let totalQuantity = 0;
89
+ items.forEach((item) => {
90
+ if (item.quantity > 0) {
91
+ totalQuantity += item.quantity;
92
+ const objImg = getImg(item);
93
+ pagaleveTransaction.order.items.push({
94
+ name: item.name || item.sku,
95
+ sku: item.sku,
96
+ quantity: item.quantity,
97
+ price: Math.floor((item.final_price || item.price) * 100),
98
+ url: `https://${params.domain}`,
99
+ reference: item.product_id,
100
+ image: objImg && objImg.url ? objImg.url : `https://${params.domain}`,
101
+ });
102
+ }
103
+ });
104
+ const birthDate = buyer.birth_date;
105
+ if (birthDate && birthDate.year && birthDate.month && birthDate.day) {
106
+ pagaleveTransaction.birth_date = `${birthDate.year}-`
107
+ + `${birthDate.month.toString().padStart(2, '0')}-`
108
+ + birthDate.day.toString().padStart(2, '0');
109
+ }
110
+
111
+ if (totalQuantity > 0) {
112
+ try {
113
+ await pagaleve.preparing;
114
+ const { data } = pagaleve.axios.post('/v1/checkouts', pagaleveTransaction, {
115
+ maxRedirects: 0,
116
+ });
117
+ transaction.payment_link = data.redirect_url || data.checkout_url;
118
+ if (isPix && data.timestamp) {
119
+ transaction.account_deposit = {
120
+ valid_thru: data.timestamp,
121
+ };
122
+ }
123
+ return {
124
+ redirect_to_payment: true,
125
+ transaction,
126
+ } as CreateTransactionResponse;
127
+ } catch (error: any) {
128
+ const errCode = 'PAGALEVE_TRANSACTION_ERR';
129
+ let { message } = error;
130
+ const err: any = new Error(`${errCode} #${orderId} => ${message}`);
131
+ if (error.response) {
132
+ const { status, data } = error.response;
133
+ if (status !== 401 && status !== 403) {
134
+ err.transaction = transaction;
135
+ err.status = status;
136
+ if (typeof data === 'object' && data) {
137
+ err.response = JSON.stringify(data);
138
+ } else {
139
+ err.response = data;
140
+ }
141
+ } else if (Array.isArray(data?.errors) && data.errors[0]?.message) {
142
+ message = data.errors[0].message;
143
+ }
144
+ }
145
+ logger.error(err);
146
+ return {
147
+ status: 409,
148
+ error: errCode,
149
+ message,
150
+ };
151
+ }
152
+ }
153
+
154
+ return {
155
+ status: 400,
156
+ error: 'PAGALEVE_TRANSACTION_INVALID',
157
+ message: 'Não há itens disponíveis no pedido',
158
+ };
159
+ };
160
+
161
+ export default pagaleveCreateTransaction;
@@ -0,0 +1,122 @@
1
+ import type { AppModuleBody, ListPaymentsResponse } from '@cloudcommerce/types';
2
+ import logger from 'firebase-functions/logger';
3
+
4
+ const pagaleveListPayments = (body: AppModuleBody<'list_payments'>) => {
5
+ const { application } = body;
6
+ const params = body.params;
7
+ const response: ListPaymentsResponse = {
8
+ payment_gateways: [],
9
+ };
10
+ const appData = { ...application.data, ...application.hidden_data };
11
+ const {
12
+ PAGALEVE_USERNAME,
13
+ PAGALEVE_PASSWORD,
14
+ } = process.env;
15
+ if (PAGALEVE_USERNAME) appData.username = PAGALEVE_USERNAME;
16
+ if (PAGALEVE_PASSWORD) appData.password = PAGALEVE_PASSWORD;
17
+
18
+ if (!appData.username || !appData.password) {
19
+ logger.warn('Missign Pagaleve username/password');
20
+ return {
21
+ status: 409,
22
+ error: 'NO_PAGALEVE_KEYS',
23
+ message: 'Usuário e/ou senha não configurados pelo lojista',
24
+ };
25
+ }
26
+
27
+ const amount = params.amount || {} as Exclude<(typeof params)['amount'], undefined>;
28
+ const intermediator = {
29
+ name: 'Pagaleve',
30
+ link: 'https://api.pagaleve.com.br',
31
+ code: 'pagaleve',
32
+ };
33
+ const { discount } = appData;
34
+ if (discount && discount.value) {
35
+ if (discount.apply_at !== 'freight') {
36
+ const { value } = discount;
37
+ response.discount_option = {
38
+ label: 'Pix',
39
+ value,
40
+ };
41
+ ['type', 'min_amount'].forEach((prop) => {
42
+ if (discount[prop]) {
43
+ response.discount_option![prop] = discount[prop];
44
+ }
45
+ });
46
+ }
47
+
48
+ if (amount.total) {
49
+ if (amount.total < discount.min_amount) {
50
+ discount.value = 0;
51
+ } else {
52
+ delete discount.min_amount;
53
+ const maxDiscount = amount[discount.apply_at || 'subtotal'];
54
+ let discountValue: number | undefined;
55
+ if (discount.type === 'percentage') {
56
+ discountValue = maxDiscount * (discount.value / 100);
57
+ } else {
58
+ discountValue = discount.value;
59
+ if (discountValue! > maxDiscount) {
60
+ discountValue = maxDiscount;
61
+ }
62
+ }
63
+ if (discountValue) {
64
+ amount.discount = (amount.discount || 0) + discountValue;
65
+ amount.total -= discountValue;
66
+ if (amount.total < 0) {
67
+ amount.total = 0;
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ const listPaymentMethods = ['payment_link', 'account_deposit'] as const;
75
+ listPaymentMethods.forEach((paymentMethod) => {
76
+ const isLinkPayment = paymentMethod === 'payment_link';
77
+ const methodConfig = (appData[paymentMethod] || {});
78
+ const minAmount = Number(methodConfig.min_amount || 1);
79
+ let validateAmount = false;
80
+ if (amount.total && minAmount >= 0) {
81
+ validateAmount = amount.total >= minAmount;
82
+ }
83
+
84
+ // Workaround for showcase
85
+ const validatePayment = amount.total ? validateAmount : true;
86
+ const methodEnable = !methodConfig.disable;
87
+ if (validatePayment && methodEnable) {
88
+ const label = methodConfig.label || (isLinkPayment ? 'Pix Parcelado' : 'Pagar com Pix');
89
+ const gateway: ListPaymentsResponse['payment_gateways'][0] = {
90
+ label,
91
+ icon: methodConfig.icon,
92
+ text: methodConfig.text,
93
+ payment_method: {
94
+ code: isLinkPayment ? 'balance_on_intermediary' : paymentMethod,
95
+ name: `${label} - ${intermediator.name} `,
96
+ },
97
+ intermediator,
98
+ };
99
+ if (!gateway.icon) {
100
+ if (isLinkPayment) {
101
+ gateway.icon = 'https://ecom-pagaleve.web.app/pagaleve-parcelado.png';
102
+ } else {
103
+ gateway.icon = 'https://ecom-pagaleve.web.app/pagaleve-pix.png';
104
+ }
105
+ }
106
+ if ((discount && discount.value && discount[paymentMethod] !== false)) {
107
+ gateway.discount = {};
108
+ ['apply_at', 'type', 'value'].forEach((field) => {
109
+ gateway.discount![field] = discount[field];
110
+ });
111
+ if (response.discount_option && !response.discount_option.label) {
112
+ response.discount_option.label = label;
113
+ }
114
+ }
115
+ response.payment_gateways.push(gateway);
116
+ }
117
+ });
118
+
119
+ return response;
120
+ };
121
+
122
+ export default pagaleveListPayments;
@@ -0,0 +1,150 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ import { createHmac, timingSafeEqual } from 'node:crypto';
3
+ import functions from 'firebase-functions/v1';
4
+ import logger from 'firebase-functions/logger';
5
+ import api from '@cloudcommerce/api';
6
+ import config from '@cloudcommerce/firebase/lib/config';
7
+ import Pagaleve from './pagaleve-constructor';
8
+
9
+ const { httpsFunctionOptions } = config.get();
10
+
11
+ const getAppHiddenData = async () => {
12
+ const { appId } = config.get().apps.pagaleve;
13
+ const { data } = await api.get(`applications?app_id=${appId}&fields=hidden_data`);
14
+ return data.result[0]?.hidden_data;
15
+ };
16
+
17
+ const parseStatusToEcom = (pagaleveTransactionStatus: string) => {
18
+ switch (pagaleveTransactionStatus.toLowerCase()) {
19
+ case 'pending':
20
+ case 'new':
21
+ case 'accepted':
22
+ return 'pending';
23
+ case 'authorized':
24
+ case 'completed':
25
+ return 'paid';
26
+ case 'expired':
27
+ case 'DECLINED':
28
+ case 'ABANDONED':
29
+ case 'canceled':
30
+ return 'voided';
31
+ default:
32
+ }
33
+ return 'unknown';
34
+ };
35
+
36
+ export const pagaleve = {
37
+ webhook: functions
38
+ .region(httpsFunctionOptions.region)
39
+ .runWith(httpsFunctionOptions)
40
+ .https.onRequest(async (req, res) => {
41
+ const { body, query: { hash } } = req;
42
+ if (typeof hash !== 'string') {
43
+ res.sendStatus(403);
44
+ return;
45
+ }
46
+ const {
47
+ id,
48
+ orderReference,
49
+ state,
50
+ amount,
51
+ } = (body || {}) as { [k: string]: any, orderReference?: string & { length: 24 } };
52
+ if (typeof orderReference !== 'string' || orderReference.length !== 24) {
53
+ res.sendStatus(400);
54
+ return;
55
+ }
56
+ let appData: Record<string, any> | undefined;
57
+ try {
58
+ appData = await getAppHiddenData();
59
+ } catch (err) {
60
+ logger.error(err);
61
+ res.sendStatus(500);
62
+ return;
63
+ }
64
+ if (!appData?.password) {
65
+ res.sendStatus(409);
66
+ return;
67
+ }
68
+ const {
69
+ PAGALEVE_USERNAME,
70
+ PAGALEVE_PASSWORD,
71
+ PAGALEVE_SANDBOX,
72
+ } = process.env;
73
+ if (PAGALEVE_USERNAME) appData.username = PAGALEVE_USERNAME;
74
+ if (PAGALEVE_PASSWORD) appData.password = PAGALEVE_PASSWORD;
75
+ const isSandbox = !!PAGALEVE_SANDBOX;
76
+
77
+ const validHash = createHmac('sha256', appData.password)
78
+ .update(orderReference).digest('hex');
79
+ if (
80
+ validHash.length !== hash.length
81
+ || !timingSafeEqual(Buffer.from(hash), Buffer.from(validHash))
82
+ ) {
83
+ res.sendStatus(401);
84
+ return;
85
+ }
86
+
87
+ const orderEndpoint = `orders/${orderReference}` as const;
88
+ try {
89
+ const { data: order } = await api.get(orderEndpoint);
90
+ if (order?.transactions) {
91
+ const transactionIndex = order.transactions.findIndex(({ app }) => {
92
+ return app?.intermediator?.code === 'pagaleve';
93
+ });
94
+ const transactionId = order.transactions[transactionIndex]?._id;
95
+ if (!transactionId) {
96
+ res.sendStatus(404);
97
+ return;
98
+ }
99
+
100
+ await api.post(`${orderEndpoint}/payments_history`, {
101
+ date_time: new Date().toISOString(),
102
+ status: parseStatusToEcom(state),
103
+ transaction_id: transactionId,
104
+ flags: ['pagaleve'],
105
+ } as Exclude<(typeof order)['payments_history'], undefined>[0]);
106
+
107
+ await api.patch(`${orderEndpoint}/transactions/${transactionId}`, {
108
+ intermediator: {
109
+ transaction_id: id || '',
110
+ transaction_code: id || '',
111
+ },
112
+ } as Partial<Exclude<(typeof order)['transactions'], undefined>[0]>);
113
+
114
+ if (state.toLowerCase() === 'authorized') {
115
+ const _pagaleve = new Pagaleve(appData.username, appData.password, isSandbox);
116
+ await _pagaleve.preparing;
117
+ const pagalevePayment = {
118
+ checkout_id: id,
119
+ currency: 'BRL',
120
+ amount,
121
+ intent: 'CAPTURE',
122
+ };
123
+ await _pagaleve.axios.post('/v1/payments', pagalevePayment, {
124
+ maxRedirects: 0,
125
+ });
126
+ }
127
+ }
128
+ } catch (error: any) {
129
+ const { response } = error;
130
+ let status: number | undefined;
131
+ if (response) {
132
+ status = response.status;
133
+ const err: any = new Error(`Webhook failed with ${status} for #${orderReference}`);
134
+ err.url = error.config?.url;
135
+ err.body = error.config?.body;
136
+ err.status = status;
137
+ err.response = JSON.stringify(response.data);
138
+ logger.error(err);
139
+ } else {
140
+ logger.error(error);
141
+ }
142
+ if (!res.headersSent) {
143
+ res.send({
144
+ status: status || 500,
145
+ msg: `Pagaleve webhook error for ${orderReference}`,
146
+ });
147
+ }
148
+ }
149
+ }),
150
+ };
@@ -0,0 +1,12 @@
1
+ import '@cloudcommerce/firebase/lib/init';
2
+ import type { AppModuleBody } from '@cloudcommerce/types';
3
+ import handleListPayments from './pagaleve-list-payments';
4
+ import handleCreateTransaction from './pagaleve-create-transaction';
5
+
6
+ export const listPayments = async (modBody: AppModuleBody<'list_payments'>) => {
7
+ return handleListPayments(modBody);
8
+ };
9
+
10
+ export const createTransaction = async (modBody: AppModuleBody<'create_transaction'>) => {
11
+ return handleCreateTransaction(modBody);
12
+ };
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "../../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "declaration": true
5
+ }
6
+ }
@@ -0,0 +1 @@
1
+ export * from './lib/pagaleve-webhook';
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cloudcommerce/app-pagarme",
3
3
  "type": "module",
4
- "version": "2.11.2",
5
- "description": "E-Com Plus Cloud Commerce app to integrate Pagar.me",
4
+ "version": "2.12.1",
5
+ "description": "e-com.plus Cloud Commerce app to integrate Pagar.me",
6
6
  "main": "lib/pagarme.js",
7
7
  "exports": {
8
8
  ".": "./lib/pagarme.js",
@@ -11,6 +11,7 @@
11
11
  "files": [
12
12
  "/lib",
13
13
  "/lib-mjs",
14
+ "/assets",
14
15
  "/types",
15
16
  "/*.{js,mjs,ts}"
16
17
  ],
@@ -2,5 +2,5 @@ import '@cloudcommerce/firebase/lib/init';
2
2
  import * as functions from 'firebase-functions/v1';
3
3
  export declare const pagarmev5: {
4
4
  onStoreEvent: functions.CloudFunction<functions.pubsub.Message>;
5
- webhooks: functions.HttpsFunction;
5
+ webhook: functions.HttpsFunction;
6
6
  };
@@ -4,11 +4,11 @@ import * as functions from 'firebase-functions/v1';
4
4
  import config from '@cloudcommerce/firebase/lib/config';
5
5
  import { createAppEventsFunction } from '@cloudcommerce/firebase/lib/helpers/pubsub';
6
6
  import handleApiEvent from '../lib-mjs/events-to-pagarme5.mjs';
7
- import handlePagarmeV5Webhook from '../lib-mjs/pagarme5-webhooks.mjs';
7
+ import handlePagarmeV5Webhook from '../lib-mjs/pagarme5-webhook.mjs';
8
8
 
9
9
  export const pagarmev5 = {
10
10
  onStoreEvent: createAppEventsFunction('pagarMeV5', handleApiEvent),
11
- webhooks: functions
11
+ webhook: functions
12
12
  .region(config.get().httpsFunctionOptions.region)
13
13
  .https.onRequest((req, res) => {
14
14
  if (req.method !== 'POST') {
@@ -1 +1 @@
1
- {"version":3,"file":"pagarme-v5-events.js","sourceRoot":"","sources":["../src/pagarme-v5-events.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,OAAO,kCAAkC,CAAC;AAC1C,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,MAAM,MAAM,oCAAoC,CAAC;AACxD,OAAO,EACL,uBAAuB,GAExB,MAAM,4CAA4C,CAAC;AACpD,OAAO,cAAc,MAAM,mCAAmC,CAAC;AAC/D,OAAO,sBAAsB,MAAM,kCAAkC,CAAC;AAEtE,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,YAAY,EAAE,uBAAuB,CACnC,WAAW,EACX,cAAiC,CAClC;IACD,QAAQ,EAAE,SAAS;SAChB,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC;SAChD,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC5B,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1B,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,CAAC;CACL,CAAC"}
1
+ {"version":3,"file":"pagarme-v5-events.js","sourceRoot":"","sources":["../src/pagarme-v5-events.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,OAAO,kCAAkC,CAAC;AAC1C,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,MAAM,MAAM,oCAAoC,CAAC;AACxD,OAAO,EACL,uBAAuB,GAExB,MAAM,4CAA4C,CAAC;AACpD,OAAO,cAAc,MAAM,mCAAmC,CAAC;AAC/D,OAAO,sBAAsB,MAAM,iCAAiC,CAAC;AAErE,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,YAAY,EAAE,uBAAuB,CACnC,WAAW,EACX,cAAiC,CAClC;IACD,OAAO,EAAE,SAAS;SACf,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC;SAChD,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC5B,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1B,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,CAAC;CACL,CAAC"}
@@ -51,7 +51,6 @@ const handleWehook = async (req, res) => {
51
51
  }
52
52
  }
53
53
  const pagarmeAxios = axios(process.env.PAGARMEV5_API_TOKEN);
54
- logger.log(`>> webhook ${JSON.stringify(body)}, type:${type}`);
55
54
  if (type === 'subscription.created' && body.data) {
56
55
  const orderOriginalId = body.data?.code;
57
56
  const subscriptionPagarmeId = body.data?.id;
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cloudcommerce/app-pagarme-v5",
3
3
  "type": "module",
4
- "version": "2.11.2",
5
- "description": "E-Com Plus Cloud Commerce app to integrate Pagar.me API v5 with recurring payments",
4
+ "version": "2.12.1",
5
+ "description": "e-com.plus Cloud Commerce app to integrate Pagar.me API v5 with recurring payments",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
8
8
  ".": "./lib/index.js",
@@ -11,6 +11,7 @@
11
11
  "files": [
12
12
  "/lib",
13
13
  "/lib-mjs",
14
+ "/assets",
14
15
  "/types",
15
16
  "/*.{js,mjs,ts}"
16
17
  ],
@@ -8,14 +8,14 @@ import {
8
8
  ApiEventHandler,
9
9
  } from '@cloudcommerce/firebase/lib/helpers/pubsub';
10
10
  import handleApiEvent from '../lib-mjs/events-to-pagarme5.mjs';
11
- import handlePagarmeV5Webhook from '../lib-mjs/pagarme5-webhooks.mjs';
11
+ import handlePagarmeV5Webhook from '../lib-mjs/pagarme5-webhook.mjs';
12
12
 
13
13
  export const pagarmev5 = {
14
14
  onStoreEvent: createAppEventsFunction(
15
15
  'pagarMeV5',
16
16
  handleApiEvent as ApiEventHandler,
17
17
  ),
18
- webhooks: functions
18
+ webhook: functions
19
19
  .region(config.get().httpsFunctionOptions.region)
20
20
  .https.onRequest((req, res) => {
21
21
  if (req.method !== 'POST') {
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cloudcommerce/app-paghiper",
3
3
  "type": "module",
4
- "version": "2.11.2",
5
- "description": "E-Com Plus Cloud Commerce app to integrate PagHiper",
4
+ "version": "2.12.1",
5
+ "description": "e-com.plus Cloud Commerce app to integrate PagHiper",
6
6
  "main": "lib/paghiper.js",
7
7
  "exports": {
8
8
  ".": "./lib/paghiper.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cloudcommerce/app-pix",
3
3
  "type": "module",
4
- "version": "2.11.2",
5
- "description": "E-Com Plus Cloud Commerce app to integrate Pix API (Bacen)",
4
+ "version": "2.12.1",
5
+ "description": "e-com.plus Cloud Commerce app to integrate Pix API (Bacen)",
6
6
  "main": "lib/pix.js",
7
7
  "exports": {
8
8
  ".": "./lib/pix.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cloudcommerce/app-tiny-erp",
3
3
  "type": "module",
4
- "version": "2.11.2",
5
- "description": "E-Com Plus Cloud Commerce app for Tiny ERP",
4
+ "version": "2.12.1",
5
+ "description": "e-com.plus Cloud Commerce app for Tiny ERP",
6
6
  "main": "lib/tiny-erp.js",
7
7
  "files": [
8
8
  "/lib",