29
votes

My function to capture the transaction on auth.net is

public function capture(Varien_Object $payment, $amount){

    if(!$this->isEnabled()){
        return parent::capture($payment, $amount);
    }else{

        $captureCase = $_POST['invoice']['capture_case'];
        if(isset($captureCase) && $captureCase == "online"){
            if($capOrderid = $payment->getOrder()->getIncrementId()){

                $capOrder = $payment->getOrder();
                $capPayment = $payment;
                $capAmount = $amount;

                $capTransID = $capPayment->getLastTransId();

                $ccProfile = $this->getProfileForOrder($capOrderid);
                if(isset($ccProfile['used_this_profile']) && $ccProfile['used_this_profile'] == 1){


                    $pID = $ccProfile['cust_profile_id'];
                    $ppID = $ccProfile['cust_paymentprofile_id'];
                    $nick = $ccProfile['nickname'];

                    $lastOrderId = $capOrder->getIncrementId();


                    $cvv = $payment->getCcCid();
                    $directResponseFields = $this->createTransaction($pID,$ppID,$capAmount,$lastOrderId,"profileTransPriorAuthCapture",$cvv,$capTransID);
                    $responseCode = $directResponseFields[0]; // 1 = Approved 2 = Declined 3 = Error
                    $responseReasonCode = $directResponseFields[2]; // See http://www.authorize.net/support/AIM_guide.pdf
                    $responseReasonText = $directResponseFields[3];
                    $approvalCode = $directResponseFields[4]; // Authorization code
                    $transId = $directResponseFields[6];

                    switch ($responseCode) {
                        case "1":
                            $capPayment->setStatus(self::STATUS_APPROVED);
                            $capPayment->setCcTransId($transId);
                            $capPayment->setLastTransId($transId);
                            if (!$capPayment->getParentTransactionId() || $transId != $capPayment->getParentTransactionId()) {
                                $capPayment->setTransactionId($transId);
                            }
                            return true;
                            break;
                        case "2":
                            Mage::throwException(__('Payment authorization transaction has been declined.'));
                            break;
                        default:
                            Mage::throwException(__('Payment authorization error.'));
                            break;
                    }

                }

            }

        }elseif(!isset($captureCase)){
            $oldorderid = Mage::getModel('adminhtml/sales_order_create')->getSession()->getOrder()->getIncrementId();

            if(isset($oldorderid) && ($oldorderid != $payment->getOrder()->getIncrementId())){ // if order is created from admin and has an order to refund first.
                $oldOrder = Mage::getModel('sales/order')->loadByIncrementId($oldorderid);
                $oldPayment = $oldOrder->getPayment();
                $oldAmount = $oldPayment->getAmountOrdered();


                $transID = $oldPayment->getLastTransId();

                $ccProfile = $this->getProfileForOrder($oldorderid);
                if(isset($ccProfile['used_this_profile']) && $ccProfile['used_this_profile'] == 1){


                    $pID = $ccProfile['cust_profile_id'];
                    $ppID = $ccProfile['cust_paymentprofile_id'];

                    if($directResponseFields = $this->refundCIM($pID,$ppID,$transID,$oldorderid,$oldAmount)){

                        $responseCode = $directResponseFields[0]; // 1 = Approved 2 = Declined 3 = Error
                        $responseReasonCode = $directResponseFields[2]; // See http://www.authorize.net/support/AIM_guide.pdf
                        $responseReasonText = $directResponseFields[3];
                        $approvalCode = $directResponseFields[4]; // Authorization code
                        $transId = $directResponseFields[6];
                        switch ($responseCode) {
                            case "1":

                                //$oldPayment->setStatus(self::STATUS_SUCCESS);
                                $oldOrder->cancel()->save();

                                //$oldPayment->setIsTransactionClosed(1);
                                $oldOrder->setState(Mage_Sales_Model_Order::STATE_CANCELED, true)->save();
                                //$oldOrder->setState(Mage_Sales_Model_Order::STATE_CLOSED, true)->save();


                                //Mage::throwException(__("a".$responseCode));
                                //return $this;
                                break;
                            case "4":
                                Mage::throwException(__('Error Code 4. You cannot refund an unsettled transaction.'));
                                break;
                            default:
                                if(isset($responseReasonText) && !empty($responseReasonText)){
                                    Mage::throwException(__("Code: ".$responseReasonCode." - ".$responseReasonText));
                                }else{
                                    Mage::throwException(__('Error in refunding the payment. This can happen if the customer has deleted their profile from CIM.'));
                                }
                                break;
                        }
                    }

                }else if(isset($transID) && $oldAmount > 0) {

                    $oldPayment->setAnetTransType(self::REQUEST_TYPE_CREDIT);
                    $oldRequest = $this->_buildRequest($oldPayment);

                    $oldRequest->setXTransId($transID);

                    $oldPayment->setXAmount($oldAmount,2);  
                    $oldRequest->setXCurrencyCode($oldOrder->getBaseCurrencyCode());
                    $oldRequest->setXCardNum($oldPayment->getCcLast4());

                    $oldResult = $this->_postRequest($oldRequest);

                    if ($oldResult->getResponseCode()==self::RESPONSE_CODE_APPROVED) {
                        $oldPayment->setStatus(self::STATUS_SUCCESS);
                        $oldOrder->cancel()->save();
                    }else{
                        Mage::throwException($this->_wrapGatewayError($oldResult->getResponseReasonText())); //////////error here/////////

                    }
                }else{
                    Mage::throwException(Mage::helper('authnet')->__('Error in refunding the payment.'));
                }
            }
        }


        $quote = Mage::getSingleton('customer/session');
        $nickname = $quote->getAuthorizenetNickname();
        $profile = $quote->getProfile();
        $postedNickname = $quote->getNickname();

        if(!isset($nickname) || $nickname == "" || $nickname == "nnnew"){

            if ($amount <= 0) {
                Mage::throwException(Mage::helper('authnet')->__('Invalid amount for authorization.'));
            }

            if ($payment->getCcTransId()) {
                $payment->setAnetTransType(self::REQUEST_TYPE_PRIOR_AUTH_CAPTURE);
            } else {
                $payment->setAnetTransType(self::REQUEST_TYPE_AUTH_CAPTURE);
            }

            $payment->setAmount($amount);

            $request= $this->_buildRequest($payment);
            $result = $this->_postRequest($request);

            if ($result->getResponseCode() == self::RESPONSE_CODE_APPROVED) {
                $payment->setStatus(self::STATUS_APPROVED);
                $payment->setCcTransId($result->getTransactionId());
                $payment->setLastTransId($result->getTransactionId());
                if (!$payment->getParentTransactionId() || $result->getTransactionId() != $payment->getParentTransactionId()) {
                    $payment->setTransactionId($result->getTransactionId());
                }
                if(isset($profile) && $profile == "save"){
                    $order = $payment->getOrder();
                    $billing = $order->getBillingAddress();

                    $ccno = $payment->getCcNumber();
                    $exp = sprintf('%04d-%02d', $payment->getCcExpYear(), $payment->getCcExpMonth());
                    $cvv = $payment->getCcCid();
                    $email = $order->getCustomerEmail();
                    $orderId = $order->getIncrementId();

                    if($profiles = $this->getCustId($email)){
                        foreach ($profiles as $_nickname => $cust_profile_id){
                            if($_nickname == $postedNickname){
                                Mage::throwException(__('Nickname already in use.')); 
                            }
                        }
                        $profileId = $cust_profile_id;
                    }else{
                        $profileId = $this->createProfile($payment,true);
                    }
                    if($profileId && $profileId != 1){
                        $ppId = $this->createPaymentProfile($billing,$profileId,$ccno,$exp,$postedNickname,$email,$cvv,true);
                        $this->assignNicknameToOrder($orderId,$profileId,$ppId,$postedNickname,0);
                    }
                }   

                return $this;
            }

            if ($result->getResponseReasonText()) {
                Mage::throwException($this->_wrapGatewayError($result->getResponseReasonText()));
            }
                Mage::throwException(Mage::helper('paygate')->__('Error in capturing the payment.'));

        }else if($nickname != "" && $nickname != "nnnew"){

            $selectedNickname = $nickname;

            $conn_selected = $this->conn();
            $results_selected = $conn_selected->query("SELECT * FROM ".$this->getTable()." WHERE cust_paymentprofile_id = '".$selectedNickname."'");
            while ($row = $results_selected->fetch() ) {
                $pID = $row['cust_profile_id'];
                $nick = $row['nickname'];
            }
            $ppID = $selectedNickname;
            $order = $payment->getOrder();
            $lastOrderId = $order->getIncrementId();


            $cvv = $payment->getCcCid();
            $directResponseFields = $this->createTransaction($pID,$ppID,$amount,$lastOrderId,"profileTransAuthCapture",$cvv);
            $responseCode = $directResponseFields[0]; // 1 = Approved 2 = Declined 3 = Error
            $responseReasonCode = $directResponseFields[2]; // See http://www.authorize.net/support/AIM_guide.pdf
            $responseReasonText = $directResponseFields[3];
            $approvalCode = $directResponseFields[4]; // Authorization code
            $transId = $directResponseFields[6];

            switch ($responseCode) {
                case "1":
                    $payment->setStatus(self::STATUS_APPROVED);
                    //$payment->setCcTransId($result->getTransactionId());
                    $payment->setLastTransId($transId);
                    if (!$payment->getParentTransactionId() || $transId != $payment->getParentTransactionId()) {
                        $payment->setTransactionId($transId);
                    }
                    $this->assignNicknameToOrder($lastOrderId,$pID,$ppID,$nick,1);
                    return true;
                    break;
                case "2":
                    Mage::throwException(__('Payment authorization transaction has been declined.'));
                    break;
                default:
                    Mage::throwException(__('Payment authorization error.'));
                    break;
            }
        }
        Mage::throwException(Mage::helper('paygate')->__('Error in capturing the payment.'));
    }
}

