REDROOM
PHP 8.2.30
Path:
Logout
Edit File
Size: 25.92 KB
Close
/proc/thread-self/root/home/byroehnu/.trash/node_modules11/flutterwave-node-v3/services/schema/create.js
Text
Base64
const joi = require('joi'); // create a virtual account const accountSchema = joi.object({ email: joi.string().max(100).email().required(), is_permanent: joi.boolean().required(), bvn: joi.when('is_permanent', { is: true, then: joi.string().trim().length(11).required(), }), duration: joi.string().min(1), frequency: joi.string().min(1), narration: joi.string().max(100), tx_ref: joi.string().trim().max(100), amount: joi.number().positive(), }); // charge bank accounts: base for NG, UK & EU direct account debits const bankChargeSchema = joi.object({ amount: joi.number().positive().required(), email: joi.string().max(100).email().required(), tx_ref: joi.string().trim().max(100).required(), currency: joi.string().uppercase().length(3).required(), fullname: joi.string().max(100), phone_number: joi .string() .max(50) .custom((value) => { if (value && !/^\+?\d+$/.test(value)) throw new Error('phone number should be digits'); return value; }), client_ip: joi .string() .ip({ version: ['ipv4', 'ipv6'], }) .default('::127.0.0.1'), device_fingerprint: joi.string().trim().max(200), redirect_url: joi.string().uri(), meta: joi.object().pattern(/^[a-zA-Z0-9_]*$/, joi.any()), is_token_io: joi .number() .positive() .when('currency', { is: joi.string().valid('GBP', 'EUR'), then: joi.required(), otherwise: joi.optional(), }), }); // create a beneficiary const beneficiarySchema = joi.object({ account_number: joi.string().required(), account_bank: joi.string().min(3).max(11).required(), beneficiary_name: joi.string().required(), currency: joi.string().uppercase().length(3), bank_name: joi.string(), }); // create virtual account in bulk const bulkAccountSchema = joi.object({ email: joi.string().max(100).email().required(), is_permanent: joi.boolean().required(), bvn: joi.when('is_permanent', { is: true, then: joi.string().trim().length(11).required(), }), accounts: joi.string().min(1).required(), frequency: joi.string().min(1), tx_ref: joi.string().trim().max(100), amount: joi.number().positive(), }); // create bulk token payment const bulkTokenDataSchema = joi.object({ token: joi.string().required(), currency: joi.string().uppercase().length(3).default('NGN').required(), country: joi.string().uppercase().length(2).default('NG'), amount: joi.number().positive().required(), email: joi.string().email().required(), full_name: joi.string(), ip: joi .string() .ip({ version: ['ipv4', 'ipv6'], }) .default('::127.0.0.1'), tx_ref: joi.string().trim().max(100).required(), }); const bulkTokenSchema = joi.object({ title: joi.string(), retry_strategy: joi .object({ retry_interval: joi.number().integer().positive().required().messages({ 'any.required': 'Retry interval is required!', }), retry_amount_variable: joi .number() .integer() .positive() .required() .messages({ 'any.required': 'Retry amount variable is required!', }), retry_attempt_variable: joi .number() .integer() .positive() .required() .messages({ 'any.required': 'Retry attempt variable is required!', }), last_attempt_variable: joi .number() .integer() .positive() .required() .messages({ 'any.required': 'Last attempt variable is required!', }), }) .required(), bulk_data: joi.array().items(bulkTokenDataSchema).required(), }); // SCHEMA IS UNUSED, createBulkTransferSchema IS USED INSTEAD // const bulkTransferSchema = joi.object({ // title: joi.string(), // bulk_data: joi // .array() // .items( // joi.object({ // account_bank: joi.string().length(3).required(), // account_number: joi.string().trim().max(20).required(), // amount: joi.number().positive().required(), // currency: joi.string().uppercase().length(3).default('NGN').required(), // narration: joi.string(), // reference: joi.string(), // meta: joi.when('currency', { // is: 'ZAR', // then: joi // .array() // .items( // joi.object({ // first_name: joi.string(), // last_name: joi.string(), // email: joi.string().email().required(), // mobile_number: joi // .string() // .max(50) // .custom((value) => { // if (value && !/^\+?\d+$/.test(value)) // throw new Error('phone number should be digits'); // return value; // }) // .required(), // recipient_address: joi.string().required(), // sender: joi.string().required(), // sender_country: joi // .string() // .uppercase() // .length(2) // .default('NG') // .required(), // }), // ) // .required(), // }), // }), // ) // .required(), // }); // THE VIRTUAL CARD SERVICE IS CURRENTLY UNAVAILABLE // const cardSchema = joi.object({ // currency: joi.string().uppercase().length(3).valid('USD').required(), // amount: joi.number().required(), // debit_currency: joi.string().uppercase().length(3).default('NGN'), // billing_name: joi.string(), // billing_address: joi.string(), // billing_city: joi.string().trim(), // billing_state: joi.string().trim().length(2), // billing_postal_code: joi.string().trim(), // billing_country: joi.string().trim().length(2), // first_name: joi.string().trim().required(), // last_name: joi.string().trim().required(), // date_of_birth: joi.string().trim().length(10).required(), // email: joi.string().email().required(), // phone: joi // .string() // .max(50) // .custom((value) => { // if (value && !/^\+?\d+$/.test(value)) // throw new Error('phone number should be digits'); // return value; // }), // title: joi.string().uppercase().valid('MR', 'MRS', 'MISS').required(), // gender: joi.string().length(1).valid('M', 'F').required(), // callback_url: joi.string().uri(), // }); // collect card payments const cardChargeSchema = joi.object({ enckey: joi.string().required(), tx_ref: joi.string().trim().max(100).required(), amount: joi.number().positive().required(), currency: joi.string().uppercase().length(3).default('NGN'), card_number: joi.string().creditCard().required(), cvv: joi.string().min(3).max(4).required(), expiry_month: joi .string() .length(2) .trim() .required() .custom((value) => { if (!Number(value) || Number(value) < 1 || Number(value) > 12) throw new Error('Invalid expiry month'); return value; }), expiry_year: joi.string().length(2).trim().required(), email: joi.string().max(100).email().required(), fullname: joi.string().max(100), phone_number: joi .string() .max(50) .custom((value) => { if (value && !/^\+?\d+$/.test(value)) throw new Error('phone number should be digits'); return value; }), client_ip: joi .string() .ip({ version: ['ipv4', 'ipv6'], }) .default('::127.0.0.1'), device_fingerprint: joi.string().trim().max(200), redirect_url: joi.string().uri(), authorization: joi.object({ mode: joi.string().max(15), pin: joi.number().positive().max(9999), address: joi.string(), city: joi.string(), state: joi.string(), country: joi.string().uppercase().length(2).default('NG'), zipcode: joi.string(), }), payment_plan: joi.string(), meta: joi.object().pattern(/^[a-zA-Z0-9_]*$/, joi.any()), subaccounts: joi .array() .items( joi.object({ id: joi.string().trim().max(100).required(), transaction_split_ratio: joi.number().positive(), transaction_charge_type: joi .string() .valid('flat', 'percentage', 'flat_subaccount'), transaction_charge: joi.number().positive(), }), ) .min(1), }); // initiate collections for different payment methods const chargeSchema = joi.object({ amount: joi.number().positive().required(), email: joi.string().max(100).email().required(), tx_ref: joi.string().trim().max(100).required(), currency: joi.string().uppercase().length(3).default('NGN').required(), fullname: joi.string().max(100), phone_number: joi .string() .max(50) .custom((value) => { if (value && !/^\+?\d+$/.test(value)) throw new Error('phone number should be digits'); return value; }), client_ip: joi .string() .ip({ version: ['ipv4', 'ipv6'], }) .default('::127.0.0.1'), device_fingerprint: joi.string().trim().max(200), redirect_url: joi.string().uri(), country: joi.string().uppercase().length(2).default('NG'), billing_address: joi.string(), billing_city: joi.string(), billing_state: joi.string(), billing_country: joi.string().uppercase().length(2).default('NG'), billing_zip: joi.string(), meta: joi.object().pattern(/^[a-zA-Z0-9_]*$/, joi.any()), expires: joi.number().positive().max(31536000), subaccounts: joi .array() .items( joi.object({ id: joi.string().trim().max(100).required(), transaction_split_ratio: joi.number().positive(), transaction_charge_type: joi .string() .valid('flat', 'percentage', 'flat_subaccount'), transaction_charge: joi.number().positive(), }), ) .min(1), sa_bank_code: joi.string(), }); // create eNaira charge const eNairaChargeSchema = joi.object({ amount: joi.number().positive().required(), email: joi.string().max(100).email().required(), tx_ref: joi.string().trim().max(100).required(), currency: joi.string().uppercase().length(3).default('NGN').required(), fullname: joi.string().max(100), phone_number: joi .string() .max(50) .custom((value) => { if (value && !/^\+?\d+$/.test(value)) throw new Error('phone number should be digits'); return value; }), client_ip: joi .string() .ip({ version: ['ipv4', 'ipv6'], }) .default('::127.0.0.1'), device_fingerprint: joi.string().trim().max(200), redirect_url: joi.string().uri(), meta: joi.object().pattern(/^[a-zA-Z0-9_]*$/, joi.any()), is_token: joi.number().positive(), is_qr: joi.number().positive(), }); // create mobile money charge const momoSchema = joi.object({ amount: joi.number().positive().required(), email: joi.string().max(100).email().required(), tx_ref: joi.string().trim().max(100).required(), currency: joi.string().uppercase().length(3).required(), phone_number: joi .string() .max(50) .custom((value) => { if (value && !/^\+?\d+$/.test(value)) throw new Error('phone number should be digits'); return value; }) .required(), network: joi.when('currency', { is: 'GHS', then: joi .string() .custom((val, helpers) => { const upper = val.toUpperCase(); const valid = ['MTN', 'AIRTELTIGO', 'VODAFONE']; if (!valid.includes(upper)) { return helpers.error('any.only'); } return upper; }) .optional() .messages({ 'any.only': 'Only MTN, AIRTELTIGO, and VODAFONE are valid for GHS.', }), otherwise: joi.when('currency', { is: 'UGX', then: joi .string() .custom((val, helpers) => { const upper = val.toUpperCase(); const valid = ['MTN', 'AIRTEL']; if (!valid.includes(upper)) { return helpers.error('any.only'); } return upper; }) .optional() .messages({ 'any.only': 'Only MTN and AIRTEL are valid for UGX.', }), otherwise: joi.when('currency', { is: 'KES', then: joi .string() .custom((val, helpers) => { const upper = val.toUpperCase(); const valid = ['SAFARICOM', 'AIRTEL']; if (!valid.includes(upper)) { return helpers.error('any.only'); } return upper; }) .optional() .messages({ 'any.only': 'Only SAFARICOM and AIRTEL are valid for KES.', }), otherwise: joi.when('currency', { is: 'RWF', then: joi .string() .custom((val, helpers) => { const upper = val.toUpperCase(); const valid = ['MTN', 'AIRTEL']; if (!valid.includes(upper)) { return helpers.error('any.only'); } return upper; }) .optional() .messages({ 'any.only': 'Only MTN and AIRTEL are valid for RWF.', }), otherwise: joi.when('currency', { is: 'TZS', then: joi .string() .custom((val, helpers) => { const upper = val.toUpperCase(); const valid = ['HALOPESA', 'AIRTEL', 'TIGO', 'VODACOM']; if (!valid.includes(upper)) { return helpers.error('any.only'); } return upper; }) .optional() .messages({ 'any.only': 'Only HALOPESA, AIRTEL, TIGO, and VODACOM are valid for TZS.', }), otherwise: joi.when('currency', { is: 'ZMW', then: joi .string() .custom((val, helpers) => { const upper = val.toUpperCase(); const valid = ['MTN', 'AIRTEL', 'ZAMTEL']; if (!valid.includes(upper)) { return helpers.error('any.only'); } return upper; }) .optional() .messages({ 'any.only': 'Only MTN, AIRTEL, and ZAMTEL are valid for ZMW.', }), otherwise: joi.when('currency', { is: 'XOF', then: joi .string() .custom((val, helpers) => { const upper = val.toUpperCase(); const valid = ['WAVE', 'MTN', 'ORANGEMONEY']; if (!valid.includes(upper)) { return helpers.error('any.only'); } return upper; }) .optional() .messages({ 'any.only': 'Only WAVE, MTN, and ORANGEMONEY are valid for XOF.', }), otherwise: joi.when('currency', { is: 'XAF', then: joi .string() .custom((val, helpers) => { const upper = val.toUpperCase(); const valid = ['MTN', 'ORANGEMONEY']; if (!valid.includes(upper)) { return helpers.error('any.only'); } return upper; }) .optional() .messages({ 'any.only': 'Only MTN and ORANGEMONEY are valid for XAF.', }), otherwise: joi.string().optional(), }), }), }), }), }), }), }), }), voucher: joi.number().optional(), country: joi.when('currency', { is: joi.valid('XAF', 'XOF'), then: joi.string().uppercase().length(2).default('CM').required(), }), order_id: joi.when('currency', { is: 'RWF', then: joi.string().trim().max(100).required(), }), fullname: joi.string().max(100), client_ip: joi .string() .ip({ version: ['ipv4', 'ipv6'], }) .default('::127.0.0.1'), meta: joi.object().pattern(/^[a-zA-Z0-9_]*$/, joi.any()), device_fingerprint: joi.string().trim().max(200), redirect_url: joi.string().uri(), }); // create a payment plan const planSchema = joi.object({ amount: joi.number().positive(), name: joi.string().trim().max(150).required(), interval: joi .string() .max(20) .valid('daily', 'weekly', 'monthly', 'quarterly', 'yearly') .required(), duration: joi.string().min(1), currency: joi.string().uppercase().length(3), }); // initiate the refunds const refundSchema = joi.object({ id: joi.string().required(), amount: joi.number().positive().required(), }); // create a subaccount const subaccountSchema = joi.object({ account_bank: joi.string().min(3).max(11).required(), account_number: joi.string().trim().max(20).required(), business_name: joi.string().trim().max(100).required(), split_value: joi.number().min(0).max(1).required(), business_mobile: joi.string().required(), business_email: joi.string().email(), business_contact: joi.string().trim().max(100), business_contact_mobile: joi.string().trim().max(100), country: joi.string().uppercase().length(2).default('NG'), meta: joi.array().items(joi.object().pattern(/^[a-zA-Z0-9_]*$/, joi.any())), split_type: joi.string().valid('percentage', 'flat'), }); // initiate a transfer const transferSchema = joi.object({ amount: joi.number().positive().required(), currency: joi.string().uppercase().length(3).default('NGN').required(), account_bank: joi.when('currency', { is: joi.valid('EUR', 'GBP', 'USD', 'KES'), then: joi.string().optional(), otherwise: joi.string().required(), }), account_number: joi.when('currency', { is: joi.valid('EUR', 'GBP', 'USD', 'KES'), then: joi.string().trim().max(20).optional(), otherwise: joi.string().trim().max(20).required(), }), narration: joi.string().max(100), debit_subaccount: joi.string().max(100), debit_currency: joi.string().uppercase().length(3).default('NGN'), reference: joi.string().trim().max(100), beneficiary: joi.number(), beneficiary_name: joi.string().max(100), destination_branch_code: joi.string().max(10), callback_url: joi.string().max(100), meta: joi.when('currency', { is: 'EUR', then: joi.array().items( joi .object({ AccountNumber: joi.string().trim().required().messages({ 'any.required': 'Account number is required!', }), RoutingNumber: joi.string().trim().required().messages({ 'any.required': 'Routing number is required!', }), SwiftCode: joi.string().required().messages({ 'any.required': 'Swift code is required!', }), BankName: joi.string().required().messages({ 'any.required': 'Destination bank name is required!', }), BeneficiaryName: joi.string().required().messages({ 'any.required': 'Beneficiary name is required!', }), BeneficiaryCountry: joi .string() .uppercase() .length(2) .required() .messages({ 'any.required': 'Beneficiary country is required!', }), PostalCode: joi.string().required().messages({ 'any.required': 'Postal code is required!', }), StreetNumber: joi.string().required().messages({ 'any.required': 'Street number is required!', }), StreetName: joi.string().required().messages({ 'any.required': 'Street name is required!', }), City: joi.string().required().messages({ 'any.required': 'City is required!', }), }) .required(), ), }), otherwise: joi.when('currency', { is: 'GBP', then: joi.array().items( joi.object({ AccountNumber: joi.string().trim().required().messages({ 'any.required': 'Account number is required!', }), RoutingNumber: joi.string().trim().required().messages({ 'any.required': 'Routing numver is required!', }), SwiftCode: joi.string().required().messages({ 'any.required': 'Swift code is required!', }), BankName: joi.string().required().messages({ 'any.required': 'Destination bank name is required!', }), BeneficiaryName: joi.string().required().messages({ 'any.required': 'Beneficiary name is required!', }), BeneficiaryCountry: joi .string() .uppercase() .length(2) .required() .messages({ 'any.required': 'Beneficiary country is required!', }), PostalCode: joi.string().required().messages({ 'any.required': 'Postal code is required!', }), StreetNumber: joi.string().required().messages({ 'any.required': 'Street number is required!', }), StreetName: joi.string().required().messages({ 'any.required': 'Street name is required!', }), City: joi.string().required().messages({ 'any.required': 'City is required!', }), }), ), }), otherwise: joi.when('currency', { is: 'USD', then: joi.array().items( joi.object({ AccountNumber: joi.string().trim().required().messages({ 'any.required': 'Account number is required!', }), RoutingNumber: joi.string().trim().required().messages({ 'any.required': 'Routing number is required!', }), SwiftCode: joi.string().required().messages({ 'any.required': 'Swift code is required!', }), BankName: joi.string().required().messages({ 'any.required': 'Destination bank name is required!', }), BeneficiaryName: joi.string().required().messages({ 'any.required': 'Beneficiary name is required!', }), BeneficiaryAddress: joi.string().required().messages({ 'any.required': 'Beneficiary address is required!', }), BeneficiaryCountry: joi .string() .uppercase() .length(2) .required() .messages({ 'any.required': 'Beneficiary country is required!', }), }), ), }), otherwise: joi.when('currency', { is: 'KES', then: joi.array().items( joi.object({ sender: joi.string().required().messages({ 'any.required': 'Sender is required!', }), mobile_number: joi .string() .max(50) .custom((value) => { if (value && !/^\+?\d+$/.test(value)) throw new Error('phone number should be digits'); return value; }) .required() .messages({ 'any.required': 'Sender mobile is required!', }), sender_country: joi.string().uppercase().length(2).required().messages({ 'any.required': 'Sender country is required!', }), }), ), }), }); // to create a modified version of your original transferSchema to include bank_code. const modifiedTransferSchema = transferSchema.keys({ bank_code: joi.when('currency', { is: joi.valid('EUR', 'GBP', 'USD', 'KES'), then: joi.string().optional(), otherwise: joi.string().required(), }), }); // create a bulk transfer const createBulkTransferSchema = joi.object({ title: joi.string(), bulk_data: joi .array() .items( modifiedTransferSchema .keys({ account_bank: joi.forbidden(), // Remove account_bank }) .rename('account_bank', 'bank_code'), ) .required(), }); // create a tokenized charge const tokenSchema = joi.object({ token: joi.string().required(), currency: joi.string().uppercase().length(3).default('NGN').required(), country: joi.string().uppercase().length(2).default('NG'), amount: joi.number().positive().required(), email: joi.string().email().required(), full_name: joi.string(), ip: joi .string() .ip({ version: ['ipv4', 'ipv6'], }) .default('::127.0.0.1'), narration: joi.string().required(), device_fingerprint: joi.string(), tx_ref: joi.string().trim().max(100).required(), do_3ds: joi.boolean(), preauthorize: joi.boolean(), redirect_url: joi.string(), }); // charge bank accounts: base for USSD charge const ussdChargeSchema = joi.object({ account_bank: joi.string().min(3).max(11).required(), amount: joi.number().positive().required(), email: joi.string().max(100).email().required(), tx_ref: joi.string().trim().max(100).required(), currency: joi.string().uppercase().length(3).default('NGN').required(), fullname: joi.string().max(100), phone_number: joi .string() .max(50) .custom((value) => { if (value && !/^\+?\d+$/.test(value)) throw new Error('phone number should be digits'); return value; }), client_ip: joi .string() .ip({ version: ['ipv4', 'ipv6'], }) .default('::127.0.0.1'), device_fingerprint: joi.string().trim().max(200), redirect_url: joi.string().uri(), meta: joi.object().pattern(/^[a-zA-Z0-9_]*$/, joi.any()), }); // Initiate transfers from one F4B wallet to another const walletTransferSchema = joi.object({ amount: joi.number().positive().required(), currency: joi.string().uppercase().length(3).default('NGN').required(), account_bank: joi.string().default('flutterwave').required(), account_number: joi.string().trim().max(20).required(), narration: joi.string().max(100).required(), debit_subaccount: joi.string().max(200), debit_currency: joi.string().uppercase().length(3).default('NGN'), reference: joi.string().trim().max(100), }); module.exports = { accountSchema, bankChargeSchema, beneficiarySchema, bulkAccountSchema, bulkTokenSchema, // bulkTransferSchema, // cardSchema, cardChargeSchema, chargeSchema, createBulkTransferSchema, eNairaChargeSchema, momoSchema, planSchema, refundSchema, subaccountSchema, transferSchema, tokenSchema, ussdChargeSchema, walletTransferSchema, };
Save
Close
Exit & Reset
Text mode: syntax highlighting auto-detects file type.
Directory Contents
Dirs: 0 × Files: 4
Delete Selected
Select All
Select None
Sort:
Name
Size
Modified
Enable drag-to-move
Name
Size
Perms
Modified
Actions
auxillary.js
4.34 KB
lrw-r--r--
2026-02-21 00:53:32
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
base.js
2.09 KB
lrw-r--r--
2026-02-21 00:53:34
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
bill.js
2.36 KB
lrw-r--r--
2026-02-21 00:53:34
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
create.js
25.92 KB
lrw-r--r--
2026-02-21 00:53:36
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Zip Selected
If ZipArchive is unavailable, a
.tar
will be created (no compression).