[freeside-commits] freeside/FS/FS Conf.pm, 1.265, 1.265.2.1 Schema.pm, 1.126, 1.126.2.1 agent.pm, 1.18, 1.18.2.1 cust_main.pm, 1.408, 1.408.2.1 cust_pay_pending.pm, 1.6, 1.6.2.1 cust_pkg.pm, 1.116, 1.116.2.1 payby.pm, 1.14, 1.14.2.1 payment_gateway.pm, 1.2, 1.2.2.1
Jeff Finucane,420,,
jeff at wavetail.420.am
Sun Mar 8 20:51:11 PDT 2009
Update of /home/cvs/cvsroot/freeside/FS/FS
In directory wavetail.420.am:/tmp/cvs-serv17014/FS/FS
Modified Files:
Tag: webpay_support_branch
Conf.pm Schema.pm agent.pm cust_main.pm cust_pay_pending.pm
cust_pkg.pm payby.pm payment_gateway.pm
Log Message:
webpay support #4103
Index: Conf.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Conf.pm,v
retrieving revision 1.265
retrieving revision 1.265.2.1
diff -u -d -r1.265 -r1.265.2.1
--- Conf.pm 2 Mar 2009 04:58:09 -0000 1.265
+++ Conf.pm 9 Mar 2009 03:51:09 -0000 1.265.2.1
@@ -8,6 +8,7 @@
use FS::ConfItem;
use FS::ConfDefaults;
use FS::Conf_compat17;
+use FS::payby;
use FS::conf;
use FS::Record qw(qsearch qsearchs);
use FS::UID qw(dbh datasrc use_confcompat);
@@ -620,6 +621,17 @@
},
{
+ 'key' => 'business-onlinepayment-namespace',
+ 'section' => 'billing',
+ 'description' => 'Specifies which perl module namespace (which group of collection routines) is used by default.',
+ 'type' => 'select',
+ 'select_hash' => [
+ 'Business::OnlinePayment' => 'Direct API (Business::OnlinePayment)',
+ 'Business::OnlineThirdPartyPayment' => 'Web API (Business::ThirdPartyPayment)',
+ ],
+ },
+
+ {
'key' => 'business-onlinepayment-description',
'section' => 'billing',
'description' => 'String passed as the description field to <a href="http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment">Business::OnlinePayment</a>. Evaluated as a double-quoted perl string, with the following variables available: <code>$agent</code> (the agent name), and <code>$pkgs</code> (a comma-separated list of packages for which these charges apply)',
Index: payby.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/payby.pm,v
retrieving revision 1.14
retrieving revision 1.14.2.1
diff -u -d -r1.14 -r1.14.2.1
--- payby.pm 3 Sep 2008 01:46:12 -0000 1.14
+++ payby.pm 9 Mar 2009 03:51:09 -0000 1.14.2.1
@@ -48,28 +48,33 @@
tinyname => 'card',
shortname => 'Credit card',
longname => 'Credit card (automatic)',
+ realtime => 1,
},
'DCRD' => {
tinyname => 'card',
shortname => 'Credit card',
longname => 'Credit card (on-demand)',
cust_pay => 'CARD', #this is a customer type only, payments are CARD...
+ realtime => 1,
},
'CHEK' => {
tinyname => 'check',
shortname => 'Electronic check',
longname => 'Electronic check (automatic)',
+ realtime => 1,
},
'DCHK' => {
tinyname => 'check',
shortname => 'Electronic check',
longname => 'Electronic check (on-demand)',
cust_pay => 'CHEK', #this is a customer type only, payments are CHEK...
+ realtime => 1,
},
'LECB' => {
tinyname => 'phone bill',
shortname => 'Phone bill billing',
longname => 'Phone bill billing',
+ realtime => 1,
},
'BILL' => {
tinyname => 'billing',
@@ -131,6 +136,15 @@
return 1;
}
+sub realtime { # can use realtime payment facilities
+ my( $self, $payby ) = @_;
+
+ return 0 unless $hash{$payby};
+ return 0 unless exists( $hash{$payby}->{realtime} );
+
+ return $hash{$payby}->{realtime};
+}
+
sub payby2longname {
my $self = shift;
map { $_ => $hash{$_}->{longname} } $self->payby;
@@ -157,6 +171,7 @@
%payby2bop = (
'CARD' => 'CC',
'CHEK' => 'ECHECK',
+ 'MCRD' => 'CC',
);
sub payby2bop {
Index: payment_gateway.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/payment_gateway.pm,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -d -r1.2 -r1.2.2.1
--- payment_gateway.pm 2 Mar 2008 01:31:38 -0000 1.2
+++ payment_gateway.pm 9 Mar 2009 03:51:09 -0000 1.2.2.1
@@ -1,12 +1,14 @@
package FS::payment_gateway;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $me $DEBUG );
use FS::Record qw( qsearch qsearchs dbh );
use FS::option_Common;
use FS::agent_payment_gateway;
@ISA = qw( FS::option_Common );
+$me = '[ FS::payment_gateway ]';
+$DEBUG=0;
=head1 NAME
@@ -37,6 +39,8 @@
=item gatewaynum - primary key
+=item gateway_namespace - Business::OnlinePayment or Business::OnlineThirdPartyPayment
+
=item gateway_module - Business::OnlinePayment:: module name
=item gateway_username - payment gateway username
@@ -110,8 +114,12 @@
my $error =
$self->ut_numbern('gatewaynum')
|| $self->ut_alpha('gateway_module')
+ || $self->ut_enum('gateway_namespace', ['Business::OnlinePayment',
+ 'Business::OnlineThirdPartyPayment',
+ ] )
|| $self->ut_textn('gateway_username')
|| $self->ut_anything('gateway_password')
+ || $self->ut_textn('gateway_callback_url') # a bit too permissive
|| $self->ut_enum('disabled', [ '', 'Y' ] )
#|| $self->ut_textn('gateway_action')
;
@@ -131,6 +139,10 @@
$self->gateway_action('Normal Authorization');
}
+ # this little kludge mimics FS::CGI::popurl
+ $self->gateway_callback_url($self->gateway_callback_url. '/')
+ if ( $self->gateway_callback_url && $self->gateway_callback_url !~ /\/$/ );
+
$self->SUPER::check;
}
@@ -186,6 +198,41 @@
}
+=item namespace_description
+
+returns a friendly name for the namespace
+
+=cut
+
+my %namespace2description = (
+ '' => 'Direct',
+ 'Business::OnlinePayment' => 'Direct',
+ 'Business::OnlineThirdPartyPayment' => 'Hosted',
+);
+
+sub namespace_description {
+ $namespace2description{shift->gateway_namespace} || 'Unknown';
+}
+
+# _upgrade_data
+#
+# Used by FS::Upgrade to migrate to a new database.
+#
+#
+
+sub _upgrade_data {
+ my ($class, %opts) = @_;
+ my $dbh = dbh;
+
+ warn "$me upgrading $class\n" if $DEBUG;
+
+ foreach ( qsearch( 'payment_gateway', { 'gateway_namespace' => '' } ) ) {
+ $_->gateway_namespace('Business::OnlinePayment'); #defaulting
+ my $error = $_->replace;
+ die "$class had error during upgrade replacement: $error" if $error;
+ }
+}
+
=back
=head1 BUGS
Index: cust_pkg.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_pkg.pm,v
retrieving revision 1.116
retrieving revision 1.116.2.1
diff -u -d -r1.116 -r1.116.2.1
--- cust_pkg.pm 22 Feb 2009 10:34:26 -0000 1.116
+++ cust_pkg.pm 9 Mar 2009 03:51:09 -0000 1.116.2.1
@@ -439,9 +439,7 @@
sub check {
my $self = shift;
- $self->locationnum('')
- if defined($self->locationnum) && length($self->locationnum)
- && ( $self->locationnum == 0 || $self->locationnum == -1 );
+ $self->locationnum('') if !$self->locationnum || $self->locationnum == -1;
my $error =
$self->ut_numbern('pkgnum')
Index: agent.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/agent.pm,v
retrieving revision 1.18
retrieving revision 1.18.2.1
diff -u -d -r1.18 -r1.18.2.1
--- agent.pm 13 Nov 2008 02:22:03 -0000 1.18
+++ agent.pm 9 Mar 2009 03:51:09 -0000 1.18.2.1
@@ -3,12 +3,14 @@
use strict;
use vars qw( @ISA );
#use Crypt::YAPassGen;
+use Business::CreditCard 0.28;
use FS::Record qw( dbh qsearch qsearchs );
use FS::cust_main;
use FS::cust_pkg;
use FS::agent_type;
use FS::reg_code;
use FS::TicketSystem;
+use FS::Conf;
@ISA = qw( FS::m2m_Common FS::Record );
@@ -200,6 +202,106 @@
FS::TicketSystem->queue($self->ticketing_queueid);
};
+=item payment_gateway [ OPTION => VALUE, ... ]
+
+Returns a payment gateway object (see L<FS::payment_gateway>) for this agent.
+
+Currently available options are I<invnum>, I<method>, and I<payinfo>.
+
+If I<invnum> is set to the number of an invoice (see L<FS::cust_bill>) then
+an attempt will be made to select a gateway suited for the taxes paid on
+the invoice.
+
+The I<method> and I<payinfo> options can be used to influence the choice
+as well. Presently only 'CC' and 'ECHECK' methods are meaningful.
+
+When the I<method> is 'CC' then the card number in I<payinfo> can direct
+this routine to route to a gateway suited for that type of card.
+
+=cut
+
+sub payment_gateway {
+ my ( $self, %options ) = @_;
+
+ my $taxclass = '';
+ if ( $options{invnum} ) {
+ my $cust_bill = qsearchs('cust_bill', { 'invnum' => $options{invnum} } );
+ die "invnum ". $options{'invnum'}. " not found" unless $cust_bill;
+ my @taxclasses =
+ map { $_->part_pkg->taxclass }
+ grep { $_ }
+ map { $_->cust_pkg }
+ $cust_bill->cust_bill_pkg;
+ unless ( grep { $taxclasses[0] ne $_ } @taxclasses ) { #unless there are
+ #different taxclasses $taxclass = $taxclasses[0];
+ }
+ }
+
+ #look for an agent gateway override first
+ my $cardtype;
+ if ( $options{method} && $options{method} eq 'CC' ) {
+ $cardtype = cardtype($options{payinfo});
+ } elsif ( $options{method} && $options{method} eq 'ECHECK' ) {
+ $cardtype = 'ACH';
+ } else {
+ $cardtype = $options{method} || '';
+ }
+
+ my $override =
+ qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => $cardtype,
+ taxclass => $taxclass, } )
+ || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => '',
+ taxclass => $taxclass, } )
+ || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => $cardtype,
+ taxclass => '', } )
+ || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => '',
+ taxclass => '', } );
+
+ my $payment_gateway = new FS::payment_gateway;
+ if ( $override ) { #use a payment gateway override
+
+ $payment_gateway = $override->payment_gateway;
+
+ } else { #use the standard settings from the config
+ # the standard settings from the config could be moved to a null agent
+ # agent_payment_gateway referenced payment_gateway
+
+ my $conf = new FS::Conf;
+ die "Real-time processing not enabled\n"
+ unless $conf->exists('business-onlinepayment');
+
+ #load up config
+ my $bop_config = 'business-onlinepayment';
+ $bop_config .= '-ach'
+ if ( $options{method}
+ && $options{method} =~ /^(ECHECK|CHEK)$/
+ && $conf->exists($bop_config. '-ach')
+ );
+ my ( $processor, $login, $password, $action, @bop_options ) =
+ $conf->config($bop_config);
+ $action ||= 'normal authorization';
+ pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/;
+ die "No real-time processor is enabled - ".
+ "did you set the business-onlinepayment configuration value?\n"
+ unless $processor;
+
+ $payment_gateway->gateway_namespace( $conf->config('business-onlinepayment-namespace') ||
+ 'Business::OnlinePayment');
+ $payment_gateway->gateway_module($processor);
+ $payment_gateway->gateway_username($login);
+ $payment_gateway->gateway_password($password);
+ $payment_gateway->gateway_action($action);
+ $payment_gateway->set('options', [ @bop_options ]);
+
+ }
+
+ $payment_gateway;
+}
+
=item num_prospect_cust_main
Returns the number of prospects (customers with no packages ever ordered) for
Index: cust_main.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_main.pm,v
retrieving revision 1.408
retrieving revision 1.408.2.1
diff -u -d -r1.408 -r1.408.2.1
--- cust_main.pm 17 Feb 2009 02:01:59 -0000 1.408
+++ cust_main.pm 9 Mar 2009 03:51:09 -0000 1.408.2.1
@@ -3368,15 +3368,23 @@
}
-=item realtime_bop METHOD AMOUNT [ OPTION => VALUE ... ]
+=item realtime_collect [ OPTION => VALUE ... ]
Runs a realtime credit card, ACH (electronic check) or phone bill transaction
-via a Business::OnlinePayment realtime gateway. See
-L<http://420.am/business-onlinepayment> for supported gateways.
+via a Business::OnlinePayment or Business::OnlineThirdPartyPayment realtime
+gateway. See L<http://420.am/business-onlinepayment> and
[...1134 lines suppressed...]
unless $refund->is_success();
- my %method2payby = (
- 'CC' => 'CARD',
- 'ECHECK' => 'CHEK',
- 'LEC' => 'LECB',
- );
-
my $paybatch = "$processor:". $refund->authorization;
$paybatch .= ':'. $refund->order_number
if $refund->can('order_number') && $refund->order_number;
@@ -4349,7 +4604,7 @@
'paynum' => $options{'paynum'},
'refund' => $amount,
'_date' => '',
- 'payby' => $method2payby{$method},
+ 'payby' => $bop_method2payby{$options{method}},
'payinfo' => $payinfo,
'paybatch' => $paybatch,
'reason' => $options{'reason'} || 'card or ACH refund',
Index: Schema.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Schema.pm,v
retrieving revision 1.126
retrieving revision 1.126.2.1
diff -u -d -r1.126 -r1.126.2.1
--- Schema.pm 2 Mar 2009 08:50:01 -0000 1.126
+++ Schema.pm 9 Mar 2009 03:51:09 -0000 1.126.2.1
@@ -845,10 +845,12 @@
'payunique', 'varchar', 'NULL', $char_d, '', '', #separate paybatch "unique" functions from current usage
'status', 'varchar', '', $char_d, '', '',
+ 'session_id', 'varchar', 'NULL', $char_d, '', '', #only need 32
'statustext', 'text', 'NULL', '', '', '',
'gatewaynum', 'int', 'NULL', '', '', '',
#'cust_balance', @money_type, '', '',
'paynum', 'int', 'NULL', '', '', '',
+ 'jobnum', 'int', 'NULL', '', '', '',
],
'primary_key' => 'paypendingnum',
'unique' => [ [ 'payunique' ] ],
@@ -1857,10 +1859,12 @@
'payment_gateway' => {
'columns' => [
'gatewaynum', 'serial', '', '', '', '',
+ 'gateway_namespace','varchar', 'NULL', $char_d, '', '',
'gateway_module', 'varchar', '', $char_d, '', '',
'gateway_username', 'varchar', 'NULL', $char_d, '', '',
'gateway_password', 'varchar', 'NULL', $char_d, '', '',
'gateway_action', 'varchar', 'NULL', $char_d, '', '',
+ 'gateway_callback_url', 'varchar', 'NULL', $char_d, '', '',
'disabled', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'gatewaynum',
Index: cust_pay_pending.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_pay_pending.pm,v
retrieving revision 1.6
retrieving revision 1.6.2.1
diff -u -d -r1.6 -r1.6.2.1
--- cust_pay_pending.pm 16 Feb 2009 23:54:37 -0000 1.6
+++ cust_pay_pending.pm 9 Mar 2009 03:51:09 -0000 1.6.2.1
@@ -191,6 +191,7 @@
#|| $self->ut_textn('statustext')
|| $self->ut_anything('statustext')
#|| $self->ut_money('cust_balance')
+ || $self->ut_hexn('session_id')
|| $self->ut_foreign_keyn('paynum', 'cust_pay', 'paynum' )
|| $self->payinfo_check() #payby/payinfo/paymask/paydate
;
@@ -215,6 +216,18 @@
$self->SUPER::check;
}
+=item cust_main
+
+Returns the associated L<FS::cust_main> record if any. Otherwise returns false.
+
+=cut
+
+sub cust_main {
+ my $self = shift;
+ qsearchs('cust_main', { custnum => $self->custnum } );
+}
+
+
#these two are kind-of false laziness w/cust_main::realtime_bop
#(currently only used when resolving pending payments manually)
More information about the freeside-commits
mailing list