From 6995be2fb5e8c9a07b38c0bb8976a10a9381fc90 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Wed, 28 Oct 2015 11:24:27 -0700 Subject: restore ckeditor, RT#18830, RT#34331 --- .../ckeditor/plugins/blockprotect/plugin.js | 139 +++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 httemplate/elements/ckeditor/plugins/blockprotect/plugin.js diff --git a/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js b/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js new file mode 100644 index 000000000..e4ef39167 --- /dev/null +++ b/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js @@ -0,0 +1,139 @@ +/** + * The "blockprotect" plugin. Adapted from the "placeholder" plugin. + */ + +(function() { + var delim_o = '{'; + var delim_c = '}'; + + var create_block = function(content, inside) { + if (inside) return content; + // fix nbsp's + content = content.replace(/ /gi, ' '); + // escape the content + var el = document.createElement('SPAN'); + // IE8 compat + if( typeof(el.textContent) != 'undefined' ) { + el.textContent = content; + } else if( typeof(el.innerText) != 'undefined' ) { + el.innerText = content; + } + el.setAttribute('class', 'cke_blockprotect'); + return el.outerHTML; + }; + var block_writeHtml = function( element ) { + // to unescape the element contents, write it out as HTML, + // stick that into a SPAN element, and then extract the text + // content of that. + var inner_writer = new CKEDITOR.htmlParser.basicWriter; + element.writeChildrenHtml(inner_writer); + + var el = document.createElement('SPAN'); + el.innerHTML = inner_writer.getHtml(); + if( typeof(el.textContent) != 'undefined' ) { + return el.textContent; + } else if( typeof(el.innerText) != 'undefined' ) { + return el.innerText; + } + }; + var to_protected_html = function(data) { + var depth = 0; + var chunk = ''; + var out = ''; + var in_tag = false; + var p = 0; // position in the string + while( 1 ) { + // find the next delimiter of either kind + var i = data.indexOf(delim_o, p); + var j = data.indexOf(delim_c, p); + if (i == -1 && j == -1) { + // then there are no more delimiters + break; + } else if ((i < j || j == -1) && i != -1) { + // next delimiter is an open + // push everything from current position to + // the delimiter + if ( i > p ) chunk += data.substr(p, i - p); + p = i + 1; + if ( depth == 0 ) { + // we're in document text. find whether an HTML tag starts, + // or ends, before the next delimiter, so that we know whether + // to output the next block in a SPAN or just as escaped text + for(var q = 0; q < chunk.length; q++ ) { + if (chunk[q] == '<') in_tag = true; + if (chunk[q] == '>') in_tag = false; + } + + // then output the chunk, and go to the start of the + // protected block + out += chunk; + chunk = ''; + } + chunk += delim_o; + depth++; + } else if ((j < i || i == -1) && j != -1) { + // next delimiter is a close + if ( j > p ) chunk += data.substr(p, j - p); + p = j + 1; + depth--; + chunk += delim_c; + if ( depth == 0 ) { + // end of a protected block + out += create_block(chunk, in_tag); + chunk = ''; + } else if ( depth < 0 ) { + depth = 0; + } + } else { + // can't happen + } + } + // append any text after the last delimiter + if ( depth ) { + out += create_block(data.substr(p), in_tag); + } else { + out += data.substr(p); + } + return out; + }; + + CKEDITOR.plugins.add( 'blockprotect', { + afterInit: function( editor ) { + CKEDITOR.addCss( '.cke_blockprotect' + + '{' + + 'background-color: #ffff88;' + + ( CKEDITOR.env.gecko ? 'cursor: default;' : '' ) + + '}' + ); + + // keep these from getting stripped out + editor.filter.allow('span(cke_blockprotect)', + 'blockprotect', true); + + // add filter at the front of toHtml + editor.on( 'toHtml', + function( evt ) { + evt.data.dataValue = + to_protected_html(evt.data.dataValue); + return evt; + }, + this, null, 0 + ); + + editor.dataProcessor.htmlFilter.addRules({ + elements: { + span: function( element ) { + if ( element.className = 'cke_blockprotect' ) { + // defeat HTML escaping + var content = block_writeHtml(element); + element.writeHtml = function(writer, filter) { + writer.text(content); + } + } + } // span function + } // elements + }); + } + }); // plugins.add +}) (); + -- cgit v1.2.1 From 42e6fdc16b285430d50607489aa3e1394fafbc16 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Wed, 28 Oct 2015 14:28:38 -0700 Subject: fix week expand / collapse images under RT 4.2, RT#34237, RT#13852 --- Makefile | 3 ++- debian/rules | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3af5da812..91b14b8a8 100644 --- a/Makefile +++ b/Makefile @@ -117,7 +117,7 @@ FREESIDE_URL = "http://localhost/freeside/" #for now, same db as specified in DATASOURCE... eventually, otherwise? RT_DB_DATABASE = freeside -TORRUS_ENABLED = 0 +TORRUS_ENABLED = 1 # for auto-version updates, so we can "make release" more things automatically RPM_SPECFILE = rpm/freeside.spec @@ -400,6 +400,7 @@ create-rt: configure-rt install-rt: if [ ${RT_ENABLED} -eq 1 ]; then ( cd rt; make install ); fi + if [ ${RT_ENABLED} -eq 1 ]; then cp -r ${RT_PATH}/share/static/images ${FREESIDE_DOCUMENT_ROOT}/rt/NoAuth/ ;fi if [ ${RT_ENABLED} -eq 1 ]; then perl -p -i -e "\ s'%%%RT_DOMAIN%%%'${RT_DOMAIN}'g;\ s'%%%RT_TIMEZONE%%%'${RT_TIMEZONE}'g;\ diff --git a/debian/rules b/debian/rules index a7f2b72d0..e7f5bd8a0 100755 --- a/debian/rules +++ b/debian/rules @@ -266,6 +266,7 @@ install-stamp: build-stamp install -d $(RT_PATH)/share ( cd rt; $(MAKE) config-install dirs files-install fixperms instruct ) + cp -r ${RT_PATH}/share/static/images ${FREESIDE_DOCUMENT_ROOT}/rt/NoAuth/ ##hack the build dir out of RT. yeah, sucky. -- cgit v1.2.1 From 96b046470a55b011ad7a6610f36f2bd68504de6f Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Wed, 28 Oct 2015 14:41:02 -0700 Subject: RT 4.2: fix ckeditor icons, RT#13852 --- rt/share/static/RichText/skins/kama/icons.png | Bin 0 -> 13244 bytes .../static/RichText/skins/kama/images/dialog_sides.gif | Bin 0 -> 48 bytes .../static/RichText/skins/kama/images/dialog_sides.png | Bin 0 -> 178 bytes .../RichText/skins/kama/images/dialog_sides_rtl.png | Bin 0 -> 181 bytes rt/share/static/RichText/skins/kama/images/mini.gif | Bin 0 -> 183 bytes rt/share/static/RichText/skins/kama/images/sprites.png | Bin 0 -> 7086 bytes .../static/RichText/skins/kama/images/sprites_ie6.png | Bin 0 -> 2724 bytes .../static/RichText/skins/kama/images/toolbar_start.gif | Bin 0 -> 105 bytes 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 rt/share/static/RichText/skins/kama/icons.png create mode 100644 rt/share/static/RichText/skins/kama/images/dialog_sides.gif create mode 100644 rt/share/static/RichText/skins/kama/images/dialog_sides.png create mode 100644 rt/share/static/RichText/skins/kama/images/dialog_sides_rtl.png create mode 100644 rt/share/static/RichText/skins/kama/images/mini.gif create mode 100644 rt/share/static/RichText/skins/kama/images/sprites.png create mode 100644 rt/share/static/RichText/skins/kama/images/sprites_ie6.png create mode 100644 rt/share/static/RichText/skins/kama/images/toolbar_start.gif diff --git a/rt/share/static/RichText/skins/kama/icons.png b/rt/share/static/RichText/skins/kama/icons.png new file mode 100644 index 000000000..a2a385773 Binary files /dev/null and b/rt/share/static/RichText/skins/kama/icons.png differ diff --git a/rt/share/static/RichText/skins/kama/images/dialog_sides.gif b/rt/share/static/RichText/skins/kama/images/dialog_sides.gif new file mode 100644 index 000000000..8f91b4753 Binary files /dev/null and b/rt/share/static/RichText/skins/kama/images/dialog_sides.gif differ diff --git a/rt/share/static/RichText/skins/kama/images/dialog_sides.png b/rt/share/static/RichText/skins/kama/images/dialog_sides.png new file mode 100644 index 000000000..1042a61cf Binary files /dev/null and b/rt/share/static/RichText/skins/kama/images/dialog_sides.png differ diff --git a/rt/share/static/RichText/skins/kama/images/dialog_sides_rtl.png b/rt/share/static/RichText/skins/kama/images/dialog_sides_rtl.png new file mode 100644 index 000000000..d7f7b49fc Binary files /dev/null and b/rt/share/static/RichText/skins/kama/images/dialog_sides_rtl.png differ diff --git a/rt/share/static/RichText/skins/kama/images/mini.gif b/rt/share/static/RichText/skins/kama/images/mini.gif new file mode 100644 index 000000000..54d910741 Binary files /dev/null and b/rt/share/static/RichText/skins/kama/images/mini.gif differ diff --git a/rt/share/static/RichText/skins/kama/images/sprites.png b/rt/share/static/RichText/skins/kama/images/sprites.png new file mode 100644 index 000000000..0cb4e1c6c Binary files /dev/null and b/rt/share/static/RichText/skins/kama/images/sprites.png differ diff --git a/rt/share/static/RichText/skins/kama/images/sprites_ie6.png b/rt/share/static/RichText/skins/kama/images/sprites_ie6.png new file mode 100644 index 000000000..5bb305c8d Binary files /dev/null and b/rt/share/static/RichText/skins/kama/images/sprites_ie6.png differ diff --git a/rt/share/static/RichText/skins/kama/images/toolbar_start.gif b/rt/share/static/RichText/skins/kama/images/toolbar_start.gif new file mode 100644 index 000000000..1774246c2 Binary files /dev/null and b/rt/share/static/RichText/skins/kama/images/toolbar_start.gif differ -- cgit v1.2.1 From 31dfca5cd65c92b9dce0af6d41db394b17ac0bf4 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Wed, 28 Oct 2015 22:12:48 -0500 Subject: RT#38533: One click re-send refund,payment receipt, invoice [changed link text] --- httemplate/view/cust_main/payment_history/invoice.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/httemplate/view/cust_main/payment_history/invoice.html b/httemplate/view/cust_main/payment_history/invoice.html index 058da5463..613936e00 100644 --- a/httemplate/view/cust_main/payment_history/invoice.html +++ b/httemplate/view/cust_main/payment_history/invoice.html @@ -35,12 +35,12 @@ if ( $cust_bill->closed !~ /^Y/i && $opt{'Void invoices'} ) { } my $email = ($opt{'has_email_address'} && $opt{'Resend invoices'}) ? - q! (invnum. - q!','Email Invoice Receipt')" TITLE="Send email receipt">email receipt)! + q!','Email Invoice Receipt')" TITLE="Send email invoice">email invoice)! : ''; my $events = ''; -- cgit v1.2.1 From 1598480a192e9a056834d636fbd7de7ae00dead6 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 29 Oct 2015 10:52:04 -0700 Subject: fix appointments vs. no direct elements/ access, RT#34237, RT#23357 --- httemplate/elements/make_appointment.html | 39 ---------------------- .../elements/popup_link-make_appointment.html | 2 +- httemplate/misc/make_appointment.html | 39 ++++++++++++++++++++++ httemplate/view/cust_main/menu.html | 2 +- 4 files changed, 41 insertions(+), 41 deletions(-) delete mode 100644 httemplate/elements/make_appointment.html create mode 100644 httemplate/misc/make_appointment.html diff --git a/httemplate/elements/make_appointment.html b/httemplate/elements/make_appointment.html deleted file mode 100644 index ddf377f54..000000000 --- a/httemplate/elements/make_appointment.html +++ /dev/null @@ -1,39 +0,0 @@ -<& /elements/header-popup.html &> - -% #XXX actually, the action needs to repace the top-level window with this -% #$params->{'action'} = $p. 'rt/Search/Schedule.html?'. $query; -
- - - -% my @sched_item = qsearch('sched_item', { 'disabled' => '', }); -% my @username = map $_->access_user->username, @sched_item; -% foreach my $username (@username) { - -% } - -Length: - -
-
- - - -
- -<& /elements/footer-popup.html &> -<%init> - -my $default_length = FS::Conf->new->config('default_appointment_length') || 180; - -#XXX '&pkgnum=$pkgnum";need to be for specific package/location, not just for a customer... default to active(/ordered) package in a pkg_class w/ticketing_queueid, otherwise, a popup? (well, we're already a popup now) we're getting complicated like form-creat_ticket.html - - - diff --git a/httemplate/elements/popup_link-make_appointment.html b/httemplate/elements/popup_link-make_appointment.html index 60a337c04..3a8d37a8c 100644 --- a/httemplate/elements/popup_link-make_appointment.html +++ b/httemplate/elements/popup_link-make_appointment.html @@ -26,6 +26,6 @@ $params->{'actionlabel'} ||= 'Schedule appointment'; #$params->{'width'} ||= 350; #$params->{'height'} ||= 220; -$params->{'action'} = $p. '/elements/make_appointment.html?custnum='. $params->{'custnum'}; +$params->{'action'} = $p. 'misc/make_appointment.html?custnum='. $params->{'custnum'}; diff --git a/httemplate/misc/make_appointment.html b/httemplate/misc/make_appointment.html new file mode 100644 index 000000000..ddf377f54 --- /dev/null +++ b/httemplate/misc/make_appointment.html @@ -0,0 +1,39 @@ +<& /elements/header-popup.html &> + +% #XXX actually, the action needs to repace the top-level window with this +% #$params->{'action'} = $p. 'rt/Search/Schedule.html?'. $query; +
+ + + +% my @sched_item = qsearch('sched_item', { 'disabled' => '', }); +% my @username = map $_->access_user->username, @sched_item; +% foreach my $username (@username) { + +% } + +Length: + +
+
+ + + +
+ +<& /elements/footer-popup.html &> +<%init> + +my $default_length = FS::Conf->new->config('default_appointment_length') || 180; + +#XXX '&pkgnum=$pkgnum";need to be for specific package/location, not just for a customer... default to active(/ordered) package in a pkg_class w/ticketing_queueid, otherwise, a popup? (well, we're already a popup now) we're getting complicated like form-creat_ticket.html + + + diff --git a/httemplate/view/cust_main/menu.html b/httemplate/view/cust_main/menu.html index b8740635d..ab2d69d34 100644 --- a/httemplate/view/cust_main/menu.html +++ b/httemplate/view/cust_main/menu.html @@ -317,7 +317,7 @@ my @menu = ( label => 'Schedule new appointment', confexists => 'ticket_system', acl => 'Make appointment', - popup => "elements/make_appointment.html?custnum=$custnum", + popup => "misc/make_appointment.html?custnum=$custnum", actionlabel => 'Schedule appointment', }, ], -- cgit v1.2.1 From bfff7e209a89e413eac7de2dd0958c184717fbf0 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 29 Oct 2015 10:57:58 -0700 Subject: fix appointments vs. no direct elements/ access, RT#34237, RT#23357 --- httemplate/elements/schedule-appointment.html | 21 --------------------- httemplate/misc/schedule-appointment.html | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 httemplate/elements/schedule-appointment.html create mode 100644 httemplate/misc/schedule-appointment.html diff --git a/httemplate/elements/schedule-appointment.html b/httemplate/elements/schedule-appointment.html deleted file mode 100644 index 69b9f422b..000000000 --- a/httemplate/elements/schedule-appointment.html +++ /dev/null @@ -1,21 +0,0 @@ -<& /elements/header-popup.html &> -

