+
+ my $gateway;
+
+ # use the gatewaynum specified by the record if possible
+ $gateway = FS::payment_gateway->by_key_with_namespace(
+ 'gatewaynum' => $record->gatewaynum,
+ ) if $record->gateway;
+
+ # otherwise use the cust agent gateway if possible (which realtime_refund_bop would do)
+ # otherwise just use default gateway
+ unless ($gateway) {
+
+ $gateway = $cust_main
+ ? $cust_main->agent->payment_gateway
+ : FS::payment_gateway->default_gateway;
+
+ # check for processor mismatch
+ unless ($table eq 'cust_pay_pending') { # has no processor table
+ if (my $processor = $record->processor) {
+
+ my $conf_processor = $gateway->gateway_module;
+ my %bop_options = $gateway->gatewaynum
+ ? $gateway->options
+ : @{ $gateway->get('options') };
+
+ # this is the same standard used by realtime_refund_bop
+ unless (
+ ($processor eq $conf_processor) ||
+ (($conf_processor eq 'CardFortress') && ($processor eq $bop_options{'gateway'}))
+ ) {
+
+ # processors don't match, so refund already cannot be run on this object,
+ # regardless of what we do now...
+ # but unless we gotta tokenize everything, just leave well enough alone
+ unless ($require_tokenized) {
+ warn "Skipping mismatched processor for $table ".$record->get($record->primary_key) if $debug;
+ next;
+ }
+ ### no error--we'll tokenize using the new gateway, just to remove stored payinfo,
+ ### because refunds are already impossible for this record, anyway
+
+ } # end processor mismatch
+
+ } # end record has processor
+ } # end not cust_pay_pending
+
+ }
+
+ # means no default gateway, no promise to tokenize, can skip
+ unless ($gateway) {
+ warn "Skipping missing gateway for $table ".$record->get($record->primary_key) if $debug;
+ next;
+ }
+
+ my $info = _token_check_gateway_info($cache,$gateway);
+ unless (ref($info)) {
+ # only throws error if Business::OnlinePayment won't load,
+ # which is just cause to abort this whole process, even if queue
+ $dbh->rollback if $oldAutoCommit;
+ die $info; # error message
+ }
+
+ # a configured gateway can't tokenize, move along
+ unless ($info->{'can_tokenize'}) {
+ warn "Skipping, cannot tokenize $table ".$record->get($record->primary_key) if $debug;
+ next;
+ }
+
+ warn "ATTEMPTING GATEWAY-ONLY TOKENIZE" if $debug && !$cust_main;
+
+ # if we got this far, time to mutex
+ $record->select_for_update;
+
+ # no clear record of name/address/etc used for transaction,
+ # but will load name/phone/id from customer if run as an object method,
+ # so we try that if we can
+ my %tokenopts = (
+ 'payment_gateway' => $gateway,
+ 'method' => 'CC',
+ 'payinfo' => $record->payinfo,
+ 'paydate' => $record->paydate,
+ );
+ my $error = $cust_main
+ ? $cust_main->realtime_tokenize(\%tokenopts)
+ : FS::cust_main::Billing_Realtime->realtime_tokenize(\%tokenopts);
+ if (FS::cust_main::Billing_Realtime->tokenized($tokenopts{'payinfo'})) { # implies no error
+ $record->payinfo($tokenopts{'payinfo'});
+ $error = $record->replace;
+ } else {
+ $error ||= 'Unknown error';
+ }