Initial commit
diff --git a/assets/css/index.html b/assets/css/index.html
new file mode 100644
index 0000000..4fad5e3
--- /dev/null
+++ b/assets/css/index.html
@@ -0,0 +1,12 @@
+<html><head><title> - Revision 2844313: /woocommerce-gateway-stripe/trunk/assets/css</title></head>
+<body>
+ <h2> - Revision 2844313: /woocommerce-gateway-stripe/trunk/assets/css</h2>
+ <ul>
+ <li><a href="../">..</a></li>
+ <li><a href="stripe-link.css">stripe-link.css</a></li>
+ <li><a href="stripe-link.scss">stripe-link.scss</a></li>
+ <li><a href="stripe-styles.css">stripe-styles.css</a></li>
+ <li><a href="stripe-styles.scss">stripe-styles.scss</a></li>
+ </ul>
+ <hr noshade><em>Powered by <a href="http://subversion.apache.org/">Apache Subversion</a> version 1.9.5 (r1770682).</em>
+</body></html>
\ No newline at end of file
diff --git a/assets/css/stripe-link.css b/assets/css/stripe-link.css
new file mode 100644
index 0000000..7989ea5
--- /dev/null
+++ b/assets/css/stripe-link.css
@@ -0,0 +1 @@
+.stripe-gateway-checkout-email-field{position:relative}.stripe-gateway-checkout-email-field button.stripe-gateway-stripelink-modal-trigger{display:none;position:absolute;right:5px;width:64px;height:40px;background:no-repeat url(../images/link.svg);background-color:transparent;cursor:pointer;border:none}
\ No newline at end of file
diff --git a/assets/css/stripe-link.scss b/assets/css/stripe-link.scss
new file mode 100644
index 0000000..26254c3
--- /dev/null
+++ b/assets/css/stripe-link.scss
@@ -0,0 +1,16 @@
+.stripe-gateway-checkout-email-field {
+ position: relative;
+}
+
+.stripe-gateway-checkout-email-field button.stripe-gateway-stripelink-modal-trigger {
+ display: none;
+ position: absolute;
+ right: 5px;
+ width: 64px;
+ height: 40px;
+ background: no-repeat
+ url( '../images/link.svg' );
+ background-color: transparent;
+ cursor: pointer;
+ border: none;
+}
\ No newline at end of file
diff --git a/assets/css/stripe-styles.css b/assets/css/stripe-styles.css
new file mode 100644
index 0000000..edd49e8
--- /dev/null
+++ b/assets/css/stripe-styles.css
@@ -0,0 +1 @@
+.wc-stripe-elements-field,.wc-stripe-iban-element-field{border:1px solid #ddd;margin:5px 0;padding:5px;background-color:#fff;outline:0}#payment .methods li.woocommerce-SavedPaymentMethods-token label{display:inline}#payment .methods li.woocommerce-SavedPaymentMethods-new label{display:inline}#add_payment_method #payment ul.payment_methods li img.stripe-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-icon{max-width:40px;padding-left:3px;margin:0}#add_payment_method #payment ul.payment_methods li img.stripe-bancontact-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-bancontact-icon{max-height:65px;max-width:45px}#add_payment_method #payment ul.payment_methods li img.stripe-ideal-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-ideal-icon{max-height:35px}#add_payment_method #payment ul.payment_methods li img.stripe-p24-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-p24-icon{max-width:65px}#add_payment_method #payment ul.payment_methods li img.stripe-alipay-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-alipay-icon{max-width:50px}#add_payment_method #payment ul.payment_methods li img.stripe-sofort-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-sofort-icon{max-width:55px}#add_payment_method #payment ul.payment_methods li img.stripe-sepa-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-sepa-icon{max-width:50px}#add_payment_method #payment ul.payment_methods li img.stripe-multibanco-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-multibanco-icon{max-height:30px}#add_payment_method #payment ul.payment_methods li img.stripe-eps-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-eps-icon{max-height:30px}#add_payment_method #payment ul.payment_methods li img.stripe-giropay-icon,.woocommerce-checkout #payment ul.payment_methods li img.stripe-giropay-icon{max-width:50px}#add_payment_method #payment ul.payment_methods li .stripe-credit-card-brand,.woocommerce-checkout #payment ul.payment_methods li .stripe-credit-card-brand{position:absolute;top:50%;margin-top:-10px;right:10px;background:no-repeat url(../images/credit-card.svg);display:block;width:30px;height:24px}#add_payment_method #payment ul.payment_methods li .stripe-visa-brand,.woocommerce-checkout #payment ul.payment_methods li .stripe-visa-brand{position:absolute;top:50%;margin-top:-10px;right:10px;background:no-repeat url(../images/visa.svg);display:block;width:30px;height:24px}#add_payment_method #payment ul.payment_methods li .stripe-amex-brand,.woocommerce-checkout #payment ul.payment_methods li .stripe-amex-brand{position:absolute;top:50%;margin-top:-10px;right:10px;background:no-repeat url(../images/amex.svg);display:block;width:30px;height:24px}#add_payment_method #payment ul.payment_methods li .stripe-diners-brand,.woocommerce-checkout #payment ul.payment_methods li .stripe-diners-brand{position:absolute;top:50%;margin-top:-10px;right:10px;background:no-repeat url(../images/diners.svg);display:block;width:30px;height:24px}#add_payment_method #payment ul.payment_methods li .stripe-discover-brand,.woocommerce-checkout #payment ul.payment_methods li .stripe-discover-brand{position:absolute;top:50%;margin-top:-10px;right:10px;background:no-repeat url(../images/discover.svg);display:block;width:30px;height:24px}#add_payment_method #payment ul.payment_methods li .stripe-jcb-brand,.woocommerce-checkout #payment ul.payment_methods li .stripe-jcb-brand{position:absolute;top:50%;margin-top:-10px;right:10px;background:no-repeat url(../images/jcb.svg);display:block;width:30px;height:24px}#add_payment_method #payment ul.payment_methods li .stripe-maestro-brand,.woocommerce-checkout #payment ul.payment_methods li .stripe-maestro-brand{position:absolute;top:50%;margin-top:-10px;right:10px;background:no-repeat url(../images/maestro.svg);display:block;width:30px;height:24px}#add_payment_method #payment ul.payment_methods li .stripe-mastercard-brand,.woocommerce-checkout #payment ul.payment_methods li .stripe-mastercard-brand{position:absolute;top:50%;margin-top:-10px;right:10px;background:no-repeat url(../images/mastercard.svg);display:block;width:30px;height:24px}#add_payment_method #payment ul.payment_methods .stripe-card-group,.woocommerce-checkout #payment ul.payment_methods .stripe-card-group{position:relative}.woocommerce-SavedPaymentMethods-token .stripe-source-errors .woocommerce-error{margin-top:1em;margin-bottom:2em}#wc-stripe-custom-button{display:block;width:100%}.woocommerce-checkout #payment #stripe_boleto_tax_id{width:100%}.gpay-button{background-origin:content-box;background-position:center center;background-repeat:no-repeat;background-size:contain;border:0;border-radius:4px;cursor:pointer;height:40px;min-height:40px;padding:11px 24px;width:100%}.gpay-button.light{width:calc(100% - 3px);background-color:#fff;margin:2px 0 3px 0}.gpay-button.light:active{background-color:#fff}.gpay-button.light:hover{background-color:#f8f8f8}.gpay-button.light:focus{box-shadow:#e8e8e8 0 1px 1px 0,#e8e8e8 0 1px 3px;outline:0}.gpay-button.light-outline{width:calc(100% - 3px);background-color:#fff;box-shadow:rgba(60,64,67,.3) 0 1px 1px 0,rgba(60,64,67,.15) 0 1px 3px 1px;margin:2px 0 3px 0}.gpay-button.light-outline:active{background-color:#fff}.gpay-button.light-outline:hover{background-color:#f8f8f8}.gpay-button.light-outline:focus{box-shadow:#e8e8e8 0 1px 1px 0,#e8e8e8 0 1px 3px;outline:0}.gpay-button.dark{background-color:#000;padding:12px 24px 10px}.gpay-button.dark:active{background-color:#5f6368}.gpay-button.dark:hover{background-color:#3c4043}.gpay-button.dark:focus{box-shadow:#5f6368 0 1px 1px 0,#5f6368 0 1px 3px;outline:0}.gpay-button.short.light,.gpay-button.short.light-outline{background-image:url(https://www.gstatic.com/instantbuy/svg/light_gpay.svg)}.gpay-button.short.dark{background-image:url(https://www.gstatic.com/instantbuy/svg/dark_gpay.svg)}
\ No newline at end of file
diff --git a/assets/css/stripe-styles.scss b/assets/css/stripe-styles.scss
new file mode 100644
index 0000000..b8ecfe9
--- /dev/null
+++ b/assets/css/stripe-styles.scss
@@ -0,0 +1,268 @@
+// TODO: Refactor this file to use SCSS syntax.
+.wc-stripe-elements-field,
+.wc-stripe-iban-element-field {
+ border: 1px solid #ddd;
+ margin: 5px 0;
+ padding: 5px;
+ background-color: #fff;
+ outline: 0;
+}
+#payment .methods li.woocommerce-SavedPaymentMethods-token label {
+ display: inline;
+}
+#payment .methods li.woocommerce-SavedPaymentMethods-new label {
+ display: inline;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-icon {
+ max-width: 40px;
+ padding-left: 3px;
+ margin: 0;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-bancontact-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-bancontact-icon {
+ max-height: 65px;
+ max-width: 45px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-ideal-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-ideal-icon {
+ max-height: 35px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-p24-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-p24-icon {
+ max-width: 65px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-alipay-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-alipay-icon {
+ max-width: 50px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-sofort-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-sofort-icon {
+ max-width: 55px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-sepa-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-sepa-icon {
+ max-width: 50px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-multibanco-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-multibanco-icon {
+ max-height: 30px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-eps-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-eps-icon {
+ max-height: 30px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li img.stripe-giropay-icon,
+#add_payment_method #payment ul.payment_methods li img.stripe-giropay-icon {
+ max-width: 50px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li .stripe-credit-card-brand,
+#add_payment_method #payment ul.payment_methods li .stripe-credit-card-brand {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ right: 10px;
+ background: no-repeat url( '../images/credit-card.svg' );
+ display: block;
+ width: 30px;
+ height: 24px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li .stripe-visa-brand,
+#add_payment_method #payment ul.payment_methods li .stripe-visa-brand {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ right: 10px;
+ background: no-repeat url( '../images/visa.svg' );
+ display: block;
+ width: 30px;
+ height: 24px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li .stripe-amex-brand,
+#add_payment_method #payment ul.payment_methods li .stripe-amex-brand {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ right: 10px;
+ background: no-repeat url( '../images/amex.svg' );
+ display: block;
+ width: 30px;
+ height: 24px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li .stripe-diners-brand,
+#add_payment_method #payment ul.payment_methods li .stripe-diners-brand {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ right: 10px;
+ background: no-repeat url( '../images/diners.svg' );
+ display: block;
+ width: 30px;
+ height: 24px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li .stripe-discover-brand,
+#add_payment_method #payment ul.payment_methods li .stripe-discover-brand {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ right: 10px;
+ background: no-repeat url( '../images/discover.svg' );
+ display: block;
+ width: 30px;
+ height: 24px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li .stripe-jcb-brand,
+#add_payment_method #payment ul.payment_methods li .stripe-jcb-brand {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ right: 10px;
+ background: no-repeat url( '../images/jcb.svg' );
+ display: block;
+ width: 30px;
+ height: 24px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li .stripe-maestro-brand,
+#add_payment_method #payment ul.payment_methods li .stripe-maestro-brand {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ right: 10px;
+ background: no-repeat url( '../images/maestro.svg' );
+ display: block;
+ width: 30px;
+ height: 24px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods li .stripe-mastercard-brand,
+#add_payment_method #payment ul.payment_methods li .stripe-mastercard-brand {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ right: 10px;
+ background: no-repeat url( '../images/mastercard.svg' );
+ display: block;
+ width: 30px;
+ height: 24px;
+}
+
+.woocommerce-checkout #payment ul.payment_methods .stripe-card-group,
+#add_payment_method #payment ul.payment_methods .stripe-card-group {
+ position: relative;
+}
+
+.woocommerce-SavedPaymentMethods-token
+ .stripe-source-errors
+ .woocommerce-error {
+ margin-top: 1em;
+ margin-bottom: 2em;
+}
+
+#wc-stripe-custom-button {
+ display: block;
+ width: 100%;
+}
+
+.woocommerce-checkout #payment #stripe_boleto_tax_id {
+ width: 100%;
+}
+
+.gpay-button {
+ background-origin: content-box;
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: contain;
+ border: 0;
+ border-radius: 4px;
+ cursor: pointer;
+ height: 40px;
+ min-height: 40px;
+ padding: 11px 24px;
+ width: 100%;
+
+ &.light {
+ // account for button box-shadow when setting width
+ width: calc( 100% - 3px );
+ background-color: #fff;
+
+ // Add vertical margin to make box-shadow visible in blocks.
+ margin: 2px 0 3px 0;
+
+ &:active {
+ background-color: #fff;
+ }
+ &:hover {
+ background-color: #f8f8f8;
+ }
+ &:focus {
+ box-shadow: #e8e8e8 0 1px 1px 0, #e8e8e8 0 1px 3px;
+ outline: 0;
+ }
+ }
+
+ &.light-outline {
+ // account for button box-shadow when setting width
+ width: calc( 100% - 3px );
+ background-color: #fff;
+
+ // The box-shadow forms the outline and as such is always on.
+ box-shadow: rgba( 60, 64, 67, 0.3 ) 0px 1px 1px 0,
+ rgba( 60, 64, 67, 0.15 ) 0 1px 3px 1px;
+
+ // Add vertical margin to make box-shadow visible in blocks.
+ margin: 2px 0 3px 0;
+
+ &:active {
+ background-color: #fff;
+ }
+ &:hover {
+ background-color: #f8f8f8;
+ }
+ &:focus {
+ box-shadow: #e8e8e8 0 1px 1px 0, #e8e8e8 0 1px 3px;
+ outline: 0;
+ }
+ }
+
+ &.dark {
+ background-color: #000;
+ padding: 12px 24px 10px;
+ &:active {
+ background-color: #5f6368;
+ }
+ &:hover {
+ background-color: #3c4043;
+ }
+ &:focus {
+ box-shadow: #5f6368 0 1px 1px 0, #5f6368 0 1px 3px;
+ outline: 0;
+ }
+ }
+
+ &.short {
+ &.light,
+ &.light-outline {
+ background-image: url( https://www.gstatic.com/instantbuy/svg/light_gpay.svg );
+ }
+ &.dark {
+ background-image: url( https://www.gstatic.com/instantbuy/svg/dark_gpay.svg );
+ }
+ }
+}
diff --git a/assets/images/alipay.svg b/assets/images/alipay.svg
new file mode 100644
index 0000000..c2ab145
--- /dev/null
+++ b/assets/images/alipay.svg
@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 374" preserveAspectRatio="xMidYMid meet"><defs><style>.cls-1{fill:#ec6c00}.cls-2{fill:#003f96}</style></defs><path class="cls-1" d="M326 287l-8 2-7 3-5 4a10 10 0 00-3 5l2 5c2 2 5 2 5 2l6-2 2-4-2-7 4-2 6-1 6 2 4 4 1 3 1 4v5l-12 4-12 4-5 3-4 3a16 16 0 00-4 4l-1 7c0 6 5 10 5 10 5 4 12 4 12 4l9-1 3-1 9-7a10 10 0 004 6c3 3 8 3 8 3l5-1 6-2v-3h-4l-4-1-2-2-1-4v-29l-1-10-6-6-7-3-10-1zm12 28v21l-6 4-6 3h-3a10 10 0 01-7-3c-2-2-2-7-2-7a13 13 0 011-6l6-5 7-4 10-3zm23-26h29v4l-4 1-3 2v1l16 35 16-34-3-3-6-2v-4h24v4l-5 2a14 14 0 00-5 5l-13 30-17 32-7 8-5 3-5 1s-5 0-8-2a6 6 0 01-2-5l1-5a8 8 0 015-2l3 1 3 1 4 5 8-8s6-10 4-18l-19-42-5-4-6-2v-4m-100-1l-8 2-9 6v-7l-1-1-22 2v4h4l3 1 3 3 1 3v63l-1 3-3 2-3 1h-4v4h36v-4l-9-2-3-2-1-3v-18l7 3 9 1h1l11-2 9-7 7-9 2-13-2-12a33 33 0 00-6-10 27 27 0 00-8-6l-11-2zm0 8c9 1 13 8 13 8 5 5 4 14 4 14a26 26 0 01-4 14c-5 7-13 8-13 8-7 1-17-5-17-5v-34a43 43 0 0117-5zM95 262l-30 71-3 5-4 3-5 2h-4v4h35v-4l-9-1c-4-2-4-4-4-4v-2l6-18h33l7 19 1 2v1c0 2-3 2-3 2l-9 1v4h39v-4h-4l-4-1-4-4a7 7 0 01-2-3l-31-73zm-2 19h1l13 32H80zm102 0a8 8 0 01-6-3 8 8 0 01-3-5 9 9 0 013-6 9 9 0 016-2 10 10 0 016 2l2 5-2 6a10 10 0 01-6 3m11 9v47l1 3 3 2 6 2v3h-31v-3l5-1 3-2 1-3v-36l-1-4-3-3-3-1h-4v-4l22-2 1 1m-40-33l-23 1h-1v4h1l4 1 4 1 3 3 1 4v68l-1 3-3 2-6 1v3h31v-3l-3-1-3-1-2-1-1-4v-80l-1-1m424 34l22-2 1 2v8l4-4 5-3a23 23 0 015-3h7l11 3 7 7 4-4 5-3a24 24 0 015-3h8s8 0 13 5c0 0 5 5 5 14v33l3 3h3l4 1v3h-32v-3l6-1 3-2v-33s0-7-3-10a12 12 0 00-7-3h-7l-5 3-3 3-2 3v33l1 3 3 3h3l3 1v3h-31v-3l5-1 3-2 1-3v-30s0-7-3-10a11 11 0 00-8-3h-6l-5 3-3 3-2 2v34l1 3 2 2 3 1 3 1v3h-31v-3l6-1 3-2 1-3v-37l-1-3-3-3-3-1h-4v-4m-126 31s0 11 6 18c0 0 6 8 15 8l12-3 9-9 4 3a37 37 0 01-12 11 36 36 0 01-16 4s-15 0-23-8a35 35 0 01-9-24 35 35 0 012-12 36 36 0 017-10 38 38 0 0110-7 40 40 0 0114-3s10 0 17 4c0 0 6 5 6 12l-2 5-5 3-7-2-2-4 1-6 1-4-4-3h-5l-7 1-6 5-4 8a44 44 0 00-2 13m85-32a40 40 0 00-24 9c-9 9-9 23-9 23a37 37 0 002 14l8 10a39 39 0 0010 7l13 2 15-3a34 34 0 0010-7l7-10 3-13a33 33 0 00-10-23c-9-9-24-9-24-9h-1zm0 5h1l9 2 6 6 3 9 1 10c0 13-5 21-5 21a19 19 0 01-14 7h-1l-8-2-6-7-4-9a61 61 0 01-1-11l1-9 3-9a26 26 0 017-6 21 21 0 018-2zm-118 55a5 5 0 005-5s0-6-5-6c0 0-6 0-6 6 0 0 0 5 6 5"/><path d="M701 0v2h5v16h3V2h5V0zm16 0v18h2V3l6 15h2l5-15v15h2V0h-3l-5 15-6-15z"/><path class="cls-2" d="M586 0l-9 1s-10 2-10 6v14l-41 1v-7h-19s-18 1-18 7v51h78v35h-54v14h54v80l40-5v-75h58v-14h-58V73h68v-7h2s5 0 8-9l3-23s0-17-18-17l-63 3V0zm62 32a6 6 0 016 6l-3 21H526V36l41-1 40-1z"/><path class="cls-1" d="M342 108l12 15 15 13s5 4 9 0l14-13 13-15s5-4 0-9l-12-15-15-13s-4-4-9 0l-14 13-13 15s-4 5 0 9m335 46a6 6 0 000-7l-10-11-12-10a5 5 0 00-6 0l-11 10-10 11s-3 3 0 7l10 11 11 10s3 3 6 0l12-10 10-11"/><path class="cls-2" d="M78 91h120a166 166 0 01-13 31s-15 29-38 51c0 0-43 40-71 40 0 0-20 0-34-7 0 0-16-10-16-31 0 0 0-28 42-36 0 0-27-2-41 13 0 0-14 12-14 34 0 0 0 21 19 34a79 79 0 0042 11h6s47-2 91-39c0 0 38-31 57-76a188 188 0 009-28l2-11h-65V46h82V33h-82V1h-21l-9 1s-10 2-10 6v25H56v13h78v31H78v14M346 0v7l-5 16a95 95 0 01-12 20v158l-40-5V71l-28 12-5-8a238 238 0 0027-23s27-27 27-45c0 0 0-4 9-6l9-1h18"/><path class="cls-2" d="M335 60h76v146h40V60h21V46h-21V0h-22l-9 1s-9 2-9 6v39h-76v14"/><path class="cls-1" d="M153 145s-51-22-83-23c0 0-26-2-47 13 0 0-22 16-23 39 0 0 0 27 22 43 0 0 20 14 52 14h3-5s-24 0-40-12c0 0-18-13-18-34 0 0 0-23 16-35 0 0 13-10 35-10l31 4 25 9 57 29s40 21 77 33c0 0 132 44 425 15l16-3s6-2 10-9c0 0 4-6 30-30 0 0 19-17 13-22l-9 1s-96 22-243 28c0 0-164 6-246-17 0 0-56-16-98-33"/></svg>
\ No newline at end of file
diff --git a/assets/images/amex.svg b/assets/images/amex.svg
new file mode 100644
index 0000000..869b167
--- /dev/null
+++ b/assets/images/amex.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 752 471" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="#2557D6" x="1" width="750" height="471" rx="40"/><path d="M1 221h36l8-19h18l8 19h71v-15l7 15h36l7-15v15h176v-32h3c3 0 3 0 3 4v28h91v-7c8 4 19 7 34 7h39l8-19h18l8 19h74v-18l11 18h59V99h-58v14l-9-14h-60v14l-7-14h-81c-14 0-26 2-36 7v-7h-56v7c-6-6-14-7-23-7H181l-14 31-14-31H89v14l-7-14H27L1 157v64zm227-17h-21v-69l-31 69h-18l-31-69v69H84l-8-20H32l-8 20H1l38-88h31l36 83v-83h34l28 59 25-59h35v88zM69 166l-15-35-14 35h29zm245 38h-70v-88h70v18h-49v16h48v18h-48v17h49v19zm100-65c0 14-10 22-15 24 4 1 8 5 10 7 3 5 4 8 4 16v18h-22v-12c0-5 1-12-3-17-3-3-8-3-15-3h-23v32h-21v-88h48c11 0 19 0 26 4s11 10 11 19zm-27 13c-3 2-6 2-10 2h-26v-19h26l10 1c3 2 4 4 4 8s-1 7-4 8zm60 52h-21v-88h21v88zm250 0h-30l-40-66v66h-43l-8-20h-44l-8 20h-24c-10 0-23-3-31-10-7-8-11-18-11-34 0-13 2-25 11-34 7-7 18-10 32-10h21v18h-20c-8 0-12 2-16 6-4 3-6 10-6 20 0 9 1 16 5 20s9 5 15 5h9l30-69h32l35 83v-83h33l37 61v-61h21v88zm-128-38l-15-35-14 35h29zm182 178c-5 7-15 11-29 11h-40v-19h40c4 0 7 0 9-2l2-6-2-6-8-1c-20-1-44 0-44-28 0-12 8-26 30-26h42v-17h-39c-12 0-20 2-26 7v-7h-58c-9 0-20 2-25 7v-7H500v7c-9-6-22-7-29-7h-68v7c-6-6-21-7-30-7h-76l-17 18-16-18H150v122h112l17-19 17 19h69v-29h7c9 1 20 0 29-4v33h57v-32h3c3 0 3 0 3 4v28h173c11 0 22-3 28-8v8h55c11 0 23-1 31-5v-23zm-342-47c0 24-18 29-36 29h-27v30h-41l-26-30-26 30h-84v-88h85l26 28 27-28h67c17 0 35 4 35 29zm-167 40h-52v-17h46v-18h-46v-16h53l23 25-24 26zm83 10l-32-36 32-34v70zm48-39h-27v-22h27c8 0 13 3 13 10 0 8-5 12-13 12zm143-40h70v18h-49v16h48v18h-48v17h49v19h-70v-88zm-27 47c5 1 8 5 10 7 3 4 4 8 4 16v18h-21v-11c0-6 0-14-4-18-3-3-8-4-15-4h-23v33h-21v-88h49c10 0 18 0 25 4s11 9 11 19c0 14-10 22-15 24zm-12-11l-10 1h-26v-19h26l10 1c3 2 4 4 4 8s-1 7-4 9zm190 5c4 4 7 10 7 19 0 19-12 28-33 28h-42v-19h41l9-2 2-6-2-6-8-2c-19-1-44 1-44-27 0-13 8-26 30-26h42v18h-38l-9 2c-2 1-3 3-3 6 0 4 2 6 5 7l8 1h11c12 0 20 2 24 7zm84-23h-38l-9 1c-2 2-3 4-3 7s2 5 5 6l8 1h11c12 1 19 3 24 7l2 3v-25z" fill="#FFF"/></g></svg>
\ No newline at end of file
diff --git a/assets/images/bancontact.svg b/assets/images/bancontact.svg
new file mode 100644
index 0000000..b545374
--- /dev/null
+++ b/assets/images/bancontact.svg
@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 530" preserveAspectRatio="xMidYMid meet"><defs><style>.cls-2{fill:#005498}</style></defs><path d="M750 485a46 46 0 01-46 45H46a46 46 0 01-46-45V46A46 46 0 0146 0h658a46 46 0 0146 46v439z" fill="#fff"/><path class="cls-2" d="M603 148H422l-18 21-59 67-19 20H149l18-20 8-10 18-21h-81c-15 0-28 12-28 28v58c0 16 13 28 28 28h313c15 0 35-9 45-20l47-54z"/><path d="M639 85c15 0 27 13 27 28v59c0 15-12 28-27 28h-82l18-21 9-10 19-21H422l-95 108H148l128-145 5-5c10-12 30-21 45-21h313z" fill="#ffd800"/><path class="cls-2" d="M666 443v-9l-2-2h-6l-3-1v-36h9a2 2 0 002-3v-9a2 2 0 00-2-2h-9v-12a2 2 0 00-1-1 3 3 0 00-1 0h-1l-13 2a11 11 0 00-1 1 2 2 0 00-1 1v9h-9a2 2 0 00-2 2v8a1 1 0 000 1 4 4 0 002 1l9 1v32a37 37 0 001 10 15 15 0 003 6 12 12 0 006 3 42 42 0 008 0 26 26 0 005 0l4-1a2 2 0 002-1m-48-2v-10a1 1 0 00-1-1 3 3 0 00-1 0 57 57 0 01-6 0 70 70 0 01-8 0 8 8 0 01-3 0 9 9 0 01-3-2 9 9 0 01-2-4 23 23 0 01-1-7v-9a23 23 0 011-6 12 12 0 012-4 9 9 0 013-2 9 9 0 013-1 70 70 0 018 1h6a2 2 0 001 0 1 1 0 001-2v-10a2 2 0 000-1 7 7 0 00-2-1l-6-1a50 50 0 00-9-1c-8 0-14 2-19 7s-7 12-7 21v9c0 9 2 17 7 21 5 5 11 7 19 7h9a56 56 0 006-1 3 3 0 002-1v-2m-72-11a25 25 0 01-4 1 18 18 0 01-5 1l-5-1c-1-1-2-2-2-5v-1a14 14 0 010-3 6 6 0 012-2 6 6 0 013-2 24 24 0 015 0h6v12zm17-27a27 27 0 00-1-11 19 19 0 00-5-7 19 19 0 00-8-3 40 40 0 00-11-2 83 83 0 00-11 1 48 48 0 00-8 1c-2 1-2 2-2 3v9a3 3 0 000 2 3 3 0 001 0h8l6-1h5a11 11 0 016 2l2 6v4h-6c-9 0-16 1-20 4-5 3-7 8-7 15l2 9a17 17 0 004 6 19 19 0 006 4 24 24 0 007 1 24 24 0 009-2 34 34 0 007-3v1a2 2 0 002 3h12a2 2 0 003-3v-39zm-59 40v-9c0-1 0-2-2-2h-5l-3-1-1-4v-32h9a2 2 0 002-3v-9a2 2 0 00-2-2h-9v-12a2 2 0 000-1 3 3 0 00-2 0l-13 2a11 11 0 00-2 1 2 2 0 00-1 1v9h-9a2 2 0 00-2 2v8a1 1 0 001 1 4 4 0 001 1l9 1v32a37 37 0 001 10 15 15 0 004 6 12 12 0 006 3 42 42 0 008 0 26 26 0 004 0l4-1 2-1m-48-1v-36a47 47 0 00-1-10 22 22 0 00-3-8 13 13 0 00-6-6 20 20 0 00-10-2 30 30 0 00-9 2 32 32 0 00-9 4v-3a2 2 0 00-2-2h-13a2 2 0 00-2 2v59a2 2 0 002 3h14a2 2 0 002-3v-43a59 59 0 016-3 13 13 0 015-1 21 21 0 014 1 5 5 0 012 1 7 7 0 011 4 31 31 0 011 4v37a2 2 0 002 3h13a2 2 0 002-1 2 2 0 001-2m-84-25c0 9-3 13-10 13-3 0-5-1-7-3s-2-6-2-10v-8c0-5 0-8 2-10s4-4 7-4c7 0 10 5 10 14zm18-8a38 38 0 00-2-12 25 25 0 00-5-9 23 23 0 00-9-6 36 36 0 00-23 0 23 23 0 00-9 6 25 25 0 00-6 9 38 38 0 00-1 12v8a38 38 0 001 12 25 25 0 006 9 23 23 0 009 5 36 36 0 0023 0 23 23 0 009-5 25 25 0 005-9 38 38 0 002-12zm-61 32v-10a1 1 0 00-1-1 3 3 0 00-1 0h-1a57 57 0 01-6 0 70 70 0 01-7 0 8 8 0 01-4 0 9 9 0 01-3-2 9 9 0 01-2-4 23 23 0 010-7v-9a23 23 0 010-6 12 12 0 012-4 9 9 0 013-2 9 9 0 014-1 70 70 0 017 1h7a3 3 0 001 0 1 1 0 001-2v-10a2 2 0 00-1-1 7 7 0 00-1-1l-6-1a50 50 0 00-9-1c-8 0-14 2-19 7s-7 12-7 21v9c0 9 2 17 7 21 5 5 11 7 19 7h9l6-1a3 3 0 001-1 3 3 0 001-2m-55 1v-37a47 47 0 00-1-9 22 22 0 00-3-8 13 13 0 00-6-6 20 20 0 00-9-2 30 30 0 00-10 2 32 32 0 00-9 4v-3a2 2 0 00-2-2h-12a2 2 0 00-3 2v59a2 2 0 003 3h13a2 2 0 002-3v-43a59 59 0 016-3 13 13 0 015-1 21 21 0 014 1 5 5 0 013 1 7 7 0 011 4 31 31 0 010 4v37a2 2 0 002 3h14a2 2 0 001-1 2 2 0 001-2m-85-12a25 25 0 01-5 1 18 18 0 01-4 1l-6-1-1-5v-1a14 14 0 010-3 6 6 0 012-2 6 6 0 013-2 24 24 0 015 0h6zm18-27a27 27 0 00-2-11 19 19 0 00-5-7 19 19 0 00-8-3 40 40 0 00-11-2 83 83 0 00-11 1 48 48 0 00-8 1c-2 1-2 2-2 3v9a3 3 0 000 2 3 3 0 002 0h8l5-1h5a11 11 0 016 2c2 1 3 3 3 6v4h-6c-10 0-17 1-21 4s-6 8-6 15l1 9a17 17 0 005 6 19 19 0 006 4 24 24 0 007 1 24 24 0 008-2 34 34 0 007-3v1a2 2 0 002 3h13a2 2 0 002-3v-39zm-80 17a9 9 0 01-3 7c-2 2-6 3-12 3h-9v-21h13c4 0 7 1 9 3a11 11 0 012 7zm0-33a18 18 0 010 4 6 6 0 01-2 3 12 12 0 01-4 1 18 18 0 01-5 1h-13v-19h9l12 2a7 7 0 013 7v1zm19 32a17 17 0 00-3-10 17 17 0 00-7-6 16 16 0 007-7 20 20 0 002-9v-3a23 23 0 00-2-10 19 19 0 00-7-8 35 35 0 00-11-4 90 90 0 00-15-1h-5l-6 1a34 34 0 00-5 0h-3c-2 1-4 1-5 3l-1 5v67l1 5a10 10 0 005 3 20 20 0 004 0h5a44 44 0 005 1h6a83 83 0 0013-1 33 33 0 0011-4 22 22 0 008-8 25 25 0 003-12v-2z"/><path fill="none" d="M0 0h750v530H0z"/></svg>
\ No newline at end of file
diff --git a/assets/images/boleto.svg b/assets/images/boleto.svg
new file mode 100644
index 0000000..02f428e
--- /dev/null
+++ b/assets/images/boleto.svg
@@ -0,0 +1 @@
+<svg width="48" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M0 0h1v20H0V0Zm2 0h3v20H2V0Zm5 0H6v20h1V0Zm9 0h1v20h-1V0Zm4 0h-1v20h1V0ZM8 0h1v20H8V0Zm19 0h-1v20h1V0Zm7 0h-1v20h1V0Zm3 0h1v20h-1V0Zm3 0h-1v20h1V0Zm1 0h3v20h-3V0Zm6 0h1v20h-1V0Zm-1 0h-1v20h1V0ZM29 0h3v20h-3V0Zm-5 0h-3v20h3V0ZM14 0h1v20h-1V0Zm-1 0h-3v20h3V0Z" fill="#000"/></svg>
\ No newline at end of file
diff --git a/assets/images/credit-card.svg b/assets/images/credit-card.svg
new file mode 100644
index 0000000..88bd0bf
--- /dev/null
+++ b/assets/images/credit-card.svg
@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 471" preserveAspectRatio="xMidYMid meet"><defs><style>.cls-1{fill:#75787c}</style></defs><g id="Page-1"><g id="amex"><path class="cls-1" d="M711 40v391H41V40h670m0-40H41A40 40 0 001 40v391a40 40 0 0040 40h670a40 40 0 0040-40V40a40 40 0 00-40-40z" transform="translate(-1)" id="Rectangle-1"/></g></g><path class="cls-1" d="M11 113h728v101H11zm34 241h93v33H45zm127 0h156v33H172z"/></svg>
\ No newline at end of file
diff --git a/assets/images/diners.svg b/assets/images/diners.svg
new file mode 100644
index 0000000..c373207
--- /dev/null
+++ b/assets/images/diners.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 750 471" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="#0079BE" width="750" height="471" rx="40"/><path d="M585 238c0-99-83-168-174-168h-78a167 167 0 100 333h78c91 1 174-74 174-165z" fill="#FFF"/><path d="M333 84a152 152 0 101 305 152 152 0 00-1-305z" fill="#0079BE"/><path d="M237 236c0-41 26-76 62-90v180a97 97 0 01-62-90zm131 90V146a97 97 0 010 180z" fill="#FFF"/></g></svg>
\ No newline at end of file
diff --git a/assets/images/discover.svg b/assets/images/discover.svg
new file mode 100644
index 0000000..6249b49
--- /dev/null
+++ b/assets/images/discover.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 780 501" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M55 0C25 0 0 25 0 55v391c0 30 25 55 55 55h670c30 0 55-25 55-55V55c0-30-25-55-55-55H55z" fill="#4D4D4D"/><path d="M415 161c31 0 56 24 56 53s-25 53-56 53-56-24-56-53 25-53 56-53zm-88 1c9 0 16 2 25 6v23c-8-8-16-11-25-11-20 0-35 15-35 34 0 20 15 34 36 34 9 0 16-3 24-11v23c-9 4-16 6-25 6-32 0-56-23-56-52s25-52 56-52zm-97 1c12 0 22 3 31 11l-11 13c-5-6-10-8-16-8-9 0-16 4-16 11 0 5 4 8 16 12 24 8 31 15 31 31 0 19-15 33-37 33-15 0-27-6-36-19l13-12c5 8 13 13 23 13 9 0 15-6 15-14 0-4-2-8-6-10l-14-6c-19-6-26-13-26-27 0-16 14-28 33-28zm235 1h22l28 67 29-67h22l-45 102h-12l-44-102zm-398 0h31c33 0 56 21 56 50 0 15-7 29-19 38-10 8-22 12-38 12H67V164zm97 0h20v100h-20V164zm411 0h59v17h-38v22h36v17h-36v27h38v17h-59V164zm72 0h31c23 0 37 11 37 30 0 15-9 25-24 28l33 42h-25l-29-40h-2v40h-21V164zm21 16v30h6c13 0 20-5 20-15s-7-15-20-15h-6zm-580 1v66h5c14 0 22-3 29-8a34 34 0 000-50c-7-6-15-8-29-8h-5z" fill="#FFF"/><path d="M780 288c-26 19-221 150-559 213h504c30 0 55-25 55-55V288z" fill="#F47216"/></g></svg>
\ No newline at end of file
diff --git a/assets/images/eps.svg b/assets/images/eps.svg
new file mode 100644
index 0000000..c10c6dd
--- /dev/null
+++ b/assets/images/eps.svg
@@ -0,0 +1 @@
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" viewBox="0 0 750 577" xml:space="preserve"><style>.st0{fill:#676a6a}.st2{fill:#b40f6b}</style><symbol id="EPS-Logo" viewBox="-385 -236 770 473"><path id="XMLID_367_" class="st0" d="M219 0h-61c-7 0-13 5-13 12s6 13 13 13h93v46h-93a59 59 0 010-118h60c7 0 12-5 12-12 1-7-5-12-12-12H89c-11-21-22-39-44-48h174a60 60 0 010 119z"/><path id="XMLID_201_" class="st0" d="M-16 71c-52 0-94-42-94-95v-197h47v102h47a95 95 0 010 190zm0-142h-47v47c0 27 21 48 47 48S32 3 32-24c0-26-22-47-48-47z"/><g id="XMLID_196_"><g id="XMLID_198_"><path id="XMLID_200_" class="st2" d="M-259-119c-44 0-82 32-92 73 0 0-3 14-3 23s3 23 3 23a95 95 0 00187-23v-23h-138c8-16 24-25 43-25h125V64c0 21-16 37-37 37h-176c-20 0-37-16-37-36v-177c0-20 17-37 37-37h176c18 0 34 13 36 30h-124z"/><path id="XMLID_199_" class="st2" d="M-259 27c-19 0-36-12-44-27h88c-8 15-25 27-44 27z"/></g><path id="XMLID_197_" class="st2" d="M-179 158c0 44-36 79-80 79-43 0-79-34-80-76v-24c0-3 2-6 5-6h30c2 0 5 3 5 6v22c0 21 18 39 40 39s40-18 40-39v-22c0-3 2-6 5-6h30c2 0 5 3 5 6v21z"/></g><g id="XMLID_13_"><path id="XMLID_192_" class="st0" d="M37-180l-4-24c-2-12-10-18-21-18-9 0-17 6-14 18l4 24h6l-4-24c-1-8 2-12 9-12 6 0 12 4 13 12l4 24h7zm-26 8c0-2 2-3 3-3 2 0 5 1 5 4 0 2-2 3-3 3-2 0-5-2-5-4zm14 0c0-3 2-3 4-3 1 0 4 1 4 4 0 2-2 3-3 3-2 0-5-2-5-4z"/><path id="XMLID_189_" class="st0" d="M53-180l-3-17c2 4 7 6 11 6 7 0 12-5 12-13 0-11-7-18-17-18-4 0-8 1-10 5l-1-4h-5l7 41h6zm-5-28c0-5 3-8 8-8s11 4 11 11c0 5-3 8-7 8-6 0-11-5-12-11z"/><path id="XMLID_186_" class="st0" d="M85-209c0-4 3-7 9-7 3 0 7 1 9 3l3-4c-4-3-9-5-13-5-9 0-14 5-14 13 0 10 8 18 19 18 9 0 14-6 11-18H85zm19 5c1 5-2 7-7 7s-9-2-11-7h18z"/><path id="XMLID_184_" class="st0" d="M125-192v-4c3 4 6 5 9 5s6-1 7-3l-4-5-4 2c-5 0-9-3-10-8l-3-16h-6l6 29h5z"/><path id="XMLID_182_" class="st0" d="M171-192l3-23 11 23h6l-15-29h-7l-3 19-5-9-5-10h-7l-5 29h7l3-23 11 23h6z"/><path id="XMLID_179_" class="st0" d="M199-209c0-4 3-7 9-7l9 3 3-4c-4-3-9-5-14-5-8 0-13 5-13 13 0 10 8 18 18 18s15-6 12-18h-24zm19 5c0 5-3 7-7 7-5 0-9-2-11-7h18z"/><path id="XMLID_168_" class="st0" d="M240-192l-6-29h-6l6 29h6zm-6 8c0-2 2-3 3-3 3 0 5 1 5 4 0 2-2 3-3 3-2 0-5-1-5-4z"/><path id="XMLID_60_" class="st0" d="M267-199c-2 2-5 3-8 3-4 0-6-2-6-4 0-3 2-3 5-4 6 0 12-2 11-10-1-5-6-8-14-8-5 0-9 1-12 5l4 5c2-3 6-5 9-5s6 1 7 4c0 3-2 4-6 4-5 1-11 2-11 8 0 7 8 10 14 10 5 0 8-1 11-4l-4-4z"/><path id="XMLID_57_" class="st0" d="M286-192l-3-16c-1-5 1-8 6-8s9 4 10 9l3 15h6l-5-29h-6l1 4c-4-3-7-5-11-5-7 0-12 5-10 14l3 16h6z"/><path id="XMLID_55_" class="st0" d="M335-221l2 16c1 5 0 8-6 8-5 0-9-4-10-9l-2-15h-6l5 29h5v-4c3 3 7 5 10 5 8 0 12-5 11-14l-3-16h-6z"/><path id="XMLID_15_" class="st0" d="M355-225c0-4 3-6 8-6s9 3 11 9l1 5c-3-3-8-5-12-5-7 0-12 5-12 13 0 11 8 18 18 18 4 0 8-2 9-5l1 4h6l-5-30c-2-11-11-14-18-14-9 0-14 4-13 11h6zm2 17c0-5 3-8 8-8 12 0 16 19 3 19-6 0-11-4-11-11z"/></g></symbol><use xlink:href="#EPS-Logo" width="770" height="473" id="XMLID_202_" x="-385" y="-236" transform="matrix(.9728 0 0 -.9728 375 286)" overflow="visible"/></svg>
\ No newline at end of file
diff --git a/assets/images/giropay.svg b/assets/images/giropay.svg
new file mode 100644
index 0000000..371d0ea
--- /dev/null
+++ b/assets/images/giropay.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 740 318"><path data-name="92653320" d="M0 57A57 57 0 0157 0h626a57 57 0 0157 57v204a57 57 0 01-57 57H57a57 57 0 01-57-57z" fill="#000268"/><path data-name="92186184" d="M24 59v200a36 36 0 0035 36h328V23H59a36 36 0 00-35 36zm448 99c0 13-7 22-17 22-9 0-17-9-17-21s7-21 17-21c11 0 17 10 17 20zm-62 73h28v-43c6 9 16 13 26 13 23 0 36-20 36-43 0-20-12-41-34-41-13 0-24 5-30 16v-14h-26v112zm128-57c0-8 7-11 17-11h11c0 10-6 19-17 19-6 0-11-3-11-8zm56 25a96 96 0 01-2-19v-30c0-24-17-33-38-33-12 0-22 2-32 6l1 19c7-5 16-6 25-6 10 0 18 2 18 13a85 85 0 00-12-1c-15 0-42 3-42 28 0 17 14 25 30 25 12 0 19-5 26-15v13h26zm12 32a79 79 0 0017 2c26 0 32-19 39-40l30-74h-28l-16 52h-1l-17-52h-30l33 82c-2 7-7 11-14 11a35 35 0 01-11-2l-2 21z" fill="#fff"/><path data-name="47303032" d="M91 158c0-11 5-20 16-20 12 0 17 10 17 19 0 12-7 21-17 21-9 0-16-7-16-20zm60-39h-25v14c-6-9-16-16-27-16-25 0-36 18-36 42 0 23 13 40 35 40 11 0 20-4 27-14v5c0 15-8 23-24 23-12 0-19-3-27-7l-2 22a92 92 0 0031 5c32 0 48-11 48-43zm47-33h-28v20h28V86zm-28 113h28v-80h-28zm105-81a64 64 0 00-10-1c-12 0-19 7-23 17h-1v-15h-25v80h28v-34c0-15 7-25 20-25a32 32 0 019 1l2-23zm47 63c-12 0-18-10-18-22s6-23 18-23 18 11 18 23-5 22-18 22zm0 20c27 0 47-16 47-42 0-27-20-42-47-42s-46 15-46 42c0 26 20 42 46 42z" fill="#ff0007"/></svg>
\ No newline at end of file
diff --git a/assets/images/ideal.svg b/assets/images/ideal.svg
new file mode 100644
index 0000000..be0b6ac
--- /dev/null
+++ b/assets/images/ideal.svg
@@ -0,0 +1 @@
+<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 661"><path d="M0 0v661h385c255 0 365-142 365-331C750 142 640 0 385 0z" fill="#fff"/><path d="M42 42h344c233 0 322 127 322 288 0 193-125 289-322 289H42zm33 33v511h311c187 0 289-87 289-256 0-174-111-255-289-255H75z"/><path d="M117 368h99v176h-99z"/><circle cx="166" cy="278" r="62"/><path d="M425 307v29h-71V221h68v29h-40v13h38v29h-38v15zm12 29l35-115h40l35 115h-30l-6-22h-38l-6 22zm45-51h20l-9-32h-2l-9 32zm79-64h29v86h42c-11-156-134-190-246-190H266v104h18c32 0 52 22 52 57 0 36-20 58-52 58h-18v209h120c182 0 245-85 247-209h-72V221zm-295 29v57h18c12 0 23-3 23-29 0-25-12-28-23-28z" fill="#d50072"/></svg>
\ No newline at end of file
diff --git a/assets/images/index.html b/assets/images/index.html
new file mode 100644
index 0000000..34cf545
--- /dev/null
+++ b/assets/images/index.html
@@ -0,0 +1,29 @@
+<html><head><title> - Revision 2844313: /woocommerce-gateway-stripe/trunk/assets/images</title></head>
+<body>
+ <h2> - Revision 2844313: /woocommerce-gateway-stripe/trunk/assets/images</h2>
+ <ul>
+ <li><a href="../">..</a></li>
+ <li><a href="alipay.svg">alipay.svg</a></li>
+ <li><a href="amex.svg">amex.svg</a></li>
+ <li><a href="bancontact.svg">bancontact.svg</a></li>
+ <li><a href="boleto.svg">boleto.svg</a></li>
+ <li><a href="credit-card.svg">credit-card.svg</a></li>
+ <li><a href="diners.svg">diners.svg</a></li>
+ <li><a href="discover.svg">discover.svg</a></li>
+ <li><a href="eps.svg">eps.svg</a></li>
+ <li><a href="giropay.svg">giropay.svg</a></li>
+ <li><a href="ideal.svg">ideal.svg</a></li>
+ <li><a href="jcb.svg">jcb.svg</a></li>
+ <li><a href="link.svg">link.svg</a></li>
+ <li><a href="maestro.svg">maestro.svg</a></li>
+ <li><a href="mastercard.svg">mastercard.svg</a></li>
+ <li><a href="multibanco.svg">multibanco.svg</a></li>
+ <li><a href="oxxo.svg">oxxo.svg</a></li>
+ <li><a href="p24.svg">p24.svg</a></li>
+ <li><a href="sepa.svg">sepa.svg</a></li>
+ <li><a href="sofort.svg">sofort.svg</a></li>
+ <li><a href="visa.svg">visa.svg</a></li>
+ <li><a href="wechat.svg">wechat.svg</a></li>
+ </ul>
+ <hr noshade><em>Powered by <a href="http://subversion.apache.org/">Apache Subversion</a> version 1.9.5 (r1770682).</em>
+</body></html>
\ No newline at end of file
diff --git a/assets/images/jcb.svg b/assets/images/jcb.svg
new file mode 100644
index 0000000..9c51507
--- /dev/null
+++ b/assets/images/jcb.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 750 471" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="0%" y1="50%" x2="100%" y2="50%" id="a"><stop stop-color="#007B40" offset="0%"/><stop stop-color="#55B330" offset="100%"/></linearGradient><linearGradient x1="0%" y1="50%" x2="100%" y2="50%" id="b"><stop stop-color="#1D2970" offset="0%"/><stop stop-color="#006DBA" offset="100%"/></linearGradient><linearGradient x1="0%" y1="50%" x2="100%" y2="50%" id="c"><stop stop-color="#6E2B2F" offset="0%"/><stop stop-color="#E30138" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><rect fill="#0E4C96" width="750" height="471" rx="40"/><path d="M617 347c0 41-33 75-75 75H133V124c0-41 33-75 75-75h409v298z" fill="#FFF"/><path d="M484 242h35c12 3 15 20 4 26-7 4-16 2-23 2h-16v-28zm42-32c2 9-7 17-15 16h-27v-26h32c5 1 9 5 10 10zm64-136v272c0 27-24 50-51 51h-81V287h88c14-1 29-10 29-25 2-15-12-25-26-27-5 0-5-2 0-2 13-3 23-16 19-30-3-14-18-19-31-19h-79v-62c2-26 27-48 53-48h79z" fill="url(#a)"/><path d="M160 125c0-27 25-51 52-51h80v273c-1 26-25 49-51 50h-81V284c26 6 53 8 80 4 16-2 34-10 39-27 4-14 2-29 2-43v-34h-46v67c-2 14-15 22-28 22-16 0-48-12-48-12l1-136z" fill="url(#b)"/><path d="M310 197c-3 1-1-8-1-11v-64c2-27 27-49 54-48h78v273c-1 26-25 49-51 50h-81V273c18 15 43 17 66 17 17 0 35-2 51-6v-23c-19 9-41 15-62 10-14-4-25-18-25-33-2-16 8-32 23-37 19-6 40-2 58 6 4 2 8 5 6-2v-18c-30-7-62-9-92-2-9 3-17 7-24 12z" fill="url(#c)"/></g></svg>
\ No newline at end of file
diff --git a/assets/images/link.svg b/assets/images/link.svg
new file mode 100644
index 0000000..310ca59
--- /dev/null
+++ b/assets/images/link.svg
@@ -0,0 +1 @@
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="64" height="40" viewBox="0 0 600 227"><path d="M167.76 39.2c-10.88 3.44-14.8 17.52-7.28 26.24 7.36 8.64 21.04 7.12 26.64-2.96 5.6-10.08-1.52-23.12-12.88-23.76-2.32-.16-5.28.08-6.48.48zM100 128.8v88.8l14.64-.16 14.56-.24.24-88.64.16-88.56H100v88.8zM381.6 114v74.08l-2.96 1.36c-1.84.8-5.28 1.28-8.64 1.36-4.56 0-6.08-.32-8.16-1.84-4.56-3.2-4.88-5.68-5.36-34.96-.4-28.8-1.36-36.32-5.6-45.6-6.4-14-22.96-21.92-39.44-18.64-22.08 4.32-37.6 17.92-59.04 51.92l-7.2 11.36-.24-30.88-.16-30.96H216v126.4h27.04l2.96-6.96c8.88-20.64 23.76-47.12 35.04-62.24 18.88-25.36 36.32-34.56 42.4-22.4 2.48 5.04 3.12 11.6 3.76 36.4.48 20.4.88 26 2 29.6 6.32 20.24 23.36 30.32 46 27.36 19.12-2.56 35.04-11.52 55.04-30.96 6.16-6 10.88-10 11.2-9.52.32.48 5.92 9.36 12.4 19.76l11.84 18.96H482c10.08 0 16.48-.32 16.8-.8.24-.48-8.32-14.96-19.12-32.24L460 153.12l6.4-9.68c7.92-12.16 16.96-27.76 23.6-41.12 2.88-5.68 5.2-10.48 5.2-10.72 0-.24-7.28-.4-16.16-.4l-16.24.08-5.92 10.96c-11.12 20.72-25.04 41.12-38.88 57.04l-6.4 7.28-.4-63.04-.4-63.12-14.56-.24L381.6 40v74zM158.4 154.4v63.2h28.8V91.2h-28.8v63.2z"/></svg>
\ No newline at end of file
diff --git a/assets/images/maestro.svg b/assets/images/maestro.svg
new file mode 100644
index 0000000..5cc879e
--- /dev/null
+++ b/assets/images/maestro.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 750 471" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="#000" width="750" height="471" rx="40"/><path d="M675 236a179 179 0 11-359 0 179 179 0 01359 0" fill="#D9222A"/><path d="M357 349l-14-19h64l10-19h-84l-8-19h100a179 179 0 005-95H320l5-19h100l-8-19h-84l10-19h64l-14-19h-36l18-19a179 179 0 1018 247h-36" fill="#0097D0"/><path d="M651 336a6 6 0 1112 0 6 6 0 01-12 0zm6 4a4 4 0 100-9 4 4 0 000 9zm-1-2h-1v-5h3l1 2-1 1 1 2h-1l-1-2h-1v2zm0-3h2l-1-1h-1v1zm-284-51c-7 2-15 3-22 3-25 0-39-11-39-33 0-26 17-44 40-44 18 0 30 10 30 27l-3 18h-44c-2 11 6 15 19 15 8 0 15-1 23-4l-4 18zm-12-44c0-2 3-13-10-13-7 0-12 4-14 13h24zm28-5c0 9 5 16 17 21 9 3 10 4 10 8s-4 7-13 7l-20-3-3 17 24 2c24 0 35-8 35-25 0-10-5-16-16-21-10-3-11-4-11-8s4-6 11-6l17 1 3-17-20-1c-26 0-35 11-34 25m-89 51h-18v-8c-6 6-13 9-24 9-12 0-20-8-20-20 0-18 14-29 39-29l10 1v-5c0-5-3-7-14-7-10 0-17 2-24 3l3-16c12-3 19-4 27-4 20 0 30 7 30 21l-2 15-7 40zm-16-33l-5-1c-13 0-19 4-19 12 0 4 3 7 8 7 9 0 16-7 16-18zm194 32l-16 2c-11 0-18-6-18-16l3-20 11-57h22l-3 17h11l-3 19h-11l-7 33c0 4 3 6 8 6l6-1-3 17m99-75c-16 0-29 6-36 18l6-17c-12-4-19 2-26 11l-2 2v-13h-21l-12 70-1 5h23l5-29c5-21 13-27 25-24-3 6-4 13-4 20 0 19 10 34 35 34s43-13 43-44c0-19-12-33-35-33zm-6 59c-8 0-13-7-13-17 0-11 7-25 18-25 9 0 12 8 12 15 0 17-6 27-17 27zm-343 17h-23l13-70-30 70h-20l-4-70-14 70h-20l17-91h35l3 51 22-51h38l-17 91" fill="#000"/><path d="M613 274a6 6 0 1112 0 6 6 0 01-12 0zm6 5a4 4 0 100-9 4 4 0 000 9zm-1-2h-1v-5h3l1 1-1 2 1 2h-1l-1-2h-1v2zm0-3h2v-1h-2v1zm-240 4c-8 2-15 3-23 3-25 0-38-11-38-33 0-25 17-44 39-44 19 0 30 11 30 27 0 5 0 11-2 18h-45c-1 11 6 16 20 16 7 0 15-2 23-5l-4 18zm-12-44c0-1 3-13-10-13-7 0-13 5-15 13h25zm27-5c0 10 5 16 17 21 10 4 11 5 11 8 0 5-4 7-13 7-7 0-13-1-20-3l-3 17c6 2 15 2 23 2 24 0 35-7 35-24 0-11-4-17-16-21-9-4-10-5-10-8 0-4 3-6 11-6l16 1 3-17-20-2c-25 0-34 11-34 25m-88 51h-19l1-8c-6 7-14 9-24 9-12 0-20-8-20-20 0-18 14-29 39-29l9 1 1-5c0-5-4-7-14-7-11 0-18 2-24 4l3-17c11-3 19-4 27-4 19 0 29 8 29 22 1 4-1 11-1 15-1 4-7 33-7 39zm-16-33h-6c-12 0-19 3-19 11 0 5 3 8 8 8 10 0 16-8 17-19zm194 32c-7 2-11 2-16 2-12 0-18-5-18-16l3-20 10-57h23l-4 18h12l-3 18h-12l-6 34c0 4 2 5 8 5h6l-3 16m110-42c0 16-7 26-18 26-8 0-12-6-12-16 0-12 7-25 18-25 9 0 12 7 12 15zm24 0c0-18-12-33-35-33-27 0-44 18-44 44 0 18 10 33 35 33 26 0 44-13 44-44zm-115-31c-2 23-7 46-11 69l-1 5h22c8-44 11-57 28-53l8-21c-12-4-19 2-26 11 0-4 2-8 1-11h-21m-270 74h-22l13-70-31 70h-20l-4-69-13 69h-20l17-91h35l2 57 24-57h37l-18 91" fill="#FFF"/></g></svg>
\ No newline at end of file
diff --git a/assets/images/mastercard.svg b/assets/images/mastercard.svg
new file mode 100644
index 0000000..df9bdde
--- /dev/null
+++ b/assets/images/mastercard.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 750 471" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="#F4F4F4" width="750" height="471" rx="40"/><path d="M619 422l-3 1a4 4 0 000 6 4 4 0 006 0 4 4 0 000-6l-3-1zm0 7a3 3 0 110-6 3 3 0 010 6zm0-5h-2v4h1v-1l1 1h1l-1-1 1-1v-1l-1-1zm0 1l1 1h-2v-1h1zm-459 3h-9v-41h9v5s8-6 12-6c9 0 14 7 14 7s4-7 14-7c14 0 16 13 16 13v29h-9v-26s0-8-9-8-10 8-10 8v26h-9v-26s-1-8-8-8c-11 0-11 8-11 8v26zm266-42c-4 0-12 6-12 6v-5h-8v41h9l-1-26s1-8 11-8l4 1 3-8-6-1zm124 0c-5 0-12 6-12 6v-5h-9v41h9v-26s0-8 10-8l5 1 3-8-6-1zm-306 0c-13 0-20 11-20 21s8 22 21 22c7 0 13-5 13-5v4h8v-41h-8v5s-6-6-14-6zm2 8c7 0 13 6 13 14 0 7-6 13-13 13s-13-6-13-13c0-8 6-14 13-14zm249-8c-13 0-20 11-20 21s8 22 21 22c7 0 13-5 13-5v4h9v-41h-9v5s-6-6-14-6zm2 8c7 0 13 6 13 14 0 7-6 13-13 13s-13-6-13-13c0-8 6-14 13-14zm81-8c-13 0-20 11-20 21s8 22 21 22c7 0 13-5 13-5v4h9v-57h-9v21s-6-6-14-6zm2 8c7 0 13 6 13 14 0 7-6 13-13 13s-13-6-13-13c0-8 6-14 13-14zm-287 35c-9 0-17-5-17-5l3-6s8 3 14 3c3 0 9-1 10-4 0-4-11-5-11-5s-15-1-15-13c0-8 8-13 17-13 6 0 17 5 17 5l-5 6-12-3c-4 0-8 2-8 5 0 8 25-1 25 17 0 11-10 13-18 13zm33-54v12h-8v9h8v20s-1 14 14 14l12-3-3-9s-4 3-7 3c-7-1-7-5-7-5v-20h14v-9h-14v-12h-9zm52 11c-15 0-22 12-21 22 0 10 6 22 21 22 7 0 16-6 16-6l-4-7s-6 5-12 5c-11 0-12-11-12-11h30s3-25-18-25zm-2 8h1c11 0 11 10 11 10h-22s0-9 10-10zm90 23l4 8s-6 4-13 4c-15 0-23-11-23-22 0-16 13-21 22-21 8 0 15 5 15 5l-5 8s-2-5-10-5-13 7-13 14 5 13 13 13c5 0 10-4 10-4z" fill="#000"/><path d="M625 279v-6h-2l-2 4-1-4h-2v6h1v-5l2 4h1l1-4v5h2zm-10 0v-5h2v-1h-4v1h1v5h1z" fill="#F79F1A"/><path d="M625 197a154 154 0 11-309 0 154 154 0 01309 0z" fill="#F79F1A"/><path d="M434 197a154 154 0 11-309 0 154 154 0 01309 0z" fill="#EA001B"/><path d="M375 75a155 155 0 000 243 155 155 0 000-243z" fill="#FF5F01"/></g></svg>
\ No newline at end of file
diff --git a/assets/images/multibanco.svg b/assets/images/multibanco.svg
new file mode 100644
index 0000000..08fc45a
--- /dev/null
+++ b/assets/images/multibanco.svg
@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 886" preserveAspectRatio="xMidYMid meet"><defs><style>.cls-2{fill:#434142}</style></defs><g id="g14"><g id="g20"><path id="path22" d="M371 714h307c70 0 71-75 64-111-4-25-46-25-51 0v28a24 24 0 01-23 24H79a24 24 0 01-24-24v-28c-5-25-47-25-51 0-7 36-6 111 64 111h303zM154 0h474c33 0 60 29 60 64v31c0 43-59 43-59 0V78a19 19 0 00-19-19H136a19 19 0 00-20 19v17c0 43-56 42-56 0V64c0-35 28-64 61-64z" fill="#2c6cae"/></g><g id="g24"><path id="path26" class="cls-2" d="M676 352c33 15 56 47 56 84 0 51-45 93-100 93H477c-14 0-26-11-26-24V211a26 26 0 0126-25h128c54 0 99 44 99 98a98 98 0 01-28 68m-115-24h49v-1a47 47 0 0040-46 47 47 0 00-47-46h-99v243h125a48 48 0 100-96h-68a27 27 0 110-54"/></g><g id="g28"><path id="path30" class="cls-2" d="M174 804a8 8 0 0116 0v45a37 37 0 01-37 37 37 37 0 01-37-37v-45a8 8 0 0116 0v45a21 21 0 0021 20 21 21 0 0021-20z"/></g><g id="g32"><path id="path34" class="cls-2" d="M252 869a8 8 0 110 17h-23a31 31 0 01-31-31v-51a8 8 0 1116 0v51a15 15 0 0015 14h23z"/></g><g id="g36"><path id="path38" class="cls-2" d="M427 500a31 31 0 11-62 6l-25-233-90 228v1l-1 1v1l-1 1a31 31 0 01-6 8l-1 1a31 31 0 01-5 3l-1 1h-1v1h-3v1a31 31 0 01-9 1h-2a31 31 0 01-10-2h-2v-1h-2v-1a31 31 0 01-5-3l-1-1-1-1h-1l-1-1v-1a31 31 0 01-3-4v-1l-1-1v-1l-1-1-90-229-25 233a31 31 0 11-62-6l30-275a52 52 0 0144-46h2a53 53 0 018 0 53 53 0 019 1 51 51 0 0136 31l77 195 77-195a51 51 0 0136-31 52 52 0 019-1 53 53 0 018 0h2a51 51 0 0138 27 52 52 0 014 9 51 51 0 012 10z"/></g><g id="g40"><path id="path42" class="cls-2" d="M113 877a8 8 0 11-17 2l-7-60-25 59a8 8 0 01-15 0l-25-59-8 60a8 8 0 11-16-2l8-70a13 13 0 018-10 15 15 0 011-1h1a15 15 0 012 0 14 14 0 0112 3 14 14 0 013 4 7 7 0 010 1l21 49 22-49a14 14 0 0110-8 15 15 0 012 0 16 16 0 012 0 14 14 0 0111 6 13 13 0 011 3 12 12 0 010 1 8 8 0 010 1z"/></g><g id="g44"><path id="path46" class="cls-2" d="M288 878a8 8 0 01-17 0v-66h-23a8 8 0 010-16h63a8 8 0 010 16h-23z"/></g><g id="g48"><path id="path50" class="cls-2" d="M339 878a8 8 0 01-16 0v-74a8 8 0 1116 0z"/></g><g id="g52"><path id="path54" class="cls-2" d="M509 877a8 8 0 11-16 2l-3-24h-29a8 8 0 110-16h27l-1-6v-1a32 32 0 00-1-4 28 28 0 00-2-5c-3-6-9-11-16-11h-1a18 18 0 00-4 1 17 17 0 00-3 1c-7 3-11 10-12 19l-5 46a8 8 0 11-16-2l5-46c1-14 9-26 20-32a33 33 0 017-2 34 34 0 018-1h1c14 0 25 8 31 20a44 44 0 013 7 47 47 0 011 7 7 7 0 010 1z"/></g><g id="g56"><path id="path58" class="cls-2" d="M534 878a8 8 0 01-16 0v-69a8 8 0 010-1 11 11 0 011-3 14 14 0 010-1 12 12 0 017-6 10 10 0 011 0h1a13 13 0 012 0 12 12 0 019 4l44 56v-54a8 8 0 1116 0v68a12 12 0 01-4 9 12 12 0 01-2 1l-1 1a12 12 0 01-9 0 7 7 0 01-1-1 12 12 0 01-2-1 10 10 0 01-1-1v-1l-44-56z"/></g><g id="g60"><path id="path62" class="cls-2" d="M664 869a8 8 0 110 17h-25a33 33 0 01-32-33v-25a33 33 0 0132-32h25a8 8 0 110 16h-25a16 16 0 00-16 16v25a16 16 0 0016 16h25z"/></g><g id="g64"><path id="path66" class="cls-2" d="M711 812a23 23 0 00-15 6 20 20 0 00-7 15v16a20 20 0 007 14 23 23 0 0015 6 23 23 0 0016-6 20 20 0 006-15v-15a20 20 0 00-6-15 23 23 0 00-16-6m0-16a39 39 0 0128 11 37 37 0 0111 26v15a37 37 0 01-11 27 39 39 0 01-28 11 39 39 0 01-27-11 37 37 0 01-11-26v-16a37 37 0 0111-26 39 39 0 0127-11z"/></g><g id="g68"><path id="path70" class="cls-2" d="M363 812v57h32a10 10 0 0010-10 10 10 0 00-2-7h-1a10 10 0 00-7-3h-11a8 8 0 110-17h4a10 10 0 006-3 10 10 0 003-7 10 10 0 00-10-10h-24zm-17 28v-36a8 8 0 011-3 8 8 0 012-3 8 8 0 016-2h32a26 26 0 0126 26 26 26 0 01-4 14 27 27 0 015 4 27 27 0 018 19 27 27 0 01-27 27h-40a8 8 0 01-9-9z"/></g></g></svg>
\ No newline at end of file
diff --git a/assets/images/oxxo.svg b/assets/images/oxxo.svg
new file mode 100644
index 0000000..521218d
--- /dev/null
+++ b/assets/images/oxxo.svg
@@ -0,0 +1 @@
+<svg width="48" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 2.926C0 1.343 1.271.059 2.84.059h41.673c1.568 0 2.84 1.284 2.84 2.867v18.133c0 1.582-1.272 2.865-2.84 2.865H2.84C1.271 23.924 0 22.641 0 21.06V2.926Z" fill="#fff"/><path d="M.033 2.636C.033 1.181 1.203 0 2.645 0H44.75c1.442 0 2.611 1.18 2.611 2.636v.084H.033v-.084ZM47.36 21.298v.066c0 1.455-1.169 2.636-2.611 2.636H2.645C1.203 24 .033 22.82.033 21.364v-.066H47.36Z" fill="#FBB110"/><path d="M32.787 11.972c0 3.685 2.96 6.672 6.612 6.672 3.65 0 6.612-2.987 6.612-6.672 0-3.686-2.961-6.673-6.612-6.673-3.652 0-6.612 2.987-6.612 6.673Zm-31.523 0c0 3.685 2.961 6.672 6.613 6.672 3.651 0 6.612-2.987 6.612-6.672 0-3.686-2.96-6.673-6.612-6.673s-6.613 2.987-6.613 6.673Zm46.096 8.063h-32.6c.588-.416 1.135-.986 1.732-1.754l3.32-4.276 1.451 1.85 1.614-2.167-1.411-1.813 3.38-4.354c1.073-1.38-.98-3.004-2.053-1.623l-2.987 3.849-3.037-3.9c-1.074-1.377-3.123.25-2.048 1.629l3.432 4.4-3.714 4.782c-1.32 1.7-2.636 3.257-5.25 3.377H.033V3.983H32.46c-.557.411-1.083.962-1.654 1.698l-3.32 4.275-1.451-1.848-1.613 2.166 1.411 1.812-3.381 4.353c-1.072 1.381.98 3.005 2.052 1.623l2.989-3.847 3.037 3.899c1.074 1.378 3.123-.25 2.048-1.628l-3.432-4.402 3.714-4.78c1.212-1.563 2.422-3.005 4.64-3.32h9.86v16.051Zm-11.92-8.063c0-2.207 1.773-3.995 3.959-3.995s3.957 1.788 3.957 3.995c0 2.206-1.771 3.994-3.957 3.994s-3.958-1.788-3.958-3.994Zm-31.52 0c0-2.207 1.771-3.995 3.957-3.995 2.185 0 3.958 1.788 3.958 3.995 0 2.206-1.773 3.994-3.958 3.994-2.186 0-3.958-1.788-3.958-3.994Z" fill="#E70020"/></svg>
\ No newline at end of file
diff --git a/assets/images/p24.svg b/assets/images/p24.svg
new file mode 100644
index 0000000..6a4f334
--- /dev/null
+++ b/assets/images/p24.svg
@@ -0,0 +1 @@
+<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 257"><path d="M0 223l19-107h49c12 0 20 3 23 7s4 14 2 27c-2 12-6 20-11 25s-14 6-27 6H19l-7 42zm21-52h29c12 0 20-1 23-4s7-8 8-17c2-10 2-16 1-19s-7-4-16-4H29zm83-23h11l-3 9h1c5-7 13-10 23-10q21 0 17 21l-1 5h-11l1-2v-4c2-7-2-11-10-11-12 0-20 7-22 23l-8 44H91zm58 0h54l-2 11-54 55h45l-2 9h-58l2-10 55-55h-41zm108 53h11v2c-1 8-5 14-10 17s-14 4-26 4c-13 0-22-2-25-7s-4-16-1-32c2-15 6-25 12-30s14-8 26-8c14 0 23 3 26 7s4 14 2 28l-1 6h-54c-2 12-2 19 0 22s7 5 16 5q14 0 18-2t6-10zm4-22v-3c2-8 1-13-1-16s-8-3-16-3-15 1-18 4-6 9-8 18h43zm46-63l-19 107h-11l19-107zm52 85h11v2c-1 8-5 14-10 17s-14 4-26 4c-14 0-22-2-25-7s-4-16-1-32c2-15 6-25 12-30s14-8 26-8c14 0 23 3 26 7s4 14 2 28l-1 6h-54c-2 12-2 19 0 22s7 5 16 5q14 0 18-2t6-10zm4-22v-3c2-8 1-13-1-16s-8-3-16-3-15 1-18 4-6 9-8 18h43zm125-31l-34 75h-16l-3-41-1-13v-13h-1l-2 7-3 6-5 13-17 41h-17l-7-75h11l4 42 1 13v13h1l2-7 3-6 5-13 18-42h16l3 42 1 13v13h1l2-7 3-6 6-13 18-42h11zm56 0l-15 34-7 16-3 9-4 8-2-8-1-9-3-16-5-34h-12l15 82-2 3c-4 10-10 15-16 15a25 25 0 01-3-1l-2 9a29 29 0 005 1c7 0 13-2 17-6s9-12 14-23l35-80z" fill="#ce4749"/><path d="M638 214l-1 10h-76l4-20q3-17 10-22c5-4 16-6 32-8q20-2 24-6c3-3 6-9 8-19 1-9 1-15-2-18s-8-4-18-4c-13 0-21 1-25 3s-6 8-7 16l-2 8h-11l1-5c2-13 6-22 12-26s17-6 33-6c14 0 23 2 27 7s5 13 3 26q-4 19-12 26t-30 8c-14 2-22 4-25 6s-6 9-8 20v4h63zm99-96l-12 71h15l-2 10h-15l-4 25h-12l4-25h-58l2-14 64-67zm-24 71l11-63-60 63zM248 84a386 386 0 0173-33l-5-26a516 516 0 00-94 40zm290-14l90-50C591 9 543 0 484 0h-1l-21 41a254 254 0 0176 29zm-339 8c-39 25-60 46-60 46h50l36-26zM454 1a547 547 0 00-118 18l4 27c38-10 72-12 102-8zm222 39L559 83a149 149 0 0117 14h174s-20-31-74-57z" fill="#afb2ba"/></svg>
\ No newline at end of file
diff --git a/assets/images/sepa.svg b/assets/images/sepa.svg
new file mode 100644
index 0000000..4170e5c
--- /dev/null
+++ b/assets/images/sepa.svg
@@ -0,0 +1 @@
+<svg version="1.1" id="svg10908" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 750 205" xml:space="preserve"><style>.st0{fill:#10298e}</style><path id="path5689" class="st0" d="M167 65h-52c0-8-1-14-3-17-3-4-11-6-25-6-13 0-22 1-27 4s-6 8-6 16c0 7 2 12 6 14 3 2 7 3 11 3l10 1 42 3c17 2 30 7 38 14 6 6 10 14 11 23a156 156 0 01-4 56c-6 14-18 23-38 27l-39 2c-28 0-48-2-60-5-14-4-23-13-27-26-3-7-4-19-4-35h51v4c0 9 3 14 8 17 4 2 8 3 13 3h19l18-2c5-2 8-5 9-9l2-10c0-9-4-14-10-16l-35-3-34-4c-17-3-28-9-33-19-5-8-8-21-8-38 0-13 2-23 4-31s7-13 13-17C26 7 37 4 50 3a423 423 0 0184 2c22 6 33 23 33 50v10"/><path id="path5693" class="st0" d="M392 205V0h103c14 0 25 1 32 4 17 5 29 16 34 32 3 9 5 22 5 39 0 21-2 36-5 45-7 18-20 28-41 31l-31 1h-42v53h-55zm56-100h34l20-3c3-2 5-5 6-11l1-16c0-8 0-15-2-19-2-6-7-10-14-11h-46v60z"/><path id="path5697" class="st0" d="M684 170h-74l-10 35h-57L605 0h83l62 205h-56l-10-35zm-11-40l-26-89-25 89h51z"/><path id="path5701" d="M316 29c22 0 43 10 57 27l11-26a105 105 0 00-167 35h-23l-14 30h30l-1 8 1 10h-15l-14 29h36a105 105 0 00154 44v-36a73 73 0 01-116-8h76l14-29H244a78 78 0 010-18h110l13-30H253c13-22 37-36 63-36" fill="#ffbe00"/><path id="path5705" class="st0" d="M316 30c22 0 42 10 56 26l1 1v-1l12-25 1-1h-1a104 104 0 00-169 35l1-1h-24v1l-14 29v2h31l-1-1-1 8 1 10 1-1h-16l-14 30v1h38-1a105 105 0 00154 44h1v-39l-2 2a72 72 0 01-114-8v1h76l14-30 1-1H244l1 1a76 76 0 010-18l-1 1h110v-1l14-29 1-2H253l1 2c13-22 37-36 62-36m-63 36h114l-1-1-13 29H244v1l-1 7 1 11v1h102l-1-1-14 29 1-1h-77l1 2a73 73 0 00116 8l-1-1v37-1c-17 11-37 17-57 17-42 0-79-24-95-61v-1h-37l1 2 14-30-1 1h16v-1a111 111 0 010-18v-1h-31l1 1 13-29h24c7-19 20-34 37-46 40-27 94-22 129 11v-1l-12 25h1a74 74 0 00-121 10v1h1z"/></svg>
\ No newline at end of file
diff --git a/assets/images/sofort.svg b/assets/images/sofort.svg
new file mode 100644
index 0000000..c0a2734
--- /dev/null
+++ b/assets/images/sofort.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 233"><path d="M248 0a69 69 0 00-30 7c-13 6-25 17-35 31a134 134 0 00-16 31c-8 22-8 40 0 52 5 7 15 15 35 15 36 0 63-24 80-71 5-12 11-35 0-51-7-9-18-14-34-14zm218 0a69 69 0 00-29 7c-13 6-26 17-35 31a133 133 0 00-17 31c-8 22-8 40 1 52 4 7 14 15 34 15 36 0 63-24 80-71 5-12 11-35 0-51-7-9-18-14-34-14zM132 2c-12 0-24 0-34 5S78 23 71 44a42 42 0 00-2 12 18 18 0 002 9 26 26 0 007 8 36 36 0 0011 6l5 1 8 2a16 16 0 013 2 7 7 0 013 3 6 6 0 011 2 9 9 0 01-1 4 9 9 0 01-5 5c-3 2-7 2-13 2H12L0 134h83c8 0 22 0 36-6s27-18 33-41c2-9 1-16-2-22s-10-9-19-12l-5-1-6-2a9 9 0 01-5-4 7 7 0 01-1-6 9 9 0 014-5 17 17 0 019-2h48l1-1a107 107 0 0131-30zm217 0c-21 0-37 11-45 31l-36 101h40l18-52h36l10-28h-35l5-16a8 8 0 018-5h42l1-1c9-13 22-23 33-30zm186 0l-48 132h41l17-47 11 47h43s-7-33-13-46a73 73 0 00-5-10c12-5 29-15 37-34 4-12 4-22-1-29-6-9-18-13-38-13zm84 0a33 33 0 016 7c5 7 7 15 6 24h24l-36 101h36l37-101h47l11-31zm-57 27h7c12 0 17 4 12 15-3 11-10 17-24 17h-7l12-32zm-324 1c13 0 16 7 5 37-11 31-20 39-32 39s-16-8-5-39c8-23 19-37 32-37zm219 0c12 0 15 7 4 37-11 31-19 39-32 39-12 0-16-8-5-39 9-23 20-37 33-37z" fill="#ee7f00"/><path d="M40 148a10 10 0 00-6 1 10 10 0 00-3 5l-1 5 5 1 6-1a10 10 0 003-5v-5l-4-1zm22 0l-6 1a10 10 0 00-3 5l-1 5 5 1 6-1a10 10 0 003-5v-5l-4-1zm412 17a35 35 0 00-9 1 30 30 0 00-8 3 29 29 0 00-7 6 27 27 0 00-5 9 18 18 0 00-1 7 12 12 0 001 5 12 12 0 003 3 28 28 0 005 3l4 2a19 19 0 013 3 7 7 0 013 3 5 5 0 01-1 3 12 12 0 01-2 4 12 12 0 01-3 3 15 15 0 01-4 1 17 17 0 01-4 1 20 20 0 01-6-1 20 20 0 01-7-4 3 3 0 00-2-1 2 2 0 00-1 1 3 3 0 00-1 1 10 10 0 00-1 1l-1 3a19 19 0 00-1 4 3 3 0 001 1 6 6 0 001 2 15 15 0 003 2 27 27 0 005 1 31 31 0 006 0 38 38 0 0010-1 34 34 0 009-4 32 32 0 008-6 29 29 0 005-9 18 18 0 001-7 12 12 0 00-1-5 12 12 0 00-3-4 32 32 0 00-5-3l-4-2a21 21 0 01-4-2 7 7 0 01-2-3 5 5 0 010-4 11 11 0 012-3 10 10 0 012-2 12 12 0 014-1 14 14 0 014-1 16 16 0 014 1 18 18 0 014 1 23 23 0 012 2 3 3 0 002 1 2 2 0 001-1 3 3 0 001-1 13 13 0 001-1l1-3v-2a10 10 0 001-2 4 4 0 000-1 2 2 0 00-1 0 5 5 0 00-1-2 17 17 0 00-3-1 26 26 0 00-4-1 28 28 0 00-5 0zm210 0a47 47 0 00-15 2 47 47 0 00-13 7 52 52 0 00-11 11 57 57 0 00-8 14 40 40 0 00-2 14 19 19 0 002 11 17 17 0 009 6 34 34 0 0013 2 58 58 0 0016-2l5-1a6 6 0 003-2 9 9 0 001-3l10-26a6 6 0 000-1 3 3 0 000-2 2 2 0 00-1-1 3 3 0 00-1 0h-22a2 2 0 00-1 0 4 4 0 00-1 1 9 9 0 00-1 2 22 22 0 00-1 2 11 11 0 00-1 4l1 1h12l-5 15a23 23 0 01-5 2 22 22 0 01-4 0 19 19 0 01-8-1 10 10 0 01-5-4 14 14 0 01-2-8 31 31 0 012-9 39 39 0 015-10 35 35 0 017-7 30 30 0 018-5 28 28 0 0117 0 29 29 0 015 2 21 21 0 013 2 3 3 0 002 0 2 2 0 001 0 4 4 0 001-1 12 12 0 001-1 23 23 0 001-3 19 19 0 001-4 3 3 0 000-2 6 6 0 00-2-1 16 16 0 00-4-2 34 34 0 00-5-2 43 43 0 00-8 0zm-413 1h-4a5 5 0 00-3 0 3 3 0 00-1 2 16 16 0 000 3l-6 57a6 6 0 000 2 2 2 0 001 1 9 9 0 003 1h9a11 11 0 003-1 5 5 0 001-1 9 9 0 002-2l25-42-5 42a5 5 0 000 2 2 2 0 001 1 8 8 0 003 1h9a13 13 0 003-1 5 5 0 002-1 9 9 0 001-2l36-57a28 28 0 002-3 2 2 0 000-2 2 2 0 00-2 0 33 33 0 00-3 0h-4a8 8 0 00-2 0 3 3 0 00-1 1 12 12 0 00-1 1l-30 50 6-49a5 5 0 000-2 1 1 0 00-1-1 6 6 0 00-2 0h-8a9 9 0 00-2 0 4 4 0 00-2 1 9 9 0 00-1 2l-30 49 7-50a4 4 0 000-1 1 1 0 000-1 6 6 0 00-2 0h-4zm158 0a29 29 0 00-4 0 15 15 0 00-2 0 4 4 0 00-1 1 2 2 0 00-1 1l-22 61a1 1 0 000 1 1 1 0 001 1 8 8 0 001 0 27 27 0 004 1 30 30 0 003-1 11 11 0 002 0 3 3 0 001-1 2 2 0 001-1l23-61a1 1 0 000-1 1 1 0 00-1-1 9 9 0 00-2 0 27 27 0 00-3 0zm-405 0a30 30 0 00-3 0 15 15 0 00-2 0 3 3 0 00-2 1 2 2 0 000 1L2 208a31 31 0 00-2 10 14 14 0 002 8 13 13 0 007 5 31 31 0 0010 2 42 42 0 0013-2 35 35 0 0018-13 43 43 0 006-11l14-39a1 1 0 000-1 1 1 0 00-1-1 9 9 0 00-2 0 25 25 0 00-3 0 30 30 0 00-3 0 14 14 0 00-2 0 3 3 0 00-1 1 2 2 0 00-1 1l-14 39a26 26 0 01-4 6 21 21 0 01-4 5 18 18 0 01-5 3 18 18 0 01-6 1 13 13 0 01-5-1 7 7 0 01-4-3 9 9 0 01-1-5 22 22 0 012-7l14-38a1 1 0 000-1 1 1 0 00-1-1 9 9 0 00-2 0 26 26 0 00-3 0zm491 0a30 30 0 00-4 0 12 12 0 00-2 0 3 3 0 00-1 1 2 2 0 00-1 1l-14 39a31 31 0 00-2 11 13 13 0 002 8 13 13 0 007 5 31 31 0 0010 2 42 42 0 0012-2 35 35 0 0019-13 42 42 0 005-11l15-39a1 1 0 00-1-2 8 8 0 00-2 0 26 26 0 00-3 0 30 30 0 00-3 0 12 12 0 00-3 0 3 3 0 00-1 1 2 2 0 00-1 1l-14 39a27 27 0 01-3 6 21 21 0 01-4 5 18 18 0 01-6 3 18 18 0 01-6 1 13 13 0 01-5-1 7 7 0 01-3-3 8 8 0 01-1-5 22 22 0 011-7l14-38a1 1 0 000-1 1 1 0 000-1 8 8 0 00-2 0 26 26 0 00-3 0zm113 0h-3a8 8 0 00-2 0 4 4 0 00-1 1 2 2 0 00-1 1l-11 31-2 7-3 7v-4l-1-4v-4l-1-4-4-24a19 19 0 00-1-4 5 5 0 00-1-2 4 4 0 00-2-1 12 12 0 00-3 0h-7a7 7 0 00-4 1 7 7 0 00-3 4l-21 58a1 1 0 000 1 1 1 0 001 1 6 6 0 001 1 24 24 0 003 0 28 28 0 003 0 10 10 0 002-1 3 3 0 001-1 2 2 0 001-1l12-34 3-7 2-7 1 6 1 6 5 30a35 35 0 000 4 7 7 0 002 3 4 4 0 002 1 10 10 0 003 0h5a8 8 0 002 0 7 7 0 002-1 8 8 0 002-1 7 7 0 001-2l21-59a1 1 0 000-1 1 1 0 000-1 4 4 0 00-2 0 27 27 0 00-3 0zm-472 0a6 6 0 00-3 1 6 6 0 00-2 3l-21 57v3a3 3 0 003 1h32a2 2 0 001 0 3 3 0 001-1 9 9 0 001-1 24 24 0 001-3 23 23 0 001-2 6 6 0 000-2 1 1 0 000-1 1 1 0 00-1 0h-23l6-19h20a2 2 0 001 0 3 3 0 001-1 8 8 0 001-1 23 23 0 001-3 20 20 0 001-2 5 5 0 000-2 1 1 0 00-1 0 1 1 0 000-1h-20l6-16h23a2 2 0 001 0 4 4 0 001-1 10 10 0 001-1 23 23 0 001-3 22 22 0 001-2 6 6 0 000-2 1 1 0 000-1 1 1 0 00-1 0zm55 0a6 6 0 00-3 1 6 6 0 00-2 3l-22 60a1 1 0 001 1 8 8 0 002 0 26 26 0 003 1 30 30 0 003-1 13 13 0 002 0 4 4 0 002-1l10-25h4a8 8 0 013 0 5 5 0 012 2 9 9 0 011 3 43 43 0 011 5v14a3 3 0 001 1 1 1 0 000 1 6 6 0 002 0l4 1 4-1a11 11 0 002 0 3 3 0 001 0 3 3 0 001-1 6 6 0 000-2 28 28 0 000-3l-1-12a34 34 0 000-5 15 15 0 00-1-3 8 8 0 00-2-2 9 9 0 00-2-2 32 32 0 006-3 27 27 0 006-3 25 25 0 004-5 28 28 0 003-6 20 20 0 001-7 10 10 0 00-1-5 10 10 0 00-4-4 20 20 0 00-7-2 60 60 0 00-7 0zm160 0a6 6 0 00-3 1 6 6 0 00-2 3l-21 57v3a3 3 0 002 1h33a2 2 0 001 0 3 3 0 001-1 8 8 0 001-1 22 22 0 001-3 23 23 0 001-2 6 6 0 000-2 1 1 0 000-1 1 1 0 00-1 0h-24l7-19h20a2 2 0 001 0 3 3 0 001-1 8 8 0 000-1 23 23 0 001-3 22 22 0 001-2 5 5 0 000-2 1 1 0 00-1-1h-19l5-16h24a2 2 0 001 0 4 4 0 001-1 8 8 0 001-1 23 23 0 001-3 23 23 0 000-2 6 6 0 001-2 1 1 0 00-1-1zm-277 0a6 6 0 00-4 1 6 6 0 00-2 3l-21 57v3a3 3 0 003 1h17a52 52 0 008 0 41 41 0 006-2 37 37 0 006-2 30 30 0 006-4 29 29 0 004-5 27 27 0 003-6 17 17 0 002-6 11 11 0 00-1-5 9 9 0 00-3-3 12 12 0 00-5-2 23 23 0 005-2 22 22 0 004-3 23 23 0 003-4 23 23 0 002-4 16 16 0 001-8 8 8 0 00-2-5 13 13 0 00-6-3 39 39 0 00-10-1zm5 10h7a15 15 0 015 0 5 5 0 012 2 4 4 0 011 3 10 10 0 01-1 3 14 14 0 01-2 3 13 13 0 01-2 3 12 12 0 01-4 2 15 15 0 01-5 1h-7zm118 0h6a31 31 0 013 0 15 15 0 013 1c2 0 3 1 3 3a9 9 0 010 5 14 14 0 01-2 4 13 13 0 01-4 3 15 15 0 01-4 2 19 19 0 01-5 1h-7zM89 203h8a20 20 0 016 0 7 7 0 013 2 5 5 0 011 3 10 10 0 01-1 4 13 13 0 01-2 4 14 14 0 01-3 3 14 14 0 01-4 2 18 18 0 01-5 0h-9z" fill="#383a41"/></svg>
\ No newline at end of file
diff --git a/assets/images/visa.svg b/assets/images/visa.svg
new file mode 100644
index 0000000..9310fcd
--- /dev/null
+++ b/assets/images/visa.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 750 471" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="#0E4595" width="750" height="471" rx="40"/><path d="M278 334l34-196h53l-33 196h-54zm246-191c-10-4-27-9-48-9-52 0-89 27-90 65 0 28 27 44 47 53 21 10 28 16 28 25 0 13-17 19-32 19-22 0-33-3-50-11l-7-3-8 44c13 6 36 10 60 11 56 0 92-27 93-67 0-23-14-40-45-54-19-9-30-15-30-24 0-8 9-17 30-17 18 0 30 4 40 8l5 2 7-42m138-5h-42c-12 0-22 4-28 17l-79 179h56l11-29h69l6 29h50l-43-196zm-66 127l21-55 8-19 3 17 12 57h-44zM233 138l-52 134-6-27c-10-31-40-65-74-82l48 171h56l84-196h-56" fill="#FFF"/><path d="M132 138H46l-1 5c67 16 111 55 130 102l-19-90c-3-12-12-16-24-17" fill="#F2AE14"/></g></svg>
\ No newline at end of file
diff --git a/assets/images/wechat.svg b/assets/images/wechat.svg
new file mode 100644
index 0000000..6c65a37
--- /dev/null
+++ b/assets/images/wechat.svg
@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 212" preserveAspectRatio="xMidYMid meet"><defs><style>.cls-1{fill:#2e3233}.cls-2{fill:#9de60b}</style></defs><path class="cls-1" d="M492 67c17-4 36 0 47 14 5 5 7 12 8 19h-21c-3-15-25-21-36-11-8 9-9 21-7 33 1 8 5 18 14 22 12 4 27-4 29-18l22 1c-2 13-8 26-21 32-20 8-48 6-60-15 2-8 4-17 2-25-1-7-4-12-6-18 0-17 14-31 29-34z"/><path class="cls-2" d="M274 70l24-1c4 21 7 42 13 62l13-51c1-5 5-11 11-10 7-1 11 5 12 10l13 51c6-20 9-41 14-61h23l-21 77c-1 6-4 13-11 16-8 2-15-5-17-12l-13-47c-3 16-7 31-12 46-1 7-7 14-15 13-7-1-11-8-13-15l-21-78z"/><path class="cls-1" d="M552 70h22v23c11 0 24-3 34 3 9 5 14 15 14 25v42h-20v-40c0-5-3-9-8-10h-21v50h-21V70zm162 0h20v21h16v15h-16v36c4 4 10 4 15 5v16c-11 0-27 2-33-11-5-14-1-31-2-46h-15V91h15V70z"/><path class="cls-2" d="M462 132c1-14-2-29-14-37-16-10-41-8-51 8-9 15-9 36 3 49 11 13 31 14 46 7 8-3 13-11 16-19h-20c-6 7-16 10-24 5-5-2-6-8-8-13h52zm-52-14c2-7 8-14 16-12 8-2 14 5 16 12h-32z"/><path class="cls-1" d="M695 114c0-12-11-22-23-24s-26-1-35 7c-6 4-7 10-9 16h19c3-10 17-11 25-6 3 3 3 7 4 11-13 0-27-2-39 5-10 6-12 22-6 32 4 7 13 8 20 8h44v-49zm-47 30c-1-4 1-7 2-10 8-2 17-2 25-2v17c-9-1-20 2-27-5z"/><path class="cls-2" d="M145 13C118-2 85-4 57 6c-19 7-36 20-47 37C1 58-3 77 2 95c5 20 18 36 35 47l-9 27 31-16a116 116 0 0039 5 67 67 0 01-3-31c3-15 11-28 21-38 19-17 45-25 70-23-5-22-21-42-41-53zM74 54c-2 9-14 14-21 8-8-6-6-20 4-23 9-4 20 6 17 15zm64-2c0 10-13 16-21 10s-6-20 4-23c8-3 18 4 17 13z"/><path class="cls-1" d="M251 114c-7-15-19-26-33-33a91 91 0 00-82 0c-17 9-31 25-36 44-3 14 0 30 8 42 11 19 31 31 53 35 15 3 31 1 46-3 9 3 17 9 25 13l-7-22c10-7 19-16 24-27a57 57 0 002-49zm-88 6c-2 7-12 9-17 3-5-5-3-15 4-17 8-3 17 6 13 14zm51 1c-2 6-12 7-16 2l-4-7c1-5 5-10 10-10 8-2 14 8 10 15z"/></svg>
\ No newline at end of file
diff --git a/assets/index.html b/assets/index.html
new file mode 100644
index 0000000..9cf8496
--- /dev/null
+++ b/assets/index.html
@@ -0,0 +1,11 @@
+<html><head><title> - Revision 2844313: /woocommerce-gateway-stripe/trunk/assets</title></head>
+<body>
+ <h2> - Revision 2844313: /woocommerce-gateway-stripe/trunk/assets</h2>
+ <ul>
+ <li><a href="../">..</a></li>
+ <li><a href="css/">css/</a></li>
+ <li><a href="images/">images/</a></li>
+ <li><a href="js/">js/</a></li>
+ </ul>
+ <hr noshade><em>Powered by <a href="http://subversion.apache.org/">Apache Subversion</a> version 1.9.5 (r1770682).</em>
+</body></html>
\ No newline at end of file
diff --git a/assets/js/index.html b/assets/js/index.html
new file mode 100644
index 0000000..5634921
--- /dev/null
+++ b/assets/js/index.html
@@ -0,0 +1,14 @@
+<html><head><title> - Revision 2844313: /woocommerce-gateway-stripe/trunk/assets/js</title></head>
+<body>
+ <h2> - Revision 2844313: /woocommerce-gateway-stripe/trunk/assets/js</h2>
+ <ul>
+ <li><a href="../">..</a></li>
+ <li><a href="jquery.mask.js">jquery.mask.js</a></li>
+ <li><a href="jquery.mask.min.js">jquery.mask.min.js</a></li>
+ <li><a href="stripe-payment-request.js">stripe-payment-request.js</a></li>
+ <li><a href="stripe-payment-request.min.js">stripe-payment-request.min.js</a></li>
+ <li><a href="stripe.js">stripe.js</a></li>
+ <li><a href="stripe.min.js">stripe.min.js</a></li>
+ </ul>
+ <hr noshade><em>Powered by <a href="http://subversion.apache.org/">Apache Subversion</a> version 1.9.5 (r1770682).</em>
+</body></html>
\ No newline at end of file
diff --git a/assets/js/jquery.mask.js b/assets/js/jquery.mask.js
new file mode 100644
index 0000000..6f2417d
--- /dev/null
+++ b/assets/js/jquery.mask.js
@@ -0,0 +1,604 @@
+/**
+ * jquery.mask.js
+ * @version: v1.14.16
+ * @author: Igor Escobar
+ *
+ * Created by Igor Escobar on 2012-03-10. Please report any bug at github.com/igorescobar/jQuery-Mask-Plugin
+ *
+ * Copyright (c) 2012 Igor Escobar http://igorescobar.com
+ *
+ * The MIT License (http://www.opensource.org/licenses/mit-license.php)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* jshint laxbreak: true */
+/* jshint maxcomplexity:17 */
+/* global define */
+
+// UMD (Universal Module Definition) patterns for JavaScript modules that work everywhere.
+// https://github.com/umdjs/umd/blob/master/templates/jqueryPlugin.js
+(function (factory, jQuery, Zepto) {
+
+ if (typeof define === 'function' && define.amd) {
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object' && typeof Meteor === 'undefined') {
+ module.exports = factory(require('jquery'));
+ } else {
+ factory(jQuery || Zepto);
+ }
+
+}(function ($) {
+ 'use strict';
+
+ var Mask = function (el, mask, options) {
+
+ var p = {
+ invalid: [],
+ getCaret: function () {
+ try {
+ var sel,
+ pos = 0,
+ ctrl = el.get(0),
+ dSel = document.selection,
+ cSelStart = ctrl.selectionStart;
+
+ // IE Support
+ if (dSel && navigator.appVersion.indexOf('MSIE 10') === -1) {
+ sel = dSel.createRange();
+ sel.moveStart('character', -p.val().length);
+ pos = sel.text.length;
+ }
+ // Firefox support
+ else if (cSelStart || cSelStart === '0') {
+ pos = cSelStart;
+ }
+
+ return pos;
+ } catch (e) {}
+ },
+ setCaret: function(pos) {
+ try {
+ if (el.is(':focus')) {
+ var range, ctrl = el.get(0);
+
+ // Firefox, WebKit, etc..
+ if (ctrl.setSelectionRange) {
+ ctrl.setSelectionRange(pos, pos);
+ } else { // IE
+ range = ctrl.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', pos);
+ range.moveStart('character', pos);
+ range.select();
+ }
+ }
+ } catch (e) {}
+ },
+ events: function() {
+ el
+ .on('keydown.mask', function(e) {
+ el.data('mask-keycode', e.keyCode || e.which);
+ el.data('mask-previus-value', el.val());
+ el.data('mask-previus-caret-pos', p.getCaret());
+ p.maskDigitPosMapOld = p.maskDigitPosMap;
+ })
+ .on($.jMaskGlobals.useInput ? 'input.mask' : 'keyup.mask', p.behaviour)
+ .on('paste.mask drop.mask', function() {
+ setTimeout(function() {
+ el.keydown().keyup();
+ }, 100);
+ })
+ .on('change.mask', function(){
+ el.data('changed', true);
+ })
+ .on('blur.mask', function(){
+ if (oldValue !== p.val() && !el.data('changed')) {
+ el.trigger('change');
+ }
+ el.data('changed', false);
+ })
+ // it's very important that this callback remains in this position
+ // otherwhise oldValue it's going to work buggy
+ .on('blur.mask', function() {
+ oldValue = p.val();
+ })
+ // select all text on focus
+ .on('focus.mask', function (e) {
+ if (options.selectOnFocus === true) {
+ $(e.target).select();
+ }
+ })
+ // clear the value if it not complete the mask
+ .on('focusout.mask', function() {
+ if (options.clearIfNotMatch && !regexMask.test(p.val())) {
+ p.val('');
+ }
+ });
+ },
+ getRegexMask: function() {
+ var maskChunks = [], translation, pattern, optional, recursive, oRecursive, r;
+
+ for (var i = 0; i < mask.length; i++) {
+ translation = jMask.translation[mask.charAt(i)];
+
+ if (translation) {
+
+ pattern = translation.pattern.toString().replace(/.{1}$|^.{1}/g, '');
+ optional = translation.optional;
+ recursive = translation.recursive;
+
+ if (recursive) {
+ maskChunks.push(mask.charAt(i));
+ oRecursive = {digit: mask.charAt(i), pattern: pattern};
+ } else {
+ maskChunks.push(!optional && !recursive ? pattern : (pattern + '?'));
+ }
+
+ } else {
+ maskChunks.push(mask.charAt(i).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
+ }
+ }
+
+ r = maskChunks.join('');
+
+ if (oRecursive) {
+ r = r.replace(new RegExp('(' + oRecursive.digit + '(.*' + oRecursive.digit + ')?)'), '($1)?')
+ .replace(new RegExp(oRecursive.digit, 'g'), oRecursive.pattern);
+ }
+
+ return new RegExp(r);
+ },
+ destroyEvents: function() {
+ el.off(['input', 'keydown', 'keyup', 'paste', 'drop', 'blur', 'focusout', ''].join('.mask '));
+ },
+ val: function(v) {
+ var isInput = el.is('input'),
+ method = isInput ? 'val' : 'text',
+ r;
+
+ if (arguments.length > 0) {
+ if (el[method]() !== v) {
+ el[method](v);
+ }
+ r = el;
+ } else {
+ r = el[method]();
+ }
+
+ return r;
+ },
+ calculateCaretPosition: function(oldVal) {
+ var newVal = p.getMasked(),
+ caretPosNew = p.getCaret();
+ if (oldVal !== newVal) {
+ var caretPosOld = el.data('mask-previus-caret-pos') || 0,
+ newValL = newVal.length,
+ oldValL = oldVal.length,
+ maskDigitsBeforeCaret = 0,
+ maskDigitsAfterCaret = 0,
+ maskDigitsBeforeCaretAll = 0,
+ maskDigitsBeforeCaretAllOld = 0,
+ i = 0;
+
+ for (i = caretPosNew; i < newValL; i++) {
+ if (!p.maskDigitPosMap[i]) {
+ break;
+ }
+ maskDigitsAfterCaret++;
+ }
+
+ for (i = caretPosNew - 1; i >= 0; i--) {
+ if (!p.maskDigitPosMap[i]) {
+ break;
+ }
+ maskDigitsBeforeCaret++;
+ }
+
+ for (i = caretPosNew - 1; i >= 0; i--) {
+ if (p.maskDigitPosMap[i]) {
+ maskDigitsBeforeCaretAll++;
+ }
+ }
+
+ for (i = caretPosOld - 1; i >= 0; i--) {
+ if (p.maskDigitPosMapOld[i]) {
+ maskDigitsBeforeCaretAllOld++;
+ }
+ }
+
+ // if the cursor is at the end keep it there
+ if (caretPosNew > oldValL) {
+ caretPosNew = newValL * 10;
+ } else if (caretPosOld >= caretPosNew && caretPosOld !== oldValL) {
+ if (!p.maskDigitPosMapOld[caretPosNew]) {
+ var caretPos = caretPosNew;
+ caretPosNew -= maskDigitsBeforeCaretAllOld - maskDigitsBeforeCaretAll;
+ caretPosNew -= maskDigitsBeforeCaret;
+ if (p.maskDigitPosMap[caretPosNew]) {
+ caretPosNew = caretPos;
+ }
+ }
+ }
+ else if (caretPosNew > caretPosOld) {
+ caretPosNew += maskDigitsBeforeCaretAll - maskDigitsBeforeCaretAllOld;
+ caretPosNew += maskDigitsAfterCaret;
+ }
+ }
+ return caretPosNew;
+ },
+ behaviour: function(e) {
+ e = e || window.event;
+ p.invalid = [];
+
+ var keyCode = el.data('mask-keycode');
+
+ if ($.inArray(keyCode, jMask.byPassKeys) === -1) {
+ var newVal = p.getMasked(),
+ caretPos = p.getCaret(),
+ oldVal = el.data('mask-previus-value') || '';
+
+ // this is a compensation to devices/browsers that don't compensate
+ // caret positioning the right way
+ setTimeout(function() {
+ p.setCaret(p.calculateCaretPosition(oldVal));
+ }, $.jMaskGlobals.keyStrokeCompensation);
+
+ p.val(newVal);
+ p.setCaret(caretPos);
+ return p.callbacks(e);
+ }
+ },
+ getMasked: function(skipMaskChars, val) {
+ var buf = [],
+ value = val === undefined ? p.val() : val + '',
+ m = 0, maskLen = mask.length,
+ v = 0, valLen = value.length,
+ offset = 1, addMethod = 'push',
+ resetPos = -1,
+ maskDigitCount = 0,
+ maskDigitPosArr = [],
+ lastMaskChar,
+ check;
+
+ if (options.reverse) {
+ addMethod = 'unshift';
+ offset = -1;
+ lastMaskChar = 0;
+ m = maskLen - 1;
+ v = valLen - 1;
+ check = function () {
+ return m > -1 && v > -1;
+ };
+ } else {
+ lastMaskChar = maskLen - 1;
+ check = function () {
+ return m < maskLen && v < valLen;
+ };
+ }
+
+ var lastUntranslatedMaskChar;
+ while (check()) {
+ var maskDigit = mask.charAt(m),
+ valDigit = value.charAt(v),
+ translation = jMask.translation[maskDigit];
+
+ if (translation) {
+ if (valDigit.match(translation.pattern)) {
+ buf[addMethod](valDigit);
+ if (translation.recursive) {
+ if (resetPos === -1) {
+ resetPos = m;
+ } else if (m === lastMaskChar && m !== resetPos) {
+ m = resetPos - offset;
+ }
+
+ if (lastMaskChar === resetPos) {
+ m -= offset;
+ }
+ }
+ m += offset;
+ } else if (valDigit === lastUntranslatedMaskChar) {
+ // matched the last untranslated (raw) mask character that we encountered
+ // likely an insert offset the mask character from the last entry; fall
+ // through and only increment v
+ maskDigitCount--;
+ lastUntranslatedMaskChar = undefined;
+ } else if (translation.optional) {
+ m += offset;
+ v -= offset;
+ } else if (translation.fallback) {
+ buf[addMethod](translation.fallback);
+ m += offset;
+ v -= offset;
+ } else {
+ p.invalid.push({p: v, v: valDigit, e: translation.pattern});
+ }
+ v += offset;
+ } else {
+ if (!skipMaskChars) {
+ buf[addMethod](maskDigit);
+ }
+
+ if (valDigit === maskDigit) {
+ maskDigitPosArr.push(v);
+ v += offset;
+ } else {
+ lastUntranslatedMaskChar = maskDigit;
+ maskDigitPosArr.push(v + maskDigitCount);
+ maskDigitCount++;
+ }
+
+ m += offset;
+ }
+ }
+
+ var lastMaskCharDigit = mask.charAt(lastMaskChar);
+ if (maskLen === valLen + 1 && !jMask.translation[lastMaskCharDigit]) {
+ buf.push(lastMaskCharDigit);
+ }
+
+ var newVal = buf.join('');
+ p.mapMaskdigitPositions(newVal, maskDigitPosArr, valLen);
+ return newVal;
+ },
+ mapMaskdigitPositions: function(newVal, maskDigitPosArr, valLen) {
+ var maskDiff = options.reverse ? newVal.length - valLen : 0;
+ p.maskDigitPosMap = {};
+ for (var i = 0; i < maskDigitPosArr.length; i++) {
+ p.maskDigitPosMap[maskDigitPosArr[i] + maskDiff] = 1;
+ }
+ },
+ callbacks: function (e) {
+ var val = p.val(),
+ changed = val !== oldValue,
+ defaultArgs = [val, e, el, options],
+ callback = function(name, criteria, args) {
+ if (typeof options[name] === 'function' && criteria) {
+ options[name].apply(this, args);
+ }
+ };
+
+ callback('onChange', changed === true, defaultArgs);
+ callback('onKeyPress', changed === true, defaultArgs);
+ callback('onComplete', val.length === mask.length, defaultArgs);
+ callback('onInvalid', p.invalid.length > 0, [val, e, el, p.invalid, options]);
+ }
+ };
+
+ el = $(el);
+ var jMask = this, oldValue = p.val(), regexMask;
+
+ mask = typeof mask === 'function' ? mask(p.val(), undefined, el, options) : mask;
+
+ // public methods
+ jMask.mask = mask;
+ jMask.options = options;
+ jMask.remove = function() {
+ var caret = p.getCaret();
+ if (jMask.options.placeholder) {
+ el.removeAttr('placeholder');
+ }
+ if (el.data('mask-maxlength')) {
+ el.removeAttr('maxlength');
+ }
+ p.destroyEvents();
+ p.val(jMask.getCleanVal());
+ p.setCaret(caret);
+ return el;
+ };
+
+ // get value without mask
+ jMask.getCleanVal = function() {
+ return p.getMasked(true);
+ };
+
+ // get masked value without the value being in the input or element
+ jMask.getMaskedVal = function(val) {
+ return p.getMasked(false, val);
+ };
+
+ jMask.init = function(onlyMask) {
+ onlyMask = onlyMask || false;
+ options = options || {};
+
+ jMask.clearIfNotMatch = $.jMaskGlobals.clearIfNotMatch;
+ jMask.byPassKeys = $.jMaskGlobals.byPassKeys;
+ jMask.translation = $.extend({}, $.jMaskGlobals.translation, options.translation);
+
+ jMask = $.extend(true, {}, jMask, options);
+
+ regexMask = p.getRegexMask();
+
+ if (onlyMask) {
+ p.events();
+ p.val(p.getMasked());
+ } else {
+ if (options.placeholder) {
+ el.attr('placeholder' , options.placeholder);
+ }
+
+ // this is necessary, otherwise if the user submit the form
+ // and then press the "back" button, the autocomplete will erase
+ // the data. Works fine on IE9+, FF, Opera, Safari.
+ if (el.data('mask')) {
+ el.attr('autocomplete', 'off');
+ }
+
+ // detect if is necessary let the user type freely.
+ // for is a lot faster than forEach.
+ for (var i = 0, maxlength = true; i < mask.length; i++) {
+ var translation = jMask.translation[mask.charAt(i)];
+ if (translation && translation.recursive) {
+ maxlength = false;
+ break;
+ }
+ }
+
+ if (maxlength) {
+ el.attr('maxlength', mask.length).data('mask-maxlength', true);
+ }
+
+ p.destroyEvents();
+ p.events();
+
+ var caret = p.getCaret();
+ p.val(p.getMasked());
+ p.setCaret(caret);
+ }
+ };
+
+ jMask.init(!el.is('input'));
+ };
+
+ $.maskWatchers = {};
+ var HTMLAttributes = function () {
+ var input = $(this),
+ options = {},
+ prefix = 'data-mask-',
+ mask = input.attr('data-mask');
+
+ if (input.attr(prefix + 'reverse')) {
+ options.reverse = true;
+ }
+
+ if (input.attr(prefix + 'clearifnotmatch')) {
+ options.clearIfNotMatch = true;
+ }
+
+ if (input.attr(prefix + 'selectonfocus') === 'true') {
+ options.selectOnFocus = true;
+ }
+
+ if (notSameMaskObject(input, mask, options)) {
+ return input.data('mask', new Mask(this, mask, options));
+ }
+ },
+ notSameMaskObject = function(field, mask, options) {
+ options = options || {};
+ var maskObject = $(field).data('mask'),
+ stringify = JSON.stringify,
+ value = $(field).val() || $(field).text();
+ try {
+ if (typeof mask === 'function') {
+ mask = mask(value);
+ }
+ return typeof maskObject !== 'object' || stringify(maskObject.options) !== stringify(options) || maskObject.mask !== mask;
+ } catch (e) {}
+ },
+ eventSupported = function(eventName) {
+ var el = document.createElement('div'), isSupported;
+
+ eventName = 'on' + eventName;
+ isSupported = (eventName in el);
+
+ if ( !isSupported ) {
+ el.setAttribute(eventName, 'return;');
+ isSupported = typeof el[eventName] === 'function';
+ }
+ el = null;
+
+ return isSupported;
+ };
+
+ $.fn.mask = function(mask, options) {
+ options = options || {};
+ var selector = this.selector,
+ globals = $.jMaskGlobals,
+ interval = globals.watchInterval,
+ watchInputs = options.watchInputs || globals.watchInputs,
+ maskFunction = function() {
+ if (notSameMaskObject(this, mask, options)) {
+ return $(this).data('mask', new Mask(this, mask, options));
+ }
+ };
+
+ $(this).each(maskFunction);
+
+ if (selector && selector !== '' && watchInputs) {
+ clearInterval($.maskWatchers[selector]);
+ $.maskWatchers[selector] = setInterval(function(){
+ $(document).find(selector).each(maskFunction);
+ }, interval);
+ }
+ return this;
+ };
+
+ $.fn.masked = function(val) {
+ return this.data('mask').getMaskedVal(val);
+ };
+
+ $.fn.unmask = function() {
+ clearInterval($.maskWatchers[this.selector]);
+ delete $.maskWatchers[this.selector];
+ return this.each(function() {
+ var dataMask = $(this).data('mask');
+ if (dataMask) {
+ dataMask.remove().removeData('mask');
+ }
+ });
+ };
+
+ $.fn.cleanVal = function() {
+ return this.data('mask').getCleanVal();
+ };
+
+ $.applyDataMask = function(selector) {
+ selector = selector || $.jMaskGlobals.maskElements;
+ var $selector = (selector instanceof $) ? selector : $(selector);
+ $selector.filter($.jMaskGlobals.dataMaskAttr).each(HTMLAttributes);
+ };
+
+ var globals = {
+ maskElements: 'input,td,span,div',
+ dataMaskAttr: '*[data-mask]',
+ dataMask: true,
+ watchInterval: 300,
+ watchInputs: true,
+ keyStrokeCompensation: 10,
+ // old versions of chrome dont work great with input event
+ useInput: !/Chrome\/[2-4][0-9]|SamsungBrowser/.test(window.navigator.userAgent) && eventSupported('input'),
+ watchDataMask: false,
+ byPassKeys: [9, 16, 17, 18, 36, 37, 38, 39, 40, 91],
+ translation: {
+ '0': {pattern: /\d/},
+ '9': {pattern: /\d/, optional: true},
+ '#': {pattern: /\d/, recursive: true},
+ 'A': {pattern: /[a-zA-Z0-9]/},
+ 'S': {pattern: /[a-zA-Z]/}
+ }
+ };
+
+ $.jMaskGlobals = $.jMaskGlobals || {};
+ globals = $.jMaskGlobals = $.extend(true, {}, globals, $.jMaskGlobals);
+
+ // looking for inputs with data-mask attribute
+ if (globals.dataMask) {
+ $.applyDataMask();
+ }
+
+ setInterval(function() {
+ if ($.jMaskGlobals.watchDataMask) {
+ $.applyDataMask();
+ }
+ }, globals.watchInterval);
+}, window.jQuery, window.Zepto));
diff --git a/assets/js/jquery.mask.min.js b/assets/js/jquery.mask.min.js
new file mode 100644
index 0000000..77ef3e4
--- /dev/null
+++ b/assets/js/jquery.mask.min.js
@@ -0,0 +1 @@
+!function(t,a,e){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports&&"undefined"==typeof Meteor?module.exports=t(require("jquery")):t(a||e)}(function(o){"use strict";function i(u,M,y){var b={invalid:[],getCaret:function(){try{var t,a=0,e=u.get(0),n=document.selection,s=e.selectionStart;return n&&-1===navigator.appVersion.indexOf("MSIE 10")?((t=n.createRange()).moveStart("character",-b.val().length),a=t.text.length):!s&&"0"!==s||(a=s),a}catch(t){}},setCaret:function(t){try{var a,e;u.is(":focus")&&((e=u.get(0)).setSelectionRange?e.setSelectionRange(t,t):((a=e.createTextRange()).collapse(!0),a.moveEnd("character",t),a.moveStart("character",t),a.select()))}catch(t){}},events:function(){u.on("keydown.mask",function(t){u.data("mask-keycode",t.keyCode||t.which),u.data("mask-previus-value",u.val()),u.data("mask-previus-caret-pos",b.getCaret()),b.maskDigitPosMapOld=b.maskDigitPosMap}).on(o.jMaskGlobals.useInput?"input.mask":"keyup.mask",b.behaviour).on("paste.mask drop.mask",function(){setTimeout(function(){u.keydown().keyup()},100)}).on("change.mask",function(){u.data("changed",!0)}).on("blur.mask",function(){r===b.val()||u.data("changed")||u.trigger("change"),u.data("changed",!1)}).on("blur.mask",function(){r=b.val()}).on("focus.mask",function(t){!0===y.selectOnFocus&&o(t.target).select()}).on("focusout.mask",function(){y.clearIfNotMatch&&!s.test(b.val())&&b.val("")})},getRegexMask:function(){for(var t,a,e,n,s,r=[],o=0;o<M.length;o++)(e=w.translation[M.charAt(o)])?(t=e.pattern.toString().replace(/.{1}$|^.{1}/g,""),a=e.optional,(e=e.recursive)?(r.push(M.charAt(o)),n={digit:M.charAt(o),pattern:t}):r.push(a||e?t+"?":t)):r.push(M.charAt(o).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"));return s=r.join(""),n&&(s=s.replace(new RegExp("("+n.digit+"(.*"+n.digit+")?)"),"($1)?").replace(new RegExp(n.digit,"g"),n.pattern)),new RegExp(s)},destroyEvents:function(){u.off(["input","keydown","keyup","paste","drop","blur","focusout",""].join(".mask "))},val:function(t){var a=u.is("input")?"val":"text",a=0<arguments.length?(u[a]()!==t&&u[a](t),u):u[a]();return a},calculateCaretPosition:function(t){var a=b.getMasked(),e=b.getCaret();if(t!==a){for(var n=u.data("mask-previus-caret-pos")||0,s=a.length,t=t.length,r=0,o=0,i=0,l=0,c=0,c=e;c<s&&b.maskDigitPosMap[c];c++)o++;for(c=e-1;0<=c&&b.maskDigitPosMap[c];c--)r++;for(c=e-1;0<=c;c--)b.maskDigitPosMap[c]&&i++;for(c=n-1;0<=c;c--)b.maskDigitPosMapOld[c]&&l++;t<e?e=10*s:e<=n&&n!==t?b.maskDigitPosMapOld[e]||(t=e,e-=l-i,b.maskDigitPosMap[e-=r]&&(e=t)):n<e&&(e+=i-l,e+=o)}return e},behaviour:function(t){t=t||window.event,b.invalid=[];var a=u.data("mask-keycode");if(-1===o.inArray(a,w.byPassKeys)){var e=b.getMasked(),a=b.getCaret(),n=u.data("mask-previus-value")||"";return setTimeout(function(){b.setCaret(b.calculateCaretPosition(n))},o.jMaskGlobals.keyStrokeCompensation),b.val(e),b.setCaret(a),b.callbacks(t)}},getMasked:function(t,a){for(var e,n,s=[],r=void 0===a?b.val():a+"",o=0,i=M.length,l=0,c=r.length,u=1,k="push",p=-1,d=0,f=[],h=y.reverse?(k="unshift",u=-1,e=0,o=i-1,l=c-1,function(){return-1<o&&-1<l}):(e=i-1,function(){return o<i&&l<c});h();){var v=M.charAt(o),g=r.charAt(l),m=w.translation[v];m?(g.match(m.pattern)?(s[k](g),m.recursive&&(-1===p?p=o:o===e&&o!==p&&(o=p-u),e===p&&(o-=u)),o+=u):g===n?(d--,n=void 0):m.optional?(o+=u,l-=u):m.fallback?(s[k](m.fallback),o+=u,l-=u):b.invalid.push({p:l,v:g,e:m.pattern}),l+=u):(t||s[k](v),g===v?(f.push(l),l+=u):(n=v,f.push(l+d),d++),o+=u)}a=M.charAt(e);i!==c+1||w.translation[a]||s.push(a);a=s.join("");return b.mapMaskdigitPositions(a,f,c),a},mapMaskdigitPositions:function(t,a,e){var n=y.reverse?t.length-e:0;b.maskDigitPosMap={};for(var s=0;s<a.length;s++)b.maskDigitPosMap[a[s]+n]=1},callbacks:function(t){function a(t,a,e){"function"==typeof y[t]&&a&&y[t].apply(this,e)}var e=b.val(),n=e!==r,s=[e,t,u,y];a("onChange",!0==n,s),a("onKeyPress",!0==n,s),a("onComplete",e.length===M.length,s),a("onInvalid",0<b.invalid.length,[e,t,u,b.invalid,y])}};u=o(u);var s,w=this,r=b.val();M="function"==typeof M?M(b.val(),void 0,u,y):M,w.mask=M,w.options=y,w.remove=function(){var t=b.getCaret();return w.options.placeholder&&u.removeAttr("placeholder"),u.data("mask-maxlength")&&u.removeAttr("maxlength"),b.destroyEvents(),b.val(w.getCleanVal()),b.setCaret(t),u},w.getCleanVal=function(){return b.getMasked(!0)},w.getMaskedVal=function(t){return b.getMasked(!1,t)},w.init=function(t){if(t=t||!1,y=y||{},w.clearIfNotMatch=o.jMaskGlobals.clearIfNotMatch,w.byPassKeys=o.jMaskGlobals.byPassKeys,w.translation=o.extend({},o.jMaskGlobals.translation,y.translation),w=o.extend(!0,{},w,y),s=b.getRegexMask(),t)b.events(),b.val(b.getMasked());else{y.placeholder&&u.attr("placeholder",y.placeholder),u.data("mask")&&u.attr("autocomplete","off");for(var a=0,e=!0;a<M.length;a++){var n=w.translation[M.charAt(a)];if(n&&n.recursive){e=!1;break}}e&&u.attr("maxlength",M.length).data("mask-maxlength",!0),b.destroyEvents(),b.events();t=b.getCaret();b.val(b.getMasked()),b.setCaret(t)}},w.init(!u.is("input"))}o.maskWatchers={};function a(){var t=o(this),a={},e="data-mask-",n=t.attr("data-mask");if(t.attr(e+"reverse")&&(a.reverse=!0),t.attr(e+"clearifnotmatch")&&(a.clearIfNotMatch=!0),"true"===t.attr(e+"selectonfocus")&&(a.selectOnFocus=!0),l(t,n,a))return t.data("mask",new i(this,n,a))}function l(t,a,e){e=e||{};var n=o(t).data("mask"),s=JSON.stringify,t=o(t).val()||o(t).text();try{return"function"==typeof a&&(a=a(t)),"object"!=typeof n||s(n.options)!==s(e)||n.mask!==a}catch(t){}}o.fn.mask=function(t,a){a=a||{};function e(){if(l(this,t,a))return o(this).data("mask",new i(this,t,a))}var n=this.selector,s=o.jMaskGlobals,r=s.watchInterval,s=a.watchInputs||s.watchInputs;return o(this).each(e),n&&""!==n&&s&&(clearInterval(o.maskWatchers[n]),o.maskWatchers[n]=setInterval(function(){o(document).find(n).each(e)},r)),this},o.fn.masked=function(t){return this.data("mask").getMaskedVal(t)},o.fn.unmask=function(){return clearInterval(o.maskWatchers[this.selector]),delete o.maskWatchers[this.selector],this.each(function(){var t=o(this).data("mask");t&&t.remove().removeData("mask")})},o.fn.cleanVal=function(){return this.data("mask").getCleanVal()},o.applyDataMask=function(t){((t=t||o.jMaskGlobals.maskElements)instanceof o?t:o(t)).filter(o.jMaskGlobals.dataMaskAttr).each(a)};var t,e,n={maskElements:"input,td,span,div",dataMaskAttr:"*[data-mask]",dataMask:!0,watchInterval:300,watchInputs:!0,keyStrokeCompensation:10,useInput:!/Chrome\/[2-4][0-9]|SamsungBrowser/.test(window.navigator.userAgent)&&(t="input",e=document.createElement("div"),(n=(t="on"+t)in e)||(e.setAttribute(t,"return;"),n="function"==typeof e[t]),e=null,n),watchDataMask:!1,byPassKeys:[9,16,17,18,36,37,38,39,40,91],translation:{0:{pattern:/\d/},9:{pattern:/\d/,optional:!0},"#":{pattern:/\d/,recursive:!0},A:{pattern:/[a-zA-Z0-9]/},S:{pattern:/[a-zA-Z]/}}};o.jMaskGlobals=o.jMaskGlobals||{},(n=o.jMaskGlobals=o.extend(!0,{},n,o.jMaskGlobals)).dataMask&&o.applyDataMask(),setInterval(function(){o.jMaskGlobals.watchDataMask&&o.applyDataMask()},n.watchInterval)},window.jQuery,window.Zepto);
diff --git a/assets/js/stripe-payment-request.js b/assets/js/stripe-payment-request.js
new file mode 100644
index 0000000..3b4fc54
--- /dev/null
+++ b/assets/js/stripe-payment-request.js
@@ -0,0 +1,825 @@
+/* global wc_stripe_payment_request_params, Stripe */
+jQuery( function( $ ) {
+ 'use strict';
+
+ var stripe = Stripe( wc_stripe_payment_request_params.stripe.key, {
+ locale: wc_stripe_payment_request_params.stripe.locale
+ } ),
+ paymentRequestType;
+
+ /**
+ * Object to handle Stripe payment forms.
+ */
+ var wc_stripe_payment_request = {
+ /**
+ * Get WC AJAX endpoint URL.
+ *
+ * @param {String} endpoint Endpoint.
+ * @return {String}
+ */
+ getAjaxURL: function( endpoint ) {
+ return wc_stripe_payment_request_params.ajax_url
+ .toString()
+ .replace( '%%endpoint%%', 'wc_stripe_' + endpoint );
+ },
+
+ getCartDetails: function() {
+ var data = {
+ security: wc_stripe_payment_request_params.nonce.payment
+ };
+
+ $.ajax( {
+ type: 'POST',
+ data: data,
+ url: wc_stripe_payment_request.getAjaxURL( 'get_cart_details' ),
+ success: function( response ) {
+ wc_stripe_payment_request.startPaymentRequest( response );
+ }
+ } );
+ },
+
+ getAttributes: function() {
+ var select = $( '.variations_form' ).find( '.variations select' ),
+ data = {},
+ count = 0,
+ chosen = 0;
+
+ select.each( function() {
+ var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
+ var value = $( this ).val() || '';
+
+ if ( value.length > 0 ) {
+ chosen ++;
+ }
+
+ count ++;
+ data[ attribute_name ] = value;
+ });
+
+ return {
+ 'count' : count,
+ 'chosenCount': chosen,
+ 'data' : data
+ };
+ },
+
+ processSource: function( source, paymentRequestType ) {
+ var data = wc_stripe_payment_request.getOrderData( source, paymentRequestType );
+
+ return $.ajax( {
+ type: 'POST',
+ data: data,
+ dataType: 'json',
+ url: wc_stripe_payment_request.getAjaxURL( 'create_order' )
+ } );
+ },
+
+ /**
+ * Get order data.
+ *
+ * @since 3.1.0
+ * @version 4.0.0
+ * @param {PaymentResponse} source Payment Response instance.
+ *
+ * @return {Object}
+ */
+ getOrderData: function( evt, paymentRequestType ) {
+ var source = evt.source;
+ var email = source.owner.email;
+ var phone = source.owner.phone;
+ var billing = source.owner.address;
+ var name = source.owner.name;
+ var shipping = evt.shippingAddress;
+ var data = {
+ _wpnonce: wc_stripe_payment_request_params.nonce.checkout,
+ billing_first_name: null !== name ? name.split( ' ' ).slice( 0, 1 ).join( ' ' ) : '',
+ billing_last_name: null !== name ? name.split( ' ' ).slice( 1 ).join( ' ' ) : '',
+ billing_company: '',
+ billing_email: null !== email ? email : evt.payerEmail,
+ billing_phone: null !== phone ? phone : evt.payerPhone && evt.payerPhone.replace( '/[() -]/g', '' ),
+ billing_country: null !== billing ? billing.country : '',
+ billing_address_1: null !== billing ? billing.line1 : '',
+ billing_address_2: null !== billing ? billing.line2 : '',
+ billing_city: null !== billing ? billing.city : '',
+ billing_state: null !== billing ? billing.state : '',
+ billing_postcode: null !== billing ? billing.postal_code : '',
+ shipping_first_name: '',
+ shipping_last_name: '',
+ shipping_company: '',
+ shipping_country: '',
+ shipping_address_1: '',
+ shipping_address_2: '',
+ shipping_city: '',
+ shipping_state: '',
+ shipping_postcode: '',
+ shipping_method: [ null === evt.shippingOption ? null : evt.shippingOption.id ],
+ order_comments: '',
+ payment_method: 'stripe',
+ ship_to_different_address: 1,
+ terms: 1,
+ stripe_source: source.id,
+ payment_request_type: paymentRequestType
+ };
+
+ if ( shipping ) {
+ data.shipping_first_name = shipping.recipient.split( ' ' ).slice( 0, 1 ).join( ' ' );
+ data.shipping_last_name = shipping.recipient.split( ' ' ).slice( 1 ).join( ' ' );
+ data.shipping_company = shipping.organization;
+ data.shipping_country = shipping.country;
+ data.shipping_address_1 = typeof shipping.addressLine[0] === 'undefined' ? '' : shipping.addressLine[0];
+ data.shipping_address_2 = typeof shipping.addressLine[1] === 'undefined' ? '' : shipping.addressLine[1];
+ data.shipping_city = shipping.city;
+ data.shipping_state = shipping.region;
+ data.shipping_postcode = shipping.postalCode;
+ }
+
+ return data;
+ },
+
+ /**
+ * Generate error message HTML.
+ *
+ * @since 3.1.0
+ * @version 4.0.0
+ * @param {String} message Error message.
+ * @return {Object}
+ */
+ getErrorMessageHTML: function( message ) {
+ return $( '<div class="woocommerce-error" />' ).text( message );
+ },
+
+ /**
+ * Display error messages.
+ *
+ * @since 4.8.0
+ * @param {Object} message DOM object with error message to display.
+ */
+ displayErrorMessage: function( message ) {
+ $( '.woocommerce-error' ).remove();
+
+ if ( wc_stripe_payment_request_params.is_product_page ) {
+ var element = $( '.product' ).first();
+ element.before( message );
+
+ $( 'html, body' ).animate({
+ scrollTop: element.prev( '.woocommerce-error' ).offset().top
+ }, 600 );
+ } else {
+ var $form = $( '.shop_table.cart' ).closest( 'form' );
+ $form.before( message );
+ $( 'html, body' ).animate({
+ scrollTop: $form.prev( '.woocommerce-error' ).offset().top
+ }, 600 );
+ }
+ },
+
+ /**
+ * Abort payment and display error messages.
+ *
+ * @since 3.1.0
+ * @version 4.8.0
+ * @param {PaymentResponse} payment Payment response instance.
+ * @param {Object} message DOM object with error message to display.
+ */
+ abortPayment: function( payment, message ) {
+ payment.complete( 'fail' );
+ wc_stripe_payment_request.displayErrorMessage( message );
+ },
+
+ /**
+ * Complete payment.
+ *
+ * @since 3.1.0
+ * @version 4.0.0
+ * @param {PaymentResponse} payment Payment response instance.
+ * @param {String} url Order thank you page URL.
+ */
+ completePayment: function( payment, url ) {
+ wc_stripe_payment_request.block();
+
+ payment.complete( 'success' );
+
+ // Success, then redirect to the Thank You page.
+ window.location = url;
+ },
+
+ block: function() {
+ $.blockUI( {
+ message: null,
+ overlayCSS: {
+ background: '#fff',
+ opacity: 0.6
+ }
+ } );
+ },
+
+ /**
+ * Update shipping options.
+ *
+ * @param {Object} details Payment details.
+ * @param {PaymentAddress} address Shipping address.
+ */
+ updateShippingOptions: function( details, address ) {
+ var data = {
+ security: wc_stripe_payment_request_params.nonce.shipping,
+ country: address.country,
+ state: address.region,
+ postcode: address.postalCode,
+ city: address.city,
+ address: typeof address.addressLine[0] === 'undefined' ? '' : address.addressLine[0],
+ address_2: typeof address.addressLine[1] === 'undefined' ? '' : address.addressLine[1],
+ payment_request_type: paymentRequestType,
+ is_product_page: wc_stripe_payment_request_params.is_product_page,
+ };
+
+ return $.ajax( {
+ type: 'POST',
+ data: data,
+ url: wc_stripe_payment_request.getAjaxURL( 'get_shipping_options' )
+ } );
+ },
+
+ /**
+ * Updates the shipping price and the total based on the shipping option.
+ *
+ * @param {Object} details The line items and shipping options.
+ * @param {String} shippingOption User's preferred shipping option to use for shipping price calculations.
+ */
+ updateShippingDetails: function( details, shippingOption ) {
+ var data = {
+ security: wc_stripe_payment_request_params.nonce.update_shipping,
+ shipping_method: [ shippingOption.id ],
+ payment_request_type: paymentRequestType,
+ is_product_page: wc_stripe_payment_request_params.is_product_page,
+ };
+
+ return $.ajax( {
+ type: 'POST',
+ data: data,
+ url: wc_stripe_payment_request.getAjaxURL( 'update_shipping_method' )
+ } );
+ },
+
+ /**
+ * Adds the item to the cart and return cart details.
+ *
+ */
+ addToCart: function() {
+ var product_id = $( '.single_add_to_cart_button' ).val();
+
+ // Check if product is a variable product.
+ if ( $( '.single_variation_wrap' ).length ) {
+ product_id = $( '.single_variation_wrap' ).find( 'input[name="product_id"]' ).val();
+ }
+
+ var data = {
+ security: wc_stripe_payment_request_params.nonce.add_to_cart,
+ product_id: product_id,
+ qty: $( '.quantity .qty' ).val(),
+ attributes: $( '.variations_form' ).length ? wc_stripe_payment_request.getAttributes().data : []
+ };
+
+ // add addons data to the POST body
+ var formData = $( 'form.cart' ).serializeArray();
+ $.each( formData, function( i, field ) {
+ if ( /^addon-/.test( field.name ) ) {
+ if ( /\[\]$/.test( field.name ) ) {
+ var fieldName = field.name.substring( 0, field.name.length - 2);
+ if ( data[ fieldName ] ) {
+ data[ fieldName ].push( field.value );
+ } else {
+ data[ fieldName ] = [ field.value ];
+ }
+ } else {
+ data[ field.name ] = field.value;
+ }
+ }
+ } );
+
+ return $.ajax( {
+ type: 'POST',
+ data: data,
+ url: wc_stripe_payment_request.getAjaxURL( 'add_to_cart' )
+ } );
+ },
+
+ clearCart: function() {
+ var data = {
+ 'security': wc_stripe_payment_request_params.nonce.clear_cart
+ };
+
+ return $.ajax( {
+ type: 'POST',
+ data: data,
+ url: wc_stripe_payment_request.getAjaxURL( 'clear_cart' ),
+ success: function( response ) {}
+ } );
+ },
+
+ getRequestOptionsFromLocal: function() {
+ return {
+ total: wc_stripe_payment_request_params.product.total,
+ currency: wc_stripe_payment_request_params.checkout.currency_code,
+ country: wc_stripe_payment_request_params.checkout.country_code,
+ requestPayerName: true,
+ requestPayerEmail: true,
+ requestPayerPhone: wc_stripe_payment_request_params.checkout.needs_payer_phone,
+ requestShipping: wc_stripe_payment_request_params.product.requestShipping,
+ displayItems: wc_stripe_payment_request_params.product.displayItems
+ };
+ },
+
+ /**
+ * Starts the payment request
+ *
+ * @since 4.0.0
+ * @version 4.8.0
+ */
+ startPaymentRequest: function( cart ) {
+ var paymentDetails,
+ options;
+
+ if ( wc_stripe_payment_request_params.is_product_page ) {
+ options = wc_stripe_payment_request.getRequestOptionsFromLocal();
+
+ paymentDetails = options;
+ } else {
+ options = {
+ total: cart.order_data.total,
+ currency: cart.order_data.currency,
+ country: cart.order_data.country_code,
+ requestPayerName: true,
+ requestPayerEmail: true,
+ requestPayerPhone: wc_stripe_payment_request_params.checkout.needs_payer_phone,
+ requestShipping: cart.shipping_required ? true : false,
+ displayItems: cart.order_data.displayItems
+ };
+
+ paymentDetails = cart.order_data;
+ }
+
+ // Puerto Rico (PR) is the only US territory/possession that's supported by Stripe.
+ // Since it's considered a US state by Stripe, we need to do some special mapping.
+ if ( 'PR' === options.country ) {
+ options.country = 'US';
+ }
+
+ // Handle errors thrown by Stripe, so we don't break the product page
+ try {
+ var paymentRequest = stripe.paymentRequest( options );
+
+ var elements = stripe.elements( { locale: wc_stripe_payment_request_params.button.locale } );
+ var prButton = wc_stripe_payment_request.createPaymentRequestButton( elements, paymentRequest );
+
+ // Check the availability of the Payment Request API first.
+ paymentRequest.canMakePayment().then( function( result ) {
+ if ( ! result ) {
+ return;
+ }
+ if ( result.applePay ) {
+ paymentRequestType = 'apple_pay';
+ } else if ( result.googlePay ) {
+ paymentRequestType = 'google_pay';
+ } else {
+ paymentRequestType = 'payment_request_api';
+ }
+
+ wc_stripe_payment_request.attachPaymentRequestButtonEventListeners( prButton, paymentRequest );
+ wc_stripe_payment_request.showPaymentRequestButton( prButton );
+ } );
+
+ // Possible statuses success, fail, invalid_payer_name, invalid_payer_email, invalid_payer_phone, invalid_shipping_address.
+ paymentRequest.on( 'shippingaddresschange', function( evt ) {
+ $.when( wc_stripe_payment_request.updateShippingOptions( paymentDetails, evt.shippingAddress ) ).then( function( response ) {
+ evt.updateWith( { status: response.result, shippingOptions: response.shipping_options, total: response.total, displayItems: response.displayItems } );
+ } );
+ } );
+
+ paymentRequest.on( 'shippingoptionchange', function( evt ) {
+ $.when( wc_stripe_payment_request.updateShippingDetails( paymentDetails, evt.shippingOption ) ).then( function( response ) {
+ if ( 'success' === response.result ) {
+ evt.updateWith( { status: 'success', total: response.total, displayItems: response.displayItems } );
+ }
+
+ if ( 'fail' === response.result ) {
+ evt.updateWith( { status: 'fail' } );
+ }
+ } );
+ } );
+
+ paymentRequest.on( 'source', function( evt ) {
+ // Check if we allow prepaid cards.
+ if ( 'no' === wc_stripe_payment_request_params.stripe.allow_prepaid_card && 'prepaid' === evt.source.card.funding ) {
+ wc_stripe_payment_request.abortPayment( evt, wc_stripe_payment_request.getErrorMessageHTML( wc_stripe_payment_request_params.i18n.no_prepaid_card ) );
+ } else {
+ $.when( wc_stripe_payment_request.processSource( evt, paymentRequestType ) ).then( function( response ) {
+ if ( 'success' === response.result ) {
+ wc_stripe_payment_request.completePayment( evt, response.redirect );
+ } else {
+ wc_stripe_payment_request.abortPayment( evt, response.messages );
+ }
+ } );
+ }
+ } );
+ } catch( e ) {
+ // Leave for troubleshooting
+ console.error( e );
+ }
+ },
+
+ getSelectedProductData: function() {
+ var product_id = $( '.single_add_to_cart_button' ).val();
+
+ // Check if product is a variable product.
+ if ( $( '.single_variation_wrap' ).length ) {
+ product_id = $( '.single_variation_wrap' ).find( 'input[name="product_id"]' ).val();
+ }
+
+ var addons = $( '#product-addons-total' ).data('price_data') || [];
+ var addon_value = addons.reduce( function ( sum, addon ) { return sum + addon.cost; }, 0 );
+
+ var data = {
+ security: wc_stripe_payment_request_params.nonce.get_selected_product_data,
+ product_id: product_id,
+ qty: $( '.quantity .qty' ).val(),
+ attributes: $( '.variations_form' ).length ? wc_stripe_payment_request.getAttributes().data : [],
+ addon_value: addon_value,
+ };
+
+ return $.ajax( {
+ type: 'POST',
+ data: data,
+ url: wc_stripe_payment_request.getAjaxURL( 'get_selected_product_data' )
+ } );
+ },
+
+ /**
+ * Creates a wrapper around a function that ensures a function can not
+ * called in rappid succesion. The function can only be executed once and then agin after
+ * the wait time has expired. Even if the wrapper is called multiple times, the wrapped
+ * function only excecutes once and then blocks until the wait time expires.
+ *
+ * @param {int} wait Milliseconds wait for the next time a function can be executed.
+ * @param {function} func The function to be wrapped.
+ * @param {bool} immediate Overriding the wait time, will force the function to fire everytime.
+ *
+ * @return {function} A wrapped function with execution limited by the wait time.
+ */
+ debounce: function( wait, func, immediate ) {
+ var timeout;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) func.apply(context, args);
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) func.apply(context, args);
+ };
+ },
+
+ /**
+ * Creates stripe paymentRequest element or connects to custom button
+ *
+ * @param {object} elements Stripe elements instance.
+ * @param {object} paymentRequest Stripe paymentRequest object.
+ *
+ * @return {object} Stripe paymentRequest element or custom button jQuery element.
+ */
+ createPaymentRequestButton: function( elements, paymentRequest ) {
+ var button;
+ if ( wc_stripe_payment_request_params.button.is_custom ) {
+ button = $( wc_stripe_payment_request_params.button.css_selector );
+ if ( button.length ) {
+ // We fallback to default paymentRequest button if no custom button is found in the UI.
+ // Add flag to be sure that created button is custom button rather than fallback element.
+ button.data( 'isCustom', true );
+ return button;
+ }
+ }
+
+ if ( wc_stripe_payment_request_params.button.is_branded ) {
+ if ( wc_stripe_payment_request.shouldUseGooglePayBrand() ) {
+ button = wc_stripe_payment_request.createGooglePayButton();
+ // Add flag to be sure that created button is branded rather than fallback element.
+ button.data( 'isBranded', true );
+ return button;
+ } else {
+ // Not implemented branded buttons default to Stripe's button
+ // Apple Pay buttons can also fall back to Stripe's button, as it's already branded
+ // Set button type to default or buy, depending on branded type, to avoid issues with Stripe
+ wc_stripe_payment_request_params.button.type = 'long' === wc_stripe_payment_request_params.button.branded_type ? 'buy' : 'default';
+ }
+ }
+
+ return elements.create( 'paymentRequestButton', {
+ paymentRequest: paymentRequest,
+ style: {
+ paymentRequestButton: {
+ type: wc_stripe_payment_request_params.button.type,
+ theme: wc_stripe_payment_request_params.button.theme,
+ height: wc_stripe_payment_request_params.button.height + 'px',
+ },
+ },
+ } );
+ },
+
+ /**
+ * Checks if button is custom payment request button.
+ *
+ * @param {object} prButton Stripe paymentRequest element or custom jQuery element.
+ *
+ * @return {boolean} True when prButton is custom button jQuery element.
+ */
+ isCustomPaymentRequestButton: function ( prButton ) {
+ return prButton && 'function' === typeof prButton.data && prButton.data( 'isCustom' );
+ },
+
+ isBrandedPaymentRequestButton: function ( prButton ) {
+ return prButton && 'function' === typeof prButton.data && prButton.data( 'isBranded' );
+ },
+
+ shouldUseGooglePayBrand: function () {
+ var ua = window.navigator.userAgent.toLowerCase();
+ var isChrome = /chrome/.test( ua ) && ! /edge|edg|opr|brave\//.test( ua ) && 'Google Inc.' === window.navigator.vendor;
+ // newer versions of Brave do not have the userAgent string
+ var isBrave = isChrome && window.navigator.brave;
+ return isChrome && ! isBrave;
+ },
+
+ createGooglePayButton: function () {
+ var allowedThemes = [ 'dark', 'light', 'light-outline' ];
+ var allowedTypes = [ 'short', 'long' ];
+
+ var theme = wc_stripe_payment_request_params.button.theme;
+ var type = wc_stripe_payment_request_params.button.branded_type;
+ var locale = wc_stripe_payment_request_params.button.locale;
+ var height = wc_stripe_payment_request_params.button.height;
+ theme = allowedThemes.includes( theme ) ? theme : 'light';
+ var gpaySvgTheme = 'dark' === theme ? 'dark' : 'light';
+ type = allowedTypes.includes( type ) ? type : 'long';
+
+ var button = $( '<button type="button" id="wc-stripe-branded-button" aria-label="Google Pay" class="gpay-button"></button>' );
+ button.css( 'height', height + 'px' );
+ button.addClass( theme + ' ' + type );
+ if ( 'long' === type ) {
+ var url = 'https://www.gstatic.com/instantbuy/svg/' + gpaySvgTheme + '/' + locale + '.svg';
+ var fallbackUrl = 'https://www.gstatic.com/instantbuy/svg/' + gpaySvgTheme + '/en.svg';
+ // Check if locale GPay button exists, default to en if not
+ setBackgroundImageWithFallback( button, url, fallbackUrl );
+ }
+
+ return button;
+ },
+
+ attachPaymentRequestButtonEventListeners: function( prButton, paymentRequest ) {
+ // First, mark the body so we know a payment request button was used.
+ // This way error handling can any display errors in the most appropriate place.
+ prButton.on( 'click', function ( evt ) {
+ $( 'body' ).addClass( 'woocommerce-stripe-prb-clicked' );
+ });
+
+ // Then, attach specific handling for selected pages and button types
+ if ( wc_stripe_payment_request_params.is_product_page ) {
+ wc_stripe_payment_request.attachProductPageEventListeners( prButton, paymentRequest );
+ } else {
+ wc_stripe_payment_request.attachCartPageEventListeners( prButton, paymentRequest );
+ }
+ },
+
+ attachProductPageEventListeners: function( prButton, paymentRequest ) {
+ var paymentRequestError = [];
+ var addToCartButton = $( '.single_add_to_cart_button' );
+
+ prButton.on( 'click', function ( evt ) {
+ // If login is required for checkout, display redirect confirmation dialog.
+ if ( wc_stripe_payment_request_params.login_confirmation ) {
+ evt.preventDefault();
+ displayLoginConfirmation( paymentRequestType );
+ return;
+ }
+
+ // First check if product can be added to cart.
+ if ( addToCartButton.is( '.disabled' ) ) {
+ evt.preventDefault(); // Prevent showing payment request modal.
+ if ( addToCartButton.is( '.wc-variation-is-unavailable' ) ) {
+ window.alert( wc_add_to_cart_variation_params.i18n_unavailable_text );
+ } else if ( addToCartButton.is( '.wc-variation-selection-needed' ) ) {
+ window.alert( wc_add_to_cart_variation_params.i18n_make_a_selection_text );
+ }
+ return;
+ }
+
+ if ( 0 < paymentRequestError.length ) {
+ evt.preventDefault();
+ window.alert( paymentRequestError );
+ return;
+ }
+
+ wc_stripe_payment_request.addToCart();
+
+ if ( wc_stripe_payment_request.isCustomPaymentRequestButton( prButton ) || wc_stripe_payment_request.isBrandedPaymentRequestButton( prButton ) ) {
+ evt.preventDefault();
+ paymentRequest.show();
+ }
+ });
+
+ $( document.body ).on( 'wc_stripe_unblock_payment_request_button wc_stripe_enable_payment_request_button', function () {
+ wc_stripe_payment_request.unblockPaymentRequestButton();
+ } );
+
+ $( document.body ).on( 'wc_stripe_block_payment_request_button', function () {
+ wc_stripe_payment_request.blockPaymentRequestButton( 'wc_request_button_is_blocked' );
+ } );
+
+ $( document.body ).on( 'wc_stripe_disable_payment_request_button', function () {
+ wc_stripe_payment_request.blockPaymentRequestButton( 'wc_request_button_is_disabled' );
+ } );
+
+ $( document.body ).on( 'woocommerce_variation_has_changed', function () {
+ $( document.body ).trigger( 'wc_stripe_block_payment_request_button' );
+
+ $.when( wc_stripe_payment_request.getSelectedProductData() ).then( function ( response ) {
+ $.when(
+ paymentRequest.update( {
+ total: response.total,
+ displayItems: response.displayItems,
+ } )
+ ).then( function () {
+ $( document.body ).trigger( 'wc_stripe_unblock_payment_request_button' );
+ } );
+ });
+ } );
+
+ // Block the payment request button as soon as an "input" event is fired, to avoid sync issues
+ // when the customer clicks on the button before the debounced event is processed.
+ $( '.quantity' ).on( 'input', '.qty', function() {
+ $( document.body ).trigger( 'wc_stripe_block_payment_request_button' );
+ } );
+
+ $( '.quantity' ).on( 'input', '.qty', wc_stripe_payment_request.debounce( 250, function() {
+ $( document.body ).trigger( 'wc_stripe_block_payment_request_button' );
+ paymentRequestError = [];
+
+ $.when( wc_stripe_payment_request.getSelectedProductData() ).then( function ( response ) {
+ if ( response.error ) {
+ paymentRequestError = [ response.error ];
+ $( document.body ).trigger( 'wc_stripe_unblock_payment_request_button' );
+ } else {
+ $.when(
+ paymentRequest.update( {
+ total: response.total,
+ displayItems: response.displayItems,
+ } )
+ ).then( function () {
+ $( document.body ).trigger( 'wc_stripe_unblock_payment_request_button' );
+ });
+ }
+ } );
+ }));
+
+ if ( $('.variations_form').length ) {
+ $( '.variations_form' ).on( 'found_variation.wc-variation-form', function ( evt, variation ) {
+ if ( variation.is_in_stock ) {
+ wc_stripe_payment_request.unhidePaymentRequestButton();
+ } else {
+ wc_stripe_payment_request.hidePaymentRequestButton();
+ }
+ } );
+ }
+ },
+
+ attachCartPageEventListeners: function ( prButton, paymentRequest ) {
+ prButton.on( 'click', function ( evt ) {
+ // If login is required for checkout, display redirect confirmation dialog.
+ if ( wc_stripe_payment_request_params.login_confirmation ) {
+ evt.preventDefault();
+ displayLoginConfirmation( paymentRequestType );
+ return;
+ }
+
+ if (
+ wc_stripe_payment_request.isCustomPaymentRequestButton(
+ prButton
+ ) ||
+ wc_stripe_payment_request.isBrandedPaymentRequestButton(
+ prButton
+ )
+ ) {
+ evt.preventDefault();
+ paymentRequest.show();
+ }
+ } );
+ },
+
+ showPaymentRequestButton: function( prButton ) {
+ if ( wc_stripe_payment_request.isCustomPaymentRequestButton( prButton ) ) {
+ prButton.addClass( 'is-active' );
+ $( '#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator' ).show();
+ } else if ( wc_stripe_payment_request.isBrandedPaymentRequestButton( prButton ) ) {
+ $( '#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator' ).show();
+ $( '#wc-stripe-payment-request-button' ).html( prButton );
+ } else if ( $( '#wc-stripe-payment-request-button' ).length ) {
+ $( '#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator' ).show();
+ prButton.mount( '#wc-stripe-payment-request-button' );
+ }
+ },
+
+ hidePaymentRequestButton: function () {
+ $( '#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator' ).hide();
+ },
+
+ unhidePaymentRequestButton: function () {
+ const stripe_wrapper = $( '#wc-stripe-payment-request-wrapper' );
+ const stripe_separator = $( '#wc-stripe-payment-request-button-separator' );
+ // If either element is hidden, ensure both show.
+ if ( stripe_wrapper.is(':hidden') || stripe_separator.is(':hidden') ) {
+ stripe_wrapper.show();
+ stripe_separator.show();
+ }
+ },
+
+ blockPaymentRequestButton: function( cssClassname ) {
+ // check if element isn't already blocked before calling block() to avoid blinking overlay issues
+ // blockUI.isBlocked is either undefined or 0 when element is not blocked
+ if ( $( '#wc-stripe-payment-request-button' ).data( 'blockUI.isBlocked' ) ) {
+ return;
+ }
+
+ $( '#wc-stripe-payment-request-button' )
+ .addClass( cssClassname )
+ .block( { message: null } );
+ },
+
+ unblockPaymentRequestButton: function() {
+ $( '#wc-stripe-payment-request-button' )
+ .removeClass( ['wc_request_button_is_blocked', 'wc_request_button_is_disabled'] )
+ .unblock();
+ },
+
+ /**
+ * Initialize event handlers and UI state
+ *
+ * @since 4.0.0
+ * @version 4.0.0
+ */
+ init: function() {
+ if ( wc_stripe_payment_request_params.is_product_page ) {
+ wc_stripe_payment_request.startPaymentRequest( '' );
+ } else {
+ wc_stripe_payment_request.getCartDetails();
+ }
+
+ },
+ };
+
+ wc_stripe_payment_request.init();
+
+ // We need to refresh payment request data when total is updated.
+ $( document.body ).on( 'updated_cart_totals', function() {
+ wc_stripe_payment_request.init();
+ } );
+
+ // We need to refresh payment request data when total is updated.
+ $( document.body ).on( 'updated_checkout', function() {
+ wc_stripe_payment_request.init();
+ } );
+
+ function setBackgroundImageWithFallback( element, background, fallback ) {
+ element.css( 'background-image', 'url(' + background + ')' );
+ // Need to use an img element to avoid CORS issues
+ var testImg = document.createElement("img");
+ testImg.onerror = function () {
+ element.css( 'background-image', 'url(' + fallback + ')' );
+ }
+ testImg.src = background;
+ }
+
+ // TODO: Replace this by `client/blocks/payment-request/login-confirmation.js`
+ // when we start using webpack to build this file.
+ function displayLoginConfirmation( paymentRequestType ) {
+ if ( ! wc_stripe_payment_request_params.login_confirmation ) {
+ return;
+ }
+
+ var message = wc_stripe_payment_request_params.login_confirmation.message;
+
+ // Replace dialog text with specific payment request type "Apple Pay" or "Google Pay".
+ if ( 'payment_request_api' !== paymentRequestType ) {
+ message = message.replace(
+ /\*\*.*?\*\*/,
+ 'apple_pay' === paymentRequestType ? 'Apple Pay' : 'Google Pay'
+ );
+ }
+
+ // Remove asterisks from string.
+ message = message.replace( /\*\*/g, '' );
+
+ if ( confirm( message ) ) {
+ // Redirect to my account page.
+ window.location.href = wc_stripe_payment_request_params.login_confirmation.redirect_url;
+ }
+ }
+} );
diff --git a/assets/js/stripe-payment-request.min.js b/assets/js/stripe-payment-request.min.js
new file mode 100644
index 0000000..f11a3d8
--- /dev/null
+++ b/assets/js/stripe-payment-request.min.js
@@ -0,0 +1 @@
+jQuery(function(i){"use strict";var o,p=Stripe(wc_stripe_payment_request_params.stripe.key,{locale:wc_stripe_payment_request_params.stripe.locale}),u={getAjaxURL:function(t){return wc_stripe_payment_request_params.ajax_url.toString().replace("%%endpoint%%","wc_stripe_"+t)},getCartDetails:function(){var t={security:wc_stripe_payment_request_params.nonce.payment};i.ajax({type:"POST",data:t,url:u.getAjaxURL("get_cart_details"),success:function(t){u.startPaymentRequest(t)}})},getAttributes:function(){var t=i(".variations_form").find(".variations select"),n={},a=0,r=0;return t.each(function(){var t=i(this).data("attribute_name")||i(this).attr("name"),e=i(this).val()||"";0<e.length&&r++,a++,n[t]=e}),{count:a,chosenCount:r,data:n}},processSource:function(t,e){e=u.getOrderData(t,e);return i.ajax({type:"POST",data:e,dataType:"json",url:u.getAjaxURL("create_order")})},getOrderData:function(t,e){var n=t.source,a=n.owner.email,r=n.owner.phone,s=n.owner.address,i=n.owner.name,o=t.shippingAddress,e={_wpnonce:wc_stripe_payment_request_params.nonce.checkout,billing_first_name:null!==i?i.split(" ").slice(0,1).join(" "):"",billing_last_name:null!==i?i.split(" ").slice(1).join(" "):"",billing_company:"",billing_email:null!==a?a:t.payerEmail,billing_phone:null!==r?r:t.payerPhone&&t.payerPhone.replace("/[() -]/g",""),billing_country:null!==s?s.country:"",billing_address_1:null!==s?s.line1:"",billing_address_2:null!==s?s.line2:"",billing_city:null!==s?s.city:"",billing_state:null!==s?s.state:"",billing_postcode:null!==s?s.postal_code:"",shipping_first_name:"",shipping_last_name:"",shipping_company:"",shipping_country:"",shipping_address_1:"",shipping_address_2:"",shipping_city:"",shipping_state:"",shipping_postcode:"",shipping_method:[null===t.shippingOption?null:t.shippingOption.id],order_comments:"",payment_method:"stripe",ship_to_different_address:1,terms:1,stripe_source:n.id,payment_request_type:e};return o&&(e.shipping_first_name=o.recipient.split(" ").slice(0,1).join(" "),e.shipping_last_name=o.recipient.split(" ").slice(1).join(" "),e.shipping_company=o.organization,e.shipping_country=o.country,e.shipping_address_1=void 0===o.addressLine[0]?"":o.addressLine[0],e.shipping_address_2=void 0===o.addressLine[1]?"":o.addressLine[1],e.shipping_city=o.city,e.shipping_state=o.region,e.shipping_postcode=o.postalCode),e},getErrorMessageHTML:function(t){return i('<div class="woocommerce-error" />').text(t)},displayErrorMessage:function(t){var e;i(".woocommerce-error").remove(),wc_stripe_payment_request_params.is_product_page?((e=i(".product").first()).before(t),i("html, body").animate({scrollTop:e.prev(".woocommerce-error").offset().top},600)):((e=i(".shop_table.cart").closest("form")).before(t),i("html, body").animate({scrollTop:e.prev(".woocommerce-error").offset().top},600))},abortPayment:function(t,e){t.complete("fail"),u.displayErrorMessage(e)},completePayment:function(t,e){u.block(),t.complete("success"),window.location=e},block:function(){i.blockUI({message:null,overlayCSS:{background:"#fff",opacity:.6}})},updateShippingOptions:function(t,e){e={security:wc_stripe_payment_request_params.nonce.shipping,country:e.country,state:e.region,postcode:e.postalCode,city:e.city,address:void 0===e.addressLine[0]?"":e.addressLine[0],address_2:void 0===e.addressLine[1]?"":e.addressLine[1],payment_request_type:o,is_product_page:wc_stripe_payment_request_params.is_product_page};return i.ajax({type:"POST",data:e,url:u.getAjaxURL("get_shipping_options")})},updateShippingDetails:function(t,e){e={security:wc_stripe_payment_request_params.nonce.update_shipping,shipping_method:[e.id],payment_request_type:o,is_product_page:wc_stripe_payment_request_params.is_product_page};return i.ajax({type:"POST",data:e,url:u.getAjaxURL("update_shipping_method")})},addToCart:function(){var t=i(".single_add_to_cart_button").val();i(".single_variation_wrap").length&&(t=i(".single_variation_wrap").find('input[name="product_id"]').val());var a={security:wc_stripe_payment_request_params.nonce.add_to_cart,product_id:t,qty:i(".quantity .qty").val(),attributes:i(".variations_form").length?u.getAttributes().data:[]},t=i("form.cart").serializeArray();return i.each(t,function(t,e){var n;/^addon-/.test(e.name)&&(/\[\]$/.test(e.name)?(n=e.name.substring(0,e.name.length-2),a[n]?a[n].push(e.value):a[n]=[e.value]):a[e.name]=e.value)}),i.ajax({type:"POST",data:a,url:u.getAjaxURL("add_to_cart")})},clearCart:function(){var t={security:wc_stripe_payment_request_params.nonce.clear_cart};return i.ajax({type:"POST",data:t,url:u.getAjaxURL("clear_cart"),success:function(t){}})},getRequestOptionsFromLocal:function(){return{total:wc_stripe_payment_request_params.product.total,currency:wc_stripe_payment_request_params.checkout.currency_code,country:wc_stripe_payment_request_params.checkout.country_code,requestPayerName:!0,requestPayerEmail:!0,requestPayerPhone:wc_stripe_payment_request_params.checkout.needs_payer_phone,requestShipping:wc_stripe_payment_request_params.product.requestShipping,displayItems:wc_stripe_payment_request_params.product.displayItems}},startPaymentRequest:function(t){var e,n=wc_stripe_payment_request_params.is_product_page?e=u.getRequestOptionsFromLocal():(e={total:t.order_data.total,currency:t.order_data.currency,country:t.order_data.country_code,requestPayerName:!0,requestPayerEmail:!0,requestPayerPhone:wc_stripe_payment_request_params.checkout.needs_payer_phone,requestShipping:!!t.shipping_required,displayItems:t.order_data.displayItems},t.order_data);"PR"===e.country&&(e.country="US");try{var a=p.paymentRequest(e),r=p.elements({locale:wc_stripe_payment_request_params.button.locale}),s=u.createPaymentRequestButton(r,a);a.canMakePayment().then(function(t){t&&(o=t.applePay?"apple_pay":t.googlePay?"google_pay":"payment_request_api",u.attachPaymentRequestButtonEventListeners(s,a),u.showPaymentRequestButton(s))}),a.on("shippingaddresschange",function(e){i.when(u.updateShippingOptions(n,e.shippingAddress)).then(function(t){e.updateWith({status:t.result,shippingOptions:t.shipping_options,total:t.total,displayItems:t.displayItems})})}),a.on("shippingoptionchange",function(e){i.when(u.updateShippingDetails(n,e.shippingOption)).then(function(t){"success"===t.result&&e.updateWith({status:"success",total:t.total,displayItems:t.displayItems}),"fail"===t.result&&e.updateWith({status:"fail"})})}),a.on("source",function(e){"no"===wc_stripe_payment_request_params.stripe.allow_prepaid_card&&"prepaid"===e.source.card.funding?u.abortPayment(e,u.getErrorMessageHTML(wc_stripe_payment_request_params.i18n.no_prepaid_card)):i.when(u.processSource(e,o)).then(function(t){"success"===t.result?u.completePayment(e,t.redirect):u.abortPayment(e,t.messages)})})}catch(t){console.error(t)}},getSelectedProductData:function(){var t=i(".single_add_to_cart_button").val();i(".single_variation_wrap").length&&(t=i(".single_variation_wrap").find('input[name="product_id"]').val());var e=(i("#product-addons-total").data("price_data")||[]).reduce(function(t,e){return t+e.cost},0),e={security:wc_stripe_payment_request_params.nonce.get_selected_product_data,product_id:t,qty:i(".quantity .qty").val(),attributes:i(".variations_form").length?u.getAttributes().data:[],addon_value:e};return i.ajax({type:"POST",data:e,url:u.getAjaxURL("get_selected_product_data")})},debounce:function(a,r,s){var i;return function(){var t=this,e=arguments,n=s&&!i;clearTimeout(i),i=setTimeout(function(){i=null,s||r.apply(t,e)},a),n&&r.apply(t,e)}},createPaymentRequestButton:function(t,e){var n;if(wc_stripe_payment_request_params.button.is_custom&&(n=i(wc_stripe_payment_request_params.button.css_selector)).length)return n.data("isCustom",!0),n;if(wc_stripe_payment_request_params.button.is_branded){if(u.shouldUseGooglePayBrand())return(n=u.createGooglePayButton()).data("isBranded",!0),n;wc_stripe_payment_request_params.button.type="long"===wc_stripe_payment_request_params.button.branded_type?"buy":"default"}return t.create("paymentRequestButton",{paymentRequest:e,style:{paymentRequestButton:{type:wc_stripe_payment_request_params.button.type,theme:wc_stripe_payment_request_params.button.theme,height:wc_stripe_payment_request_params.button.height+"px"}}})},isCustomPaymentRequestButton:function(t){return t&&"function"==typeof t.data&&t.data("isCustom")},isBrandedPaymentRequestButton:function(t){return t&&"function"==typeof t.data&&t.data("isBranded")},shouldUseGooglePayBrand:function(){var t=window.navigator.userAgent.toLowerCase(),e=/chrome/.test(t)&&!/edge|edg|opr|brave\//.test(t)&&"Google Inc."===window.navigator.vendor,t=e&&window.navigator.brave;return e&&!t},createGooglePayButton:function(){var t=wc_stripe_payment_request_params.button.theme,e=wc_stripe_payment_request_params.button.branded_type,n=wc_stripe_payment_request_params.button.locale,a=wc_stripe_payment_request_params.button.height,r="dark"===(t=["dark","light","light-outline"].includes(t)?t:"light")?"dark":"light",e=["short","long"].includes(e)?e:"long",s=i('<button type="button" id="wc-stripe-branded-button" aria-label="Google Pay" class="gpay-button"></button>');return s.css("height",a+"px"),s.addClass(t+" "+e),"long"===e&&function(t,e,n){t.css("background-image","url("+e+")");var a=document.createElement("img");a.onerror=function(){t.css("background-image","url("+n+")")},a.src=e}(s,"https://www.gstatic.com/instantbuy/svg/"+r+"/"+n+".svg","https://www.gstatic.com/instantbuy/svg/"+r+"/en.svg"),s},attachPaymentRequestButtonEventListeners:function(t,e){t.on("click",function(t){i("body").addClass("woocommerce-stripe-prb-clicked")}),wc_stripe_payment_request_params.is_product_page?u.attachProductPageEventListeners(t,e):u.attachCartPageEventListeners(t,e)},attachProductPageEventListeners:function(e,n){var a=[],r=i(".single_add_to_cart_button");e.on("click",function(t){return wc_stripe_payment_request_params.login_confirmation?(t.preventDefault(),void s(o)):r.is(".disabled")?(t.preventDefault(),void(r.is(".wc-variation-is-unavailable")?window.alert(wc_add_to_cart_variation_params.i18n_unavailable_text):r.is(".wc-variation-selection-needed")&&window.alert(wc_add_to_cart_variation_params.i18n_make_a_selection_text))):0<a.length?(t.preventDefault(),void window.alert(a)):(u.addToCart(),void((u.isCustomPaymentRequestButton(e)||u.isBrandedPaymentRequestButton(e))&&(t.preventDefault(),n.show())))}),i(document.body).on("wc_stripe_unblock_payment_request_button wc_stripe_enable_payment_request_button",function(){u.unblockPaymentRequestButton()}),i(document.body).on("wc_stripe_block_payment_request_button",function(){u.blockPaymentRequestButton("wc_request_button_is_blocked")}),i(document.body).on("wc_stripe_disable_payment_request_button",function(){u.blockPaymentRequestButton("wc_request_button_is_disabled")}),i(document.body).on("woocommerce_variation_has_changed",function(){i(document.body).trigger("wc_stripe_block_payment_request_button"),i.when(u.getSelectedProductData()).then(function(t){i.when(n.update({total:t.total,displayItems:t.displayItems})).then(function(){i(document.body).trigger("wc_stripe_unblock_payment_request_button")})})}),i(".quantity").on("input",".qty",function(){i(document.body).trigger("wc_stripe_block_payment_request_button")}),i(".quantity").on("input",".qty",u.debounce(250,function(){i(document.body).trigger("wc_stripe_block_payment_request_button"),a=[],i.when(u.getSelectedProductData()).then(function(t){t.error?(a=[t.error],i(document.body).trigger("wc_stripe_unblock_payment_request_button")):i.when(n.update({total:t.total,displayItems:t.displayItems})).then(function(){i(document.body).trigger("wc_stripe_unblock_payment_request_button")})})})),i(".variations_form").length&&i(".variations_form").on("found_variation.wc-variation-form",function(t,e){e.is_in_stock?u.unhidePaymentRequestButton():u.hidePaymentRequestButton()})},attachCartPageEventListeners:function(e,n){e.on("click",function(t){return wc_stripe_payment_request_params.login_confirmation?(t.preventDefault(),void s(o)):void((u.isCustomPaymentRequestButton(e)||u.isBrandedPaymentRequestButton(e))&&(t.preventDefault(),n.show()))})},showPaymentRequestButton:function(t){u.isCustomPaymentRequestButton(t)?(t.addClass("is-active"),i("#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator").show()):u.isBrandedPaymentRequestButton(t)?(i("#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator").show(),i("#wc-stripe-payment-request-button").html(t)):i("#wc-stripe-payment-request-button").length&&(i("#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator").show(),t.mount("#wc-stripe-payment-request-button"))},hidePaymentRequestButton:function(){i("#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator").hide()},unhidePaymentRequestButton:function(){const t=i("#wc-stripe-payment-request-wrapper"),e=i("#wc-stripe-payment-request-button-separator");(t.is(":hidden")||e.is(":hidden"))&&(t.show(),e.show())},blockPaymentRequestButton:function(t){i("#wc-stripe-payment-request-button").data("blockUI.isBlocked")||i("#wc-stripe-payment-request-button").addClass(t).block({message:null})},unblockPaymentRequestButton:function(){i("#wc-stripe-payment-request-button").removeClass(["wc_request_button_is_blocked","wc_request_button_is_disabled"]).unblock()},init:function(){wc_stripe_payment_request_params.is_product_page?u.startPaymentRequest(""):u.getCartDetails()}};function s(t){var e;wc_stripe_payment_request_params.login_confirmation&&(e=wc_stripe_payment_request_params.login_confirmation.message,e=(e="payment_request_api"!==t?e.replace(/\*\*.*?\*\*/,"apple_pay"===t?"Apple Pay":"Google Pay"):e).replace(/\*\*/g,""),confirm(e)&&(window.location.href=wc_stripe_payment_request_params.login_confirmation.redirect_url))}u.init(),i(document.body).on("updated_cart_totals",function(){u.init()}),i(document.body).on("updated_checkout",function(){u.init()})});
diff --git a/assets/js/stripe.js b/assets/js/stripe.js
new file mode 100644
index 0000000..f055320
--- /dev/null
+++ b/assets/js/stripe.js
@@ -0,0 +1,1041 @@
+/* global wc_stripe_params */
+
+jQuery( function( $ ) {
+ 'use strict';
+
+ try {
+ var stripe = Stripe( wc_stripe_params.key, {
+ locale: wc_stripe_params.stripe_locale || 'auto',
+ } );
+ } catch( error ) {
+ console.log( error );
+ return;
+ }
+
+ var stripe_elements_options = Object.keys( wc_stripe_params.elements_options ).length ? wc_stripe_params.elements_options : {},
+ sepa_elements_options = Object.keys( wc_stripe_params.sepa_elements_options ).length ? wc_stripe_params.sepa_elements_options : {},
+ elements = stripe.elements( stripe_elements_options ),
+ iban = elements.create( 'iban', sepa_elements_options ),
+ stripe_card,
+ stripe_exp,
+ stripe_cvc;
+
+ /**
+ * Object to handle Stripe elements payment form.
+ */
+ var wc_stripe_form = {
+ /**
+ * Get WC AJAX endpoint URL.
+ *
+ * @param {String} endpoint Endpoint.
+ * @return {String}
+ */
+ getAjaxURL: function( endpoint ) {
+ return wc_stripe_params.ajaxurl
+ .toString()
+ .replace( '%%endpoint%%', 'wc_stripe_' + endpoint );
+ },
+
+ /**
+ * Unmounts all Stripe elements when the checkout page is being updated.
+ */
+ unmountElements: function() {
+ if ( 'yes' === wc_stripe_params.inline_cc_form ) {
+ stripe_card.unmount( '#stripe-card-element' );
+ } else {
+ stripe_card.unmount( '#stripe-card-element' );
+ stripe_exp.unmount( '#stripe-exp-element' );
+ stripe_cvc.unmount( '#stripe-cvc-element' );
+ }
+ },
+
+ /**
+ * Mounts all elements to their DOM nodes on initial loads and updates.
+ */
+ mountElements: function() {
+ if ( ! $( '#stripe-card-element' ).length ) {
+ return;
+ }
+
+ if ( 'yes' === wc_stripe_params.inline_cc_form ) {
+ stripe_card.mount( '#stripe-card-element' );
+ return;
+ }
+
+ stripe_card.mount( '#stripe-card-element' );
+ stripe_exp.mount( '#stripe-exp-element' );
+ stripe_cvc.mount( '#stripe-cvc-element' );
+ },
+
+ /**
+ * Creates all Stripe elements that will be used to enter cards or IBANs.
+ */
+ createElements: function() {
+ var elementStyles = {
+ base: {
+ iconColor: '#666EE8',
+ color: '#31325F',
+ fontSize: '15px',
+ '::placeholder': {
+ color: '#CFD7E0',
+ }
+ }
+ };
+
+ var elementClasses = {
+ focus: 'focused',
+ empty: 'empty',
+ invalid: 'invalid',
+ };
+
+ elementStyles = wc_stripe_params.elements_styling ? wc_stripe_params.elements_styling : elementStyles;
+ elementClasses = wc_stripe_params.elements_classes ? wc_stripe_params.elements_classes : elementClasses;
+
+ if ( 'yes' === wc_stripe_params.inline_cc_form ) {
+ stripe_card = elements.create( 'card', { style: elementStyles, hidePostalCode: true } );
+
+ stripe_card.addEventListener( 'change', function( event ) {
+ wc_stripe_form.onCCFormChange();
+
+ if ( event.error ) {
+ $( document.body ).trigger( 'stripeError', event );
+ }
+ } );
+ } else {
+ stripe_card = elements.create( 'cardNumber', { style: elementStyles, classes: elementClasses } );
+ stripe_exp = elements.create( 'cardExpiry', { style: elementStyles, classes: elementClasses } );
+ stripe_cvc = elements.create( 'cardCvc', { style: elementStyles, classes: elementClasses } );
+
+ stripe_card.addEventListener( 'change', function( event ) {
+ wc_stripe_form.onCCFormChange();
+
+ wc_stripe_form.updateCardBrand( event.brand );
+
+ if ( event.error ) {
+ $( document.body ).trigger( 'stripeError', event );
+ }
+ } );
+
+ stripe_exp.addEventListener( 'change', function( event ) {
+ wc_stripe_form.onCCFormChange();
+
+ if ( event.error ) {
+ $( document.body ).trigger( 'stripeError', event );
+ }
+ } );
+
+ stripe_cvc.addEventListener( 'change', function( event ) {
+ wc_stripe_form.onCCFormChange();
+
+ if ( event.error ) {
+ $( document.body ).trigger( 'stripeError', event );
+ }
+ } );
+ }
+
+ /**
+ * Only in checkout page we need to delay the mounting of the
+ * card as some AJAX process needs to happen before we do.
+ */
+ if ( 'yes' === wc_stripe_params.is_checkout ) {
+ $( document.body ).on( 'updated_checkout', function() {
+ // Don't re-mount if already mounted in DOM.
+ if ( $( '#stripe-card-element' ).children().length ) {
+ return;
+ }
+
+ // Unmount prior to re-mounting.
+ if ( stripe_card ) {
+ wc_stripe_form.unmountElements();
+ }
+
+ wc_stripe_form.mountElements();
+
+ if ( $( '#stripe-iban-element' ).length ) {
+ iban.mount( '#stripe-iban-element' );
+ }
+ } );
+ } else if ( $( 'form#add_payment_method' ).length || $( 'form#order_review' ).length ) {
+ wc_stripe_form.mountElements();
+
+ if ( $( '#stripe-iban-element' ).length ) {
+ iban.mount( '#stripe-iban-element' );
+ }
+ }
+ },
+
+ /**
+ * Updates the card brand logo with non-inline CC forms.
+ *
+ * @param {string} brand The identifier of the chosen brand.
+ */
+ updateCardBrand: function( brand ) {
+ var brandClass = {
+ 'visa': 'stripe-visa-brand',
+ 'mastercard': 'stripe-mastercard-brand',
+ 'amex': 'stripe-amex-brand',
+ 'discover': 'stripe-discover-brand',
+ 'diners': 'stripe-diners-brand',
+ 'jcb': 'stripe-jcb-brand',
+ 'unknown': 'stripe-credit-card-brand'
+ };
+
+ var imageElement = $( '.stripe-card-brand' ),
+ imageClass = 'stripe-credit-card-brand';
+
+ if ( brand in brandClass ) {
+ imageClass = brandClass[ brand ];
+ }
+
+ // Remove existing card brand class.
+ $.each( brandClass, function( index, el ) {
+ imageElement.removeClass( el );
+ } );
+
+ imageElement.addClass( imageClass );
+ },
+
+ /**
+ * Initialize event handlers and UI state.
+ */
+ init: function() {
+ // Initialize tokenization script if on change payment method page and pay for order page.
+ if ( 'yes' === wc_stripe_params.is_change_payment_page || 'yes' === wc_stripe_params.is_pay_for_order_page ) {
+ $( document.body ).trigger( 'wc-credit-card-form-init' );
+ }
+
+ // checkout page
+ if ( $( 'form.woocommerce-checkout' ).length ) {
+ this.form = $( 'form.woocommerce-checkout' );
+ }
+
+ $( 'form.woocommerce-checkout' )
+ .on(
+ 'checkout_place_order_stripe checkout_place_order_stripe_bancontact checkout_place_order_stripe_sofort checkout_place_order_stripe_giropay checkout_place_order_stripe_ideal checkout_place_order_stripe_alipay checkout_place_order_stripe_sepa checkout_place_order_stripe_boleto checkout_place_order_stripe_oxxo',
+ this.onSubmit
+ );
+
+ // pay order page
+ if ( $( 'form#order_review' ).length ) {
+ this.form = $( 'form#order_review' );
+ }
+
+ $( 'form#order_review, form#add_payment_method' )
+ .on(
+ 'submit',
+ this.onSubmit
+ );
+
+ // add payment method page
+ if ( $( 'form#add_payment_method' ).length ) {
+ this.form = $( 'form#add_payment_method' );
+ }
+
+ $( 'form.woocommerce-checkout' )
+ .on(
+ 'change',
+ this.reset
+ );
+
+ $( document )
+ .on(
+ 'stripeError',
+ this.onError
+ )
+ .on(
+ 'checkout_error',
+ this.reset
+ );
+
+ // SEPA IBAN.
+ iban.on( 'change',
+ this.onSepaError
+ );
+
+ // Subscription early renewals modal.
+ if ($('#early_renewal_modal_submit[data-payment-method]').length) {
+ $('#early_renewal_modal_submit[data-payment-method=stripe]').on('click', this.onEarlyRenewalSubmit);
+ } else {
+ $('#early_renewal_modal_submit').on('click', this.onEarlyRenewalSubmit);
+ }
+
+ wc_stripe_form.createElements();
+
+ // Listen for hash changes in order to handle payment intents
+ window.addEventListener( 'hashchange', wc_stripe_form.onHashChange );
+ wc_stripe_form.maybeConfirmIntent();
+
+ //Mask CPF/CNPJ field when using Boleto
+ $( document ).on( 'change', '.wc_payment_methods', function () {
+ if ( ! $( '#stripe_boleto_tax_id' ).length ) {
+ return;
+ }
+
+ var TaxIdMaskBehavior = function ( val ) {
+ return val.replace( /\D/g, '' ).length >= 12 ? '00.000.000/0000-00' : '000.000.000-009999';
+ },
+ spOptions = {
+ onKeyPress: function ( val, e, field, options ) {
+ field.mask( TaxIdMaskBehavior.apply( {}, arguments ), options );
+ }
+ };
+
+ $( '#stripe_boleto_tax_id' ).mask( TaxIdMaskBehavior, spOptions );
+ });
+ },
+
+ /**
+ * Check to see if Stripe in general is being used for checkout.
+ *
+ * @return {boolean}
+ */
+ isStripeChosen: function() {
+ return $( '#payment_method_stripe, #payment_method_stripe_bancontact, #payment_method_stripe_sofort, #payment_method_stripe_giropay, #payment_method_stripe_ideal, #payment_method_stripe_alipay, #payment_method_stripe_sepa, #payment_method_stripe_eps, #payment_method_stripe_multibanco, #payment_method_stripe_boleto, #payment_method_stripe_oxxo' ).is( ':checked' ) || ( $( '#payment_method_stripe' ).is( ':checked' ) && 'new' === $( 'input[name="wc-stripe-payment-token"]:checked' ).val() ) || ( $( '#payment_method_stripe_sepa' ).is( ':checked' ) && 'new' === $( 'input[name="wc-stripe-payment-token"]:checked' ).val() );
+ },
+
+ /**
+ * Currently only support saved cards via credit cards and SEPA. No other payment method.
+ *
+ * @return {boolean}
+ */
+ isStripeSaveCardChosen: function() {
+ return (
+ $( '#payment_method_stripe' ).is( ':checked' ) &&
+ $( 'input[name="wc-stripe-payment-token"]' ).is( ':checked' ) &&
+ 'new' !== $( 'input[name="wc-stripe-payment-token"]:checked' ).val()
+ ) || (
+ $( '#payment_method_stripe_sepa' ).is( ':checked' ) &&
+ $( 'input[name="wc-stripe_sepa-payment-token"]' ).is( ':checked' ) &&
+ 'new' !== $( 'input[name="wc-stripe_sepa-payment-token"]:checked' ).val()
+ );
+ },
+
+ /**
+ * Check if Stripe credit card is being used.
+ *
+ * @return {boolean}
+ */
+ isStripeCardChosen: function() {
+ return $( '#payment_method_stripe' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe Bancontact is being used.
+ *
+ * @return {boolean}
+ */
+ isBancontactChosen: function() {
+ return $( '#payment_method_stripe_bancontact' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe giropay is being used.
+ *
+ * @return {boolean}
+ */
+ isGiropayChosen: function() {
+ return $( '#payment_method_stripe_giropay' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe iDEAL is being used.
+ *
+ * @return {boolean}
+ */
+ isIdealChosen: function() {
+ return $( '#payment_method_stripe_ideal' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe Sofort is being used.
+ *
+ * @return {boolean}
+ */
+ isSofortChosen: function() {
+ return $( '#payment_method_stripe_sofort' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe Alipay is being used.
+ *
+ * @return {boolean}
+ */
+ isAlipayChosen: function() {
+ return $( '#payment_method_stripe_alipay' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe SEPA Direct Debit is being used.
+ *
+ * @return {boolean}
+ */
+ isSepaChosen: function() {
+ return $( '#payment_method_stripe_sepa' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe P24 is being used.
+ *
+ * @return {boolean}
+ */
+ isP24Chosen: function() {
+ return $( '#payment_method_stripe_p24' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe EPS is being used.
+ *
+ * @return {boolean}
+ */
+ isEpsChosen: function() {
+ return $( '#payment_method_stripe_eps' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe Multibanco is being used.
+ *
+ * @return {boolean}
+ */
+ isMultibancoChosen: function() {
+ return $( '#payment_method_stripe_multibanco' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe Boleto is being used.
+ *
+ * @return {boolean}
+ */
+ isBoletoChosen: function() {
+ return $( '#payment_method_stripe_boleto' ).is( ':checked' );
+ },
+
+ /**
+ * Check if Stripe OXXO is being used.
+ *
+ * @return {boolean}
+ */
+ isOxxoChosen: function() {
+ return $( '#payment_method_stripe_oxxo' ).is( ':checked' );
+ },
+
+ /**
+ * Checks if a source ID is present as a hidden input.
+ * Only used when SEPA Direct Debit is chosen.
+ *
+ * @return {boolean}
+ */
+ hasSource: function() {
+ return 0 < $( 'input.stripe-source' ).length;
+ },
+
+ /**
+ * Check whether a mobile device is being used.
+ *
+ * @return {boolean}
+ */
+ isMobile: function() {
+ if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent ) ) {
+ return true;
+ }
+
+ return false;
+ },
+
+ /**
+ * Blocks payment forms with an overlay while being submitted.
+ */
+ block: function() {
+ if ( ! wc_stripe_form.isMobile() ) {
+ wc_stripe_form.form.block( {
+ message: null,
+ overlayCSS: {
+ background: '#fff',
+ opacity: 0.6
+ }
+ } );
+ }
+ },
+
+ /**
+ * Removes overlays from payment forms.
+ */
+ unblock: function() {
+ wc_stripe_form.form && wc_stripe_form.form.unblock();
+ },
+
+ /**
+ * Returns the selected payment method HTML element.
+ *
+ * @return {HTMLElement}
+ */
+ getSelectedPaymentElement: function() {
+ return $( '.payment_methods input[name="payment_method"]:checked' );
+ },
+
+ /**
+ * Retrieves "owner" data from either the billing fields in a form or preset settings.
+ *
+ * @return {Object}
+ */
+ getOwnerDetails: function() {
+ var first_name = $( '#billing_first_name' ).length ? $( '#billing_first_name' ).val() : wc_stripe_params.billing_first_name,
+ last_name = $( '#billing_last_name' ).length ? $( '#billing_last_name' ).val() : wc_stripe_params.billing_last_name,
+ owner = { name: '', address: {}, email: '', phone: '' };
+
+ owner.name = first_name;
+
+ if ( first_name && last_name ) {
+ owner.name = first_name + ' ' + last_name;
+ } else {
+ owner.name = $( '#stripe-payment-data' ).data( 'full-name' );
+ }
+
+ owner.email = $( '#billing_email' ).val();
+ owner.phone = $( '#billing_phone' ).val();
+
+ /* Stripe does not like empty string values so
+ * we need to remove the parameter if we're not
+ * passing any value.
+ */
+ if ( typeof owner.phone === 'undefined' || 0 >= owner.phone.length ) {
+ delete owner.phone;
+ }
+
+ if ( typeof owner.email === 'undefined' || 0 >= owner.email.length ) {
+ if ( $( '#stripe-payment-data' ).data( 'email' ).length ) {
+ owner.email = $( '#stripe-payment-data' ).data( 'email' );
+ } else {
+ delete owner.email;
+ }
+ }
+
+ if ( typeof owner.name === 'undefined' || 0 >= owner.name.length ) {
+ delete owner.name;
+ }
+
+ owner.address.line1 = $( '#billing_address_1' ).val() || wc_stripe_params.billing_address_1;
+ owner.address.line2 = $( '#billing_address_2' ).val() || wc_stripe_params.billing_address_2;
+ owner.address.state = $( '#billing_state' ).val() || wc_stripe_params.billing_state;
+ owner.address.city = $( '#billing_city' ).val() || wc_stripe_params.billing_city;
+ owner.address.postal_code = $( '#billing_postcode' ).val() || wc_stripe_params.billing_postcode;
+ owner.address.country = $( '#billing_country' ).val() || wc_stripe_params.billing_country;
+
+ return {
+ owner: owner,
+ };
+ },
+
+ /**
+ * Initiates the creation of a Source object.
+ *
+ * Currently this is only used for credit cards and SEPA Direct Debit,
+ * all other payment methods work with redirects to create sources.
+ */
+ createSource: function() {
+ var extra_details = wc_stripe_form.getOwnerDetails();
+
+ // Handle SEPA Direct Debit payments.
+ if ( wc_stripe_form.isSepaChosen() ) {
+ extra_details.currency = $( '#stripe-sepa_debit-payment-data' ).data( 'currency' );
+ extra_details.mandate = { notification_method: wc_stripe_params.sepa_mandate_notification };
+ extra_details.type = 'sepa_debit';
+
+ return stripe.createSource( iban, extra_details ).then( wc_stripe_form.sourceResponse );
+ }
+
+ // Handle card payments.
+ return stripe.createSource( stripe_card, extra_details )
+ .then( wc_stripe_form.sourceResponse );
+ },
+
+ /**
+ * Handles responses, based on source object.
+ *
+ * @param {Object} response The `stripe.createSource` response.
+ */
+ sourceResponse: function( response ) {
+ if ( response.error ) {
+ $( document.body ).trigger( 'stripeError', response );
+ return;
+ }
+
+ wc_stripe_form.reset();
+
+ wc_stripe_form.form.append(
+ $( '<input type="hidden" />' )
+ .addClass( 'stripe-source' )
+ .attr( 'name', 'stripe_source' )
+ .val( response.source.id )
+ );
+
+ if ( $( 'form#add_payment_method' ).length || $( '#wc-stripe-change-payment-method' ).length ) {
+ wc_stripe_form.sourceSetup( response );
+ return;
+ }
+
+ wc_stripe_form.form.trigger( 'submit' );
+ },
+
+ /**
+ * Authenticate Source if necessary by creating and confirming a SetupIntent.
+ *
+ * @param {Object} response The `stripe.createSource` response.
+ */
+ sourceSetup: function( response ) {
+ var apiError = {
+ error: {
+ type: 'api_connection_error'
+ }
+ };
+
+ $.post( {
+ url: wc_stripe_form.getAjaxURL( 'create_setup_intent'),
+ dataType: 'json',
+ data: {
+ stripe_source_id: response.source.id,
+ nonce: wc_stripe_params.add_card_nonce,
+ },
+ error: function() {
+ $( document.body ).trigger( 'stripeError', apiError );
+ }
+ } ).done( function( serverResponse ) {
+ if ( 'success' === serverResponse.status ) {
+ if ( $( 'form#add_payment_method' ).length ) {
+ $( wc_stripe_form.form ).off( 'submit', wc_stripe_form.form.onSubmit );
+ }
+ wc_stripe_form.form.trigger( 'submit' );
+ return;
+ } else if ( 'requires_action' !== serverResponse.status ) {
+ $( document.body ).trigger( 'stripeError', serverResponse );
+ return;
+ }
+
+ stripe.confirmCardSetup( serverResponse.client_secret, { payment_method: response.source.id } )
+ .then( function( result ) {
+ if ( result.error ) {
+ $( document.body ).trigger( 'stripeError', result );
+ return;
+ }
+
+ if ( $( 'form#add_payment_method' ).length ) {
+ $( wc_stripe_form.form ).off( 'submit', wc_stripe_form.form.onSubmit );
+ }
+ wc_stripe_form.form.trigger( 'submit' );
+ } )
+ .catch( function( err ) {
+ console.log( err );
+ $( document.body ).trigger( 'stripeError', { error: err } );
+ } );
+ } );
+ },
+
+ /**
+ * Performs payment-related actions when a checkout/payment form is being submitted.
+ *
+ * @return {boolean} An indicator whether the submission should proceed.
+ * WooCommerce's checkout.js stops only on `false`, so this needs to be explicit.
+ */
+ onSubmit: function() {
+ if ( ! wc_stripe_form.isStripeChosen() ) {
+ return true;
+ }
+
+ // If a source is already in place, submit the form as usual.
+ if ( wc_stripe_form.isStripeSaveCardChosen() || wc_stripe_form.hasSource() ) {
+ return true;
+ }
+
+ // For methods that needs redirect, we will create the source server side so we can obtain the order ID.
+ if (
+ wc_stripe_form.isBancontactChosen() ||
+ wc_stripe_form.isGiropayChosen() ||
+ wc_stripe_form.isIdealChosen() ||
+ wc_stripe_form.isAlipayChosen() ||
+ wc_stripe_form.isSofortChosen() ||
+ wc_stripe_form.isP24Chosen() ||
+ wc_stripe_form.isEpsChosen() ||
+ wc_stripe_form.isMultibancoChosen()
+ ) {
+ return true;
+ }
+
+ wc_stripe_form.block();
+
+ if( wc_stripe_form.isBoletoChosen() ) {
+ if( ! $( '#stripe_boleto_tax_id' ).val() ) {
+ wc_stripe_form.submitError( wc_stripe_params.cpf_cnpj_required_msg );
+ wc_stripe_form.unblock();
+ return false;
+ }
+
+ wc_stripe_form.handleBoleto();
+ } else if ( wc_stripe_form.isOxxoChosen() ) {
+ wc_stripe_form.handleOxxo();
+ } else {
+ wc_stripe_form.createSource();
+ }
+
+ return false;
+ },
+
+ /**
+ * Will show a modal for printing the Boleto.
+ * After the customer closes the modal proceeds with checkout normally
+ */
+ handleBoleto: function () {
+ wc_stripe_form.executeCheckout( 'boleto', function ( checkout_response ) {
+ stripe.confirmBoletoPayment(
+ checkout_response.client_secret,
+ checkout_response.confirm_payment_data
+ )
+ .then(function ( response ) {
+ wc_stripe_form.handleConfirmResponse( checkout_response, response );
+ });
+ } );
+ },
+
+ /**
+ * Executes the checkout and then execute the callback instead of redirect to success page
+ * @param callback
+ */
+ executeCheckout: function ( payment_method, callback ) {
+ const formFields = wc_stripe_form.form.serializeArray().reduce( ( obj, field ) => {
+ obj[ field.name ] = field.value;
+ return obj;
+ }, {} );
+
+ if( wc_stripe_form.form.attr('id') === 'order_review' ) {
+ formFields._ajax_nonce = wc_stripe_params.updatePaymentIntentNonce;
+ formFields.order_id = wc_stripe_params.orderId;
+
+ $.ajax( {
+ url: wc_stripe_form.getAjaxURL( payment_method + '_update_payment_intent' ),
+ type: 'POST',
+ data: formFields,
+ success: function ( response ) {
+
+ if( 'success' !== response.result ) {
+ wc_stripe_form.submitError( response.messages );
+ wc_stripe_form.unblock();
+ return;
+ }
+
+ callback( response );
+ }
+ } );
+
+ } else {
+ $.ajax( {
+ url: wc_stripe_params.checkout_url,
+ type: 'POST',
+ data: formFields,
+ success: function ( checkout_response ) {
+
+ if( 'success' !== checkout_response.result ) {
+ wc_stripe_form.submitError( checkout_response.messages, true );
+ wc_stripe_form.unblock();
+ return;
+ }
+
+ callback( checkout_response );
+ }
+ } );
+ }
+ },
+
+ /**
+ * Handles response of the Confirm<payment_method>Payment like confirmBoletoPayment and confirmOxxoPayment
+ * @param checkout_response
+ * @param response
+ */
+ handleConfirmResponse: function ( checkout_response, response ) {
+ if ( response.error ) {
+ $( document.body ).trigger( 'stripeError', response );
+ return;
+ }
+
+ if ( -1 === checkout_response.redirect.indexOf( 'https://' ) || -1 === checkout_response.redirect.indexOf( 'http://' ) ) {
+ window.location = checkout_response.redirect;
+ } else {
+ window.location = decodeURI( checkout_response.redirect );
+ }
+ },
+
+ /**
+ * Will show a modal for printing the OXXO Voucher.
+ * After the customer closes the modal proceeds with checkout normally
+ */
+ handleOxxo: function () {
+ wc_stripe_form.executeCheckout( 'oxxo', function ( checkout_response ) {
+ stripe.confirmOxxoPayment(
+ checkout_response.client_secret,
+ checkout_response.confirm_payment_data
+ )
+ .then(function (response) {
+ wc_stripe_form.handleConfirmResponse( checkout_response, response );
+ } );
+ } );
+ },
+
+ /**
+ * If a new credit card is entered, reset sources.
+ */
+ onCCFormChange: function() {
+ wc_stripe_form.reset();
+ },
+
+ /**
+ * Removes all Stripe errors and hidden fields with IDs from the form.
+ */
+ reset: function() {
+ $( '.wc-stripe-error, .stripe-source' ).remove();
+ },
+
+ /**
+ * Displays a SEPA-specific error message.
+ *
+ * @param {Event} e The event with the error.
+ */
+ onSepaError: function( e ) {
+ var errorContainer = wc_stripe_form.getSelectedPaymentElement().parents( 'li' ).eq( 0 ).find( '.stripe-source-errors' );
+
+ if ( ! e.error ) {
+ $( errorContainer ).html( '' );
+ return;
+ }
+
+ console.log( e.error.message ); // Leave for troubleshooting.
+ $( errorContainer ).html( '<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li /></ul>' );
+ $( errorContainer ).find( 'li' ).text( e.error.message ); // Prevent XSS
+ },
+
+ /**
+ * Displays stripe-related errors.
+ *
+ * @param {Event} e The jQuery event.
+ * @param {Object} result The result of Stripe call.
+ */
+ onError: function( e, result ) {
+ var message = result.error.message;
+ var selectedMethodElement = wc_stripe_form.getSelectedPaymentElement().closest( 'li' );
+ var savedTokens = selectedMethodElement.find( '.woocommerce-SavedPaymentMethods-tokenInput' );
+ var errorContainer;
+
+ var prButtonClicked = $( 'body' ).hasClass( 'woocommerce-stripe-prb-clicked' );
+ if ( prButtonClicked ) {
+ // If payment was initiated with a payment request button, display errors in the notices div.
+ $( 'body' ).removeClass( 'woocommerce-stripe-prb-clicked' );
+ errorContainer = $( 'div.woocommerce-notices-wrapper' ).first();
+ } else if ( savedTokens.length ) {
+ // In case there are saved cards too, display the message next to the correct one.
+ var selectedToken = savedTokens.filter( ':checked' );
+
+ if ( selectedToken.closest( '.woocommerce-SavedPaymentMethods-new' ).length ) {
+ // Display the error next to the CC fields if a new card is being entered.
+ errorContainer = $( '#wc-stripe-cc-form .stripe-source-errors' );
+ } else {
+ // Display the error next to the chosen saved card.
+ errorContainer = selectedToken.closest( 'li' ).find( '.stripe-source-errors' );
+ }
+ } else {
+ // When no saved cards are available, display the error next to CC fields.
+ errorContainer = selectedMethodElement.find( '.stripe-source-errors' );
+ }
+
+ /*
+ * If payment method is SEPA and owner name is not completed,
+ * source cannot be created. So we need to show the normal
+ * Billing name is required error message on top of form instead
+ * of inline.
+ */
+ if ( wc_stripe_form.isSepaChosen() ) {
+ if ( 'invalid_owner_name' === result.error.code && wc_stripe_params.hasOwnProperty( result.error.code ) ) {
+ wc_stripe_form.submitError( wc_stripe_params[ result.error.code ] );
+ return;
+ }
+ }
+
+ // Notify users that the email is invalid.
+ if ( 'email_invalid' === result.error.code ) {
+ message = wc_stripe_params.email_invalid;
+ } else if (
+ /*
+ * Customers do not need to know the specifics of the below type of errors
+ * therefore return a generic localizable error message.
+ */
+ 'invalid_request_error' === result.error.type ||
+ 'api_connection_error' === result.error.type ||
+ 'api_error' === result.error.type ||
+ 'authentication_error' === result.error.type ||
+ 'rate_limit_error' === result.error.type
+ ) {
+ message = wc_stripe_params.invalid_request_error;
+ }
+
+ if ( wc_stripe_params.hasOwnProperty(result.error.code) ) {
+ message = wc_stripe_params[ result.error.code ];
+ }
+
+ wc_stripe_form.reset();
+ $( '.woocommerce-NoticeGroup-checkout' ).remove();
+ console.log( result.error.message ); // Leave for troubleshooting.
+ $( errorContainer ).html( '<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li /></ul>' );
+ $( errorContainer ).find( 'li' ).text( message ); // Prevent XSS
+
+ if ( $( '.wc-stripe-error' ).length ) {
+ $( 'html, body' ).animate({
+ scrollTop: ( $( '.wc-stripe-error' ).offset().top - 200 )
+ }, 200 );
+ }
+ wc_stripe_form.unblock();
+ $.unblockUI(); // If arriving via Payment Request Button.
+ },
+
+ /**
+ * Displays an error message in the beginning of the form and scrolls to it.
+ *
+ * @param {Object} error_message An error message jQuery object.
+ */
+ submitError: function( error_message, is_html = false ) {
+ if( ! is_html ) {
+ var error = $( '<div><ul class="woocommerce-error"><li /></ul></div>' );
+ error.find( 'li' ).text( error_message ); // Prevent XSS
+ error_message = error.html();
+ }
+
+ $( '.woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message' ).remove();
+ wc_stripe_form.form.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">' + error_message + '</div>' );
+ wc_stripe_form.form.removeClass( 'processing' ).unblock();
+ wc_stripe_form.form.find( '.input-text, select, input:checkbox' ).trigger( 'blur' );
+
+ var selector = '';
+
+ if ( $( '#add_payment_method' ).length ) {
+ selector = $( '#add_payment_method' );
+ }
+
+ if ( $( '#order_review' ).length ) {
+ selector = $( '#order_review' );
+ }
+
+ if ( $( 'form.checkout' ).length ) {
+ selector = $( 'form.checkout' );
+ }
+
+ if ( selector.length ) {
+ $( 'html, body' ).animate({
+ scrollTop: ( selector.offset().top - 100 )
+ }, 500 );
+ }
+
+ $( document.body ).trigger( 'checkout_error' );
+ wc_stripe_form.unblock();
+ },
+
+ /**
+ * Handles changes in the hash in order to show a modal for PaymentIntent/SetupIntent confirmations.
+ *
+ * Listens for `hashchange` events and checks for a hash in the following format:
+ * #confirm-pi-<intentClientSecret>:<successRedirectURL>
+ *
+ * If such a hash appears, the partials will be used to call `stripe.handleCardPayment`
+ * in order to allow customers to confirm an 3DS/SCA authorization, or stripe.handleCardSetup if
+ * what needs to be confirmed is a SetupIntent.
+ *
+ * Those redirects/hashes are generated in `WC_Gateway_Stripe::process_payment`.
+ */
+ onHashChange: function() {
+ var partials = window.location.hash.match( /^#?confirm-(pi|si)-([^:]+):(.+)$/ );
+
+ if ( ! partials || 4 > partials.length ) {
+ return;
+ }
+
+ var type = partials[1];
+ var intentClientSecret = partials[2];
+ var redirectURL = decodeURIComponent( partials[3] );
+
+ // Cleanup the URL
+ window.location.hash = '';
+
+ wc_stripe_form.openIntentModal( intentClientSecret, redirectURL, false, 'si' === type );
+ },
+
+ maybeConfirmIntent: function() {
+ if ( ! $( '#stripe-intent-id' ).length || ! $( '#stripe-intent-return' ).length ) {
+ return;
+ }
+
+ var intentSecret = $( '#stripe-intent-id' ).val();
+ var returnURL = $( '#stripe-intent-return' ).val();
+
+ wc_stripe_form.openIntentModal( intentSecret, returnURL, true, false );
+ },
+
+ /**
+ * Opens the modal for PaymentIntent authorizations.
+ *
+ * @param {string} intentClientSecret The client secret of the intent.
+ * @param {string} redirectURL The URL to ping on fail or redirect to on success.
+ * @param {boolean} alwaysRedirect If set to true, an immediate redirect will happen no matter the result.
+ * If not, an error will be displayed on failure.
+ * @param {boolean} isSetupIntent If set to true, ameans that the flow is handling a Setup Intent.
+ * If false, it's a Payment Intent.
+ */
+ openIntentModal: function( intentClientSecret, redirectURL, alwaysRedirect, isSetupIntent ) {
+ stripe[ isSetupIntent ? 'handleCardSetup' : 'handleCardPayment' ]( intentClientSecret )
+ .then( function( response ) {
+ if ( response.error ) {
+ throw response.error;
+ }
+
+ var intent = response[ isSetupIntent ? 'setupIntent' : 'paymentIntent' ];
+ if ( 'requires_capture' !== intent.status && 'succeeded' !== intent.status ) {
+ return;
+ }
+
+ window.location = redirectURL;
+ } )
+ .catch( function( error ) {
+ if ( alwaysRedirect ) {
+ window.location = redirectURL;
+ return;
+ }
+
+ $( document.body ).trigger( 'stripeError', { error: error } );
+ wc_stripe_form.form && wc_stripe_form.form.removeClass( 'processing' );
+
+ // Report back to the server.
+ $.get( redirectURL + '&is_ajax' );
+ } );
+ },
+
+ /**
+ * Prevents the standard behavior of the "Renew Now" button in the
+ * early renewals modal by using AJAX instead of a simple redirect.
+ *
+ * @param {Event} e The event that occured.
+ */
+ onEarlyRenewalSubmit: function( e ) {
+ e.preventDefault();
+
+ $.ajax( {
+ url: $( '#early_renewal_modal_submit' ).attr( 'href' ),
+ method: 'get',
+ success: function( html ) {
+ var response = JSON.parse( html );
+
+ if ( response.stripe_sca_required ) {
+ wc_stripe_form.openIntentModal( response.intent_secret, response.redirect_url, true, false );
+ } else {
+ window.location = response.redirect_url;
+ }
+ },
+ } );
+
+ return false;
+ },
+ };
+
+ wc_stripe_form.init();
+} );
diff --git a/assets/js/stripe.min.js b/assets/js/stripe.min.js
new file mode 100644
index 0000000..06c3497
--- /dev/null
+++ b/assets/js/stripe.min.js
@@ -0,0 +1 @@
+jQuery(function(i){"use strict";try{var n=Stripe(wc_stripe_params.key,{locale:wc_stripe_params.stripe_locale||"auto"})}catch(e){return void console.log(e)}var t,o,s,e=Object.keys(wc_stripe_params.elements_options).length?wc_stripe_params.elements_options:{},r=Object.keys(wc_stripe_params.sepa_elements_options).length?wc_stripe_params.sepa_elements_options:{},a=n.elements(e),c=a.create("iban",r),m={getAjaxURL:function(e){return wc_stripe_params.ajaxurl.toString().replace("%%endpoint%%","wc_stripe_"+e)},unmountElements:function(){"yes"===wc_stripe_params.inline_cc_form?t.unmount("#stripe-card-element"):(t.unmount("#stripe-card-element"),o.unmount("#stripe-exp-element"),s.unmount("#stripe-cvc-element"))},mountElements:function(){i("#stripe-card-element").length&&("yes"!==wc_stripe_params.inline_cc_form?(t.mount("#stripe-card-element"),o.mount("#stripe-exp-element"),s.mount("#stripe-cvc-element")):t.mount("#stripe-card-element"))},createElements:function(){var e={base:{iconColor:"#666EE8",color:"#31325F",fontSize:"15px","::placeholder":{color:"#CFD7E0"}}},r={focus:"focused",empty:"empty",invalid:"invalid"},e=wc_stripe_params.elements_styling||e,r=wc_stripe_params.elements_classes||r;"yes"===wc_stripe_params.inline_cc_form?(t=a.create("card",{style:e,hidePostalCode:!0})).addEventListener("change",function(e){m.onCCFormChange(),e.error&&i(document.body).trigger("stripeError",e)}):(t=a.create("cardNumber",{style:e,classes:r}),o=a.create("cardExpiry",{style:e,classes:r}),s=a.create("cardCvc",{style:e,classes:r}),t.addEventListener("change",function(e){m.onCCFormChange(),m.updateCardBrand(e.brand),e.error&&i(document.body).trigger("stripeError",e)}),o.addEventListener("change",function(e){m.onCCFormChange(),e.error&&i(document.body).trigger("stripeError",e)}),s.addEventListener("change",function(e){m.onCCFormChange(),e.error&&i(document.body).trigger("stripeError",e)})),"yes"===wc_stripe_params.is_checkout?i(document.body).on("updated_checkout",function(){i("#stripe-card-element").children().length||(t&&m.unmountElements(),m.mountElements(),i("#stripe-iban-element").length&&c.mount("#stripe-iban-element"))}):(i("form#add_payment_method").length||i("form#order_review").length)&&(m.mountElements(),i("#stripe-iban-element").length&&c.mount("#stripe-iban-element"))},updateCardBrand:function(e){var r={visa:"stripe-visa-brand",mastercard:"stripe-mastercard-brand",amex:"stripe-amex-brand",discover:"stripe-discover-brand",diners:"stripe-diners-brand",jcb:"stripe-jcb-brand",unknown:"stripe-credit-card-brand"},t=i(".stripe-card-brand"),e=e in r?r[e]:"stripe-credit-card-brand";i.each(r,function(e,r){t.removeClass(r)}),t.addClass(e)},init:function(){"yes"!==wc_stripe_params.is_change_payment_page&&"yes"!==wc_stripe_params.is_pay_for_order_page||i(document.body).trigger("wc-credit-card-form-init"),i("form.woocommerce-checkout").length&&(this.form=i("form.woocommerce-checkout")),i("form.woocommerce-checkout").on("checkout_place_order_stripe checkout_place_order_stripe_bancontact checkout_place_order_stripe_sofort checkout_place_order_stripe_giropay checkout_place_order_stripe_ideal checkout_place_order_stripe_alipay checkout_place_order_stripe_sepa checkout_place_order_stripe_boleto checkout_place_order_stripe_oxxo",this.onSubmit),i("form#order_review").length&&(this.form=i("form#order_review")),i("form#order_review, form#add_payment_method").on("submit",this.onSubmit),i("form#add_payment_method").length&&(this.form=i("form#add_payment_method")),i("form.woocommerce-checkout").on("change",this.reset),i(document).on("stripeError",this.onError).on("checkout_error",this.reset),c.on("change",this.onSepaError),(i("#early_renewal_modal_submit[data-payment-method]").length?i("#early_renewal_modal_submit[data-payment-method=stripe]"):i("#early_renewal_modal_submit")).on("click",this.onEarlyRenewalSubmit),m.createElements(),window.addEventListener("hashchange",m.onHashChange),m.maybeConfirmIntent(),i(document).on("change",".wc_payment_methods",function(){var n,e;i("#stripe_boleto_tax_id").length&&(n=function(e){return 12<=e.replace(/\D/g,"").length?"00.000.000/0000-00":"000.000.000-009999"},e={onKeyPress:function(e,r,t,o){t.mask(n.apply({},arguments),o)}},i("#stripe_boleto_tax_id").mask(n,e))})},isStripeChosen:function(){return i("#payment_method_stripe, #payment_method_stripe_bancontact, #payment_method_stripe_sofort, #payment_method_stripe_giropay, #payment_method_stripe_ideal, #payment_method_stripe_alipay, #payment_method_stripe_sepa, #payment_method_stripe_eps, #payment_method_stripe_multibanco, #payment_method_stripe_boleto, #payment_method_stripe_oxxo").is(":checked")||i("#payment_method_stripe").is(":checked")&&"new"===i('input[name="wc-stripe-payment-token"]:checked').val()||i("#payment_method_stripe_sepa").is(":checked")&&"new"===i('input[name="wc-stripe-payment-token"]:checked').val()},isStripeSaveCardChosen:function(){return i("#payment_method_stripe").is(":checked")&&i('input[name="wc-stripe-payment-token"]').is(":checked")&&"new"!==i('input[name="wc-stripe-payment-token"]:checked').val()||i("#payment_method_stripe_sepa").is(":checked")&&i('input[name="wc-stripe_sepa-payment-token"]').is(":checked")&&"new"!==i('input[name="wc-stripe_sepa-payment-token"]:checked').val()},isStripeCardChosen:function(){return i("#payment_method_stripe").is(":checked")},isBancontactChosen:function(){return i("#payment_method_stripe_bancontact").is(":checked")},isGiropayChosen:function(){return i("#payment_method_stripe_giropay").is(":checked")},isIdealChosen:function(){return i("#payment_method_stripe_ideal").is(":checked")},isSofortChosen:function(){return i("#payment_method_stripe_sofort").is(":checked")},isAlipayChosen:function(){return i("#payment_method_stripe_alipay").is(":checked")},isSepaChosen:function(){return i("#payment_method_stripe_sepa").is(":checked")},isP24Chosen:function(){return i("#payment_method_stripe_p24").is(":checked")},isEpsChosen:function(){return i("#payment_method_stripe_eps").is(":checked")},isMultibancoChosen:function(){return i("#payment_method_stripe_multibanco").is(":checked")},isBoletoChosen:function(){return i("#payment_method_stripe_boleto").is(":checked")},isOxxoChosen:function(){return i("#payment_method_stripe_oxxo").is(":checked")},hasSource:function(){return 0<i("input.stripe-source").length},isMobile:function(){return!!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},block:function(){m.isMobile()||m.form.block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){m.form&&m.form.unblock()},getSelectedPaymentElement:function(){return i('.payment_methods input[name="payment_method"]:checked')},getOwnerDetails:function(){var e=i("#billing_first_name").length?i("#billing_first_name").val():wc_stripe_params.billing_first_name,r=i("#billing_last_name").length?i("#billing_last_name").val():wc_stripe_params.billing_last_name,t={name:"",address:{},email:"",phone:""};return t.name=e,t.name=e&&r?e+" "+r:i("#stripe-payment-data").data("full-name"),t.email=i("#billing_email").val(),t.phone=i("#billing_phone").val(),(void 0===t.phone||t.phone.length<=0)&&delete t.phone,(void 0===t.email||t.email.length<=0)&&(i("#stripe-payment-data").data("email").length?t.email=i("#stripe-payment-data").data("email"):delete t.email),(void 0===t.name||t.name.length<=0)&&delete t.name,t.address.line1=i("#billing_address_1").val()||wc_stripe_params.billing_address_1,t.address.line2=i("#billing_address_2").val()||wc_stripe_params.billing_address_2,t.address.state=i("#billing_state").val()||wc_stripe_params.billing_state,t.address.city=i("#billing_city").val()||wc_stripe_params.billing_city,t.address.postal_code=i("#billing_postcode").val()||wc_stripe_params.billing_postcode,t.address.country=i("#billing_country").val()||wc_stripe_params.billing_country,{owner:t}},createSource:function(){var e=m.getOwnerDetails();return m.isSepaChosen()?(e.currency=i("#stripe-sepa_debit-payment-data").data("currency"),e.mandate={notification_method:wc_stripe_params.sepa_mandate_notification},e.type="sepa_debit",n.createSource(c,e).then(m.sourceResponse)):n.createSource(t,e).then(m.sourceResponse)},sourceResponse:function(e){e.error?i(document.body).trigger("stripeError",e):(m.reset(),m.form.append(i('<input type="hidden" />').addClass("stripe-source").attr("name","stripe_source").val(e.source.id)),i("form#add_payment_method").length||i("#wc-stripe-change-payment-method").length?m.sourceSetup(e):m.form.trigger("submit"))},sourceSetup:function(r){var e={error:{type:"api_connection_error"}};i.post({url:m.getAjaxURL("create_setup_intent"),dataType:"json",data:{stripe_source_id:r.source.id,nonce:wc_stripe_params.add_card_nonce},error:function(){i(document.body).trigger("stripeError",e)}}).done(function(e){return"success"===e.status?(i("form#add_payment_method").length&&i(m.form).off("submit",m.form.onSubmit),void m.form.trigger("submit")):void("requires_action"===e.status?n.confirmCardSetup(e.client_secret,{payment_method:r.source.id}).then(function(e){e.error?i(document.body).trigger("stripeError",e):(i("form#add_payment_method").length&&i(m.form).off("submit",m.form.onSubmit),m.form.trigger("submit"))}).catch(function(e){console.log(e),i(document.body).trigger("stripeError",{error:e})}):i(document.body).trigger("stripeError",e))})},onSubmit:function(){if(!m.isStripeChosen())return!0;if(m.isStripeSaveCardChosen()||m.hasSource())return!0;if(m.isBancontactChosen()||m.isGiropayChosen()||m.isIdealChosen()||m.isAlipayChosen()||m.isSofortChosen()||m.isP24Chosen()||m.isEpsChosen()||m.isMultibancoChosen())return!0;if(m.block(),m.isBoletoChosen()){if(!i("#stripe_boleto_tax_id").val())return m.submitError(wc_stripe_params.cpf_cnpj_required_msg),m.unblock(),!1;m.handleBoleto()}else m.isOxxoChosen()?m.handleOxxo():m.createSource();return!1},handleBoleto:function(){m.executeCheckout("boleto",function(r){n.confirmBoletoPayment(r.client_secret,r.confirm_payment_data).then(function(e){m.handleConfirmResponse(r,e)})})},executeCheckout:function(e,r){const t=m.form.serializeArray().reduce((e,r)=>(e[r.name]=r.value,e),{});"order_review"===m.form.attr("id")?(t._ajax_nonce=wc_stripe_params.updatePaymentIntentNonce,t.order_id=wc_stripe_params.orderId,i.ajax({url:m.getAjaxURL(e+"_update_payment_intent"),type:"POST",data:t,success:function(e){if("success"!==e.result)return m.submitError(e.messages),void m.unblock();r(e)}})):i.ajax({url:wc_stripe_params.checkout_url,type:"POST",data:t,success:function(e){if("success"!==e.result)return m.submitError(e.messages,!0),void m.unblock();r(e)}})},handleConfirmResponse:function(e,r){r.error?i(document.body).trigger("stripeError",r):-1===e.redirect.indexOf("https://")||-1===e.redirect.indexOf("http://")?window.location=e.redirect:window.location=decodeURI(e.redirect)},handleOxxo:function(){m.executeCheckout("oxxo",function(r){n.confirmOxxoPayment(r.client_secret,r.confirm_payment_data).then(function(e){m.handleConfirmResponse(r,e)})})},onCCFormChange:function(){m.reset()},reset:function(){i(".wc-stripe-error, .stripe-source").remove()},onSepaError:function(e){var r=m.getSelectedPaymentElement().parents("li").eq(0).find(".stripe-source-errors");e.error?(console.log(e.error.message),i(r).html('<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li /></ul>'),i(r).find("li").text(e.error.message)):i(r).html("")},onError:function(e,r){var t=r.error.message,o=m.getSelectedPaymentElement().closest("li"),n=o.find(".woocommerce-SavedPaymentMethods-tokenInput");o=i("body").hasClass("woocommerce-stripe-prb-clicked")?(i("body").removeClass("woocommerce-stripe-prb-clicked"),i("div.woocommerce-notices-wrapper").first()):n.length?(n=n.filter(":checked")).closest(".woocommerce-SavedPaymentMethods-new").length?i("#wc-stripe-cc-form .stripe-source-errors"):n.closest("li").find(".stripe-source-errors"):o.find(".stripe-source-errors"),m.isSepaChosen()&&"invalid_owner_name"===r.error.code&&wc_stripe_params.hasOwnProperty(r.error.code)?m.submitError(wc_stripe_params[r.error.code]):("email_invalid"===r.error.code?t=wc_stripe_params.email_invalid:"invalid_request_error"!==r.error.type&&"api_connection_error"!==r.error.type&&"api_error"!==r.error.type&&"authentication_error"!==r.error.type&&"rate_limit_error"!==r.error.type||(t=wc_stripe_params.invalid_request_error),wc_stripe_params.hasOwnProperty(r.error.code)&&(t=wc_stripe_params[r.error.code]),m.reset(),i(".woocommerce-NoticeGroup-checkout").remove(),console.log(r.error.message),i(o).html('<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li /></ul>'),i(o).find("li").text(t),i(".wc-stripe-error").length&&i("html, body").animate({scrollTop:i(".wc-stripe-error").offset().top-200},200),m.unblock(),i.unblockUI())},submitError:function(e,r=!1){r||((r=i('<div><ul class="woocommerce-error"><li /></ul></div>')).find("li").text(e),e=r.html()),i(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),m.form.prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+e+"</div>"),m.form.removeClass("processing").unblock(),m.form.find(".input-text, select, input:checkbox").trigger("blur");e="";i("#add_payment_method").length&&(e=i("#add_payment_method")),i("#order_review").length&&(e=i("#order_review")),(e=i("form.checkout").length?i("form.checkout"):e).length&&i("html, body").animate({scrollTop:e.offset().top-100},500),i(document.body).trigger("checkout_error"),m.unblock()},onHashChange:function(){var e,r,t=window.location.hash.match(/^#?confirm-(pi|si)-([^:]+):(.+)$/);!t||t.length<4||(e=t[1],r=t[2],t=decodeURIComponent(t[3]),window.location.hash="",m.openIntentModal(r,t,!1,"si"===e))},maybeConfirmIntent:function(){var e,r;i("#stripe-intent-id").length&&i("#stripe-intent-return").length&&(e=i("#stripe-intent-id").val(),r=i("#stripe-intent-return").val(),m.openIntentModal(e,r,!0,!1))},openIntentModal:function(e,r,t,o){n[o?"handleCardSetup":"handleCardPayment"](e).then(function(e){if(e.error)throw e.error;e=e[o?"setupIntent":"paymentIntent"];"requires_capture"!==e.status&&"succeeded"!==e.status||(window.location=r)}).catch(function(e){t?window.location=r:(i(document.body).trigger("stripeError",{error:e}),m.form&&m.form.removeClass("processing"),i.get(r+"&is_ajax"))})},onEarlyRenewalSubmit:function(e){return e.preventDefault(),i.ajax({url:i("#early_renewal_modal_submit").attr("href"),method:"get",success:function(e){e=JSON.parse(e);e.stripe_sca_required?m.openIntentModal(e.intent_secret,e.redirect_url,!0,!1):window.location=e.redirect_url}}),!1}};m.init()});