front/controllers/payment/index.js

/* ============================================================================ *\
|| ########################################################################## ||
|| # Auction Software Marketplace          Release: 0.6   Build 0.7         # ||
|| # ---------------------------------------------------------------------- # ||
|| # License # 35YAHCNR9344X6O666C123AB                                     # ||
|| # ---------------------------------------------------------------------- # ||
|| # Copyright ©2014–2021 Develop Scripts LLC. All Rights Reserved          # ||
|| # This file may not be redistributed in whole or significant part.       # ||
|| # ------------- AUCTION SOFTWARE IS NOT FREE SOFTWARE ------------------ # ||
|| # http://www.auctionsoftwaremarketplace.com|support@auctionsoftware.com  # ||
|| # ---------------------------------------------------------------------- # ||
|| ########################################################################## ||
\* ============================================================================ */

/* eslint-disable prefer-destructuring */
/* eslint-disable no-param-reassign */
const axios = require('axios')

const paymentModule = require('../../modules/payment').default
const cartCtrl = require('../cart')

const schemaModule = require('./schema').default
const { jsonResponse } = require('../logger')
const kountCtrl = require('../kount')

const shortDescribeSCH = async (items) => {
    function changingdata(item) {
        const payItems = {
            itemId: item.item_id,
            name: item.title.substring(0, 31),
            description: item.desc_proc,
            quantity: item.qty,
            unitPrice: item.buynowamount,
            taxable: 'true',
        }
        return payItems
    }
    const promises = items.map(changingdata)
    items = await Promise.all(promises)
    return items
}

const generateRequestData = async (type, cardDetails, lineItem, cartValues, refTransId) => {
    const request = {}
    request.createTransactionRequest = {}
    request.createTransactionRequest.merchantAuthentication = {
        name: global.authorize.api_login_id,
        transactionKey: global.authorize.transaction_key,
    }
    const results = await Promise.all([
        paymentModule.insertPayLogRequest(cartValues.id, cartValues.user_id, type, 'authorize'),
    ])
    request.createTransactionRequest.refId = results[0].insertId
    request.createTransactionRequest.transactionRequest = {}
    if (type === 'priorAuthCaptureTransaction') {
        request.createTransactionRequest.transactionRequest.transactionType = type
        request.createTransactionRequest.transactionRequest.amount = cardDetails.card_amount
        request.createTransactionRequest.transactionRequest.refTransId = refTransId
    } else {
        request.createTransactionRequest.transactionRequest.transactionType = type
        request.createTransactionRequest.transactionRequest.amount = cardDetails.card_amount
        request.createTransactionRequest.transactionRequest.payment = {
            creditCard: {
                cardNumber: cardDetails.card_number,
                expirationDate: cardDetails.card_expiry,
                cardCode: cardDetails.card_cvv,
            },
        }

        request.createTransactionRequest.transactionRequest.lineItems = {
            lineItem,
        }
        request.createTransactionRequest.transactionRequest.tax = {
            amount: cartValues.total_tax,
            name: 'Sales Tax',
        }
        request.createTransactionRequest.transactionRequest.customer = {
            id: cartValues.user_id,
        }
        request.createTransactionRequest.transactionRequest.billTo = {
            firstName: cartValues.bill_first_name,
            lastName: cartValues.bill_first_name,
            address: cartValues.bill_address1,
            city: cartValues.bill_city,
            state: cartValues.bill_state,
            zip: cartValues.bill_zipcode,
            country: 'USA',
        }
        request.createTransactionRequest.transactionRequest.customerIP = '192.168.1.1'

        request.createTransactionRequest.transactionRequest.userFields = {
            userField: [
                {
                    name: 'refId',
                    value: results[0].insertId,
                },
            ],
        }
    }

    return request
}

const makeApiCall = async (data) => {
    let responseData = {}
    const url = global.authorize.endpoint
    const options = {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        data,
        url,
    }
    // paymentModule.updatePayLogRequest(
    //     { request: JSON.stringify(data) },
    //     data.createTransactionRequest.refId,
    //     1,
    // )
    const response = await axios(options)
    const paymentResponse = response.data.transactionResponse
    if (paymentResponse) {
        paymentModule.updatePayLogRequest(
            { response: JSON.stringify(paymentResponse), transactionID: paymentResponse.transId },
            paymentResponse.userFields[0].value,
            0,
        )
    }

    if (
        paymentResponse &&
        (parseInt(paymentResponse.responseCode, 10) === 1 ||
            parseInt(paymentResponse.responseCode, 10) === 4)
    ) {
        responseData = {
            status: 'success',
            responseType: 1,
            message: 'Payment succesfully completed!',
            responseData: { paymentResponse },
        }
    } else if (paymentResponse && paymentResponse.errors) {
        responseData = {
            status: 'error',
            responseType: 2,
            message: paymentResponse.errors[0].errorText,
        }
    } else if (response.data.messages.message.length) {
        responseData = {
            status: 'error',
            responseType: 3,
            message: response.data.messages.message[0].text,
        }
    } else {
        responseData = {
            status: 'error',
            responseType: 4,
            message: 'Payment Gateway Error.',
        }
    }
    return responseData
}

