I have a client who has signed up for a sagepay account. His current website runs off wordpress 3.0 and currently doesn't have any sort of ecommerce functionality.
He's needing a button that lets users submit a deposit of £300 through sagepay (this amount never changes).
(Usually, I would suggest using paypal for something like this, but apparently due to the travel nature of his business, paypal won't let my client have a pro account)
I've looked at the method described in a similar thread on here back in March (How Do I Make a SagePay BuyNow Button?), but I'm not really sure how to implement this within a page on wordpress, not hugely knowledgeable on php bar basic template editing, so I got totally lost at the $PAYMENT_CRYPT part.
If anyone could provide the steps I need to take to implement a basic button that submits the same amount each time, and then collects all the card details/customer details once it's sent them to sagepay gateway, it would be hugely appreciated!
In short, no. These is no easy way to approach this. Unless you link to a Payment form to SagePay and use the new IFRAME feature. You can have certain information within WordPress that allows PHP code on your template pages or your template files.
1 - IFRAME the form within your PHP server and code the form on its own that way the CSS will become like the CSS on the WordPress page
2 - Create a payment module for it
3 - Use an existing Payment eCommerce server module for WordPress - there are plenty of plugins already
4 - Create a payment button hyper link, once clicked, it goes to a PHP form on your server for the £300 amount..
5 - Use Nochex or another payment vendor, Google Wallet etc (this is not an easy option for the client)
With the FORM, you could have:
<?
# Define your vars
$serverLive="https://live.sagepay.com/gateway/service/vspform-register.vsp"
//$serverLive="https://test.sagepay.com/gateway/service/vspform-register.vsp"
$YOUR_VENDOR_LOGIN_NAME="";
$VendorTxCode="406227821909";
$Amount="350.00";
$Currency="GBP";
$Description="1 ACME Widget";
$SuccessURL="http://example.com/success.php";
$FailureURL="http://example.com/fail.php";
$BillingSurname="Smith";
$BillingFirstnames="John";
$BillingAddress1="123 Main Street";
$BillingCity="Anywhere";
$BillingPostCode="29555";
$BillingCountry="USA";
$DeliverySurname="Smith";
$DeliveryFirstnames="John";
$DeliverAddress1="123 Main Street";
$DeliveryCity="Anywhere";
$DeliveryPostCode="29555";
$DeliveryCountry="GBP";
# The address information can be done via jQuery on your page or get some defaults
?>
<form action="<?=$serverLive?>" method="POST" id="SagePayForm" name="SagePayForm">
<input type="hidden" name="VPSProtocol" value="2.23" />
<input type="hidden" name="TxType" value="PAYMENT" />
<input type="hidden" name="Vendor" value="<?= $YOUR_VENDOR_LOGIN_NAME ?>" />
<input type="hidden" name="Crypt" value="<?= $PAYMENT_CRYPT ?>">
<input type="image" src="images/buynow-sagepay.png" />
</form>
<script type="text/javascript">
function submitform()
{
document.SagePayForm.submit();
}
submitform();
</script>
Even with this code you would still need to use some SagePay libraries, such as the XOR and Crypt functions:
// Crypt and XOR functions
private function simpleXor($string, $password) {
$data=array();
for ($i=0; $i < utf8_strlen($password); $i++) {
$data[$i]=ord(substr($password, $i, 1));
}
$output='';
for ($i=0; $i < utf8_strlen($string); $i++) {
$output .= chr(ord(substr($string, $i, 1)) ^ ($data[$i % utf8_strlen($password)]));
}
return $output;
}
Related
I’m trying to use the contact form in my template using do_shortcode and popup (Request availability button on a page). But I’ve noticed that form generated only inputs without <form> tag as usual so it failed to submit.
That’s how I’m implementing it in functions.php
function wc_shop_popup() {
$reqform = '[contact-form-7 id="987" title="Request availability"]';
echo '<a class="button button_full_width button_left req_button popup-link" href="#popup-availability" rel="lightbox" data-type="inline"><span class="button_icon"><i class="icon-layout"></i></span><span class="button_label">Request Availability</span></a>
<div id="popup-availability" class="popup-content mfp-hide"><div class="popup-inner" style="padding:20px;">'.do_shortcode($reqform).'</div></div>';
}
add_action( 'woocommerce_after_add_to_cart_button', 'wc_shop_popup' );
This is the page - Request availability button. Any suggestions?
The problem was that contact form has been generated inside of add to cart form. I used another woocommerce hook called "woocommerce_after_single_product_summary" instead of "woocommerce_after_add_to_cart_button" and it's working!
Summary
We have a Magento 2 store that we are having trouble setting up Google Analytics to track eccommerce correctly.
We have followed the Magento docs for setting up GA & GTM, but it is not collecting the correct amount of Sessions with Add to Basket in the Conversions > Ecommerce > Shopping Behavior.
From the image above you can see that it is not tracking the sessions correctly. 27 Sessions with Checkout but only 1 Session with Add to Basket, this does not add up, a user must add to cart before getting to the checkout.
Also, when I check the no of orders on Magento I see there are actually 29 orders, 27 of which are from different users. So it seems it's not capturing the number of orders correctly too.
Debugging/Setup
We followed the Magento docs for setting up GA & GTM as I show below. If you click on an image below you should see a better quality one.
We have E-commerce setup in GA:
At first I discovered with the GTM preview mode that the addToCart tag which was set up with the recommended Magento configuration was not firing. It seems the data layer event was not firing for the GTM trigger.
So I set up a new trigger which fired on Click and added it to the :
I can now see the tag firing in GTM preview mode:
And I can see the Add to Cart event in GAs Real-time Event report.
But still it's not showing the correct data in the Sessions with Add to Basket in the Conversions > Ecommerce > Shopping Behavior.
Questions
What could I be missing?
Should I set Non-Interaction Hit to false in the GTM tag setting?
Should I set use data layer to false for the tag in GTM, as the
addToCart custom event is not firing? Or maybe this is still needed
for something.
Any tips on how I can debug why the addToCart custom event is nor
firing on Magento while GTM is in preview mode?
I noted that the session in Magento is 3.5 hours, while in GA the Session timeout is only 30min. Perhaps this could be it? we changed the GA session timeout to match Magento's, and this was not it :(
Thank you in advance, any help appreciated :)
Based on the comment from #lossleader to my question, I was able to identify and fix the issue. I'll answer it here in case anyone else finds it helpful.
Basically as #lossleader said in his comment the main thing is:
The custom event should also have contained the e-commerce data for the use dataLayer tag.
So triggering the addToCart tag with a simple click event is not enough as it does not contain the e-commerce data, I needed to fix how the enhance ecommerce addToCart event was triggered on Magento.
I discovered that Magento Commerce changed/fixed how they end up calling the function which trigger this event in recent upgrades, i.e. commit MAGETWO-69210 & commit MAGETWO-87437
Our Magento did receive these changes as the list.phtml template and the catalog-add-to-cart.js file were being overridden in it's theme.
Updating the theme files as the below diff shows resolved the issue in our case:
diff --git a/app/code/Namespace/CategoryPages/view/frontend/templates/product/list.phtml b/app/code/Namespace/CategoryPages/view/frontend/templates/product/list.phtml
index 6771e863..2ab8905c 100644
--- a/app/design/frontend/Namespace/theme/Magento_Catalog/templates/product/list.phtml
+++ b/app/design/frontend/Namespace/theme/Magento_Catalog/templates/product/list.phtml
## -91,7 +91,7 ## $_helper = $this->helper('Magento\Catalog\Helper\Output');
<div class="actions-primary"<?php echo strpos($pos, $viewMode . '-primary') ? $position : ''; ?>>
<?php if ($_product->isSaleable()): ?>
<?php $postParams = $block->getAddToCartPostParams($_product); ?>
- <form data-role="tocart-form" action="<?php /* #escapeNotVerified */ echo $postParams['action']; ?>" method="post">
+ <form data-role="tocart-form" data-product-sku="<?= $block->escapeHtml($_product->getSku()) ?>" action="<?= /* #NoEscape */ $postParams['action'] ?>" method="post">
<input type="hidden" name="product" value="<?php /* #escapeNotVerified */ echo $postParams['data']['product']; ?>">
<input type="hidden" name="<?php /* #escapeNotVerified */ echo Action::PARAM_NAME_URL_ENCODED; ?>" value="<?php /* #escapeNotVerified */ echo $postParams['data'][Action::PARAM_NAME_URL_ENCODED]; ?>">
<?php echo $block->getBlockHtml('formkey')?>
diff --git a/app/design/frontend/Namespace/theme/Magento_Catalog/web/js/catalog-add-to-cart.js b/app/design/frontend/Namespace/theme/Magento_Catalog/web/js/catalog-add-to-cart.js
index fae6f0fa..34978ec4 100644
--- a/app/design/frontend/Namespace/theme/Magento_Catalog/web/js/catalog-add-to-cart.js
+++ b/app/design/frontend/Namespace/theme/Magento_Catalog/web/js/catalog-add-to-cart.js
## -6,8 +6,10 ##
define([
'jquery',
'mage/translate',
+ 'underscore',
+ 'Magento_Catalog/js/product/view/product-ids-resolver',
'jquery/ui'
-], function ($, $t) {
+], function ($, $t, _, idsResolver) {
'use strict';
$.widget('mage.catalogAddToCart', {
## -75,7 +77,9 ## define([
* #param {String} form
*/
ajaxSubmit: function (form) {
- var self = this;
+ var self = this,
+ productIds = idsResolver(form),
+ formData = new FormData(form[0]);
$(self.options.minicartSelector).trigger('contentLoading');
self.disableAddToCartButton(form);
## -97,6 +101,13 ## define([
success: function (res) {
var eventData, parameters;
+ $(document).trigger('ajax:addToCart', {
+ 'sku': form.data().productSku,
+ 'productIds': productIds,
+ 'form': form,
+ 'response': res
+ });
+
if (self.isLoaderEnabled()) {
$('body').trigger(self.options.processStop);
}
The custom event that was pushed should also have contained the e-commerce data referred to in the "use dataLayer" tag, so you really needed to fix the magento configuration or detection of the user action rather than emulate it. I.e. look for customizations to the store's html around these inputs/forms and try reverting them to stock.
It looks like you found the complete answer by looking into updates to magento for the addToCart event that were being overridden by the installed theme.
Hi I'm trying to get into Wordpress Ajax Requests right now. Now I have finished a script that works perfectly. But since I'm not a security professional, I'd like to ask you if you can help me.
I would also like to know if I have to use a form every time or if I can start a request directly via jQuery Ajax. If so, how do I do that with dynamic requests where I can not set the nonce before? e.g. in a list where each entry has multiple buttons?
Many Thanks!
template-form.php
<form method="post" id="form">
<input type="text" name="form_name" />
<?php wp_nonce_field( 'form_action', 'form_nonce' ); ?>
<input type="submit" id="submit" value="save">
</form>
script.js
jQuery("#submit").click(function (e) {
e.preventDefault();
jQuery.post(ajaxurl + "/ajax.php", jQuery("#form").serialize()).done(function (data) {
alert(data);
});
return false;
});
ajax.php
<?php
define( 'WP_USE_THEMES', false );
require_once( $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php' );
if( isset( $_POST['form_nonce'] ) && wp_verify_nonce( $_POST['form_nonce'], 'form_action') ) {
$form_name = sanitize_text_field($_POST['form_name']);
echo "is working";
}else{
echo "not working";
wp_die();
}
?>
I would also like to know if I have to use a form every time or if I
can start a request directly via jQuery Ajax. If so, how do I do that
with dynamic requests where I can not set the nonce before? e.g. in a
list where each entry has multiple buttons?
No you could also use wp_nonce_url to make ajax calls.
But as far as I know, I will not work if you have a multisite installation and send an ajax call from one blog of the network to another blog.
Apart from that, you code looks ok to me and you are also saying that it is working.
Therefore I am confused where exactly you need help.
Could you clarify your question, please?
I'm trying to implement the checkout fuctionality (+ stripe with WooCommerce Stripe Payment Gateway plugin) in a modal window, and I'm using the ajax for this. Here is my backend code to get/refresh the checkout:
add_action('wp_ajax_refresh_checkout', 'getCheckoutPageContentCallBack');
add_action('wp_ajax_nopriv_refresh_checkout', 'getCheckoutPageContentCallBack');
function getCheckoutPageContentCallBack() {
define('WOOCOMMERCE_CHECKOUT', true);
echo do_shortcode('[woocommerce_checkout]');
if (class_exists('WooCommerce')) {
$wcurl = WooCommerce::plugin_url();
$credit_card_form_script = file_get_contents($wcurl . '/assets/js/frontend/credit-card-form.min.js');
if ($credit_card_form_script) {
echo "<script>";
echo $credit_card_form_script;
echo "</script>";
}
$checkout_script = file_get_contents($wcurl . '/assets/js/frontend/checkout.min.js');
if ($checkout_script) {
echo "<script>";
echo $checkout_script;
echo "</script>";
}
}
wp_die();
}
I included all the scripts that checkout page has, but still getting the error:
Please enter your card details to make a payment. Developers: Please make sure that you are including jQuery and there are no JavaScript errors on the page.
jQuery is included and there are no js errors on the page. The original checkout page works just fine. I thought the problem was that I removed the payment part from the original part by this code:
remove_action('woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20);
add_action('woocommerce_checkout_order_payment', 'woocommerce_checkout_payment', 20);
But commenting these lines gave me nothing. I edited the page, so this is not even a shop page right now (just a page with a loop).
I noticed that when making payments via the checkout page, the first request goes to the https://api.stripe.com/v1/tokens with card credentials, the next one goes to /checkout/?wc-ajax=checkout with stripe_token and so When I try to checkout from my modal, there is no request to the Stripe API, just to the checkout. Maybe there is some script I need to include every time I refresh the checkout? I can't find any info about it.
I need some guidance on how to properly code a dynamic web page containing 10 questions each having its own submit button. Here's a quick background and what I'm doing.
I'm creating a question/answer page in which a user answers questions and hits Submit. Each question has a point value which gets added to the user's bank if answered correctly.
The questions are populated on the page through a database table containing three fields - QuestionNumber, Question, Points. Each Question has a QuestionNumber assigned to it so I can easily and quickly ID the question and answer. This displays fine (here's the code):
<?
$rt = mysql_query("SELECT * FROM Questions WHERE Status='Open' ORDER BY 'Number' LIMIT 10");
while ($row = mysql_fetch_array($rt)) {
$number=$row[0];
$category = $row[1];
$question=$row[2];
$points=$row[4];
?>
<form action="processor.php" method="post" class="qForm">
<div class="questionCell">
<div class="question"><? echo $question; ?></div>
<div class="answer">Answer: <input class="inputField" name="a0001" type="text" size="40" maxlength="40" />
<input name="HHQuestion" value="Question: <? echo $number; ?>" type="submit" /></div>
</div>
</form>
<?
}
?>
This form gets repeated 10 times on the page, and each has its own question and QuestionNumber. Also, every submit button has the value assigned based on the questionNumber. I did this so that the user (young kids) knows which question they're about to answer. This all displays very nicely on the page.
The problem I'm having is with the POST file "processor.php", which has not been created yet. The way I envision it to work is that when someone submits their answer, the processor.php file will capture the quesiotnNumber (that's assigned to the button) and answer from the text field, then validate it again the database table.
I know that I should be using SWITCH / CASE (as opposed to IF ELSE) when using multiple buttons, which I'm fine with. But how do I capture the QuestionNumber on the form into the processor.php file?
My ultimate goal for this project is to just populate the question table in the database, and let the webpage work dynamically.
Thanks in advance for any help and guidance.
R
I'm a little confused about your wording, but am I understanding correctly in thinking that you wish to submit the answer to each question to the database although you have them all running on the same page?
If so, I'd recommend using an AJAX library to send the data back and get a quick response. There are a number out there, but jQuery is very simple to use (along with having a number of other features). Below is some psuedocode:
function submitAnswer(questionid)
{
answer = document.getElementById("a000"+questionid);
$.get("processor.php", {"answer": answer, "question": questionid}, function (data) {
if (data.response == "200") {
document.getElementById("response-"+questionid).innerHTML = "Thanks for answering";
}
});
}
Then you could call it with something like:
<input type = "submit" onclick = "submitAnswer('<?=$number?>'); void(0); return false;">
Please note this is all psuedo! Your mileage may vary! Shout out if you have any questions.