[open-ils-commits] [GIT] Evergreen ILS branch master updated. 5b2e58257dffc97e2257aaa1bed4117d2a331028

Evergreen Git git at git.evergreen-ils.org
Wed Aug 5 17:41:10 EDT 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  5b2e58257dffc97e2257aaa1bed4117d2a331028 (commit)
       via  9aada1966acfdef18a98d6b762a9b03ae337bb3a (commit)
       via  9aa36c7d7f0d681b108282c062e44f640f792cb9 (commit)
       via  cfabfa7abd42e61a0387a73ab19f712f82162d66 (commit)
      from  ad66d9e03b0bb00eba9c19eceefe73756e10d95e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 5b2e58257dffc97e2257aaa1bed4117d2a331028
Author: Jason Etheridge <jason at EquinoxInitiative.org>
Date:   Mon Aug 3 08:37:18 2020 -0400

    LP1774892 release notes
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/docs/RELEASE_NOTES_NEXT/OPAC/stripe-v3.adoc b/docs/RELEASE_NOTES_NEXT/OPAC/stripe-v3.adoc
new file mode 100644
index 0000000000..e2fe3627d2
--- /dev/null
+++ b/docs/RELEASE_NOTES_NEXT/OPAC/stripe-v3.adoc
@@ -0,0 +1,11 @@
+Credit card payments using Stripe now on version 3 (Elements)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+When Stripe payments are enabled, the public catalog will now
+use version 3 of the Stripe client library, as well as its
+Elements API for building the credit card form.  For
+technical reasons, this more easily lends a site to PCI
+compliance.
+
+On the staff side, the credit card option is disabled for
+Stripe, as that has not been implemented and in the past
+would just give an error.

commit 9aada1966acfdef18a98d6b762a9b03ae337bb3a
Author: Jason Etheridge <jason at EquinoxInitiative.org>
Date:   Fri Jul 10 12:15:22 2020 -0400

    LP1774892 stripe elements
    
    This fixes some minor errors with the generic payment form.
    
    Signed-off-by: Jason Etheridge <jason at EquinoxInitiative.org>
    Signed-off-by: John Amundson <jamundson at cwmars.org>
    Signed-off-by: Dawn Dale <ddale at georgialibraries.org>
    Signed-off-by: Jason Stephenson <jason at sigio.com>
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/Open-ILS/src/templates/opac/myopac/generic_payment_form.tt2 b/Open-ILS/src/templates/opac/myopac/generic_payment_form.tt2
index 4a67062539..53479bd95f 100644
--- a/Open-ILS/src/templates/opac/myopac/generic_payment_form.tt2
+++ b/Open-ILS/src/templates/opac/myopac/generic_payment_form.tt2
@@ -32,7 +32,7 @@
                         readonly="readonly" />   
                     <a title="[% l('Update Email Address') %]"
                         href="[% ctx.opac_root %]/myopac/update_email?return_to_referer=1">[% l("Update") %]</a>
-                </td
+                </td>
             </tr>
             <tr>
                 <td><label for="payment-billing-address">[% l('Street Address') %]</label></td>
@@ -124,5 +124,5 @@
             
       </tbody>
     </table>
-     [% INCLUDE "opac/parts/myopac/main_refund_policy.tt2" %]
 </form>
+<table width="100%">[% INCLUDE "opac/parts/myopac/main_refund_policy.tt2" %]</table>

