1 package FS::Cron::pay_batch;
4 use vars qw( @ISA @EXPORT_OK $me $DEBUG );
8 use FS::Record qw( qsearch qsearchs );
13 @ISA = qw( Exporter );
14 @EXPORT_OK = qw ( pay_batch_submit pay_batch_receive );
16 $me = '[FS::Cron::pay_batch]';
19 # -v: enable debugging
21 # -m: Experimental multi-process mode uses the job queue for multi-process and/or multi-machine billing.
22 # -r: Multi-process mode dry run option
23 # -a: Only process customers with the specified agentnum
26 my $conf = FS::Conf->new;
27 # returns a list of arrayrefs: [ gateway, payby, agentnum ]
30 if ( $conf->exists('batch-spoolagent') ) {
32 @agentnums = split(',', $opt{a});
34 @agentnums = map { $_->agentnum } qsearch('agent');
39 warn "Payment batch processing skipped in per-agent mode.\n" if $DEBUG;
44 foreach my $agentnum (@agentnums) {
46 foreach my $payby ('CARD', 'CHEK') {
47 my $gatewaynum = $conf->config("batch-gateway-$payby", $agentnum);
49 my $gateway = FS::payment_gateway->by_key($gatewaynum)
50 or die "payment_gateway '$gatewaynum' not found\n";
51 push @return, [ $gateway, $payby, $agentnum ];
57 sub pay_batch_submit {
59 local $DEBUG = ($opt{l} || 1) if $opt{v};
60 # if anything goes wrong, don't try to roll back previously submitted batches
61 local $FS::UID::AutoCommit = 1;
65 warn "$me batch_submit\n" if $DEBUG;
66 foreach my $config (batch_gateways(%opt)) {
67 my ($gateway, $payby, $agentnum) = @$config;
68 if ( $gateway->batch_processor->can('default_transport') ) {
70 my $search = { status => 'O', payby => $payby };
71 $search->{agentnum} = $agentnum if $agentnum;
73 foreach my $pay_batch ( qsearch('pay_batch', $search) ) {
75 warn "Exporting batch ".$pay_batch->batchnum."\n" if $DEBUG;
76 eval { $pay_batch->export_to_gateway( $gateway, debug => $DEBUG ); };
79 # warn the error and continue. rolling back the transaction once
80 # we've started sending batches is bad.
81 warn "error submitting batch ".$pay_batch->batchnum." to gateway '".
82 $gateway->label."': $@\n";
86 } else { #can't(default_transport)
87 warn "Payment gateway '".$gateway->label.
88 "' doesn't support automatic transport; skipped.\n";
95 sub pay_batch_receive {
97 local $DEBUG = ($opt{l} || 1) if $opt{v};
98 local $FS::UID::AutoCommit = 0;
103 warn "$me batch_receive\n" if $DEBUG;
106 # If a gateway is selected for more than one payby+agentnum, still
107 # only import from it once; we expect it will send back multiple
109 foreach my $config (batch_gateways(%opt)) {
110 my ($gateway, $payby, $agentnum) = @$config;
111 next if $gateway_done{$gateway->gatewaynum};
112 next unless $gateway->batch_processor->can('default_transport');
113 # already warned about this above
114 warn "Importing results from '".$gateway->label."'\n" if $DEBUG;
115 # Note that import_from_gateway is not agent-limited; if a gateway
116 # returns results for batches not associated with this agent, we will
117 # still accept them. Well-behaved gateways will not do that.
119 FS::pay_batch->import_from_gateway( gateway =>$gateway, debug => $DEBUG )
122 # this we can roll back
124 die "error receiving from gateway '".$gateway->label."':\n$error\n";
128 # resolve batches if we can
129 foreach my $pay_batch (qsearch('pay_batch', { status => 'I' })) {
130 warn "Trying to resolve batch ".$pay_batch->batchnum."\n" if $DEBUG;
131 $error = $pay_batch->try_to_resolve;
134 die "unable to resolve batch ".$pay_batch->batchnum.":\n$error\n";