diff --git a/README.md b/README.md index a88275e..de21462 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![expressCart](https://raw.githubusercontent.com/mrvautin/expressCart/master/public/images/logo.png) -`expressCart` is a fully functional shopping cart built in Node.js (Express, MongoDB) with Stripe, PayPal and Authorize.net payments. +`expressCart` is a fully functional shopping cart built in Node.js (Express, MongoDB) with Stripe, PayPal, Authorize.net and Adyen payments. [![Github stars](https://img.shields.io/github/stars/mrvautin/expressCart.svg?style=social&label=Star)](https://github.com/mrvautin/expressCart) [![Build Status](https://travis-ci.org/mrvautin/expressCart.svg?branch=master)](https://travis-ci.org/mrvautin/expressCart) @@ -263,6 +263,23 @@ The Authorize.net config file is located: `/config/authorizenet.json`. A example Note: The credentials are obtained from your Authorize.net account dashboard. +##### Adyen (Payments) + +The Adyen config file is located: `/config/adyen.json`. A example Adyen settings file is provided: + +``` +{ + "environment": "TEST", + "apiKey": "this_is_not_real", + "publicKey": "this_is_not_real", + "merchantAccount": "this_is_not_real", + "statementDescriptor": "a_statement_descriptor", + "currency": "AUD" +} +``` + +Note: The `publicKey`, `apiKey` and `merchantAccount` is obtained from your Adyen account dashboard. + ## Email settings You will need to configure your SMTP details for expressCart to send email receipts to your customers. diff --git a/app.js b/app.js index f6eb088..ac3b8ba 100644 --- a/app.js +++ b/app.js @@ -54,6 +54,13 @@ switch(config.paymentGateway){ process.exit(2); } break; + + case'adyen': + if(ajv.validate(require('./config/adyenSchema'), require('./config/adyen.json')) === false){ + console.log(colors.red(`adyen config is incorrect: ${ajv.errorsText()}`)); + process.exit(2); + } + break; } // require the routes @@ -66,6 +73,7 @@ const user = require('./routes/user'); const paypal = require('./routes/payments/paypal'); const stripe = require('./routes/payments/stripe'); const authorizenet = require('./routes/payments/authorizenet'); +const adyen = require('./routes/payments/adyen'); const app = express(); @@ -324,6 +332,7 @@ app.use('/', admin); app.use('/paypal', paypal); app.use('/stripe', stripe); app.use('/authorizenet', authorizenet); +app.use('/adyen', adyen); // catch 404 and forward to error handler app.use((req, res, next) => { diff --git a/config/adyen.json b/config/adyen.json new file mode 100644 index 0000000..17f0d5a --- /dev/null +++ b/config/adyen.json @@ -0,0 +1,8 @@ +{ + "environment": "TEST", + "apiKey": "this_is_not_real", + "publicKey": "this_is_not_real", + "merchantAccount": "this_is_not_real", + "statementDescriptor": "a_statement_descriptor", + "currency": "AUD" +} \ No newline at end of file diff --git a/config/adyenSchema.json b/config/adyenSchema.json new file mode 100644 index 0000000..9d1184e --- /dev/null +++ b/config/adyenSchema.json @@ -0,0 +1,32 @@ +{ + "properties": { + "environment": { + "type": "string", + "enum": ["TEST", "LIVE"] + }, + "apiKey": { + "type": "string" + }, + "publicKey": { + "type": "string" + }, + "merchantAccount": { + "type": "string" + }, + "statementDescriptor": { + "type": "string" + }, + "currency": { + "type": "string" + } + }, + "required": [ + "environment", + "apiKey", + "publicKey", + "merchantAccount", + "statementDescriptor", + "currency" + ], + "additionalProperties": false +} diff --git a/config/baseSchema.json b/config/baseSchema.json index 498fe55..394c2eb 100644 --- a/config/baseSchema.json +++ b/config/baseSchema.json @@ -83,7 +83,7 @@ }, "paymentGateway": { "type": "string", - "enum": ["paypal", "stripe", "authorizenet"] + "enum": ["paypal", "stripe", "authorizenet", "adyen"] }, "databaseConnectionString": { "type": "string" diff --git a/locales/en.json b/locales/en.json index 92dd6fc..7be6076 100644 --- a/locales/en.json +++ b/locales/en.json @@ -163,5 +163,6 @@ "List": "List", "Order type": "Order type", "New user": "New user", - "Payment ID": "Payment ID" + "Payment ID": "Payment ID", + "Payment Message": "Payment Message" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 98ce640..d289dba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@adyen/api-library": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@adyen/api-library/-/api-library-2.1.7.tgz", + "integrity": "sha512-EQXOyXJ6A4ceqWYIiAwXdISVWVZfvQEPhf4roYkLiOL01GSTL0waWucUvS8tXOBOtSzrhTw1zUqC0YGBjULaRA==", + "requires": { + "https-proxy-agent": "3.0.1" + } + }, "@ava/babel-plugin-throws-helper": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-4.0.0.tgz", @@ -508,6 +516,14 @@ "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", @@ -2865,6 +2881,19 @@ "es6-symbol": "^3.1.1" } }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", @@ -5236,6 +5265,30 @@ "toidentifier": "1.0.0" } }, + "https-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", + "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "i18n": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.8.4.tgz", diff --git a/package.json b/package.json index 88bf2b9..b5449f2 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,14 @@ ], "verbose": true, "environmentVariables": { - "NODE_ENV": "test" - } + "NODE_ENV": "test" + } }, "engines": { "node": "10.16.0" }, "dependencies": { + "@adyen/api-library": "^2.1.7", "ajv": "^6.10.2", "async": "^2.6.3", "axios": "^0.19.0", @@ -87,6 +88,9 @@ "nodejs", "ecommerce", "paypal", + "stripe", + "authorise.net", + "adyen", "lunr", "cart", "shopping" diff --git a/public/javascripts/expressCart.js b/public/javascripts/expressCart.js index 71050e8..fe12481 100644 --- a/public/javascripts/expressCart.js +++ b/public/javascripts/expressCart.js @@ -1,4 +1,5 @@ -/* eslint-disable prefer-arrow-callback, no-var, no-tabs */ +/* eslint-disable prefer-arrow-callback, no-var, no-tabs */ +/* globals AdyenCheckout */ $(document).ready(function (){ // setup if material theme if($('#cartTheme').val() === 'Material'){ @@ -310,6 +311,63 @@ $(document).ready(function (){ } }); + if($('#adyen-dropin').length > 0){ + $.ajax({ + method: 'POST', + url: '/adyen/setup' + }) + .done(function(response){ + const configuration = { + locale: 'en-AU', + environment: response.environment.toLowerCase(), + originKey: response.publicKey, + paymentMethodsResponse: response.paymentsResponse + }; + const checkout = new AdyenCheckout(configuration); + checkout + .create('dropin', { + paymentMethodsConfiguration: { + card: { + hasHolderName: false, + holderNameRequired: false, + enableStoreDetails: false, + groupTypes: ['mc', 'visa'], + name: 'Credit or debit card' + } + }, + onSubmit: (state, dropin) => { + if($('#shipping-form').validator('validate').has('.has-error').length === 0){ + $.ajax({ + type: 'POST', + url: '/adyen/checkout_action', + data: { + shipEmail: $('#shipEmail').val(), + shipFirstname: $('#shipFirstname').val(), + shipLastname: $('#shipLastname').val(), + shipAddr1: $('#shipAddr1').val(), + shipAddr2: $('#shipAddr2').val(), + shipCountry: $('#shipCountry').val(), + shipState: $('#shipState').val(), + shipPostcode: $('#shipPostcode').val(), + shipPhoneNumber: $('#shipPhoneNumber').val(), + payment: JSON.stringify(state.data.paymentMethod) + } + }).done((response) => { + window.location = '/payment/' + response.paymentId; + }).fail((response) => { + console.log('Response', response); + showNotification('Failed to complete transaction', 'danger', true); + }); + } + } + }) + .mount('#adyen-dropin'); + }) + .fail(function(msg){ + showNotification(msg.responseJSON.message, 'danger'); + }); + }; + // call update settings API $('#settingsForm').validator().on('submit', function(e){ if(!e.isDefaultPrevented()){ diff --git a/public/javascripts/expressCart.min.js b/public/javascripts/expressCart.min.js index 222bb91..9c58589 100644 --- a/public/javascripts/expressCart.min.js +++ b/public/javascripts/expressCart.min.js @@ -1 +1 @@ -function deleteFromCart(t){$.ajax({method:"POST",url:"/product/removefromcart",data:{cartId:t.attr("data-id")}}).done(function(e){$("#cart-count").text(e.totalCartItems),0===e.totalCartItems?($(t).closest(".cart-row").hide("slow",function(){$(t).closest(".cart-row").remove()}),$(".cart-contents-shipping").hide("slow",function(){$(".cart-contents-shipping").remove()}),showNotification(e.message,"success"),setTimeout(function(){window.location="/"},3700)):($(t).closest(".cart-row").hide("slow",function(){$(t).closest(".cart-row").remove()}),showNotification(e.message,"success"))}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function slugify(t){return $.trim(t).replace(/[^a-z0-9-æøå]/gi,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").replace(/æ/gi,"ae").replace(/ø/gi,"oe").replace(/å/gi,"a").toLowerCase()}function cartUpdate(t){$(t).val()>0?""!==$(t).val()&&updateCart():$(t).val(1)}function updateCart(){var t=[];$(".cart-product-quantity").each(function(){var e={cartIndex:$(this).attr("id"),itemQuantity:$(this).val(),productId:$(this).attr("data-id")};t.push(e)}),$.ajax({method:"POST",url:"/product/updatecart",data:{items:JSON.stringify(t)}}).done(function(t){updateCartDiv(),$("#cart-count").text(t.totalCartItems)}).fail(function(t){showNotification(t.responseJSON.message,"danger",!0)})}function updateCartDiv(){var t=window.location.pathname.split("/").length>0?window.location.pathname.split("/")[1]:"";$.ajax({method:"GET",url:"/cartPartial",data:{path:t}}).done(function(t){$("#cart").html(t)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function getSelectedOptions(){var t={};return $(".product-opt").each(function(){if("opt-"!==$(this).attr("name")){var e=$(this).val().trim();"radio"===$(this).attr("type")&&(e=$('input[name="'+$(this).attr("name")+'"]:checked').val()),t[$(this).attr("name").substring(4,$(this).attr("name").length)]=e}else t[$(this).val().trim()]=$(this).prop("checked")}),t}function showNotification(t,e,a){a=a||!1,$("#notify_message").removeClass(),$("#notify_message").addClass("alert-"+e),$("#notify_message").html(t),$("#notify_message").slideDown(600).delay(2500).slideUp(600,function(){!0===a&&location.reload()})}$(document).ready(function(){if("Material"===$("#cartTheme").val()&&$(".materialboxed").materialbox(),$(window).width()<768&&($(".menu-side").on("click",function(t){t.preventDefault(),$('.menu-side li:not(".active")').slideToggle()}),$('.menu-side li:not(".active")').hide(),$(".menu-side>.active").html(''),$(".menu-side>.active").addClass("menu-side-mobile"),0===$("#navbar ul li").length&&$("#navbar").hide(),$("#offcanvasClose").hide()),$(".shipping-form input").each(function(t){$(this).wrap("
");var e=$(this).attr("placeholder");$(this).after('")}),$(".shipping-form input").on("focus",function(){$(this).next().addClass("floatLabel"),$(this).next().removeClass("hidden")}),$(".shipping-form input").on("blur",function(){""===$(this).val()&&($(this).next().addClass("hidden"),$(this).next().removeClass("floatLabel"))}),$(".menu-btn").on("click",function(t){t.preventDefault()}),$("#sendTestEmail").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/admin/testEmail"}).done(function(t){showNotification(t,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#footerHtml").length){var t=window.CodeMirror.fromTextArea(document.getElementById("footerHtml"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1});t.setValue(t.getValue())}if($("#googleAnalytics").length&&window.CodeMirror.fromTextArea(document.getElementById("googleAnalytics"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1}),$("#customCss").length){var e=window.CodeMirror.fromTextArea(document.getElementById("customCss"),{mode:"text/css",tabMode:"indent",theme:"flatly",lineNumbers:!0}),a=window.cssbeautify(e.getValue(),{indent:" ",autosemicolon:!0});e.setValue(a)}if($("table").each(function(){$(this).addClass("table table-hover")}),$("#productTags").tokenfield(),$(document).on("click",".dashboard_list",function(t){window.document.location=$(this).attr("href")}).hover(function(){$(this).toggleClass("hover")}),$(".product-title").dotdotdot({ellipsis:"..."}),$('input[class="published_state"]').change(function(){$.ajax({method:"POST",url:"/admin/product/published_state",data:{id:this.id,state:this.checked}}).done(function(t){showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".btn-qty-minus",function(t){var e=$(t.target).parent().parent().find(".cart-product-quantity");$(e).val(parseInt(e.val())-1),cartUpdate(e)}),$(document).on("click",".btn-qty-add",function(t){var e=$(t.target).parent().parent().find(".cart-product-quantity");$(e).val(parseInt(e.val())+1),cartUpdate(e)}),$(document).on("change",".cart-product-quantity",function(t){cartUpdate(t.target)}),$(document).on("click",".btn-delete-from-cart",function(t){deleteFromCart($(t.target))}),$(document).on("click",".orderFilterByStatus",function(t){t.preventDefault(),window.location="/admin/orders/bystatus/"+$("#orderStatusFilter").val()}),$("#pager").length){var o=$("#pageNum").val(),i=$("#productsPerPage").val(),n=$("#totalProductCount").val(),r=$("#paginateUrl").val(),s=$("#searchTerm").val();""!==s&&(s+="/");var c="/"+r+"/"+s+"{{number}}",d=Math.ceil(n/i);parseInt(n)>parseInt(i)&&$("#pager").bootpag({total:d,page:o,maxVisible:5,href:c,wrapClass:"pagination",prevClass:"waves-effect",nextClass:"waves-effect",activeClass:"pag-active waves-effect"})}if($(document).on("click","#btnPageUpdate",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/pages/update",data:{page_id:$("#page_id").val(),pageName:$("#pageName").val(),pageSlug:$("#pageSlug").val(),pageEnabled:$("#pageEnabled").is(":checked"),pageContent:$("#pageContent").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#btnGenerateAPIkey",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/admin/createApiKey"}).done(function(t){$("#apiKey").val(t.apiKey),showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".product_opt_remove",function(t){t.preventDefault();var e=$(this).closest("li").find(".opt-name").html();$.ajax({method:"POST",url:"/admin/product/removeoption",data:{productId:$("#productId").val(),optName:e}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#product_opt_add",function(t){t.preventDefault();var e=$("#product_optName").val(),a=$("#product_optLabel").val(),o=$("#product_optType").val(),i=$("#product_optOptions").val(),n={};""!==$("#productOptions").val()&&'"{}"'!==$("#productOptions").val()&&(n=JSON.parse($("#productOptions").val()));var r='
  • ';r+='
    ',r+='
    '+e+"
    ",r+='
    '+a+"
    ",r+='
    '+o+"
    ",r+='
    '+i+"
    ",r+='
    ',r+='',r+="
  • ",$("#product_opt_wrapper").append(r),n[e]={optName:e,optLabel:a,optType:o,optOptions:$.grep(i.split(","),function(t){return 0===t||t})},$("#productOptions").val(JSON.stringify(n)),$("#product_optName").val(""),$("#product_optLabel").val(""),$("#product_optOptions").val("")}),$("#stripeButton").validator().on("click",function(t){(t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length)&&window.StripeCheckout.configure({key:$("#stripeButton").data("key"),image:$("#stripeButton").data("image"),locale:"auto",token:function(t){$("#stripeButton").data("subscription")&&$("#shipping-form").append(''),$("#shipping-form").append(''),$("#shipping-form").submit()}}).open({email:$("#stripeButton").data("email"),name:$("#stripeButton").data("name"),description:$("#stripeButton").data("description"),zipCode:$("#stripeButton").data("zipCode"),amount:$("#stripeButton").data("amount"),currency:$("#stripeButton").data("currency"),subscription:$("#stripeButton").data("subscription")})}),$("#settingsForm").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$("#footerHtml_input").val($(".CodeMirror")[0].CodeMirror.getValue()),$("#googleAnalytics_input").val($(".CodeMirror")[1].CodeMirror.getValue()),$("#customCss_input").val($(".CodeMirror")[2].CodeMirror.getValue()),$.ajax({method:"POST",url:"/admin/settings/update",data:$("#settingsForm").serialize()}).done(function(t){showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}))}),$("#customerLogout").on("click",function(t){$.ajax({method:"POST",url:"/customer/logout",data:{}}).done(function(t){location.reload()})}),$("#createCustomerAccount").validator().on("click",function(t){t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/customer/create",data:{email:$("#shipEmail").val(),firstName:$("#shipFirstname").val(),lastName:$("#shipLastname").val(),address1:$("#shipAddr1").val(),address2:$("#shipAddr2").val(),country:$("#shipCountry").val(),state:$("#shipState").val(),postcode:$("#shipPostcode").val(),phone:$("#shipPhoneNumber").val(),password:$("#newCustomerPassword").val()}}).done(function(t){location.reload()}).fail(function(t){showNotification(t.responseJSON.err,"danger")})}),$("#loginForm").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/admin/login_action",data:{email:$("#email").val(),password:$("#password").val()}}).done(function(t){window.location="/admin"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerLogin").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/login_action",data:{loginEmail:$("#customerLoginEmail").val(),loginPassword:$("#customerLoginPassword").val()}}).done(function(t){var e=t.customer;$("#shipEmail").val(e.email),$("#shipFirstname").val(e.firstName),$("#shipLastname").val(e.lastName),$("#shipAddr1").val(e.address1),$("#shipAddr2").val(e.address2),$("#shipCountry").val(e.country),$("#shipState").val(e.state),$("#shipPostcode").val(e.postcode),$("#shipPhoneNumber").val(e.phone),location.reload()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$(document).on("click",".image-next",function(t){var e=$(".thumbnail-image"),a=0,o=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(o=a+1===e.length||a+1<0?0:a+1),a++}),$("#product-title-image").attr("src",$(e).eq(o).attr("src"))}),$(document).on("click",".image-prev",function(t){var e=$(".thumbnail-image"),a=0,o=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(o=a-1===e.length||a-1<0?e.length-1:a-1),a++}),$("#product-title-image").attr("src",$(e).eq(o).attr("src"))}),$(document).on("click","#orderStatusUpdate",function(t){$.ajax({method:"POST",url:"/admin/order/statusupdate",data:{order_id:$("#order_id").val(),status:$("#orderStatus").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".product-add-to-cart",function(t){var e=getSelectedOptions();parseInt($("#product_quantity").val())<0&&$("#product_quantity").val(0),$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$("#productId").val(),productQuantity:$("#product_quantity").val(),productOptions:JSON.stringify(e),productComment:$("#product_comment").val()}}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(".cart-product-quantity").on("input",function(){cartUpdate()}),$(document).on("click",".pushy-link",function(t){$("body").removeClass("pushy-open-right")}),$(document).on("click",".add-to-cart",function(t){var e="/product/"+$(this).attr("data-id");$(this).attr("data-link")&&(e="/product/"+$(this).attr("data-link")),"true"===$(this).attr("data-has-options")?window.location=e:$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id")}}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#empty-cart",function(t){$.ajax({method:"POST",url:"/product/emptycart"}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success",!0)})}),$(".qty-btn-minus").on("click",function(){var t=parseInt($("#product_quantity").val())-1;$("#product_quantity").val(t>0?t:1)}),$(".qty-btn-plus").on("click",function(){$("#product_quantity").val(parseInt($("#product_quantity").val())+1)}),$(".thumbnail-image").on("click",function(){$("#product-title-image").attr("src",$(this).attr("src"))}),$(".set-as-main-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/setasmainimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(".btn-delete-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/deleteimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#validate_permalink",function(t){""!==$("#productPermalink").val()?$.ajax({method:"POST",url:"/admin/api/validate_permalink",data:{permalink:$("#productPermalink").val(),docId:$("#productId").val()}}).done(function(t){console.log("msg",t),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}):showNotification("Please enter a permalink to validate","danger")}),$(document).on("click","#btn_product_filter",function(t){""!==$("#product_filter").val()?window.location.href="/admin/products/filter/"+$("#product_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_order_filter",function(t){""!==$("#order_filter").val()?window.location.href="/admin/orders/filter/"+$("#order_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_customer_filter",function(t){""!==$("#customer_filter").val()?window.location.href="/admin/customers/filter/"+$("#customer_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_search_reset",function(t){window.location.replace("/")}),$(document).on("click","#btn_search",function(t){t.preventDefault(),""===$("#frm_search").val().trim()?showNotification("Please enter a search value","danger"):window.location.href="/search/"+$("#frm_search").val()}),$(document).on("click","#frm_edit_product_save",function(t){""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val()))}),""!==$("#input_notify_message").val()){var l=$("#input_notify_message").val(),u=$("#input_notify_messageType").val();$("#input_notify_message").val(""),$("#input_notify_messageType").val(""),showNotification(l,u,!1)}}); \ No newline at end of file +function deleteFromCart(t){$.ajax({method:"POST",url:"/product/removefromcart",data:{cartId:t.attr("data-id")}}).done(function(e){$("#cart-count").text(e.totalCartItems),0===e.totalCartItems?($(t).closest(".cart-row").hide("slow",function(){$(t).closest(".cart-row").remove()}),$(".cart-contents-shipping").hide("slow",function(){$(".cart-contents-shipping").remove()}),showNotification(e.message,"success"),setTimeout(function(){window.location="/"},3700)):($(t).closest(".cart-row").hide("slow",function(){$(t).closest(".cart-row").remove()}),showNotification(e.message,"success"))}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function slugify(t){return $.trim(t).replace(/[^a-z0-9-æøå]/gi,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").replace(/æ/gi,"ae").replace(/ø/gi,"oe").replace(/å/gi,"a").toLowerCase()}function cartUpdate(t){$(t).val()>0?""!==$(t).val()&&updateCart():$(t).val(1)}function updateCart(){var t=[];$(".cart-product-quantity").each(function(){var e={cartIndex:$(this).attr("id"),itemQuantity:$(this).val(),productId:$(this).attr("data-id")};t.push(e)}),$.ajax({method:"POST",url:"/product/updatecart",data:{items:JSON.stringify(t)}}).done(function(t){updateCartDiv(),$("#cart-count").text(t.totalCartItems)}).fail(function(t){showNotification(t.responseJSON.message,"danger",!0)})}function updateCartDiv(){var t=window.location.pathname.split("/").length>0?window.location.pathname.split("/")[1]:"";$.ajax({method:"GET",url:"/cartPartial",data:{path:t}}).done(function(t){$("#cart").html(t)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function getSelectedOptions(){var t={};return $(".product-opt").each(function(){if("opt-"!==$(this).attr("name")){var e=$(this).val().trim();"radio"===$(this).attr("type")&&(e=$('input[name="'+$(this).attr("name")+'"]:checked').val()),t[$(this).attr("name").substring(4,$(this).attr("name").length)]=e}else t[$(this).val().trim()]=$(this).prop("checked")}),t}function showNotification(t,e,a){a=a||!1,$("#notify_message").removeClass(),$("#notify_message").addClass("alert-"+e),$("#notify_message").html(t),$("#notify_message").slideDown(600).delay(2500).slideUp(600,function(){!0===a&&location.reload()})}$(document).ready(function(){if("Material"===$("#cartTheme").val()&&$(".materialboxed").materialbox(),$(window).width()<768&&($(".menu-side").on("click",function(t){t.preventDefault(),$('.menu-side li:not(".active")').slideToggle()}),$('.menu-side li:not(".active")').hide(),$(".menu-side>.active").html(''),$(".menu-side>.active").addClass("menu-side-mobile"),0===$("#navbar ul li").length&&$("#navbar").hide(),$("#offcanvasClose").hide()),$(".shipping-form input").each(function(t){$(this).wrap("
    ");var e=$(this).attr("placeholder");$(this).after('")}),$(".shipping-form input").on("focus",function(){$(this).next().addClass("floatLabel"),$(this).next().removeClass("hidden")}),$(".shipping-form input").on("blur",function(){""===$(this).val()&&($(this).next().addClass("hidden"),$(this).next().removeClass("floatLabel"))}),$(".menu-btn").on("click",function(t){t.preventDefault()}),$("#sendTestEmail").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/admin/testEmail"}).done(function(t){showNotification(t,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#footerHtml").length){var t=window.CodeMirror.fromTextArea(document.getElementById("footerHtml"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1});t.setValue(t.getValue())}if($("#googleAnalytics").length&&window.CodeMirror.fromTextArea(document.getElementById("googleAnalytics"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1}),$("#customCss").length){var e=window.CodeMirror.fromTextArea(document.getElementById("customCss"),{mode:"text/css",tabMode:"indent",theme:"flatly",lineNumbers:!0}),a=window.cssbeautify(e.getValue(),{indent:" ",autosemicolon:!0});e.setValue(a)}if($("table").each(function(){$(this).addClass("table table-hover")}),$("#productTags").tokenfield(),$(document).on("click",".dashboard_list",function(t){window.document.location=$(this).attr("href")}).hover(function(){$(this).toggleClass("hover")}),$(".product-title").dotdotdot({ellipsis:"..."}),$('input[class="published_state"]').change(function(){$.ajax({method:"POST",url:"/admin/product/published_state",data:{id:this.id,state:this.checked}}).done(function(t){showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".btn-qty-minus",function(t){var e=$(t.target).parent().parent().find(".cart-product-quantity");$(e).val(parseInt(e.val())-1),cartUpdate(e)}),$(document).on("click",".btn-qty-add",function(t){var e=$(t.target).parent().parent().find(".cart-product-quantity");$(e).val(parseInt(e.val())+1),cartUpdate(e)}),$(document).on("change",".cart-product-quantity",function(t){cartUpdate(t.target)}),$(document).on("click",".btn-delete-from-cart",function(t){deleteFromCart($(t.target))}),$(document).on("click",".orderFilterByStatus",function(t){t.preventDefault(),window.location="/admin/orders/bystatus/"+$("#orderStatusFilter").val()}),$("#pager").length){var o=$("#pageNum").val(),i=$("#productsPerPage").val(),n=$("#totalProductCount").val(),s=$("#paginateUrl").val(),r=$("#searchTerm").val();""!==r&&(r+="/");var c="/"+s+"/"+r+"{{number}}",d=Math.ceil(n/i);parseInt(n)>parseInt(i)&&$("#pager").bootpag({total:d,page:o,maxVisible:5,href:c,wrapClass:"pagination",prevClass:"waves-effect",nextClass:"waves-effect",activeClass:"pag-active waves-effect"})}if($(document).on("click","#btnPageUpdate",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/pages/update",data:{page_id:$("#page_id").val(),pageName:$("#pageName").val(),pageSlug:$("#pageSlug").val(),pageEnabled:$("#pageEnabled").is(":checked"),pageContent:$("#pageContent").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#btnGenerateAPIkey",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/admin/createApiKey"}).done(function(t){$("#apiKey").val(t.apiKey),showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".product_opt_remove",function(t){t.preventDefault();var e=$(this).closest("li").find(".opt-name").html();$.ajax({method:"POST",url:"/admin/product/removeoption",data:{productId:$("#productId").val(),optName:e}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#product_opt_add",function(t){t.preventDefault();var e=$("#product_optName").val(),a=$("#product_optLabel").val(),o=$("#product_optType").val(),i=$("#product_optOptions").val(),n={};""!==$("#productOptions").val()&&'"{}"'!==$("#productOptions").val()&&(n=JSON.parse($("#productOptions").val()));var s='
  • ';s+='
    ',s+='
    '+e+"
    ",s+='
    '+a+"
    ",s+='
    '+o+"
    ",s+='
    '+i+"
    ",s+='
    ',s+='',s+="
  • ",$("#product_opt_wrapper").append(s),n[e]={optName:e,optLabel:a,optType:o,optOptions:$.grep(i.split(","),function(t){return 0===t||t})},$("#productOptions").val(JSON.stringify(n)),$("#product_optName").val(""),$("#product_optLabel").val(""),$("#product_optOptions").val("")}),$("#stripeButton").validator().on("click",function(t){(t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length)&&window.StripeCheckout.configure({key:$("#stripeButton").data("key"),image:$("#stripeButton").data("image"),locale:"auto",token:function(t){$("#stripeButton").data("subscription")&&$("#shipping-form").append(''),$("#shipping-form").append(''),$("#shipping-form").submit()}}).open({email:$("#stripeButton").data("email"),name:$("#stripeButton").data("name"),description:$("#stripeButton").data("description"),zipCode:$("#stripeButton").data("zipCode"),amount:$("#stripeButton").data("amount"),currency:$("#stripeButton").data("currency"),subscription:$("#stripeButton").data("subscription")})}),$("#adyen-dropin").length>0&&$.ajax({method:"POST",url:"/adyen/setup"}).done(function(t){const e={locale:"en-AU",environment:t.environment.toLowerCase(),originKey:t.publicKey,paymentMethodsResponse:t.paymentsResponse};new AdyenCheckout(e).create("dropin",{paymentMethodsConfiguration:{card:{hasHolderName:!1,holderNameRequired:!1,enableStoreDetails:!1,groupTypes:["mc","visa"],name:"Credit or debit card"}},onSubmit:(t,e)=>{0===$("#shipping-form").validator("validate").has(".has-error").length&&$.ajax({type:"POST",url:"/adyen/checkout_action",data:{shipEmail:$("#shipEmail").val(),shipFirstname:$("#shipFirstname").val(),shipLastname:$("#shipLastname").val(),shipAddr1:$("#shipAddr1").val(),shipAddr2:$("#shipAddr2").val(),shipCountry:$("#shipCountry").val(),shipState:$("#shipState").val(),shipPostcode:$("#shipPostcode").val(),shipPhoneNumber:$("#shipPhoneNumber").val(),payment:JSON.stringify(t.data.paymentMethod)}}).done(t=>{window.location="/payment/"+t.paymentId}).fail(t=>{console.log("Response",t),showNotification("Failed to complete transaction","danger",!0)})}}).mount("#adyen-dropin")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}),$("#settingsForm").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$("#footerHtml_input").val($(".CodeMirror")[0].CodeMirror.getValue()),$("#googleAnalytics_input").val($(".CodeMirror")[1].CodeMirror.getValue()),$("#customCss_input").val($(".CodeMirror")[2].CodeMirror.getValue()),$.ajax({method:"POST",url:"/admin/settings/update",data:$("#settingsForm").serialize()}).done(function(t){showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}))}),$("#customerLogout").on("click",function(t){$.ajax({method:"POST",url:"/customer/logout",data:{}}).done(function(t){location.reload()})}),$("#createCustomerAccount").validator().on("click",function(t){t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/customer/create",data:{email:$("#shipEmail").val(),firstName:$("#shipFirstname").val(),lastName:$("#shipLastname").val(),address1:$("#shipAddr1").val(),address2:$("#shipAddr2").val(),country:$("#shipCountry").val(),state:$("#shipState").val(),postcode:$("#shipPostcode").val(),phone:$("#shipPhoneNumber").val(),password:$("#newCustomerPassword").val()}}).done(function(t){location.reload()}).fail(function(t){showNotification(t.responseJSON.err,"danger")})}),$("#loginForm").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/admin/login_action",data:{email:$("#email").val(),password:$("#password").val()}}).done(function(t){window.location="/admin"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerLogin").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/login_action",data:{loginEmail:$("#customerLoginEmail").val(),loginPassword:$("#customerLoginPassword").val()}}).done(function(t){var e=t.customer;$("#shipEmail").val(e.email),$("#shipFirstname").val(e.firstName),$("#shipLastname").val(e.lastName),$("#shipAddr1").val(e.address1),$("#shipAddr2").val(e.address2),$("#shipCountry").val(e.country),$("#shipState").val(e.state),$("#shipPostcode").val(e.postcode),$("#shipPhoneNumber").val(e.phone),location.reload()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$(document).on("click",".image-next",function(t){var e=$(".thumbnail-image"),a=0,o=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(o=a+1===e.length||a+1<0?0:a+1),a++}),$("#product-title-image").attr("src",$(e).eq(o).attr("src"))}),$(document).on("click",".image-prev",function(t){var e=$(".thumbnail-image"),a=0,o=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(o=a-1===e.length||a-1<0?e.length-1:a-1),a++}),$("#product-title-image").attr("src",$(e).eq(o).attr("src"))}),$(document).on("click","#orderStatusUpdate",function(t){$.ajax({method:"POST",url:"/admin/order/statusupdate",data:{order_id:$("#order_id").val(),status:$("#orderStatus").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".product-add-to-cart",function(t){var e=getSelectedOptions();parseInt($("#product_quantity").val())<0&&$("#product_quantity").val(0),$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$("#productId").val(),productQuantity:$("#product_quantity").val(),productOptions:JSON.stringify(e),productComment:$("#product_comment").val()}}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(".cart-product-quantity").on("input",function(){cartUpdate()}),$(document).on("click",".pushy-link",function(t){$("body").removeClass("pushy-open-right")}),$(document).on("click",".add-to-cart",function(t){var e="/product/"+$(this).attr("data-id");$(this).attr("data-link")&&(e="/product/"+$(this).attr("data-link")),"true"===$(this).attr("data-has-options")?window.location=e:$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id")}}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#empty-cart",function(t){$.ajax({method:"POST",url:"/product/emptycart"}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success",!0)})}),$(".qty-btn-minus").on("click",function(){var t=parseInt($("#product_quantity").val())-1;$("#product_quantity").val(t>0?t:1)}),$(".qty-btn-plus").on("click",function(){$("#product_quantity").val(parseInt($("#product_quantity").val())+1)}),$(".thumbnail-image").on("click",function(){$("#product-title-image").attr("src",$(this).attr("src"))}),$(".set-as-main-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/setasmainimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(".btn-delete-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/deleteimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#validate_permalink",function(t){""!==$("#productPermalink").val()?$.ajax({method:"POST",url:"/admin/api/validate_permalink",data:{permalink:$("#productPermalink").val(),docId:$("#productId").val()}}).done(function(t){console.log("msg",t),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}):showNotification("Please enter a permalink to validate","danger")}),$(document).on("click","#btn_product_filter",function(t){""!==$("#product_filter").val()?window.location.href="/admin/products/filter/"+$("#product_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_order_filter",function(t){""!==$("#order_filter").val()?window.location.href="/admin/orders/filter/"+$("#order_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_customer_filter",function(t){""!==$("#customer_filter").val()?window.location.href="/admin/customers/filter/"+$("#customer_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_search_reset",function(t){window.location.replace("/")}),$(document).on("click","#btn_search",function(t){t.preventDefault(),""===$("#frm_search").val().trim()?showNotification("Please enter a search value","danger"):window.location.href="/search/"+$("#frm_search").val()}),$(document).on("click","#frm_edit_product_save",function(t){""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val()))}),""!==$("#input_notify_message").val()){var l=$("#input_notify_message").val(),u=$("#input_notify_messageType").val();$("#input_notify_message").val(""),$("#input_notify_messageType").val(""),showNotification(l,u,!1)}}); \ No newline at end of file diff --git a/routes/payments/adyen.js b/routes/payments/adyen.js new file mode 100644 index 0000000..67fe4b1 --- /dev/null +++ b/routes/payments/adyen.js @@ -0,0 +1,138 @@ +const express = require('express'); +const common = require('../../lib/common'); +const { indexOrders } = require('../../lib/indexing'); +const numeral = require('numeral'); +const { Client, CheckoutAPI } = require('@adyen/api-library'); +const router = express.Router(); + +router.post('/setup', async (req, res, next) => { + const adyenConfig = common.getPaymentConfig(); + + const client = new Client({ + apiKey: adyenConfig.apiKey, + environment: adyenConfig.environment + }); + const checkout = new CheckoutAPI(client); + let paymentsResponse; + try{ + paymentsResponse = await checkout.paymentMethods({ + amount: { + currency: 'AUD', + value: 0 + }, + countryCode: 'AU', + channel: 'Web', + merchantAccount: adyenConfig.merchantAccount + }); + }catch(ex){ + console.log('Exception getting supported payment methods', ex.message); + res.status(400).json({ message: 'Failed to retrieve payment methods.' + ex.message }); + } + res.status(200).json({ + paymentsResponse, + environment: adyenConfig.environment, + publicKey: adyenConfig.publicKey + }); +}); + +router.post('/checkout_action', async (req, res, next) => { + const db = req.app.db; + const config = req.app.config; + const adyenConfig = common.getPaymentConfig(); + + const client = new Client({ + apiKey: adyenConfig.apiKey, + environment: adyenConfig.environment + }); + const checkout = new CheckoutAPI(client); + let response; + try{ + response = await checkout.payments({ + shopperInteraction: 'Ecommerce', + amount: { + currency: adyenConfig.currency, + value: numeral(req.session.totalCartAmount).format('0.00').replace('.', '') + }, + paymentMethod: JSON.parse(req.body.payment), + reference: adyenConfig.statementDescriptor, + merchantAccount: adyenConfig.merchantAccount, + shopperStatement: adyenConfig.statementDescriptor + }); + }catch(ex){ + console.log('Payment exception', ex.message); + req.session.messageType = 'danger'; + req.session.message = 'Card declined. Contact card issuer'; + return; + } + + // Update response + let paymentStatus = 'Paid'; + if(response && response.resultCode !== 'Authorised'){ + paymentStatus = 'Declined'; + } + + // new order doc + const orderDoc = { + orderPaymentId: response.pspReference, + orderPaymentGateway: 'Adyen', + orderPaymentMessage: response.refusalReason, + 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, + orderComment: req.body.orderComment, + orderStatus: paymentStatus, + orderDate: new Date(), + orderProducts: req.session.cart, + orderType: 'Single' + }; + + // insert order into DB + const newOrder = await db.orders.insertOne(orderDoc); + + // get the new ID + const newId = newOrder.insertedId; + + // add to lunr index + indexOrders(req.app) + .then(() => { + // Process the result + if(paymentStatus === 'Paid'){ + // set the results + req.session.messageType = 'success'; + req.session.message = 'Your payment was successfully completed'; + req.session.paymentEmailAddr = orderDoc.orderEmail; + req.session.paymentApproved = true; + req.session.paymentDetails = '

    Order ID: ' + newId + '

    Transaction ID: ' + response.pspReference + '

    '; + + // 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){ + 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)); + } + res.status(200).json({ paymentId: newId }); + }); +}); + +module.exports = router; diff --git a/views/order.hbs b/views/order.hbs index 9481625..15b1f47 100644 --- a/views/order.hbs +++ b/views/order.hbs @@ -28,6 +28,9 @@
  • {{ @root.__ "Order ID" }}: {{result._id}}
  • {{ @root.__ "Payment Gateway ref" }}: {{result.orderPaymentId}}
  • {{ @root.__ "Payment Gateway" }}: {{result.orderPaymentGateway}}
  • + {{#if result.orderPaymentMessage}} +
  • {{ @root.__ "Payment Message" }}: {{result.orderPaymentMessage}}
  • + {{/if}}
  • {{ @root.__ "Order total amount" }}: {{currencySymbol config.currencySymbol}}{{formatAmount result.orderTotal}}
  • {{ @root.__ "Email address" }}: {{result.orderEmail}}
  • {{ @root.__ "First name" }}: {{result.orderFirstname}}
  • diff --git a/views/partials/menu.hbs b/views/partials/menu.hbs index f79dc37..313082c 100644 --- a/views/partials/menu.hbs +++ b/views/partials/menu.hbs @@ -1,5 +1,5 @@
    -

    Menu

    +

     

    diff --git a/views/themes/Material/pay.hbs b/views/themes/Material/pay.hbs index c8413b2..73b3c80 100644 --- a/views/themes/Material/pay.hbs +++ b/views/themes/Material/pay.hbs @@ -54,6 +54,9 @@ {{#ifCond config.paymentGateway '==' 'authorizenet'}} {{> partials/payments/authorizenet}} {{/ifCond}} + {{#ifCond config.paymentGateway '==' 'adyen'}} + {{> partials/payments/adyen}} + {{/ifCond}} {{/if}} diff --git a/views/themes/Mono/pay.hbs b/views/themes/Mono/pay.hbs index 9b57baf..abb5278 100644 --- a/views/themes/Mono/pay.hbs +++ b/views/themes/Mono/pay.hbs @@ -54,6 +54,9 @@ {{#ifCond config.paymentGateway '==' 'authorizenet'}} {{> partials/payments/authorizenet}} {{/ifCond}} + {{#ifCond config.paymentGateway '==' 'adyen'}} + {{> partials/payments/adyen}} + {{/ifCond}} {{/if}}