Maingate Add Diff GiveX Gift Card Code
[video width="1280" height="800" mp4="http://wiki.onelivemedia.com/wp-content/uploads/2017/09/rcrecord_1.mp4"][/video]
open checkout.liquid and replace the code with the following:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="{{ locale }}" dir="{{ direction }}" class="{{ checkout_html_classes }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, height=device-height, minimum-scale=1.0, user-scalable=0">
<meta name="referrer" content="origin">
<title>{{ shop.name }} - {{ page_title }}</title>
{{ content_for_header }}
{{ checkout_stylesheets }}
{{ checkout_scripts }}
{{ 'jquery.min.js' | asset_url | script_tag }}
<script type="text/javascript">
var DISCOUNT_FORM = {
FORM_CLASS: '.discount__form',
DISCOUNT_FIELD_CLASS: '.billing__discount',
DISCOUNT_INVALID_WRAPPER_CLASS: '.discount__invalid',
SUBMIT_CLASS: '.discount__submit'
};
(function() {
$(function() {
try { validateUI(); } catch(e) {}
// --------------------------------------------------
// SHOPIFY MAPPINGS
// --------------------------------------------------
// declaration for discount mapping
var discount;
// --------------------------------------------------
// SHOPIFY HELPER FUNCTIONS
// --------------------------------------------------
// determines current Shopify checkout step based on DOM content
function currentStep() {
if ($(".step[data-step=contact_information]").length) return 'contact_info';
if ($(".step[data-step=shipping_method]").length) return 'shipping_method';
else if ($('.step[data-step=payment_method]').length) return 'billing_info';
else if ($('html.page--processing').length) return 'processing_payment';
else if ($('html.page--stock-problems').length) return 'stock_problems';
else if ($('html.page--thank-you').length) return 'thank_you';
return false;
}
// check discount field is populated
function validateDiscountForm(form) {
if ($(form).find(DISCOUNT_FORM.DISCOUNT_FIELD_CLASS).val() != '') {
$(form).find(DISCOUNT_FORM.SUBMIT_CLASS).attr('disabled', false).removeClass('btn--disabled');
return true;
} else {
$(form).find(DISCOUNT_FORM.SUBMIT_CLASS).attr('disabled', true).addClass('btn--disabled');
return false;
}
}
// check all discount forms on page
function validateDiscountForms() {
$(DISCOUNT_FORM.FORM_CLASS).each(function() {
validateDiscountForm(this);
});
}
function createMobileForm() {
// Only created the mobile form if it doesn't exist
if($(".section--reductions .ui-element__discount").length === 0) {
var insertedForm = $('.ui-element__discount').clone().insertAfter(
$('.section--reductions [data-reduction-form]').first()
);
$('.ui-element__discount').show();
return insertedForm.find('form')[0];
}
return undefined;
}
// hook into Shopify's checkout JS to trigger custom code on discount events
function setupDiscountHandler() {
if ( $('#checkout_reduction_code').length ) {
var _old_updater = ReductionForm.prototype.updatePage;
ReductionForm.prototype.updatePage = function(r) {
_old_updater.apply(this, arguments);
handleDiscountEvent();
// We need to recreate the mobile form since it gets destroyed on certain
// update events
var createdForm = createMobileForm();
if(createdForm) {
setupFormListeners(createdForm);
}
};
handleDiscountEvent();
$('.ui-element__discount').insertAfter(
$('.order-summary__sections .order-summary__section--discount').first()
);
createMobileForm();
$('.ui-element__discount').show();
}
}
function setupFormListeners(form) {
// --------------------------------------------------
// FORM EVENTS
// --------------------------------------------------
// validate and allow / deny discount submission
$(form).on('change keyup input blur', 'input', function() {
validateDiscountForm($(this).parents(DISCOUNT_FORM.FORM_CLASS).addBack().first());
});
// discount form submit handler
$(form).submit(function(e) {
e.preventDefault();
if (!validateDiscountForm(this))
return false;
$(this).find('button[type=submit]').addClass('btn--loading');
submitCustomPromo($(this).find(DISCOUNT_FORM.DISCOUNT_FIELD_CLASS).val());
});
}
// handles discount form responses. will update custom discount
// forms to match shopify's response
function handleDiscountEvent() {
// re-initialize discount values based on shopify's new DOM
discount = {
$field: $('#checkout_reduction_code'),
errors: !!$('#error-for-reduction_code').length,
submit: function() {
$('#checkout_reduction_code').closest('form').submit();
},
remove: function() {
$('.applied-reduction-code__clear-button').click();
},
};
// scramble to find discount name and amount in the DOM
discount.applied_code = {
// ew. name comes from either a successful discount info div, the shopify form val() itself,
// or a warning status message that needs to be regex'd in order to find the code
name: $('.applied-reduction-code__information').text() || $('#checkout_reduction_code').val() || ($('[data-discount-warning]').text().match(/for the (.+) discount code/)||[]).pop(),
// also ew. amount can be found in Shopify's DOM but needs to be cleaned
amount: $('.applied-reduction-code__information').closest('form')
.find('.content-box__row__right').length && parseFloat(
$('.applied-reduction-code__information').closest('form')
.find('.content-box__row__right').text()
.replace('-','').replace('$','').replace(',','').trim()
).toFixed(2).replace('.00',''),
};
// if code is applied successfully, show applied form, hide others
if (discount.applied_code.amount) {
$(DISCOUNT_FORM.FORM_CLASS).find('.field').removeClass('field--error').show();
$(DISCOUNT_FORM.DISCOUNT_INVALID_WRAPPER_CLASS).hide();
$(DISCOUNT_FORM.DISCOUNT_FIELD_CLASS).val('').blur();
// if code failed to apply, hide applied form and show default form
} else if (discount.errors) {
$(DISCOUNT_FORM.FORM_CLASS).find('.field').addClass('field--error').show();
$(DISCOUNT_FORM.DISCOUNT_INVALID_WRAPPER_CLASS).show();
$(DISCOUNT_FORM.DISCOUNT_FIELD_CLASS).focus();
// else a discount was removed or no discount is applied yet
} else {
$(DISCOUNT_FORM.FORM_CLASS).find('.field').removeClass('field--error').show();
$(DISCOUNT_FORM.DISCOUNT_INVALID_WRAPPER_CLASS).hide();
$(DISCOUNT_FORM.DISCOUNT_FIELD_CLASS).val('').blur();
}
$(DISCOUNT_FORM.FORM_CLASS).find('button[type=submit]').removeClass('btn--loading');
}
function submitCustomPromo(code) {
var AUTH_CARD_URL = '/apps/api/v1/authorize_gift_card';
$.post(AUTH_CARD_URL, { gift_card_code: code }).always(function(r) {
console.log(r);
submitShopifyCode(code);
});
}
function submitShopifyCode(code) {
if(code.length > 20) {
code = code.substring(code.length - 20);
}
discount.$field.val(code);
discount.submit();
}
// --------------------------------------------------
// CHECKOUT STEP SPECIFIC LOGIC
// --------------------------------------------------
if (currentStep() == 'contact_info'
|| currentStep() == 'shipping_method'
|| currentStep() == 'billing_info') {
setupDiscountHandler();
$(DISCOUNT_FORM.FORM_CLASS).each(function() {
setupFormListeners(this);
});
validateDiscountForms();
}
function validateUI() {
for (var field in DISCOUNT_FORM) {
if (DISCOUNT_FORM.hasOwnProperty(field) && !$(DISCOUNT_FORM[field]).length)
console.log('%c DISCOUNT FORM - UI ELEMENT MISSING: ' + field + '. Value specified: ' + DISCOUNT_FORM[field], 'background: #fff0f0; color: #ff1234');
}
}
});
}());
</script>
</head>
<body>
{{ skip_to_content_link }}
{% unless settings.gtm-container-id == blank %}
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id={{ settings.gtm-container-id }}"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','{{ settings.gtm-container-id }}');</script>
<!-- End Google Tag Manager -->
{% endunless %}
<div class="banner" data-header>
<div class="wrap">
{{ content_for_logo }}
</div>
</div>
{{ order_summary_toggle }}
<div class="content" data-content>
<div class="wrap">
<div class="main" role="main">
<div class="main__header">
{{ content_for_logo }}
{{ breadcrumb }}
{{ alternative_payment_methods }}
</div>
<div class="main__content">
{{ content_for_layout }}
</div>
<div class="main__footer" role="contentinfo">
{{ content_for_footer }}
</div>
</div>
<div class="sidebar">
<div class="sidebar__header">
{{ content_for_logo }}
</div>
<div class="sidebar__content">
{{ content_for_order_summary }}
</div>
</div>
</div>
</div>
<div class="order-summary__section order-summary__section--discount ui-element__discount">
<form class="discount__form">
<div class="fieldset">
<div class="field">
<div class="field__input-btn-wrapper">
<div class="field__input-wrapper"><label class="field__label" for="custom-promo__code">PROMOTION CODE</label>
<input placeholder="Gift Card or Discount Code" class="field__input billing__discount" autocomplete="off" size="30" type="text" id="custom-promo__code">
</div>
<button type="submit" class="field__input-btn btn discount__submit">
<span class="btn__content visually-hidden-on-mobile">Apply</span>
<i class="btn__content shown-on-mobile icon icon--arrow"></i>
<i class="btn__spinner icon icon--button-spinner"></i>
</button>
</div>
<p class="discount__invalid field__message field__message--error">Unable to find a valid discount matching the code entered</p>
</div>
</div>
</form>
</div>
{{ tracking_code }}
<script type="text/javascript">
$(document).ready(function() {
$('input[name="checkout[shipping_address][first_name]"]').attr('maxlength', 20);
$('input[name="checkout[shipping_address][last_name]"]').attr('maxlength', 20);
$('input[name="checkout[shipping_address][company]"]').attr('maxlength', 40);
$('input[name="checkout[shipping_address][address1]"]').attr('maxlength', 40);
$('input[name="checkout[shipping_address][address2]"]').attr('maxlength', 40);
$('input[name="checkout[shipping_address][city]"]').attr('maxlength', 30);
});
</script>
</body>
</html>
<style type="text/css">
#livechat-compact-container {
display: none;
}
.order-summary__section--discount { display: none; }
[class*=ui-element__] { display: none; }
.section--reductions div[data-reduction-form] { display: none; }
</style>
Create a snippet named page.gift_cart_checker.liquid
and add the following code:
{% include 'theme-variables' %}
<section id="page-wrap" class="section-wrap">
{% include '__containers-open' %}
<h1 class="page-header">{{ page_title }}</h1>
<div class="balance-page-form">
<form id="cart-balance-form">
<div class="form-group">
<label class="control-label" for="giftcartFormInput">Gift Card</label>
<div class="controls">
<input type="text" id="giftcartFormInput" class="input-xlarge form-control" name="gift_card_code">
</div>
</div>
<button class="btn btn-primary" id="card-balance-form-submit" type="submit" disabled>Verify Card</button>
</form>
<br/>
<form id="captcha-form" action="https://www.google.com/recaptcha/api/siteverify" method="POST">
<div class="g-recaptcha" data-sitekey="6Lf7Ei8UAAAAAHwtTIecgqmQQD4OLTNQYJVGtlA1" data-callback="verifySubmitState" data-expired-callback="disableButton"></div>
</form>
</div>
<div id="gift-card-message"></div>
{% include '__containers-close' %}
</section>
open _base.scss.liquid and add the following code at the end of the file.
#gift-card-message {
margin-top: 10px;
}
Open _base.js Change the window events to on load instead of .load. Should be around line 163
$(window).on('load', function(){
Still in _base.js add the following code at the bottom of the file
// Form submission handling for the gift card balance checker page
$(function() {
$('#cart-balance-form').submit(function(e) {
e.preventDefault();
var VERIFY_CARD_URL = '/apps/api/v1/check_gift_card_balance';
var $responseContainer = $('#gift-card-message');
$responseContainer.empty().removeClass('text-danger');
$.post({
url: VERIFY_CARD_URL,
data: $(this).serialize(),
dataType: 'json'
})
.done(function(r) {
$responseContainer.html(r.message);
})
.fail(function(r){
$responseContainer.html(r.responseJSON.message).addClass('text-danger');
});
});
});
$(function() {
$("#cart-balance-form #giftcartFormInput").change(function() {
if($("#giftcartFormInput").attr("data-captcha") == "true")
{
$("#card-balance-form-submit").prop('disabled', false);
}
});
window.verifySubmitState = function()
{
$("#giftcartFormInput").attr("data-captcha", "true");
if($("#giftcartFormInput").val().length) {
$("#card-balance-form-submit").prop('disabled', false);
}
}
window.disableButton = function()
{
$("#giftcartFormInput").attr("data-captcha", "false");
$("#card-balance-form-submit").prop('disabled', true);
}
});
Open theme.liquid and right before the </head> tag add the following code:
<script src='https://www.google.com/recaptcha/api.js'></script>Still within theme.liquid find the line that says
var uniformThumbnailsOpts = ;and change it to
var uniformThumbnailsOpts = null;
APP PRE-INSTALL
Reach out to the Diff team and have them add the store to their list of stores. IMPORTANT: Without this step, the app will not install.
Within the back-end of Shopify create a private app (keep note of the settings because they will be used to set up the givex integration app).
Give read and write access to gift cards and gift cards adjustments.
Contact Shopify and ask them to unlock Gift Cards and Gift Card Adjustments.
INSTALL THE APP
go to givex-shopify-integration.bencrudo.com/login
and add your Shopify URL Click install.
APP SETTINGS
Within the app navigate to the Jobs section and set each interval to 2
Navigate to the Givex configurations section and add the API Key & Password and Givex credentials.
CAPTCHA
Create a new recaptcha. Open https://www.google.com/recaptcha/admin in your browser
choose reCAPTCHA V2
and add the store's actual domain name
Copy the data-sitekey
Back in Shopify open page.gift_cart_checker.liquid and replace the data-sitekey with the new one.