the issue comes randomly when I try to Caputre an already authorized amount..Dump of my transaction request is

[request] => Array
        (
            [x_version] => 3.1
            [x_delim_data] => True
            [x_relay_response] => False
            [x_test_request] => FALSE
            [x_login] => ****
            [x_tran_key] => ****
            [x_type] => PRIOR_AUTH_CAPTURE
            [x_method] => CC
            [x_invoice_num] => dummy
            [x_amount] => 127.48
            [x_currency_code] => USD
            [x_trans_id] => 
            [x_first_name] => dummy
            [x_last_name] => dummyl
            [x_company] => 
            [x_address] => dummy Apt 67
            [x_city] => dummy
            [x_state] => California
            [x_zip] => dummy
            [x_country] => US
            [x_phone] => dummy
            [x_fax] => 
            [x_cust_id] => 
            [x_customer_ip] => 68.183xxxxx8
            [x_customer_tax_id] => 
            [x_email] => [email protected]
            [x_email_customer] => 0
            [x_merchant_email] => 
            [x_ship_to_first_name] =>dummy
            [x_ship_to_last_name] => dummy
            [x_ship_to_company] => 
            [x_ship_to_address] => dummy Blvd.
            [x_ship_to_city] => dummy
            [x_ship_to_state] => dummy
            [x_ship_to_zip] => dummy
            [x_ship_to_country] => US
            [x_po_num] => 
            [x_tax] => 0.0000
            [x_freight] => 0.0000
        )

