Magento - Dynamically disable payment method based on criteria - magento

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.

Related

Magento: set canUseCheckout to false payment method

I want to disallow some payment methods while checkout onepagecontroller is in indexAction. I've tried like this:
$payments = Mage::getSingleton('payment/config')->getAllMethods();
foreach($payments as $payment)
{
$methodinstance = Mage::helper('payment')->getMethodInstance($payment->getCode());
$methodinstance-> // here i want to set the protected $_canUseCheckout of the specific method class... maybe with __set(var, value) ?
}
So is there a way to set the canUseCheckout of each method temporarily to false ? Maybe i don't have to use the vars.. maybe theres a function ?
I didn't find such in the Model_Abstract Class of payment methods...
you can disable any payment method. for disable payment method, go to payment method model which is you want disable and fine the protected $_canUseCheckout = true; please do false this variable and check it.

Mark order as pending in capture method in custom Payment Method

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.

Observe customer account verification event in Magento

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.

Add checkbox to Magento checkout?

I've been searching, trying, and failing alot here. What I want is to add a checkbox, on the Shipping page of Onepage checkout, the standard magento checkout.
I want to create a checkbox so that customers can check it if they want their products to be placed on their address without a signature.
I've been messing around with some old "Accept Terms" checkboxes, but with no luck.
I'm hoping that somebody might have had to make the same kind of customization.
What you can do is save the preference in the checkout/session via an observer. First, add the checkbox to the shipping section and give it the property of name=shipping[no_signature]. Then, create a new module and hook into the event controller_action_postdispatch_checkout_onepage_saveShipping and then use this code:
public function controller_action_postdispatch_checkout_onepage_saveShipping($observer)
{
$params = (Mage::app()->getRequest()->getParams()) ? Mage::app()->getRequest()->getParams() : array();
if (isset($params['shipping']['no_signature']) && $params['shipping']['no_signature']) {
Mage::getSingleton('checkout/session')->setNoSignature(true);
} else {
Mage::getSingleton('checkout/session')->setNoSignature(false);
}
return $this;
}
Then, when the order is about to be placed, hook into the event sales_order_place_before you can add a comment to the order like this:
public function sales_order_place_before($observer)
{
$order = $observer->getOrder();
if (Mage::getSingleton('checkout/session')->getNoSignature()) {
$order->setCustomerNote('No signature required.');
} else {
$order->setCustomerNote(null);
}
return $this;
}
When you go to Sales > Orders, you should see a comment on the order regarding if the customer requires a signature or not. This is under the assumption that no other module or custom code is injecting anything into the customer_note field on the order object.

Checking If Order is Being Edited By Admin?

My custom shipping module was failing because it couldn't get a sales quote when an order was being edited on the backend. This was the code I was using:
class Mymodule_Model_Mycarrier_Customrate
extends Mage_Shipping_Model_Carrier_Abstract
implements Mage_Shipping_Model_Carrier_Interface
{
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
$quote = Mage::getSingleton('checkout/type_onepage')->getQuote();
I need to get the current quote so I have access to the address information. I am making an API request that requires a street address.
Now if the order was being edited on the backend, this would obviously result in an error because the checkout singleton is no longer relevant. Instead I get the quote like this:
$quote = Mage::getSingleton('adminhtml/session_quote')->getQuote();
In my collectRates() method I need to determine which singleton to load. First I want to ask if this is the proper way of doing things, and also if my check for the backend is sufficient:
$quote = Mage::getSingleton('checkout/type_onepage')->getQuote();
// If admin is editing an order, find the quote by admin session.
if(Mage::getSingleton('admin/session')->isLoggedIn()){
$quote = Mage::getSingleton('adminhtml/session_quote')->getQuote();
}
I don't want this to potentially cause problems later. I also get the feeling that I may be using the collectRates() method wrong if I have to create a workaround like this.
The Mage_Shipping_Model_Rate_Request object already has access to the address via $request->getDestStreet(), etc...

Resources