/**
 * On Payment Success
 *
 * @memberOf frontend.payment
 * @param {string} cartID cartID which the payment is success
 * @param {string} userID userID which the payment is success
 * @param {object} req req object
 * @param {paymentModule.getMinimumInvoiceID} modules
 * @param {paymentModule.getCartDetails} modules
 * @param {paymentModule.markCartPaid} modules
 * @param {paymentModule.markBuyNowPaid} modules
 * @param {paymentModule.addAppointment} modules
 * @param {paymentModule.updateBuynowAppointment} modules
 */
const paymentSuccess = async (cartID, userID, req) => {
    const [results, cartDetails] = await Promise.all([
        paymentModule.getMinimumInvoiceID(cartID),
        paymentModule.getCartDetails(cartID),
    ])
    if (req.body.payment_method === 'card') {
        await Promise.all([
            paymentModule.markCartPaid(req.body.payment_method, cartID, 1),
            paymentModule.markBuyNowPaid(cartID, results[0].common_invoice, 1),
        ])
    } else if (req.body.payment_method === 'curbside') {
        await Promise.all([
            paymentModule.markCartPaid(req.body.payment_method, cartID, 0),
            paymentModule.markBuyNowPaid(cartID, results[0].common_invoice, 0),
        ])
    }
    let apnmtIDUpdate = req.body.appointmentID
    if (!apnmtIDUpdate) {
        const resultsAppoint = await Promise.all([
            paymentModule.addAppointment(req.body.pickup, userID, cartDetails[0].cartlocation_id),
        ])
        apnmtIDUpdate = resultsAppoint[0].insertId
    }
    await Promise.all([paymentModule.updateBuynowAppointment(cartID, apnmtIDUpdate)])
    const responseData = {}
    return responseData
}