commit 9aa36c7d7f0d681b108282c062e44f640f792cb9
Author: Jason Etheridge <jason at EquinoxInitiative.org>
Date:   Fri Jul 10 12:08:30 2020 -0400

    LP1774892 stripe elements
    
    This commit breaks some code out into separate files for easier understanding.
    
    The Stripe form was then tweaked and repositioned to work with specific selected
    transactions, invoke the last chance screen, and show the refund policy.
    
    Signed-off-by: Jason Etheridge <jason at EquinoxInitiative.org>
    Signed-off-by: John Amundson <jamundson at cwmars.org>
    Signed-off-by: Dawn Dale <ddale at georgialibraries.org>
    Signed-off-by: Jason Stephenson <jason at sigio.com>
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/Open-ILS/src/templates/opac/myopac/generic_payment_form.tt2 b/Open-ILS/src/templates/opac/myopac/generic_payment_form.tt2
new file mode 100644
index 0000000000..4a67062539
--- /dev/null
+++ b/Open-ILS/src/templates/opac/myopac/generic_payment_form.tt2
@@ -0,0 +1,128 @@
+<form method="post" id="payment_form" action='#payment'>
+    <input type="hidden" name="last_chance" value="1" />
+    [% FOR xact IN CGI.param('xact') %]
+    <input type="hidden" name="xact" value="[% xact | html %]" />
+    [% END %]
+    [% FOR xact IN CGI.param('xact_misc') %]
+    <input type="hidden" name="xact_misc" value="[% xact | html %]" />
+    [% END %]
+
+     <table id="billing_info_table">
+      <tbody>
+          <tr>
+              <td colspan='2' class="cc_header"><strong>[% l('Billing Information') %]</strong></td>
+           </tr>
+           <tr> 
+            <td><label for="payment-first-name">[% l('First Name') %]</label></td>
+                <td><input type="text"  name="billing_first" id="payment-first-name" 
+                    value="[% ctx.user.first_given_name | html %]" /></td>
+            </tr>
+            <tr>
+                <td><label for="payment-last-name">[% l('Last Name') %]</label></td>
+                <td><input type="text" name="billing_last" id="payment-last-name" 
+                    value="[% ctx.user.family_name | html %]" /></td>
+            </tr>
+
+            <tr>
+                <td><label for="payment-email-addr">[% l('Email Address') %]</label></td>
+                <td>
+                    
+                    <input id="payment-email-addr" type="text" 
+                         value="[% ctx.user.email | html %]" disabled="disabled" 
+                        readonly="readonly" />   
+                    <a title="[% l('Update Email Address') %]"
+                        href="[% ctx.opac_root %]/myopac/update_email?return_to_referer=1">[% l("Update") %]</a>
+                </td
+            </tr>
+            <tr>
+                <td><label for="payment-billing-address">[% l('Street Address') %]</label></td>
+                <td><input type="text" name="billing_address" id="payment-billing-address" 
+                    value="[% ctx.user.billing_address.street1 _ ctx.user.billing_address.street2 | html %]" /></td>
+            </tr>
+            <tr>
+                <td><label for="payment-billing-city">[% l('City' )%]</label></td>
+                <td><input type="text" name="billing_city" id="payment-billing-city" 
+                    value="[% ctx.user.billing_address.city | html %]" /></td>
+            </tr>
+            <tr>
+                <td><label for="payment-billing-state">[% l('State or Province') %]</label></td>
+                <td><input type="text" name="billing_state" id="payment-billing-state"
+                    value="[% ctx.user.billing_address.state | html %]" /></td>
+            </tr>
+            <tr>
+                <td><label for="paymenet-billing-zip">[% l('ZIP or Postal Code') %]</label></td>
+                [% USE zip=String(ctx.user.billing_address.post_code) %]
+                <td><input type="tel" pattern="[0-9]*" maxlength="5" size="5" name="billing_zip" id="paymenet-billing-zip"
+                    value="[% zip.truncate(5)  %]" /></td>
+            </tr>
+           </tbody>
+           </table>
+           
+           <table id="credit_card_info_table">
+           <tbody>
+            <tr>
+              <td colspan='2' class="cc_header"><strong>[% l('Credit Card Information') %]</strong></td>
+            </tr>
+            <tr>
+                <td><label for="payment-credit-card">[% l('Credit Card #') %]</label></td>
+                
+                 <!-- Make type tel, which prompts for numbers in mobile -->
+                <td><input type="tel" pattern="[0-9]*" maxlength="16" id="payment-credit-card" required name="number"/></td>
+            </tr>
+            <tr>
+                <td><label for="payment-security-code">[% l('Security Code') %]</label></td>
+                <td>
+                     <!-- Make type tel, which prompts for numbers in mobile -->
+                    <input type="tel" pattern="[0-9]*" size="4" maxlength="5" id="payment-security-code" name="cvv2"/></td>
+            </tr>
+            <tr>
+                <td><label for="payment-expire-month">[% l('Expiration Month') %]</label></td>
+                <td>
+                    <select id="payment-expire-month" required name="expire_month">
+                        <option value="-1"></option>
+                        <option value="01">[% l("January (1)") %]</option>
+                        <option value="02">[% l("February (2)") %]</option>
+                        <option value="03">[% l("March (3)") %]</option>
+                        <option value="04">[% l("April (4)") %]</option>
+                        <option value="05">[% l("May (5)") %]</option>
+                        <option value="06">[% l("June (6)") %]</option>
+                        <option value="07">[% l("July (7)") %]</option>
+                        <option value="08">[% l("August (8)") %]</option>
+                        <option value="09">[% l("September (9)") %]</option>
+                        <option value="10">[% l("October (10)") %]</option>
+                        <option value="11">[% l("November (11)") %]</option>
+                        <option value="12">[% l("December (12)") %]</option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <td><label for="payment-expire-year">[% l('Expiration Year') %]</label></td>
+                <td>
+                    <select id="payment-expire-year" name="expire_year">
+                    [% year = date.format(date.now, '%Y');
+                    y = year;
+                    WHILE y < year + 10; # show ten years starting now %]
+                        <option value="[% y %]">[% y %]</option>
+                    [% y = y + 1; END %]
+                    </select>
+                </td>
+            </tr>
+            <tr>
+               <td colspan='2'>
+                   <div id="payment_actions">
+                      [% l('Total amount:') %]
+                       <strong>[% money(ctx.fines.balance_owed) %]</strong><br />
+      
+                     <input type="submit" id="payment_submit" value="[% l('Next') %]" class="opac-button" />
+                     <a href="[% mkurl(ctx.opac_root _ '/myopac/main', {}, 1) %]" class="opac-button">[% l('Cancel') %]</a> 
+                     <br/>
+                     
+                      
+                   </div>
+               </td>
+            </tr>
+            
+      </tbody>
+    </table>
+     [% INCLUDE "opac/parts/myopac/main_refund_policy.tt2" %]
+</form>
diff --git a/Open-ILS/src/templates/opac/myopac/last_chance_form.tt2 b/Open-ILS/src/templates/opac/myopac/last_chance_form.tt2
new file mode 100644
index 0000000000..150ffb682b
--- /dev/null
+++ b/Open-ILS/src/templates/opac/myopac/last_chance_form.tt2
@@ -0,0 +1,55 @@
+<p><big>[% l("Are you sure you are ready to charge ") %]
+     <strong> [% l("[_1] ", money(ctx.fines.balance_owed))%]</strong>
+    [% l("to your credit card?") %]</big></p>
+<form action="[% ctx.opac_root %]/myopac/main_pay_init" method="post">
+    [% FOR k IN CGI.Vars;
+        NEXT UNLESS k;
+        FOR val IN CGI.param(k) %]
+    <input type="hidden" name="[% k | html %]" value="[% val | html %]" />
+    [% END; END %]
+    
+    <input type="submit" value="[% l('Submit') %]" class="opac-button"/>
+    <a href="[% mkurl(ctx.opac_root _ '/myopac/main#selected_fines', {}, 1) %]" class="opac-button">[% l('Cancel') %]</a>
+
+ <table title="[% l('List of Transactions') %]" id="acct_fines_confirm_header"
+    class="table_no_border_space table_no_cell_pad" style="padding-top:1em;">
+<thead>
+  <tr>
+    <th>[% l('Charge/Fee') %]</th>
+    <th>[% l('Amount') %]</th>
+ </tr>
+</thead>
+<tbody>
+  [%
+   FOR f IN ctx.fines.circulation;
+     NEXT IF CGI.param('xact').size &&
+        !CGI.param('xact').grep(f.xact.id).size;
+     attrs = {marc_xml => f.marc_xml};
+     IF f.marc_xml;
+         PROCESS get_marc_attrs args=attrs;
+     ELSIF f.xact.reservation;
+          attrs.title = f.xact.reservation.target_resource_type.name;
+     END %]
+     <tr>
+        <td>[% attrs.title | html %]</td>
+        <td class="text-right">[% money(f.xact.balance_owed) %]</td>
+     </tr>
+      [%
+      END;
+      FOR f IN ctx.fines.grocery;
+          NEXT IF CGI.param('xact_misc').size &&
+              !CGI.param('xact_misc').grep(f.xact.id).size %]
+          <tr>
+             <td>[% f.xact.last_billing_type | html %]</td>
+             <td class="text-right">[% money(f.xact.balance_owed) %]</td>
+        </tr>
+    [% END %]
+ </tbody>
+</table> 
+ 
+<p style="padding-top: 2em;">
+<big>[% l("Are you sure you are ready to charge ") %]
+     <strong> [% l("[_1] ", money(ctx.fines.balance_owed))%]</strong>
+    [% l("to your credit card?") %]</big></p>        
+    <input type="submit" value="[% l('Submit') %]" class="opac-button"/>
+    <a href="[% mkurl(ctx.opac_root _ '/myopac/main#selected_fines', {}, 1) %]" class="opac-button">[% l('Cancel') %]</a>
diff --git a/Open-ILS/src/templates/opac/myopac/main_payment_form.tt2 b/Open-ILS/src/templates/opac/myopac/main_payment_form.tt2
index 6c40229a65..2d60ce6166 100644
--- a/Open-ILS/src/templates/opac/myopac/main_payment_form.tt2
+++ b/Open-ILS/src/templates/opac/myopac/main_payment_form.tt2
@@ -18,292 +18,16 @@
     [% l("The minimum amount you can pay is \$0.01.") %]
 </div>
 [% ELSE %]
-[% IF ctx.use_stripe %]
-<noscript>
-    [% l("Your browser does not have Javascript enabled, and we cannot " _
-        "process credit card payments without it.  Please change your " _
-        "browser settings and try again.") %]
-</noscript>
-<script type="text/javascript">
-function build_stripe_form() {
-    var elements = stripe.elements();
-
-    var style = {
-        base: {
-            color: '#32325d',
-            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
-            fontSmoothing: 'antialiased',
-            fontSize: '16px',
-            '::placeholder': {
-                color: '#aab7c4'
-            }
-        },
-        invalid: {
-            color: '#fa755a',
-            iconColor: '#fa755a'
-        }
-    };
-
-    var card = elements.create('card', {style: style});
-    card.mount('#card-element');
-
-    // real-time validation
-    card.on('change', function(event) {
-      var displayError = document.getElementById('card-errors');
-      if (event.error) {
-        displayError.textContent = event.error.message;
-      } else {
-        displayError.textContent = '';
-      }
-    });
-
-    // let's try some auto-focus
-    card.on('ready', function(event) {
-        try { card.focus(); } catch(E) { console.log('failed to focus card element',E); }
-    });
-
-    var form = document.getElementById('payment-form');
-    form.addEventListener('submit', function(event) {
-      event.preventDefault();
-
-      stripe.createToken(card).then(function(result) {
-        if (result.error) {
-          // Inform the user if there was an error.
-          var errorElement = document.getElementById('card-errors');
-          errorElement.textContent = result.error.message;
-        } else {
-          // Send the token to your server.
-          stripeTokenHandler(result.token);
-        }
-      });
-    });
-
-    function stripeTokenHandler(token) {
-      var form = document.getElementById('payment-form');
-      var hiddenInput = document.createElement('input');
-      hiddenInput.setAttribute('type', 'hidden');
-      hiddenInput.setAttribute('name', 'stripe_token');
-      hiddenInput.setAttribute('value', token.id);
-      form.appendChild(hiddenInput);
-
-      form.submit();
-    }
-}
-[% IF ctx.want_jquery %]
-    // jquery won't actually load until after this execution thread
-    setTimeout(function() { $(document).ready(build_stripe_form) }, 0);
-[% ELSE %]
-    // but jquery is preferable to doing this
-    setTimeout(build_stripe_form,0);
-[% END %]
-</script>
-<form action="[% ctx.opac_root %]/myopac/main_pay_init" method="post" id="payment-form">
-  <div class="form-row">
-    <label for="card-element">
-      <h1>Credit Card Information</h1>
-    </label>
-    <div id="card-element">
-      <!-- A Stripe Element will be inserted here. -->
-    </div>
-
-    <!-- Used to display form errors. -->
-    <div id="card-errors" role="alert"></div>
-  </div>
-
-  <button class="opac-button">Submit Payment</button>
-</form>
-[% ELSE %]
 <div id="pay_fines_now">
     [% IF last_chance %]
-    
-    <p><big>[% l("Are you sure you are ready to charge ") %]
-         <strong> [% l("[_1] ", money(ctx.fines.balance_owed))%]</strong>
-        [% l("to your credit card?") %]</big></p>
-    <form action="[% ctx.opac_root %]/myopac/main_pay_init" method="post">
-        [% FOR k IN CGI.Vars;
-            NEXT UNLESS k;
-            FOR val IN CGI.param(k) %]
-        <input type="hidden" name="[% k | html %]" value="[% val | html %]" />
-        [% END; END %]
-        
-        <input type="submit" value="[% l('Submit') %]" class="opac-button"/>
-        <a href="[% mkurl(ctx.opac_root _ '/myopac/main#selected_fines', {}, 1) %]" class="opac-button">[% l('Cancel') %]</a>
-
-     <table title="[% l('List of Transactions') %]" id="acct_fines_confirm_header"
-        class="table_no_border_space table_no_cell_pad" style="padding-top:1em;">
-   <thead>
-      <tr>
-        <th>[% l('Charge/Fee') %]</th>
-        <th>[% l('Amount') %]</th>
-     </tr>
-   </thead>
-   <tbody>
-      [%
-       FOR f IN ctx.fines.circulation;
-         NEXT IF CGI.param('xact').size &&
-            !CGI.param('xact').grep(f.xact.id).size;
-         attrs = {marc_xml => f.marc_xml};
-         IF f.marc_xml;
-             PROCESS get_marc_attrs args=attrs;
-         ELSIF f.xact.reservation;
-              attrs.title = f.xact.reservation.target_resource_type.name;
-         END %]
-         <tr>
-            <td>[% attrs.title | html %]</td>
-            <td class="text-right">[% money(f.xact.balance_owed) %]</td>
-         </tr>
-          [%
-          END;
-          FOR f IN ctx.fines.grocery;
-              NEXT IF CGI.param('xact_misc').size &&
-                  !CGI.param('xact_misc').grep(f.xact.id).size %]
-              <tr>
-                 <td>[% f.xact.last_billing_type | html %]</td>
-                 <td class="text-right">[% money(f.xact.balance_owed) %]</td>
-            </tr>
-        [% END %]
-     </tbody>
-   </table> 
-     
-    <p style="padding-top: 2em;">
-    <big>[% l("Are you sure you are ready to charge ") %]
-         <strong> [% l("[_1] ", money(ctx.fines.balance_owed))%]</strong>
-        [% l("to your credit card?") %]</big></p>        
-        <input type="submit" value="[% l('Submit') %]" class="opac-button"/>
-        <a href="[% mkurl(ctx.opac_root _ '/myopac/main#selected_fines', {}, 1) %]" class="opac-button">[% l('Cancel') %]</a>
+        [% PROCESS "opac/myopac/last_chance_form.tt2"; %]
     [% ELSE %]
-    
-    <form method="post" id="payment_form" action='#payment'>
-        <input type="hidden" name="last_chance" value="1" />
-        [% FOR xact IN CGI.param('xact') %]
-        <input type="hidden" name="xact" value="[% xact | html %]" />
-        [% END %]
-        [% FOR xact IN CGI.param('xact_misc') %]
-        <input type="hidden" name="xact_misc" value="[% xact | html %]" />
-        [% END %]
-
-         <table id="billing_info_table">
-          <tbody>
-              <tr>
-                  <td colspan='2' class="cc_header"><strong>[% l('Billing Information') %]</strong></td>
-               </tr>
-               <tr> 
-                <td><label for="payment-first-name">[% l('First Name') %]</label></td>
-                    <td><input type="text"  name="billing_first" id="payment-first-name" 
-                        value="[% ctx.user.first_given_name | html %]" /></td>
-                </tr>
-                <tr>
-                    <td><label for="payment-last-name">[% l('Last Name') %]</label></td>
-                    <td><input type="text" name="billing_last" id="payment-last-name" 
-                        value="[% ctx.user.family_name | html %]" /></td>
-                </tr>
-
-                <tr>
-                    <td><label for="payment-email-addr">[% l('Email Address') %]</label></td>
-                    <td>
-                        
-                        <input id="payment-email-addr" type="text" 
-                             value="[% ctx.user.email | html %]" disabled="disabled" 
-                            readonly="readonly" />   
-                        <a title="[% l('Update Email Address') %]"
-                            href="[% ctx.opac_root %]/myopac/update_email?return_to_referer=1">[% l("Update") %]</a>
-                    </td
-                </tr>
-                <tr>
-                    <td><label for="payment-billing-address">[% l('Street Address') %]</label></td>
-                    <td><input type="text" name="billing_address" id="payment-billing-address" 
-                        value="[% ctx.user.billing_address.street1 _ ctx.user.billing_address.street2 | html %]" /></td>
-                </tr>
-                <tr>
-                    <td><label for="payment-billing-city">[% l('City' )%]</label></td>
-                    <td><input type="text" name="billing_city" id="payment-billing-city" 
-                        value="[% ctx.user.billing_address.city | html %]" /></td>
-                </tr>
-                <tr>
-                    <td><label for="payment-billing-state">[% l('State or Province') %]</label></td>
-                    <td><input type="text" name="billing_state" id="payment-billing-state"
-                        value="[% ctx.user.billing_address.state | html %]" /></td>
-                </tr>
-                <tr>
-                    <td><label for="paymenet-billing-zip">[% l('ZIP or Postal Code') %]</label></td>
-                    [% USE zip=String(ctx.user.billing_address.post_code) %]
-                    <td><input type="tel" pattern="[0-9]*" maxlength="5" size="5" name="billing_zip" id="paymenet-billing-zip"
-                        value="[% zip.truncate(5)  %]" /></td>
-                </tr>
-               </tbody>
-               </table>
-               
-               <table id="credit_card_info_table">
-               <tbody>
-                <tr>
-                  <td colspan='2' class="cc_header"><strong>[% l('Credit Card Information') %]</strong></td>
-                </tr>
-                <tr>
-                    <td><label for="payment-credit-card">[% l('Credit Card #') %]</label></td>
-                    
-                     <!-- Make type tel, which prompts for numbers in mobile -->
-                    <td><input type="tel" pattern="[0-9]*" maxlength="16" id="payment-credit-card" required name="number"/></td>
-                </tr>
-                <tr>
-                    <td><label for="payment-security-code">[% l('Security Code') %]</label></td>
-                    <td>
-                         <!-- Make type tel, which prompts for numbers in mobile -->
-                        <input type="tel" pattern="[0-9]*" size="4" maxlength="5" id="payment-security-code" name="cvv2"/></td>
-                </tr>
-                <tr>
-                    <td><label for="payment-expire-month">[% l('Expiration Month') %]</label></td>
-                    <td>
-                        <select id="payment-expire-month" required name="expire_month">
-                            <option value="-1"></option>
-                            <option value="01">[% l("January (1)") %]</option>
-                            <option value="02">[% l("February (2)") %]</option>
-                            <option value="03">[% l("March (3)") %]</option>
-                            <option value="04">[% l("April (4)") %]</option>
-                            <option value="05">[% l("May (5)") %]</option>
-                            <option value="06">[% l("June (6)") %]</option>
-                            <option value="07">[% l("July (7)") %]</option>
-                            <option value="08">[% l("August (8)") %]</option>
-                            <option value="09">[% l("September (9)") %]</option>
-                            <option value="10">[% l("October (10)") %]</option>
-                            <option value="11">[% l("November (11)") %]</option>
-                            <option value="12">[% l("December (12)") %]</option>
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td><label for="payment-expire-year">[% l('Expiration Year') %]</label></td>
-                    <td>
-                        <select id="payment-expire-year" name="expire_year">
-                        [% year = date.format(date.now, '%Y');
-                        y = year;
-                        WHILE y < year + 10; # show ten years starting now %]
-                            <option value="[% y %]">[% y %]</option>
-                        [% y = y + 1; END %]
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                   <td colspan='2'>
-                       <div id="payment_actions">
-                          [% l('Total amount:') %]
-                           <strong>[% money(ctx.fines.balance_owed) %]</strong><br />
-          
-                         <input type="submit" id="payment_submit" value="[% l('Next') %]" class="opac-button" />
-                         <a href="[% mkurl(ctx.opac_root _ '/myopac/main', {}, 1) %]" class="opac-button">[% l('Cancel') %]</a> 
-                         <br/>
-                         
-                          
-                       </div>
-                   </td>
-                </tr>
-                
-          </tbody>
-        </table>
-         [% INCLUDE "opac/parts/myopac/main_refund_policy.tt2" %]
-        
+        [% IF ctx.use_stripe %]
+            [% PROCESS "opac/myopac/stripe_payment_form.tt2"; %]
+        [% ELSE %]
+            [% PROCESS "opac/myopac/generic_payment_form.tt2"; %]
+        [% END %] <!-- of IF ctx.use_stripe -->
     [% END %]
-    </form>
 </div>
-[% END %]
-[% END %]
-[% END %]
+[% END %] <!-- of IF ctx.fines.balance_owed <= 0 -->
+[% END %] <!-- of.. something in one of the PROCESS or WRAPPER blocks? -->
diff --git a/Open-ILS/src/templates/opac/myopac/stripe_payment_form.tt2 b/Open-ILS/src/templates/opac/myopac/stripe_payment_form.tt2
new file mode 100644
index 0000000000..b282e9c1de
--- /dev/null
+++ b/Open-ILS/src/templates/opac/myopac/stripe_payment_form.tt2
@@ -0,0 +1,102 @@
+<noscript>
+    [% l("Your browser does not have Javascript enabled, and we cannot " _
+        "process credit card payments without it.  Please change your " _
+        "browser settings and try again.") %]
+</noscript>
+<script type="text/javascript">
+function build_stripe_form() {
+    var elements = stripe.elements();
+
+    var style = {
+        base: {
+            color: '#32325d',
+            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
+            fontSmoothing: 'antialiased',
+            fontSize: '16px',
+            '::placeholder': {
+                color: '#aab7c4'
+            }
+        },
+        invalid: {
+            color: '#fa755a',
+            iconColor: '#fa755a'
+        }
+    };
+
+    var card = elements.create('card', {style: style});
+    card.mount('#card-element');
+
+    // real-time validation
+    card.on('change', function(event) {
+      var displayError = document.getElementById('card-errors');
+      if (event.error) {
+        displayError.textContent = event.error.message;
+      } else {
+        displayError.textContent = '';
+      }
+    });
+
+    // let's try some auto-focus
+    card.on('ready', function(event) {
+        try { card.focus(); } catch(E) { console.log('failed to focus card element',E); }
+    });
+
+    var form = document.getElementById('payment-form');
+    form.addEventListener('submit', function(event) {
+      event.preventDefault();
+
+      stripe.createToken(card).then(function(result) {
+        if (result.error) {
+          // Inform the user if there was an error.
+          var errorElement = document.getElementById('card-errors');
+          errorElement.textContent = result.error.message;
+        } else {
+          // Send the token to your server.
+          stripeTokenHandler(result.token);
+        }
+      });
+    });
+
+    function stripeTokenHandler(token) {
+      var form = document.getElementById('payment-form');
+      var hiddenInput = document.createElement('input');
+      hiddenInput.setAttribute('type', 'hidden');
+      hiddenInput.setAttribute('name', 'stripe_token');
+      hiddenInput.setAttribute('value', token.id);
+      form.appendChild(hiddenInput);
+
+      form.submit();
+    }
+}
+[% IF ctx.want_jquery %]
+    // jquery won't actually load until after this execution thread
+    setTimeout(function() { $(document).ready(build_stripe_form) }, 0);
+[% ELSE %]
+    // but jquery is preferable to doing this
+    setTimeout(build_stripe_form,0);
+[% END %]
+</script>
+<form action="#payment" method="post" id="payment-form">
+  <input type="hidden" name="last_chance" value="1" />
+  [% FOR xact IN CGI.param('xact') %]
+  <input type="hidden" name="xact" value="[% xact | html %]" />
+  [% END %]
+  [% FOR xact IN CGI.param('xact_misc') %]
+  <input type="hidden" name="xact_misc" value="[% xact | html %]" />
+  [% END %]
+  <div class="form-row">
+    <label for="card-element">
+      <h1>Credit Card Information</h1>
+    </label>
+    <div id="card-element">
+      <!-- A Stripe Element will be inserted here. -->
+    </div>
+
+    <!-- Used to display form errors. -->
+    <div id="card-errors" role="alert"></div>
+  </div>
+
+  <button class="opac-button">Next</button>
+  <a href="[% mkurl(ctx.opac_root _ '/myopac/main', {}, 1) %]" class="opac-button">[% l('Cancel') %]</a> 
+</form>
+<table>[% INCLUDE "opac/parts/myopac/main_refund_policy.tt2" %]</table>

commit cfabfa7abd42e61a0387a73ab19f712f82162d66
Author: Jason Etheridge <jason at EquinoxInitiative.org>
Date:   Fri Jun 12 09:57:03 2020 -0400

    LP1774892 stripe elements
    
    This commmit changes the OPAC to use https://js.stripe.com/v3/ instead of
    https://js.stripe.com/v2/ for processing payments through Stripe.
    
    Additionally, it disables the "internal" credit card form in the staff client
    when Stripe is the payment processor (or if the processor is not set at all),
    as that does not currently work.
    
    It also does not replace Business::Stripe's use of the "Charges API" with the
    newer "Payment Intents" API on the backend, but credit card details are still
    not sent to the Evergreen server.
    
    Signed-off-by: Jason Etheridge <jason at EquinoxInitiative.org>
    Signed-off-by: John Amundson <jamundson at cwmars.org>
    Signed-off-by: Dawn Dale <ddale at georgialibraries.org>
    Signed-off-by: Jason Stephenson <jason at sigio.com>
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/Open-ILS/src/templates/opac/css/style.css.tt2 b/Open-ILS/src/templates/opac/css/style.css.tt2
index 72c092fa4f..6fe12ea051 100644
--- a/Open-ILS/src/templates/opac/css/style.css.tt2
+++ b/Open-ILS/src/templates/opac/css/style.css.tt2
@@ -1367,6 +1367,17 @@ div.result_table_utils_cont {
    text-align:center;
 }
 
+/* Stripe's payment form */
+#payment-form
+{
+    background-color: [% css_colors.accent_ultralight %];
+    width: 50%;
+}
+#card-element
+{
+    padding: 10px;
+}
+
 /* text to state what is seen on cc statement */
 .cc_disclaimer
 {
diff --git a/Open-ILS/src/templates/opac/myopac/main_payment_form.tt2 b/Open-ILS/src/templates/opac/myopac/main_payment_form.tt2
index 455af6a91c..6c40229a65 100644
--- a/Open-ILS/src/templates/opac/myopac/main_payment_form.tt2
+++ b/Open-ILS/src/templates/opac/myopac/main_payment_form.tt2
@@ -24,8 +24,96 @@
         "process credit card payments without it.  Please change your " _
         "browser settings and try again.") %]
 </noscript>
+<script type="text/javascript">
+function build_stripe_form() {
+    var elements = stripe.elements();
+
+    var style = {
+        base: {
+            color: '#32325d',
+            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
+            fontSmoothing: 'antialiased',
+            fontSize: '16px',
+            '::placeholder': {
+                color: '#aab7c4'
+            }
+        },
+        invalid: {
+            color: '#fa755a',
+            iconColor: '#fa755a'
+        }
+    };
+
+    var card = elements.create('card', {style: style});
+    card.mount('#card-element');
+
+    // real-time validation
+    card.on('change', function(event) {
+      var displayError = document.getElementById('card-errors');
+      if (event.error) {
+        displayError.textContent = event.error.message;
+      } else {
+        displayError.textContent = '';
+      }
+    });
+
+    // let's try some auto-focus
+    card.on('ready', function(event) {
+        try { card.focus(); } catch(E) { console.log('failed to focus card element',E); }
+    });
+
+    var form = document.getElementById('payment-form');
+    form.addEventListener('submit', function(event) {
+      event.preventDefault();
+
+      stripe.createToken(card).then(function(result) {
+        if (result.error) {
+          // Inform the user if there was an error.
+          var errorElement = document.getElementById('card-errors');
+          errorElement.textContent = result.error.message;
+        } else {
+          // Send the token to your server.
+          stripeTokenHandler(result.token);
+        }
+      });
+    });
+
+    function stripeTokenHandler(token) {
+      var form = document.getElementById('payment-form');
+      var hiddenInput = document.createElement('input');
+      hiddenInput.setAttribute('type', 'hidden');
+      hiddenInput.setAttribute('name', 'stripe_token');
+      hiddenInput.setAttribute('value', token.id);
+      form.appendChild(hiddenInput);
+
+      form.submit();
+    }
+}
+[% IF ctx.want_jquery %]
+    // jquery won't actually load until after this execution thread
+    setTimeout(function() { $(document).ready(build_stripe_form) }, 0);
+[% ELSE %]
+    // but jquery is preferable to doing this
+    setTimeout(build_stripe_form,0);
 [% END %]
-<div id="pay_fines_now"[% IF ctx.use_stripe %] class="hide_me"[% END %]>
+</script>
+<form action="[% ctx.opac_root %]/myopac/main_pay_init" method="post" id="payment-form">
+  <div class="form-row">
+    <label for="card-element">
+      <h1>Credit Card Information</h1>
+    </label>
+    <div id="card-element">
+      <!-- A Stripe Element will be inserted here. -->
+    </div>
+
+    <!-- Used to display form errors. -->
+    <div id="card-errors" role="alert"></div>
+  </div>
+
+  <button class="opac-button">Submit Payment</button>
+</form>
+[% ELSE %]
+<div id="pay_fines_now">
     [% IF last_chance %]
     
     <p><big>[% l("Are you sure you are ready to charge ") %]
@@ -85,11 +173,7 @@
         <a href="[% mkurl(ctx.opac_root _ '/myopac/main#selected_fines', {}, 1) %]" class="opac-button">[% l('Cancel') %]</a>
     [% ELSE %]
     
-    <form method="post" id="payment_form" action='#payment'
-    [% IF ctx.use_stripe %]
-    onsubmit="return stripe_onsubmit();"
-    [% END %]
-    >
+    <form method="post" id="payment_form" action='#payment'>
         <input type="hidden" name="last_chance" value="1" />
         [% FOR xact IN CGI.param('xact') %]
         <input type="hidden" name="xact" value="[% xact | html %]" />
@@ -97,9 +181,6 @@
         [% FOR xact IN CGI.param('xact_misc') %]
         <input type="hidden" name="xact_misc" value="[% xact | html %]" />
         [% END %]
-        [% IF ctx.use_stripe %]
-        <input type="hidden" name="stripe_token" id="stripe_token" />
-        [% END %]
 
          <table id="billing_info_table">
           <tbody>
@@ -161,36 +242,18 @@
                     <td><label for="payment-credit-card">[% l('Credit Card #') %]</label></td>
                     
                      <!-- Make type tel, which prompts for numbers in mobile -->
-                    <td><input type="tel" pattern="[0-9]*" maxlength="16" id="payment-credit-card" required 
-                    [% IF ctx.use_stripe %]
-                    data-stripe="number"
-                    [% ELSE %]
-                    name="number"
-                    [% END %]
-                    /></td>
+                    <td><input type="tel" pattern="[0-9]*" maxlength="16" id="payment-credit-card" required name="number"/></td>
                 </tr>
                 <tr>
                     <td><label for="payment-security-code">[% l('Security Code') %]</label></td>
                     <td>
                          <!-- Make type tel, which prompts for numbers in mobile -->
-                        <input type="tel" pattern="[0-9]*" size="4" maxlength="5" id="payment-security-code"
-                        [% IF ctx.use_stripe %]
-                        data-stripe="cvc"
-                        [% ELSE %]
-                        name="cvv2"
-                        [% END %]
-                        /></td>
+                        <input type="tel" pattern="[0-9]*" size="4" maxlength="5" id="payment-security-code" name="cvv2"/></td>
                 </tr>
                 <tr>
                     <td><label for="payment-expire-month">[% l('Expiration Month') %]</label></td>
                     <td>
-                        <select id="payment-expire-month" required
-                        [% IF ctx.use_stripe %]
-                        data-stripe="exp_month"
-                        [% ELSE %]
-                        name="expire_month"
-                        [% END %]
-                        >
+                        <select id="payment-expire-month" required name="expire_month">
                             <option value="-1"></option>
                             <option value="01">[% l("January (1)") %]</option>
                             <option value="02">[% l("February (2)") %]</option>
@@ -210,13 +273,7 @@
                 <tr>
                     <td><label for="payment-expire-year">[% l('Expiration Year') %]</label></td>
                     <td>
-                        <select id="payment-expire-year"
-                        [%- IF ctx.use_stripe %]
-                        data-stripe="exp_year"
-                        [% ELSE %]
-                        name="expire_year"
-                        [% END -%]
-                        >
+                        <select id="payment-expire-year" name="expire_year">
                         [% year = date.format(date.now, '%Y');
                         y = year;
                         WHILE y < year + 10; # show ten years starting now %]
@@ -249,3 +306,4 @@
 </div>
 [% END %]
 [% END %]
+[% END %]
diff --git a/Open-ILS/src/templates/opac/parts/stripe.tt2 b/Open-ILS/src/templates/opac/parts/stripe.tt2
index ea4ca04a61..29fea86025 100644
--- a/Open-ILS/src/templates/opac/parts/stripe.tt2
+++ b/Open-ILS/src/templates/opac/parts/stripe.tt2
@@ -1,35 +1,9 @@
 [%- PROCESS "opac/parts/header.tt2" %]
 [% IF ctx.use_stripe %]
-        <script type="text/javascript" src="https://js.stripe.com/v2/"></script> <!-- use an ou setting for this url? -->
+        <script type="text/javascript" src="https://js.stripe.com/v3/"></script> <!-- use an ou setting for this url? -->
         <script type="text/javascript">
         // This script is only displayed when logged in, so ctx.user.home_ou is always available
-        Stripe.setPublishableKey('[% ctx.get_org_setting(ctx.user.home_ou.id, 'credit.processor.stripe.pubkey') %]');
+        var stripe = Stripe('[% ctx.get_org_setting(ctx.user.home_ou.id, 'credit.processor.stripe.pubkey') %]');
 
-        function stripe_onsubmit() {
-            var form = document.getElementById("payment_form");
-            var button = document.getElementById("payment_submit");
-
-            button.disabled = true;
-
-            Stripe.card.createToken(form, stripe_callback);
-
-            return false;
-        }
-
-        function stripe_callback(status, response) {
-            var form = document.getElementById("payment_form");
-            var button = document.getElementById("payment_submit");
-            var stripe_token = document.getElementById("stripe_token");
-
-            if(response.error) {
-                alert(response.error.message);
-                button.disabled = false;
-                return;
-            }
-
-            stripe_token.value = response.id; // response.id is the token id, though there are more fields available if needed.
-            form.setAttribute("onsubmit","");
-            form.submit();
-        }
         </script>
 [%- END %]
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_cc_payment_dialog.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_cc_payment_dialog.tt2
index 1551f56b94..4511b51357 100644
--- a/Open-ILS/src/templates/staff/circ/patron/t_cc_payment_dialog.tt2
+++ b/Open-ILS/src/templates/staff/circ/patron/t_cc_payment_dialog.tt2
@@ -13,7 +13,7 @@
         <div class="col-md-4"><label>[% l('Process Where?') %]</label></div>
         <div class="col-md-8">
           <select class="form-control" ng-model="context.cc.where_process">
-            <option value='1'>
+            <option value='1' ng-disabled="context.cc.disable_internal">
               [% l('Process payment through Evergreen') %]</option>
             <option value='0'>
               [% l('Record externally processed payment') %]</option>
diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js b/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
index 539fe6cc69..f9a6d66700 100644
--- a/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
+++ b/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
@@ -16,7 +16,8 @@ function($q , egCore , egWorkLog , patronSvc) {
             'ui.circ.billing.uncheck_bills_and_unfocus_payment_box',
             'ui.circ.billing.amount_warn', 'ui.circ.billing.amount_limit',
             'circ.staff_client.do_not_auto_attempt_print',
-            'circ.disable_patron_credit'
+            'circ.disable_patron_credit',
+            'credit.processor.default'
         ]).then(function(s) {return service.settings = s});
     }
 
