Results 1 to 5 of 5
  1. #1
    Join Date
    Jan 2011
    Posts
    65
    Plugin Contributions
    0

    Default Added my own MessageStack for Additional Credit Card Processing Errors

    So I looked through the code, and it appears as if the functionality to display custom message strings via the messagestack depending on the error response code received from PayPal has been programmed into the payment module.

    So in the file /includes/modules/payment/paypaldp.php, the original code for the custom messagestacks is as follows:

    Code:
    case 'DoDirectPayment':
            if ($basicError ||
               ((isset($_SESSION['paypal_ec_token']) && isset($response['TOKEN'])) && $_SESSION['paypal_ec_token'] != urldecode($response['TOKEN'])) ) {
                // Error, so send the store owner a complete dump of the transaction.
              if ($this->enableDebugging) {
                $this->_doDebug('PayPal Error Log - before_process() - DP', "In function: before_process() - Direct Payment \r\nDid first contact attempt return error? " . ($error_occurred ? "Yes" : "No") . " \r\n\r\nValue List:\r\n" . str_replace('&',"\r\n", urldecode($doPayPal->_sanitizeLog($doPayPal->_parseNameValueList($doPayPal->lastParamList)))) . "\r\n\r\nResponse:\r\n" . urldecode(print_r($response, true)));
              }
              $errorText = MODULE_PAYMENT_PAYPALDP_INVALID_RESPONSE;
              $errorNum = urldecode($response['L_ERRORCODE0'] . ' ' . $response['RESULT'] . ' <!-- ' . $response['RESPMSG'] . ' -->');
              if ($response['RESULT'] == 25) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_NOT_WPP_ACCOUNT_ERROR;
              if ($response['L_ERRORCODE0'] == 10500 || $response['L_ERRORCODE0'] == 10501) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_NOT_US_WPP_ACCOUNT_ERROR;
              if ($response['HOSTCODE'] == 10500 || $response['HOSTCODE'] == 10501) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_NOT_UKWPP_ACCOUNT_ERROR;
              if ($response['HOSTCODE'] == 10558) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_CANNOT_USE_THIS_CURRENCY_ERROR;
              if ($response['L_ERRORCODE0'] == 10002) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_SANDBOX_VS_LIVE_ERROR;
              if ($response['L_ERRORCODE0'] == 10565) {
                $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_WPP_BAD_COUNTRY_ERROR;
                $_SESSION['payment'] = '';
              }
              if ($response['L_ERRORCODE0'] == 10566) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_CARD_TYPE_NOT_SUPPORTED;
              if ($response['L_ERRORCODE0'] == 10736) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_ADDR_ERROR;
              if ($response['L_ERRORCODE0'] == 10752) {
                $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_DECLINED;
                $errorNum = '10752';
              }
              if ($response['L_ERRORCODE0'] == 15012) { // Mastercard CE agreement not signed between merchant and PayPal. Thus cannot accept mastercard.
                $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_CARD_TYPE_NOT_SUPPORTED;
                $errorNum = '15012';
              }
              if ($response['L_ERRORCODE0'] == 15005) {
                $errorText = 'Card rejected by the bank. Your IP address has been recorded.';
                $errorNum = '15005';
              }
              if ($response['RESPMSG'] != '') $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_DECLINED . ' ' . $errorText;
    
              $detailedMessage = ($errorText == MODULE_PAYMENT_PAYPALDP_INVALID_RESPONSE || $errorText == MODULE_PAYMENT_PAYPALDP_TEXT_DECLINED || $this->enableDebugging || $response['CURL_ERRORS'] != '' || $this->emailAlerts) ? (isset($response['RESULT']) && $response['RESULT'] != 0 ? MODULE_PAYMENT_PAYPALDP_CANNOT_BE_COMPLETED . ' (' . $errorNum . ')' : $errorNum) . ' ' . urldecode(' ' . $response['L_SHORTMESSAGE0'] . ' - ' . $response['L_LONGMESSAGE0'] . ' ' . $response['CURL_ERRORS']) : '';
              $explain = "\n\nProblem occurred while customer #" . $_SESSION['customer_id'] . ' -- ' . $_SESSION['customer_first_name'] . ' ' . $_SESSION['customer_last_name'] . ' -- was attempting checkout.' . "\n";
              $detailedEmailMessage = MODULE_PAYMENT_PAYPALDP_TEXT_EMAIL_ERROR_MESSAGE . urldecode($response['L_ERRORCODE0']  . ' ' . $response['RESPMSG']. "\n" . $response['L_SHORTMESSAGE0'] . "\n" . $response['L_LONGMESSAGE0'] . $response['L_ERRORCODE1'] . "\n" . $response['L_SHORTMESSAGE1'] . "\n" . $response['L_LONGMESSAGE1'] . $response['L_ERRORCODE2'] . "\n" . $response['L_SHORTMESSAGE2'] . "\n" . $response['L_LONGMESSAGE2'] . ($response['CURL_ERRORS'] != '' ? "\n" . $response['CURL_ERRORS'] : '') . "\n\n" . 'Zen Cart message: ' . $detailedMessage . "\n\n" . $errorInfo . "\n\n" . 'Transaction Response Details: ' . print_r($response, true) . "\n\n" . 'Transaction Submission: ' . urldecode($doPayPal->_sanitizeLog($doPayPal->_parseNameValueList($doPayPal->lastParamList), true)));
              $detailedEmailMessage .= $explain;
              zen_mail(STORE_NAME, STORE_OWNER_EMAIL_ADDRESS, MODULE_PAYMENT_PAYPALDP_TEXT_EMAIL_ERROR_SUBJECT . ' (' . zen_uncomment($errorNum) . ')', zen_uncomment($detailedMessage . $explain), STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, array('EMAIL_MESSAGE_HTML'=>nl2br(zen_uncomment($detailedEmailMessage))), 'paymentalert');
              if ($response['L_ERRORCODE0'] == 15012) $detailedEmailMessage = '';
              $this->terminateEC(($detailedEmailMessage == '' ? $errorText . ' (' . $errorNum . ') ' : $detailedMessage), ($gateway_mode ? true : false), FILENAME_CHECKOUT_PAYMENT);
              return true;
            }
            break;
    Specifically, the last like of code:
    Code:
    $this->terminateEC(($detailedEmailMessage == '' ? $errorText . ' (' . $errorNum . ') ' : $detailedMessage), ($gateway_mode ? true : false), FILENAME_CHECKOUT_PAYMENT);

    The problem is that the terminateEC functioncall never passes the $errorText value because in almost all instances, the ternary operator where the condition $detailedEmailMessage == '' (ie., blank) is never met. I'm not sure why that conditional operator needs to require that $detailedEmailMessage has to be blank in order for the errorText and errorNum values to be passed to the terminateEC functioncall, as it seems more logical that the errorText and errorNum values should be passed in any case where a basicError has occurred when PayPal attempts to process the submitted payment information.

    This is why the terminateEC functioncall only ever displays PayPal's generic alert messages, which, in my opinion, are ambiguous, and difficult for the customer to decipher as to what exactly went wrong with their payment attempt.

    Here is the modification to the code to make the messagestack display customized error messages:
    Code:
    case 'DoDirectPayment':
            if ($basicError ||
               ((isset($_SESSION['paypal_ec_token']) && isset($response['TOKEN'])) && $_SESSION['paypal_ec_token'] != urldecode($response['TOKEN'])) ) {
                // Error, so send the store owner a complete dump of the transaction.
              if ($this->enableDebugging) {
                $this->_doDebug('PayPal Error Log - before_process() - DP', "In function: before_process() - Direct Payment \r\nDid first contact attempt return error? " . ($error_occurred ? "Yes" : "No") . " \r\n\r\nValue List:\r\n" . str_replace('&',"\r\n", urldecode($doPayPal->_sanitizeLog($doPayPal->_parseNameValueList($doPayPal->lastParamList)))) . "\r\n\r\nResponse:\r\n" . urldecode(print_r($response, true)));
              }
              $errorText = MODULE_PAYMENT_PAYPALDP_INVALID_RESPONSE;
              $errorNum = urldecode($response['L_ERRORCODE0'] . ' ' . $response['RESULT'] . ' <!-- ' . $response['RESPMSG'] . ' -->');
              if ($response['RESULT'] == 25) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_NOT_WPP_ACCOUNT_ERROR;
              if ($response['L_ERRORCODE0'] == 10500 || $response['L_ERRORCODE0'] == 10501) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_NOT_US_WPP_ACCOUNT_ERROR;
              if ($response['HOSTCODE'] == 10500 || $response['HOSTCODE'] == 10501) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_NOT_UKWPP_ACCOUNT_ERROR;
              if ($response['HOSTCODE'] == 10558) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_CANNOT_USE_THIS_CURRENCY_ERROR;
              if ($response['L_ERRORCODE0'] == 10002) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_SANDBOX_VS_LIVE_ERROR;
              if ($response['L_ERRORCODE0'] == 10565) {
                $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_WPP_BAD_COUNTRY_ERROR;
                $_SESSION['payment'] = '';
              }
              if ($response['L_ERRORCODE0'] == 10566) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_CARD_TYPE_NOT_SUPPORTED;
              if ($response['L_ERRORCODE0'] == 10736) $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_ADDR_ERROR;
              if ($response['L_ERRORCODE0'] == 10752) {
                $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_DECLINED;
                $errorNum = '10752';
              }
              if ($response['L_ERRORCODE0'] == 15012) { // Mastercard CE agreement not signed between merchant and PayPal. Thus cannot accept mastercard.
                $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_CARD_TYPE_NOT_SUPPORTED;
                $errorNum = '15012';
              }
              if ($response['L_ERRORCODE0'] == 15005) {
                $errorText = 'Credit card was declined, please contact your credit card issuer for assistance or use a different credit card. Your IP address has been recorded as a precautionary measure.';
                $errorNum = '15005';
              }
              if ($response['L_ERRORCODE0'] == 11611) {
                $errorText = 'We could not validate your credit card details, please verify that your billing address and 3 digit CVC code were inputted correctly and try again, or contact us for assistance. Your IP address has been recorded as a precautionary measure.';
                $errorNum = '11611';
              }
              if ($response['RESPMSG'] != '') $errorText = MODULE_PAYMENT_PAYPALDP_TEXT_DECLINED . ' ' . $errorText;
    
              $detailedMessage = ($errorText == MODULE_PAYMENT_PAYPALDP_INVALID_RESPONSE || $errorText == MODULE_PAYMENT_PAYPALDP_TEXT_DECLINED || $this->enableDebugging || $response['CURL_ERRORS'] != '' || $this->emailAlerts) ? (isset($response['RESULT']) && $response['RESULT'] != 0 ? MODULE_PAYMENT_PAYPALDP_CANNOT_BE_COMPLETED . ' (' . $errorNum . ')' : $errorNum) . ' ' . urldecode(' ' . $response['L_SHORTMESSAGE0'] . ' - ' . $response['L_LONGMESSAGE0'] . ' ' . $response['CURL_ERRORS']) : '';
              $explain = "\n\nProblem occurred while customer #" . $_SESSION['customer_id'] . ' -- ' . $_SESSION['customer_first_name'] . ' ' . $_SESSION['customer_last_name'] . ' -- was attempting checkout.' . "\n";
              $detailedEmailMessage = MODULE_PAYMENT_PAYPALDP_TEXT_EMAIL_ERROR_MESSAGE . urldecode($response['L_ERRORCODE0']  . ' ' . $response['RESPMSG']. "\n" . $response['L_SHORTMESSAGE0'] . "\n" . $response['L_LONGMESSAGE0'] . $response['L_ERRORCODE1'] . "\n" . $response['L_SHORTMESSAGE1'] . "\n" . $response['L_LONGMESSAGE1'] . $response['L_ERRORCODE2'] . "\n" . $response['L_SHORTMESSAGE2'] . "\n" . $response['L_LONGMESSAGE2'] . ($response['CURL_ERRORS'] != '' ? "\n" . $response['CURL_ERRORS'] : '') . "\n\n" . 'Zen Cart message: ' . $detailedMessage . "\n\n" . $errorInfo . "\n\n" . 'Transaction Response Details: ' . print_r($response, true) . "\n\n" . 'Transaction Submission: ' . urldecode($doPayPal->_sanitizeLog($doPayPal->_parseNameValueList($doPayPal->lastParamList), true)));
              $detailedEmailMessage .= $explain;
              zen_mail(STORE_NAME, STORE_OWNER_EMAIL_ADDRESS, MODULE_PAYMENT_PAYPALDP_TEXT_EMAIL_ERROR_SUBJECT . ' (' . zen_uncomment($errorNum) . ')', zen_uncomment($detailedMessage . $explain), STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, array('EMAIL_MESSAGE_HTML'=>nl2br(zen_uncomment($detailedEmailMessage))), 'paymentalert');
              if ($response['L_ERRORCODE0'] == 15012) $detailedEmailMessage = '';
              $this->terminateEC($errorText . ' (' . $errorNum . ')', ($gateway_mode ? true : false), FILENAME_CHECKOUT_PAYMENT);
              return true;
            }
            break;
    In the code above are examples of what I used in my custom messagestack for error 15005 (credit card declined by customer's bank) and error 11611 (payment rejected based on PayPal's fraud management filters). You can change it to however you see fit for your own store.

    It is basically up to you to use your own discretion concerning how much info you wish to divulge to customers concerning their payment attempts. For instance, in my specific situation, I employ PayPal Fraud Management Filters, PayPal automatically logs all IP's for failed payment attempts, I use MaxMind Orders to verify all customer's purchases, and just basic common sense when evaluating whether or not I think a customer is high risk for being fraudulent, not to mention Zen-Cart's own built in credit card slamming feature...

    So for me, I was having roughly 5-10% of my customers receiving a generic "15005 Processor Decline - This transaction cannot be processed." message and having them email or call me being frustrated because they don't realize the payment attempt was declined by their own bank... I don't think is the optimal method for handling the situation. A custom messageStack informing them that their bank declined the transation and to contact their credit card issuer for more information I think is much more efficient. But again this is just my opinion and my own preference for how I want to deal with this situation.

    I just thought I'd pass along the method/solution to customizing the messageStack based on PayPal's errorcodes, and how anyone wishes to use it can based on their own discretion.

    Hope you guys find some use out of this!

  2. #2
    Join Date
    Jan 2007
    Location
    Australia
    Posts
    6,167
    Plugin Contributions
    7

    Default Re: Added my own MessageStack for Additional Credit Card Processing Errors

    Quote Originally Posted by RoboPhung View Post
    Specifically, the last like of code:
    Code:
    $this->terminateEC(($detailedEmailMessage == '' ? $errorText . ' (' . $errorNum . ') ' : $detailedMessage), ($gateway_mode ? true : false), FILENAME_CHECKOUT_PAYMENT);
    The problem is that the terminateEC functioncall never passes the $errorText value because in almost all instances, the ternary operator where the condition $detailedEmailMessage == '' (ie., blank) is never met.
    The code appears correct. Perhaps you are misreading it? This code is akin to an If/then/else structure that states "IF the $detailedEmailMessage is an empty string THEN output the $errorText ELSE output the $detailedEmailMessage"

    In other words, it should only output the less informative $errorText IF it hasn't been able to create the more useful $detailedEmailMessage.

    Cheers
    Rod

  3. #3
    Join Date
    Jan 2011
    Posts
    65
    Plugin Contributions
    0

    Default Re: Added my own MessageStack for Additional Credit Card Processing Errors

    Quote Originally Posted by RodG View Post
    The code appears correct. Perhaps you are misreading it? This code is akin to an If/then/else structure that states "IF the $detailedEmailMessage is an empty string THEN output the $errorText ELSE output the $detailedEmailMessage"

    In other words, it should only output the less informative $errorText IF it hasn't been able to create the more useful $detailedEmailMessage.

    Cheers
    Rod
    Yep but the issue with that conditional statement is that the contents of $detailedEmailMessage is an information dump that is meant for the zen-cart administrator, and is only for their use.

    $errorText contains the message that is displayed to the customer in the messageStack when they unsuccessfully attempt payment.

    They're two different things. That conditional statement in the original code specifies to only pass the messageStack error message for the customer to see in the event that a detailed information dump has not been sent to the administrator.

    This is why in almost all cases, the errorText is never passed, and the messageStack only ever displays PayPal's own generic messages (which I think the code is programmed to set as the $errorText value since it's not being passed a value otherwise).

    Actually thinking about it now....perhaps the ternary statement's logic was meant to read:

    Code:
    $this->terminateEC(($detailedEmailMessage !== '' ? $errorText . ' (' . $errorNum . ') ' : $detailedMessage), ($gateway_mode ? true : false), FILENAME_CHECKOUT_PAYMENT);
    So the logic becomes, IF there exists a detailed error dump generated to be sent to the administrator, then an error occurred, so pass the errortext message string along so that it can be displayed in the messageStack to the customer.

  4. #4
    Join Date
    Jan 2004
    Posts
    66,374
    Blog Entries
    7
    Plugin Contributions
    274

    Default Re: Added my own MessageStack for Additional Credit Card Processing Errors

    Perhaps this small change would solve the problem of messages not being displayed?
    https://github.com/zencart/zc-v15/co...63878a3ee4116c
    .

    Zen Cart - putting the dream of business ownership within reach of anyone!
    Donate to: DrByte directly or to the Zen Cart team as a whole

    Remember: Any code suggestions you see here are merely suggestions. You assume full responsibility for your use of any such suggestions, including any impact ANY alterations you make to your site may have on your PCI compliance.
    Furthermore, any advice you see here about PCI matters is merely an opinion, and should not be relied upon as "official". Official PCI information should be obtained from the PCI Security Council directly or from one of their authorized Assessors.

  5. #5
    Join Date
    Jan 2011
    Posts
    65
    Plugin Contributions
    0

    Default Re: Added my own MessageStack for Additional Credit Card Processing Errors

    Quote Originally Posted by DrByte View Post
    Perhaps this small change would solve the problem of messages not being displayed?
    https://github.com/zencart/zc-v15/co...63878a3ee4116c
    Oh sorry, it would be much more informative if I had specified that my original post and proposed change in the code to display the custom message stacks pertains to the paypal wpp module for zc 1.3.9h.

    It looks like the code you're pointing out belongs to 1.5, and appears to be completely rewritten.

    Really looking forward to upgrading and migrating to 1.5 in the very near future!

 

 

Similar Threads

  1. Call-In for Credit Card Processing Module....
    By ChrystiLell in forum Addon Payment Modules
    Replies: 2
    Last Post: 9 Apr 2010, 07:12 PM
  2. Replies: 0
    Last Post: 7 Jul 2009, 04:30 PM
  3. Installing ANZ Bank's eGateway for credit card processing
    By johnwey in forum Addon Payment Modules
    Replies: 3
    Last Post: 17 Nov 2008, 08:53 PM
  4. what are options for credit card processing
    By sobebabies in forum Built-in Shipping and Payment Modules
    Replies: 6
    Last Post: 11 Aug 2007, 10:30 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
disjunctive-egg
Zen-Cart, Internet Selling Services, Klamath Falls, OR