cloudcommerce 0.31.2 → 0.32.0

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 (113) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/action.yml +8 -0
  3. package/ecomplus-stores/barra-doce/functions/many/package.json +3 -3
  4. package/ecomplus-stores/barra-doce/functions/ssr/package.json +6 -6
  5. package/ecomplus-stores/barra-doce/functions/with-apps/package.json +3 -3
  6. package/ecomplus-stores/barra-doce/package.json +2 -2
  7. package/ecomplus-stores/monocard/functions/many/package.json +3 -3
  8. package/ecomplus-stores/monocard/functions/ssr/package.json +6 -6
  9. package/ecomplus-stores/monocard/functions/with-apps/package.json +3 -3
  10. package/ecomplus-stores/monocard/package.json +2 -2
  11. package/package.json +4 -4
  12. package/packages/api/package.json +1 -1
  13. package/packages/apps/affilate-program/package.json +2 -2
  14. package/packages/apps/correios/package.json +3 -3
  15. package/packages/apps/custom-payment/package.json +1 -1
  16. package/packages/apps/custom-shipping/package.json +1 -1
  17. package/packages/apps/datafrete/package.json +2 -2
  18. package/packages/apps/discounts/package.json +1 -1
  19. package/packages/apps/emails/package.json +2 -2
  20. package/packages/apps/fb-conversions/package.json +2 -2
  21. package/packages/apps/flash-courier/package.json +2 -2
  22. package/packages/apps/frenet/package.json +2 -2
  23. package/packages/apps/galaxpay/package.json +2 -2
  24. package/packages/apps/google-analytics/package.json +2 -2
  25. package/packages/apps/jadlog/package.json +1 -1
  26. package/packages/apps/loyalty-points/package.json +1 -1
  27. package/packages/apps/mandae/package.json +3 -3
  28. package/packages/apps/melhor-envio/package.json +2 -2
  29. package/packages/apps/mercadopago/package.json +2 -2
  30. package/packages/apps/pagarme/package.json +2 -2
  31. package/packages/apps/pagarme-v5/CHANGELOG.md +1 -0
  32. package/packages/apps/pagarme-v5/README.md +1 -0
  33. package/packages/apps/pagarme-v5/assets/onload-expression.js +38 -0
  34. package/packages/apps/pagarme-v5/assets/onload-expression.min.js +1 -0
  35. package/packages/apps/pagarme-v5/events.js +1 -0
  36. package/packages/apps/pagarme-v5/lib/index.d.ts +1 -0
  37. package/packages/apps/pagarme-v5/lib/index.js +2 -0
  38. package/packages/apps/pagarme-v5/lib/index.js.map +1 -0
  39. package/packages/apps/pagarme-v5/lib/pagarme-v5-events.d.ts +6 -0
  40. package/packages/apps/pagarme-v5/lib/pagarme-v5-events.js +21 -0
  41. package/packages/apps/pagarme-v5/lib/pagarme-v5-events.js.map +1 -0
  42. package/packages/apps/pagarme-v5/lib/pagarme-v5.d.ts +4 -0
  43. package/packages/apps/pagarme-v5/lib/pagarme-v5.js +12 -0
  44. package/packages/apps/pagarme-v5/lib/pagarme-v5.js.map +1 -0
  45. package/packages/apps/pagarme-v5/lib-mjs/create-pagarme5-transaction.mjs +208 -0
  46. package/packages/apps/pagarme-v5/lib-mjs/events-to-pagarme5.mjs +209 -0
  47. package/packages/apps/pagarme-v5/lib-mjs/functions-lib/api-utils.mjs +220 -0
  48. package/packages/apps/pagarme-v5/lib-mjs/functions-lib/firestore-utils.mjs +24 -0
  49. package/packages/apps/pagarme-v5/lib-mjs/functions-lib/pagarme/create-axios.mjs +12 -0
  50. package/packages/apps/pagarme-v5/lib-mjs/functions-lib/pagarme/handle-plans.mjs +69 -0
  51. package/packages/apps/pagarme-v5/lib-mjs/functions-lib/pagarme/parses-utils.mjs +61 -0
  52. package/packages/apps/pagarme-v5/lib-mjs/functions-lib/pagarme/payment-subscription.mjs +244 -0
  53. package/packages/apps/pagarme-v5/lib-mjs/functions-lib/payments/add-installments.mjs +45 -0
  54. package/packages/apps/pagarme-v5/lib-mjs/list-pagarme5-payments.mjs +218 -0
  55. package/packages/apps/pagarme-v5/lib-mjs/pagarme5-webhooks.mjs +343 -0
  56. package/packages/apps/pagarme-v5/package.json +38 -0
  57. package/packages/apps/pagarme-v5/scripts/build.sh +4 -0
  58. package/packages/apps/pagarme-v5/scripts/tests.sh +9 -0
  59. package/packages/apps/pagarme-v5/src/index.ts +1 -0
  60. package/packages/apps/pagarme-v5/src/pagarme-v5-events.ts +27 -0
  61. package/packages/apps/pagarme-v5/src/pagarme-v5.ts +12 -0
  62. package/packages/apps/pagarme-v5/tests/1-list-payments.test.mjs +37 -0
  63. package/packages/apps/pagarme-v5/tests/2-create-transaction.test.mjs +56 -0
  64. package/packages/apps/pagarme-v5/tsconfig.json +6 -0
  65. package/packages/apps/paghiper/package.json +2 -2
  66. package/packages/apps/pix/package.json +2 -2
  67. package/packages/apps/tiny-erp/package.json +2 -2
  68. package/packages/apps/webhooks/package.json +2 -2
  69. package/packages/cli/config/firebase.json +0 -25
  70. package/packages/cli/package.json +1 -1
  71. package/packages/config/lib/config.js +1 -1
  72. package/packages/config/lib/config.js.map +1 -1
  73. package/packages/config/package.json +1 -1
  74. package/packages/config/src/config.ts +1 -1
  75. package/packages/emails/package.json +1 -1
  76. package/packages/eslint/package.json +2 -2
  77. package/packages/events/lib/firebase.js +2 -0
  78. package/packages/events/lib/firebase.js.map +1 -1
  79. package/packages/events/package.json +3 -2
  80. package/packages/events/src/firebase.ts +2 -0
  81. package/packages/feeds/package.json +1 -1
  82. package/packages/firebase/lib/config.d.ts +4 -0
  83. package/packages/firebase/lib/config.js +9 -0
  84. package/packages/firebase/lib/config.js.map +1 -1
  85. package/packages/firebase/package.json +2 -2
  86. package/packages/firebase/src/config.ts +10 -0
  87. package/packages/i18n/package.json +1 -1
  88. package/packages/modules/lib/firebase/call-app-module.js +12 -0
  89. package/packages/modules/lib/firebase/call-app-module.js.map +1 -1
  90. package/packages/modules/lib/firebase/handle-module.js +2 -1
  91. package/packages/modules/lib/firebase/handle-module.js.map +1 -1
  92. package/packages/modules/lib/firebase.js +10 -0
  93. package/packages/modules/lib/firebase.js.map +1 -1
  94. package/packages/modules/package.json +3 -2
  95. package/packages/modules/src/firebase/call-app-module.ts +12 -0
  96. package/packages/modules/src/firebase/handle-module.ts +5 -1
  97. package/packages/modules/src/firebase.ts +13 -0
  98. package/packages/passport/package.json +2 -2
  99. package/packages/ssr/cloudflare/swr-worker.js +1 -1
  100. package/packages/ssr/lib/analytics-events.js +23 -0
  101. package/packages/ssr/lib/analytics-events.js.map +1 -0
  102. package/packages/ssr/lib/firebase/serve-storefront.js +27 -0
  103. package/packages/ssr/lib/firebase/serve-storefront.js.map +1 -1
  104. package/packages/ssr/package.json +5 -4
  105. package/packages/ssr/src/analytics-events.ts +23 -0
  106. package/packages/ssr/src/cloudflare/swr-worker.ts +1 -1
  107. package/packages/ssr/src/firebase/serve-storefront.ts +28 -0
  108. package/packages/storefront/package.json +5 -5
  109. package/packages/storefront/src/lib/scripts/vbeta-app.ts +14 -4
  110. package/packages/storefront/src/lib/state/customer-session.ts +2 -6
  111. package/packages/storefront/src/lib/state/modules-info.ts +2 -1
  112. package/packages/test-base/package.json +1 -1
  113. package/packages/types/package.json +1 -1
