Hi i have 2 payment method available in my magento2 store . One is cash on delivery and other is custom payment gateway . I install custom payment gateway extension and it is working fine .
Now i have some conditions if that condition is ok then only i need to make active that custom payment gateway extension .
My products have a product attribute called 'otherthancod' . If
'otherthancod' is active then only show the custom
payment gateway in checkout page. For that i write the following code .
$items = $cart->getItems();
$flag = 0;
$count=0;
foreach($items as $item){
$attribute1 = $item->getProduct()->getData('otherthancod');
if($attribute1){
$flag++;
$count++;
}else{
$flag--;
}
}
if($flag == $count){
$checkResult = $observer->getEvent()->getResult();
$checkResult->setData('is_available', true);
}else{
$checkResult = $observer->getEvent()->getResult();
$checkResult->setData('is_available', false);
}
Now i want to know where i need to put this code ? I don't want to create another extension for that .
Please help.
In my custom payment extension i have seen the following page
app/code/custompaymentgaetway/custom/Gateway/Config/config.php
class Config extends \Magento\Payment\Gateway\Config\Config{
}
can i add if condition before this class ? I think this class is activating payment gateway .
I can see that in frontend template of my payment gateway is
\view\frontend\web\template\custompaymentgaetway.html. Actually i want to hide this frontend once the condition is false .
Don't hesitate to create your own module in app/code/YourNamespace.
Basically you just need a registration.php file and an etc/module.xml:
https://devdocs.magento.com/videos/fundamentals/create-a-new-module/
Also see the following example showing how to declare the Observer for this event:
https://magento.stackexchange.com/a/188367/27460
You should not afraid of setup:upgrade command as it is OOTB Magento command it should work fine, and If something break then please fix it might be some permission issue on server side
First you will need to create events.xml file under app/code/Company/Module/etc/. Then write “payment_method_is_active” event in it. This is the event that hits on the checkout page for payment method availability.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="payment_method_is_active">
<observer name="custom_payment" instance="Company\Module\Observer\PaymentMethodAvailable" />
</event>
</config>
Now create PaymentMethodAvailable.php under Company/Module/Observer/ and write the following code in the file. I am disabling the check money order payment method, you can change the payment method code according to your need.
<?php
namespace Company\Module\Observer;
use Magento\Framework\Event\ObserverInterface;
class PaymentMethodAvailable implements ObserverInterface
{
/**
* payment_method_is_active event handler.
*
* #param \Magento\Framework\Event\Observer $observer
*/
public function execute(\Magento\Framework\Event\Observer $observer)
{
// you can replace "checkmo" with your required payment method code
if($observer->getEvent()->getMethodInstance()->getCode()=="checkmo"){
$checkResult = $observer->getEvent()->getResult();
$checkResult->setData('is_available', false); //this is disabling the payment method at checkout page
}
}
}
Now the payment method Check Money Order is disabled from checkout page .
For reference please check this link
Related
I am working on API based Payment gateway in magento, When user directly pay from credit card, I am doing my all process by calling api specific function in capture method of payment gateway.
When I will enable 3D secure option for payment gateway I need to redirect user to 3rdparty for verification for that I am using getOrderPlaceRedirectUrl with condition.
With Condition I ma also saving order with pending status but Magento generate the invoice and mark as paid and change status to processing. that I need to do once get successful authentication from 3rdparty.
for updating order status using following code:
$order->setState( Mage_Sales_Model_Order::STATE_NEW, true );
$order->save();
If anyone can help how can I control to not generate invoice in capture method will be very appreciated.
If you use capture() in your payment method, and your capture() method returns without throwing an exception, then Magento assumes that the capture is done, "the money is in your pocket", so it makes the invoice. This is not good if you use a 3rd party payment gateway.
You can do the following: set your *payment_action* to order in your config.xml
<config>
<default>
<payment>
<yourPaymentCode>
<order_status>pending_payment</order_status>
<payment_action>order</payment_action>
...
In your payment method set the attributes and implement the order() method.
Snd set getOrderPlaceRedirectUrl, but you already did that.
class Your_Module_Model_PaymentMethod
extends Mage_Payment_Model_Method_Abstract
{
// set these attributes
protected $_code = 'yourPaymentCode';
protected $_isGateway = true;
protected $_canCapture = false;
protected $_canAuthorize = false;
protected $_canOrder = true;
public function order(Varien_Object $payment, $amount)
{
// initialize your gateway transaction as needed
// $gateway is just an imaginary example of course
$gateway->init( $amount,
$payment->getOrder()->getId(),
$returnUrl,
...);
if($gateway->isSuccess()) {
// save transaction id
$payment->setTransactionId($gateway->getTransactionId());
} else {
// this message will be shown to the customer
Mage::throwException($gateway->getErrorMessage());
}
return $this;
}
And somehow the gateway has to respond. In my case they redirect the customer to $responseUrl given in init(), but they warn that it is possible that the user's browser crashes after payment but before they can be redirected to our store: In that case they call the URL in the background, so handling that URL cannot rely on session data. I made a controller for this:
public function gatewayResponseAction()
{
// again the imaginary example $gateway
$order = Mage::getModel('sales/order')->load( $gateway->getOrderId() );
$payment = $order->getPayment();
$transaction = $payment->getTransaction( $gateway->getTransactionId() );
if ($gateway->isSuccess())
{
$payment->registerCaptureNotification( $gateway->getAmount() );
$payment->save();
$order->save();
$this->_redirect('checkout/onepage/success');
}
else
{
Mage::getSingleton('core/session')
->addError($gateway->getErrorMessage() );
// set quote active again, and cancel order
// so the user can make a new order
$quote = Mage::getModel('sales/quote')->load( $order->getQuoteId() );
$quote->setIsActive( true )->save();
$order->cancel()->save();
$this->_redirect('checkout/onepage');
}
}
Try setting the state to pending payment, something like the following;
$order->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT,
'pending_payment',
'3D Secure Auth Now Taking Place')->save();
P.S. The PayPal module that comes with Magento does exactly what you are trying to do, so take a look at PayPal Standard model and controller for some pointers.
The thing is, I want to send them manually via the API because in my country a invoice is a legal-bound order.
Is there a way to do that?
Thanks for your help!
Go to System->Configuration->Sales Emails and disable "Invoice".
I don't think the accepted answer is the best possible way to handle the problem. If you disable the automatic transactional emails completely from the backend, you also can't trigger them manually or use them in your custom module anymore. That means you have to create every transactional email you disabled from scratch if you need to send it at another point as magento standart, which also is a considerable maintenance effort in the aftermath.
The solution I came up with is to programmatically disable sending the email on invoice creation and leverage the default sender classes in a custom observer event. In our case we wanted to send the invoice email when shipment is created.
You do that by overriding \Magento\Sales\Model\InvoiceOrder. Locate the line
$this->notifierInterface->notify($order, $invoice, $comment);
And remove it.
If you want to trigger the email, you can still do that from anywhere you want using the standard "send" function from the InvoiceSender. In our case, we trigger the email from observer like this:
<?php
namespace Vendor\Module\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Email\Sender\InvoiceSender;
class SendInvoiceWithShipment implements ObserverInterface
{
protected $_invoiceSender;
public function __construct(
InvoiceSender $invoiceSender
) {
$this->_invoiceSender = $invoiceSender;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
$order = $observer->getShipment()->getOrder();
$invoices = $order->getInvoiceCollection();
foreach ($invoices as $invoice) {
// this is where the magic happens
$this->_invoiceSender->send($invoice);
}
}
}
Observer is triggered by event sales_order_shipment_save_after
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name='sales_order_shipment_save_after'>
<observer name='SendInvoiceWithShipment' instance='Vendor\Module\Observer\SendInvoiceWithShipment'
/>
</event>
</config>
You can do this for every transactional email.
I have a special case where users have to sign up for an account via the account sign up page (e.g. /customer/account/create/). Upon completion, and in the event that they have a product in the cart, I need to redirect them back to the checkout screen.
I currently have an observer in place that listens to the customer_register_success event. The observer upgrades the users account to a membership group via this code:
class Hatclub_MembershipHandler_Model_Observer {
// members group id
const GROUP_ID = 4;
// called when a customer registers for the site
public function registrationSuccess(Varien_Event_Observer $observer) {
// extract customer data from event
$customer = $observer->getCustomer();
// a cookie should have been set with the membership id
if (isset($_COOKIE['membership_account_id'])) {
$customer
->setGroupId(self::GROUP_ID)
->setRmsId($_COOKIE['membership_account_id']);
}
return $this;
}
}
Is there another event that I can listen to that is better suited for what I want to do? I have a redirect_to cookie that is available as well if that helps.
After much trial and error, I came across a solution. Since I'm already using the customer_register_success event and modifying user data with my observer, I had to use another event called customer_save_after and it worked like a charm.
config.xml event block
<customer_save_after>
<observers>
<customer_session_observer>
<class>hatclub_membership_handler/observer</class>
<method>customerSave</method>
<type>singleton</type>
</customer_session_observer>
</observers>
</customer_save_after>
observer.php method
public function customerSave() {
// set redirect url from cookie, default to null
$redirect_url = (isset($_COOKIE['redirect_url']))
? isset($_COOKIE['redirect_url']) : null;
// if a redirect url was specified
if (isset($redirect_url)) {
// remove cookie to prevent infinite loop
unset($_COOKIE['redirect_url']);
// redirect to provided url
Mage::app()->getResponse()
->setHeader('Location', $redirect_url)
->sendHeaders();
}
}
The redirect within an observer was a bit of a struggle, but I managed to accomplish it using
Mage::app()->getResponse()
->setHeader('Location', $redirect_url)
->sendHeaders();
Suggestions and criticism welcome.
Is there a way to catch the event when the customer verifies it's account? I need this feature to enable user's access to other integrated subsystem
Since confirmAction() doesnt seem to fire any events in
/app/code/core/Mage/Customer/controllers/AccountController.php
You could do either
Overriding Frontend Core Controllers to create you own event using Mage::dispatchEvent() or add code directly to confirmAction in AccountController.php
Use #Pavel Novitsky answer but you may need to check that you are on the confirm account controller or check for the changing of email verification flag, because this event will trigger every time a customer information is change/updated
eg
public function myObserver(Varien_Event_Observer $observer)
{
if(Mage::app()->getRequest()->getControllerName() == '....account_confirm'){
$customer = $observer->getCustomer();
....
}
}
Every model has standard load_before, load_after, save_before, save_after, etc. events. Look at the Mage_Core_Model_Abstract to get the list of all predefined events.
For customers you can use customer_save_after event. In observer check original data vs new data:
public function myObserver(Varien_Event_Observer $observer)
{
$customer = $observer->getCustomer();
$orig_active_flag = $custoner->getOrigData('is_active');
$new_active_flag = $customer->getData('is_active');
// do something here …
return $this;
}
Even you can create your own event after customer vefication using below code.
Mage::dispatchEvent('Yuor_Unique_Event_Name', array());
Now using this event you can do anything you want.
I have an extremely simple module that allows a customer to "Purchase On Account". The module doesn't do anything special really (it was simply modified from a Cash On Delivery module.)
The problem is I only want to offer this payment method to logged in customers.
So far my module looks like this:
BuyOnAccount/
etc/
config.xml
system.xml
Model/
PaymentMethod.php
The content of PaymentMethod.php is:
class MyCompany_BuyOnAccount_Model_PaymentMethod extends Mage_Payment_Model_Method_Abstract
{
protected $_code = 'buyonaccount';
protected $_isInitializeNeeded = true;
protected $_canUseInternal = false;
protected $_canUseForMultishipping = false;
}
The config and system xml files contain the usual sort of thing (please let me know if you would like to see the code and i'll edit)
So bascically I need to disable the module if the user is not logged in (but obviously only for the current customer session!)
Any ideas?
Thanks
You can just add a method to your payment model called isAvailable(Mage_Sales_Model_Quote $quote) that returns a bool. For example, in your situation you could add something like:
public function isAvailable($quote = null) {
$isLoggedIn = Mage::helper('customer')->isLoggedIn();
return parent::isAvailable($quote) && $isLoggedIn;
}
The Mage_Payment_Model_Method_Free payment method that ships with Magento is an example of a payment method that employs this -- it'll only show if the basket total is zero.