Added authorize.net payments
parent
2f9911fd1e
commit
70105e73bc
9
app.js
9
app.js
|
@ -43,6 +43,13 @@ if(config.paymentGateway === 'stripe'){
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(config.paymentGateway === 'authorizenet'){
|
||||||
|
const authorizenetConfig = ajv.validate(require('./config/authorizenetSchema'), require('./config/authorizenet.json'));
|
||||||
|
if(authorizenetConfig === false){
|
||||||
|
console.log(colors.red(`Authorizenet config is incorrect: ${ajv.errorsText()}`));
|
||||||
|
process.exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// require the routes
|
// require the routes
|
||||||
const index = require('./routes/index');
|
const index = require('./routes/index');
|
||||||
|
@ -50,6 +57,7 @@ const admin = require('./routes/admin');
|
||||||
const customer = require('./routes/customer');
|
const customer = require('./routes/customer');
|
||||||
const paypal = require('./routes/payments/paypal');
|
const paypal = require('./routes/payments/paypal');
|
||||||
const stripe = require('./routes/payments/stripe');
|
const stripe = require('./routes/payments/stripe');
|
||||||
|
const authorizenet = require('./routes/payments/authorizenet');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
@ -224,6 +232,7 @@ app.use('/', customer);
|
||||||
app.use('/admin', admin);
|
app.use('/admin', admin);
|
||||||
app.use('/paypal', paypal);
|
app.use('/paypal', paypal);
|
||||||
app.use('/stripe', stripe);
|
app.use('/stripe', stripe);
|
||||||
|
app.use('/authorizenet', authorizenet);
|
||||||
|
|
||||||
// catch 404 and forward to error handler
|
// catch 404 and forward to error handler
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"loginId": "loginId",
|
||||||
|
"transactionKey": "transactionKey",
|
||||||
|
"clientKey": "clientKey",
|
||||||
|
"mode": "test"
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"loginId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"transactionKey": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"clientKey": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"mode": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["test", "live"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"loginId",
|
||||||
|
"transactionKey",
|
||||||
|
"clientKey",
|
||||||
|
"mode"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
|
@ -83,7 +83,7 @@
|
||||||
},
|
},
|
||||||
"paymentGateway": {
|
"paymentGateway": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["paypal", "stripe"]
|
"enum": ["paypal", "stripe", "authorizenet"]
|
||||||
},
|
},
|
||||||
"databaseConnectionString": {
|
"databaseConnectionString": {
|
||||||
"format": "uri-template",
|
"format": "uri-template",
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.0.0",
|
"ajv": "^6.0.0",
|
||||||
"async": "^2.6.0",
|
"async": "^2.6.0",
|
||||||
|
"axios": "^0.17.1",
|
||||||
"bcrypt-nodejs": "0.0.3",
|
"bcrypt-nodejs": "0.0.3",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"body-parser": "^1.17.2",
|
"body-parser": "^1.17.2",
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
"rand-token": "^0.4.0",
|
"rand-token": "^0.4.0",
|
||||||
"rimraf": "^2.6.2",
|
"rimraf": "^2.6.2",
|
||||||
"sitemap": "^1.6.0",
|
"sitemap": "^1.6.0",
|
||||||
|
"strip-bom": "^3.0.0",
|
||||||
"stripe": "^5.4.0",
|
"stripe": "^5.4.0",
|
||||||
"uglifycss": "0.0.27"
|
"uglifycss": "0.0.27"
|
||||||
},
|
},
|
||||||
|
|
|
@ -50,6 +50,9 @@
|
||||||
{{#ifCond config.paymentGateway '==' 'stripe'}}
|
{{#ifCond config.paymentGateway '==' 'stripe'}}
|
||||||
{{> payments/stripe}}
|
{{> payments/stripe}}
|
||||||
{{/ifCond}}
|
{{/ifCond}}
|
||||||
|
{{#ifCond config.paymentGateway '==' 'authorizenet'}}
|
||||||
|
{{> payments/authorizenet}}
|
||||||
|
{{/ifCond}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
const express = require('express');
|
||||||
|
const axios = require('axios');
|
||||||
|
const stripBom = require('strip-bom');
|
||||||
|
const common = require('../common');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// The homepage of the site
|
||||||
|
router.post('/checkout_action', (req, res, next) => {
|
||||||
|
const db = req.app.db;
|
||||||
|
const config = common.getConfig();
|
||||||
|
const authorizenetConfig = common.getPaymentConfig();
|
||||||
|
|
||||||
|
let authorizeUrl = 'https://api.authorize.net/xml/v1/request.api';
|
||||||
|
if(authorizenetConfig.mode === 'test'){
|
||||||
|
authorizeUrl = 'https://apitest.authorize.net/xml/v1/request.api';
|
||||||
|
}
|
||||||
|
|
||||||
|
const chargeJson = {
|
||||||
|
createTransactionRequest: {
|
||||||
|
merchantAuthentication: {
|
||||||
|
name: authorizenetConfig.loginId,
|
||||||
|
transactionKey: authorizenetConfig.transactionKey
|
||||||
|
},
|
||||||
|
transactionRequest: {
|
||||||
|
transactionType: 'authCaptureTransaction',
|
||||||
|
amount: req.session.totalCartAmount,
|
||||||
|
payment: {
|
||||||
|
opaqueData: {
|
||||||
|
dataDescriptor: req.body.opaqueData.dataDescriptor,
|
||||||
|
dataValue: req.body.opaqueData.dataValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
axios.post(authorizeUrl, chargeJson, {responseType: 'text'})
|
||||||
|
.then((response) => {
|
||||||
|
// This is crazy but the Authorize.net API returns a string with BOM and totally
|
||||||
|
// screws the JSON response being parsed. So many hours wasted!
|
||||||
|
const txn = JSON.parse(stripBom(response.data)).transactionResponse;
|
||||||
|
|
||||||
|
if(!txn){
|
||||||
|
console.log('Declined request payload', chargeJson);
|
||||||
|
console.log('Declined response payload', response.data);
|
||||||
|
res.status(400).json({err: 'Your payment has declined. Please try again'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// order status if approved
|
||||||
|
let orderStatus = 'Paid';
|
||||||
|
if(txn && txn.responseCode !== '1'){
|
||||||
|
console.log('Declined response payload', response.data);
|
||||||
|
orderStatus = 'Declined';
|
||||||
|
}
|
||||||
|
|
||||||
|
let orderDoc = {
|
||||||
|
orderPaymentId: txn.transHash,
|
||||||
|
orderPaymentGateway: 'AuthorizeNet',
|
||||||
|
orderPaymentMessage: 'Your payment was successfully completed',
|
||||||
|
orderTotal: req.session.totalCartAmount,
|
||||||
|
orderEmail: req.body.shipEmail,
|
||||||
|
orderFirstname: req.body.shipFirstname,
|
||||||
|
orderLastname: req.body.shipLastname,
|
||||||
|
orderAddr1: req.body.shipAddr1,
|
||||||
|
orderAddr2: req.body.shipAddr2,
|
||||||
|
orderCountry: req.body.shipCountry,
|
||||||
|
orderState: req.body.shipState,
|
||||||
|
orderPostcode: req.body.shipPostcode,
|
||||||
|
orderPhoneNumber: req.body.shipPhoneNumber,
|
||||||
|
orderStatus: orderStatus,
|
||||||
|
orderDate: new Date(),
|
||||||
|
orderProducts: req.session.cart
|
||||||
|
};
|
||||||
|
|
||||||
|
// insert order into DB
|
||||||
|
db.orders.insert(orderDoc, (err, newDoc) => {
|
||||||
|
if(err){
|
||||||
|
console.info(err.stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the new ID
|
||||||
|
let newId = newDoc.insertedIds['0'];
|
||||||
|
|
||||||
|
// add to lunr index
|
||||||
|
common.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>${txn.transHash}</p>`;
|
||||||
|
|
||||||
|
// set payment results for email
|
||||||
|
let 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){
|
||||||
|
req.session.cart = null;
|
||||||
|
req.session.orderId = null;
|
||||||
|
req.session.totalCartAmount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the email with the response
|
||||||
|
// TODO: Should fix this to properly handle result
|
||||||
|
common.sendEmail(req.session.paymentEmailAddr, `Your payment with ${config.cartTitle}`, common.getEmailTemplate(paymentResults));
|
||||||
|
|
||||||
|
// redirect to outcome
|
||||||
|
res.status(200).json({orderId: 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> ${txn.transHash}</p>`;
|
||||||
|
res.status(400).json({err: true, orderId: newId});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log('Error sending payment to API', err);
|
||||||
|
res.status(400).json({err: 'Your payment has declined. Please try again'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-md-12">
|
<div class="col-xs-12 col-md-12">
|
||||||
{{#if pageCloseBtn}}
|
{{#if pageCloseBtn}}
|
||||||
<div class="row {{checkout}}">
|
<div class="row {{checkout}}">
|
||||||
<div class="col-lg-12 text-right">
|
<div class="col-lg-12 text-right">
|
||||||
|
@ -11,91 +11,88 @@
|
||||||
<div class="panel-heading">Cart contents</div>
|
<div class="panel-heading">Cart contents</div>
|
||||||
<div class="panel-body cart-body">
|
<div class="panel-body cart-body">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
{{#each session.cart}}
|
{{#each session.cart}}
|
||||||
<div class="row cart-row">
|
<div class="row cart-row">
|
||||||
<div class="col-xs-4 col-md-2">
|
<div class="col-xs-4 col-md-2">
|
||||||
{{#if productImage}}
|
{{#if productImage}}
|
||||||
<img class="img-responsive" src="{{this.productImage}}" alt="{{this.title}} product image">
|
<img class="img-responsive" src="{{this.productImage}}" alt="{{this.title}} product image"> {{else}}
|
||||||
{{else}}
|
<img class="img-responsive" src="/uploads/placeholder.png" alt="{{this.title}} product image"> {{/if}}
|
||||||
<img class="img-responsive" src="/uploads/placeholder.png" alt="{{this.title}} product image">
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="cart-item-row text-left col-xs-12 col-md-7">
|
<div class="cart-item-row text-left col-xs-12 col-md-7">
|
||||||
<p><a class="cart-link" href="/product/{{this.link}}">{{this.title}}</a></p>
|
|
||||||
<p>
|
<p>
|
||||||
{{#each this.options}}
|
<a class="cart-link" href="/product/{{this.link}}">{{this.title}}</a>
|
||||||
{{#if @last}}
|
|
||||||
{{this}}
|
|
||||||
{{else}}
|
|
||||||
{{this}} /
|
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<div class="form-group">
|
{{#each this.options}} {{#if @last}} {{this}} {{else}} {{this}} / {{/if}} {{/each}}
|
||||||
<div class="col-lg-5 no-pad-left">
|
</p>
|
||||||
<div class="input-group">
|
<p>
|
||||||
<span class="input-group-btn">
|
<div class="form-group">
|
||||||
<button class="btn btn-sm btn-primary btn-qty-minus" type="button">-</button>
|
<div class="col-lg-5 no-pad-left">
|
||||||
</span>
|
<div class="input-group">
|
||||||
<input type="number" class="form-control cart-product-quantity input-sm text-center" data-id="{{this.productId}}" id="{{@key}}" maxlength="2" value="{{this.quantity}}">
|
<span class="input-group-btn">
|
||||||
<span class="input-group-btn">
|
<button class="btn btn-sm btn-primary btn-qty-minus" type="button">-</button>
|
||||||
<button class="btn btn-sm btn-primary btn-qty-add" type="button">+</button>
|
</span>
|
||||||
</span>
|
<input type="number" class="form-control cart-product-quantity input-sm text-center" data-id="{{this.productId}}" id="{{@key}}"
|
||||||
|
maxlength="2" value="{{this.quantity}}">
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="btn btn-sm btn-primary btn-qty-add" type="button">+</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-lg-4 cart-item-row text-right no-pad-right">
|
<div class="col-xs-12 col-lg-4 cart-item-row text-right no-pad-right">
|
||||||
<strong>{{currencySymbol ../config.currencySymbol}}{{formatAmount this.totalItemPrice}}</strong>
|
<strong>{{currencySymbol ../config.currencySymbol}}{{formatAmount this.totalItemPrice}}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
{{#if session.cart}}
|
{{#if session.cart}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="cart-contents-shipping col-md-12 no-pad-right">
|
<div class="cart-contents-shipping col-md-12 no-pad-right">
|
||||||
{{#ifCond session.shippingCostApplied '===' true}}
|
{{#ifCond session.shippingCostApplied '===' true}}
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
Shipping: <strong>{{currencySymbol config.currencySymbol}}{{formatAmount config.flatShipping}}</strong>
|
Shipping:
|
||||||
</div>
|
<strong>{{currencySymbol config.currencySymbol}}{{formatAmount config.flatShipping}}</strong>
|
||||||
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
Shipping: <strong>FREE</strong>
|
Shipping:
|
||||||
</div>
|
<strong>FREE</strong>
|
||||||
|
</div>
|
||||||
{{/ifCond}}
|
{{/ifCond}}
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
Total: <strong>{{currencySymbol config.currencySymbol}}{{formatAmount session.totalCartAmount}}</strong>
|
Total:
|
||||||
|
<strong>{{currencySymbol config.currencySymbol}}{{formatAmount session.totalCartAmount}}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="cart-contents-shipping col-md-12 no-pad-right">
|
<div class="cart-contents-shipping col-md-12 no-pad-right">
|
||||||
Cart empty
|
Cart empty
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{#if session.cart}}
|
{{#if session.cart}}
|
||||||
<div class="col-xs-6 col-lg-6 text-left">
|
<div class="col-xs-6 col-lg-6 text-left">
|
||||||
<button class="btn btn-danger" id="empty-cart" type="button">Empty cart</button>
|
<button class="btn btn-danger" id="empty-cart" type="button">Empty cart</button>
|
||||||
</div>
|
</div>
|
||||||
{{#ifCond page '!=' 'pay'}}
|
{{#ifCond page '!=' 'pay'}}
|
||||||
<div class="text-right col-xs-6 col-md-6">
|
<div class="text-right col-xs-6 col-md-6">
|
||||||
{{#ifCond page '==' 'checkout'}}
|
{{#ifCond page '==' 'checkout'}}
|
||||||
<a href="/pay" class="btn btn-default">Pay now</a>
|
<a href="/pay" class="btn btn-default">Pay now</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a href="/checkout" class="btn btn-default">Checkout</a>
|
<a href="/checkout" class="btn btn-default">Checkout</a>
|
||||||
{{/ifCond}}
|
|
||||||
</div>
|
|
||||||
{{/ifCond}}
|
{{/ifCond}}
|
||||||
{{/if}}
|
</div>
|
||||||
|
{{/ifCond}} {{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,61 @@
|
||||||
|
{{#ifCond paymentConfig.mode '==' 'test'}}
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="https://jstest.authorize.net/v3/AcceptUI.js"
|
||||||
|
charset="utf-8">
|
||||||
|
</script>
|
||||||
|
{{else}}
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="https://js.authorize.net/v3/AcceptUI.js"
|
||||||
|
charset="utf-8">
|
||||||
|
</script>
|
||||||
|
{{/ifCond}}
|
||||||
|
<script>
|
||||||
|
function responseHandler(data){
|
||||||
|
// Set fields from the form
|
||||||
|
data.shipEmail = $('#shipEmail').val();
|
||||||
|
data.shipFirstname = $('#shipFirstname').val();
|
||||||
|
data.shipLastname = $('#shipLastname').val();
|
||||||
|
data.shipAddr1 = $('#shipAddr1').val();
|
||||||
|
data.shipAddr2 = $('#shipAddr2').val();
|
||||||
|
data.shipCountry = $('#shipCountry').val();
|
||||||
|
data.shipState = $('#shipState').val();
|
||||||
|
data.shipPostcode = $('#shipPostcode').val();
|
||||||
|
data.shipPhoneNumber = $('#shipPhoneNumber').val();
|
||||||
|
$.ajax({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/authorizenet/checkout_action',
|
||||||
|
dataType: 'json',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.done(function(data){
|
||||||
|
if(data.orderId){
|
||||||
|
window.location = '/payment/' + data.orderId;
|
||||||
|
}else{
|
||||||
|
showNotification('Transaction approved', 'success', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.fail(function(data){
|
||||||
|
if(data.orderId){
|
||||||
|
window.location = '/payment/' + data.orderId;
|
||||||
|
}else{
|
||||||
|
showNotification('Your payment has declined. Please try again.', 'danger');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<div class="col-xs-12 col-md-12 text-center">
|
||||||
|
<form id="paymentForm" method="POST">
|
||||||
|
<input type="hidden" name="dataValue" id="dataValue" />
|
||||||
|
<input type="hidden" name="dataDescriptor" id="dataDescriptor" />
|
||||||
|
<button type="button"
|
||||||
|
class="AcceptUI btn btn-success"
|
||||||
|
data-billingAddressOptions='{"show":false, "required":false}'
|
||||||
|
data-apiLoginID="{{paymentConfig.loginId}}"
|
||||||
|
data-clientKey="{{paymentConfig.clientKey}}"
|
||||||
|
data-acceptUIFormBtnTxt="Submit"
|
||||||
|
data-acceptUIFormHeaderTxt="Card Information"
|
||||||
|
data-responseHandler="responseHandler">Process payment
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -31,6 +31,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<form id="shipping-form" class="shipping-form" action="/{{config.paymentGateway}}/checkout_action" method="post" role="form" data-toggle="validator" novalidate="false">
|
<form id="shipping-form" class="shipping-form" action="/{{config.paymentGateway}}/checkout_action" method="post" role="form" data-toggle="validator" novalidate="false">
|
||||||
{{> payments/shipping-form}}
|
{{> payments/shipping-form}}
|
||||||
|
|
||||||
{{#if session.customer}}
|
{{#if session.customer}}
|
||||||
{{#ifCond config.paymentGateway '==' 'paypal'}}
|
{{#ifCond config.paymentGateway '==' 'paypal'}}
|
||||||
{{> payments/paypal}}
|
{{> payments/paypal}}
|
||||||
|
@ -50,6 +51,9 @@
|
||||||
{{#ifCond config.paymentGateway '==' 'stripe'}}
|
{{#ifCond config.paymentGateway '==' 'stripe'}}
|
||||||
{{> payments/stripe}}
|
{{> payments/stripe}}
|
||||||
{{/ifCond}}
|
{{/ifCond}}
|
||||||
|
{{#ifCond config.paymentGateway '==' 'authorizenet'}}
|
||||||
|
{{> payments/authorizenet}}
|
||||||
|
{{/ifCond}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue