@infrab4a/connect 5.3.0-beta.30 → 5.3.0-beta.32
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/index.cjs.js +333 -92
- package/index.esm.js +324 -74
- package/package.json +1 -1
- package/src/domain/shop-settings/models/shop-configs.d.ts +3 -12
- package/src/domain/shop-settings/models/types/antifraud-config.type.d.ts +21 -0
- package/src/domain/shop-settings/models/types/index.d.ts +1 -0
- package/src/domain/shop-settings/models/types/limit-orders.type.d.ts +3 -2
- package/src/domain/shopping/helpers/antifraud-enabled.helper.d.ts +8 -0
- package/src/domain/shopping/helpers/antifraud-volume-limits.helper.d.ts +6 -0
- package/src/domain/shopping/helpers/index.d.ts +2 -0
- package/src/domain/shopping/index.d.ts +1 -0
- package/src/domain/shopping/models/campaign-hashtag-posts.d.ts +23 -0
- package/src/domain/shopping/models/campaign-hashtag.d.ts +12 -10
- package/src/domain/shopping/models/checkout.d.ts +2 -0
- package/src/domain/shopping/models/coupons/coupon.d.ts +1 -0
- package/src/domain/shopping/models/index.d.ts +1 -0
- package/src/domain/shopping/models/line-item.d.ts +4 -0
- package/src/domain/shopping/models/order.d.ts +1 -0
- package/src/domain/shopping/models/shipping-method.d.ts +1 -0
- package/src/domain/shopping/models/types/line-item-recurrence.type.d.ts +1 -1
- package/src/domain/shopping/repositories/campaign-hashtag-posts.repository.d.ts +4 -0
- package/src/domain/shopping/repositories/index.d.ts +1 -0
- package/src/domain/shopping/services/antifraud-bankslip.service.d.ts +3 -1
- package/src/domain/shopping/services/antifraud-card.service.d.ts +6 -6
- package/src/domain/shopping/services/antifraud-glampoints.service.d.ts +4 -2
- package/src/domain/shopping/services/antifraud-pix.service.d.ts +4 -2
- package/src/domain/shopping/types/antifraud-card-validation.type.d.ts +40 -0
- package/src/domain/shopping/types/antifraud-volume-limits.type.d.ts +24 -0
- package/src/domain/shopping/types/create-recurrency-payload.type.d.ts +0 -2
- package/src/domain/shopping/types/index.d.ts +3 -0
- package/src/domain/shopping/types/shopping-recurrence-update-payloads.type.d.ts +35 -0
- package/src/infra/cache/index.d.ts +1 -0
- package/src/infra/cache/resolve-cache-config.d.ts +2 -0
- package/src/infra/cache/restcache.adapter.d.ts +3 -0
- package/src/infra/firebase/firestore/repositories/shopping/campaign-hashtag-posts-firestore.repository.d.ts +8 -0
- package/src/infra/firebase/firestore/repositories/shopping/index.d.ts +1 -0
- package/src/utils/index.d.ts +1 -0
- package/src/utils/to-cents.d.ts +5 -0
package/index.cjs.js
CHANGED
|
@@ -20,25 +20,7 @@ var storage = require('firebase/storage');
|
|
|
20
20
|
|
|
21
21
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
if (e && e.__esModule) return e;
|
|
25
|
-
var n = Object.create(null);
|
|
26
|
-
if (e) {
|
|
27
|
-
Object.keys(e).forEach(function (k) {
|
|
28
|
-
if (k !== 'default') {
|
|
29
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
30
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
31
|
-
enumerable: true,
|
|
32
|
-
get: function () { return e[k]; }
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
n["default"] = e;
|
|
38
|
-
return Object.freeze(n);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
var serializeJavascript__namespace = /*#__PURE__*/_interopNamespace(serializeJavascript);
|
|
23
|
+
var serializeJavascript__default = /*#__PURE__*/_interopDefaultLegacy(serializeJavascript);
|
|
42
24
|
var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
|
|
43
25
|
|
|
44
26
|
exports.AntifraudProviders = void 0;
|
|
@@ -175,6 +157,123 @@ class PaymentProviderFactory {
|
|
|
175
157
|
}
|
|
176
158
|
}
|
|
177
159
|
|
|
160
|
+
const ANTIFRAUD_CONFIG_CACHE_TTL_SECONDS = 60;
|
|
161
|
+
/**
|
|
162
|
+
* Lê `shopConfigs.antifraude.enabled`.
|
|
163
|
+
* - `false` explícito → antifraude desligado
|
|
164
|
+
* - ausente / erro / inválido → `true` (mantém comportamento histórico)
|
|
165
|
+
*/
|
|
166
|
+
async function isAntifraudEnabled(shopConfigsRepository) {
|
|
167
|
+
if (!shopConfigsRepository) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const result = await shopConfigsRepository.find({}, { cache: { enabled: true, ttl: ANTIFRAUD_CONFIG_CACHE_TTL_SECONDS } });
|
|
172
|
+
const enabled = result?.data?.at(0)?.antifraude?.enabled;
|
|
173
|
+
if (typeof enabled === 'boolean') {
|
|
174
|
+
return enabled;
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
console.warn(JSON.stringify({
|
|
180
|
+
msg: 'antifraud_enabled_config_load_failed',
|
|
181
|
+
enabled: true,
|
|
182
|
+
error: error instanceof Error ? error.message : String(error),
|
|
183
|
+
}));
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Defaults de runtime (week.zip = Infinity). Usados só como fallback no checkout. */
|
|
189
|
+
const DEFAULT_ANTIFRAUD_VOLUME_LIMITS = {
|
|
190
|
+
enabled: true,
|
|
191
|
+
source: 'fallback',
|
|
192
|
+
day: {
|
|
193
|
+
subscriber: { cpf: 4, email: 4, phone: 4, card: 4, zip: 4 },
|
|
194
|
+
nonSubscriber: { cpf: 2, email: 2, phone: 2, card: 2, zip: 2 },
|
|
195
|
+
},
|
|
196
|
+
week: {
|
|
197
|
+
subscriber: { cpf: 12, email: 12, phone: 12, card: 12, zip: Infinity },
|
|
198
|
+
nonSubscriber: { cpf: 7, email: 7, phone: 7, card: 7, zip: Infinity },
|
|
199
|
+
},
|
|
200
|
+
blockedAttemptsDay: {
|
|
201
|
+
subscriber: 7,
|
|
202
|
+
nonSubscriber: 5,
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
function isPositiveInteger(value) {
|
|
206
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 1 && Number.isInteger(value);
|
|
207
|
+
}
|
|
208
|
+
function normalizeLimitOrders(raw, allowInfiniteZip) {
|
|
209
|
+
if (!raw)
|
|
210
|
+
return null;
|
|
211
|
+
const zip = allowInfiniteZip && (raw.zip === null || raw.zip === undefined || raw.zip === Infinity) ? Infinity : raw.zip;
|
|
212
|
+
const normalized = {
|
|
213
|
+
cpf: raw.cpf,
|
|
214
|
+
email: raw.email,
|
|
215
|
+
phone: raw.phone,
|
|
216
|
+
zip: zip,
|
|
217
|
+
card: raw.card,
|
|
218
|
+
};
|
|
219
|
+
for (const key of ['cpf', 'email', 'phone', 'zip', 'card']) {
|
|
220
|
+
if (key === 'zip' && normalized.zip === Infinity)
|
|
221
|
+
continue;
|
|
222
|
+
if (!isPositiveInteger(normalized[key]))
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return normalized;
|
|
226
|
+
}
|
|
227
|
+
function cloneFallbackLimits() {
|
|
228
|
+
return {
|
|
229
|
+
...DEFAULT_ANTIFRAUD_VOLUME_LIMITS,
|
|
230
|
+
day: {
|
|
231
|
+
subscriber: { ...DEFAULT_ANTIFRAUD_VOLUME_LIMITS.day.subscriber },
|
|
232
|
+
nonSubscriber: { ...DEFAULT_ANTIFRAUD_VOLUME_LIMITS.day.nonSubscriber },
|
|
233
|
+
},
|
|
234
|
+
week: {
|
|
235
|
+
subscriber: { ...DEFAULT_ANTIFRAUD_VOLUME_LIMITS.week.subscriber },
|
|
236
|
+
nonSubscriber: { ...DEFAULT_ANTIFRAUD_VOLUME_LIMITS.week.nonSubscriber },
|
|
237
|
+
},
|
|
238
|
+
blockedAttemptsDay: { ...DEFAULT_ANTIFRAUD_VOLUME_LIMITS.blockedAttemptsDay },
|
|
239
|
+
source: 'fallback',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/** Config inválida/ausente → fallback (comportamento histórico). */
|
|
243
|
+
function resolveAntifraudVolumeLimits(antifraude) {
|
|
244
|
+
if (!antifraude || typeof antifraude.enabled !== 'boolean') {
|
|
245
|
+
return cloneFallbackLimits();
|
|
246
|
+
}
|
|
247
|
+
const daySubscriber = normalizeLimitOrders(antifraude.day?.subscriber, false);
|
|
248
|
+
const dayNonSubscriber = normalizeLimitOrders(antifraude.day?.nonSubscriber, false);
|
|
249
|
+
const weekSubscriber = normalizeLimitOrders(antifraude.week?.subscriber, true);
|
|
250
|
+
const weekNonSubscriber = normalizeLimitOrders(antifraude.week?.nonSubscriber, true);
|
|
251
|
+
const blocked = antifraude.blockedAttemptsDay;
|
|
252
|
+
if (!daySubscriber ||
|
|
253
|
+
!dayNonSubscriber ||
|
|
254
|
+
!weekSubscriber ||
|
|
255
|
+
!weekNonSubscriber ||
|
|
256
|
+
!blocked ||
|
|
257
|
+
!isPositiveInteger(blocked.subscriber) ||
|
|
258
|
+
!isPositiveInteger(blocked.nonSubscriber)) {
|
|
259
|
+
// Kill-switch explícito prevalece mesmo com payload inválido.
|
|
260
|
+
if (antifraude.enabled === false) {
|
|
261
|
+
return { ...cloneFallbackLimits(), enabled: false, source: 'fallback' };
|
|
262
|
+
}
|
|
263
|
+
return cloneFallbackLimits();
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
enabled: antifraude.enabled,
|
|
267
|
+
source: 'config',
|
|
268
|
+
day: { subscriber: daySubscriber, nonSubscriber: dayNonSubscriber },
|
|
269
|
+
week: { subscriber: weekSubscriber, nonSubscriber: weekNonSubscriber },
|
|
270
|
+
blockedAttemptsDay: {
|
|
271
|
+
subscriber: blocked.subscriber,
|
|
272
|
+
nonSubscriber: blocked.nonSubscriber,
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
178
277
|
const registry = new Map();
|
|
179
278
|
function registerClass(name, classConstructor) {
|
|
180
279
|
registry.set(name, classConstructor);
|
|
@@ -660,9 +759,22 @@ const deserialize = (data) => {
|
|
|
660
759
|
return eval('(' + data + ')');
|
|
661
760
|
};
|
|
662
761
|
const serialize = (data) => {
|
|
663
|
-
return
|
|
762
|
+
return serializeJavascript__default["default"](data);
|
|
664
763
|
};
|
|
665
764
|
|
|
765
|
+
/**
|
|
766
|
+
* Converts a BRL major-unit amount (e.g. 10.5) to integer cents (1050).
|
|
767
|
+
* Uses fixed 2-decimal normalization to avoid IEEE-754 artifacts like 19.99 * 100.
|
|
768
|
+
*/
|
|
769
|
+
function toCents(amount) {
|
|
770
|
+
if (!Number.isFinite(amount)) {
|
|
771
|
+
throw new Error(`Invalid amount: ${amount}`);
|
|
772
|
+
}
|
|
773
|
+
const sign = amount < 0 ? -1 : 1;
|
|
774
|
+
const [whole, fraction = '0'] = Math.abs(amount).toFixed(2).split('.');
|
|
775
|
+
return sign * (Number(whole) * 100 + Number(fraction));
|
|
776
|
+
}
|
|
777
|
+
|
|
666
778
|
class BaseModel {
|
|
667
779
|
get identifier() {
|
|
668
780
|
const fields = this.constructor.identifiersFields.filter((field) => field !== 'identifier');
|
|
@@ -1043,6 +1155,12 @@ class CampaignHashtag extends BaseModel {
|
|
|
1043
1155
|
}
|
|
1044
1156
|
}
|
|
1045
1157
|
|
|
1158
|
+
class CampaignHashtagPosts extends BaseModel {
|
|
1159
|
+
static get identifiersFields() {
|
|
1160
|
+
return ['id'];
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1046
1164
|
class BeautyProfile extends BaseModel {
|
|
1047
1165
|
toPlain() {
|
|
1048
1166
|
const plain = super.toPlain();
|
|
@@ -1911,12 +2029,23 @@ class StockOutError extends BusinessError {
|
|
|
1911
2029
|
}
|
|
1912
2030
|
}
|
|
1913
2031
|
|
|
2032
|
+
/* eslint-disable no-console */
|
|
1914
2033
|
class AntifraudBankSlipService {
|
|
1915
|
-
constructor(orderBlockedRepository) {
|
|
2034
|
+
constructor(orderBlockedRepository, shopConfigsRepository) {
|
|
1916
2035
|
this.orderBlockedRepository = orderBlockedRepository;
|
|
2036
|
+
this.shopConfigsRepository = shopConfigsRepository;
|
|
1917
2037
|
this.MAX_ORDER_VALUE = 5000;
|
|
1918
2038
|
}
|
|
1919
2039
|
async validate(checkout) {
|
|
2040
|
+
const enabled = await isAntifraudEnabled(this.shopConfigsRepository);
|
|
2041
|
+
if (!enabled) {
|
|
2042
|
+
console.info(JSON.stringify({
|
|
2043
|
+
msg: 'antifraud_bankslip_skipped',
|
|
2044
|
+
enabled: false,
|
|
2045
|
+
checkoutId: checkout.id,
|
|
2046
|
+
}));
|
|
2047
|
+
return true;
|
|
2048
|
+
}
|
|
1920
2049
|
if (checkout.totalPrice && checkout.totalPrice > this.MAX_ORDER_VALUE && !checkout.user?.isSubscriber) {
|
|
1921
2050
|
await this.orderBlockedRepository.createBlockedOrderOrPayment({
|
|
1922
2051
|
checkout,
|
|
@@ -1938,62 +2067,67 @@ class AntifraudBankSlipService {
|
|
|
1938
2067
|
}
|
|
1939
2068
|
}
|
|
1940
2069
|
|
|
2070
|
+
/* eslint-disable max-params */
|
|
1941
2071
|
class AntifraudCardService {
|
|
1942
|
-
constructor(orderRepository, orderBlockedRepository) {
|
|
2072
|
+
constructor(orderRepository, orderBlockedRepository, shopConfigsRepository) {
|
|
1943
2073
|
this.orderRepository = orderRepository;
|
|
1944
2074
|
this.orderBlockedRepository = orderBlockedRepository;
|
|
1945
|
-
this.
|
|
1946
|
-
this.LIMIT_ORDERS_WEEK = null;
|
|
2075
|
+
this.shopConfigsRepository = shopConfigsRepository;
|
|
1947
2076
|
}
|
|
1948
2077
|
async validate(checkout, card) {
|
|
1949
|
-
|
|
1950
|
-
await this.
|
|
1951
|
-
|
|
2078
|
+
// Limites locais por request — evita race em provider Nest singleton entre awaits.
|
|
2079
|
+
const resolved = await this.loadResolvedLimits();
|
|
2080
|
+
const isSubscriber = !!checkout.user?.isSubscriber;
|
|
2081
|
+
const dayLimits = isSubscriber ? resolved.day.subscriber : resolved.day.nonSubscriber;
|
|
2082
|
+
const weekLimits = isSubscriber ? resolved.week.subscriber : resolved.week.nonSubscriber;
|
|
2083
|
+
const blockedAttemptsDay = isSubscriber
|
|
2084
|
+
? resolved.blockedAttemptsDay.subscriber
|
|
2085
|
+
: resolved.blockedAttemptsDay.nonSubscriber;
|
|
2086
|
+
if (!resolved.enabled) {
|
|
2087
|
+
console.info(JSON.stringify({
|
|
2088
|
+
msg: 'antifraud_card_volume_skipped',
|
|
2089
|
+
source: resolved.source,
|
|
2090
|
+
enabled: false,
|
|
2091
|
+
checkoutId: checkout.id,
|
|
2092
|
+
isSubscriber,
|
|
2093
|
+
}));
|
|
2094
|
+
return true;
|
|
2095
|
+
}
|
|
2096
|
+
console.info(JSON.stringify({
|
|
2097
|
+
msg: 'antifraud_card_volume_limits',
|
|
2098
|
+
source: resolved.source,
|
|
2099
|
+
enabled: true,
|
|
2100
|
+
checkoutId: checkout.id,
|
|
2101
|
+
isSubscriber,
|
|
2102
|
+
blockedAttemptsDay,
|
|
2103
|
+
day: dayLimits,
|
|
2104
|
+
week: weekLimits,
|
|
2105
|
+
}));
|
|
2106
|
+
await this.validateBlockedOrderAttempts(checkout, card, blockedAttemptsDay);
|
|
2107
|
+
await this.validateDayAndWeekOrderLimits(checkout, card, dayLimits, weekLimits);
|
|
1952
2108
|
return true;
|
|
1953
2109
|
}
|
|
1954
|
-
|
|
1955
|
-
this.
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
};
|
|
1971
|
-
this.LIMIT_ORDERS_WEEK = {
|
|
1972
|
-
subscriber: {
|
|
1973
|
-
cpf: 12,
|
|
1974
|
-
email: 12,
|
|
1975
|
-
phone: 12,
|
|
1976
|
-
card: 12,
|
|
1977
|
-
zip: Infinity,
|
|
1978
|
-
},
|
|
1979
|
-
nonSubscriber: {
|
|
1980
|
-
cpf: 7,
|
|
1981
|
-
email: 7,
|
|
1982
|
-
phone: 7,
|
|
1983
|
-
card: 7,
|
|
1984
|
-
zip: Infinity,
|
|
1985
|
-
},
|
|
1986
|
-
};
|
|
1987
|
-
this.LIMIT_BLOCKED_ORDERS_DAY = isSubscriber ? 7 : 5;
|
|
1988
|
-
}
|
|
1989
|
-
getLimitsByUserType(type, isSubscriber) {
|
|
1990
|
-
const limits = type === 'day' ? this.LIMIT_ORDERS_DAY : this.LIMIT_ORDERS_WEEK;
|
|
1991
|
-
return isSubscriber ? limits['subscriber'] : limits['nonSubscriber'];
|
|
2110
|
+
async loadResolvedLimits() {
|
|
2111
|
+
if (!this.shopConfigsRepository) {
|
|
2112
|
+
return resolveAntifraudVolumeLimits(null);
|
|
2113
|
+
}
|
|
2114
|
+
try {
|
|
2115
|
+
const result = await this.shopConfigsRepository.find({}, { cache: { enabled: true, ttl: ANTIFRAUD_CONFIG_CACHE_TTL_SECONDS } });
|
|
2116
|
+
return resolveAntifraudVolumeLimits(result?.data?.at(0)?.antifraude);
|
|
2117
|
+
}
|
|
2118
|
+
catch (error) {
|
|
2119
|
+
console.warn(JSON.stringify({
|
|
2120
|
+
msg: 'antifraud_card_volume_config_load_failed',
|
|
2121
|
+
source: 'fallback',
|
|
2122
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2123
|
+
}));
|
|
2124
|
+
return resolveAntifraudVolumeLimits(null);
|
|
2125
|
+
}
|
|
1992
2126
|
}
|
|
1993
|
-
async validateBlockedOrderAttempts(checkout, card) {
|
|
1994
|
-
const isValid = await this.verifyBlockedOrderAttempts(checkout, card);
|
|
2127
|
+
async validateBlockedOrderAttempts(checkout, card, blockedAttemptsDay) {
|
|
2128
|
+
const isValid = await this.verifyBlockedOrderAttempts(checkout, card, blockedAttemptsDay);
|
|
1995
2129
|
if (!isValid) {
|
|
1996
|
-
throw new FraudValidationError(`Cliente com mais de ${
|
|
2130
|
+
throw new FraudValidationError(`Cliente com mais de ${blockedAttemptsDay} compras negadas/bloqueadas no dia`, exports.ErrorsCode.fraudPreventionInternal, {
|
|
1997
2131
|
checkoutId: checkout.id,
|
|
1998
2132
|
userEmail: checkout.user.email,
|
|
1999
2133
|
info: {
|
|
@@ -2004,8 +2138,8 @@ class AntifraudCardService {
|
|
|
2004
2138
|
});
|
|
2005
2139
|
}
|
|
2006
2140
|
}
|
|
2007
|
-
async validateDayAndWeekOrderLimits(checkout, card) {
|
|
2008
|
-
const isValid = await this.verifyDayAndWeekOrders(checkout, card);
|
|
2141
|
+
async validateDayAndWeekOrderLimits(checkout, card, dayLimits, weekLimits) {
|
|
2142
|
+
const isValid = await this.verifyDayAndWeekOrders(checkout, card, dayLimits, weekLimits);
|
|
2009
2143
|
if (!isValid) {
|
|
2010
2144
|
throw new FraudValidationError('Cliente tentando comprar mais do que o permitido no dia/semana', exports.ErrorsCode.fraudPreventionInternal, {
|
|
2011
2145
|
checkoutId: checkout.id,
|
|
@@ -2018,15 +2152,15 @@ class AntifraudCardService {
|
|
|
2018
2152
|
});
|
|
2019
2153
|
}
|
|
2020
2154
|
}
|
|
2021
|
-
async verifyBlockedOrderAttempts(checkout, card) {
|
|
2155
|
+
async verifyBlockedOrderAttempts(checkout, card, blockedAttemptsDay) {
|
|
2022
2156
|
const dateRange = this.getTodayDateRange();
|
|
2023
2157
|
const blockedOrders = await this.getBlockedOrdersByMultipleCriteria(checkout, dateRange);
|
|
2024
2158
|
const totalBlockedAttempts = this.calculateUniqueBlockedAttempts(blockedOrders, checkout);
|
|
2025
|
-
if (totalBlockedAttempts >=
|
|
2159
|
+
if (totalBlockedAttempts >= blockedAttemptsDay) {
|
|
2026
2160
|
await this.createBlockedOrderRecord({
|
|
2027
2161
|
checkout,
|
|
2028
2162
|
card,
|
|
2029
|
-
reason: `More than ${
|
|
2163
|
+
reason: `More than ${blockedAttemptsDay} attempts have failed`,
|
|
2030
2164
|
key: 'Failed attempts',
|
|
2031
2165
|
period: 'day',
|
|
2032
2166
|
});
|
|
@@ -2128,12 +2262,12 @@ class AntifraudCardService {
|
|
|
2128
2262
|
card,
|
|
2129
2263
|
});
|
|
2130
2264
|
}
|
|
2131
|
-
async verifyDayAndWeekOrders(checkout, card) {
|
|
2265
|
+
async verifyDayAndWeekOrders(checkout, card, dayLimits, weekLimits) {
|
|
2132
2266
|
const validationParams = this.buildValidationParams(checkout, card);
|
|
2133
|
-
const isDayLimitValid = await this.validateDayOrderLimits(checkout, validationParams);
|
|
2267
|
+
const isDayLimitValid = await this.validateDayOrderLimits(checkout, validationParams, dayLimits);
|
|
2134
2268
|
if (!isDayLimitValid)
|
|
2135
2269
|
return false;
|
|
2136
|
-
const isWeekLimitValid = await this.validateWeekOrderLimits(checkout, validationParams);
|
|
2270
|
+
const isWeekLimitValid = await this.validateWeekOrderLimits(checkout, validationParams, weekLimits);
|
|
2137
2271
|
return isWeekLimitValid;
|
|
2138
2272
|
}
|
|
2139
2273
|
buildValidationParams(checkout, card) {
|
|
@@ -2145,9 +2279,8 @@ class AntifraudCardService {
|
|
|
2145
2279
|
card,
|
|
2146
2280
|
};
|
|
2147
2281
|
}
|
|
2148
|
-
async validateDayOrderLimits(checkout, params) {
|
|
2282
|
+
async validateDayOrderLimits(checkout, params, limits) {
|
|
2149
2283
|
const ordersPerDay = await this.validateOrdersByRange(params, this.getDateRange('day'));
|
|
2150
|
-
const limits = this.getLimitsByUserType('day', checkout.user.isSubscriber);
|
|
2151
2284
|
return this.checkOrderLimitsAndBlock({
|
|
2152
2285
|
checkout,
|
|
2153
2286
|
orderCounts: ordersPerDay,
|
|
@@ -2155,9 +2288,8 @@ class AntifraudCardService {
|
|
|
2155
2288
|
period: 'day',
|
|
2156
2289
|
});
|
|
2157
2290
|
}
|
|
2158
|
-
async validateWeekOrderLimits(checkout, params) {
|
|
2291
|
+
async validateWeekOrderLimits(checkout, params, limits) {
|
|
2159
2292
|
const ordersPerWeek = await this.validateOrdersByRange(params, this.getDateRange('week'));
|
|
2160
|
-
const limits = this.getLimitsByUserType('week', checkout.user.isSubscriber);
|
|
2161
2293
|
return this.checkOrderLimitsAndBlock({
|
|
2162
2294
|
checkout,
|
|
2163
2295
|
orderCounts: ordersPerWeek,
|
|
@@ -2234,15 +2366,35 @@ class AntifraudCardService {
|
|
|
2234
2366
|
}
|
|
2235
2367
|
|
|
2236
2368
|
class AntifraudGlampointsService {
|
|
2237
|
-
constructor() {
|
|
2238
|
-
|
|
2369
|
+
constructor(shopConfigsRepository) {
|
|
2370
|
+
this.shopConfigsRepository = shopConfigsRepository;
|
|
2371
|
+
}
|
|
2372
|
+
async validate(checkout) {
|
|
2373
|
+
const enabled = await isAntifraudEnabled(this.shopConfigsRepository);
|
|
2374
|
+
if (!enabled) {
|
|
2375
|
+
console.info(JSON.stringify({
|
|
2376
|
+
msg: 'antifraud_glampoints_skipped',
|
|
2377
|
+
enabled: false,
|
|
2378
|
+
checkoutId: checkout.id,
|
|
2379
|
+
}));
|
|
2380
|
+
}
|
|
2239
2381
|
return true;
|
|
2240
2382
|
}
|
|
2241
2383
|
}
|
|
2242
2384
|
|
|
2243
2385
|
class AntifraudPixService {
|
|
2244
|
-
constructor() {
|
|
2245
|
-
|
|
2386
|
+
constructor(shopConfigsRepository) {
|
|
2387
|
+
this.shopConfigsRepository = shopConfigsRepository;
|
|
2388
|
+
}
|
|
2389
|
+
async validate(checkout) {
|
|
2390
|
+
const enabled = await isAntifraudEnabled(this.shopConfigsRepository);
|
|
2391
|
+
if (!enabled) {
|
|
2392
|
+
console.info(JSON.stringify({
|
|
2393
|
+
msg: 'antifraud_pix_skipped',
|
|
2394
|
+
enabled: false,
|
|
2395
|
+
checkoutId: checkout.id,
|
|
2396
|
+
}));
|
|
2397
|
+
}
|
|
2246
2398
|
return true;
|
|
2247
2399
|
}
|
|
2248
2400
|
}
|
|
@@ -2596,6 +2748,26 @@ class ShopSettings extends BaseModel {
|
|
|
2596
2748
|
}
|
|
2597
2749
|
}
|
|
2598
2750
|
|
|
2751
|
+
/**
|
|
2752
|
+
* Defaults iguais ao hardcode histórico do checkout.
|
|
2753
|
+
* `week.*.zip = null` → Infinity no runtime do volume de cartão.
|
|
2754
|
+
*/
|
|
2755
|
+
const DEFAULT_SHOP_ANTIFRAUD_CONFIG = {
|
|
2756
|
+
enabled: true,
|
|
2757
|
+
day: {
|
|
2758
|
+
subscriber: { cpf: 4, email: 4, phone: 4, card: 4, zip: 4 },
|
|
2759
|
+
nonSubscriber: { cpf: 2, email: 2, phone: 2, card: 2, zip: 2 },
|
|
2760
|
+
},
|
|
2761
|
+
week: {
|
|
2762
|
+
subscriber: { cpf: 12, email: 12, phone: 12, card: 12, zip: null },
|
|
2763
|
+
nonSubscriber: { cpf: 7, email: 7, phone: 7, card: 7, zip: null },
|
|
2764
|
+
},
|
|
2765
|
+
blockedAttemptsDay: {
|
|
2766
|
+
subscriber: 7,
|
|
2767
|
+
nonSubscriber: 5,
|
|
2768
|
+
},
|
|
2769
|
+
};
|
|
2770
|
+
|
|
2599
2771
|
class AdyenBlockedOrderHelper {
|
|
2600
2772
|
static async handleUnauthorizedPayment(params) {
|
|
2601
2773
|
await params.orderBlockedRepository.createBlockedOrderOrPayment({
|
|
@@ -2720,11 +2892,39 @@ class AdyenCardAxiosAdapter {
|
|
|
2720
2892
|
}
|
|
2721
2893
|
}
|
|
2722
2894
|
|
|
2895
|
+
function resolveCacheConfig(cache) {
|
|
2896
|
+
if (lodash.isNil(cache) || typeof cache !== 'object')
|
|
2897
|
+
return undefined;
|
|
2898
|
+
const candidate = cache;
|
|
2899
|
+
const cacheAdapter = candidate.cacheAdapter;
|
|
2900
|
+
if (!cacheAdapter)
|
|
2901
|
+
return undefined;
|
|
2902
|
+
if (!isCacheAdapter(cacheAdapter))
|
|
2903
|
+
return undefined;
|
|
2904
|
+
if (typeof cacheAdapter.isConfigured === 'function' && !cacheAdapter.isConfigured()) {
|
|
2905
|
+
return undefined;
|
|
2906
|
+
}
|
|
2907
|
+
return {
|
|
2908
|
+
cacheAdapter,
|
|
2909
|
+
ttlDefault: candidate.ttlDefault,
|
|
2910
|
+
};
|
|
2911
|
+
}
|
|
2912
|
+
function isCacheAdapter(adapter) {
|
|
2913
|
+
return (typeof adapter.get === 'function' &&
|
|
2914
|
+
typeof adapter.set === 'function' &&
|
|
2915
|
+
typeof adapter.remove === 'function' &&
|
|
2916
|
+
typeof adapter.clear === 'function');
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2723
2919
|
class RestCacheAdapter {
|
|
2724
2920
|
constructor(config) {
|
|
2921
|
+
this.client = null;
|
|
2725
2922
|
this.logger = new DebugHelper('RestCacheAdapter');
|
|
2923
|
+
this.configured = this.isValidBaseURL(config.baseURL);
|
|
2924
|
+
if (!this.configured)
|
|
2925
|
+
return;
|
|
2726
2926
|
this.client = axios__default["default"].create({
|
|
2727
|
-
baseURL: config.baseURL,
|
|
2927
|
+
baseURL: config.baseURL.trim(),
|
|
2728
2928
|
headers: {
|
|
2729
2929
|
'Content-Type': 'application/json',
|
|
2730
2930
|
...(lodash.isNil(config.authToken) ? {} : { Authorization: `Bearer ${config.authToken}` }),
|
|
@@ -2732,7 +2932,12 @@ class RestCacheAdapter {
|
|
|
2732
2932
|
},
|
|
2733
2933
|
});
|
|
2734
2934
|
}
|
|
2935
|
+
isConfigured() {
|
|
2936
|
+
return this.configured;
|
|
2937
|
+
}
|
|
2735
2938
|
async set(options) {
|
|
2939
|
+
if (!this.client)
|
|
2940
|
+
return false;
|
|
2736
2941
|
try {
|
|
2737
2942
|
const response = await this.client.post('/redis/set', {
|
|
2738
2943
|
key: options.key,
|
|
@@ -2748,6 +2953,8 @@ class RestCacheAdapter {
|
|
|
2748
2953
|
}
|
|
2749
2954
|
}
|
|
2750
2955
|
async get(key) {
|
|
2956
|
+
if (!this.client)
|
|
2957
|
+
return null;
|
|
2751
2958
|
try {
|
|
2752
2959
|
const response = await this.client.post('/redis/get', {
|
|
2753
2960
|
key,
|
|
@@ -2764,6 +2971,8 @@ class RestCacheAdapter {
|
|
|
2764
2971
|
}
|
|
2765
2972
|
}
|
|
2766
2973
|
async remove(key) {
|
|
2974
|
+
if (!this.client)
|
|
2975
|
+
return false;
|
|
2767
2976
|
try {
|
|
2768
2977
|
const response = await this.client.post('/redis/del', {
|
|
2769
2978
|
key,
|
|
@@ -2777,6 +2986,8 @@ class RestCacheAdapter {
|
|
|
2777
2986
|
}
|
|
2778
2987
|
}
|
|
2779
2988
|
async clear() {
|
|
2989
|
+
if (!this.client)
|
|
2990
|
+
return false;
|
|
2780
2991
|
try {
|
|
2781
2992
|
const response = await this.client.post('/redis/flushdb', {});
|
|
2782
2993
|
return response.data.success;
|
|
@@ -2787,6 +2998,9 @@ class RestCacheAdapter {
|
|
|
2787
2998
|
return false;
|
|
2788
2999
|
}
|
|
2789
3000
|
}
|
|
3001
|
+
isValidBaseURL(baseURL) {
|
|
3002
|
+
return lodash.isString(baseURL) && baseURL.trim().length > 0;
|
|
3003
|
+
}
|
|
2790
3004
|
}
|
|
2791
3005
|
|
|
2792
3006
|
class AxiosAdapter {
|
|
@@ -5437,7 +5651,7 @@ class CampaignHashtagFirestoreRepository extends withCrudFirestore(withHelpers(w
|
|
|
5437
5651
|
constructor({ firestore, interceptors, cache, }) {
|
|
5438
5652
|
super({
|
|
5439
5653
|
firestore,
|
|
5440
|
-
collectionName: '
|
|
5654
|
+
collectionName: 'CampaignsHashtags',
|
|
5441
5655
|
model: CampaignHashtag,
|
|
5442
5656
|
interceptors,
|
|
5443
5657
|
cache,
|
|
@@ -5445,6 +5659,18 @@ class CampaignHashtagFirestoreRepository extends withCrudFirestore(withHelpers(w
|
|
|
5445
5659
|
}
|
|
5446
5660
|
}
|
|
5447
5661
|
|
|
5662
|
+
class CampaignHashtagPostsFirestoreRepository extends withCrudFirestore(withHelpers(withFirestore(Base))) {
|
|
5663
|
+
constructor({ firestore, interceptors, cache, }) {
|
|
5664
|
+
super({
|
|
5665
|
+
firestore,
|
|
5666
|
+
collectionName: 'CampaignsHashtagsPosts',
|
|
5667
|
+
model: CampaignHashtagPosts,
|
|
5668
|
+
interceptors,
|
|
5669
|
+
cache,
|
|
5670
|
+
});
|
|
5671
|
+
}
|
|
5672
|
+
}
|
|
5673
|
+
|
|
5448
5674
|
class CheckoutFirestoreRepository extends withCrudFirestore(withHelpers(withFirestore(Base))) {
|
|
5449
5675
|
constructor({ firestore, interceptors, cache, }) {
|
|
5450
5676
|
super({
|
|
@@ -6133,7 +6359,7 @@ function createHasuraGraphQLClass(MixinBase) {
|
|
|
6133
6359
|
this.model = options.model;
|
|
6134
6360
|
this.fields = options.fields || this.model.identifiersFields;
|
|
6135
6361
|
this.logger = DebugHelper.from(this);
|
|
6136
|
-
this.cache = options.cache;
|
|
6362
|
+
this.cache = resolveCacheConfig(options.cache);
|
|
6137
6363
|
}
|
|
6138
6364
|
get headers() {
|
|
6139
6365
|
return HasuraAuthHelper.buildHeaders(this.authOptions);
|
|
@@ -11130,9 +11356,9 @@ class PagarmeV5BaseAxiosAdapter {
|
|
|
11130
11356
|
}
|
|
11131
11357
|
async refund(order, amount) {
|
|
11132
11358
|
try {
|
|
11133
|
-
console.warn('[PAGARME REFUND] Starting refund process for order', order.id, order.payment, 'with amount', amount);
|
|
11134
|
-
const
|
|
11135
|
-
console.warn('[PAGARME REFUND] Amount to send in cents',
|
|
11359
|
+
console.warn('[PAGARME REFUND] Starting refund process for order', order.id, order.payment.payment_method, order.payment.amount, 'to refund with amount', amount);
|
|
11360
|
+
const amountInCents = toCents(amount);
|
|
11361
|
+
console.warn('[PAGARME REFUND] Amount to send in cents', amountInCents);
|
|
11136
11362
|
const { data } = await axios__default["default"]({
|
|
11137
11363
|
method: 'DELETE',
|
|
11138
11364
|
url: `${this.credentials.URL}/charges/${order.payment.charger_id}`,
|
|
@@ -11141,7 +11367,7 @@ class PagarmeV5BaseAxiosAdapter {
|
|
|
11141
11367
|
'Content-Type': 'application/json',
|
|
11142
11368
|
},
|
|
11143
11369
|
data: {
|
|
11144
|
-
amount:
|
|
11370
|
+
amount: amountInCents,
|
|
11145
11371
|
},
|
|
11146
11372
|
});
|
|
11147
11373
|
console.warn('[RESPONSE PAGARME REFUND]', JSON.stringify(data));
|
|
@@ -11157,7 +11383,13 @@ class PagarmeV5BaseAxiosAdapter {
|
|
|
11157
11383
|
});
|
|
11158
11384
|
return {
|
|
11159
11385
|
status: this.getRefundStatus(data.status),
|
|
11160
|
-
success: [
|
|
11386
|
+
success: [
|
|
11387
|
+
exports.PagarMeV5OrderStatus.Pago,
|
|
11388
|
+
exports.PagarMeV5OrderStatus.Cancelado,
|
|
11389
|
+
exports.PagarMeV5PaymentStatus['Em processamento'],
|
|
11390
|
+
].includes(data.status)
|
|
11391
|
+
? true
|
|
11392
|
+
: false,
|
|
11161
11393
|
};
|
|
11162
11394
|
}
|
|
11163
11395
|
catch (error) {
|
|
@@ -11672,6 +11904,7 @@ Object.defineProperty(exports, 'unset', {
|
|
|
11672
11904
|
enumerable: true,
|
|
11673
11905
|
get: function () { return lodash.unset; }
|
|
11674
11906
|
});
|
|
11907
|
+
exports.ANTIFRAUD_CONFIG_CACHE_TTL_SECONDS = ANTIFRAUD_CONFIG_CACHE_TTL_SECONDS;
|
|
11675
11908
|
exports.Address = Address;
|
|
11676
11909
|
exports.AdyenCardAxiosAdapter = AdyenCardAxiosAdapter;
|
|
11677
11910
|
exports.AdyenPaymentMethodFactory = AdyenPaymentMethodFactory;
|
|
@@ -11698,6 +11931,8 @@ exports.CampaignDashboard = CampaignDashboard;
|
|
|
11698
11931
|
exports.CampaignDashboardFirestoreRepository = CampaignDashboardFirestoreRepository;
|
|
11699
11932
|
exports.CampaignHashtag = CampaignHashtag;
|
|
11700
11933
|
exports.CampaignHashtagFirestoreRepository = CampaignHashtagFirestoreRepository;
|
|
11934
|
+
exports.CampaignHashtagPosts = CampaignHashtagPosts;
|
|
11935
|
+
exports.CampaignHashtagPostsFirestoreRepository = CampaignHashtagPostsFirestoreRepository;
|
|
11701
11936
|
exports.Category = Category;
|
|
11702
11937
|
exports.CategoryCollectionChildren = CategoryCollectionChildren;
|
|
11703
11938
|
exports.CategoryCollectionChildrenHasuraGraphQLRepository = CategoryCollectionChildrenHasuraGraphQLRepository;
|
|
@@ -11719,6 +11954,8 @@ exports.ConnectDocumentService = ConnectDocumentService;
|
|
|
11719
11954
|
exports.ConnectFirestoreService = ConnectFirestoreService;
|
|
11720
11955
|
exports.Coupon = Coupon;
|
|
11721
11956
|
exports.CouponFirestoreRepository = CouponFirestoreRepository;
|
|
11957
|
+
exports.DEFAULT_ANTIFRAUD_VOLUME_LIMITS = DEFAULT_ANTIFRAUD_VOLUME_LIMITS;
|
|
11958
|
+
exports.DEFAULT_SHOP_ANTIFRAUD_CONFIG = DEFAULT_SHOP_ANTIFRAUD_CONFIG;
|
|
11722
11959
|
exports.Debug = Debug;
|
|
11723
11960
|
exports.DebugDecoratorHelper = DebugDecoratorHelper;
|
|
11724
11961
|
exports.DebugHelper = DebugHelper;
|
|
@@ -11855,12 +12092,16 @@ exports.WishlistHasuraGraphQLRepository = WishlistHasuraGraphQLRepository;
|
|
|
11855
12092
|
exports.deserialize = deserialize;
|
|
11856
12093
|
exports.getClass = getClass;
|
|
11857
12094
|
exports.is = is;
|
|
12095
|
+
exports.isAntifraudEnabled = isAntifraudEnabled;
|
|
11858
12096
|
exports.isDebuggable = isDebuggable;
|
|
11859
12097
|
exports.isUUID = isUUID;
|
|
11860
12098
|
exports.parseDateTime = parseDateTime;
|
|
11861
12099
|
exports.registerClass = registerClass;
|
|
12100
|
+
exports.resolveAntifraudVolumeLimits = resolveAntifraudVolumeLimits;
|
|
12101
|
+
exports.resolveCacheConfig = resolveCacheConfig;
|
|
11862
12102
|
exports.resolveClass = resolveClass;
|
|
11863
12103
|
exports.serialize = serialize;
|
|
12104
|
+
exports.toCents = toCents;
|
|
11864
12105
|
exports.withCreateFirestore = withCreateFirestore;
|
|
11865
12106
|
exports.withCreateHasuraGraphQL = withCreateHasuraGraphQL;
|
|
11866
12107
|
exports.withCrudFirestore = withCrudFirestore;
|