Prevent Observer method called twice - events

i am using Magento 1.5.1.0 and the "mPAY24 Payment Gateway" Extension.
I have an Observer class for the event "sales_order_payment_pay" sending notification
E-Mails to the manufacturer of the items.
This solution has some strange behavour:
When logged as a registered user - the observer method is called as expected
When checking out as a guest user, the "sales_order_payment_pay" Event is
fired when the "payment transaction" (Mastercard, VISA) was successful" and
a second time after clicking the "return Button" to get back to the Magento Shop.
because this behavior the E-Mail is sent twice.
Is there a way to prevent the observer method from beeing executed twice?
Kind Regards,
Bertie

No. As a client (vs. system) developer, you don't get to decide when an event fires.
Here's some general jumping off points for solving this problem:
Instead, you need to change the behavior of your observer method. Instead of blindly firing off an email in the observer method, you'll need to examine the state of the system and/or the objects in the $observer->getData() array, and determine if the event was fired after a payment transaction, or if it was fired after clicking the "clicking the return Button".
If it's the former, send your email as expected. If it's the later, just return from the observer method and/or skip the email with a conditional.
If this isn't your own observer method that's the problem (it's a core observer or a an observer that's part of the module), use a class rewrite to replace the observer method with your own. If you detect the correct state, call the return parent::observerMethodName, if it's the "clicking the return Button" state, just return null and skip calling the parent.
If the observer was setup with a hard-coded class name (not a class alias), then you'll need to use a code pool override to change the behavior of your method.

Related

How to create custom error when convert cart to order in Shopware6?

I'm trying to make plugin for Shopware6 that adds choice of period of delivery (for example, user can chose product to be delivered March 07 9:00-11:00). Problem is that can't be more than 15 orders in each period. So if used proceeds to make Order from Cart, and if period he chose has more than 15 orders, I must somehow invalidate form and tell to user to chose another period.
So I must:
somehow subscribe to the event "user makes an order from card",
check if chosen period is correct,
if not, tell it to user and don't create an order.
Is there any way to do it? In Symfony, I would just add validation to entity PeriodOfDelivery. But in Shopware I cannot do it because controller is in Shopware Core and I cannot edit it.
You can subscribe on CartConvertedEvent::class event. You can get original and converted cart data from the event.
In subscriber, you can do any check that you need and throw a specific exception.
You can implement your own exception class. use \Shopware\Core\Checkout\Order\Exception\DeliveryWithoutAddressException as template. In your own exception, you can specify own error code and message.

Magento event always dispatched when order is placed successfully?

