@cloudcommerce/app-woovi 2.56.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 E-Com Club Softwares para E-commerce <ti@e-com.club>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # `@cloudcommerce/app-woovi`
package/events.js ADDED
@@ -0,0 +1 @@
1
+ export * from './lib/woovi-events.js';
package/lib/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './woovi';
package/lib/index.js ADDED
@@ -0,0 +1,3 @@
1
+ // eslint-disable-next-line import/prefer-default-export
2
+ export * from './woovi.js';
3
+ // # sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,cAAc,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const getWooviAxios: () => Promise<import("axios").AxiosInstance>;
2
+ export default getWooviAxios;
@@ -0,0 +1,18 @@
1
+ import axios from 'axios';
2
+
3
+ export const getWooviAxios = async () => {
4
+ const { WOOVI_APP_ID } = process.env;
5
+ const baseURL = 'https://api.woovi.com/api/v1/';
6
+ const wooviAxios = axios.create({
7
+ baseURL,
8
+ headers: {
9
+ 'User-Agent': 'ecomplus/1.0.0 (Node.js; prod)',
10
+ 'Authorization': WOOVI_APP_ID,
11
+ 'Content-Type': 'application/json',
12
+ },
13
+ });
14
+ return wooviAxios;
15
+ };
16
+
17
+ export default getWooviAxios;
18
+ // # sourceMappingURL=woovi-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"woovi-api.js","sourceRoot":"","sources":["../../src/util/woovi-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;IACtC,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IACrC,MAAM,OAAO,GAAG,+BAA+B,CAAC;IAChD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;QAC9B,OAAO;QACP,OAAO,EAAE;YACP,YAAY,EAAE,gCAAgC;YAC9C,eAAe,EAAE,YAAY;YAC7B,cAAc,EAAE,kBAAkB;SACnC;KACF,CAAC,CAAC;IACH,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,76 @@
1
+ import type { AppModuleBody } from '@cloudcommerce/types';
2
+ declare const _default: (modBody: AppModuleBody<"create_transaction">) => Promise<{
3
+ error: string;
4
+ message: string;
5
+ transaction?: undefined;
6
+ } | {
7
+ transaction: {
8
+ payment_link?: string;
9
+ payment_instructions?: string;
10
+ intermediator?: {
11
+ transaction_id?: string;
12
+ transaction_code?: string;
13
+ transaction_reference?: string;
14
+ payment_method?: {
15
+ code: string;
16
+ name?: string;
17
+ };
18
+ buyer_id?: string;
19
+ };
20
+ credit_card?: {
21
+ holder_name?: string;
22
+ avs_result_code?: string | null;
23
+ cvv_result_code?: string | null;
24
+ bin?: number;
25
+ company?: string;
26
+ last_digits?: string;
27
+ token?: string;
28
+ error_code?: "incorrect_number" | "invalid_number" | "invalid_expiry_date" | "invalid_cvc" | "expired_card" | "incorrect_cvc" | "incorrect_zip" | "incorrect_address" | "card_declined" | "processing_error" | "call_issuer" | "pick_up_card";
29
+ };
30
+ banking_billet?: {
31
+ code?: string;
32
+ valid_thru?: string;
33
+ text_lines?: string[];
34
+ link?: string;
35
+ };
36
+ loyalty_points?: {
37
+ name?: string;
38
+ program_id: string;
39
+ points_value: number;
40
+ ratio?: number;
41
+ };
42
+ account_deposit?: {
43
+ valid_thru?: string;
44
+ text_lines?: string[];
45
+ };
46
+ currency_id?: string;
47
+ currency_symbol?: string;
48
+ discount?: number;
49
+ amount: number;
50
+ installments?: {
51
+ number: number;
52
+ value?: number;
53
+ tax?: boolean;
54
+ total?: number;
55
+ };
56
+ creditor_fees?: {
57
+ installment?: number;
58
+ operational?: number;
59
+ intermediation?: number;
60
+ other?: number;
61
+ };
62
+ status?: {
63
+ updated_at?: string;
64
+ current: "pending" | "under_analysis" | "authorized" | "unauthorized" | "paid" | "in_dispute" | "refunded" | "voided" | "unknown";
65
+ };
66
+ flags?: string[];
67
+ custom_fields?: {
68
+ field: string;
69
+ value: string;
70
+ }[];
71
+ notes?: string;
72
+ };
73
+ error?: undefined;
74
+ message?: undefined;
75
+ }>;
76
+ export default _default;
@@ -0,0 +1,105 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { logger } from '@cloudcommerce/firebase/lib/config';
3
+ import { fullName as getFullname, phone as getPhone } from '@ecomplus/utils';
4
+ import { getWooviAxios } from './util/woovi-api.js';
5
+
6
+ export default async (modBody) => {
7
+ const { application, params } = modBody;
8
+ const appData = {
9
+ ...application.data,
10
+ ...application.hidden_data,
11
+ };
12
+ if (appData.woovi_app_id) {
13
+ process.env.WOOVI_APP_ID = appData.woovi_app_id;
14
+ }
15
+ const { WOOVI_APP_ID } = process.env;
16
+ if (!WOOVI_APP_ID) {
17
+ logger.warn('Checkout missing Woovi AppID');
18
+ return {
19
+ error: 'NO_WOOVI_APP_ID',
20
+ message: 'AppID não configurado (lojista deve configurar o aplicativo)',
21
+ };
22
+ }
23
+ const {
24
+ order_id: orderId, order_number: orderNumber, payment_method: paymentMethod, amount, buyer,
25
+ } = params;
26
+ const wooviAxios = await getWooviAxios();
27
+ const transaction = {
28
+ amount: amount.total,
29
+ status: {
30
+ current: 'pending',
31
+ },
32
+ };
33
+ if (paymentMethod.code !== 'account_deposit') {
34
+ return {
35
+ error: 'PAYMENT_METHOD_NOT_SUPPORTED',
36
+ message: 'Apenas Pix é suportado no momento',
37
+ };
38
+ }
39
+ try {
40
+ const correlationID = randomUUID();
41
+ const valueInCents = Math.round(amount.total * 100);
42
+ const phone = getPhone(buyer);
43
+ const phoneNumber = phone
44
+ ? phone.replace(/\D/g, '')
45
+ : undefined;
46
+ const wooviCharge = {
47
+ correlationID,
48
+ value: valueInCents,
49
+ comment: `Pedido ${orderNumber}`,
50
+ };
51
+ const customerName = buyer.fullname || getFullname(buyer);
52
+ if (customerName) {
53
+ wooviCharge.customer = {
54
+ name: customerName,
55
+ email: buyer.email,
56
+ phone: phoneNumber,
57
+ taxID: buyer.doc_number,
58
+ };
59
+ }
60
+ if (appData.expires_in) {
61
+ wooviCharge.expiresIn = Math.max(appData.expires_in, 60 * 5);
62
+ }
63
+ const { data: wooviResponse } = await wooviAxios.post('/charge', wooviCharge);
64
+ if (!wooviResponse.charge) {
65
+ throw new Error(wooviResponse.error || 'Erro ao criar cobrança Pix');
66
+ }
67
+ const { charge } = wooviResponse;
68
+ transaction.intermediator = {
69
+ transaction_id: charge.correlationID,
70
+ transaction_reference: charge.paymentLinkID,
71
+ transaction_code: charge.brCode,
72
+ payment_method: {
73
+ code: 'account_deposit',
74
+ name: 'Pix - Woovi',
75
+ },
76
+ };
77
+ if (charge.paymentLinkUrl) {
78
+ transaction.payment_link = charge.paymentLinkUrl;
79
+ }
80
+ if (charge.qrCodeImage) {
81
+ transaction.notes = `<img src="${charge.qrCodeImage}" style="display:block;margin:0 auto">`;
82
+ }
83
+ if (charge.expiresDate) {
84
+ transaction.account_deposit = {
85
+ valid_thru: new Date(charge.expiresDate).toISOString(),
86
+ };
87
+ }
88
+ return { transaction };
89
+ } catch (_err) {
90
+ const err = _err;
91
+ logger.warn(`Failed payment for ${orderId}`, {
92
+ orderNumber,
93
+ url: err.config?.url,
94
+ request: err.config?.data,
95
+ response: err.response?.data,
96
+ status: err.response?.status,
97
+ });
98
+ logger.error(err);
99
+ return {
100
+ error: 'WOOVI_TRANSACTION_ERROR',
101
+ message: err.message,
102
+ };
103
+ }
104
+ };
105
+ // # sourceMappingURL=woovi-create-transaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"woovi-create-transaction.js","sourceRoot":"","sources":["../src/woovi-create-transaction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import '@cloudcommerce/firebase/lib/init';
2
+ import * as functions from 'firebase-functions/v1';
3
+ export declare const woovi: {
4
+ webhook: functions.HttpsFunction;
5
+ };
@@ -0,0 +1,113 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ import '@cloudcommerce/firebase/lib/init';
3
+ import * as functions from 'firebase-functions/v1';
4
+ import api from '@cloudcommerce/api';
5
+ import config, { logger } from '@cloudcommerce/firebase/lib/config';
6
+ import getAppData from '@cloudcommerce/firebase/lib/helpers/get-app-data';
7
+
8
+ const parseWooviStatus = (event) => {
9
+ switch (event) {
10
+ case 'OPENPIX:CHARGE_CREATED':
11
+ return 'pending';
12
+ case 'OPENPIX:CHARGE_COMPLETED':
13
+ case 'OPENPIX:CHARGE_COMPLETED_NOT_SAME_CUSTOMER_PAYER':
14
+ case 'PIX_AUTOMATIC_COBR_COMPLETED':
15
+ return 'paid';
16
+ case 'OPENPIX:CHARGE_EXPIRED':
17
+ return 'voided';
18
+ case 'OPENPIX:TRANSACTION_REFUND_RECEIVED':
19
+ case 'PIX_TRANSACTION_REFUND_SENT_CONFIRMED':
20
+ return 'refunded';
21
+ default:
22
+ return null;
23
+ }
24
+ };
25
+ const listOrdersByTransaction = async (correlationID) => {
26
+ const filters = `?transactions.intermediator.transaction_id=${correlationID}`
27
+ + '&fields=_id,transactions._id,transactions.app,transactions.intermediator,transactions.status';
28
+ const { result } = (await api.get(`/orders${filters}`)).data;
29
+ return result;
30
+ };
31
+ const handleWebhook = async (req, res) => {
32
+ const { body } = req;
33
+ const event = body?.event;
34
+ const charge = body?.charge || body?.pix;
35
+ if (!event || !charge) {
36
+ logger.warn('Woovi webhook missing event or charge', { body });
37
+ return res.sendStatus(400);
38
+ }
39
+ const { correlationID } = charge;
40
+ if (!correlationID || typeof correlationID !== 'string') {
41
+ logger.warn('Woovi webhook missing correlationID', { body });
42
+ return res.sendStatus(400);
43
+ }
44
+ logger.info(`> Woovi notification: ${event}`, { correlationID });
45
+ if (!process.env.WOOVI_APP_ID) {
46
+ const appData = await getAppData('woovi');
47
+ if (appData.woovi_app_id) {
48
+ process.env.WOOVI_APP_ID = appData.woovi_app_id;
49
+ }
50
+ }
51
+ const { WOOVI_APP_ID } = process.env;
52
+ if (!WOOVI_APP_ID) {
53
+ logger.warn('Missing Woovi AppID');
54
+ return res.sendStatus(403);
55
+ }
56
+ try {
57
+ const status = parseWooviStatus(event);
58
+ if (!status) {
59
+ logger.info(`Ignoring Woovi event: ${event}`);
60
+ return res.sendStatus(204);
61
+ }
62
+ let orders = [];
63
+ if (correlationID) {
64
+ orders = await listOrdersByTransaction(correlationID);
65
+ }
66
+ if (!orders.length) {
67
+ logger.warn('Order not found for Woovi charge', { correlationID });
68
+ return res.sendStatus(404);
69
+ }
70
+ await Promise.all(orders.map(async (order) => {
71
+ const { _id: orderId, transactions } = order;
72
+ let transactionId;
73
+ if (transactions) {
74
+ const transaction = transactions.find((t) => t.intermediator?.transaction_id === correlationID);
75
+ if (transaction) {
76
+ if (transaction.status?.current === status) {
77
+ return;
78
+ }
79
+ transactionId = transaction._id;
80
+ }
81
+ }
82
+ await api.post(`orders/${orderId}/payments_history`, {
83
+ date_time: new Date().toISOString(),
84
+ status,
85
+ transaction_id: transactionId,
86
+ flags: ['woovi', event],
87
+ });
88
+ logger.info(`Updated order ${orderId} to ${status}`);
89
+ }));
90
+ return res.sendStatus(200);
91
+ } catch (err) {
92
+ logger.error('Woovi webhook error', err);
93
+ return res.status(500).send({
94
+ error: 'woovi_webhook_error',
95
+ message: err.message,
96
+ });
97
+ }
98
+ };
99
+ const { httpsFunctionOptions } = config.get();
100
+
101
+ export const woovi = {
102
+ webhook: functions
103
+ .region(httpsFunctionOptions.region)
104
+ .runWith(httpsFunctionOptions)
105
+ .https.onRequest((req, res) => {
106
+ if (req.method !== 'POST') {
107
+ res.sendStatus(405);
108
+ } else {
109
+ handleWebhook(req, res);
110
+ }
111
+ }),
112
+ };
113
+ // # sourceMappingURL=woovi-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"woovi-events.js","sourceRoot":"","sources":["../src/woovi-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { AppModuleBody, ListPaymentsResponse } from '@cloudcommerce/types';
2
+ export declare const wooviListPayments: (modBody: AppModuleBody<"list_payments">) => Promise<ListPaymentsResponse | {
3
+ error: string;
4
+ message: string;
5
+ }>;
6
+ export default wooviListPayments;
@@ -0,0 +1,69 @@
1
+ export const wooviListPayments = async (modBody) => {
2
+ const { application } = modBody;
3
+ const appData = {
4
+ ...application.data,
5
+ ...application.hidden_data,
6
+ };
7
+ if (appData.woovi_app_id) {
8
+ process.env.WOOVI_APP_ID = appData.woovi_app_id;
9
+ }
10
+ if (!process.env.WOOVI_APP_ID) {
11
+ return {
12
+ error: 'NO_WOOVI_APP_ID',
13
+ message: 'AppID não configurado (lojista deve configurar o aplicativo)',
14
+ };
15
+ }
16
+ const response = {
17
+ payment_gateways: [],
18
+ };
19
+ const { discount } = appData;
20
+ if (discount?.value > 0) {
21
+ if (discount.apply_at !== 'freight') {
22
+ const { value } = discount;
23
+ response.discount_option = {
24
+ label: appData.discount_option_label,
25
+ value,
26
+ };
27
+ const discountTypeMinAmount = ['type', 'min_amount'];
28
+ discountTypeMinAmount.forEach((prop) => {
29
+ if (response.discount_option && discount[prop]) {
30
+ response.discount_option[prop] = discount[prop];
31
+ }
32
+ });
33
+ }
34
+ }
35
+ const intermediator = {
36
+ name: 'Woovi',
37
+ link: 'https://woovi.com/',
38
+ code: 'woovi1',
39
+ };
40
+ const paymentMethod = 'account_deposit';
41
+ const methodConfig = appData[paymentMethod] || {};
42
+ let { label } = methodConfig;
43
+ if (!label) {
44
+ label = 'Pix';
45
+ }
46
+ const gateway = {
47
+ label,
48
+ icon: methodConfig.icon,
49
+ text: methodConfig.text,
50
+ payment_method: {
51
+ code: paymentMethod,
52
+ name: `${label} - ${intermediator.name}`,
53
+ },
54
+ intermediator,
55
+ };
56
+ if (methodConfig.discount) {
57
+ gateway.discount = methodConfig.discount;
58
+ } else if (discount?.[paymentMethod] === true) {
59
+ gateway.discount = discount;
60
+ if (response.discount_option && !response.discount_option.label) {
61
+ response.discount_option.label = label;
62
+ }
63
+ }
64
+ response.payment_gateways.push(gateway);
65
+ return response;
66
+ };
67
+
68
+ export default wooviListPayments;
69
+ // # sourceMappingURL=woovi-list-payments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"woovi-list-payments.js","sourceRoot":"","sources":["../src/woovi-list-payments.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,OAAuC,EAAE,EAAE;IACjF,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,OAAO,GAAG;QACd,GAAG,WAAW,CAAC,IAAI;QACnB,GAAG,WAAW,CAAC,WAAW;KAC3B,CAAC;IACF,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAClD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC9B,OAAO;YACL,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,8DAA8D;SACxE,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAyB;QACrC,gBAAgB,EAAE,EAAE;KACrB,CAAC;IAEF,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC7B,IAAI,QAAQ,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACpC,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;YAC3B,QAAQ,CAAC,eAAe,GAAG;gBACzB,KAAK,EAAE,OAAO,CAAC,qBAAqB;gBACpC,KAAK;aACN,CAAC;YACF,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACrD,qBAAqB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACrC,IAAI,QAAQ,CAAC,eAAe,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/C,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG;QACpB,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,oBAAoB;QAC1B,IAAI,EAAE,QAAQ;KACf,CAAC;IACF,MAAM,aAAa,GAAG,iBAAiB,CAAC;IACxC,MAAM,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IAClD,IAAI,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC;IAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IACD,MAAM,OAAO,GAAmB;QAC9B,KAAK;QACL,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,cAAc,EAAE;YACd,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,GAAG,KAAK,MAAM,aAAa,CAAC,IAAI,EAAE;SACzC;QACD,aAAa;KACd,CAAC;IACF,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC1B,OAAO,CAAC,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC;IAC3C,CAAC;SAAM,IAAI,QAAQ,EAAE,CAAC,aAAa,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC5B,IAAI,QAAQ,CAAC,eAAe,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;YAChE,QAAQ,CAAC,eAAe,CAAC,KAAK,GAAG,KAAK,CAAC;QACzC,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAExC,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
package/lib/woovi.d.ts ADDED
@@ -0,0 +1,80 @@
1
+ import '@cloudcommerce/firebase/lib/init';
2
+ import type { AppModuleBody } from '@cloudcommerce/types';
3
+ export declare const listPayments: (modBody: AppModuleBody<"list_payments">) => Promise<import("@cloudcommerce/types").ListPaymentsResponse | {
4
+ error: string;
5
+ message: string;
6
+ }>;
7
+ export declare const createTransaction: (modBody: AppModuleBody<"create_transaction">) => Promise<{
8
+ error: string;
9
+ message: string;
10
+ transaction?: undefined;
11
+ } | {
12
+ transaction: {
13
+ payment_link?: string;
14
+ payment_instructions?: string;
15
+ intermediator?: {
16
+ transaction_id?: string;
17
+ transaction_code?: string;
18
+ transaction_reference?: string;
19
+ payment_method?: {
20
+ code: string;
21
+ name?: string;
22
+ };
23
+ buyer_id?: string;
24
+ };
25
+ credit_card?: {
26
+ holder_name?: string;
27
+ avs_result_code?: string | null;
28
+ cvv_result_code?: string | null;
29
+ bin?: number;
30
+ company?: string;
31
+ last_digits?: string;
32
+ token?: string;
33
+ error_code?: "incorrect_number" | "invalid_number" | "invalid_expiry_date" | "invalid_cvc" | "expired_card" | "incorrect_cvc" | "incorrect_zip" | "incorrect_address" | "card_declined" | "processing_error" | "call_issuer" | "pick_up_card";
34
+ };
35
+ banking_billet?: {
36
+ code?: string;
37
+ valid_thru?: string;
38
+ text_lines?: string[];
39
+ link?: string;
40
+ };
41
+ loyalty_points?: {
42
+ name?: string;
43
+ program_id: string;
44
+ points_value: number;
45
+ ratio?: number;
46
+ };
47
+ account_deposit?: {
48
+ valid_thru?: string;
49
+ text_lines?: string[];
50
+ };
51
+ currency_id?: string;
52
+ currency_symbol?: string;
53
+ discount?: number;
54
+ amount: number;
55
+ installments?: {
56
+ number: number;
57
+ value?: number;
58
+ tax?: boolean;
59
+ total?: number;
60
+ };
61
+ creditor_fees?: {
62
+ installment?: number;
63
+ operational?: number;
64
+ intermediation?: number;
65
+ other?: number;
66
+ };
67
+ status?: {
68
+ updated_at?: string;
69
+ current: "pending" | "under_analysis" | "authorized" | "unauthorized" | "paid" | "in_dispute" | "refunded" | "voided" | "unknown";
70
+ };
71
+ flags?: string[];
72
+ custom_fields?: {
73
+ field: string;
74
+ value: string;
75
+ }[];
76
+ notes?: string;
77
+ };
78
+ error?: undefined;
79
+ message?: undefined;
80
+ }>;
package/lib/woovi.js ADDED
@@ -0,0 +1,12 @@
1
+ import '@cloudcommerce/firebase/lib/init';
2
+ import handleListPayments from './woovi-list-payments.js';
3
+ import handleCreateTransaction from './woovi-create-transaction.js';
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=woovi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"woovi.js","sourceRoot":"","sources":["../src/woovi.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAE1C,OAAO,kBAAkB,MAAM,uBAAuB,CAAC;AACvD,OAAO,uBAAuB,MAAM,4BAA4B,CAAC;AAEjE,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,OAAuC,EAAE,EAAE;IAC5E,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,OAA4C,EAAE,EAAE;IACtF,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@cloudcommerce/app-woovi",
3
+ "type": "module",
4
+ "version": "2.56.0",
5
+ "description": "e-com.plus Cloud Commerce app to integrate Woovi (OpenPix) Pix payments",
6
+ "main": "lib/woovi.js",
7
+ "exports": {
8
+ ".": "./lib/woovi.js",
9
+ "./events": "./lib/woovi-events.js"
10
+ },
11
+ "files": [
12
+ "/lib",
13
+ "/lib-mjs",
14
+ "/assets",
15
+ "/types",
16
+ "/*.{js,mjs,ts}"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/ecomplus/cloud-commerce.git",
21
+ "directory": "packages/apps/woovi"
22
+ },
23
+ "author": "E-Com Club Softwares para E-commerce <ti@e-com.club>",
24
+ "license": "MIT",
25
+ "bugs": {
26
+ "url": "https://github.com/ecomplus/cloud-commerce/issues"
27
+ },
28
+ "homepage": "https://github.com/ecomplus/cloud-commerce/tree/main/packages/apps/woovi#readme",
29
+ "dependencies": {
30
+ "@ecomplus/utils": "1.5.0-rc.6",
31
+ "axios": "^1.13.2",
32
+ "firebase-admin": "^13.6.0",
33
+ "firebase-functions": "^6.6.0",
34
+ "@cloudcommerce/api": "2.56.0",
35
+ "@cloudcommerce/firebase": "2.56.0"
36
+ },
37
+ "devDependencies": {
38
+ "@cloudcommerce/types": "2.56.0"
39
+ },
40
+ "scripts": {
41
+ "build": "bash ../../../scripts/build-lib.sh"
42
+ }
43
+ }