【问题标题】:Magento Credit card number mismatch with credit card type exceptionMagento 信用卡号与信用卡类型异常不匹配
【发布时间】:2012-04-25 14:08:54
【问题描述】:

我正在使用 magento api,但在创建订单时遇到了一些问题。我已经能够完成所有工作,以创建正常工作的订单。我看到的问题是当我调用方法来创建订单时,我总是得到异常:Credit card number mismatch with credit card type.

我正在运行 Magento 版本。 1.6.2.0

我已验证我正在测试的卡可以通过 magento 前端工作。

非常感谢任何帮助。

这是我正在使用的测试代码:

<?php
$proxy = new SoapClient('http://localhost/index.php/api/soap/?wsdl');
$sessionId = $proxy->login('shopapi', 'test123');

// Create a quote, get quote identifier
$shoppingCartId = $proxy->call( $sessionId, 'cart.create');

// Set customer, for example guest
$customerAsGuest = array(
    "firstname" => "testFirstname",
    "lastname" => "testLastName",
    "email" => "test@test.com",
    //"website_id" => "0",
    //"store_id" => "0",
    "mode" => "guest"
);
$resultCustomerSet = $proxy->call($sessionId, 'cart_customer.set', array( $shoppingCartId, $customerAsGuest) );

// Set customer addresses, for example guest's addresses
$arrAddresses = array(
    array(
        "mode" => "shipping",
        "firstname" => "testFirstname",
        "lastname" => "testLastname",
        "company" => "testCompany",
        "street" => "testStreet",
        "city" => "testCity",
        "region" => "CA",
        "postcode" => "90049",
        "country_id" => "US",
        "telephone" => "0123456789",
        "fax" => "0123456789",
        "is_default_shipping" => 0,
        "is_default_billing" => 0
    ),
    array(
        "mode" => "billing",
        "firstname" => "testFirstname",
        "lastname" => "testLastname",
        "company" => "testCompany",
        "street" => "testStreet",
        "city" => "testCity",
        "region" => "CA",
        "postcode" => "90049",
        "country_id" => "US",
        "telephone" => "0123456789",
        "fax" => "0123456789",
        "is_default_shipping" => 0,
        "is_default_billing" => 0
    )
);
$resultCustomerAddresses = $proxy->call($sessionId, "cart_customer.addresses", array($shoppingCartId, $arrAddresses));

// add products into shopping cart
$arrProducts = array(
    array(
        "product_id" => "1",
        "qty" => 1
    )
);
$resultCartProductAdd = $proxy->call($sessionId, "cart_product.add", array($shoppingCartId, $arrProducts));


// get list of products
$shoppingCartProducts = $proxy->call($sessionId, "cart_product.list", array($shoppingCartId));


// set payment method
$paymentMethod = array(
    "method" => "authorizenet",
    "cc_type" => 'MC',
    "cc_number" =>'5555555555554444' ,
    "cc_exp_month" => 9,
    "cc_exp_year" => 2014,
    "cc_cid" => 123     
);
$resultPaymentMethod = $proxy->call($sessionId, "cart_payment.method", array($shoppingCartId, $paymentMethod));


// create order
$resultOrderCreation = $proxy->call($sessionId,"cart.order",array($shoppingCartId));
var_dump($resultOrderCreation);
 ?>

【问题讨论】:

标签: php magento


【解决方案1】:

根据您的帖子,您对 cart_payment.method 的调用已成功,因此 CC 号码正在验证为 MC 卡,正如预期的那样。

问题是 Magento 出于 PCI 的考虑,不会将 CC 编号保存在数据库中(在大多数情况下)。

因此,当您在一个请求中发送付款详细信息以及 CC 编号和 CID,然后在另一个请求中创建订单时,状态会丢失并且 CC 编号和 CID 会被清空。

当订单创建时,支付数据会被第二次验证,当这种情况发生时,它有一个空的 CC 编号和一个 MC 类型,导致你看到的错误。

很遗憾,我看不到让 cart.order 接受付款数据的方法。

您可以编写一个模块来使用一种新方法扩展结帐 API,该方法在一次调用中完成这两个步骤,这可能会解决问题。