I'm finding Magento event dispatching is quite a frustrating area. I suppose a lot of that frustration is, as usual, down to the lack of documentation.
I would like my code to be triggered at various stages as a visitor traverses through a site. So I put some debug in Mage::dispatchEvent, and I walked through the site to see what events are fired at each stage. There are a lot!
Two places I am interested in are:
when the visitor had selected a billing address and moved on to the next stage of the checkout process.
when a user successfully places an order
For the billing address one, the events that I saw being fired that look relevant are:
controller_action_predispatch_checkout_onepage_saveBilling
controller_action_postdispatch_checkout_onepage_saveBilling
The 'pre' and 'post' suggested to me that there is actually a 'checkout_onepage_saveBilling' event, but there isn't, so my first question is why the 'pre' and 'post'?
For the successful order, the events that look good are:
checkout_onepage_controller_success_action
checkout_multishipping_controller_success_action
My second question is will these events be fired for all payment methods? For example, if using Google Checkout, or PayPal (standard redirect), will the event fire, and at what point? When returning to the site from PayPal? If so that would beg the question what if the user does not return after completing payment.
Thanks for any help.
Sadly, I've noticed that checkout_submit_all_after does not fire for Paypal Express orders.
Short of modifying the Paypal models to add this (or perhaps hooking into events they may fire - I haven't checked on that yet), I think checkout_onepage_controller_success_action may really be the only event you can absolutely count on for every type of order.
The predispatch event will fire before the action has been called, the postdispatch event will fire after the action has been completed. So if you need to know what the result of the action was, you should use the postdispatch event.
For successful orders, checkout the checkout_submit_all_after event.
If you haven't seen it, https://www.nicksays.co.uk/magento-events-cheat-sheet-1-9/, is a handy reference for Magento events.

Why use event listeners over function calls?

I've been studying event listeners lately and I think I've finally gotten them down. Basically, they are functions that are called on another object's method. My question is, why create an event listener when calling the function will work just fine?
Example, I want to call player.display_health(), and when this is fired, the method player.get_health() should be fired and stored so that display_health() has access to it. Why should I use an event listener over simply calling the function? Even if display_health() were in another object, this still doesn't appear to be a problem to me.
If you have another example that fits the usage better, please let me know. Perhaps particular languages don't benefit from it as much? (Javascript, PHP, ASP?)
You might not always be in control of the code that's doing the calling. Or even if you are, you don't want to introduce dependencies into that code. In cases like that, it's better for the code to fire an event and allow the code you do control, or the code that should have the dependency, to listen for the event and act accordingly.
For example, perhaps you're creating a library that will be used by other people. They don't have the source code or in some way can't/shouldn't be able to modify it (or shouldn't have to). Your documentation states that specific events are raised under specific circumstances. They can then, in turn, respond to those events.
Or perhaps you have some domain libraries in your enterprise. You do control them and can modify them, but architecturally they're generally considered to be working as they currently are coded and shouldn't be changed. (Don't want to incur a round of QA to re-validate the updated code, the code belongs to another department and they don't want you to change it, etc.) And you're in the position where you want that code to be able to do different things in different circumstances/environments. If that code raises and event where relevant, you can hook your code into it (and/or swap out accordingly) without having to mess with that code.
Just a couple quick examples, I'm sure others have more.
My question is, why create an event listener when calling the function will work just fine?
What if you don't know what function you want to call?
Take the classic example, a Button that the user can click on. Whoever writes the library has no idea what function you want called when the button is clicked. It would also be pretty prohibitive if every Button could only call the same function when it is clicked.
So instead, you can attach an event handler to the event. Then when the event is triggered, the Button can do what it needs to, without having to know at compile-time exactly what function it's supposed to be calling.
In Brief, you can write the code without event listener, but using event listener help other to use the same code as library.
Even with the detailed answers above, I was still having trouble understanding what the actual difference was between using a controller / functions OR an event listener.
One of the things that has been left out in all of these answers is that the use of Events and Event Listeners comes in handy when you do not want to couple your code so closely. Each function, class, etc, should have singleness of purpose.
So say you are getting hit with an API request from an outsider. In my case, my exact problem understanding this concept was when I am receiving API calls from Stripe Webhooks.
The purpose of Stripe Webhooks is: say a customer spends $10,000 on your website. Your standard procedure is to Auth and Capture. Update DB to reflect their new membership status. In a perfect world, and in our company's case, 999/1000 times, this goes perfectly. Either their card is declined on the spot, or the payment goes through. In both cases, we send them an email letting them know.
But what about the 1/1000 time when the user pays and Stripe returns a Card Failure error (which can be a number of different things)? In our case, we email them and tell them the billing has failed. The problem we've encountered is that some BANKS are investigating large charges, which comes back as an Error, but then a few minutes later the bank authorizes the charges and the payment is captured.
So what is there to do? Enter Stripe Webhooks. Stripe Webhooks will hit an API endpoint if something like this occurs. Actually, Stripe Webhooks can hit your API any and every time a payment isn't instantly Authed, Captured, or if the customer asks for a refund.
This is where an Event Listener comes in handy. Stripe shoots over a POST with the customer info, as well as the Webhook type. We will now process that, update the database, and shoot them a success email.
But why not just use a standard route and controller?
The reason we don't just use a standard route and controller is because we would either need to modify the already defined functions, classes, etc, or create a new series of classes that are coupled together, such as -> Stripe API Calls Received, Update DB, Send Email. Instead of coupling these closely together, we use an Event Listener to first accept the API Call, then hit each of those Classes, Functions, etc., leaving everything uncoupled.
I looked everywhere, and I think the Laravel documentation explains it best. I finally understood when given a concrete example, and what the purpose of an Event Listener is:
Events serve as a great way to decouple various aspects of your application, since a single event can have multiple listeners that do not depend on each other. For example, you may wish to send a Slack notification to your user each time an order has shipped. Instead of coupling your order processing code to your Slack notification code, you can raise an OrderShipped event, which a listener can receive and transform into a Slack notification.
https://laravel.com/docs/5.6/events
I think the main reason for events vs function calls is that events are 'listened to' while calls are 'made'. So a function call is always made to another object whereas listeners 'choose' to listen for an event to be broadcast from your object.
The observer pattern is a good study for this capability. Here is a brief node.js example which illustrates the concept:
var events = require('events');
var Person = function(pname) {
var name = pname;
};
var james = new Person('james');
var mary = new Person('mary');
var loudmouth = new Person('blabberer');
loudmouth.mouth = new events.EventEmitter();
//jame's observer.
james.read_lips = function(msg){
console.log("james found out: " + msg);
};
//james adds his event to the emitter's event listener.
james.enter_elevator = function(){
console.log('james is in the elevator');
//NOTE: james adds HIMSELF as a listener for the events that may
//transpire while he is in the elevator.
loudmouth.mouth.on('elevator gossip', james.read_lips)
};
//james removes his event from the emitter when he leaves the elevator.
james.leave_elevator = function(){
// read lips is how james responds to the event.
loudmouth.mouth.removeListener('elevator gossip', james.read_lips);
console.log('james has left the elevator');
};
//mary's observer
mary.overhear = function(msg){
console.log("mary heard: " + msg);
};
//mary adds her observer event to the emitter's event listeners
mary.enter_elevator = function(){
// overhear is how mary responds to the event.
console.log('mary is in the elevator');
//NOTE: now mary adds HERSELF to the listeners in the elevator and
//she observes using a different method than james which suits her.
loudmouth.mouth.on('elevator gossip', mary.overhear);
};
loudmouth.speaks = function(what_is_said){
console.log('loudmouth: ' + what_is_said);
this.mouth.emit('elevator gossip', what_is_said);
};
james.enter_elevator();
mary.enter_elevator();
loudmouth.speaks('boss is having an affair');
james.leave_elevator();
loudmouth.speaks('just kidding');
console.log('james did not hear the last line because he was not listening anymore =)');
so in this 'story' the actors choose to listen or when to not listen for events from a third party. I hope this helps.

Magento - Adminhtml - Get id of order just created

I want to do some post processing on an order, made using admin panel.
I have subscribed to the controller_action_postdispatch_adminhtml_sales_order_create_save event, and the correct function of this observer is being invoked.
How can I get the id of the order just saved in the saveAction in my function.
Mage_Adminhtml_Model_Sales_Order doesn't appear to save the order in the session anywhere, so this may be tough with the event you've chosen. In fact, the controller action you specified calls _getSession()->clear() to lose all the data from the session.
I would suggest finding a different event to use.

Synchronizing Event Calls from Threads to Event Handlers on Windows Forms

I have an object that is updated from a polling loop on a thread. This object fires particular events when data changes, etc.
I'm trying to use this object in conjunction with a windows form, where I create event handlers on the form to update the UI. Of course, this causes cross-thread operation exceptions if I try to manipulate the UI directly in these handlers.
I can get it to work by going through the standard procedure of checking InvokeRequired, using a delegate, blah blah blah. But I want to publish this object as a library, and I don't want end-users to have to worry about all that.
I want my object to somehow take care of synchronizing those event callbacks with the form so that end-users can manipulate the UI elements in those handlers worry-free.
Is there a way to do this??
If your object is always related to a single form, there is a simple trick indeed. The important fact here is, that you instanciate your object from the thread you like to affect the form later.
The trick is to instanciate a simple Control (new Control()) in your object in the constructor. When you perform logic on your form, use the Invoke/BeginInvoke methods on this simple control, to dispatch the action to the correct calling thread. So you have the dispatching logic directly in your object and there is no need for other users of your object to take care about this.

Resources