forked from mrvautin/expressCart
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
279 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"description": "Card payment", | ||
"currency": "USD", | ||
"userId": "test_this_is_not_real", | ||
"apiKey": "test_this_is_not_real", | ||
"baseUrl": "https://test-gsc.verifone.cloud", | ||
"entityId": "test_this_is_not_real", | ||
"paymentContract": "test_this_is_not_real" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"properties": { | ||
"description": { | ||
"type": "string" | ||
}, | ||
"currency": { | ||
"type": "string" | ||
}, | ||
"userId": { | ||
"type": "string" | ||
}, | ||
"apiKey": { | ||
"type": "string" | ||
}, | ||
"baseUrl": { | ||
"type": "string" | ||
}, | ||
"entityId": { | ||
"type": "string" | ||
}, | ||
"paymentContract": { | ||
"type": "string" | ||
} | ||
}, | ||
"required": [ | ||
"description", | ||
"currency", | ||
"userId", | ||
"apiKey", | ||
"baseUrl", | ||
"entityId", | ||
"paymentContract" | ||
], | ||
"additionalProperties": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -103,6 +103,10 @@ | |
{ | ||
"type": "string", | ||
"enum": [ "zip"] | ||
}, | ||
{ | ||
"type": "string", | ||
"enum": [ "verifone"] | ||
} | ||
] | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
const got = require('got'); | ||
const numeral = require('numeral'); | ||
const { getPaymentConfig } = require('./config'); | ||
|
||
const setupVerifone = async(req) => { | ||
const config = req.app.config; | ||
const paymentConfig = getPaymentConfig('verifone'); | ||
const base64Auth = Buffer.from(`${paymentConfig.userId}:${paymentConfig.apiKey}`).toString('base64'); | ||
|
||
// Create the payload | ||
const payload = { | ||
entity_id: paymentConfig.entityId, | ||
currency_code: paymentConfig.currency, | ||
amount: numeral(req.session.totalCartAmount).format('0.00').replace('.', ''), | ||
configurations: { | ||
card: { | ||
payment_contract_id: paymentConfig.paymentContract | ||
} | ||
}, | ||
interaction_type: 'IFRAME', | ||
return_url: `${config.baseUrl}/verifone/checkout_return` | ||
}; | ||
|
||
let setupResponse; | ||
try{ | ||
setupResponse = await got.post(`${paymentConfig.baseUrl}/oidc/checkout-service/v2/checkout`, { | ||
json: payload, | ||
headers: { | ||
'content-type': 'application/json', | ||
Accept: 'application/json', | ||
Authorization: `Basic ${base64Auth}` | ||
}, | ||
rejectUnauthorized: false | ||
}); | ||
|
||
// Parse the response | ||
setupResponse = JSON.parse(setupResponse.body); | ||
|
||
// Set our Checkout variables | ||
return { | ||
id: setupResponse.id, | ||
url: setupResponse.url | ||
}; | ||
}catch(ex){ | ||
console.log('ex', ex); | ||
console.log('payload', payload); | ||
return {}; | ||
} | ||
}; | ||
|
||
module.exports = { | ||
setupVerifone | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
const express = require('express'); | ||
const { indexOrders } = require('../indexing'); | ||
const { getId, sendEmail, getEmailTemplate } = require('../common'); | ||
const { getPaymentConfig } = require('../config'); | ||
const { emptyCart } = require('../cart'); | ||
const got = require('got'); | ||
const router = express.Router(); | ||
|
||
// The homepage of the site | ||
router.get('/checkout_return', async (req, res, next) => { | ||
const db = req.app.db; | ||
const config = req.app.config; | ||
const paymentConfig = getPaymentConfig('verifone'); | ||
const base64Auth = Buffer.from(`${paymentConfig.userId}:${paymentConfig.apiKey}`).toString('base64'); | ||
|
||
// Get checkoutid from session | ||
const checkoutId = req.session.verifoneCheckout; | ||
|
||
// Remove checkout from session | ||
delete req.session.verifoneCheckout; | ||
|
||
// Grab the checkout and the transaction | ||
let checkoutResponse; | ||
let transactionResponse; | ||
try{ | ||
checkoutResponse = await got.get(`${paymentConfig.baseUrl}/oidc/checkout-service/v2/checkout/${checkoutId}`, { | ||
headers: { | ||
'content-type': 'application/json', | ||
Accept: 'application/json', | ||
Authorization: `Basic ${base64Auth}` | ||
}, | ||
rejectUnauthorized: false | ||
}); | ||
|
||
// Parse the response | ||
checkoutResponse = JSON.parse(checkoutResponse.body); | ||
|
||
transactionResponse = await got.get(`${paymentConfig.baseUrl}/oidc/api/v2/transaction/${checkoutResponse.transaction_id}`, { | ||
headers: { | ||
'content-type': 'application/json', | ||
Accept: 'application/json', | ||
Authorization: `Basic ${base64Auth}` | ||
}, | ||
rejectUnauthorized: false | ||
}); | ||
|
||
// Parse the response | ||
transactionResponse = JSON.parse(transactionResponse.body); | ||
|
||
// order status if approved | ||
let orderStatus = 'Paid'; | ||
if(transactionResponse && transactionResponse.status !== 'SALE AUTHORISED'){ | ||
console.log('Declined response payload', checkoutResponse); | ||
orderStatus = 'Declined'; | ||
} | ||
|
||
// Set the transactionid | ||
const transactionId = checkoutResponse.transaction_id; | ||
|
||
const orderDoc = { | ||
orderPaymentId: transactionId, | ||
orderPaymentGateway: 'Verifone', | ||
orderPaymentMessage: `${transactionResponse.reason_code} - ${transactionResponse.status}`, | ||
orderTotal: req.session.totalCartAmount, | ||
orderShipping: req.session.totalCartShipping, | ||
orderItemCount: req.session.totalCartItems, | ||
orderProductCount: req.session.totalCartProducts, | ||
orderCustomer: getId(req.session.customerId), | ||
orderEmail: req.session.customerEmail, | ||
orderCompany: req.session.customerCompany, | ||
orderFirstname: req.session.customerFirstname, | ||
orderLastname: req.session.customerLastname, | ||
orderAddr1: req.session.customerAddress1, | ||
orderAddr2: req.session.customerAddress2, | ||
orderCountry: req.session.customerCountry, | ||
orderState: req.session.customerState, | ||
orderPostcode: req.session.customerPostcode, | ||
orderPhoneNumber: req.session.customerPhone, | ||
orderComment: req.session.orderComment, | ||
orderStatus: orderStatus, | ||
orderDate: new Date(), | ||
orderProducts: req.session.cart, | ||
orderType: 'Single' | ||
}; | ||
|
||
// insert order into DB | ||
try{ | ||
const newDoc = await db.orders.insertOne(orderDoc); | ||
|
||
// get the new ID | ||
const newId = newDoc.insertedId; | ||
|
||
// add to lunr index | ||
indexOrders(req.app) | ||
.then(() => { | ||
// if approved, send email etc | ||
if(orderStatus === 'Paid'){ | ||
// set the results | ||
req.session.messageType = 'success'; | ||
req.session.message = 'Your payment was successfully completed'; | ||
req.session.paymentEmailAddr = newDoc.ops[0].orderEmail; | ||
req.session.paymentApproved = true; | ||
req.session.paymentDetails = `<p><strong>Order ID: </strong>${newId}</p> | ||
<p><strong>Transaction ID: </strong>${orderDoc.orderPaymentId}</p>`; | ||
|
||
// set payment results for email | ||
const paymentResults = { | ||
message: req.session.message, | ||
messageType: req.session.messageType, | ||
paymentEmailAddr: req.session.paymentEmailAddr, | ||
paymentApproved: true, | ||
paymentDetails: req.session.paymentDetails | ||
}; | ||
|
||
// clear the cart | ||
if(req.session.cart){ | ||
emptyCart(req, res, 'function'); | ||
} | ||
|
||
// send the email with the response | ||
// TODO: Should fix this to properly handle result | ||
sendEmail(req.session.paymentEmailAddr, `Your payment with ${config.cartTitle}`, getEmailTemplate(paymentResults)); | ||
|
||
// redirect to outcome | ||
res.redirect(`/payment/${newId}`); | ||
}else{ | ||
// redirect to failure | ||
req.session.messageType = 'danger'; | ||
req.session.message = 'Your payment has declined. Please try again'; | ||
req.session.paymentApproved = false; | ||
req.session.paymentDetails = `<p><strong>Order ID: </strong>${newId} | ||
</p><p><strong>Transaction ID: </strong> ${transactionId}</p>`; | ||
res.redirect(`/payment/${newId}`); | ||
} | ||
}); | ||
}catch(ex){ | ||
console.log('Error getting payment response', ex); | ||
res.status(400).json({ err: 'Your payment has declined. Please try again' }); | ||
} | ||
}catch(ex){ | ||
console.info('Exception processing payment', ex); | ||
req.session.messageType = 'danger'; | ||
req.session.message = 'Your payment has declined. Please try again'; | ||
req.session.paymentApproved = false; | ||
req.session.paymentDetails = ''; | ||
res.redirect('/checkout/payment'); | ||
} | ||
}); | ||
|
||
module.exports = router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.