Cancel Magento Orders With Expired Pre-Authorization - magento

I have some orders in my Magento site that are older than 30 days so the authorize.net pre-auth has expired. When I go to cancel the orders, it tries to submit the pre-auth void but it fails because the original transaction no longer exists. Is there any way to manual override this void procedure and simply cancel an order in this state?

An easy way to do these Cancels as one-offs when you need to is to:
1) Grab the Auth.net transaction ID from the Order in Magento. It should display this in the Comments History at the bottom of the order.
2) Search the sales_payment_transaction table > txn_id field for that transaction ID
3) Once you locate the record in mySQL (helpful if you have phpMyAdmin), then just NULL out the txn_id for that record.
4) Back in Magento admin, you can now Cancel the order since it knows not to try and go back to Auth.net to cancel it.
** Alternatively you can easily find the record by the Order ID in the URL and find it that way in the same table. For instance:
https://www.yourdomain.com/store/index.php/backend/sales_order/view/order_id/6957/key/4c16ff2bfed4b496670be4747sdjhdfd6/
It's order_id: 6957 in the database.

Take a look #
/app/code/core/Mage/Paygate/Model/Authorizenet.php
Turn on debugging for your payment module to see the result of $result->getResponseCode() for an expired transaction. Once you figure out what the result (code/error code) are, you could create a new 'case' that mimic case self::RESPONSE_CODE_APPROVED:
Also take a look # $this->_isTransactionExpired($realAuthTransactionId) to see why it isn't catching your expired transaction.
protected function _voidCardTransaction($payment, $card)
{
$authTransactionId = $card->getLastTransId();
$authTransaction = $payment->getTransaction($authTransactionId);
$realAuthTransactionId = $authTransaction->getAdditionalInformation($this->_realTransactionIdKey);
$payment->setAnetTransType(self::REQUEST_TYPE_VOID);
$payment->setXTransId($realAuthTransactionId);
$request= $this->_buildRequest($payment);
$result = $this->_postRequest($request);
switch ($result->getResponseCode()) {
case self::RESPONSE_CODE_APPROVED:
if ($result->getResponseReasonCode() == self::RESPONSE_REASON_CODE_APPROVED) {
$voidTransactionId = $result->getTransactionId() . '-void';
$card->setLastTransId($voidTransactionId);
return $this->_addTransaction(
$payment,
$voidTransactionId,
Mage_Sales_Model_Order_Payment_Transaction::TYPE_VOID,
array(
'is_transaction_closed' => 1,
'should_close_parent_transaction' => 1,
'parent_transaction_id' => $authTransactionId
),
array($this->_realTransactionIdKey => $result->getTransactionId()),
Mage::helper('paygate')->getTransactionMessage(
$payment, self::REQUEST_TYPE_VOID, $result->getTransactionId(), $card
)
);
}
$exceptionMessage = $this->_wrapGatewayError($result->getResponseReasonText());
break;
case self::RESPONSE_CODE_DECLINED:
case self::RESPONSE_CODE_ERROR:
if ($result->getResponseReasonCode() == self::RESPONSE_REASON_CODE_NOT_FOUND
&& $this->_isTransactionExpired($realAuthTransactionId)
) {
.....
public function canVoid(Varien_Object $payment)
{
if ($this->_isGatewayActionsLocked($this->getInfoInstance())) {
return false;
}
return $this->_isPreauthorizeCapture($this->getInfoInstance());
}

For anyone still looking for how to cancel an order with an expired authorization.
Update the database record for sales_payment_transaction by changing the is_cloased value for the transaction to 1(Yes).
You will need the order id and the transaction id which you can both get from the url when viewing the transaction in your browser.
https//magento.com/admin/sales_transactions/view/txn_id/11111/order_id/55555/
$collection = Mage::getModel('sales/order_payment_transaction')
->getCollection()
->addAttributeToFilter('order_id', '11111')
->addAttributeToFilter('txn_id', '55555');
foreach ($collection as $col) {
if ($col->getId()){
$col->setIsClosed(1)->save();
}
}
You can also update the value through phpMyAdmin by opening the sales_payment_transaction and looking the for the row with order_id and txn_id for your order.
Once the is_closed value is set to 1, you should now be able to cancel the order since it tells the system the authorization is closed and not to try to void the authorization which has already expired on authorize dot net

Related

symfony 3 time when log in and log out

I'm pretty much new in symfony 3, so how I could get time when user log in and log out.. I know i should create entity for time.. that entity would have id,userID startTime, endTime.. and user should have a connection(many to many, that lot of user could have lot of log in.. ) with this entity.... I'd like to store in database this information. I tried to search on google but I found nothing in common.
I'd like to activate time startTime when this button is pressed
Sign
in
and code in controller
#Route("/login", name="authentication_login")
public function loginActionAction(Request $request)
{
$authenticationUtils = $this->get('security.authentication_utils');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('AppBundle:uzduotis:login.html.twig', array(
'last_username' => $lastUsername,
'error' => $error,
));
}
then for endTime
/**
* #Route("/logout", name="logout")
* #Method({"GET"})
*/
public function logoutAction(Request $request)
{
$session = $this->$request->getSession();
$session = $this->get('session')->clear();
return $this->render('AppBundle:uzduotis:login.html.twig');
}
For this answer I assume you store the users in the database. If not, please show how you do it.
First of all please have a look at the doctrine documentation on how to connect entities to each other. In your case this should help:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-many-bidirectional
There's also a pretty good tutorial on this subject in the Symfony documentation: http://symfony.com/doc/current/doctrine/associations.html
In the controller you can fetch the currently logged in user by executing $user = $this->get('security.token_storage')->getToken()->getUser();. That will return the database entity of the user that you can modify immediately. E.g. by adding a new record to the time table (example code):
$time = new TimeLog();
$time->setUser($user);
$time->setType('login');
$time->setTimestamp(time());
In case saving does not work, try with the persist and flush methods of $this->get('doctrine')->getManager(). There's lots of documentation about this, too.

Unset session in SilverStripe

I am building a pretty simple online shop in SilverStripe. I am writing a function to remove an item from the cart (order in my case).
My setup:
My endpoint is returning JSON to the view for use in ajax.
public function remove() {
// Get existing order from SESSION
$sessionOrder = Session::get('order');
// Get the product id from POST
$productId = $_POST['product'];
// Remove the product from order object
unset($sessionOrder[$productId]);
// Set the order session value to the updated order
Session::set('order', $sessionOrder);
// Save the session (don't think this is needed, but thought I would try)
Session::save();
// Return object to view
return json_encode(Session::get('order'));
}
My issue:
When I post data to this route, the product gets removed but only temporarily, then next time remove is called, the previous item is back.
Example:
Order object:
{
product-1: {
name: 'Product One'
},
product-2: {
name: 'Product Two'
}
}
When I post to remove product-1 I get the following:
{
product-2: {
name: 'Product Two'
}
}
Which appears to have worked but then I try and remove product-2 with and get this:
{
product-1: {
name: 'Product One'
}
}
The SON OF A B is back! When I retrieve the entire cart, it still contains both.
How do I get the order to stick?
Your expectation is correct, and it should work with the code you wrote. However, the way the session data is managed doesn't work well with data being deleted, because it is not seen as a change of state. Only existing data being edited is seen as such. See Session::recursivelyApply() if you want to know more.
Only way I know is to (unfortunately) emphasized textmanipulate $_SESSION directly before you set the new value for 'order'
public function remove() {
// Get existing order from SESSION
$sessionOrder = Session::get('order');
// Get the product id from POST
$productId = $_POST['product'];
// Remove the product from order object
unset($sessionOrder[$productId]);
if (isset($_SESSION['order'])){
unset($_SESSION['order']);
}
// Set the order session value to the updated order
Session::set('order', $sessionOrder);
// Return object to view
return json_encode(Session::get('order'));
}

Cancelled Paypal orders not showing in Magento admin

I have configured a Magento 1.9 community store and all orders for which payment is made through Paypal or other payment methods (like cash on delivery), are showing up in backend.
However, when I checkout selecting Paypal as the gateway, cancel my order on the Paypal page and return to the website - my order is not showing in the admin. Isn't it supposed to show up as a cancelled order.
Since this was a store migrated from Shopify, we had to manually create about a 100 orders and change their dates in the database manually. Can this be a reason for this unexpected behaviour?
Edit 1: No order info is displayed in the grid even if the paypal window is closed instead of clicking in cancel as many answers are suggesting.
This is obvious because when you (as a customer) cancel an order in PayPal payment page it automatically destroys (unset) the order and the order quote before redirecting to shop - Not to be confused with the famous: Cancelled Order where as the name suggests is shown for the actual orders which have been actually done and then cancelled.
Depending on the PayPal method you are using this can be treated differently.
In standard PayPal you can find it in this controller:
\magento\app\code\core\Mage\Paypal\controllers\StandardController.php
when you cancel the order, cancelAction(), it first cancels the order:
public function cancelAction()
{
$session = Mage::getSingleton('checkout/session');
$session->setQuoteId($session->getPaypalStandardQuoteId(true));
if ($session->getLastRealOrderId()) {
$order = Mage::getModel('sales/order')->loadByIncrementId($session->getLastRealOrderId());
if ($order->getId()) {
$order->cancel()->save();
}
Mage::helper('paypal/checkout')->restoreQuote();
}
$this->_redirect('checkout/cart');
}
and then redirectAction() unset the quote before redirecting back to the cart page:
public function redirectAction()
{
$session = Mage::getSingleton('checkout/session');
$session->setPaypalStandardQuoteId($session->getQuoteId());
$this->getResponse()->setBody($this->getLayout()->createBlock('paypal/standard_redirect')->toHtml());
$session->unsQuoteId();
$session->unsRedirectUrl();
}
On the other hand in PayPal Express, cancel operation is triggered in this controller:
\app\code\core\Mage\Paypal\Controller\Express\Abstract.php
public function cancelAction()
{
try {
$this->_initToken(false);
// TODO verify if this logic of order cancelation is deprecated
// if there is an order - cancel it
$orderId = $this->_getCheckoutSession()->getLastOrderId();
$order = ($orderId) ? Mage::getModel('sales/order')->load($orderId) : false;
if ($order && $order->getId() && $order->getQuoteId() == $this->_getCheckoutSession()->getQuoteId()) {
$order->cancel()->save();
$this->_getCheckoutSession()
->unsLastQuoteId()
->unsLastSuccessQuoteId()
->unsLastOrderId()
->unsLastRealOrderId()
->addSuccess($this->__('Express Checkout and Order have been canceled.'))
;
} else {
$this->_getCheckoutSession()->addSuccess($this->__('Express Checkout has been canceled.'));
}
} catch (Mage_Core_Exception $e) {
$this->_getCheckoutSession()->addError($e->getMessage());
} catch (Exception $e) {
$this->_getCheckoutSession()->addError($this->__('Unable to cancel Express Checkout.'));
Mage::logException($e);
}
$this->_redirect('checkout/cart');
}
where it unset everything in the same place.
So in your case if you need to keep the quote (which I suppose is what you have been exploiting in your custom module) you have to change this behavior of PayPal module.
Please remember if you are going to do this do not modify the original core files, instead extend these classes in your custom module and apply your changes there.
When you cancel the order from Paypal page without completing the payment, it will redirect you back to your cart page. The order will not get placed.
If you close the page after paypal redirection, without completing the payment(note that you do not have to press cancel here) the order will get placed with pending payment status.
To verify whether paypal is working correctly or not, try to complete the payment process via paypal. If you are using it for testing purposes you can use the sandbox mode so that you won't get charged for your order.
Hope this helps!!

Magento automatic order status - getting list of order_status / state

I am trying to build a Magento module that observes certain events and tries to proceed automatically to a new automatic status/state, based on payment method.
In order to do that, I organized some status on the backoffice based on payment method. For example:
event: sales_order_place_after
Automatic status: pp_1_pending - First status/state where a new placed order will automatically have this status if the payment method is paypal.
event: sales_order_payment_pay
Automatic status: pp_2_payment - Second status/state after an order is payed when the payment method is paypal
event: sales_order_invoice_save_after
Automatic status: pp_3_complete- Third and final status/state after an order is invoiced, ending the transaction.
For this to work I would need to collect all status with the prefix pp_ and after checking which was set on the order, proceed to the next status in order. This way this module would be scalable.
However I can't seem to get the status collection. I am trying:
$statuses = Mage::getModel('sales/order_status')
->getCollection()
->addAttributeToSelect('status')
->addAttributeToSelect('label')
->addFieldToFilter('status',array('like','pp_'));
Hope anyone can help me. Thanks all!
The addAttributeToSelect() function is used for EAV based models.For flat models use addFieildToSelect()
The code should be
$statuses = Mage::getModel('sales/order_status')
->getCollection()
->addFieldToSelect('status')
->addFieldToSelect('label')
->addFieldToFilter('status',array('like'=>'pp_%'));
Have a look at the generated SELECT query if it looks ok.
$collection->getSelect()->__toString();
you have to use the wildcard (%) in your query, because you want the statuses that begin with pp_:
$statuses = Mage::getModel('sales/order_status')
->getCollection()
->addAttributeToSelect('status')
->addAttributeToSelect('label')
->addFieldToFilter('status',array('like','pp_%'));
in case someone is wondering, to get both states and status together, here's a function for you:
private function _allStatusStateCollection($filter) {
$collection = Mage::getModel( 'sales/order_status' )
->getCollection()->joinStates();
if ($filter != '') { return $collection->addFieldToFilter('main_table.status',array('like'=>$filter.'%')); }
return $collection;
}

How to avoid errors in saving data - Cakephp

I'm using Cakephp and trying to put in a method to make sure our reservation system doesn't let two users book the same appointment. Ex. User 1 opens the appointment, and User 2 opens it simultaneously. User 1 books the appointment. User 2 tries to book it but the system checks and sees it is no longer available.
I imagine this would take place in validation, or in a beforeSave(), but can't figure out how to do it.
Right now I made a function in the model to call from the controller. In the controller I have:
if ($this->Timeslot->checkIfNotAvailable()) {
$this->Session->setFlash('This timeslot is no longer available');
$this->redirect(array('controller' => 'users', 'action' => 'partner_homepage'));
}
and in the model I have this function:
function checkIfNotAvailable($data) {
$this->recursive = -1;
$timeslot = $this->find('all', array(
'conditions' => array(
'Timeslot.id' => $this->data['Timeslot']['id'])
)
);
if ($timeslot['student_id'] == 0) {
//They can reserve it, do not spring a flag
return false;
} else {
//Throw a flag!
return true;
}
}
I think I'm mixed up using custom validation when it's not called for. And it's not working obviously. Any suggestions?
Thanks!
If what you have is working, you can stick with it, you could also try creating a beforeValidate() call back function in your Model.
class YourModel extends AppModel {
function beforeValidate(){
if( !$this->checkIfNotAvailable( $this->data ) ) {
unset($this->data['YourModel']['time_slot']);
}
return true; //this is required, otherwise validation will always fail
}
}
This way you remove the time_slot before it goes to validation and it will drop a validation error at that point, kicking the user back to the edit page and getting them to pick a different time slot, ideally the updated data entry page will no longer have the used time slot available.

Resources