Getting UserState in onAfterOrderCreated

  • Posts: 195
  • Thank you received: 13
  • Hikashop Business
4 years 6 months ago #319082

-- HikaShop version -- : 4.3.0
-- Joomla version -- : 3.9.11
-- PHP version -- : 7.2.30
-- Error-message(debug-mod must be tuned on) -- : This is specific to my application - Braintree payment plugin

We have developed the Braintree Payment Plugin. Some JS on the checkout page takes parameters from the authorization transaction and sends them via AJAX call which ends up in onPaymentNotification. There the setUserState (or JFactory::getSession()->set() saves the array of parameters as the user state / session variable.

Once the user then clicks the Finish button in checkout, the onAfterOrderCreate (or onBeforeOrderCreate or onPaymentDisplay) when I try to get the parameters from the user state or session (same thing?) they are not there.

The above happens on the first attempt at checkout by a logged in user in native or legacy checkout mode. Guest users are able to checkout fine.

If you have any ideas why the onAfterOrderCreate, onBeforeOrderCreate, or onPaymentDisplay functions would NOT be able to immediately read user state values please let us know. Of if you have suggestions on another secure way to store information per order (without custom fields) please let us know that also.

Thanks for reading. Paul @ 3by400.com


3by400, Inc.
3by400.com
Websites that Work, Marketing that Matters

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
4 years 6 months ago #319087

Hi,

I don't see why the data in the user session would be lost after the creation of the order and only for logged in users.
The user session is not reset and we don't touch session parameters we're not aware of in the HikaShop code.
I would recommend to try to add calls to hikashop_writeToLog($var) in a onBeforeOrderCreate function of your plugin so that you can check that the variable is there before the order creation by checking the HikaShop payment log file (setting in the Hikashop configuration where hikashop_writeToLog will dump your $var). And also add it at the beginning of your onAfterOrderCreate function.

Please Log in or Create an account to join the conversation.

  • Posts: 195
  • Thank you received: 13
  • Hikashop Business
4 years 6 months ago #319181

I am extensively logging information in the various plugin functions / methods. When I save things in user state variables within the onPaymentNotification method I can read back from the user state and get what was written to it. But after that I get nothing from the user state in. the class constructor or other functions (on other triggers). I have also verified that the session id is the same when read inside the onPaymentNotification method and all other methods.

All I can conclude at this point is that either the user state / session is being cleared after the onPaymentNotification method by something other than my code, or there is an instance situation where the variables I set in the user state / session are not in the same scope as those in other methods.

Perhaps the solution would be to drop using the onPaymentNotification in favor of using the Joomla com_ajax capability.

Any. thoughts or ideas would be appreciated.
Thanks, Paul


3by400, Inc.
3by400.com
Websites that Work, Marketing that Matters

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
4 years 6 months ago #319183

Hi,

Well, without looking at the code and debugging it myself I can't say more on the issue that what you and I already said.

Regarding doing it another way, If you add your parameters in hidden input fields with the correct name, you can have them saved in the session by HikaShop for you.
For example, if you add in the custom_html attribute of your $method a hidden field with the name checkout[payment][custom][XXX][YYY] (where XXX is the id of the payment method and YYY the name of your variable) you can then fill it in the javascript, and then, in onBeforeOrderCreate you can us such code to retrieve the data:

$app = JFactory::getApplication();
$checkout_custom = $app->getUserState(HIKASHOP_COMPONENT.'.checkout_custom', null);
if(!empty($checkout_custom))
	$checkout_custom = json_decode(base64_decode($checkout_custom), true);
echo $checkout_custom[(int)$order->order_payment_id]['YYY'];
That's the mechanism several payment plugins use when they have their own credit card form on the checkout and want to pass data from the payment gateway to the payment plugin. So I'm sure this works.
I actually already talked to you about that in an email conversation and provided an example with the authorize.js plugin (which uses that exact method).
So maybe you didn't get the email and it went to your spam folder or something ?

Please Log in or Create an account to join the conversation.

  • Posts: 195
  • Thank you received: 13
  • Hikashop Business
4 years 6 months ago #319352

Nicolas, We very much appreciate your suggestions. Yes, we did get the previous one, but had not followed up with that, but will now. I've downloaded the plugin you referenced and am reviewing how that works.

Is checkPaymentDisplay() a newer HikaShop function? It is not listed in the available documentation. But it is a public function in that plugin. If it is basic to HikaShop now, at what point is that event triggered?

Thanks, Paul


3by400, Inc.
3by400.com
Websites that Work, Marketing that Matters

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
4 years 6 months ago #319379

Hi,

Yes, it's a relatively new function.
It's basically the same as the onPaymentDisplay function but with less code to add as it's only called for your payment plugin while onPaymentDisplay is called upon all the plugins implementing it.

Please Log in or Create an account to join the conversation.

  • Posts: 195
  • Thank you received: 13
  • Hikashop Business
4 years 6 months ago #319441

The checkPaymentDisplay event is not firing under any circumstances for me. Are there any specific steps I need to take to set up for that? Does it require native checkout? (I am going back and forth from legacy to native, so maybe I've just missed it.)

So far I have been able to successfully use the custom_html and related capabilities you've mentioned to get data from hidden fields back to the onBeforeOrderCreate method.

Also, are the custom_html and checkout_custom capabilities limited to native checkout?

Thanks, Paul


3by400, Inc.
3by400.com
Websites that Work, Marketing that Matters
Last edit: 4 years 6 months ago by 3by400.

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
4 years 6 months ago #319445

Hi,

If you still have the onPaymentDisplay function in your plugin, and that you don't call parent::onPaymentDisplay in your function, then checkPaymentDisplay won't be called as it's called from the onPaymentDisplay function of the class hikashopPlugin your plugin is supposed to extend from.

The custom_html will be displayed by the legacy checkout. However, there is no mechanism to get the data from the POST and store it in the session so that checkout_custom is available later on. It's up to you to get the data from the POST in the onPaymentSave function of your plugin:

function onPaymentSave(&$cart, &$rates, &$payment_id) {
 $result = parent::onPaymentSave($cart, $rates, $payment_id);
 $config = hikashop_config();
 if($config->get('checkout_legacy')) {
  // get data from the POST and store it in the session
 }
 return $result;
}

Also, there is no javascript mechanism to plug yourself before the submit of the checkout page with the registerAjax function like there is with the new checkout. So it's up to you to add an event listener on the next button to run your javascript.

The Authorize.js plugin is actually not compatible with the legacy checkout.

Last edit: 4 years 6 months ago by nicolas.

Please Log in or Create an account to join the conversation.

  • Posts: 195
  • Thank you received: 13
  • Hikashop Business
4 years 5 months ago #320678

Nicolas (or Jerome),
Using the authorizejs plugin as a reference I have implemented the 'custom_html' methodology. My form for gathering the user's payment information is loading properly (and with an automatically included Submit button). I've added the necessary hidden fields. I can submit a payment, get the results needed (a token or nonce) from Braintree and am properly setting the hidden fields.

I seem to not be doing something right. After clicking the (automatically added) Submit button within the payment method the checkPaymentDisplay function is triggered, and I'm getting the array of hidden fields, but not with the values from Braintree. It would seem the Submit causes an immediate sending of the hidden field and related form values possibly before they are set after waiting on the Braintree response. It may be that the API call to Braintree is asynchronous and thus the Submit is not waiting on that to complete.

Does the w.checkout.submitPayment(step, pos) need to be included within my JS event handling as it is in the authorizejs plugin? Or is that specific to what the authorizejs is doing?

Nicolas, Your suggestion from months ago to use the window.Oby.registerAjax code is not firing at all in my JS. It is the window.Oby.registerAjax("custompayment.submit", ...) from the authorizejs.js that IS firing for me. Am I missing something?

Also, not sure that I need it, but what causes the window.Oby.registerAjax("custompayment.needsubmit", ...) to fire? I'm not seeing that firing at all either.

Thanks, Paul


3by400, Inc.
3by400.com
Websites that Work, Marketing that Matters

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
4 years 5 months ago #320709

Hi,

Yes, the custompayment.needsubmit and the custompayment.submit events are what is used by the authorizejs plugin to get the data from the credit card form, sent the information to Authorize.net, and cancel the submit. And while it sends the information to authorize, it aslo setup a callback with the Accept.dispatchData function so that after the token is retrieved from authorize.net, it can call window.checkout.submitPayment to submit the form again with the token and not the credit card data (for PCI DSS compliance)

The custompayment.needsubmit event is called by the code in checkout / show_block_payment.php:

window.Oby.registerAjax('checkoutFormSubmit', function(params){
	var needSubmit = window.Oby.fireAjax('custompayment.needsubmit', {'step': <?php echo (int)$this->step; ?>, 'payment_id': window.checkout.selectedPayment});
	if(needSubmit === false || needSubmit.length == 0)
		return;
	window.checkout.submitCustomPayment(needSubmit[0],window.checkout.selectedPayment,<?php echo $this->step; ?>,<?php echo $this->module_position; ?>);
	return true;
});
This allows the payment plugin's js code to stop the submit of the whole page when the user clicks on the "next" / "finish" button.

If the js of the plugin stops the submit and sends back its name, you can see that this will call submitCustomPayment.
This function is also defined in checkout / show_block_payment:
window.checkout.submitCustomPayment = function(name, id, step, pos) {
	var ret = window.Oby.fireAjax('custompayment.submit', {method: name, payment_id: id, step: step, pos: pos});
	if(ret === false || ret.length == 0) return window.checkout.submitBlock('payment', step, pos);
	return false;
};
As you can see, it will trigger the second event, custompayment.submit.

That way, whether the user clicks on the submit button of the credit card form, or the "next" / "finish" button of the whole checkout page, you're able to catch it, do your stuff and then call the submit yourself again once you hear back from the payment gateway.

Please Log in or Create an account to join the conversation.

  • Posts: 195
  • Thank you received: 13
  • Hikashop Business
4 years 4 months ago #321908

Nicolas,
I've made progress on our payment plugin. Most questions though.

1) The authorizejs plugin does not appear to use the onPaymentDisplay function to set AuthorizeJS as a usable method. Is there a newer methodology to set the payment method as usable? When checkout first loads my payment method does not show unless I refresh the page (could be I have an initialization issue in JS).

2) There does not appear to be any methodology in authorizejs to handle switching from one payment method to another (e.g. PayPal to mine). I can do that in JS by registering an onClick event. But why doesn't authorizejs have something similar? Is there something about using the in-page (custom_html) methodology that replaces using an onClick event on the payment method's radio button? Perhaps I'm missing something in authorizejs that recognizes and does not initialize if the authorizejs method is not selected?

