@uappi/public-sdk 1.20.0 → 1.21.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/components/PaymentHosted/PaymentHosted.vue +15 -2
- package/components/PaymentHosted/types.ts +6 -1
- package/modules/Api/endpoints/OrderPaymentCodeComposable.ts +10 -0
- package/modules/Api/index.ts +7 -0
- package/modules/Api/types/context/api-config.types.ts +8 -2
- package/modules/Api/types/endpoints/cart/cart.interfaces.ts +1 -0
- package/modules/Api/types/endpoints/order/order-payment-code.interfaces.ts +13 -0
- package/modules/Api/types/endpoints/order/order-payment-code.types.ts +9 -0
- package/modules/Api/types/index.ts +8 -0
- package/modules/Tracking/facebook/events/actions/addPaymentInfo.ts +2 -0
- package/modules/Tracking/facebook/events/actions/addToCart.ts +2 -0
- package/modules/Tracking/facebook/events/actions/initiateCheckout.ts +2 -0
- package/modules/Tracking/facebook/events/actions/purchase.ts +2 -0
- package/modules/Tracking/facebook/events/actions/purchaseOrder.ts +18 -0
- package/modules/Tracking/facebook/events/actions/search.ts +2 -0
- package/modules/Tracking/facebook/events/views/pageView.ts +2 -0
- package/modules/Tracking/facebook/events/views/viewContent.ts +2 -0
- package/modules/Tracking/gtm/events/actions/purchaseOrder.ts +49 -0
- package/package.json +1 -1
|
@@ -3,7 +3,9 @@ import { ref, shallowRef, computed, onMounted, onUnmounted } from 'vue';
|
|
|
3
3
|
|
|
4
4
|
import api from '../../modules/Api';
|
|
5
5
|
import { purchaseAction } from '../../modules/Tracking/gtm/events/actions/purchase';
|
|
6
|
+
import { purchaseOrderAction } from '../../modules/Tracking/gtm/events/actions/purchaseOrder';
|
|
6
7
|
import { purchaseAction as facebookPurchaseAction } from '../../modules/Tracking/facebook/events/actions/purchase';
|
|
8
|
+
import { purchaseOrderAction as facebookPurchaseOrderAction } from '../../modules/Tracking/facebook/events/actions/purchaseOrder';
|
|
7
9
|
|
|
8
10
|
import type { Props, Emits, PaymentSuccessData, PaymentRedirectData } from './types';
|
|
9
11
|
import type { CartResponse } from '../../modules/Api/types';
|
|
@@ -51,7 +53,10 @@ const iframeSrc = computed(() => {
|
|
|
51
53
|
});
|
|
52
54
|
|
|
53
55
|
async function requestPaymentToken(): Promise<string> {
|
|
54
|
-
const response = await api.cart.paymentToken({
|
|
56
|
+
const response = await api.cart.paymentToken({
|
|
57
|
+
paymentOptionId: props.option.id,
|
|
58
|
+
...(props.orderGroupPaymentCode ? { orderGroupPaymentCode: props.orderGroupPaymentCode } : {}),
|
|
59
|
+
});
|
|
55
60
|
|
|
56
61
|
if (!response?.token) {
|
|
57
62
|
console.error('[PaymentHosted] Token ausente na resposta:', response);
|
|
@@ -70,6 +75,7 @@ async function fetchPaymentToken(): Promise<void> {
|
|
|
70
75
|
paymentToken.value = await requestPaymentToken();
|
|
71
76
|
} catch (err) {
|
|
72
77
|
console.error('[PaymentHosted] Erro ao buscar token de pagamento:', err);
|
|
78
|
+
emit('token-error', (err as { errorCode?: string })?.errorCode);
|
|
73
79
|
tokenError.value = 'Não foi possível iniciar o formulário de pagamento.';
|
|
74
80
|
} finally {
|
|
75
81
|
loadingToken.value = false;
|
|
@@ -96,6 +102,10 @@ async function refreshPaymentToken(): Promise<void> {
|
|
|
96
102
|
}
|
|
97
103
|
|
|
98
104
|
async function fetchCartSnapshot(): Promise<void> {
|
|
105
|
+
// No fluxo de link o carrinho ativo não é a compra: o CartBroker devolveria um
|
|
106
|
+
// carrinho vazio recém-criado, e o evento sairia com itens que não existem
|
|
107
|
+
if (props.orderGroupPaymentCode) return;
|
|
108
|
+
|
|
99
109
|
try {
|
|
100
110
|
cartSnapshot.value = await api.cart.listDetail();
|
|
101
111
|
} catch (err) {
|
|
@@ -131,7 +141,10 @@ function handleIframeMessage(event: MessageEvent): void {
|
|
|
131
141
|
break;
|
|
132
142
|
|
|
133
143
|
case 'UAPPI_PAYMENT_SUCCESS':
|
|
134
|
-
if (
|
|
144
|
+
if (props.orderGroup) {
|
|
145
|
+
purchaseOrderAction(props.option.paymentType.code, props.orderGroup);
|
|
146
|
+
facebookPurchaseOrderAction(props.orderGroup.id, props.orderGroup.values?.totalValue ?? 0);
|
|
147
|
+
} else if (cartSnapshot.value) {
|
|
135
148
|
purchaseAction(props.option.paymentType.code, cartSnapshot.value);
|
|
136
149
|
facebookPurchaseAction(data.id, cartSnapshot.value);
|
|
137
150
|
} else {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PaymentOption, BuyCartResponse } from '../../modules/Api/types';
|
|
1
|
+
import type { PaymentOption, BuyCartResponse, CustomerOrderResponse } from '../../modules/Api/types';
|
|
2
2
|
|
|
3
3
|
export interface Props {
|
|
4
4
|
/** Opção de pagamento selecionada (ex: item retornado por `api.cart.listPayments`). */
|
|
@@ -11,10 +11,15 @@ export interface Props {
|
|
|
11
11
|
countryCode?: string;
|
|
12
12
|
/** Host do serviço render.uappi. Sobrescreve `VITE_PAYMENT_IFRAME_HOST` quando informado. */
|
|
13
13
|
iframeHost?: string;
|
|
14
|
+
/** Código do link de pagamento. Informado, o token sai para o pedido do link. */
|
|
15
|
+
orderGroupPaymentCode?: string;
|
|
16
|
+
/** Grupo de pedido do link. Obrigatório junto de `orderGroupPaymentCode`. */
|
|
17
|
+
orderGroup?: CustomerOrderResponse;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export interface Emits {
|
|
17
21
|
(e: 'payment-ready'): void;
|
|
22
|
+
(e: 'token-error', errorCode: string | undefined): void;
|
|
18
23
|
(e: 'payment-success', data: PaymentSuccessData): void;
|
|
19
24
|
(e: 'payment-redirect', url: string, data: PaymentRedirectData): void;
|
|
20
25
|
(e: 'payment-error', errorCode: string | undefined, message: string): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { usePublicApi } from '..';
|
|
2
|
+
|
|
3
|
+
import type { OrderPaymentCodeDetailResponse } from '../types';
|
|
4
|
+
|
|
5
|
+
export function detailOrderPaymentCode(code: string) {
|
|
6
|
+
return usePublicApi<OrderPaymentCodeDetailResponse>({
|
|
7
|
+
endpoint: `/publics/order/payment-code/${code}`,
|
|
8
|
+
method: 'GET',
|
|
9
|
+
});
|
|
10
|
+
}
|
package/modules/Api/index.ts
CHANGED
|
@@ -58,6 +58,7 @@ import { listMenu } from './endpoints/MenuComposable';
|
|
|
58
58
|
import { listPairOffers } from './endpoints/PairOfferComposable';
|
|
59
59
|
import { getPromotionalForecast } from './endpoints/PromotionalForecastComposable';
|
|
60
60
|
import { paymentConditions } from './endpoints/PaymentComposable';
|
|
61
|
+
import { detailOrderPaymentCode } from './endpoints/OrderPaymentCodeComposable';
|
|
61
62
|
import {
|
|
62
63
|
deleteProductComment,
|
|
63
64
|
createProductComment,
|
|
@@ -216,6 +217,10 @@ const promotional = {
|
|
|
216
217
|
getPromotionalForecast,
|
|
217
218
|
};
|
|
218
219
|
|
|
220
|
+
const order = {
|
|
221
|
+
detailOrderPaymentCode
|
|
222
|
+
};
|
|
223
|
+
|
|
219
224
|
const notify = {
|
|
220
225
|
contact
|
|
221
226
|
}
|
|
@@ -226,6 +231,7 @@ export {
|
|
|
226
231
|
customer,
|
|
227
232
|
customization,
|
|
228
233
|
cart,
|
|
234
|
+
order,
|
|
229
235
|
product,
|
|
230
236
|
promotional,
|
|
231
237
|
notify,
|
|
@@ -238,6 +244,7 @@ export default {
|
|
|
238
244
|
customer,
|
|
239
245
|
customization,
|
|
240
246
|
cart,
|
|
247
|
+
order,
|
|
241
248
|
product,
|
|
242
249
|
promotional,
|
|
243
250
|
notify,
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { Ref } from 'vue';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
ApiParams,
|
|
5
|
+
CustomerErrorCode,
|
|
6
|
+
CustomerMFAErrorCode,
|
|
7
|
+
OrderPaymentCodeErrorCode,
|
|
8
|
+
} from '..';
|
|
4
9
|
|
|
5
10
|
export type ApiStatus = 'pending' | 'success' | 'error';
|
|
6
11
|
|
|
@@ -63,6 +68,7 @@ export interface ApiErrorData {
|
|
|
63
68
|
| 'UAPPI_TOOLS_ITEM_EVALUATED'
|
|
64
69
|
| 'UAPPI_TOOLS_REVIEW_NOT_FOUND'
|
|
65
70
|
| CustomerErrorCode
|
|
66
|
-
| CustomerMFAErrorCode
|
|
71
|
+
| CustomerMFAErrorCode
|
|
72
|
+
| OrderPaymentCodeErrorCode;
|
|
67
73
|
message: string;
|
|
68
74
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CustomerOrderResponse, PaymentConfiguration, PaymentResponse } from '../..';
|
|
2
|
+
|
|
3
|
+
export interface OrderPaymentCodeAvailableOption {
|
|
4
|
+
option: PaymentResponse[number];
|
|
5
|
+
settings: Array<PaymentConfiguration>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface OrderPaymentCodeDetailResponse {
|
|
9
|
+
code: string;
|
|
10
|
+
expiresAt: string;
|
|
11
|
+
orderGroup: CustomerOrderResponse | null;
|
|
12
|
+
paymentOptions: Array<OrderPaymentCodeAvailableOption>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type OrderPaymentCodeErrorCode =
|
|
2
|
+
| 'UAPPI_STORE_ORDER_PAYMENT_CODE_NOT_FOUND'
|
|
3
|
+
| 'UAPPI_STORE_ORDER_PAYMENT_CODE_EXPIRED'
|
|
4
|
+
| 'UAPPI_STORE_ORDER_PAYMENT_CODE_INVALID_ORDER_STATUS'
|
|
5
|
+
| 'UAPPI_STORE_ORDER_PAYMENT_CODE_ALREADY_PAID'
|
|
6
|
+
| 'UAPPI_STORE_ORDER_INVALID_PAYMENT_OPTION'
|
|
7
|
+
| 'UAPPI_STORE_ORDER_PAYMENT_FAIL'
|
|
8
|
+
| 'UAPPI_STORE_ORDER_ANTI_FRAUD_FAIL'
|
|
9
|
+
| 'UAPPI_RENDER_PAYMENT_EXPIRED_TOKEN';
|
|
@@ -137,6 +137,11 @@ import type { Media } from './endpoints/media/media.interfaces';
|
|
|
137
137
|
import type { Target, Type } from './endpoints/menu/menu.enums';
|
|
138
138
|
import type { Menu, MenuItem } from './endpoints/menu/menu.interfaces';
|
|
139
139
|
import type { Order, OrderItem } from './endpoints/order/order.interfaces';
|
|
140
|
+
import type {
|
|
141
|
+
OrderPaymentCodeAvailableOption,
|
|
142
|
+
OrderPaymentCodeDetailResponse,
|
|
143
|
+
} from './endpoints/order/order-payment-code.interfaces';
|
|
144
|
+
import type { OrderPaymentCodeErrorCode } from './endpoints/order/order-payment-code.types';
|
|
140
145
|
import type { Page } from './endpoints/page/page.interfaces';
|
|
141
146
|
import type { Pagination } from './endpoints/pagination/pagination.interfaces';
|
|
142
147
|
import type {
|
|
@@ -522,6 +527,9 @@ export type {
|
|
|
522
527
|
// Order
|
|
523
528
|
Order,
|
|
524
529
|
OrderItem,
|
|
530
|
+
OrderPaymentCodeAvailableOption,
|
|
531
|
+
OrderPaymentCodeDetailResponse,
|
|
532
|
+
OrderPaymentCodeErrorCode,
|
|
525
533
|
Storage,
|
|
526
534
|
|
|
527
535
|
// COUNTRY TYPES
|
|
@@ -5,6 +5,8 @@ import { pushFbq } from '../../../utils/pushFbq';
|
|
|
5
5
|
import type { CartResponse } from '../../../../Api/types';
|
|
6
6
|
|
|
7
7
|
export function addPaymentInfoAction(cartPayload: CartResponse) {
|
|
8
|
+
if (!window.fbq) return;
|
|
9
|
+
|
|
8
10
|
const value = totalValue(cartPayload);
|
|
9
11
|
|
|
10
12
|
api.thirdParty
|
|
@@ -9,6 +9,8 @@ export function addToCartAction(
|
|
|
9
9
|
cartPayload: CartResponse,
|
|
10
10
|
upsertPayload?: UpsertTrackingCartRequest,
|
|
11
11
|
) {
|
|
12
|
+
if (!window.fbq) return;
|
|
13
|
+
|
|
12
14
|
getAddedCartItems(cartPayload, upsertPayload).forEach(item => {
|
|
13
15
|
const quantity = item.oldQuantity
|
|
14
16
|
? item.quantity - item.oldQuantity
|
|
@@ -5,6 +5,8 @@ import { pushFbq } from '../../../utils/pushFbq';
|
|
|
5
5
|
import type { CartResponse } from '../../../../Api/types';
|
|
6
6
|
|
|
7
7
|
export function initiateCheckoutAction(cartPayload: CartResponse) {
|
|
8
|
+
if (!window.fbq) return;
|
|
9
|
+
|
|
8
10
|
const value = totalValue(cartPayload);
|
|
9
11
|
|
|
10
12
|
api.thirdParty
|
|
@@ -5,6 +5,8 @@ import { pushFbq } from '../../../utils/pushFbq';
|
|
|
5
5
|
import type { CartResponse } from '../../../../Api/types';
|
|
6
6
|
|
|
7
7
|
export function purchaseAction(orderGroupId: number, cartPayload: CartResponse) {
|
|
8
|
+
if (!window.fbq) return;
|
|
9
|
+
|
|
8
10
|
const value = totalValue(cartPayload);
|
|
9
11
|
|
|
10
12
|
api.thirdParty
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import api from '../../../../Api';
|
|
2
|
+
import { pushFbq } from '../../../utils/pushFbq';
|
|
3
|
+
|
|
4
|
+
export function purchaseOrderAction(orderGroupId: number, value: number) {
|
|
5
|
+
if (!window.fbq) return;
|
|
6
|
+
|
|
7
|
+
api.thirdParty
|
|
8
|
+
.facebookPurchase({ orderGroupId })
|
|
9
|
+
.then(eventId =>
|
|
10
|
+
pushFbq(
|
|
11
|
+
'track',
|
|
12
|
+
'Purchase',
|
|
13
|
+
{ value, currency: 'BRL' },
|
|
14
|
+
{ eventID: eventId },
|
|
15
|
+
),
|
|
16
|
+
)
|
|
17
|
+
.catch(() => {});
|
|
18
|
+
}
|
|
@@ -2,6 +2,8 @@ import api from '../../../../Api';
|
|
|
2
2
|
import { pushFbq } from '../../../utils/pushFbq';
|
|
3
3
|
|
|
4
4
|
export function searchAction(searchTerm: string, contentIds: Array<string>) {
|
|
5
|
+
if (!window.fbq) return;
|
|
6
|
+
|
|
5
7
|
api.thirdParty
|
|
6
8
|
.facebookSearch({ searchTerm, contentIds })
|
|
7
9
|
.then(eventId =>
|
|
@@ -4,6 +4,8 @@ import { pushFbq } from '../../../utils/pushFbq';
|
|
|
4
4
|
import type { Product } from '../../../../Api/types';
|
|
5
5
|
|
|
6
6
|
export function viewContent(product: Product) {
|
|
7
|
+
if (!window.fbq) return;
|
|
8
|
+
|
|
7
9
|
api.thirdParty
|
|
8
10
|
.facebookViewContent({ productId: product.id })
|
|
9
11
|
.then(eventId =>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { pushDatalayer } from '../../../utils/pushDatalayer';
|
|
2
|
+
|
|
3
|
+
import type { CustomerOrderResponse } from '../../../../Api/types';
|
|
4
|
+
|
|
5
|
+
export function purchaseOrderAction(
|
|
6
|
+
paymentMethod: string,
|
|
7
|
+
orderGroup: CustomerOrderResponse,
|
|
8
|
+
) {
|
|
9
|
+
const coupon =
|
|
10
|
+
orderGroup.discounts?.find(discount => discount.type === 'coupon')
|
|
11
|
+
?.entityId ?? '';
|
|
12
|
+
|
|
13
|
+
pushDatalayer({
|
|
14
|
+
event: 'purchase',
|
|
15
|
+
ecommerce: {
|
|
16
|
+
currency: 'BRL',
|
|
17
|
+
affiliation: 'Loja Virtual',
|
|
18
|
+
|
|
19
|
+
payment_status: 'em aberto',
|
|
20
|
+
payment_type: paymentMethod,
|
|
21
|
+
|
|
22
|
+
shipping: orderGroup.values?.shippingValue ?? 0,
|
|
23
|
+
shipping_tier: orderGroup.orders[0]?.shipping?.label ?? '',
|
|
24
|
+
tax: 0,
|
|
25
|
+
transaction_id: orderGroup.code,
|
|
26
|
+
|
|
27
|
+
value: orderGroup.values?.totalValue ?? 0,
|
|
28
|
+
coupon,
|
|
29
|
+
items: orderGroup.orders
|
|
30
|
+
.flatMap(order => order.items)
|
|
31
|
+
.map(item => {
|
|
32
|
+
return {
|
|
33
|
+
item_category: '',
|
|
34
|
+
coupon,
|
|
35
|
+
// o item do pedido não carrega a marca, diferente do item do carrinho
|
|
36
|
+
item_brand: '',
|
|
37
|
+
item_id: item.productId,
|
|
38
|
+
item_name: item.name,
|
|
39
|
+
item_variant:
|
|
40
|
+
item.simpleProduct?.currentAttributes
|
|
41
|
+
?.map(attribute => attribute.value.label)
|
|
42
|
+
.join(', ') ?? '',
|
|
43
|
+
price: item.unitValue,
|
|
44
|
+
quantity: item.quantity,
|
|
45
|
+
};
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|