Scheduling appointment...

- -<& /elements/footer-popup.html &> -<%init> - -my @username = map encode_entities($_), $cgi->param('username'); -my $LengthMin = encode_entities( $cgi->param('LengthMin') ); -my $custnum = encode_entities( $cgi->param('custnum') ); - -my $query = join('&', map "username=$_", @username). - "&LengthMin=$LengthMin". - "&custnum=$custnum". - "&RedirectToBasics=1"; - #XXX '&pkgnum=$pkgnum";need to be for specific package/location, not just for a customer... default to active(/ordered) package in a pkg_class w/ticketing_queueid, otherwise, a popup? we're getting complicated like form-creat_ticket.html - -my $url = $p. 'rt/Search/Schedule.html?'. $query; - - diff --git a/httemplate/misc/schedule-appointment.html b/httemplate/misc/schedule-appointment.html new file mode 100644 index 000000000..69b9f422b --- /dev/null +++ b/httemplate/misc/schedule-appointment.html @@ -0,0 +1,21 @@ +<& /elements/header-popup.html &> +

Scheduling appointment...

+ +<& /elements/footer-popup.html &> +<%init> + +my @username = map encode_entities($_), $cgi->param('username'); +my $LengthMin = encode_entities( $cgi->param('LengthMin') ); +my $custnum = encode_entities( $cgi->param('custnum') ); + +my $query = join('&', map "username=$_", @username). + "&LengthMin=$LengthMin". + "&custnum=$custnum". + "&RedirectToBasics=1"; + #XXX '&pkgnum=$pkgnum";need to be for specific package/location, not just for a customer... default to active(/ordered) package in a pkg_class w/ticketing_queueid, otherwise, a popup? we're getting complicated like form-creat_ticket.html + +my $url = $p. 'rt/Search/Schedule.html?'. $query; + + -- cgit v1.2.1 From 9ff00dc1dc9d5a6c63bfb3444e8e7c382cd603bf Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 29 Oct 2015 13:12:26 -0700 Subject: fix appointments vs. no direct elements/ access, RT#34237, RT#23357 --- httemplate/misc/make_appointment.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httemplate/misc/make_appointment.html b/httemplate/misc/make_appointment.html index ddf377f54..6f308e0a8 100644 --- a/httemplate/misc/make_appointment.html +++ b/httemplate/misc/make_appointment.html @@ -2,7 +2,7 @@ % #XXX actually, the action needs to repace the top-level window with this % #$params->{'action'} = $p. 'rt/Search/Schedule.html?'. $query; -
+ -- cgit v1.2.1 From 7b53b47c6422721dc9490467b29ce2d0a319c9d0 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Thu, 29 Oct 2015 19:58:54 -0500 Subject: RT#38432: OFM - Send refund receipt [added template initial data] --- FS/FS/msg_template/InitialData.pm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/FS/FS/msg_template/InitialData.pm b/FS/FS/msg_template/InitialData.pm index dbb9f4037..baf145d8b 100644 --- a/FS/FS/msg_template/InitialData.pm +++ b/FS/FS/msg_template/InitialData.pm @@ -19,6 +19,23 @@ If you did not request this password reset, you may safely ignore and delete thi