Thanks, Paul


3by400, Inc.
3by400.com
Websites that Work, Marketing that Matters

Please Log in or Create an account to join the conversation.

  • Posts: 26158
  • Thank you received: 4028
  • MODERATOR
4 years 4 months ago #321917

Hello,

In the plugin, the function "getCustomHtmlForm" generate the HTML form which is displayed during the checkout process.
It also add some javascript to initialize the AuthorizeJS lib, based on the "window.hikashop.ready" and the inclusion of the JS files.
When the method is not selected, the form is just hidden but still there ; so the JS should initialize the data even if it's not the selected method, thus if the customer change the method, the payment form will be visible (and already set-up).

Regards,


Jerome - Obsidev.com
HikaMarket & HikaSerial developer / HikaShop core dev team.

Also helping the HikaShop support team when having some time or couldn't sleep.
By the way, do not send me private message, use the "contact us" form instead.

Please Log in or Create an account to join the conversation.

  • Posts: 195
  • Thank you received: 13
  • Hikashop Business
4 years 4 months ago #321964

Thanks Jerome. I have implemented the getCustomHtmlForm customized for my payment method and that is working.

My first issue is that the first checkout page opens, my payment method is not showing (unless I use the onPaymentDisplay function to set my method as usable). But the separate PayPal method that I have enabled is displayed as soon as the checkout page loads.