module.exports = {
    /**
     * Authorize the payment
     *
     * @memberOf frontend.payment
     * @param {frontend.cart.getSingleCartDetails} modules
     * @param {frontend.payment.paymentSuccess} modules
     * @param {paymentModule.authorizeInsertPayRecord} modules
     */
    authorizePayment: async (req, res) => {
        try {
            // const paymentData = {
            //     card_number: '5424000000000015',
            //     card_expiry: '2020-12',
            //     card_cvv: '999',
            //     card_amount: '10',
            // }
            const [cartDetails] = await Promise.all([
                cartCtrl.getSingleCartDetails(req, req.body.cart_id),
            ])

            if (req.body.payment_method === 'card') {
                cartDetails.cartItems = await shortDescribeSCH(cartDetails.cartItems)
                let detailsFirstCard = {}
                let detailsSecondCard = {}
                detailsFirstCard = {
                    card_number: req.body.card_number,
                    card_expiry: req.body.card_expiry,
                    card_cvv: req.body.card_cvv,
                    card_amount: req.body.card_amount,
                }
                let kountResponse = { status: 'success' }
                let kountResponseSecond = { status: 'success' }
                if (req.body.no_of_cards === 'multiple') {
                    detailsSecondCard = {
                        card_number: req.body.second_card_number,
                        card_expiry: req.body.second_card_expiry,
                        card_cvv: req.body.second_card_cvv,
                        card_amount: req.body.second_card_amount,
                    }
                    ;[kountResponse, kountResponseSecond] = await Promise.all([
                        kountCtrl.getPaymentValidation(req, detailsFirstCard, cartDetails),
                        kountCtrl.getPaymentValidation(req, detailsSecondCard, cartDetails),
                    ])
                } else {
                    ;[kountResponse] = await Promise.all([
                        kountCtrl.getPaymentValidation(req, detailsFirstCard, cartDetails),
                    ])
                }
                console.log('kountResponse Payment', kountResponse, kountResponseSecond)
                if (
                    kountResponse.status === 'success' &&
                    kountResponseSecond.status === 'success'
                ) {
                    const dataFirstCard = await generateRequestData(
                        'authOnlyTransaction',
                        detailsFirstCard,
                        cartDetails.cartItems,
                        cartDetails.cartValues,
                    )

                    const captureDataFirstCard = await generateRequestData(
                        'authCaptureTransaction',
                        detailsFirstCard,
                        cartDetails.cartItems,
                        cartDetails.cartValues,
                    )

                    if (req.body.no_of_cards === 'multiple') {
                        const dataSecondCard = await generateRequestData(
                            'authOnlyTransaction',
                            detailsSecondCard,
                            cartDetails.cartItems,
                            cartDetails.cartValues,
                        )

                        const captureDataSecondCard = await generateRequestData(
                            'authCaptureTransaction',
                            detailsSecondCard,
                            cartDetails.cartItems,
                            cartDetails.cartValues,
                        )

                        const [authResponseFirstCard, authResponseSecondCard] = await Promise.all([
                            makeApiCall(dataFirstCard),
                            makeApiCall(dataSecondCard),
                        ])
                        if (
                            authResponseFirstCard.status === 'success' &&
                            authResponseSecondCard.status === 'success'
                        ) {
                            const [
                                captureResponseFirstCard,
                                captureResponseSecondCard,
                            ] = await Promise.all([
                                makeApiCall(captureDataFirstCard),
                                makeApiCall(captureDataSecondCard),
                            ])
                            if (
                                captureResponseFirstCard.status === 'success' &&
                                captureResponseSecondCard.status === 'success'
                            ) {
                                await Promise.all([
                                    paymentModule.authorizeInsertPayRecord(
                                        req,
                                        detailsFirstCard,
                                        cartDetails.cartValues,
                                        captureResponseFirstCard.responseData.paymentResponse,
                                    ),
                                    paymentModule.authorizeInsertPayRecord(
                                        req,
                                        detailsSecondCard,
                                        cartDetails.cartValues,
                                        captureResponseSecondCard.responseData.paymentResponse,
                                    ),
                                    paymentSuccess(
                                        cartDetails.cartValues.id,
                                        cartDetails.cartValues.user_id,
                                        req,
                                    ),
                                ])
                                jsonResponse(
                                    res,
                                    captureResponseFirstCard.status,
                                    captureResponseFirstCard,
                                )
                            } else if (captureResponseFirstCard.status !== 'success') {
                                jsonResponse(
                                    res,
                                    captureResponseFirstCard.status,
                                    captureResponseFirstCard,
                                )
                            } else {
                                jsonResponse(
                                    res,
                                    captureResponseSecondCard.status,
                                    captureResponseSecondCard,
                                )
                            }
                        } else if (authResponseFirstCard.status !== 'success') {
                            jsonResponse(res, authResponseFirstCard.status, authResponseFirstCard)
                        } else {
                            jsonResponse(res, authResponseSecondCard.status, authResponseSecondCard)
                        }
                    } else {
                        const [authResponseFirstCard] = await Promise.all([
                            makeApiCall(dataFirstCard),
                        ])
                        if (authResponseFirstCard.status === 'success') {
                            const [captureResponseFirstCard] = await Promise.all([
                                makeApiCall(captureDataFirstCard),
                            ])
                            if (captureResponseFirstCard.status === 'success') {
                                await Promise.all([
                                    paymentModule.authorizeInsertPayRecord(
                                        req,
                                        detailsFirstCard,
                                        cartDetails.cartValues,
                                        captureResponseFirstCard.responseData.paymentResponse,
                                    ),
                                    paymentSuccess(
                                        cartDetails.cartValues.id,
                                        cartDetails.cartValues.user_id,
                                        req,
                                    ),
                                ])
                                jsonResponse(
                                    res,
                                    captureResponseFirstCard.status,
                                    captureResponseFirstCard,
                                )
                            } else {
                                jsonResponse(
                                    res,
                                    captureResponseFirstCard.status,
                                    captureResponseFirstCard,
                                )
                            }
                        } else {
                            jsonResponse(res, authResponseFirstCard.status, authResponseFirstCard)
                        }
                    }
                } else if (kountResponse.status === 'success') {
                    jsonResponse(res, 'error', {
                        responseType: kountResponseSecond.responseType,
                        message: kountResponseSecond.message,
                        responseData: kountResponseSecond.responseData,
                    })
                } else {
                    jsonResponse(res, 'error', {
                        responseType: kountResponse.responseType,
                        message: kountResponse.message,
                        responseData: kountResponse.responseData,
                    })
                }
            } else if (req.body.payment_method === 'curbside') {
                await Promise.all([
                    paymentSuccess(cartDetails.cartValues.id, cartDetails.cartValues.user_id, req),
                ])
                jsonResponse(res, 'success', {
                    responseType: 1,
                    message: 'Checkout Successfully completed!',
                })
            }
        } catch (e) {
            console.error(e)
            jsonResponse(res, 'error', {
                responseType: 5,
                message: 'Internal Server error!',
            })
        }
    },
}