@infrab4a/connect-nestjs 2.0.0-alpha.9 → 3.0.0-alpha.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/eslint.config.js +17 -0
- package/package.json +4 -15
- package/project.json +49 -0
- package/rollup.config.js +17 -0
- package/src/consts/es-config.const.ts +1 -0
- package/src/consts/hasura-options.const.ts +1 -0
- package/src/consts/index.ts +4 -0
- package/src/consts/storage.const.ts +1 -0
- package/src/consts/vertex-config.const.ts +1 -0
- package/src/index.ts +7 -0
- package/src/infra/elasticsearch/adapters/index.ts +1 -0
- package/src/infra/elasticsearch/adapters/native-elasticsearch-adapter.ts +137 -0
- package/src/infra/elasticsearch/index.ts +1 -0
- package/src/infra/firebase/firestore/index.ts +2 -0
- package/src/infra/firebase/firestore/services/connect-collection-reference.ts +27 -0
- package/src/infra/firebase/firestore/services/connect-collection.service.ts +137 -0
- package/src/infra/firebase/firestore/services/connect-document-reference.ts +12 -0
- package/src/infra/firebase/firestore/services/connect-document.service.ts +51 -0
- package/src/infra/firebase/firestore/services/connect-firestore.service.ts +24 -0
- package/src/infra/firebase/firestore/services/connect-firestore.ts +9 -0
- package/src/infra/firebase/firestore/services/index.ts +6 -0
- package/src/infra/firebase/firestore/types/connect-query-snapshot.type.ts +6 -0
- package/src/infra/firebase/firestore/types/index.ts +1 -0
- package/src/infra/firebase/firestore/vo/connect-base-document-snapshot.vo.ts +27 -0
- package/src/infra/firebase/firestore/vo/index.ts +1 -0
- package/src/infra/firebase/index.ts +1 -0
- package/src/infra/index.ts +4 -0
- package/src/infra/pagarme/adapters/index.ts +3 -0
- package/src/infra/pagarme/adapters/pagarme-bank-slip-api.adapter.ts +96 -0
- package/src/infra/pagarme/adapters/pagarme-card-api.adapter.ts +226 -0
- package/src/infra/pagarme/adapters/pagarme-pix-api.adapter.ts +69 -0
- package/src/infra/pagarme/index.ts +1 -0
- package/src/infra/vertex-ai/adapters/discovery-engine-adapter.ts +148 -0
- package/src/infra/vertex-ai/adapters/index.ts +1 -0
- package/src/infra/vertex-ai/helpers/index.ts +1 -0
- package/src/infra/vertex-ai/helpers/product-vertex-ai.helper.ts +52 -0
- package/src/infra/vertex-ai/index.ts +3 -0
- package/src/infra/vertex-ai/types/index.ts +2 -0
- package/src/infra/vertex-ai/types/vertex-config.ts +23 -0
- package/src/infra/vertex-ai/types/vertex-search-result.ts +17 -0
- package/src/nest-connect.module.ts +36 -0
- package/src/nest-elastic-search.module.ts +26 -0
- package/src/nest-firestore.module.ts +363 -0
- package/src/nest-hasura-graphql.module.ts +227 -0
- package/src/nest-storage.module.ts +16 -0
- package/src/nest-vertex-ai-search.module.ts +26 -0
- package/src/types/pagarme.d.ts +25 -0
- package/tsconfig.json +15 -0
- package/tsconfig.lib.json +7 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +17 -0
- package/index.cjs.d.ts +0 -1
- package/index.cjs.default.js +0 -1
- package/index.cjs.js +0 -1334
- package/index.cjs.mjs +0 -2
- package/index.esm.js +0 -1317
- package/src/consts/es-config.const.d.ts +0 -1
- package/src/consts/hasura-options.const.d.ts +0 -1
- package/src/consts/index.d.ts +0 -4
- package/src/consts/storage.const.d.ts +0 -1
- package/src/consts/vertex-config.const.d.ts +0 -1
- package/src/index.d.ts +0 -7
- package/src/infra/elasticsearch/adapters/index.d.ts +0 -1
- package/src/infra/elasticsearch/adapters/native-elasticsearch-adapter.d.ts +0 -19
- package/src/infra/elasticsearch/index.d.ts +0 -1
- package/src/infra/firebase/firestore/index.d.ts +0 -2
- package/src/infra/firebase/firestore/services/connect-collection-reference.d.ts +0 -19
- package/src/infra/firebase/firestore/services/connect-collection.service.d.ts +0 -32
- package/src/infra/firebase/firestore/services/connect-document-reference.d.ts +0 -11
- package/src/infra/firebase/firestore/services/connect-document.service.d.ts +0 -17
- package/src/infra/firebase/firestore/services/connect-firestore.d.ts +0 -7
- package/src/infra/firebase/firestore/services/connect-firestore.service.d.ts +0 -8
- package/src/infra/firebase/firestore/services/index.d.ts +0 -6
- package/src/infra/firebase/firestore/types/connect-query-snapshot.type.d.ts +0 -4
- package/src/infra/firebase/firestore/types/index.d.ts +0 -1
- package/src/infra/firebase/firestore/vo/connect-base-document-snapshot.vo.d.ts +0 -12
- package/src/infra/firebase/firestore/vo/index.d.ts +0 -1
- package/src/infra/firebase/index.d.ts +0 -1
- package/src/infra/index.d.ts +0 -4
- package/src/infra/pagarme/adapters/index.d.ts +0 -3
- package/src/infra/pagarme/adapters/pagarme-bank-slip-api.adapter.d.ts +0 -9
- package/src/infra/pagarme/adapters/pagarme-card-api.adapter.d.ts +0 -21
- package/src/infra/pagarme/adapters/pagarme-pix-api.adapter.d.ts +0 -8
- package/src/infra/pagarme/index.d.ts +0 -1
- package/src/infra/vertex-ai/adapters/discovery-engine-adapter.d.ts +0 -17
- package/src/infra/vertex-ai/adapters/index.d.ts +0 -1
- package/src/infra/vertex-ai/helpers/index.d.ts +0 -1
- package/src/infra/vertex-ai/helpers/product-vertex-ai.helper.d.ts +0 -7
- package/src/infra/vertex-ai/index.d.ts +0 -3
- package/src/infra/vertex-ai/types/index.d.ts +0 -2
- package/src/infra/vertex-ai/types/vertex-config.d.ts +0 -23
- package/src/infra/vertex-ai/types/vertex-search-result.d.ts +0 -18
- package/src/nest-connect.module.d.ts +0 -13
- package/src/nest-elastic-search.module.d.ts +0 -5
- package/src/nest-firestore.module.d.ts +0 -10
- package/src/nest-hasura-graphql.module.d.ts +0 -13
- package/src/nest-storage.module.d.ts +0 -2
- package/src/nest-vertex-ai-search.module.d.ts +0 -5
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addDays,
|
|
3
|
+
BusinessError,
|
|
4
|
+
Checkout,
|
|
5
|
+
format,
|
|
6
|
+
PagarmeCredentials,
|
|
7
|
+
PagarmePaymentStatus,
|
|
8
|
+
Payment,
|
|
9
|
+
PaymentError,
|
|
10
|
+
PaymentProviderBankSlip,
|
|
11
|
+
PaymentRepository,
|
|
12
|
+
PaymentTransaction,
|
|
13
|
+
} from '@infrab4a/connect'
|
|
14
|
+
import pagarme from 'pagarme'
|
|
15
|
+
|
|
16
|
+
export class PagarmeBankSlipAPIAdapter implements PaymentProviderBankSlip {
|
|
17
|
+
constructor(private credentials: PagarmeCredentials, private paymentRepository: PaymentRepository) {}
|
|
18
|
+
|
|
19
|
+
public async pay(checkout: Checkout): Promise<Payment> {
|
|
20
|
+
try {
|
|
21
|
+
const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
|
|
22
|
+
const payload = this.createBoletoPayment(checkout)
|
|
23
|
+
const result = await client.transactions.create(payload)
|
|
24
|
+
|
|
25
|
+
console.warn('[PAGARME BOLETO DATA TO SEND]', payload)
|
|
26
|
+
console.warn('result PagarmeBankSlipAPIAdapter', JSON.stringify(result))
|
|
27
|
+
|
|
28
|
+
if (result.status !== PagarmePaymentStatus['Em processamento']) {
|
|
29
|
+
return Promise.reject(
|
|
30
|
+
new PaymentError('Houve uma falha ao gerar o boleto. Tente novamente', {
|
|
31
|
+
checkoutId: checkout.id,
|
|
32
|
+
userEmail: checkout.user.email,
|
|
33
|
+
info: result,
|
|
34
|
+
}),
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const payment = await this.paymentRepository.create({
|
|
39
|
+
createdAt: new Date(),
|
|
40
|
+
updatedAt: new Date(),
|
|
41
|
+
userId: checkout.user.id,
|
|
42
|
+
checkoutId: checkout.id,
|
|
43
|
+
totalPrice: checkout.totalPrice,
|
|
44
|
+
paymentProvider: 'pagarMe',
|
|
45
|
+
transaction: result,
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
return payment
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Error PagarmeBankSlipAPIAdapter', JSON.stringify(error))
|
|
51
|
+
throw new PaymentError('Houve uma falha ao gerar o boleto. Tente novamente', {
|
|
52
|
+
checkoutId: checkout.id,
|
|
53
|
+
userEmail: checkout.user.email,
|
|
54
|
+
info: error,
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public async getBoletoTransaction(paymentId: number): Promise<PaymentTransaction> {
|
|
60
|
+
try {
|
|
61
|
+
const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
|
|
62
|
+
const result = await client.transactions.find({ id: paymentId })
|
|
63
|
+
|
|
64
|
+
return result as PaymentTransaction
|
|
65
|
+
} catch (error) {
|
|
66
|
+
throw new BusinessError('Houve uma falha buscar o boleto com paymentId: ' + paymentId, {
|
|
67
|
+
paymentId,
|
|
68
|
+
info: error,
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private createBoletoPayment(checkout: Checkout) {
|
|
74
|
+
return {
|
|
75
|
+
api_key: this.credentials.API_KEY,
|
|
76
|
+
amount: Math.floor(checkout.totalPrice * 100),
|
|
77
|
+
boleto_rules: ['strict_expiration_date'],
|
|
78
|
+
boleto_instructions: 'Sr. Caixa, NÃO aceitar o pagamento após o vencimento.',
|
|
79
|
+
boleto_expiration_date: format(addDays(new Date(), 3), 'yyyy-MM-dd'),
|
|
80
|
+
payment_method: 'boleto',
|
|
81
|
+
postback_url: this.credentials.URL_POSTBACK,
|
|
82
|
+
customer: {
|
|
83
|
+
external_id: checkout.user.id,
|
|
84
|
+
type: 'individual',
|
|
85
|
+
country: 'br',
|
|
86
|
+
name: checkout.user.displayName,
|
|
87
|
+
documents: [
|
|
88
|
+
{
|
|
89
|
+
type: 'cpf',
|
|
90
|
+
number: checkout.user.cpf,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BusinessError,
|
|
3
|
+
BusinessUnitEnum,
|
|
4
|
+
CardInfo,
|
|
5
|
+
Checkout,
|
|
6
|
+
LineItem,
|
|
7
|
+
OrderBlockedRepository,
|
|
8
|
+
PagarMeCard,
|
|
9
|
+
PagarmeCredentials,
|
|
10
|
+
PagarmePaymentStatus,
|
|
11
|
+
Payment,
|
|
12
|
+
PaymentCardInfo,
|
|
13
|
+
PaymentError,
|
|
14
|
+
PaymentProviderCard,
|
|
15
|
+
PaymentProviders,
|
|
16
|
+
PaymentRepository,
|
|
17
|
+
PaymentTransaction,
|
|
18
|
+
Shops,
|
|
19
|
+
} from '@infrab4a/connect'
|
|
20
|
+
import pagarme from 'pagarme'
|
|
21
|
+
|
|
22
|
+
export class PagarmeCardAPIAdapter implements PaymentProviderCard<PagarMeCard> {
|
|
23
|
+
constructor(
|
|
24
|
+
private credentials: PagarmeCredentials,
|
|
25
|
+
private paymentRepository: PaymentRepository,
|
|
26
|
+
private orderBlockedRepository: OrderBlockedRepository,
|
|
27
|
+
) {}
|
|
28
|
+
|
|
29
|
+
public async pay(checkout: Checkout, card: PaymentCardInfo): Promise<Payment> {
|
|
30
|
+
try {
|
|
31
|
+
const client = await this.createPagarmeClient()
|
|
32
|
+
const transactionResult = await this.executeCardTransaction(client, checkout, card)
|
|
33
|
+
|
|
34
|
+
await this.validateTransactionResult(transactionResult, checkout, card)
|
|
35
|
+
|
|
36
|
+
return await this.createPaymentRecord(checkout, transactionResult)
|
|
37
|
+
} catch (error) {
|
|
38
|
+
this.handlePaymentError(error, checkout)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private async createPagarmeClient() {
|
|
43
|
+
return await pagarme.client.connect({ api_key: this.credentials.API_KEY })
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private async executeCardTransaction(client: any, checkout: Checkout, card: PaymentCardInfo) {
|
|
47
|
+
const payload = this.createCardPayment(checkout, card)
|
|
48
|
+
const result = await client.transactions.create(payload)
|
|
49
|
+
|
|
50
|
+
this.logTransactionDetails(payload, result)
|
|
51
|
+
|
|
52
|
+
return result
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private logTransactionDetails(payload: any, result: any): void {
|
|
56
|
+
console.warn('[PAGARME CARD DATA TO SEND]', payload)
|
|
57
|
+
console.warn('result PagarmeCardAPIAdapter', JSON.stringify(result))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private async validateTransactionResult(result: any, checkout: Checkout, card: PaymentCardInfo): Promise<void> {
|
|
61
|
+
if (result.status !== PagarmePaymentStatus.Pago) {
|
|
62
|
+
await this.handleUnauthorizedPayment(checkout, card, result)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private async handleUnauthorizedPayment(checkout: Checkout, card: PaymentCardInfo, result: any): Promise<never> {
|
|
67
|
+
await this.createBlockedOrderRecord(checkout, card)
|
|
68
|
+
|
|
69
|
+
throw new PaymentError(
|
|
70
|
+
'Seu pagamento com cartão não foi autorizado. Para não perder seus produtos, pague com PIX ou outro cartão de crédito',
|
|
71
|
+
{
|
|
72
|
+
checkoutId: checkout.id,
|
|
73
|
+
userEmail: checkout.user.email,
|
|
74
|
+
info: result,
|
|
75
|
+
},
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private async createBlockedOrderRecord(checkout: Checkout, card: PaymentCardInfo): Promise<void> {
|
|
80
|
+
await this.orderBlockedRepository.createBlockedOrderOrPayment({
|
|
81
|
+
checkout,
|
|
82
|
+
blockType: 'Card not authorized',
|
|
83
|
+
type: 'Card',
|
|
84
|
+
limiteRange: 'day',
|
|
85
|
+
card,
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private async createPaymentRecord(checkout: Checkout, transactionResult: any): Promise<Payment> {
|
|
90
|
+
return await this.paymentRepository.create({
|
|
91
|
+
createdAt: new Date(),
|
|
92
|
+
updatedAt: new Date(),
|
|
93
|
+
userId: checkout.user.id,
|
|
94
|
+
checkoutId: checkout.id,
|
|
95
|
+
totalPrice: checkout.totalPrice,
|
|
96
|
+
paymentProvider: PaymentProviders.PAGARME,
|
|
97
|
+
transaction: { ...transactionResult, paidAt: new Date() },
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private handlePaymentError(error: any, checkout: Checkout): never {
|
|
102
|
+
console.error('Error PagarmeCardAPIAdapter', JSON.stringify(error))
|
|
103
|
+
|
|
104
|
+
throw new PaymentError(
|
|
105
|
+
'Seu pagamento com cartão não foi autorizado. Para não perder seus produtos, pague com PIX ou outro cartão de crédito',
|
|
106
|
+
{
|
|
107
|
+
checkoutId: checkout.id,
|
|
108
|
+
userEmail: checkout.user.email,
|
|
109
|
+
info: error,
|
|
110
|
+
},
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public async addCard(card: CardInfo): Promise<PagarMeCard> {
|
|
115
|
+
try {
|
|
116
|
+
const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
|
|
117
|
+
const result = await client.cards.create({
|
|
118
|
+
card_number: card.number,
|
|
119
|
+
card_expiration_date: card.expirationDate.replace('/', ''),
|
|
120
|
+
card_holder_name: card.name,
|
|
121
|
+
card_cvv: card.cvv,
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
return result as PagarMeCard
|
|
125
|
+
} catch (error) {
|
|
126
|
+
throw new BusinessError('Houve uma falha adicionar o cartão', {
|
|
127
|
+
info: error,
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public async createCardHash(bu: BusinessUnitEnum, card: CardInfo): Promise<string> {
|
|
133
|
+
try {
|
|
134
|
+
const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
|
|
135
|
+
const result = await client.security.encrypt({
|
|
136
|
+
card_number: card.number,
|
|
137
|
+
card_expiration_date: card.expirationDate.replace('/', ''),
|
|
138
|
+
card_holder_name: card.name,
|
|
139
|
+
card_cvv: card.cvv,
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
return result as string
|
|
143
|
+
} catch (error) {
|
|
144
|
+
throw new BusinessError('Houve uma falha ao gerar o hash do cartão', {
|
|
145
|
+
info: error,
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public async getCardByToken(id: string): Promise<PagarMeCard> {
|
|
151
|
+
try {
|
|
152
|
+
const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
|
|
153
|
+
const result = await client.cards.find({
|
|
154
|
+
id,
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
return result as PagarMeCard
|
|
158
|
+
} catch (error) {
|
|
159
|
+
throw new BusinessError('Houve uma falha buscar o cartão com id: ' + id, {
|
|
160
|
+
info: error,
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public async createTransaction(data: any): Promise<PaymentTransaction> {
|
|
166
|
+
try {
|
|
167
|
+
const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
|
|
168
|
+
const result = await client.transactions.create(data)
|
|
169
|
+
|
|
170
|
+
return result as PaymentTransaction
|
|
171
|
+
} catch (error) {
|
|
172
|
+
throw new BusinessError('Houve uma falha ao criar a transação', {
|
|
173
|
+
info: error,
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private createCardPayment(checkout: Checkout, card: PaymentCardInfo) {
|
|
179
|
+
return {
|
|
180
|
+
api_key: this.credentials.API_KEY,
|
|
181
|
+
amount: Math.floor(checkout.totalPrice * 100),
|
|
182
|
+
card_id: card.cardId,
|
|
183
|
+
card_cvv: card.cardCvv,
|
|
184
|
+
payment_method: 'credit_card',
|
|
185
|
+
installments: card.installments,
|
|
186
|
+
soft_descriptor: checkout.shop === Shops.GLAMSHOP ? 'Glam' : "Men's Market",
|
|
187
|
+
customer: {
|
|
188
|
+
external_id: checkout.user.id,
|
|
189
|
+
name: checkout.user.displayName,
|
|
190
|
+
type: 'individual',
|
|
191
|
+
country: 'br',
|
|
192
|
+
email: checkout.user.email,
|
|
193
|
+
phone_numbers: checkout.user.phone ? ['+55' + checkout.user.phone] : '',
|
|
194
|
+
documents: [
|
|
195
|
+
{
|
|
196
|
+
type: 'cpf',
|
|
197
|
+
number: checkout.user.cpf,
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
billing: {
|
|
202
|
+
name: checkout.user.displayName,
|
|
203
|
+
address: {
|
|
204
|
+
country: 'br',
|
|
205
|
+
state: checkout.billingAddress ? checkout.billingAddress.state : checkout.shippingAddress?.state,
|
|
206
|
+
city: checkout.billingAddress ? checkout.billingAddress.city : checkout.shippingAddress?.city,
|
|
207
|
+
neighborhood: checkout.billingAddress ? checkout.billingAddress.district : checkout.shippingAddress?.district,
|
|
208
|
+
street: checkout.billingAddress ? checkout.billingAddress.street : checkout.shippingAddress?.street,
|
|
209
|
+
street_number: checkout.billingAddress ? checkout.billingAddress.number : checkout.shippingAddress?.number,
|
|
210
|
+
zipcode: checkout.billingAddress
|
|
211
|
+
? checkout.billingAddress.zip.replace('-', '')
|
|
212
|
+
: checkout.shippingAddress?.zip.replace('-', ''),
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
items: checkout.lineItems.map((item: LineItem) => {
|
|
216
|
+
return {
|
|
217
|
+
id: item.id,
|
|
218
|
+
title: checkout.user.isSubscriber ? `${item.name} - ASSINANTE` : item.name,
|
|
219
|
+
unit_price: Math.floor(item.pricePaid * 100),
|
|
220
|
+
quantity: item.quantity,
|
|
221
|
+
tangible: true,
|
|
222
|
+
}
|
|
223
|
+
}),
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addDays,
|
|
3
|
+
Checkout,
|
|
4
|
+
format,
|
|
5
|
+
PagarmeCredentials,
|
|
6
|
+
Payment,
|
|
7
|
+
PaymentError,
|
|
8
|
+
PaymentProviderPix,
|
|
9
|
+
PaymentRepository,
|
|
10
|
+
} from '@infrab4a/connect'
|
|
11
|
+
import pagarme from 'pagarme'
|
|
12
|
+
|
|
13
|
+
export class PagarmePixAPIAdapter implements PaymentProviderPix {
|
|
14
|
+
constructor(private credentials: PagarmeCredentials, private paymentRepository: PaymentRepository) {}
|
|
15
|
+
|
|
16
|
+
public async pay(checkout: Checkout): Promise<Payment> {
|
|
17
|
+
try {
|
|
18
|
+
const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
|
|
19
|
+
const payload = this.createPixPayment(checkout)
|
|
20
|
+
const result = await client.transactions.create(payload)
|
|
21
|
+
|
|
22
|
+
console.warn('[PAGARME PIX DATA TO SEND]', payload)
|
|
23
|
+
console.warn('result PagarmePixAPIAdapter', JSON.stringify(result))
|
|
24
|
+
|
|
25
|
+
const payment = await this.paymentRepository.create({
|
|
26
|
+
createdAt: new Date(),
|
|
27
|
+
updatedAt: new Date(),
|
|
28
|
+
userId: checkout.user.id,
|
|
29
|
+
checkoutId: checkout.id,
|
|
30
|
+
totalPrice: checkout.totalPrice,
|
|
31
|
+
paymentProvider: 'pagarMe',
|
|
32
|
+
transaction: result,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return payment
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error('Error PagarmePixAPIAdapter', JSON.stringify(error))
|
|
38
|
+
throw new PaymentError('Houve uma falha ao processar pagamento com pix', {
|
|
39
|
+
checkoutId: checkout.id,
|
|
40
|
+
userEmail: checkout.user.email,
|
|
41
|
+
info: error,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private createPixPayment(checkout: Checkout) {
|
|
47
|
+
return {
|
|
48
|
+
payment_method: 'pix',
|
|
49
|
+
amount: Math.floor(checkout.totalPrice * 100),
|
|
50
|
+
api_key: this.credentials.API_KEY,
|
|
51
|
+
postback_url: this.credentials.URL_POSTBACK,
|
|
52
|
+
pix_expiration_date: format(addDays(new Date(), 1), 'yyyy-MM-dd'),
|
|
53
|
+
customer: {
|
|
54
|
+
external_id: checkout.user.id,
|
|
55
|
+
type: 'individual',
|
|
56
|
+
country: 'br',
|
|
57
|
+
name: checkout.user.displayName,
|
|
58
|
+
email: checkout.user.email.trim(),
|
|
59
|
+
phone_numbers: checkout.user.phone ? ['+55' + checkout.user.phone] : '',
|
|
60
|
+
documents: [
|
|
61
|
+
{
|
|
62
|
+
type: 'cpf',
|
|
63
|
+
number: checkout.user.cpf,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './adapters'
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { DocumentServiceClient } from '@google-cloud/discoveryengine'
|
|
2
|
+
import { SearchServiceClient } from '@google-cloud/discoveryengine/build/src/v1beta'
|
|
3
|
+
import { ProductBulk, ProductHasuraGraphQL, ProductSearch, VertexSearchAdapter } from '@infrab4a/connect'
|
|
4
|
+
import { Inject, Injectable } from '@nestjs/common'
|
|
5
|
+
|
|
6
|
+
import { VERTEX_CONFIG } from '../../../consts'
|
|
7
|
+
import { ProductVertexHelper } from '../helpers/product-vertex-ai.helper'
|
|
8
|
+
import { VertexConfig, VertexSearchResult } from '../types'
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class DiscoveryEngineVertexAdapter implements VertexSearchAdapter<ProductSearch> {
|
|
12
|
+
private config: VertexConfig
|
|
13
|
+
private parentEngine: string
|
|
14
|
+
private parentDataStore: string
|
|
15
|
+
private servingConfig: string
|
|
16
|
+
private searchClient
|
|
17
|
+
private documentClient
|
|
18
|
+
|
|
19
|
+
constructor(@Inject(VERTEX_CONFIG) configuration: VertexConfig) {
|
|
20
|
+
this.config = configuration
|
|
21
|
+
this.parentEngine =
|
|
22
|
+
`projects/${this.config.projectId}/locations/${this.config.location}/` +
|
|
23
|
+
`collections/default_collection/engines/${this.config.dataStoreId}`
|
|
24
|
+
this.parentDataStore =
|
|
25
|
+
`projects/${this.config.projectId}/locations/${this.config.location}/` +
|
|
26
|
+
`collections/default_collection/dataStores/${this.config.dataStoreId}/branches/default_branch/documents`
|
|
27
|
+
this.searchClient = new SearchServiceClient({
|
|
28
|
+
apiEndpoint: configuration.apiEndpoint,
|
|
29
|
+
credentials: configuration.credentials,
|
|
30
|
+
})
|
|
31
|
+
this.documentClient = new DocumentServiceClient({
|
|
32
|
+
apiEndpoint: configuration.apiEndpoint,
|
|
33
|
+
credentials: configuration.credentials,
|
|
34
|
+
})
|
|
35
|
+
this.servingConfig = this.searchClient.projectLocationCollectionDataStoreServingConfigPath(
|
|
36
|
+
configuration.projectId,
|
|
37
|
+
configuration.location,
|
|
38
|
+
configuration.collectionId,
|
|
39
|
+
configuration.dataStoreId,
|
|
40
|
+
configuration.servingConfigId,
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public async save(product: ProductHasuraGraphQL) {
|
|
45
|
+
const productSearch = ProductVertexHelper.productMapper(product)
|
|
46
|
+
|
|
47
|
+
const request = {
|
|
48
|
+
parent: this.parentEngine,
|
|
49
|
+
allowMissing: true,
|
|
50
|
+
document: {
|
|
51
|
+
name: this.parentDataStore + `/${product.id}`,
|
|
52
|
+
jsonData: JSON.stringify(productSearch),
|
|
53
|
+
data: 'jsonData',
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const response = await this.documentClient.updateDocument(request)
|
|
58
|
+
|
|
59
|
+
return response
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public async update(id: string, data: ProductHasuraGraphQL) {
|
|
63
|
+
const productSearch = ProductVertexHelper.productMapper(data)
|
|
64
|
+
|
|
65
|
+
const request = {
|
|
66
|
+
parent: this.parentEngine,
|
|
67
|
+
allowMissing: true,
|
|
68
|
+
document: {
|
|
69
|
+
name: this.parentDataStore + `/${id}`,
|
|
70
|
+
jsonData: JSON.stringify(productSearch),
|
|
71
|
+
data: 'jsonData',
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const response = await this.documentClient.updateDocument(request)
|
|
76
|
+
|
|
77
|
+
return response
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public async query(term: string, total: number) {
|
|
81
|
+
const response = (await this.searchClient.search(
|
|
82
|
+
{
|
|
83
|
+
pageSize: total,
|
|
84
|
+
query: term,
|
|
85
|
+
filter: '',
|
|
86
|
+
languageCode: 'pt-BR',
|
|
87
|
+
servingConfig: this.servingConfig,
|
|
88
|
+
relevanceThreshold: 'MEDIUM',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
autoPaginate: false,
|
|
92
|
+
},
|
|
93
|
+
)) as VertexSearchResult<ProductSearch>
|
|
94
|
+
|
|
95
|
+
return ProductVertexHelper.resultProductMapper(response)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public async get(id: string) {
|
|
99
|
+
const request = {
|
|
100
|
+
name: this.parentDataStore + `/${id}`,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const response = await this.documentClient.getDocument(request)
|
|
104
|
+
const document = JSON.parse(response[0].jsonData)
|
|
105
|
+
|
|
106
|
+
return document
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public async delete(id: string) {
|
|
110
|
+
const request = {
|
|
111
|
+
name: this.parentDataStore + `/${id}`,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
await this.documentClient.deleteDocument(request)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public async bulkProducts(products: ProductBulk[]): Promise<void> {
|
|
118
|
+
try {
|
|
119
|
+
const batchSize = 100
|
|
120
|
+
let total = 0
|
|
121
|
+
|
|
122
|
+
for (let index = 0; index < products.length; index += batchSize) {
|
|
123
|
+
const bulkProducts = products.slice(index, index + batchSize)
|
|
124
|
+
|
|
125
|
+
const [operation] = await this.documentClient.importDocuments({
|
|
126
|
+
parent:
|
|
127
|
+
`projects/${this.config.projectId}/locations/${this.config.location}/` +
|
|
128
|
+
`collections/default_collection/dataStores/${this.config.dataStoreId}/branches/default_branch`,
|
|
129
|
+
inlineSource: {
|
|
130
|
+
documents: bulkProducts,
|
|
131
|
+
},
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
total += bulkProducts.length
|
|
135
|
+
const [response] = await operation.promise()
|
|
136
|
+
|
|
137
|
+
console.warn(
|
|
138
|
+
`Imported: ${total} documents`,
|
|
139
|
+
((total / products.length) * 100).toFixed(2) + '%',
|
|
140
|
+
'Erros: ',
|
|
141
|
+
response.errorSamples ? response.errorSamples : [],
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error(error)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './discovery-engine-adapter'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './product-vertex-ai.helper'
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ProductHasuraGraphQL, ProductSearch } from '@infrab4a/connect'
|
|
2
|
+
|
|
3
|
+
import { VertexSearchResult } from '../types'
|
|
4
|
+
|
|
5
|
+
export class ProductVertexHelper {
|
|
6
|
+
constructor() {}
|
|
7
|
+
|
|
8
|
+
public static productMapper(product: ProductHasuraGraphQL): ProductSearch {
|
|
9
|
+
const image = product.miniatures && (product.miniatures as string[]).length ? product.miniatures[0] : null
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
id: product.id.toString(),
|
|
13
|
+
miniatures: image,
|
|
14
|
+
icon: image,
|
|
15
|
+
name: product.name,
|
|
16
|
+
brand: product.brand?.toString().trim() ? product.brand?.toString().trim() : null,
|
|
17
|
+
ean: product.EAN,
|
|
18
|
+
sku: product.sku,
|
|
19
|
+
slug: product.slug,
|
|
20
|
+
published: product.published,
|
|
21
|
+
gender: product.gender,
|
|
22
|
+
stock: product.stock.quantity,
|
|
23
|
+
rating: product.rate,
|
|
24
|
+
shoppingCount: product.shoppingCount,
|
|
25
|
+
description: product.description.description,
|
|
26
|
+
fullPrice: product.fullPrice,
|
|
27
|
+
price: product.price.price,
|
|
28
|
+
subscriberPrice: product.subscriberPrice,
|
|
29
|
+
outlet: product.outlet,
|
|
30
|
+
createdAt: product.createdAt,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public static resultProductMapper(result: VertexSearchResult<ProductSearch>): ProductSearch[] {
|
|
35
|
+
return result[0].length
|
|
36
|
+
? result[0].map((result) => {
|
|
37
|
+
return {
|
|
38
|
+
id: result.document?.structData.fields.id.stringValue,
|
|
39
|
+
name: result.document?.structData.fields.name.stringValue,
|
|
40
|
+
brand: result.document?.structData.fields.brand?.stringValue,
|
|
41
|
+
stock: result.document?.structData.fields.stock?.numberValue,
|
|
42
|
+
rating: result.document?.structData.fields.rating?.stringValue,
|
|
43
|
+
gender: result.document?.structData.fields.gender?.stringValue,
|
|
44
|
+
slug: result.document?.structData.fields.slug?.stringValue,
|
|
45
|
+
sku: result.document?.structData.fields.sku?.stringValue,
|
|
46
|
+
ean: result.document?.structData.fields.ean?.stringValue,
|
|
47
|
+
description: result.document?.structData.fields.description?.stringValue,
|
|
48
|
+
} as any
|
|
49
|
+
})
|
|
50
|
+
: []
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type VertexConfig = {
|
|
2
|
+
credentials: {
|
|
3
|
+
type: string
|
|
4
|
+
project_id: string
|
|
5
|
+
private_key_id: string
|
|
6
|
+
private_key: string
|
|
7
|
+
client_email: string
|
|
8
|
+
client_id: string
|
|
9
|
+
auth_uri?: string
|
|
10
|
+
token_uri?: string
|
|
11
|
+
auth_provider_x509_cert_url?: string
|
|
12
|
+
client_x509_cert_url?: string
|
|
13
|
+
apiKey?: string
|
|
14
|
+
authDomain?: string
|
|
15
|
+
}
|
|
16
|
+
apiEndpoint: string
|
|
17
|
+
projectId: string
|
|
18
|
+
location: string
|
|
19
|
+
dataStoreId: string
|
|
20
|
+
collectionId: string
|
|
21
|
+
engine: string
|
|
22
|
+
servingConfigId: string
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { protos } from '@google-cloud/discoveryengine'
|
|
2
|
+
|
|
3
|
+
export type VertexSearchResult<T> = [
|
|
4
|
+
VertexResult<T>[],
|
|
5
|
+
protos.google.cloud.discoveryengine.v1.ISearchRequest | null,
|
|
6
|
+
protos.google.cloud.discoveryengine.v1.ISearchResponse,
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
type VertexResult<T> = {
|
|
10
|
+
id?: string | null
|
|
11
|
+
document?: {
|
|
12
|
+
structData: {
|
|
13
|
+
fields: { [P in keyof T]: any }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
chunk?: protos.google.cloud.discoveryengine.v1.IChunk
|
|
17
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { isNil } from '@infrab4a/connect'
|
|
2
|
+
import { DynamicModule, Module } from '@nestjs/common'
|
|
3
|
+
|
|
4
|
+
import { ESClientOptions, VertexConfig } from './infra'
|
|
5
|
+
import { NestElasticSeachModule } from './nest-elastic-search.module'
|
|
6
|
+
import { NestFirestoreModule } from './nest-firestore.module'
|
|
7
|
+
import { HasuraGraphQLOptions, NestHasuraGraphQLModule } from './nest-hasura-graphql.module'
|
|
8
|
+
import { NestVertexSeachModule } from './nest-vertex-ai-search.module'
|
|
9
|
+
|
|
10
|
+
@Module({})
|
|
11
|
+
export class NestConnectModule {
|
|
12
|
+
public static initializeApp(options: {
|
|
13
|
+
firebase?: {
|
|
14
|
+
googleApplicationCredential: string
|
|
15
|
+
}
|
|
16
|
+
elasticSearch?: ESClientOptions
|
|
17
|
+
hasura: HasuraGraphQLOptions
|
|
18
|
+
vertex?: VertexConfig
|
|
19
|
+
}): DynamicModule {
|
|
20
|
+
return {
|
|
21
|
+
module: NestConnectModule,
|
|
22
|
+
imports: [
|
|
23
|
+
...(options.firebase ? [NestFirestoreModule.initializeApp({ firebase: options.firebase })] : []),
|
|
24
|
+
...(isNil(options?.hasura) ? [] : [NestHasuraGraphQLModule.initializeApp(options.hasura)]),
|
|
25
|
+
...(isNil(options?.elasticSearch) ? [] : [NestElasticSeachModule.initializeApp(options.elasticSearch)]),
|
|
26
|
+
...(isNil(options?.vertex) ? [] : [NestVertexSeachModule.initializeApp(options.vertex)]),
|
|
27
|
+
],
|
|
28
|
+
exports: [
|
|
29
|
+
...(options.firebase ? [NestFirestoreModule] : []),
|
|
30
|
+
...(isNil(options?.hasura) ? [] : [NestHasuraGraphQLModule]),
|
|
31
|
+
...(isNil(options?.elasticSearch) ? [] : [NestElasticSeachModule]),
|
|
32
|
+
...(isNil(options?.vertex) ? [] : [NestVertexSeachModule]),
|
|
33
|
+
],
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|