{ $company_name } Support +END + ], + }, + { msgname => 'Refund receipt', + msgclass => 'email', + mime_type => 'text/html', + _conf => 'refund_receipt_msgnum', + _insert_args => [ subject => '{ $company_name } refund receipt', + body => <<'END', +Dear {$first} {$last},
+
+The following refund has been applied to your account.
+
+Refund ID: {$refundnum}
+Date: {$date}
+Amount: {$refund}
+ END ], }, -- cgit v1.2.1 From a51e2d1d9c27f9329b3ff0305a60dbf773a11b71 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Thu, 29 Oct 2015 22:17:08 -0500 Subject: RT#38671: Do not include charges and credits from failed signup processing [added void reason] --- FS/FS/ClientAPI/MyAccount.pm | 4 ++-- FS/FS/ClientAPI/Signup.pm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 89c70f75c..f272cd490 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -2521,8 +2521,8 @@ sub _do_bop_realtime { #this used to apply a credit, but now we can void invoices... foreach my $cust_bill (@cust_bill) { - my $voiderror = $cust_bill->void(); - warn "Error voiding cust bill after decline: $voiderror"; + my $voiderror = $cust_bill->void('automatic payment failed'); + warn "Error voiding cust bill after decline: $voiderror" if $voiderror; } } diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm index a4ea21b8f..e166d407e 100644 --- a/FS/FS/ClientAPI/Signup.pm +++ b/FS/FS/ClientAPI/Signup.pm @@ -824,8 +824,8 @@ sub new_customer { #this used to apply a credit, but now we can void invoices... foreach my $cust_bill (@cust_bill) { - my $voiderror = $cust_bill->void(); - warn "Error voiding cust bill after decline: $voiderror"; + my $voiderror = $cust_bill->void('automatic payment failed'); + warn "Error voiding cust bill after decline: $voiderror" if $voiderror; } #should check list for errors... -- cgit v1.2.1 From b8fc5d2178e7358661e37ef97b7619f7a9080f3a Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Fri, 30 Oct 2015 01:57:46 -0500 Subject: RT#38722: DFH: paymentech upload and download retry --- FS/FS/log_context.pm | 2 ++ FS/bin/freeside-paymentech-download | 42 +++++++++++++++++++++++---------- FS/bin/freeside-paymentech-upload | 47 +++++++++++++++++++++++++------------ 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/FS/FS/log_context.pm b/FS/FS/log_context.pm index bd142471c..ff3471760 100644 --- a/FS/FS/log_context.pm +++ b/FS/FS/log_context.pm @@ -18,6 +18,8 @@ my @contexts = ( qw( queue upgrade upgrade_taxable_billpkgnum + freeside-paymentech-upload + freeside-paymentech-download ) ); =head1 NAME diff --git a/FS/bin/freeside-paymentech-download b/FS/bin/freeside-paymentech-download index 16ac3c23b..1b2f95175 100755 --- a/FS/bin/freeside-paymentech-download +++ b/FS/bin/freeside-paymentech-download @@ -11,11 +11,20 @@ use FS::Record qw(qsearch qsearchs); use FS::pay_batch; use FS::cust_pay_batch; use FS::Conf; +use FS::Log; use vars qw( $opt_t $opt_v $opt_a ); getopts('vta:'); #$Net::SFTP::Foreign::debug = -1; + +sub log_and_die { + my $message = shift; + my $log = FS::Log->new('freeside-paymenttech-download'); + $log->error($message); + die $message; +} + sub usage { " Usage: freeside-paymentech-download [ -v ] [ -t ] [ -a archivedir ] user\n @@ -25,13 +34,13 @@ my $user = shift or die &usage; adminsuidsetup $user; if ( $opt_a ) { - die "no such directory: $opt_a\n" + log_and_die("no such directory: $opt_a\n") unless -d $opt_a; - die "archive directory $opt_a is not writable by the freeside user\n" + log_and_die("archive directory $opt_a is not writable by the freeside user\n") unless -w $opt_a; } -my $unzip_check = `which unzip` or die "can't find unzip executable\n"; +my $unzip_check = `which unzip` or log_and_die("can't find unzip executable\n"); #my $tmpdir = File::Temp->newdir(); my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere? @@ -39,22 +48,31 @@ my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere? my $conf = new FS::Conf; my @batchconf = $conf->config('batchconfig-paymentech'); # BIN, terminalID, merchantID, username, password -my $username = $batchconf[3] or die "no Paymentech batch username configured\n"; -my $password = $batchconf[4] or die "no Paymentech batch password configured\n"; +my $username = $batchconf[3] or log_and_die("no Paymentech batch username configured\n"); +my $password = $batchconf[4] or log_and_die("no Paymentech batch password configured\n"); my $host = ($opt_t ? 'orbitalbatchvar.paymentech.net' : 'orbitalbatch.paymentech.net'); print STDERR "Connecting to $username\@$host...\n" if $opt_v; -my $sftp = Net::SFTP::Foreign->new( host => $host, - user => $username, - password => $password, - timeout => 30, - ); -die "failed to connect to '$username\@$host'\n(".$sftp->error.")\n" if $sftp->error; +my $sftp; +my $ssh_retry = 25; # number of times to try connection, needs to be >= 1 +my $ssh_retry_wait = 60*5; # seconds to wait between tries +while ($ssh_retry > 0) { + $sftp = Net::SFTP::Foreign->new( host => $host, + user => $username, + password => $password, + timeout => 30, + ); + last unless $sftp->error; + $ssh_retry -= 1; + sleep($ssh_retry_wait) if $ssh_retry > 0; +} + +log_and_die("failed to connect to '$username\@$host'\n(".$sftp->error.")\n") if $sftp->error; my @files = map { $_->{filename} } @{ $sftp->ls('.', wanted => qr/_resp\.zip$/) }; -die "no response files found\n" if !@files; +log_and_die("no response files found\n") if !@files; BATCH: foreach my $filename (@files) { diff --git a/FS/bin/freeside-paymentech-upload b/FS/bin/freeside-paymentech-upload index 609019eb2..a6e6a5d28 100755 --- a/FS/bin/freeside-paymentech-upload +++ b/FS/bin/freeside-paymentech-upload @@ -11,12 +11,20 @@ use FS::Record qw(qsearch qsearchs); use FS::pay_batch; use FS::cust_pay_batch; use FS::Conf; +use FS::Log; use vars qw( $opt_a $opt_t $opt_v $opt_p ); getopts('avtp:'); #$Net::SFTP::Foreign::debug = -1; +sub log_and_die { + my $message = shift; + my $log = FS::Log->new('freeside-paymenttech-upload'); + $log->error($message); + die $message; +} + sub usage { " Usage: freeside-paymentech-upload [ -v ] [ -t ] user batchnum @@ -26,7 +34,7 @@ sub usage { " my $user = shift or die &usage; adminsuidsetup $user; -my $zip_check = `which zip` or die "can't find zip executable\n"; +my $zip_check = `which zip` or log_and_die("can't find zip executable\n"); my @batches; @@ -34,21 +42,21 @@ if($opt_a) { my %criteria = (status => 'O'); $criteria{'payby'} = uc($opt_p) if $opt_p; @batches = qsearch('pay_batch', \%criteria); - die "No open batches found".($opt_p ? " of type '$opt_p'" : '').".\n" + log_and_die("No open batches found".($opt_p ? " of type '$opt_p'" : '').".\n") if !@batches; } else { my $batchnum = shift; - die &usage if !$batchnum; + log_and_die("batchnum not passed\n".&usage) if !$batchnum; @batches = qsearchs('pay_batch', { batchnum => $batchnum } ); - die "Can't find payment batch '$batchnum'\n" if !@batches; + log_and_die("Can't find payment batch '$batchnum'\n") if !@batches; } my $conf = new FS::Conf; my @batchconf = $conf->config('batchconfig-paymentech'); # BIN, terminalID, merchantID, username, password -my $username = $batchconf[3] or die "no Paymentech batch username configured\n"; -my $password = $batchconf[4] or die "no Paymentech batch password configured\n"; +my $username = $batchconf[3] or log_and_die("no Paymentech batch username configured\n"); +my $password = $batchconf[4] or log_and_die("no Paymentech batch password configured\n"); #my $tmpdir = File::Temp->newdir(); my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere? @@ -61,7 +69,7 @@ foreach my $pay_batch (@batches) { print STDERR "Exporting batch $batchnum to $filename...\n" if $opt_v; my $text = $pay_batch->export_batch(format => 'paymentech'); $text =~ s!FILEID!$filename! - or die "couldn't find FILEID tag\n"; + or log_and_die("couldn't find FILEID tag\n"); open OUT, ">$tmpdir/$filename.xml"; print OUT $text; close OUT; @@ -69,7 +77,7 @@ foreach my $pay_batch (@batches) { system('zip', '-P', $password, '-q', '-j', "$tmpdir/$filename.zip", "$tmpdir/$filename.xml"); - die "failed to create zip file\n" if (! -f "$tmpdir/$filename.zip" ); + log_and_die("failed to create zip file\n") if (! -f "$tmpdir/$filename.zip" ); push @filenames, $filename; } @@ -77,17 +85,26 @@ my $host = ($opt_t ? 'orbitalbatchvar.paymentech.net' : 'orbitalbatch.paymentech.net'); print STDERR "Connecting to $username\@$host...\n" if $opt_v; -my $sftp = Net::SFTP::Foreign->new( host => $host, - user => $username, - password => $password, - timeout => 30, - ); -die "failed to connect to '$username\@$host'\n(".$sftp->error.")\n" +my $sftp; +my $ssh_retry = 25; # number of times to try connection, needs to be >= 1 +my $ssh_retry_wait = 60*5; # seconds to wait between tries +while ($ssh_retry > 0) { + $sftp = Net::SFTP::Foreign->new( host => $host, + user => $username, + password => $password, + timeout => 30, + ); + last unless $sftp->error; + $ssh_retry -= 1; + sleep($ssh_retry_wait) if $ssh_retry > 0; +} + +log_and_die("failed to connect to '$username\@$host'\n(".$sftp->error.")\n") if $sftp->error; foreach my $filename (@filenames) { $sftp->put("$tmpdir/$filename.zip", "$filename.zip") - or die "failed to upload file (".$sftp->error.")\n"; + or log_and_die("failed to upload file (".$sftp->error.")\n"); } print STDERR "Finished!\n" if $opt_v; -- cgit v1.2.1