@@ -0,0 +1,12 @@
1
+ import '@cloudcommerce/firebase/lib/init';
2
+ import handleListPayments from '../lib-mjs/list-pagarme5-payments.mjs';
3
+ import handleCreateTransaction from '../lib-mjs/create-pagarme5-transaction.mjs';
4
+
5
+ export const listPayments = async (modBody) => {
6
+ return handleListPayments(modBody);
7
+ };
8
+
9
+ export const createTransaction = async (modBody) => {
10
+ return handleCreateTransaction(modBody);
11
+ };
12
+ // # sourceMappingURL=pagarme-v5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagarme-v5.js","sourceRoot":"","sources":["../src/pagarme-v5.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAE1C,OAAO,kBAAkB,MAAM,uCAAuC,CAAC;AACvE,OAAO,uBAAuB,MAAM,4CAA4C,CAAC;AAEjF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,OAAsB,EAAE,EAAE;IAC3D,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,OAAsB,EAAE,EAAE;IAChE,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC,CAAC"}
@@ -0,0 +1,208 @@
1
+ import logger from 'firebase-functions/logger';
2
+ import config from '@cloudcommerce/firebase/lib/config';
3
+ import { getFirestore } from 'firebase-admin/firestore';
4
+ import { createSubscription, createPayment } from './functions-lib/pagarme/payment-subscription.mjs';
5
+ import { getPlanInTransction } from './functions-lib/pagarme/handle-plans.mjs';
6
+ import { parserInvoiceStatusToEcom, parseAddress } from './functions-lib/pagarme/parses-utils.mjs';
7
+ import axios from './functions-lib/pagarme/create-axios.mjs';
8
+
9
+ export default async (appData) => {
10
+ const colletionFirebase = getFirestore().collection('pagarmeV5Subscriptions');
11
+
12
+ const { params, application } = appData;
13
+
14
+ const configApp = { ...application.data, ...application.hidden_data };
15
+
16
+ if (!process.env.PAGARMEV5_API_TOKEN) {
17
+ const pagarmeApiToken = configApp.pagarme_api_token;
18
+ if (pagarmeApiToken && typeof pagarmeApiToken === 'string') {
19
+ process.env.PAGARMEV5_API_TOKEN = pagarmeApiToken;
20
+ } else {
21
+ logger.warn('Missing PAGARMEV5 API TOKEN');
22
+ }
23
+ }
24
+
25
+ const pagarmeAxios = axios(process.env.PAGARMEV5_API_TOKEN);
26
+ const { storeId } = config.get();
27
+
28
+ const orderId = params.order_id;
29
+
30
+ const { amount, to, buyer } = params;
31
+ logger.log(`[PagarMe V5] Transaction #${orderId}`);
32
+ logger.log(`[PagarMe V5] Type transaction ${params.type}`);
33
+
34
+ const paymentMethod = params.payment_method.code;
35
+
36
+ const transaction = {
37
+ amount: amount.total,
38
+ };
39
+
40
+ const isRecurrence = params.type === 'recurrence';
41
+ let subscriptionPagarmeId;
42
+ let address;
43
+
44
+ if (to && to.street) {
45
+ address = parseAddress(to);
46
+ } else if (params.billing_address) {
47
+ address = parseAddress(params.billing_address);
48
+ }
49
+
50
+ let redirectToPayment = false;
51
+ try {
52
+ const pagarMeCustomer = {
53
+ name: buyer.fullname,
54
+ type: buyer.registry_type === 'j' ? 'company' : 'individual',
55
+ email: buyer.email,
56
+ code: buyer.customer_id,
57
+ document: buyer.doc_number,
58
+ document_type: buyer.registry_type === 'j' ? 'cnpj' : 'cpf',
59
+ address,
60
+ phones: {
61
+ [`${buyer.phone.type === 'personal' ? 'mobile_phone' : 'home_phone'}`]: {
62
+ country_code: `${(buyer.phone.country_code || 55)}`,
63
+ area_code: (buyer.phone.number).substring(0, 2),
64
+ number: (buyer.phone.number).substring(2),
65
+ },
66
+ },
67
+ };
68
+ const birthDate = buyer.birth_date;
69
+ if (birthDate && birthDate.year && birthDate.day) {
70
+ pagarMeCustomer.birthday = `${birthDate.year}-`
71
+ + `${birthDate.month.toString().padStart(2, '0')}-`
72
+ + birthDate.day.toString().padStart(2, '0');
73
+ }
74
+
75
+ if (isRecurrence) {
76
+ const methodConfigName = params.payment_method.code === 'credit_card' ? configApp.credit_card.label : configApp.banking_billet.label;
77
+ let labelPaymentGateway = params.payment_method.name.replace('- Pagar.me', '');
78
+ labelPaymentGateway = labelPaymentGateway.replace(methodConfigName, '');
79
+
80
+ const plan = getPlanInTransction(labelPaymentGateway, configApp.recurrence);
81
+ const { data: subcription } = await createSubscription(
82
+ params,
83
+ configApp,
84
+ storeId,
85
+ plan,
86
+ pagarMeCustomer,
87
+ );
88
+ logger.log(`[PagarMe V5] Response: ${JSON.stringify(subcription)}`);
89
+ subscriptionPagarmeId = subcription.id;
90
+ // /invoices
91
+ const { data: { data: invoices } } = await pagarmeAxios.get(`/invoices?subscription_id=${subscriptionPagarmeId}`);
92
+ logger.log(`[PagarMe V5] Invoices: ${JSON.stringify(invoices)}`);
93
+
94
+ const { data: charge } = await pagarmeAxios.get(`/charges/${invoices[0].charge.id}`);
95
+
96
+ logger.log(`[PagarMe V5] Charge: ${JSON.stringify(charge)}`);
97
+ const transactionPagarme = charge.last_transaction;
98
+
99
+ transaction.status = {
100
+ updated_at: invoices[0].created_at || new Date().toISOString(),
101
+ current: parserInvoiceStatusToEcom(invoices[0].status),
102
+ };
103
+
104
+ transaction.intermediator = {
105
+ transaction_id: invoices[0].id,
106
+ transaction_code: `${transactionPagarme.acquirer_auth_code || ''}`,
107
+ transaction_reference: `${transactionPagarme.acquirer_tid || ''}`,
108
+ };
109
+
110
+ if (paymentMethod === 'banking_billet') {
111
+ transaction.banking_billet = {
112
+ // code: charge.last_transaction.barcode,
113
+ valid_thrud: charge.last_transaction.due_at,
114
+ link: charge.last_transaction.pdf,
115
+ };
116
+ transaction.payment_link = charge.last_transaction.url;
117
+ redirectToPayment = true;
118
+ }
119
+ // console.log('>> transaction ', JSON.stringify(transaction))
120
+ await colletionFirebase.doc(orderId)
121
+ .set({
122
+ status: subcription.status,
123
+ orderNumber: params.order_number,
124
+ created_at: new Date().toISOString(),
125
+ plan,
126
+ subscriptionPagarmeId,
127
+ invoicePagarmeId: invoices[0].id,
128
+ changePagarmeId: charge.id,
129
+ items: subcription.items,
130
+ amount,
131
+ })
132
+ .catch(logger.error);
133
+
134
+ // logger.log('[PagarMe V5] Save Firebase');
135
+ } else {
136
+ // type payment
137
+ const { data: payment } = await createPayment(params, configApp, pagarMeCustomer);
138
+ logger.log(`[PagarMe V5] Response: ${JSON.stringify(payment)}`);
139
+ const [charge] = payment.charges;
140
+
141
+ const transactionPagarme = charge.last_transaction;
142
+
143
+ transaction.status = {
144
+ updated_at: charge.created_at || new Date().toISOString(),
145
+ current: parserInvoiceStatusToEcom(charge.status),
146
+ };
147
+
148
+ transaction.intermediator = {
149
+ transaction_id: payment.id,
150
+ transaction_code: `${transactionPagarme.acquirer_auth_code || ''}`,
151
+ transaction_reference: `${transactionPagarme.acquirer_tid || ''}`,
152
+ };
153
+
154
+ if (paymentMethod === 'account_deposit') {
155
+ let notes = '<div style="display:block;margin:0 auto"> ';
156
+ notes += `<img src="${transactionPagarme.qr_code_url}" style="display:block;margin:0 auto"> `;
157
+ notes += '</div>';
158
+ transaction.notes = notes;
159
+ if (transactionPagarme.qr_code) {
160
+ transaction.intermediator.transaction_code = transactionPagarme.qr_code;
161
+ }
162
+ if (transactionPagarme.expires_at) {
163
+ transaction.account_deposit = {
164
+ valid_thru: transactionPagarme.expires_at,
165
+ };
166
+ }
167
+ } else if (paymentMethod === 'banking_billet') {
168
+ transaction.banking_billet = {
169
+ // code: charge.last_transaction.barcode,
170
+ valid_thrud: charge.last_transaction.due_at,
171
+ link: charge.last_transaction.pdf,
172
+ };
173
+ transaction.payment_link = charge.last_transaction.url;
174
+ redirectToPayment = true;
175
+ }
176
+ }
177
+
178
+ return {
179
+ redirect_to_payment: redirectToPayment,
180
+ transaction,
181
+ };
182
+ } catch (error) {
183
+ logger.error(error);
184
+ // try to debug request error
185
+ const errCode = isRecurrence ? 'PAGARMEV5_SUBSCRIPTION_ERR' : 'PAGARMEV5_TRANSACTION_ERR';
186
+ let { message } = error;
187
+ const err = new Error(`${errCode}- ${orderId} => ${message}`);
188
+ if (error.response) {
189
+ const { status, data } = error.response;
190
+ if (status !== 401 && status !== 403) {
191
+ // err.payment = JSON.stringify(pagarmeTransaction)
192
+ err.status = status;
193
+ if (typeof data === 'object' && data) {
194
+ err.response = JSON.stringify(data);
195
+ } else {
196
+ err.response = data;
197
+ }
198
+ } else if (data && Array.isArray(data.errors) && data.errors[0] && data.errors[0].message) {
199
+ message = data.errors[0].message;
200
+ }
201
+ }
202
+ // logger.error(err);
203
+ return {
204
+ error: errCode,
205
+ message,
206
+ };
207
+ }
208
+ };
@@ -0,0 +1,209 @@
1
+ import api from '@cloudcommerce/api';
2
+ import logger from 'firebase-functions/logger';
3
+ // import config from '@cloudcommerce/firebase/lib/config';
4
+ import { getFirestore } from 'firebase-admin/firestore';
5
+ import ecomUtils from '@ecomplus/utils';
6
+ import axios from './functions-lib/pagarme/create-axios.mjs';
7
+ import { getOrderWithQueryString } from './functions-lib/api-utils.mjs';
8
+ import { getDocFirestore } from './functions-lib/firestore-utils.mjs';
9
+
10
+ const colletionFirebase = getFirestore().collection('pagarmeV5Subscriptions');
11
+
12
+ const eventOrderCancelled = async (
13
+ apiDoc,
14
+ pagarmeAxios,
15
+ ) => {
16
+ const order = apiDoc;
17
+ if (order?.transactions[0]?.type === 'recurrence') {
18
+ const { data: { data: subcriptions } } = await pagarmeAxios.get(`/subscriptions?code=${order._id}`);
19
+ if (subcriptions && subcriptions[0].status !== 'canceled') {
20
+ try {
21
+ logger.log(`> (App PagarMe V5): Try cancel subscription: #${order._id}`);
22
+ await pagarmeAxios.delete(`/subscriptions/${subcriptions[0].id}`);
23
+ logger.log('> (App PagarMe V5): Successfully canceled');
24
+ await colletionFirebase.doc(order._id)
25
+ .set({
26
+ status: 'cancelled',
27
+ updatedAt: new Date().toISOString(),
28
+ }, { merge: true })
29
+ .catch(logger.error);
30
+
31
+ logger.log('>> SUCESSS');
32
+ return null;
33
+ } catch (err) {
34
+ logger.error('> (App PagarMe V5): Error when canceling in Pagar.Me, return the status');
35
+ await api.patch(order._id, { status: 'open' })
36
+ .catch(logger.error);
37
+
38
+ return null;
39
+ }
40
+ } else {
41
+ logger.log('> (App PagarMe V5): Subscription already canceled or does not exist');
42
+ return null;
43
+ }
44
+ }
45
+ // edit items order order Original
46
+ return null;
47
+ };
48
+
49
+ const eventProducts = async (
50
+ apiDoc,
51
+ pagarmeAxios,
52
+ ) => {
53
+ // console.log('> Edit product ', resourceId, 's: ', storeId);
54
+ const product = apiDoc;
55
+
56
+ let query = 'status!=cancelled&transactions.type=recurrence';
57
+ query += '&transactions.app.intermediator.code=pagarme';
58
+ query += `&items.product_id=${product._id}`;
59
+
60
+ const result = await getOrderWithQueryString(query);
61
+
62
+ if (result && result.length) {
63
+ let i = 0;
64
+ while (i < result.length) {
65
+ const updateItemPagarme = [];
66
+ // eslint-disable-next-line no-await-in-loop
67
+ const order = (await api.get(`orders/${result[i]._id}`)).data;
68
+ // eslint-disable-next-line no-await-in-loop
69
+ const docSubscription = await getDocFirestore(colletionFirebase, result[i]._id);
70
+ logger.log('> (App PagarMe v5): Order ', JSON.stringify(order), ' ', JSON.stringify(docSubscription));
71
+ if (order && docSubscription) {
72
+ const itemsUpdate = [];
73
+ order.items.forEach((orderItem) => {
74
+ if (orderItem.product_id === product._id) {
75
+ if (orderItem.variation_id) {
76
+ const variation = product.variations
77
+ .find((itemFind) => itemFind.sku === orderItem.sku);
78
+
79
+ let quantity = orderItem.quantity;
80
+ if (variation && variation.quantity < orderItem.quantity) {
81
+ quantity = variation.quantity;
82
+ } else if (!variation) {
83
+ quantity = 0;
84
+ }
85
+ const newItem = {
86
+ sku: variation.sku,
87
+ price: ecomUtils.price({ ...product, ...variation }),
88
+ quantity,
89
+ };
90
+ if ((orderItem.final_price && orderItem.final_price !== newItem.price)
91
+ || orderItem.price !== newItem.price || orderItem.quantity !== newItem.quantity) {
92
+ itemsUpdate.push(newItem);
93
+ }
94
+ } else {
95
+ const newItem = {
96
+ sku: product.sku,
97
+ price: ecomUtils.price(product),
98
+ quantity: product.quantity < orderItem.quantity
99
+ ? product.quantity : orderItem.quantity,
100
+ };
101
+ if ((orderItem.final_price && orderItem.final_price !== newItem.price)
102
+ || orderItem.price !== newItem.price || orderItem.quantity !== newItem.quantity) {
103
+ itemsUpdate.push(newItem);
104
+ }
105
+ }
106
+ }
107
+ });
108
+
109
+ if (itemsUpdate.length) {
110
+ docSubscription?.items?.forEach((itemPagarme) => {
111
+ const itemToEdit = itemsUpdate.find((itemFind) => itemPagarme.id === `pi_${itemFind.sku}`);
112
+ if (itemToEdit && !itemPagarme.cycles) {
113
+ itemPagarme.quantity = itemToEdit.quantity;
114
+ itemPagarme.pricing_scheme.price = Math.floor((itemToEdit.price) * 100);
115
+ updateItemPagarme.push({
116
+ subscription_id: docSubscription.subscriptionPagarmeId,
117
+ item: itemPagarme,
118
+ });
119
+ }
120
+ });
121
+ }
122
+ }
123
+ // order not found or error
124
+ if (updateItemPagarme.length) {
125
+ logger.log('> (App PagarMe V5): Try update item in Pagar.Me');
126
+ try {
127
+ // eslint-disable-next-line no-await-in-loop
128
+ await Promise.all(updateItemPagarme.map((itemPagarme) => {
129
+ return pagarmeAxios.put(
130
+ `/subscriptions/${itemPagarme.subscription_id}/items/${itemPagarme.item.id}`,
131
+ {
132
+ ...itemPagarme.item,
133
+ },
134
+ );
135
+ }));
136
+ } catch (err) {
137
+ logger.error(err);
138
+ /* When creating a new order, check the items saved in Pagar.Me
139
+ with the original order items
140
+
141
+ No need to save to firestore
142
+ */
143
+ }
144
+ }
145
+ i += 1;
146
+ }
147
+ logger.log('>> SUCESSS');
148
+ return null;
149
+ }
150
+ logger.log('>> Orders not found ');
151
+ return null;
152
+ };
153
+
154
+ const handleApiEvent = async ({
155
+ evName,
156
+ apiEvent,
157
+ apiDoc,
158
+ app,
159
+ }) => {
160
+ const resourceId = apiEvent.resource_id;
161
+ logger.info('>> ', resourceId, ' - Action: ', apiEvent.action);
162
+ const key = `${evName}_${resourceId}`;
163
+ const configApp = { ...app.data, ...app.hidden_data };
164
+ if (
165
+ Array.isArray(configApp.ignore_events)
166
+ && configApp.ignore_events.includes(evName)
167
+ ) {
168
+ logger.info('>> ', key, ' - Ignored event');
169
+ return null;
170
+ }
171
+ logger.info(`> Webhook ${resourceId} [${evName}] => ${apiDoc}`);
172
+
173
+ if (!process.env.PAGARMEV5_API_TOKEN) {
174
+ const pagarmeApiToken = configApp.pagarme_api_token;
175
+ if (pagarmeApiToken && typeof pagarmeApiToken === 'string') {
176
+ process.env.PAGARMEV5_API_TOKEN = pagarmeApiToken;
177
+ } else {
178
+ logger.warn('Missing PAGARMEV5 API TOKEN');
179
+ return null;
180
+ }
181
+ }
182
+
183
+ try {
184
+ const pagarmeAxios = axios(process.env.PAGARMEV5_API_TOKEN);
185
+
186
+ if (evName === 'orders-cancelled') {
187
+ return eventOrderCancelled(apiDoc, pagarmeAxios);
188
+ }
189
+
190
+ if (evName.startsWith('products-') && evName !== 'products-new') {
191
+ return eventProducts(apiDoc, pagarmeAxios);
192
+ }
193
+
194
+ return null;
195
+ } catch (error) {
196
+ const statusCode = error.response?.status;
197
+ if (statusCode === 404) {
198
+ logger.warn('> (App PagarMe V5): Subscription not found in PagarMe');
199
+ return null;
200
+ }
201
+ if (statusCode === 401 || statusCode === 403) {
202
+ logger.warn('> (App PagarMe V5): Unauthorized subscription deletion request');
203
+ return null;
204
+ }
205
+ throw error;
206
+ }
207
+ };
208
+
209
+ export default handleApiEvent;
@@ -0,0 +1,220 @@
1
+ import ecomUtils from '@ecomplus/utils';
2
+ import api from '@cloudcommerce/api';
3
+
4
+ const getOrderById = async (orderId) => {
5
+ const { data } = await api.get(`orders/${orderId}`);
6
+ return data;
7
+ };
8
+
9
+ const addPaymentHistory = async (orderId, body) => {
10
+ return api.post(`orders/${orderId}/payments_history`, body);
11
+ };
12
+
13
+ const updateTransaction = (orderId, body, transactionId) => {
14
+ const urlTransaction = transactionId ? `/${transactionId}` : '';
15
+ const method = transactionId ? 'PATCH' : 'POST';
16
+
17
+ return api[method](`orders/${orderId}/transactions${urlTransaction}`, body);
18
+ };
19
+
20
+ const getOrderIntermediatorTransactionId = async (invoiceId) => {
21
+ let queryString = `?transactions.intermediator.transaction_id=${invoiceId}`;
22
+ queryString += '&fields=transactions,financial_status.current,status';
23
+ const data = await api.get(`orders${queryString}`);
24
+
25
+ return data?.result.length ? data?.result[0] : null;
26
+ };
27
+
28
+ const checkItemsAndRecalculeteOrder = (amount, items, plan, itemsPagarme) => {
29
+ let subtotal = 0;
30
+ let item;
31
+ let i = 0;
32
+ while (i < items.length) {
33
+ item = items[i];
34
+
35
+ if (item.flags && (item.flags.includes('freebie') || item.flags.includes('discount-set-free'))) {
36
+ items.splice(i, 1);
37
+ } else {
38
+ // eslint-disable-next-line no-loop-func
39
+ const itemFound = itemsPagarme.find((itemFind) => itemFind.id === `pi_${item.sku}`);
40
+
41
+ if (itemFound) {
42
+ item.quantity = itemFound.quantity;
43
+ if (item.final_price) {
44
+ item.final_price = (itemFound.pricing_scheme.price / 100);
45
+ }
46
+ item.price = (itemFound.pricing_scheme.price / 100);
47
+ subtotal += item.quantity * (item.final_price || item.price);
48
+ i += 1;
49
+ } else {
50
+ items.splice(i, 1);
51
+ }
52
+ }
53
+ }
54
+
55
+ if (subtotal > 0) {
56
+ amount.subtotal = subtotal;
57
+ amount.total = amount.subtotal + (amount.tax || 0)
58
+ + (amount.freight || 0) + (amount.extra || 0);
59
+
60
+ let planDiscount;
61
+ if (plan && plan.discount) {
62
+ if (plan.discount.type === 'percentage') {
63
+ planDiscount = amount[plan.discount.apply_at];
64
+ planDiscount *= ((plan.discount.value) / 100);
65
+ }
66
+ }
67
+ // if the plan doesn't exist, because it's subscription before the update
68
+ amount.discount = plan ? ((plan.discount && plan.discount.type !== 'percentage' ? plan.discount.value : planDiscount) || 0) : (amount.discount || 0);
69
+
70
+ amount.total -= amount.discount;
71
+ amount.total = amount.total > 0 ? amount.total : 0;
72
+
73
+ return amount.total > 0 ? Math.floor((amount.total).toFixed(2) * 1000) / 10 : 0;
74
+ }
75
+
76
+ return 0;
77
+ };
78
+
79
+ const createNewOrderBasedOld = (oldOrder, plan, status, charge, subscriptionPagarme) => {
80
+ const {
81
+ buyers, items, domain, amount,
82
+ } = oldOrder;
83
+ const channelType = oldOrder.channel_type;
84
+ const shippingLines = oldOrder.shipping_lines;
85
+ const shippingMethodLabel = oldOrder.shipping_method_label;
86
+ const paymentMethodLabel = oldOrder.payment_method_label;
87
+ const originalTransaction = oldOrder.transactions[0];
88
+
89
+ const portion = charge.code?.replace(`${oldOrder._id}-`, '');
90
+ const itemsPagarme = subscriptionPagarme.items;
91
+
92
+ checkItemsAndRecalculeteOrder(amount, items, plan, itemsPagarme);
93
+ if (amount.balance) {
94
+ delete amount.balance;
95
+ }
96
+
97
+ items.forEach((item) => {
98
+ if (item.stock_status && item.stock_status !== 'unmanaged') {
99
+ item.stock_status = 'pending';
100
+ }
101
+ });
102
+ const transactionPagarme = charge.last_transaction;
103
+
104
+ const transactions = [
105
+ {
106
+ amount: amount.total,
107
+ status: {
108
+ updated_at: transactionPagarme.updated_at || new Date().toISOString(),
109
+ current: status,
110
+ },
111
+ intermediator: {
112
+ transaction_id: `${charge.invoice.id}`,
113
+ transaction_code: `${transactionPagarme.acquirer_auth_code || ''}`,
114
+ transaction_reference: `${transactionPagarme.acquirer_tid || ''}`,
115
+ },
116
+ payment_method: originalTransaction.payment_method,
117
+ app: originalTransaction.app,
118
+ _id: ecomUtils.randomObjectId(),
119
+ notes: `Parcela #${portion} referente à ${plan?.label || 'Assinatura'}`,
120
+ custom_fields: originalTransaction.custom_fields,
121
+ },
122
+ ];
123
+
124
+ transactions[0].payment_link = transactionPagarme.url;
125
+
126
+ const financialStatus = {
127
+ updated_at: transactionPagarme.updated_at || new Date().toISOString(),
128
+ current: status,
129
+ };
130
+
131
+ let notes = `Parcela #${portion} desconto de ${plan.discount.type === 'percentage' ? '' : 'R$'}`;
132
+ notes += ` ${plan.discount.value} ${plan.discount.type === 'percentage' ? '%' : ''}`;
133
+ notes += ` sobre ${plan.discount.apply_at}`;
134
+
135
+ const body = {
136
+ opened_at: new Date().toISOString(),
137
+ items,
138
+ shipping_lines: shippingLines,
139
+ buyers,
140
+ channel_type: channelType,
141
+ domain,
142
+ amount,
143
+ shipping_method_label: shippingMethodLabel,
144
+ payment_method_label: paymentMethodLabel,
145
+ transactions,
146
+ financial_status: financialStatus,
147
+ subscription_order: {
148
+ _id: oldOrder._id,
149
+ number: oldOrder.number,
150
+ },
151
+ notes,
152
+ staff_notes: `Valor cobrado no Pagar.Me R$${(charge.amount) / 100}`,
153
+ };
154
+ return api.post('orders', body);
155
+ };
156
+
157
+ // const updateOrder = async (orderId, body) => {
158
+ // return api.patch(`orders/${orderId}`, body);
159
+ // };
160
+
161
+ const getOrderWithQueryString = async (query) => {
162
+ const { data } = await api.get(`orders?${query}`);
163
+
164
+ return data?.result.length ? data?.result : null;
165
+ };
166
+
167
+ const getProductById = async (productId) => {
168
+ const { data } = await api.get(`products/${productId}`);
169
+ return data;
170
+ };
171
+
172
+ const checkItemCategory = async (categoryIds, itemsPagarme, itemsApi) => {
173
+ let i = 0;
174
+
175
+ const itemsIdPagarmeDelete = [];
176
+ while (i < itemsPagarme.length) {
177
+ const itemPagarme = itemsPagarme[i];
178
+ // Obs.: freight is one item, initially do not remove freight
179
+ const isItemFreigth = itemPagarme?.id?.startsWith('pi_freight_');
180
+ const itemFound = itemsApi.find((itemFind) => itemPagarme.id === `pi_${itemFind.sku}`);
181
+ const itemFoundIndex = itemsApi.indexOf(itemFound);
182
+
183
+ if (itemFound && !isItemFreigth) {
184
+ // eslint-disable-next-line no-await-in-loop
185
+ const product = await getProductById(itemFound.product_id);
186
+ if (product.categories) {
187
+ let canSign = false;
188
+ product.categories.forEach((category) => {
189
+ if (categoryIds.includes(category._id)) {
190
+ canSign = true;
191
+ }
192
+ });
193
+
194
+ if (!canSign) {
195
+ itemsIdPagarmeDelete.push(itemPagarme.id);
196
+ itemsApi.splice(itemFoundIndex, 1);
197
+ }
198
+ } else {
199
+ itemsIdPagarmeDelete.push(itemPagarme.id);
200
+ itemsApi.splice(itemFoundIndex, 1);
201
+ }
202
+ } else if (!isItemFreigth) {
203
+ itemsIdPagarmeDelete.push(itemPagarme.id);
204
+ }
205
+ i += 1;
206
+ }
207
+
208
+ return itemsIdPagarmeDelete;
209
+ };
210
+
211
+ export {
212
+ getOrderById,
213
+ addPaymentHistory,
214
+ updateTransaction,
215
+ getOrderIntermediatorTransactionId,
216
+ createNewOrderBasedOld,
217
+ getOrderWithQueryString,
218
+ getProductById,
219
+ checkItemCategory,
220
+ };
@@ -0,0 +1,24 @@
1
+ import logger from 'firebase-functions/logger';
2
+
3
+ const getDocFirestore = async (collection, documentId) => {
4
+ const documentSnapshot = await collection.doc(documentId).get();
5
+ let data;
6
+ if (documentSnapshot) {
7
+ data = documentSnapshot.data();
8
+ }
9
+ return data;
10
+ };
11
+
12
+ const updateDocFirestore = async (collection, documentId, body) => {
13
+ const updatedAt = new Date().toISOString();
14
+ body.updatedAt = updatedAt;
15
+
16
+ await collection.doc(documentId)
17
+ .set(body, { merge: true })
18
+ .catch(logger.error);
19
+ };
20
+
21
+ export {
22
+ getDocFirestore,
23
+ updateDocFirestore,
24
+ };
@@ -0,0 +1,12 @@
1
+ import axios from 'axios';
2
+
3
+ export default (apiSecretKey) => {
4
+ return axios.create({
5
+ baseURL: 'https://api.pagar.me/core/v5',
6
+ headers: {
7
+ accept: 'application/json',
8
+ 'content-type': 'application/json',
9
+ Authorization: 'Basic ' + Buffer.from(`${apiSecretKey}:`).toString('base64'),
10
+ },
11
+ });
12
+ };