【讨论】:

    【解决方案2】:

    我也遇到了这个问题。我的解决方案是创建一个自定义 SOAP 端点,它可以一次处理所有订单创建和提交逻辑,而无需多次 API 调用。

    即使这样,我也遇到了卡片类型不匹配的异常。

    诀窍是,一旦我使用 getPayment->importData 方法设置付款信息、收集总计并保存报价,它似乎忘记了卡信息。可能是为了(不是处理的最佳方式)PCI-DSS 合规性。

    为了解决这个问题,我在保存报价后,在提交订单之前添加了另一个 getPayment->importData 行。

    这是在不更改任何核心文件的情况下实现的。

    查看示例:

    public function customCheckout($checkoutData=false)
      {
        if(!$checkoutData){
          Mage::throwException("No checkout data received.");
        }
        if(!json_decode($checkoutData)){
          Mage::throwException("Bad checkout data received.");
        }
    
        $data = json_decode($checkoutData);
    
        $email = 'email@email.cc';
    
        // get the basic store info to associate with order
        $websiteId  = Mage::app()->getWebsite()->getId();
        $store      = Mage::app()->getStore();
    
        // begin checkout with a quote
        $quote    = Mage::getModel('sales/quote')->setStoreId($store->getId());
    
        // set customer by email
        $customer = Mage::getModel('customer/customer')
                      ->setWebsiteId($websiteId)
                      ->loadByEmail($email);
    
        // handle customer not exists by creating a new customer
        if($customer->getId() == ''){
          $customer = Mage::getModel('customer/customer');
          $customer->setWebsiteId($websiteId)
                   ->setStore($store)
                   ->setFirstName("Bob")
                   ->setLastName("Loblaw")
                   ->setEmail($email)
                   ->setPassword('password');
          $customer->save();
        }
    
        // assign customer to SO quote
        $quote->assignCustomer($customer);
    
        // do we want to send a confirmation email to the customer?
        // my guess is we would handle that in a separate service.
        $quote->setSendConfirmation(0);
    
        // add products to quote
        foreach($data->products as $item){
          $product = Mage::getModel('catalog/product')->load($item->id);
          $quote->addProduct($product,new Varien_Object(array('qty'=>$item->qty)));
        }
    
        // set SO billing address
        $billingAddress = $quote->getBillingAddress()->addData(array(
          'customer_address_id' => '',
          'prefix' => '',
          'firstname' => $data->customer->firstName,
          'middlename' => '',
          'lastname' => $data->customer->lastName,
          'suffix' => '',
          'company' => '',
          'street' => array(
            '0' => 'street1',
            '1' => 'street2'
          ),
          'city'=>'city',
          'country_id'=>'US',
          'region'=>'WA',
          'postcode'=>'98101',
          'telephone' => '425-425-4254',
          'fax' => '789-789-7897',
          'vat_id' => '',
          'save_in_address_book' => 0
        ));
    
        // set SO shipping address, this will probably be the location of sale, on-site
        $shippingAddress = $quote->getShippingAddress()->addData(array(
          'customer_address_id' => '',
          'prefix' => '',
          'firstname' => $data->customer->firstName,
          'middlename' => 'middle',
          'lastname' => $data->customer->lastName,
          'suffix' => '',
          'company' => '',
          'street' => array(
            '0' => 'street1',
            '1' => 'street2'
          ),
          'city'=>'city',
          'country_id'=>'US',
          'region'=>'WA',
          'postcode'=>'98201',
          'telephone' => '425-425-4254',
          'fax' => '789-789-7897',
          'vat_id' => '',
          'save_in_address_book' => 0
        ));
    
        // set shipping method, if it's sold on site we aren't charging for delivery
        $shipMethod='freeshipping_freeshipping';
    
        $shippingAddress->setCollectShippingRates(true)
                        ->collectShippingRates()
                        ->setShippingMethod($shipMethod)
                        ->setPaymentMethod($data->payment->method);
    
        // set payment method
        $quote->getPayment()->importData(array(
          'method'      =>$data->payment->method,
          'cc_type'     =>$data->payment->type,
          'cc_number'   =>$data->payment->number,
          'cc_exp_year' =>$data->payment->expYear,
          'cc_exp_month'=>$data->payment->expMonth,
        ));
    
        // collect totals, save quote
        $quote->collectTotals()->save();
    
        // turn the quote into an order
        $service = Mage::getModel('sales/service_quote',$quote);
    
        // set payment method A SECOND TIME!!!!!!!!!!!!!
        $quote->getPayment()->importData(array(
          'method'      =>$data->payment->method,
          'cc_type'     =>$data->payment->type,
          'cc_number'   =>$data->payment->number,
          'cc_exp_year' =>$data->payment->expYear,
          'cc_exp_month'=>$data->payment->expMonth,
        ));
    
        $service->submitAll();
        $increment_id = $service->getOrder()->getRealOrderId();
    
        $quote = $customer = $service = null;
    
        $retval = new stdClass;
        $retval->orderId = $increment_id;
    
        return json_encode($retval);
      }
    

    【讨论】:

    • 这个解决方案对我有用。是否会导致与 PCI 投诉相关的任何问题? @布拉德
    • 它不会导致任何 PCI 问题。按照我的示例的编写方式,它不会将卡信息保留在将其发送到付款方式之后。如果您使用的支付方式保留了卡数据,那么您已经有 PCI 风险。
    • 我正在使用开箱即用的 authorize.net 模块,并且 saveCC 已在模块级别禁用。所以不会导致任何问题吧?
    • 我希望不会,但如果您有顾虑,我会核实一下。检查日志和/或分析数据库以查找卡信息。
    【解决方案3】:

    我从未对付款方式代码authorizenet 进行过成功的 API 交易。这只总是通过前端成功,不知道为什么..我也没有时间调查原因。尽管我一直在做的是改用authorizenet_direct post。我背后的原因/我是如何偶然发现的,这同样适用于 Paypal 支付方式。 API 似乎只适用于paypal_directpaypaluk_direct。试试吧!它应该工作。至少,这对我有用。

    $paymentMethod = array(
        "method" => "authorizenet_directpost",
        "cc_type" => 'MC',
        "cc_number" =>'5555555555554444' ,
        "cc_exp_month" => 9,
        "cc_exp_year" => 2014,
        "cc_cid" => 123     
    );
    

    【讨论】:

    • 这个问题是它使订单处于待付款状态,而不是处于处理状态。我已将其设置为授权和捕获,但它似乎从未捕获。
    • 它可能没有捕获,因为它没有有效的交易来引用捕获。 AuthorizeNet DirectPost 方法似乎与 Checkout API 不兼容,除非您手动发布付款详细信息并取回有效交易。不确定这是否可能。
    【解决方案4】:

    实际上,我刚刚发现了一种通过 API 进行 authorize.net 付款的方法。

    首先在 /app/code/core/Mage/Payment/Model/Method/Cc.php 中,取消注释保存 cid 的那一行,所以函数在第 65 行看起来像这样

    public function prepareSave()
    {
        $info = $this->getInfoInstance();
        if ($this->_canSaveCc) {
            $info->setCcNumberEnc($info->encrypt($info->getCcNumber()));
        }
        $info->setCcCidEnc($info->encrypt($info->getCcCid()));
        $info->setCcNumber(null)
            ->setCcCid(null);
        return $this;
    }
    

    然后在您的付款方式的主模型文件中,确保将变量设置为:

        protected $_canSaveCc = true;
    

    我已经使用它测试了 2 种付款方式,现在都可以通过 API 正常工作。

    【讨论】:

    • 我有同样的问题并尝试了你的解决方案,但它不起作用..我应该做一些我可能会丢失的其他事情......谢谢
    • 请不要这样做。您允许 Magento 保存持卡人数据,这是一个重要的 PCI-DSS 暴露,您最好尽可能避免。破解 Magento 核心通常不是一个好主意。如果您决定应用更新,这是一个很好的方法,可能会或可能不会丢失您的更改。
    【解决方案5】:

    这是我的解决方案: 转到/app/code/core/Mage/Payment/Model/Method/Cc.php 并查看功能:

    public function prepareSave()
    {
        $info = $this->getInfoInstance();
        if ($this->_canSaveCc) {
            $info->setCcNumberEnc($info->encrypt($info->getCcNumber()));
        }
        //$info->setCcCidEnc($info->encrypt($info->getCcCid()));
        $info->setCcNumber(null)
            ->setCcCid(null);
        return $this;
    }
    

    只有注释行:

    $info->setCcNumber(null)
     ->setCcCid(null);
    

    【讨论】:

    • 我有同样的问题并尝试了你的解决方案,但它不起作用..我应该做一些我可能会丢失的其他事情......谢谢
    猜你喜欢
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    • 2011-02-04
    • 1970-01-01
    • 2011-06-02
    • 1970-01-01
    • 2019-10-06
    相关资源
    最近更新 更多