and the response is

[result] => Array
        (
            [response_code] => 3
            [response_subcode] => 2
            [response_reason_code] => 33
            [response_reason_text] => A valid referenced transaction ID is required.
            [approval_code] => 
            [avs_result_code] => P
            [transaction_id] => 0
            [invoice_number] => 100dddd38
            [description] => 
            [amount] => 127.48
            [method] => CC
            [transaction_type] => prior_auth_capture
            [customer_id] => 
            [md5_hash] => dummy
            [card_code_response_code] => 
            [c_av_vresponse_code] => 
            [split_tender_id] => 
            [acc_number] => 
            [card_type] => 
            [requested_amount] => 
            [balance_on_card] => 
        )

I noted that Transaction ID is missing In my Request, the Auth.net developer site says the same ..Some times the orders get captured, but most of time, they dont..I also noted that both successful captures and unsuccessfull captures,transaction ID exists in Magento ( I can view it in in admin panel, see this

When I try to create invoice and capture transaction via mag admin, I get the error

Gateway error: A valid referenced transaction ID is required.

I am wondering why this Happening..Can somebody help me>? any idea?

My plate form is Magento Enterpise (1.12.x) and the extension I am trying to get working is Elayers ( I did not purchased it, working for someone)

1
x_trans_id needs to be set in the request for prior_auth_capture. It should be parsed out of the response to the original auth_only request.mike__t
I already figured it out that the function is not sending this, can you tell me how can I add this, please not it is being sent for few orders thoughZaffar Saffee
I've ran in to a similar situation when the column type was set to integer of a certain size for the transaction id. Sometimes the id would be greater than the column was capable of and would store erroneous, truncated or no data. Can you check your table and make sure the id is there and that it matches with auth.net shows for that transaction?iJeep
thanks...yes, I have made sure that transaction ID from AUTH is saved to mag database and its visible in admin back end too, I am sure that transaction ID is being saved as it should be..also, you can see the debug, transaction ID is being sent EMPTYZaffar Saffee
What happens when you echo out $transID? What do you get?John Conde

1 Answers

1
votes

TransctionID is being hidden when you're loading the model in the version of Magento that you are using. Try using the ->addFieldToSelect('transaction_id') on loading the model. The reason for this is because it is a protected data attribute and should never be dealt with directly the way you have attempted here.

Alternatively you really should be using Magento's ability to create invoice from the sales order model.

$order = Mage::getModel('sales/order');
$service = Mage::getModel('sales/service_order' , $order);
$service->prepareInvoice();

prepareInvoice takes an optional array of ( 'sku' => 'qty' )

Which makes it easy to manage the potential for multiple invoices per order.