@@ -543,6 +544,13 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
         if (s['circ.disable_patron_credit']) {
             $scope.disablePatronCredit = true;
         }
+        if (!s['credit.processor.default']) {
+            // If we don't have a CC processor, we should disable the "internal" CC form
+            $scope.disableCreditCardForm = true;
+        } else {
+            // Stripe isn't supported in the staff client currently, so disable here too
+            $scope.disableCreditCardForm = (s['credit.processor.default'] == 'Stripe');
+        }
     });
 
     $scope.gridControls.allItemsRetrieved = function() {
@@ -691,6 +699,8 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
         if ($scope.payment_type != 'credit_card_payment') 
             return $q.when();
 
+        var disableCreditCardForm = $scope.disableCreditCardForm;
+
         return $uibModal.open({
             templateUrl : './circ/patron/t_cc_payment_dialog',
             backdrop: 'static',
@@ -700,7 +710,8 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
 
                     $scope.context = {
                         cc : {
-                            where_process : '1', // internal=1 ; external=0
+                            where_process : disableCreditCardForm ? '0' : '1', // internal=1 ; external=0
+                            disable_internal : disableCreditCardForm,
                             type : 'VISA', // external only
                             billing_first : patronSvc.current.first_given_name(),
                             billing_last : patronSvc.current.family_name()

-----------------------------------------------------------------------

Summary of changes:
 Open-ILS/src/templates/opac/css/style.css.tt2      |  11 +
 .../templates/opac/myopac/generic_payment_form.tt2 | 128 +++++++++++
 .../src/templates/opac/myopac/last_chance_form.tt2 |  55 +++++
 .../templates/opac/myopac/main_payment_form.tt2    | 234 +--------------------
 .../templates/opac/myopac/stripe_payment_form.tt2  | 102 +++++++++
 Open-ILS/src/templates/opac/parts/stripe.tt2       |  30 +--
 .../staff/circ/patron/t_cc_payment_dialog.tt2      |   2 +-
 .../web/js/ui/default/staff/circ/patron/bills.js   |  15 +-
 docs/RELEASE_NOTES_NEXT/OPAC/stripe-v3.adoc        |  11 +
 9 files changed, 331 insertions(+), 257 deletions(-)
 create mode 100644 Open-ILS/src/templates/opac/myopac/generic_payment_form.tt2
 create mode 100644 Open-ILS/src/templates/opac/myopac/last_chance_form.tt2
 create mode 100644 Open-ILS/src/templates/opac/myopac/stripe_payment_form.tt2
 create mode 100644 docs/RELEASE_NOTES_NEXT/OPAC/stripe-v3.adoc


hooks/post-receive
-- 
Evergreen ILS



More information about the open-ils-commits mailing list