Committer: ssafronova
LJSUP-8014: Credit card payment process refactoringU trunk/bin/upgrading/en_LJ.dat U trunk/cgi-bin/LJ/Pay/Payment.pm U trunk/cgi-bin/LJ/Pay/RecBill.pm U trunk/htdocs/admin/accounts/paidsearch.bml U trunk/ssldocs/manage/account/cc.bml U trunk/ssldocs/pay/cc.bml
Modified: trunk/bin/upgrading/en_LJ.dat =================================================================== --- trunk/bin/upgrading/en_LJ.dat 2011-03-05 07:12:27 UTC (rev 10192) +++ trunk/bin/upgrading/en_LJ.dat 2011-03-05 08:09:24 UTC (rev 10193) @@ -138,6 +138,173 @@ after_entry_post_extra_option|staleness=1 after_entry_post_extra_option=Post it to LJ Bazaar +authcap.reason.code.100=Successful transaction. + +authcap.reason.code.101=The request is missing one or more required fields. Resend the request with the complete information. + +authcap.reason.code.102=One or more fields in the request contains invalid data. Resend the request with the correct information. + +authcap.reason.code.110=Only a partial amount was approved. + +authcap.reason.code.150=Error: General system failure at CyberSource. + +authcap.reason.code.151<< +Error: The request was received but there was a server timeout. This error does not include timeouts between the client and the server. +Possible action: To avoid duplicating the transaction, do not resend the request until you have reviewed the transaction status in the Business Center. +. + +authcap.reason.code.152<< +Error: The request was received, but a service did not finish running in time. +Possible action: To avoid duplicating the transaction, do not resend the request until you have reviewed the transaction status in the Business Center. +. + +authcap.reason.code.200<< +The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the Address Verification Service (AVS) check. +Possible action: You can capture the authorization, but consider reviewing the order for the possibility of fraud. +. + +authcap.reason.code.201<< +The issuing bank has questions about the request. You do not receive an authorization code programmatically, but you might receive one verbally by calling the processor. +Possible action: Call your processor to possibly receive a verbal authorization. For contact phone numbers, refer to your merchant bank information. +. + +authcap.reason.code.202<< +Expired card. You might also receive this if the expiration date you provided does not match the date the issuing bank has on file. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.203<< +General decline of the card. No other information provided by the issuing bank. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.204<< +Insufficient funds in the account. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.205<< +Stolen or lost card. +Possible action: Refer the transaction to your customer support center for manual review. +. + +authcap.reason.code.207<< +Issuing bank unavailable. +Possible action: Wait a few minutes and resend the request. +. + +authcap.reason.code.208<< +Inactive card or card not authorized for card-not-present transactions. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.209<< +American Express Card Identification Digits (CID) did not match. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.210<< +The card has reached the credit limit. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.211<< +Invalid CVN. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.221<< +The customer matched an entry on the processor’s negative file. +Possible action: Review the order and contact the payment processor. +. + +authcap.reason.code.230<< +The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the CVN check. +Possible action: You can capture the authorization, but consider reviewing the order for the possibility of fraud. +. + +authcap.reason.code.231<< +Invalid account number. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.232<< +The card type is not accepted by the payment processor. +Possible action: Contact your merchant bank to confirm that your account is set up to receive the card in question. +. + +authcap.reason.code.233<< +General decline by the processor. +Possible action: Request a different card or other form of payment. +. + +authcap.reason.code.234<< +There is a problem with your CyberSource merchant configuration. +Possible action: Do not resend the request. Contact Customer Support to correct the configuration problem. +. + +authcap.reason.code.235<< +The requested amount exceeds the originally authorized amount. Occurs, for example, if you try to capture an amount larger than the original authorization amount. +Possible action: Issue a new authorization and capture request for the new amount. +. + +authcap.reason.code.236<< +Processor failure. +Possible action: Wait a few minutes and resend the request. +. + +authcap.reason.code.237<< +The authorization has already been reversed. +Possible action: No action required. +. + +authcap.reason.code.238<< +The authorization has already been captured. +Possible action: No action required. +. + +authcap.reason.code.239<< +The requested transaction amount must match the previous transaction amount. +Possible action: Correct the amount and resend the request. +. + +authcap.reason.code.240<< +The card type sent is invalid or does not correlate with the credit card number. +Possible action: Confirm that the card type correlates with the credit card number specified in the request, then resend the request. +. + +authcap.reason.code.241<< +The request ID is invalid. +Possible action: Request a new authorization, and if successful, proceed with the capture. +. + +authcap.reason.code.242<< +You requested a capture, but there is no corresponding, unused authorization record. Occurs if there was not a previously successful authorization request or if the previously successful authorization has already been used by another capture request. +Possible action: Request a new authorization, and if successful, proceed with the capture. +. + +authcap.reason.code.243<< +The transaction has already been settled or reversed. +Possible action: No action required. +. + +authcap.reason.code.246<< +The capture or credit is not voidable because the capture or credit information has already been submitted to your processor. Or, you requested a void for a type of transaction that cannot be voided. +Possible action: No action required. +. + +authcap.reason.code.247<< +You requested a credit for a capture that was previously voided. +Possible action: No action required. +. + +authcap.reason.code.250<< +Error: The request was received, but there was a timeout at the payment processor. +Possible action: To avoid duplicating the transaction, do not resend the request until you have reviewed the transaction status in the Business Center. +. + +authcap.reason.code.unknown=Unknown error, code [[code]] + birthday.text=Hey, [[user]], see which of your friends' [[link]] are coming up! LiveJournal keeps a list of their birthdays for you. bml.badcontent.body=We're sorry, but there was an error in the information you submitted. Please go back and try again. Modified: trunk/cgi-bin/LJ/Pay/Payment.pm =================================================================== --- trunk/cgi-bin/LJ/Pay/Payment.pm 2011-03-05 07:12:27 UTC (rev 10192) +++ trunk/cgi-bin/LJ/Pay/Payment.pm 2011-03-05 08:09:24 UTC (rev 10193) @@ -1250,13 +1250,14 @@ sub authcap_err_str { my $self = shift; my $rv = shift; + my $lang = shift; return 'unknown error' unless ref $rv; unless (%$rv) { - return "empty respons from transaction plugin"; + return "empty response from transaction plugin"; } - return { + my $old_text = { 1 => q{The security information from your card does not match the information you entered. Please go back and try again. Please note that a $1.00 charge may appear on your statement temporarily from the authorization attempt.}, 2 => q{Your card was not allowed by our card processor. Please try another card.}, 3 => q{The card number you entered is invalid. Please go back and re-enter your card number or try a different card. You may also want to contact your card issuer to see if there is a problem with your account.}, @@ -1274,6 +1275,13 @@ # failed request? ($rv->{req_status} eq 'fail' ? $rv->{req_status_str} : 'Success'); + + my $err_code = $rv->{req_status_code}; + my $err_text = LJ::Lang::get_text($lang, 'authcap.reason.code.' . $err_code, undef, undef); + $err_text ||= LJ::Lang::get_text($lang, 'authcap.reason.code.unknown', undef, { code => $err_code }); + + my $err_field = $rv->{req_error_field}; + return ($old_text, $err_text, $err_field); } sub authcap_is_success { Modified: trunk/cgi-bin/LJ/Pay/RecBill.pm =================================================================== --- trunk/cgi-bin/LJ/Pay/RecBill.pm 2011-03-05 07:12:27 UTC (rev 10192) +++ trunk/cgi-bin/LJ/Pay/RecBill.pm 2011-03-05 08:09:24 UTC (rev 10193) @@ -857,6 +857,7 @@ { my $s = @{$self->{items}||[]} > 1 ? 's' : ''; my $subject = "Payment Failure"; + my ($old_text, $err_text, $err_field) = LJ::Pay::Payment->authcap_err_str($retval, 'en'); my $msg = "An automatic payment attempt on your account, $u->{user}, " . "for \$" . sprintf("%.02f", $pmt->{amount}) . " USD to your " . @@ -865,7 +866,7 @@ "The card processor reported the following error:\n\n" . - " " . LJ::Pay::Payment->authcap_err_str($retval) . "\n\n" . + " $old_text\n\n" . "Since your scheduled payment has failed, automatic payments have been" . "turned off for your account. To reenroll in automatic payments with" . @@ -2256,9 +2257,9 @@ $$retry_flag = 1 if $trans->should_retry($rv); # save notes on this payment with the calculated error string - my $errstr = LJ::Pay::Payment->authcap_err_str($rv); - $pmt->payvar_set('last_status_str' => $errstr); - _debug("errstr=$errstr"); + my ($old_text, $err_text, $err_field) = LJ::Pay::Payment->authcap_err_str($rv, 'en'); + $pmt->payvar_set('last_status_str' => $old_text); + _debug("errstr=$old_text"); return $rv; } Modified: trunk/htdocs/admin/accounts/paidsearch.bml =================================================================== --- trunk/htdocs/admin/accounts/paidsearch.bml 2011-03-05 07:12:27 UTC (rev 10192) +++ trunk/htdocs/admin/accounts/paidsearch.bml 2011-03-05 08:09:24 UTC (rev 10193) @@ -76,16 +76,18 @@ ); my $bind = join(",", map { "?" } @acid); - # include payments tied to account codes either purchased by or used by the user (new payment system) - $sth = $dbh->prepare("SELECT pi.payid FROM acctpayitem p, payitems pi " . - "WHERE pi.piid=p.piid AND p.acid IN ($bind) LIMIT 5000"); - $sth->execute(@acid); - $matched{$_} = 1 while $_ = $sth->fetchrow_array; - - # include payments tied to account codes either purchased by or used by the user (new payment system) - $sth = $dbh->prepare("SELECT payid FROM acctpay WHERE acid IN ($bind) LIMIT 5000"); - $sth->execute(@acid); - $matched{$_} = 1 while $_ = $sth->fetchrow_array; + if ($bind) { + # include payments tied to account codes either purchased by or used by the user (new payment system) + $sth = $dbh->prepare("SELECT pi.payid FROM acctpayitem p, payitems pi " . + "WHERE pi.piid=p.piid AND p.acid IN ($bind) LIMIT 5000"); + $sth->execute(@acid); + $matched{$_} = 1 while $_ = $sth->fetchrow_array; + + # include payments tied to account codes either purchased by or used by the user (new payment system) + $sth = $dbh->prepare("SELECT payid FROM acctpay WHERE acid IN ($bind) LIMIT 5000"); + $sth->execute(@acid); + $matched{$_} = 1 while $_ = $sth->fetchrow_array; + } } } Modified: trunk/ssldocs/manage/account/cc.bml =================================================================== --- trunk/ssldocs/manage/account/cc.bml 2011-03-05 07:12:27 UTC (rev 10192) +++ trunk/ssldocs/manage/account/cc.bml 2011-03-05 08:09:24 UTC (rev 10193) @@ -77,7 +77,7 @@ my $now = time(); - my ($ret, $err, $err_field, $print_cc_form); + my ($ret, $err, $err_field, $print_cc_form, $old_err_text); # Sysban checks my $uniq = LJ::Request->notes('uniq'); @@ -139,8 +139,8 @@ return 1; } else { - $$err = BML::ml('.error.autherror', {'errormsg' => LJ::Pay::Payment->authcap_err_str($rv) || $ML{'.error.unknownautherror'}}); - + ($old_err_text, $$err, $err_field) = LJ::Pay::Payment->authcap_err_str($rv, BML::get_language()); + $print_cc_form = 1; return 0; } }; @@ -497,8 +497,9 @@ $pmt->set_mailed('Y'); } else { - my $errstr = LJ::Pay::Payment->authcap_err_str($rv); - $die->( $errstr, 1 ); + ($old_err_text, $err, $err_field) = LJ::Pay::Payment->authcap_err_str($rv, BML::get_language()); + $print_cc_form = 1; + $die->( $err, 1 ); } LJ::Pay::release_lock($u); Modified: trunk/ssldocs/pay/cc.bml =================================================================== --- trunk/ssldocs/pay/cc.bml 2011-03-05 07:12:27 UTC (rev 10192) +++ trunk/ssldocs/pay/cc.bml 2011-03-05 08:09:24 UTC (rev 10193) @@ -116,12 +116,34 @@ $ccform .= LJ::html_hidden("cart", $cart); $ccform .= LJ::html_hidden("amt_charge", $amt_charge); + + my $cc_form_return = sub { + my ($err, $err_field) = @_; + + $ccform .= "<span class='b-bubble b-bubble-warning' id='move_to_$err_field'><i class='i-bubble-arrow-border'></i><i class='i-bubble-arrow'></i>$err</span>"; + $ccform .= "<script type=\"text/javascript\">jQuery(function(){"; + $ccform .= "jQuery(\"#move_to_$err_field\").appendTo(jQuery(\"#ccform [name=$err_field]\").closest(\"li\")).show();"; + $ccform .= "});</script>"; + + $ccform .= LJ::Widget::CreditCard::render( LJ::Pay::RecBill->valid_countries, $err, \%POST, undef, + { + 'cvv2' => 1, + 'has_coppa' => $has_coppa, + } + ); + + $ccform .= "</form>"; + + $ret .= $ccform; + return $ret; + }; + my $email = $remote ? $remote->email_raw : " "; $email = $POST{email} || $email; ### POST: authorize/capture - my $err; + my ($err, $err_text, $err_field); if (LJ::did_post()) { my $dbh = LJ::get_db_writer(); my $no_charge = $ML{'.error.nocharge'}; @@ -509,23 +531,7 @@ # process credit card form fields my ($formerr, $err_field); unless (LJ::Widget::CreditCard::validate(\%POST, \$formerr, \$err_field) || $LJ::DEBUG{'no_cc_needed'}) { - - $ccform .= "<span class='b-bubble b-bubble-warning' id='move_to_$err_field'><i class='i-bubble-arrow-border'></i><i class='i-bubble-arrow'></i>$formerr</span>"; - $ccform .= "<script type=\"text/javascript\">jQuery(function(){"; - $ccform .= "jQuery(\"#move_to_$err_field\").appendTo(jQuery(\"#ccform [name=$err_field]\").closest(\"li\")).show();"; - $ccform .= "});</script>"; - - $ccform .= LJ::Widget::CreditCard::render( LJ::Pay::RecBill->valid_countries, $formerr, \%POST, undef, - { - 'cvv2' => 1, - 'has_coppa' => $has_coppa, - } - ); - - $ccform .= "</form>"; - - $ret .= $ccform; - return $ret; + return $cc_form_return->($formerr, $err_field); } # send fraud watch emails if necessary @@ -597,8 +603,10 @@ if ($coppa_only) { $capture{charge_amt} = 1.00; $rv = $cartobj->authorize ( %capture ); - return $error->(LJ::Pay::Payment->authcap_err_str($rv)) - unless LJ::Pay::Payment->authcap_is_success($rv) || $LJ::DEBUG{'no_cc_needed'}; + unless (LJ::Pay::Payment->authcap_is_success($rv) || $LJ::DEBUG{'no_cc_needed'}) { + my ($old_text, $err_text, $err_field) = LJ::Pay::Payment->authcap_err_str($rv, BML::get_language()); + return $cc_form_return->($err_text, $err_field); + } } elsif ($cartobj->get_amount() > 0) { $rv = eval { $cartobj->capture ( %capture ) }; return $error->($@) unless $rv; @@ -608,7 +616,8 @@ $complete_order->(); } else { my %done; my $emailtxt; - $err = LJ::Pay::Payment->authcap_err_str($rv); + ($err, $err_text, $err_field) = LJ::Pay::Payment->authcap_err_str($rv, BML::get_language()); + # $err is old message and will be 'en' in any case my @rcpts = map { [ $_->{'rcptid'}, $_->{'rcptemail'} ] } @{$cartobj->{'items'}}; push @rcpts, [ $remote->{userid}, $remote->email_raw ] if $cartobj->{userid}; @@ -676,9 +685,7 @@ if ($err) { $unlock->(); - return BML::ml('.error.cantprocesspayment', {'errormsg' => $err}) . - "<p>$ML{'.error.cantprocesspayment.fundsheld'}</p>" . - "<p>" . BML::ml('.error.cantprocesspayment.moreinfo', {'aopts' => "href='$LJ::SITEROOT/support/faqbrowse.bml?faqid=190'"}) . "</p>"; + return $cc_form_return->($err_text, $err_field); } # if the order amount is 0, mark this cart as free. this catches