@feardread/fear 1.0.1
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/FEAR.js +459 -0
- package/FEARServer.js +280 -0
- package/controllers/agent.js +438 -0
- package/controllers/auth/index.js +345 -0
- package/controllers/auth/token.js +50 -0
- package/controllers/blog.js +105 -0
- package/controllers/brand.js +10 -0
- package/controllers/cart.js +425 -0
- package/controllers/category.js +9 -0
- package/controllers/coupon.js +63 -0
- package/controllers/crud/crud.js +508 -0
- package/controllers/crud/index.js +36 -0
- package/controllers/email.js +34 -0
- package/controllers/enquiry.js +65 -0
- package/controllers/events.js +9 -0
- package/controllers/order.js +125 -0
- package/controllers/payment.js +31 -0
- package/controllers/product.js +147 -0
- package/controllers/review.js +247 -0
- package/controllers/tag.js +10 -0
- package/controllers/task.js +10 -0
- package/controllers/upload.js +41 -0
- package/controllers/user.js +401 -0
- package/index.js +7 -0
- package/libs/agent/index.js +561 -0
- package/libs/agent/modules/ai/ai.js +285 -0
- package/libs/agent/modules/ai/chat.js +518 -0
- package/libs/agent/modules/ai/config.js +688 -0
- package/libs/agent/modules/ai/operations.js +787 -0
- package/libs/agent/modules/analyze/api.js +546 -0
- package/libs/agent/modules/analyze/dorks.js +395 -0
- package/libs/agent/modules/ccard/README.md +454 -0
- package/libs/agent/modules/ccard/audit.js +479 -0
- package/libs/agent/modules/ccard/checker.js +674 -0
- package/libs/agent/modules/ccard/payment-processors.json +16 -0
- package/libs/agent/modules/ccard/validator.js +629 -0
- package/libs/agent/modules/code/analyzer.js +303 -0
- package/libs/agent/modules/code/jquery.js +1093 -0
- package/libs/agent/modules/code/react.js +1536 -0
- package/libs/agent/modules/code/refactor.js +499 -0
- package/libs/agent/modules/crypto/exchange.js +564 -0
- package/libs/agent/modules/net/proxy.js +409 -0
- package/libs/agent/modules/security/cve.js +442 -0
- package/libs/agent/modules/security/monitor.js +360 -0
- package/libs/agent/modules/security/scanner.js +300 -0
- package/libs/agent/modules/security/vulnerability.js +506 -0
- package/libs/agent/modules/security/web.js +465 -0
- package/libs/agent/modules/utils/browser.js +492 -0
- package/libs/agent/modules/utils/colorizer.js +285 -0
- package/libs/agent/modules/utils/manager.js +478 -0
- package/libs/cloud/index.js +228 -0
- package/libs/config/db.js +21 -0
- package/libs/config/validator.js +82 -0
- package/libs/db/index.js +318 -0
- package/libs/emailer/imap.js +126 -0
- package/libs/emailer/info.js +41 -0
- package/libs/emailer/smtp.js +77 -0
- package/libs/handler/async.js +3 -0
- package/libs/handler/error.js +66 -0
- package/libs/handler/index.js +161 -0
- package/libs/logger/index.js +49 -0
- package/libs/logger/morgan.js +24 -0
- package/libs/passport/passport.js +109 -0
- package/libs/search/api.js +384 -0
- package/libs/search/features.js +219 -0
- package/libs/search/service.js +64 -0
- package/libs/swagger/config.js +18 -0
- package/libs/swagger/index.js +35 -0
- package/libs/validator/index.js +254 -0
- package/models/blog.js +31 -0
- package/models/brand.js +12 -0
- package/models/cart.js +14 -0
- package/models/category.js +11 -0
- package/models/coupon.js +9 -0
- package/models/customer.js +0 -0
- package/models/enquiry.js +29 -0
- package/models/events.js +13 -0
- package/models/order.js +94 -0
- package/models/product.js +32 -0
- package/models/review.js +14 -0
- package/models/tag.js +10 -0
- package/models/task.js +11 -0
- package/models/user.js +68 -0
- package/package.json +12 -0
- package/routes/agent.js +615 -0
- package/routes/auth.js +13 -0
- package/routes/blog.js +19 -0
- package/routes/brand.js +15 -0
- package/routes/cart.js +105 -0
- package/routes/category.js +16 -0
- package/routes/coupon.js +15 -0
- package/routes/enquiry.js +14 -0
- package/routes/events.js +16 -0
- package/routes/mail.js +170 -0
- package/routes/order.js +19 -0
- package/routes/product.js +22 -0
- package/routes/review.js +11 -0
- package/routes/task.js +12 -0
- package/routes/user.js +17 -0
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
const colorizer = require('../utils/colorizer');
|
|
2
|
+
const fs = require('fs').promises;
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Card Status Checker Module
|
|
7
|
+
* Tests if credit cards are active/issued by performing authorization checks
|
|
8
|
+
* with payment processors (Stripe, PayPal, Authorize.net, etc.)
|
|
9
|
+
*
|
|
10
|
+
* IMPORTANT: This module requires PCI DSS compliance and proper API credentials.
|
|
11
|
+
* Only use in authorized testing environments.
|
|
12
|
+
*/
|
|
13
|
+
class CardStatusChecker {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.providers = {
|
|
16
|
+
stripe: null,
|
|
17
|
+
paypal: null,
|
|
18
|
+
authorizenet: null,
|
|
19
|
+
braintree: null
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
this.config = {
|
|
23
|
+
testMode: true, // Always start in test mode
|
|
24
|
+
timeout: 10000,
|
|
25
|
+
retryAttempts: 2
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
this.loadConfiguration();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Load API credentials from environment or config file
|
|
33
|
+
*/
|
|
34
|
+
async loadConfiguration() {
|
|
35
|
+
try {
|
|
36
|
+
// Try to load from config file
|
|
37
|
+
const configPath = path.join(process.cwd(), 'config', 'payment-processors.json');
|
|
38
|
+
const configData = await fs.readFile(configPath, 'utf8');
|
|
39
|
+
const config = JSON.parse(configData);
|
|
40
|
+
|
|
41
|
+
if (config.stripe) {
|
|
42
|
+
this.initializeStripe(config.stripe);
|
|
43
|
+
}
|
|
44
|
+
if (config.paypal) {
|
|
45
|
+
this.initializePayPal(config.paypal);
|
|
46
|
+
}
|
|
47
|
+
if (config.authorizenet) {
|
|
48
|
+
this.initializeAuthorizeNet(config.authorizenet);
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
// Fall back to environment variables
|
|
52
|
+
this.loadFromEnvironment();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Load credentials from environment variables
|
|
58
|
+
*/
|
|
59
|
+
loadFromEnvironment() {
|
|
60
|
+
if (process.env.STRIPE_SECRET_KEY) {
|
|
61
|
+
this.initializeStripe({
|
|
62
|
+
secretKey: process.env.STRIPE_SECRET_KEY,
|
|
63
|
+
testMode: process.env.STRIPE_TEST_MODE !== 'false'
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (process.env.PAYPAL_CLIENT_ID && process.env.PAYPAL_CLIENT_SECRET) {
|
|
68
|
+
this.initializePayPal({
|
|
69
|
+
clientId: process.env.PAYPAL_CLIENT_ID,
|
|
70
|
+
clientSecret: process.env.PAYPAL_CLIENT_SECRET,
|
|
71
|
+
testMode: process.env.PAYPAL_TEST_MODE !== 'false'
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (process.env.AUTHORIZENET_API_LOGIN && process.env.AUTHORIZENET_TRANSACTION_KEY) {
|
|
76
|
+
this.initializeAuthorizeNet({
|
|
77
|
+
apiLogin: process.env.AUTHORIZENET_API_LOGIN,
|
|
78
|
+
transactionKey: process.env.AUTHORIZENET_TRANSACTION_KEY,
|
|
79
|
+
testMode: process.env.AUTHORIZENET_TEST_MODE !== 'false'
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Initialize Stripe API
|
|
86
|
+
*/
|
|
87
|
+
initializeStripe(config) {
|
|
88
|
+
try {
|
|
89
|
+
const stripe = require('stripe')(config.secretKey);
|
|
90
|
+
this.providers.stripe = {
|
|
91
|
+
client: stripe,
|
|
92
|
+
testMode: config.testMode
|
|
93
|
+
};
|
|
94
|
+
console.log(colorizer.success('Stripe initialized in ' + (config.testMode ? 'TEST' : 'LIVE') + ' mode'));
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.log(colorizer.warning('Stripe SDK not available. Run: npm install stripe'));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Initialize PayPal API
|
|
102
|
+
*/
|
|
103
|
+
initializePayPal(config) {
|
|
104
|
+
try {
|
|
105
|
+
const paypal = require('@paypal/checkout-server-sdk');
|
|
106
|
+
const environment = config.testMode
|
|
107
|
+
? new paypal.core.SandboxEnvironment(config.clientId, config.clientSecret)
|
|
108
|
+
: new paypal.core.LiveEnvironment(config.clientId, config.clientSecret);
|
|
109
|
+
|
|
110
|
+
this.providers.paypal = {
|
|
111
|
+
client: new paypal.core.PayPalHttpClient(environment),
|
|
112
|
+
testMode: config.testMode
|
|
113
|
+
};
|
|
114
|
+
console.log(colorizer.success('PayPal initialized in ' + (config.testMode ? 'SANDBOX' : 'LIVE') + ' mode'));
|
|
115
|
+
} catch (err) {
|
|
116
|
+
console.log(colorizer.warning('PayPal SDK not available. Run: npm install @paypal/checkout-server-sdk'));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Initialize Authorize.Net API
|
|
122
|
+
*/
|
|
123
|
+
initializeAuthorizeNet(config) {
|
|
124
|
+
try {
|
|
125
|
+
const ApiContracts = require('authorizenet').APIContracts;
|
|
126
|
+
const ApiControllers = require('authorizenet').APIControllers;
|
|
127
|
+
|
|
128
|
+
this.providers.authorizenet = {
|
|
129
|
+
ApiContracts,
|
|
130
|
+
ApiControllers,
|
|
131
|
+
credentials: {
|
|
132
|
+
apiLogin: config.apiLogin,
|
|
133
|
+
transactionKey: config.transactionKey
|
|
134
|
+
},
|
|
135
|
+
testMode: config.testMode
|
|
136
|
+
};
|
|
137
|
+
console.log(colorizer.success('Authorize.Net initialized in ' + (config.testMode ? 'TEST' : 'LIVE') + ' mode'));
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.log(colorizer.warning('Authorize.Net SDK not available. Run: npm install authorizenet'));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Check card status using specified provider
|
|
145
|
+
*/
|
|
146
|
+
async checkCardStatus(args) {
|
|
147
|
+
const [cardNumber, provider = 'stripe'] = args;
|
|
148
|
+
|
|
149
|
+
if (!cardNumber) {
|
|
150
|
+
console.log(colorizer.error('Usage: check-card-status <card_number> [provider]'));
|
|
151
|
+
console.log(colorizer.info('Providers: stripe, paypal, authorizenet'));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Validate card number format
|
|
156
|
+
if (!this.validateCardFormat(cardNumber)) {
|
|
157
|
+
console.log(colorizer.error('Invalid card number format'));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log(colorizer.section('Card Status Check'));
|
|
162
|
+
console.log(colorizer.cyan('Card: ') + this.maskCardNumber(cardNumber));
|
|
163
|
+
console.log(colorizer.cyan('Provider: ') + provider.toUpperCase());
|
|
164
|
+
console.log(colorizer.cyan('Mode: ') + (this.config.testMode ? 'TEST' : 'LIVE'));
|
|
165
|
+
console.log();
|
|
166
|
+
|
|
167
|
+
let result;
|
|
168
|
+
const E = (err) => {
|
|
169
|
+
console.log(colorizer.error('Status check failed: ' + err.message));
|
|
170
|
+
if (process.env.DEBUG) {
|
|
171
|
+
console.log(colorizer.dim(err.stack));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
switch (provider.toLowerCase()) {
|
|
176
|
+
case 'stripe':
|
|
177
|
+
await this.checkWithStripe(cardNumber)
|
|
178
|
+
.then(result => this.displayResult(result))
|
|
179
|
+
.catch(err => E(err))
|
|
180
|
+
|
|
181
|
+
break;
|
|
182
|
+
case 'paypal':
|
|
183
|
+
result = await this.checkWithPayPal(cardNumber)
|
|
184
|
+
.then(result => this.displayResult(result))
|
|
185
|
+
.catch(err => E(err));
|
|
186
|
+
break;
|
|
187
|
+
case 'authorizenet':
|
|
188
|
+
result = await this.checkWithAuthorizeNet(cardNumber)
|
|
189
|
+
.then(result => this.displayResult(result))
|
|
190
|
+
.catch(err => E(err));
|
|
191
|
+
break;
|
|
192
|
+
default:
|
|
193
|
+
console.log(colorizer.error('Unknown provider: ' + provider));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Check card status using Stripe
|
|
200
|
+
* Uses $0.00 authorization to verify card without charging
|
|
201
|
+
*/
|
|
202
|
+
async checkWithStripe(cardNumber) {
|
|
203
|
+
if (!this.providers.stripe) {
|
|
204
|
+
throw new Error('Stripe not configured. Set STRIPE_SECRET_KEY environment variable.');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const stripe = this.providers.stripe.client;
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
// Create a payment method to test the card
|
|
211
|
+
const paymentMethod = await stripe.paymentMethods.create({
|
|
212
|
+
type: 'card',
|
|
213
|
+
card: {
|
|
214
|
+
number: cardNumber,
|
|
215
|
+
exp_month: 12,
|
|
216
|
+
exp_year: new Date().getFullYear() + 1,
|
|
217
|
+
cvc: '123'
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// If we got here, the card format is valid
|
|
222
|
+
// Now try to create a setup intent to verify the card is active
|
|
223
|
+
const setupIntent = await stripe.setupIntents.create({
|
|
224
|
+
payment_method: paymentMethod.id,
|
|
225
|
+
confirm: true,
|
|
226
|
+
payment_method_types: ['card']
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
status: 'active',
|
|
231
|
+
provider: 'Stripe',
|
|
232
|
+
cardBrand: paymentMethod.card.brand,
|
|
233
|
+
cardLast4: paymentMethod.card.last4,
|
|
234
|
+
cardCountry: paymentMethod.card.country,
|
|
235
|
+
funding: paymentMethod.card.funding,
|
|
236
|
+
checks: {
|
|
237
|
+
cvcCheck: paymentMethod.card.checks?.cvc_check,
|
|
238
|
+
addressCheck: paymentMethod.card.checks?.address_line1_check,
|
|
239
|
+
zipCheck: paymentMethod.card.checks?.address_postal_code_check
|
|
240
|
+
},
|
|
241
|
+
message: 'Card is active and valid'
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
} catch (err) {
|
|
245
|
+
return this.parseStripeError(err);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Parse Stripe error to determine card status
|
|
251
|
+
*/
|
|
252
|
+
parseStripeError(err) {
|
|
253
|
+
const code = err.code || err.type;
|
|
254
|
+
|
|
255
|
+
const errorMap = {
|
|
256
|
+
'card_declined': { status: 'declined', message: 'Card was declined by issuer' },
|
|
257
|
+
'expired_card': { status: 'expired', message: 'Card has expired' },
|
|
258
|
+
'incorrect_cvc': { status: 'active', message: 'Card exists but CVC incorrect' },
|
|
259
|
+
'incorrect_number': { status: 'invalid', message: 'Card number is invalid' },
|
|
260
|
+
'invalid_number': { status: 'invalid', message: 'Card number format is invalid' },
|
|
261
|
+
'invalid_expiry_month': { status: 'invalid', message: 'Invalid expiry month' },
|
|
262
|
+
'invalid_expiry_year': { status: 'invalid', message: 'Invalid expiry year' },
|
|
263
|
+
'processing_error': { status: 'unknown', message: 'Processing error occurred' },
|
|
264
|
+
'rate_limit': { status: 'unknown', message: 'Rate limit exceeded' }
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const errorInfo = errorMap[code] || {
|
|
268
|
+
status: 'error',
|
|
269
|
+
message: err.message || 'Unknown error occurred'
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
...errorInfo,
|
|
274
|
+
provider: 'Stripe',
|
|
275
|
+
errorCode: code
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Check card status using PayPal
|
|
281
|
+
*/
|
|
282
|
+
async checkWithPayPal(cardNumber) {
|
|
283
|
+
if (!this.providers.paypal) {
|
|
284
|
+
throw new Error('PayPal not configured. Set PAYPAL_CLIENT_ID and PAYPAL_CLIENT_SECRET.');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// PayPal verification logic
|
|
288
|
+
// Note: PayPal doesn't support direct card verification without a transaction
|
|
289
|
+
return {
|
|
290
|
+
status: 'info',
|
|
291
|
+
provider: 'PayPal',
|
|
292
|
+
message: 'PayPal requires a transaction context for card verification',
|
|
293
|
+
suggestion: 'Use Stripe or Authorize.Net for standalone card verification'
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Check card status using Authorize.Net
|
|
299
|
+
*/
|
|
300
|
+
async checkWithAuthorizeNet(cardNumber) {
|
|
301
|
+
if (!this.providers.authorizenet) {
|
|
302
|
+
throw new Error('Authorize.Net not configured. Set AUTHORIZENET_API_LOGIN and AUTHORIZENET_TRANSACTION_KEY.');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const { ApiContracts, ApiControllers, credentials } = this.providers.authorizenet;
|
|
306
|
+
|
|
307
|
+
return new Promise((resolve, reject) => {
|
|
308
|
+
const merchantAuth = new ApiContracts.MerchantAuthenticationType();
|
|
309
|
+
merchantAuth.setName(credentials.apiLogin);
|
|
310
|
+
merchantAuth.setTransactionKey(credentials.transactionKey);
|
|
311
|
+
|
|
312
|
+
const creditCard = new ApiContracts.CreditCardType();
|
|
313
|
+
creditCard.setCardNumber(cardNumber);
|
|
314
|
+
creditCard.setExpirationDate('1225'); // Use far future date
|
|
315
|
+
|
|
316
|
+
const payment = new ApiContracts.PaymentType();
|
|
317
|
+
payment.setCreditCard(creditCard);
|
|
318
|
+
|
|
319
|
+
const transactionRequest = new ApiContracts.TransactionRequestType();
|
|
320
|
+
transactionRequest.setTransactionType(ApiContracts.TransactionTypeEnum.AUTHONLYTRANSACTION);
|
|
321
|
+
transactionRequest.setPayment(payment);
|
|
322
|
+
transactionRequest.setAmount(0.00); // Zero auth
|
|
323
|
+
|
|
324
|
+
const request = new ApiContracts.CreateTransactionRequest();
|
|
325
|
+
request.setMerchantAuthentication(merchantAuth);
|
|
326
|
+
request.setTransactionRequest(transactionRequest);
|
|
327
|
+
|
|
328
|
+
const ctrl = new ApiControllers.CreateTransactionController(request.getJSON());
|
|
329
|
+
|
|
330
|
+
if (this.providers.authorizenet.testMode) {
|
|
331
|
+
ctrl.setEnvironment('https://apitest.authorize.net/xml/v1/request.api');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
ctrl.execute(() => {
|
|
335
|
+
const response = ctrl.getResponse();
|
|
336
|
+
const result = new ApiContracts.CreateTransactionResponse(response);
|
|
337
|
+
|
|
338
|
+
if (result.getMessages().getResultCode() === ApiContracts.MessageTypeEnum.OK) {
|
|
339
|
+
resolve({
|
|
340
|
+
status: 'active',
|
|
341
|
+
provider: 'Authorize.Net',
|
|
342
|
+
message: 'Card is active and valid',
|
|
343
|
+
transactionId: result.getTransactionResponse().getTransId()
|
|
344
|
+
});
|
|
345
|
+
} else {
|
|
346
|
+
const errors = result.getTransactionResponse().getErrors();
|
|
347
|
+
resolve({
|
|
348
|
+
status: 'declined',
|
|
349
|
+
provider: 'Authorize.Net',
|
|
350
|
+
message: errors ? errors.getError()[0].getErrorText() : 'Card declined',
|
|
351
|
+
errorCode: errors ? errors.getError()[0].getErrorCode() : 'unknown'
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Batch check multiple cards
|
|
360
|
+
*/
|
|
361
|
+
async checkBatch(args) {
|
|
362
|
+
const [filePath, provider = 'stripe'] = args;
|
|
363
|
+
|
|
364
|
+
if (!filePath) {
|
|
365
|
+
console.log(colorizer.error('Usage: check-card-batch <file_path> [provider]'));
|
|
366
|
+
console.log(colorizer.info('File should contain one card number per line'));
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
372
|
+
const cards = content.split('\n').filter(line => line.trim());
|
|
373
|
+
|
|
374
|
+
console.log(colorizer.section('Batch Card Status Check'));
|
|
375
|
+
console.log(colorizer.cyan('Cards to check: ') + cards.length);
|
|
376
|
+
console.log(colorizer.cyan('Provider: ') + provider.toUpperCase());
|
|
377
|
+
console.log();
|
|
378
|
+
|
|
379
|
+
const results = [];
|
|
380
|
+
|
|
381
|
+
for (let i = 0; i < cards.length; i++) {
|
|
382
|
+
const card = cards[i].trim();
|
|
383
|
+
console.log(colorizer.dim(`[${i + 1}/${cards.length}] Checking ${this.maskCardNumber(card)}...`));
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
let result;
|
|
387
|
+
switch (provider.toLowerCase()) {
|
|
388
|
+
case 'stripe':
|
|
389
|
+
result = await this.checkWithStripe(card);
|
|
390
|
+
break;
|
|
391
|
+
case 'authorizenet':
|
|
392
|
+
result = await this.checkWithAuthorizeNet(card);
|
|
393
|
+
break;
|
|
394
|
+
default:
|
|
395
|
+
result = { status: 'error', message: 'Invalid provider' };
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
results.push({ card: this.maskCardNumber(card), ...result });
|
|
399
|
+
|
|
400
|
+
// Rate limiting delay
|
|
401
|
+
await this.delay(1000);
|
|
402
|
+
|
|
403
|
+
} catch (err) {
|
|
404
|
+
results.push({
|
|
405
|
+
card: this.maskCardNumber(card),
|
|
406
|
+
status: 'error',
|
|
407
|
+
message: err.message
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
console.log();
|
|
413
|
+
this.displayBatchResults(results);
|
|
414
|
+
|
|
415
|
+
// Offer to export
|
|
416
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
417
|
+
const exportPath = `card-status-${timestamp}.json`;
|
|
418
|
+
await fs.writeFile(exportPath, JSON.stringify(results, null, 2));
|
|
419
|
+
console.log(colorizer.success(`Results exported to: ${exportPath}`));
|
|
420
|
+
|
|
421
|
+
} catch (err) {
|
|
422
|
+
console.log(colorizer.error('Batch check failed: ' + err.message));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Configure the module
|
|
428
|
+
*/
|
|
429
|
+
async configure(args) {
|
|
430
|
+
const [provider, ...credentials] = args;
|
|
431
|
+
|
|
432
|
+
console.log(colorizer.section('Card Status Checker Configuration'));
|
|
433
|
+
console.log();
|
|
434
|
+
|
|
435
|
+
if (!provider) {
|
|
436
|
+
this.showConfiguration();
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
switch (provider.toLowerCase()) {
|
|
441
|
+
case 'stripe':
|
|
442
|
+
if (credentials[0]) {
|
|
443
|
+
this.initializeStripe({ secretKey: credentials[0], testMode: true });
|
|
444
|
+
console.log(colorizer.success('Stripe configured successfully'));
|
|
445
|
+
} else {
|
|
446
|
+
console.log(colorizer.error('Usage: configure-card-checker stripe <secret_key>'));
|
|
447
|
+
}
|
|
448
|
+
break;
|
|
449
|
+
|
|
450
|
+
case 'authorizenet':
|
|
451
|
+
if (credentials.length >= 2) {
|
|
452
|
+
this.initializeAuthorizeNet({
|
|
453
|
+
apiLogin: credentials[0],
|
|
454
|
+
transactionKey: credentials[1],
|
|
455
|
+
testMode: true
|
|
456
|
+
});
|
|
457
|
+
console.log(colorizer.success('Authorize.Net configured successfully'));
|
|
458
|
+
} else {
|
|
459
|
+
console.log(colorizer.error('Usage: configure-card-checker authorizenet <api_login> <transaction_key>'));
|
|
460
|
+
}
|
|
461
|
+
break;
|
|
462
|
+
|
|
463
|
+
case 'mode':
|
|
464
|
+
this.config.testMode = credentials[0] === 'test';
|
|
465
|
+
console.log(colorizer.success('Mode set to: ' + (this.config.testMode ? 'TEST' : 'LIVE')));
|
|
466
|
+
break;
|
|
467
|
+
|
|
468
|
+
default:
|
|
469
|
+
console.log(colorizer.error('Unknown provider: ' + provider));
|
|
470
|
+
console.log(colorizer.info('Supported providers: stripe, authorizenet'));
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
console.log();
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Show current configuration
|
|
478
|
+
*/
|
|
479
|
+
showConfiguration() {
|
|
480
|
+
console.log(colorizer.cyan('Current Configuration:'));
|
|
481
|
+
console.log(colorizer.dim(' Mode: ') + (this.config.testMode ? 'TEST' : 'LIVE'));
|
|
482
|
+
console.log();
|
|
483
|
+
|
|
484
|
+
console.log(colorizer.cyan('Provider Status:'));
|
|
485
|
+
Object.entries(this.providers).forEach(([name, config]) => {
|
|
486
|
+
const status = config ? colorizer.green('✓ Configured') : colorizer.dim('✗ Not configured');
|
|
487
|
+
console.log(colorizer.dim(` ${name.padEnd(15)}: `) + status);
|
|
488
|
+
});
|
|
489
|
+
console.log();
|
|
490
|
+
|
|
491
|
+
console.log(colorizer.cyan('Setup Commands:'));
|
|
492
|
+
console.log(colorizer.dim(' configure-card-checker stripe <secret_key>'));
|
|
493
|
+
console.log(colorizer.dim(' configure-card-checker authorizenet <api_login> <transaction_key>'));
|
|
494
|
+
console.log(colorizer.dim(' configure-card-checker mode <test|live>'));
|
|
495
|
+
console.log();
|
|
496
|
+
|
|
497
|
+
console.log(colorizer.cyan('Environment Variables:'));
|
|
498
|
+
console.log(colorizer.dim(' STRIPE_SECRET_KEY'));
|
|
499
|
+
console.log(colorizer.dim(' PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET'));
|
|
500
|
+
console.log(colorizer.dim(' AUTHORIZENET_API_LOGIN, AUTHORIZENET_TRANSACTION_KEY'));
|
|
501
|
+
console.log();
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Show help information
|
|
506
|
+
*/
|
|
507
|
+
showHelp() {
|
|
508
|
+
console.log(colorizer.box('Card Status Checker - Help'));
|
|
509
|
+
console.log();
|
|
510
|
+
|
|
511
|
+
console.log(colorizer.section('COMMANDS'));
|
|
512
|
+
console.log(colorizer.cyan(' check-card-status <number> [provider]'));
|
|
513
|
+
console.log(colorizer.dim(' Check if a card is active with payment processor'));
|
|
514
|
+
console.log();
|
|
515
|
+
console.log(colorizer.cyan(' check-card-batch <file> [provider]'));
|
|
516
|
+
console.log(colorizer.dim(' Batch check multiple cards from file'));
|
|
517
|
+
console.log();
|
|
518
|
+
console.log(colorizer.cyan(' configure-card-checker [provider] [credentials...]'));
|
|
519
|
+
console.log(colorizer.dim(' Configure payment processor credentials'));
|
|
520
|
+
console.log();
|
|
521
|
+
console.log(colorizer.cyan(' card-checker-help'));
|
|
522
|
+
console.log(colorizer.dim(' Show this help message'));
|
|
523
|
+
console.log();
|
|
524
|
+
|
|
525
|
+
console.log(colorizer.section('SUPPORTED PROVIDERS'));
|
|
526
|
+
console.log(colorizer.dim(' • Stripe - Best for direct card verification'));
|
|
527
|
+
console.log(colorizer.dim(' • Authorize.Net - Good for merchant verification'));
|
|
528
|
+
console.log(colorizer.dim(' • PayPal - Limited standalone verification'));
|
|
529
|
+
console.log();
|
|
530
|
+
|
|
531
|
+
console.log(colorizer.section('SECURITY NOTES'));
|
|
532
|
+
console.log(colorizer.warning('⚠ IMPORTANT: This module handles sensitive payment data'));
|
|
533
|
+
console.log(colorizer.dim(' • Always use test mode for development'));
|
|
534
|
+
console.log(colorizer.dim(' • Requires PCI DSS compliance in production'));
|
|
535
|
+
console.log(colorizer.dim(' • Never log or store full card numbers'));
|
|
536
|
+
console.log(colorizer.dim(' • Use tokenization when possible'));
|
|
537
|
+
console.log(colorizer.dim(' • Implement rate limiting and fraud detection'));
|
|
538
|
+
console.log();
|
|
539
|
+
|
|
540
|
+
console.log(colorizer.section('TEST CARDS'));
|
|
541
|
+
console.log(colorizer.dim('Stripe Test Cards:'));
|
|
542
|
+
console.log(colorizer.dim(' 4242424242424242 - Visa (Success)'));
|
|
543
|
+
console.log(colorizer.dim(' 4000000000000002 - Visa (Declined)'));
|
|
544
|
+
console.log(colorizer.dim(' 4000000000009995 - Visa (Insufficient Funds)'));
|
|
545
|
+
console.log();
|
|
546
|
+
|
|
547
|
+
return Promise.resolve();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Display single check result
|
|
552
|
+
*/
|
|
553
|
+
displayResult(result) {
|
|
554
|
+
console.log(colorizer.section('Result'));
|
|
555
|
+
|
|
556
|
+
const statusColor = {
|
|
557
|
+
'active': colorizer.green,
|
|
558
|
+
'declined': colorizer.red,
|
|
559
|
+
'expired': colorizer.yellow,
|
|
560
|
+
'invalid': colorizer.red,
|
|
561
|
+
'error': colorizer.red,
|
|
562
|
+
'unknown': colorizer.dim,
|
|
563
|
+
'info': colorizer.cyan
|
|
564
|
+
}[result.status] || colorizer.dim;
|
|
565
|
+
|
|
566
|
+
console.log(colorizer.cyan('Status: ')); // + statusColor(result.status.toUpperCase()));
|
|
567
|
+
console.log(colorizer.cyan('Message: ') + result.message);
|
|
568
|
+
|
|
569
|
+
if (result.cardBrand) {
|
|
570
|
+
console.log(colorizer.cyan('Card Brand: ') + result.cardBrand);
|
|
571
|
+
}
|
|
572
|
+
if (result.cardLast4) {
|
|
573
|
+
console.log(colorizer.cyan('Last 4: ') + result.cardLast4);
|
|
574
|
+
}
|
|
575
|
+
if (result.funding) {
|
|
576
|
+
console.log(colorizer.cyan('Funding: ') + result.funding);
|
|
577
|
+
}
|
|
578
|
+
if (result.cardCountry) {
|
|
579
|
+
console.log(colorizer.cyan('Country: ') + result.cardCountry);
|
|
580
|
+
}
|
|
581
|
+
if (result.errorCode) {
|
|
582
|
+
console.log(colorizer.cyan('Error Code: ') + result.errorCode);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
console.log();
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Display batch results summary
|
|
590
|
+
*/
|
|
591
|
+
displayBatchResults(results) {
|
|
592
|
+
const summary = {
|
|
593
|
+
total: results.length,
|
|
594
|
+
active: results.filter(r => r.status === 'active').length,
|
|
595
|
+
declined: results.filter(r => r.status === 'declined').length,
|
|
596
|
+
expired: results.filter(r => r.status === 'expired').length,
|
|
597
|
+
invalid: results.filter(r => r.status === 'invalid').length,
|
|
598
|
+
error: results.filter(r => r.status === 'error').length
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
console.log(colorizer.section('Batch Results Summary'));
|
|
602
|
+
console.log(colorizer.cyan('Total Cards: ') + summary.total);
|
|
603
|
+
console.log(colorizer.green('Active: ') + summary.active);
|
|
604
|
+
console.log(colorizer.red('Declined: ') + summary.declined);
|
|
605
|
+
console.log(colorizer.yellow('Expired: ') + summary.expired);
|
|
606
|
+
console.log(colorizer.red('Invalid: ') + summary.invalid);
|
|
607
|
+
console.log(colorizer.dim('Errors: ') + summary.error);
|
|
608
|
+
console.log();
|
|
609
|
+
|
|
610
|
+
// Show individual results
|
|
611
|
+
console.log(colorizer.section('Individual Results'));
|
|
612
|
+
results.forEach((result, i) => {
|
|
613
|
+
const statusIcon = {
|
|
614
|
+
'active': '✓',
|
|
615
|
+
'declined': '✗',
|
|
616
|
+
'expired': '⚠',
|
|
617
|
+
'invalid': '✗',
|
|
618
|
+
'error': '✗'
|
|
619
|
+
}[result.status] || '?';
|
|
620
|
+
|
|
621
|
+
console.log(`${(i + 1).toString().padStart(3)}. ${statusIcon} ${result.card} - ${result.status} - ${result.message}`);
|
|
622
|
+
});
|
|
623
|
+
console.log();
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Validate card number format using Luhn algorithm
|
|
628
|
+
*/
|
|
629
|
+
validateCardFormat(cardNumber) {
|
|
630
|
+
const cleaned = cardNumber.replace(/\s|-/g, '');
|
|
631
|
+
|
|
632
|
+
if (!/^\d{13,19}$/.test(cleaned)) {
|
|
633
|
+
return false;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// Luhn algorithm
|
|
637
|
+
let sum = 0;
|
|
638
|
+
let isEven = false;
|
|
639
|
+
|
|
640
|
+
for (let i = cleaned.length - 1; i >= 0; i--) {
|
|
641
|
+
let digit = parseInt(cleaned[i], 10);
|
|
642
|
+
|
|
643
|
+
if (isEven) {
|
|
644
|
+
digit *= 2;
|
|
645
|
+
if (digit > 9) {
|
|
646
|
+
digit -= 9;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
sum += digit;
|
|
651
|
+
isEven = !isEven;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
return sum % 10 === 0;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Mask card number for display
|
|
659
|
+
*/
|
|
660
|
+
maskCardNumber(cardNumber) {
|
|
661
|
+
const cleaned = cardNumber.replace(/\s|-/g, '');
|
|
662
|
+
if (cleaned.length < 8) return '****';
|
|
663
|
+
return cleaned.slice(0, 4) + '****' + cleaned.slice(-4);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* Delay helper for rate limiting
|
|
668
|
+
*/
|
|
669
|
+
delay(ms) {
|
|
670
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
module.exports = CardStatusChecker;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"stripe": {
|
|
3
|
+
"secretKey": "sk_test_your_key_here",
|
|
4
|
+
"testMode": true
|
|
5
|
+
},
|
|
6
|
+
"paypal": {
|
|
7
|
+
"clientId": "your_client_id",
|
|
8
|
+
"clientSecret": "your_client_secret",
|
|
9
|
+
"testMode": true
|
|
10
|
+
},
|
|
11
|
+
"authorizenet": {
|
|
12
|
+
"apiLogin": "your_api_login",
|
|
13
|
+
"transactionKey": "your_transaction_key",
|
|
14
|
+
"testMode": true
|
|
15
|
+
}
|
|
16
|
+
}
|