If I click the 'Next' button after selecting a guest user, then my payment method is displayed. Since the payment methods are displayed on the same checkout page (single page checkout basically), then the user may not click on the "Next" button, but instead just scroll down. And in that case they would see only PayPal as a payment method. Refreshing the page also does show my payment method. My JS is not currently hiding anything from within the getCustomHtmlForm code (either as HTML or via JS).

I've looked through the authorizejs.php and authorizejs.js code numerous times and perhaps I've missed it. I cannot find any code that sets display:none or visibility:hidden or vice-versa if another payment method is selected. This would seem needed in the JS as a registered onChange event when any payment method radio button is clicked. There is a lot of library code that is bundled with the authorizejs plugin so maybe it is elsewhere and I just haven't found it.

And, Jerome, I really appreciate your allowing the authorizejs code to be viewed as an example. That helps a lot since there seems to not yet be documentation on how the HikaShop custom_html methodology works for payment methods. Thanks for all your help. Paul


3by400, Inc.
3by400.com
Websites that Work, Marketing that Matters

Please Log in or Create an account to join the conversation.

  • Posts: 195
  • Thank you received: 13
  • Hikashop Business
4 years 4 months ago #321969

Nicolas or Jerome,
I'm seeing now that switching payment methods does handle hiding and showing the custom_html content of the payment method. So no further code is needed which explains why the authorizejs.js code does NOT include it.

I'm still not seeing a solution to the payment method being shown (not just the custom_html, but the entire payment method) when the checkout page first loads. I have to click the 'Next' button after entering the 'guest' information in order for my payment method to be displayed.

Thanks for all your help and insight so far.
Paul


3by400, Inc.
3by400.com
Websites that Work, Marketing that Matters

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
4 years 4 months ago #321966

Hi,

1. You need to set your method as usable in onPaymentDisplay. All payment plugins do that. And if that's not the case, it's probably because your plugin's class doesn't extend from hikashopPaymentPlugin which has a generic onPaymentDisplay function to do it for you.

2. It seems that what you're saying is that the payment method is not available before the user logs in or fills in the guest form. I suppose that either you have some kind of restriction to the payment method or some check in onPaymentDisplay to not add the payment method in some cases (display it only for some countries, or something like that).
Now, the payment method selector will hide the HTML from onPaymentDisplay when another payment method is selected and will display it when your payment method is selected. That is handled automatically by the system.

Please Log in or Create an account to join the conversation.

Time to create page: 0.073 seconds
Powered by Kunena Forum