Version Description
TUESDAY, 4TH JANUARY 2022 = * New: Supports Alipay payment method. * New: Supports iDEAL payment method. * Improvement: More customization options for Express Checkout. * Improvement: Webhook integration for multiple events - charge.refunded, charge.dispute.created, charge.dispute.closed, payment_intent.succeeded, payment_intent.amount_capturable_updated, payment_intent.payment_failed, review.opened, review.closed.
Download this release
Release Info
Developer | brainstormworg |
Plugin | Stripe Payments For WooCommerce by Checkout Plugins |
Version | 1.2.0 |
Comparing to | |
See all releases |
Code changes from version 1.1.1 to 1.2.0
- admin/admin-controller.php +65 -26
- admin/assets/css/express-checkout.css +0 -4
- admin/assets/js/admin.js +63 -0
- admin/assets/js/express-checkout.js +66 -17
- assets/css/stripe-elements.css +25 -6
- assets/icon/alipay.svg +1 -0
- assets/icon/ideal.svg +1 -0
- assets/js/payment-request.js +20 -0
- assets/js/stripe-elements.js +108 -31
- autoloader.php +21 -0
- checkout-plugins-stripe-woo.php +2 -2
- compatibility/apple-pay.php +1 -1
- gateway/abstract-payment-gateway.php +495 -4
- gateway/local-gateway.php +351 -0
- gateway/stripe/alipay.php +336 -0
- gateway/stripe/card-payments.php +25 -385
- gateway/stripe/frontend-scripts.php +59 -25
- gateway/stripe/ideal.php +264 -0
- gateway/stripe/payment-request-api.php +46 -27
- gateway/stripe/stripe-api.php +10 -0
- gateway/stripe/webhook.php +350 -3
- inc/helper.php +49 -20
- inc/notice.php +131 -0
- inc/traits/subscriptions.php +3 -2
- readme.txt +57 -8
admin/admin-controller.php
CHANGED
@@ -77,6 +77,8 @@ class Admin_Controller {
|
|
77 |
'cpsw_api_settings' => __( 'Stripe API Settings', 'checkout-plugins-stripe-woo' ),
|
78 |
'cpsw_stripe' => __( 'Credit Cards', 'checkout-plugins-stripe-woo' ),
|
79 |
'cpsw_express_checkout' => __( 'Express Checkout', 'checkout-plugins-stripe-woo' ),
|
|
|
|
|
80 |
];
|
81 |
|
82 |
}
|
@@ -106,6 +108,7 @@ class Admin_Controller {
|
|
106 |
add_action( 'wp_ajax_cpsw_test_stripe_connection', [ $this, 'connection_test' ] );
|
107 |
add_action( 'wp_ajax_cpsw_disconnect_account', [ $this, 'disconnect_account' ] );
|
108 |
add_action( 'wp_ajax_cpsw_js_errors', [ $this, 'js_errors' ] );
|
|
|
109 |
|
110 |
add_action( 'woocommerce_settings_save_cpsw_api_settings', [ $this, 'check_connection_on_updates' ] );
|
111 |
add_filter( 'woocommerce_save_settings_checkout_cpsw_express_checkout', [ $this, 'cpsw_express_checkout_option_updates' ] );
|
@@ -132,6 +135,7 @@ class Admin_Controller {
|
|
132 |
$express_checkout = [];
|
133 |
$radio_checkbox = [
|
134 |
'express_checkout_enabled' => 'no',
|
|
|
135 |
'express_checkout_product_sticky_footer' => 'no',
|
136 |
'express_checkout_product_checkout_page' => 'no',
|
137 |
];
|
@@ -154,8 +158,9 @@ class Admin_Controller {
|
|
154 |
}
|
155 |
|
156 |
if ( ! empty( $express_checkout ) ) {
|
157 |
-
$cpsw_stripe
|
158 |
-
$cpsw_stripe =
|
|
|
159 |
update_option( 'woocommerce_cpsw_stripe_settings', $cpsw_stripe );
|
160 |
}
|
161 |
}
|
@@ -196,12 +201,15 @@ class Admin_Controller {
|
|
196 |
* @since 0.0.1
|
197 |
*/
|
198 |
public function enqueue_scripts() {
|
199 |
-
|
|
|
200 |
|
201 |
-
|
|
|
|
|
202 |
wp_enqueue_style( 'cpsw-admin-style' );
|
203 |
|
204 |
-
wp_register_script( 'cpsw-admin-js', plugins_url( 'assets/js/admin.js', __FILE__ ), [ 'jquery' ],
|
205 |
wp_enqueue_script( 'cpsw-admin-js' );
|
206 |
|
207 |
wp_localize_script(
|
@@ -223,18 +231,19 @@ class Admin_Controller {
|
|
223 |
'is_connected' => $this->is_stripe_connected(),
|
224 |
'is_manually_connected' => isset( $_GET['connect'] ) ? sanitize_text_field( $_GET['connect'] ) : '', //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
225 |
'cpsw_admin_settings_tab' => isset( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : '', //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
|
226 |
]
|
227 |
);
|
228 |
}
|
229 |
|
230 |
if ( isset( $_GET['page'] ) && 'wc-settings' === $_GET['page'] && isset( $_GET['tab'] ) && 'checkout' === $_GET['tab'] && isset( $_GET['section'] ) && 'cpsw_express_checkout' === $_GET['section'] ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
231 |
-
wp_register_style( 'cpsw-express-checkout-style', plugins_url( 'assets/css/express-checkout.css', __FILE__ ), [],
|
232 |
wp_enqueue_style( 'cpsw-express-checkout-style' );
|
233 |
|
234 |
-
wp_register_script( 'cpsw-stripe-external', 'https://js.stripe.com/v3/', [],
|
235 |
wp_enqueue_script( 'cpsw-stripe-external' );
|
236 |
|
237 |
-
wp_register_script( 'cpsw-express-checkout-js', plugins_url( 'assets/js/express-checkout.js', __FILE__ ), [ 'jquery', 'cpsw-stripe-external' ],
|
238 |
wp_enqueue_script( 'cpsw-express-checkout-js' );
|
239 |
|
240 |
$public_key = ( 'live' === Helper::get_payment_mode() ) ? Helper::get_setting( 'cpsw_pub_key' ) : Helper::get_setting( 'cpsw_test_pub_key' );
|
@@ -457,6 +466,7 @@ class Admin_Controller {
|
|
457 |
<?php
|
458 |
}
|
459 |
|
|
|
460 |
/**
|
461 |
* This method is used to display block for Stripe webhook url.
|
462 |
*
|
@@ -1264,10 +1274,8 @@ class Admin_Controller {
|
|
1264 |
* @return array $settings_tab Settings tabs array returned.
|
1265 |
*/
|
1266 |
public function add_settings_links( $settings_tab ) {
|
1267 |
-
if ( isset( $_GET['section'] ) &&
|
1268 |
-
$settings_tab
|
1269 |
-
$settings_tab['cpsw_stripe'] = __( 'Credit Cards', 'checkout-plugins-stripe-woo' );
|
1270 |
-
$settings_tab['cpsw_express_checkout'] = __( 'Express Checkout', 'checkout-plugins-stripe-woo' );
|
1271 |
}
|
1272 |
array_shift( $settings_tab );
|
1273 |
return apply_filters( 'cpsw_setting_tabs', $settings_tab );
|
@@ -1335,12 +1343,13 @@ class Admin_Controller {
|
|
1335 |
],
|
1336 |
];
|
1337 |
} else {
|
|
|
1338 |
$settings = [
|
1339 |
'section_title' => [
|
1340 |
'name' => __( 'Express Checkout', 'checkout-plugins-stripe-woo' ),
|
1341 |
'type' => 'title',
|
1342 |
/* translators: HTML Markup*/
|
1343 |
-
'desc' => sprintf( __( 'Accept payment using Apple Pay, Google Pay, Browser Payment Method.%1$1sExpress
|
1344 |
'id' => 'cpsw_express_checkout',
|
1345 |
],
|
1346 |
'enable' => [
|
@@ -1354,7 +1363,7 @@ class Admin_Controller {
|
|
1354 |
'type' => 'multiselect',
|
1355 |
'class' => 'cpsw_express_checkout_location',
|
1356 |
'id' => 'cpsw_express_checkout_location',
|
1357 |
-
'desc_tip' => __( 'Choose page to display
|
1358 |
'options' => [
|
1359 |
'product' => __( 'Product', 'checkout-plugins-stripe-woo' ),
|
1360 |
'cart' => __( 'Cart', 'checkout-plugins-stripe-woo' ),
|
@@ -1366,7 +1375,7 @@ class Admin_Controller {
|
|
1366 |
'title' => __( 'Button type', 'checkout-plugins-stripe-woo' ),
|
1367 |
'type' => 'select',
|
1368 |
'id' => 'cpsw_express_checkout_button_type',
|
1369 |
-
'desc' => __( 'Select label for
|
1370 |
'value' => $values['express_checkout_button_type'],
|
1371 |
'options' => [
|
1372 |
'default' => __( 'Default', 'checkout-plugins-stripe-woo' ),
|
@@ -1380,7 +1389,7 @@ class Admin_Controller {
|
|
1380 |
'title' => __( 'Button theme', 'checkout-plugins-stripe-woo' ),
|
1381 |
'type' => 'select',
|
1382 |
'id' => 'cpsw_express_checkout_button_theme',
|
1383 |
-
'desc' => __( 'Select theme for
|
1384 |
'value' => $values['express_checkout_button_theme'],
|
1385 |
'options' => [
|
1386 |
'dark' => __( 'Dark', 'checkout-plugins-stripe-woo' ),
|
@@ -1393,7 +1402,7 @@ class Admin_Controller {
|
|
1393 |
'title' => __( 'Button height', 'checkout-plugins-stripe-woo' ),
|
1394 |
'type' => 'number',
|
1395 |
'id' => 'cpsw_express_checkout_button_height',
|
1396 |
-
'desc' => __( 'Select height for
|
1397 |
'value' => $values['express_checkout_button_height'],
|
1398 |
'desc_tip' => true,
|
1399 |
],
|
@@ -1401,7 +1410,7 @@ class Admin_Controller {
|
|
1401 |
'title' => __( 'Separator text', 'checkout-plugins-stripe-woo' ),
|
1402 |
'type' => 'text',
|
1403 |
'id' => 'cpsw_express_checkout_separator',
|
1404 |
-
'desc' => __( 'Add
|
1405 |
'value' => $values['express_checkout_separator'],
|
1406 |
'desc_tip' => true,
|
1407 |
],
|
@@ -1420,11 +1429,18 @@ class Admin_Controller {
|
|
1420 |
'desc' => __( 'Advanced customization options for product page.', 'checkout-plugins-stripe-woo' ),
|
1421 |
'id' => 'cpsw_express_checkout_product_page',
|
1422 |
],
|
1423 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
1424 |
'title' => __( 'Button position', 'checkout-plugins-stripe-woo' ),
|
1425 |
'type' => 'select',
|
1426 |
'id' => 'cpsw_express_checkout_product_page_position',
|
1427 |
-
'
|
|
|
1428 |
'value' => $values['express_checkout_product_page_position'],
|
1429 |
'options' => [
|
1430 |
'above' => __( 'Above Add to Cart', 'checkout-plugins-stripe-woo' ),
|
@@ -1432,10 +1448,20 @@ class Admin_Controller {
|
|
1432 |
],
|
1433 |
'desc_tip' => true,
|
1434 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1435 |
'sticky_footer' => [
|
1436 |
'name' => __( 'Responsive behaviour', 'checkout-plugins-stripe-woo' ),
|
1437 |
/* translators: HTML Markup*/
|
1438 |
-
'desc' => sprintf( __( 'If checked the
|
|
|
1439 |
'type' => 'checkbox',
|
1440 |
'id' => 'cpsw_express_checkout_product_sticky_footer',
|
1441 |
'value' => $values['express_checkout_product_sticky_footer'],
|
@@ -1447,7 +1473,7 @@ class Admin_Controller {
|
|
1447 |
'checkout_page_section_title' => [
|
1448 |
'name' => __( 'Checkout page options', 'checkout-plugins-stripe-woo' ),
|
1449 |
'type' => 'title',
|
1450 |
-
'desc' => __( 'Advanced customization options for
|
1451 |
'id' => 'cpsw_express_checkout_product_page',
|
1452 |
],
|
1453 |
'checkout_page_options' => [
|
@@ -1456,12 +1482,25 @@ class Admin_Controller {
|
|
1456 |
'id' => 'cpsw_express_checkout_product_checkout_page',
|
1457 |
'value' => $values['express_checkout_product_checkout_page'],
|
1458 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1459 |
'title' => [
|
1460 |
'title' => __( 'Title', 'checkout-plugins-stripe-woo' ),
|
1461 |
'type' => 'text',
|
1462 |
'class' => 'cpsw_checkout_options',
|
1463 |
'id' => 'cpsw_express_checkout_title',
|
1464 |
-
'desc' => __( 'Add a title above
|
1465 |
'value' => $values['express_checkout_title'],
|
1466 |
'desc_tip' => true,
|
1467 |
],
|
@@ -1470,7 +1509,7 @@ class Admin_Controller {
|
|
1470 |
'type' => 'text',
|
1471 |
'class' => 'cpsw_checkout_options',
|
1472 |
'id' => 'cpsw_express_checkout_tagline',
|
1473 |
-
'desc' => __( 'Add a tagline
|
1474 |
'value' => $values['express_checkout_tagline'],
|
1475 |
'desc_tip' => true,
|
1476 |
],
|
@@ -1488,7 +1527,7 @@ class Admin_Controller {
|
|
1488 |
'type' => 'select',
|
1489 |
'class' => 'cpsw_checkout_options',
|
1490 |
'id' => 'cpsw_express_checkout_button_alignment',
|
1491 |
-
'desc' => __( 'This setting will align title, tagline and button based on selection on
|
1492 |
'value' => $values['express_checkout_button_alignment'],
|
1493 |
'options' => [
|
1494 |
'left' => __( 'Left', 'checkout-plugins-stripe-woo' ),
|
@@ -1502,7 +1541,7 @@ class Admin_Controller {
|
|
1502 |
'type' => 'text',
|
1503 |
'class' => 'cpsw_checkout_options',
|
1504 |
'id' => 'cpsw_express_checkout_separator_checkout',
|
1505 |
-
'desc' => __( 'Add separator text for
|
1506 |
'value' => $values['express_checkout_separator_checkout'],
|
1507 |
'desc_tip' => true,
|
1508 |
],
|
77 |
'cpsw_api_settings' => __( 'Stripe API Settings', 'checkout-plugins-stripe-woo' ),
|
78 |
'cpsw_stripe' => __( 'Credit Cards', 'checkout-plugins-stripe-woo' ),
|
79 |
'cpsw_express_checkout' => __( 'Express Checkout', 'checkout-plugins-stripe-woo' ),
|
80 |
+
'cpsw_alipay' => __( 'Alipay', 'checkout-plugins-stripe-woo' ),
|
81 |
+
'cpsw_ideal' => __( 'iDEAL', 'checkout-plugins-stripe-woo' ),
|
82 |
];
|
83 |
|
84 |
}
|
108 |
add_action( 'wp_ajax_cpsw_test_stripe_connection', [ $this, 'connection_test' ] );
|
109 |
add_action( 'wp_ajax_cpsw_disconnect_account', [ $this, 'disconnect_account' ] );
|
110 |
add_action( 'wp_ajax_cpsw_js_errors', [ $this, 'js_errors' ] );
|
111 |
+
add_action( 'wp_ajax_nopriv_cpsw_js_errors', [ $this, 'js_errors' ] );
|
112 |
|
113 |
add_action( 'woocommerce_settings_save_cpsw_api_settings', [ $this, 'check_connection_on_updates' ] );
|
114 |
add_filter( 'woocommerce_save_settings_checkout_cpsw_express_checkout', [ $this, 'cpsw_express_checkout_option_updates' ] );
|
135 |
$express_checkout = [];
|
136 |
$radio_checkbox = [
|
137 |
'express_checkout_enabled' => 'no',
|
138 |
+
'express_checkout_product_options' => 'no',
|
139 |
'express_checkout_product_sticky_footer' => 'no',
|
140 |
'express_checkout_product_checkout_page' => 'no',
|
141 |
];
|
158 |
}
|
159 |
|
160 |
if ( ! empty( $express_checkout ) ) {
|
161 |
+
$cpsw_stripe = get_option( 'woocommerce_cpsw_stripe_settings' );
|
162 |
+
$cpsw_stripe['express_checkout_location'] = [];
|
163 |
+
$cpsw_stripe = array_merge( $cpsw_stripe, $radio_checkbox, $express_checkout );
|
164 |
update_option( 'woocommerce_cpsw_stripe_settings', $cpsw_stripe );
|
165 |
}
|
166 |
}
|
201 |
* @since 0.0.1
|
202 |
*/
|
203 |
public function enqueue_scripts() {
|
204 |
+
$version = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? time() : CPSW_VERSION;
|
205 |
+
$allow_scripts_methods = [ 'cpsw_stripe', 'cpsw_alipay', 'cpsw_ideal' ];
|
206 |
|
207 |
+
if ( isset( $_GET['page'] ) && 'wc-settings' === $_GET['page'] && isset( $_GET['tab'] ) && ( 'cpsw_api_settings' === $_GET['tab'] || isset( $_GET['section'] ) && ( in_array( sanitize_text_field( $_GET['section'] ), $allow_scripts_methods, true ) ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
208 |
+
|
209 |
+
wp_register_style( 'cpsw-admin-style', plugins_url( 'assets/css/admin.css', __FILE__ ), [], $version, 'all' );
|
210 |
wp_enqueue_style( 'cpsw-admin-style' );
|
211 |
|
212 |
+
wp_register_script( 'cpsw-admin-js', plugins_url( 'assets/js/admin.js', __FILE__ ), [ 'jquery' ], $version, true );
|
213 |
wp_enqueue_script( 'cpsw-admin-js' );
|
214 |
|
215 |
wp_localize_script(
|
231 |
'is_connected' => $this->is_stripe_connected(),
|
232 |
'is_manually_connected' => isset( $_GET['connect'] ) ? sanitize_text_field( $_GET['connect'] ) : '', //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
233 |
'cpsw_admin_settings_tab' => isset( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : '', //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
234 |
+
'cpsw_admin_current_page' => isset( $_GET['section'] ) ? sanitize_text_field( $_GET['section'] ) : '', //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
235 |
]
|
236 |
);
|
237 |
}
|
238 |
|
239 |
if ( isset( $_GET['page'] ) && 'wc-settings' === $_GET['page'] && isset( $_GET['tab'] ) && 'checkout' === $_GET['tab'] && isset( $_GET['section'] ) && 'cpsw_express_checkout' === $_GET['section'] ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
240 |
+
wp_register_style( 'cpsw-express-checkout-style', plugins_url( 'assets/css/express-checkout.css', __FILE__ ), [], $version, 'all' );
|
241 |
wp_enqueue_style( 'cpsw-express-checkout-style' );
|
242 |
|
243 |
+
wp_register_script( 'cpsw-stripe-external', 'https://js.stripe.com/v3/', [], $version, true );
|
244 |
wp_enqueue_script( 'cpsw-stripe-external' );
|
245 |
|
246 |
+
wp_register_script( 'cpsw-express-checkout-js', plugins_url( 'assets/js/express-checkout.js', __FILE__ ), [ 'jquery', 'cpsw-stripe-external' ], $version, true );
|
247 |
wp_enqueue_script( 'cpsw-express-checkout-js' );
|
248 |
|
249 |
$public_key = ( 'live' === Helper::get_payment_mode() ) ? Helper::get_setting( 'cpsw_pub_key' ) : Helper::get_setting( 'cpsw_test_pub_key' );
|
466 |
<?php
|
467 |
}
|
468 |
|
469 |
+
|
470 |
/**
|
471 |
* This method is used to display block for Stripe webhook url.
|
472 |
*
|
1274 |
* @return array $settings_tab Settings tabs array returned.
|
1275 |
*/
|
1276 |
public function add_settings_links( $settings_tab ) {
|
1277 |
+
if ( isset( $_GET['section'] ) && 0 === strpos( $_GET['section'], 'cpsw_' ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
1278 |
+
$settings_tab = array_merge( $settings_tab, $this->navigation );
|
|
|
|
|
1279 |
}
|
1280 |
array_shift( $settings_tab );
|
1281 |
return apply_filters( 'cpsw_setting_tabs', $settings_tab );
|
1343 |
],
|
1344 |
];
|
1345 |
} else {
|
1346 |
+
// Default values need to be set in Helper class.
|
1347 |
$settings = [
|
1348 |
'section_title' => [
|
1349 |
'name' => __( 'Express Checkout', 'checkout-plugins-stripe-woo' ),
|
1350 |
'type' => 'title',
|
1351 |
/* translators: HTML Markup*/
|
1352 |
+
'desc' => sprintf( __( 'Accept payment using Apple Pay, Google Pay, Browser Payment Method.%1$1sExpress Checkout uses Payment Request API which is based on client\'s browser and saved cards.%1$1sPlease check %2$2sprerequisite%3$3s for Apple Pay, Google Pay and Browser Payment Method.', 'checkout-plugins-stripe-woo' ), '<br/>', '<a href="https://stripe.com/docs/stripe-js/elements/payment-request-button#html-js-testing" target="_blank">', '</a>' ),
|
1353 |
'id' => 'cpsw_express_checkout',
|
1354 |
],
|
1355 |
'enable' => [
|
1363 |
'type' => 'multiselect',
|
1364 |
'class' => 'cpsw_express_checkout_location',
|
1365 |
'id' => 'cpsw_express_checkout_location',
|
1366 |
+
'desc_tip' => __( 'Choose page to display Express Checkout buttons.', 'checkout-plugins-stripe-woo' ),
|
1367 |
'options' => [
|
1368 |
'product' => __( 'Product', 'checkout-plugins-stripe-woo' ),
|
1369 |
'cart' => __( 'Cart', 'checkout-plugins-stripe-woo' ),
|
1375 |
'title' => __( 'Button type', 'checkout-plugins-stripe-woo' ),
|
1376 |
'type' => 'select',
|
1377 |
'id' => 'cpsw_express_checkout_button_type',
|
1378 |
+
'desc' => __( 'Select label for Express Checkout button. Unfortunately, we can\'t customize the label because of the restrictions from Stripe.', 'checkout-plugins-stripe-woo' ),
|
1379 |
'value' => $values['express_checkout_button_type'],
|
1380 |
'options' => [
|
1381 |
'default' => __( 'Default', 'checkout-plugins-stripe-woo' ),
|
1389 |
'title' => __( 'Button theme', 'checkout-plugins-stripe-woo' ),
|
1390 |
'type' => 'select',
|
1391 |
'id' => 'cpsw_express_checkout_button_theme',
|
1392 |
+
'desc' => __( 'Select theme for Express Checkout button.', 'checkout-plugins-stripe-woo' ),
|
1393 |
'value' => $values['express_checkout_button_theme'],
|
1394 |
'options' => [
|
1395 |
'dark' => __( 'Dark', 'checkout-plugins-stripe-woo' ),
|
1402 |
'title' => __( 'Button height', 'checkout-plugins-stripe-woo' ),
|
1403 |
'type' => 'number',
|
1404 |
'id' => 'cpsw_express_checkout_button_height',
|
1405 |
+
'desc' => __( 'Select height for Express Checkout button (in px). Button height can be between 35px to 60px. Default height 40px.', 'checkout-plugins-stripe-woo' ),
|
1406 |
'value' => $values['express_checkout_button_height'],
|
1407 |
'desc_tip' => true,
|
1408 |
],
|
1410 |
'title' => __( 'Separator text', 'checkout-plugins-stripe-woo' ),
|
1411 |
'type' => 'text',
|
1412 |
'id' => 'cpsw_express_checkout_separator',
|
1413 |
+
'desc' => __( 'Add separator text for the Express Checkout button. This will help to distinguish between Express Checkout and other buttons.', 'checkout-plugins-stripe-woo' ),
|
1414 |
'value' => $values['express_checkout_separator'],
|
1415 |
'desc_tip' => true,
|
1416 |
],
|
1429 |
'desc' => __( 'Advanced customization options for product page.', 'checkout-plugins-stripe-woo' ),
|
1430 |
'id' => 'cpsw_express_checkout_product_page',
|
1431 |
],
|
1432 |
+
'product_page_options' => [
|
1433 |
+
'title' => __( 'Advanced options', 'checkout-plugins-stripe-woo' ),
|
1434 |
+
'type' => 'checkbox',
|
1435 |
+
'id' => 'cpsw_express_checkout_product_options',
|
1436 |
+
'value' => $values['express_checkout_product_options'],
|
1437 |
+
],
|
1438 |
+
'product_button_position' => [
|
1439 |
'title' => __( 'Button position', 'checkout-plugins-stripe-woo' ),
|
1440 |
'type' => 'select',
|
1441 |
'id' => 'cpsw_express_checkout_product_page_position',
|
1442 |
+
'class' => 'cpsw_product_options',
|
1443 |
+
'desc' => __( 'Select the position of Express Checkout button. This option will work only for Product page.', 'checkout-plugins-stripe-woo' ),
|
1444 |
'value' => $values['express_checkout_product_page_position'],
|
1445 |
'options' => [
|
1446 |
'above' => __( 'Above Add to Cart', 'checkout-plugins-stripe-woo' ),
|
1448 |
],
|
1449 |
'desc_tip' => true,
|
1450 |
],
|
1451 |
+
'product_button_width' => [
|
1452 |
+
'title' => __( 'Button width', 'checkout-plugins-stripe-woo' ),
|
1453 |
+
'type' => 'number',
|
1454 |
+
'class' => 'cpsw_product_options',
|
1455 |
+
'id' => 'cpsw_express_checkout_product_button_width',
|
1456 |
+
'desc' => __( 'Select width for button (in px). Minimum width should be 150px, Default width 100%', 'checkout-plugins-stripe-woo' ),
|
1457 |
+
'value' => $values['express_checkout_product_button_width'],
|
1458 |
+
'desc_tip' => true,
|
1459 |
+
],
|
1460 |
'sticky_footer' => [
|
1461 |
'name' => __( 'Responsive behaviour', 'checkout-plugins-stripe-woo' ),
|
1462 |
/* translators: HTML Markup*/
|
1463 |
+
'desc' => sprintf( __( 'If checked the Express Checkout button will stick%1$1sat bottom of screen on responsive devices.', 'checkout-plugins-stripe-woo' ), '<br/>' ),
|
1464 |
+
'class' => 'cpsw_product_options',
|
1465 |
'type' => 'checkbox',
|
1466 |
'id' => 'cpsw_express_checkout_product_sticky_footer',
|
1467 |
'value' => $values['express_checkout_product_sticky_footer'],
|
1473 |
'checkout_page_section_title' => [
|
1474 |
'name' => __( 'Checkout page options', 'checkout-plugins-stripe-woo' ),
|
1475 |
'type' => 'title',
|
1476 |
+
'desc' => __( 'Advanced customization options for Checkout page.', 'checkout-plugins-stripe-woo' ),
|
1477 |
'id' => 'cpsw_express_checkout_product_page',
|
1478 |
],
|
1479 |
'checkout_page_options' => [
|
1482 |
'id' => 'cpsw_express_checkout_product_checkout_page',
|
1483 |
'value' => $values['express_checkout_product_checkout_page'],
|
1484 |
],
|
1485 |
+
'checkout_button_position' => [
|
1486 |
+
'title' => __( 'Button position', 'checkout-plugins-stripe-woo' ),
|
1487 |
+
'type' => 'select',
|
1488 |
+
'class' => 'cpsw_checkout_options',
|
1489 |
+
'id' => 'cpsw_express_checkout_checkout_page_position',
|
1490 |
+
'desc' => __( 'Select the position of Express Checkout button. This option will work only for Checkout page.', 'checkout-plugins-stripe-woo' ),
|
1491 |
+
'value' => $values['express_checkout_checkout_page_position'],
|
1492 |
+
'options' => [
|
1493 |
+
'above-checkout' => __( 'Above checkout form', 'checkout-plugins-stripe-woo' ),
|
1494 |
+
'above-billing' => __( 'Above billing details', 'checkout-plugins-stripe-woo' ),
|
1495 |
+
],
|
1496 |
+
'desc_tip' => true,
|
1497 |
+
],
|
1498 |
'title' => [
|
1499 |
'title' => __( 'Title', 'checkout-plugins-stripe-woo' ),
|
1500 |
'type' => 'text',
|
1501 |
'class' => 'cpsw_checkout_options',
|
1502 |
'id' => 'cpsw_express_checkout_title',
|
1503 |
+
'desc' => __( 'Add a title above Express Checkout button on Checkout page.', 'checkout-plugins-stripe-woo' ),
|
1504 |
'value' => $values['express_checkout_title'],
|
1505 |
'desc_tip' => true,
|
1506 |
],
|
1509 |
'type' => 'text',
|
1510 |
'class' => 'cpsw_checkout_options',
|
1511 |
'id' => 'cpsw_express_checkout_tagline',
|
1512 |
+
'desc' => __( 'Add a tagline below the title on Checkout page.', 'checkout-plugins-stripe-woo' ),
|
1513 |
'value' => $values['express_checkout_tagline'],
|
1514 |
'desc_tip' => true,
|
1515 |
],
|
1527 |
'type' => 'select',
|
1528 |
'class' => 'cpsw_checkout_options',
|
1529 |
'id' => 'cpsw_express_checkout_button_alignment',
|
1530 |
+
'desc' => __( 'This setting will align title, tagline and button based on selection on Checkout page.', 'checkout-plugins-stripe-woo' ),
|
1531 |
'value' => $values['express_checkout_button_alignment'],
|
1532 |
'options' => [
|
1533 |
'left' => __( 'Left', 'checkout-plugins-stripe-woo' ),
|
1541 |
'type' => 'text',
|
1542 |
'class' => 'cpsw_checkout_options',
|
1543 |
'id' => 'cpsw_express_checkout_separator_checkout',
|
1544 |
+
'desc' => __( 'Add separator text for Checkout page. If empty will show default separator text.', 'checkout-plugins-stripe-woo' ),
|
1545 |
'value' => $values['express_checkout_separator_checkout'],
|
1546 |
'desc_tip' => true,
|
1547 |
],
|
admin/assets/css/express-checkout.css
CHANGED
@@ -5,9 +5,6 @@
|
|
5 |
|
6 |
.cpsw_floating_preview {
|
7 |
width: 400px;
|
8 |
-
position: fixed;
|
9 |
-
left: 900px;
|
10 |
-
top: 300px;
|
11 |
}
|
12 |
|
13 |
.cpsw_express_checkout_preview {
|
@@ -21,7 +18,6 @@
|
|
21 |
}
|
22 |
|
23 |
.cpsw_preview_tagline {
|
24 |
-
font-style: italic;
|
25 |
margin-bottom: 1em;
|
26 |
}
|
27 |
|
5 |
|
6 |
.cpsw_floating_preview {
|
7 |
width: 400px;
|
|
|
|
|
|
|
8 |
}
|
9 |
|
10 |
.cpsw_express_checkout_preview {
|
18 |
}
|
19 |
|
20 |
.cpsw_preview_tagline {
|
|
|
21 |
margin-bottom: 1em;
|
22 |
}
|
23 |
|
admin/assets/js/admin.js
CHANGED
@@ -193,4 +193,67 @@
|
|
193 |
$( document ).ready( function() {
|
194 |
$( '.cpsw_select_woo' ).selectWoo();
|
195 |
} );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
}( jQuery ) );
|
193 |
$( document ).ready( function() {
|
194 |
$( '.cpsw_select_woo' ).selectWoo();
|
195 |
} );
|
196 |
+
|
197 |
+
const CPSWAdminPaymentSettings = {
|
198 |
+
init() {
|
199 |
+
$( '[name^="woocommerce_' + cpsw_ajax_object.cpsw_admin_current_page + '_allowed_countries"]' ).on( 'change', this.display_children );
|
200 |
+
$( '[name^="cpsw_mode"]' ).on( 'change', this.show_hide_webhook_secret );
|
201 |
+
|
202 |
+
this.display_children();
|
203 |
+
this.show_hide_webhook_secret();
|
204 |
+
},
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Show hide webhook secret
|
208 |
+
*/
|
209 |
+
show_hide_webhook_secret() {
|
210 |
+
const mode = $( '#cpsw_mode' ).val();
|
211 |
+
|
212 |
+
if ( 'test' === mode ) {
|
213 |
+
$( '#cpsw_test_webhook_secret' ).parents( 'tr' ).show();
|
214 |
+
$( '#cpsw_live_webhook_secret' ).parents( 'tr' ).hide();
|
215 |
+
} else if ( 'live' === mode ) {
|
216 |
+
$( '#cpsw_test_webhook_secret' ).parents( 'tr' ).hide();
|
217 |
+
$( '#cpsw_live_webhook_secret' ).parents( 'tr' ).show();
|
218 |
+
}
|
219 |
+
},
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Show hide country dorpdown
|
223 |
+
*/
|
224 |
+
display_children() {
|
225 |
+
$( '[data-show-if]' ).each( function( i, el ) {
|
226 |
+
const $this = $( el );
|
227 |
+
const values = $this.data( 'show-if' );
|
228 |
+
const hidden = [];
|
229 |
+
$.each( values, function( k, v ) {
|
230 |
+
const $key = $( '#woocommerce_' + cpsw_ajax_object.cpsw_admin_current_page + '_allowed_countries' );
|
231 |
+
if ( hidden.indexOf( $this.attr( 'id' ) ) === -1 ) {
|
232 |
+
if ( $key.is( ':checkbox' ) ) {
|
233 |
+
if ( $key.is( ':checked' ) === v ) {
|
234 |
+
$this.closest( 'tr' ).show();
|
235 |
+
} else {
|
236 |
+
$this.closest( 'tr' ).hide();
|
237 |
+
hidden.push( $this.attr( 'id' ) );
|
238 |
+
}
|
239 |
+
} else {
|
240 |
+
if ( $key.val() === v ) {
|
241 |
+
$this.closest( 'tr' ).show();
|
242 |
+
} else {
|
243 |
+
$this.closest( 'tr' ).hide();
|
244 |
+
hidden.push( $this.attr( 'id' ) );
|
245 |
+
}
|
246 |
+
}
|
247 |
+
} else {
|
248 |
+
$this.closest( 'tr' ).hide();
|
249 |
+
hidden.push( $this.attr( 'id' ) );
|
250 |
+
}
|
251 |
+
}.bind( this ) );
|
252 |
+
}.bind( this ) );
|
253 |
+
},
|
254 |
+
};
|
255 |
+
|
256 |
+
$( function() {
|
257 |
+
CPSWAdminPaymentSettings.init();
|
258 |
+
} );
|
259 |
}( jQuery ) );
|
admin/assets/js/express-checkout.js
CHANGED
@@ -44,12 +44,13 @@
|
|
44 |
|
45 |
if ( $( '.cpsw_express_checkout_preview_wrapper .cpsw_express_checkout_preview' ).length > 0 ) {
|
46 |
$( '.cpsw_button_preview_label' ).css( { display: 'block' } );
|
|
|
47 |
$( '.cpsw_express_checkout_preview_wrapper .cpsw_express_checkout_preview' ).fadeIn();
|
48 |
prButton.mount( '.cpsw_express_checkout_preview_wrapper .cpsw_express_checkout_preview' );
|
49 |
$( '.cpsw_preview_title' ).html( $( '#cpsw_express_checkout_title' ).val() );
|
50 |
$( '.cpsw_preview_tagline' ).html( $( '#cpsw_express_checkout_tagline' ).val() );
|
51 |
if ( $( '#cpsw_express_checkout_product_checkout_page' ).is( ':checked' ) ) {
|
52 |
-
const buttonWidth = $( '#cpsw_express_checkout_button_width' ).val() + 'px';
|
53 |
$( '.cpsw_express_checkout_preview' ).width( buttonWidth );
|
54 |
|
55 |
$( '.cpsw_express_checkout_preview_wrapper' ).css( { textAlign: $( '#cpsw_express_checkout_button_alignment' ).val() } );
|
@@ -68,8 +69,7 @@
|
|
68 |
function addCheckoutPreviewElement() {
|
69 |
removeCheckoutPreviewElement();
|
70 |
$( '.cpsw_express_checkout_preview_wrapper' ).prepend( '<h3 class="cpsw_preview_title"></h3><p class="cpsw_preview_tagline"></p>' );
|
71 |
-
$( '.cpsw_express_checkout_preview_wrapper' ).after( '<p class="cpsw_preview_notice">NOTE: Title and Tagline appears only on
|
72 |
-
$( '.cpsw_preview_notice' ).css( { display: 'block' } );
|
73 |
|
74 |
const buttonWidth = $( '#cpsw_express_checkout_button_width' ).val() + 'px';
|
75 |
$( '.cpsw_express_checkout_preview' ).width( buttonWidth );
|
@@ -87,18 +87,28 @@
|
|
87 |
$( '.cpsw_express_checkout_preview' ).css( { margin: '0 auto', float: 'none', width: '100%' } );
|
88 |
}
|
89 |
|
90 |
-
function
|
91 |
-
|
92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
$( this ).parents( 'tr' ).hide();
|
94 |
-
|
|
|
|
|
95 |
} );
|
96 |
} else {
|
97 |
-
$(
|
98 |
$( this ).parents( 'tr' ).show();
|
99 |
-
|
100 |
-
|
101 |
-
|
|
|
|
|
102 |
} );
|
103 |
}
|
104 |
}
|
@@ -137,10 +147,15 @@
|
|
137 |
generateExpressCheckoutDemo( style );
|
138 |
} );
|
139 |
|
140 |
-
|
|
|
141 |
|
142 |
$( '#cpsw_express_checkout_product_checkout_page' ).change( function() {
|
143 |
-
|
|
|
|
|
|
|
|
|
144 |
} );
|
145 |
|
146 |
if ( $( document ).width() > 1200 ) {
|
@@ -148,6 +163,36 @@
|
|
148 |
buttonPreview.parents( 'tr' ).hide();
|
149 |
$( '.submit' ).after( '<div class="cpsw_floating_preview"><span class="cpsw_button_preview_label">Button preview</div>' );
|
150 |
$( '.cpsw_floating_preview' ).append( buttonPreview );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
}
|
152 |
|
153 |
$( '#cpsw_express_checkout_title' ).keyup( function() {
|
@@ -158,13 +203,17 @@
|
|
158 |
$( '.cpsw_preview_tagline' ).html( $( this ).val() );
|
159 |
} );
|
160 |
|
161 |
-
$( '#cpsw_express_checkout_button_width' ).change( function() {
|
162 |
-
let buttonWidth = $(
|
163 |
-
if ( buttonWidth < 150 ) {
|
164 |
-
$(
|
165 |
buttonWidth = 150;
|
166 |
alert( 'Express Checkout button width should not be less than 150px' );
|
167 |
}
|
|
|
|
|
|
|
|
|
168 |
$( '.cpsw_express_checkout_preview' ).width( buttonWidth );
|
169 |
} );
|
170 |
|
44 |
|
45 |
if ( $( '.cpsw_express_checkout_preview_wrapper .cpsw_express_checkout_preview' ).length > 0 ) {
|
46 |
$( '.cpsw_button_preview_label' ).css( { display: 'block' } );
|
47 |
+
$( '.cpsw_preview_notice' ).css( { display: 'block' } );
|
48 |
$( '.cpsw_express_checkout_preview_wrapper .cpsw_express_checkout_preview' ).fadeIn();
|
49 |
prButton.mount( '.cpsw_express_checkout_preview_wrapper .cpsw_express_checkout_preview' );
|
50 |
$( '.cpsw_preview_title' ).html( $( '#cpsw_express_checkout_title' ).val() );
|
51 |
$( '.cpsw_preview_tagline' ).html( $( '#cpsw_express_checkout_tagline' ).val() );
|
52 |
if ( $( '#cpsw_express_checkout_product_checkout_page' ).is( ':checked' ) ) {
|
53 |
+
const buttonWidth = $( '#cpsw_express_checkout_button_width' ).val() ? $( '#cpsw_express_checkout_button_width' ).val() + 'px' : '100%';
|
54 |
$( '.cpsw_express_checkout_preview' ).width( buttonWidth );
|
55 |
|
56 |
$( '.cpsw_express_checkout_preview_wrapper' ).css( { textAlign: $( '#cpsw_express_checkout_button_alignment' ).val() } );
|
69 |
function addCheckoutPreviewElement() {
|
70 |
removeCheckoutPreviewElement();
|
71 |
$( '.cpsw_express_checkout_preview_wrapper' ).prepend( '<h3 class="cpsw_preview_title"></h3><p class="cpsw_preview_tagline"></p>' );
|
72 |
+
$( '.cpsw_express_checkout_preview_wrapper' ).after( '<p class="cpsw_preview_notice">NOTE: Title and Tagline appears only on Checkout page.</p>' );
|
|
|
73 |
|
74 |
const buttonWidth = $( '#cpsw_express_checkout_button_width' ).val() + 'px';
|
75 |
$( '.cpsw_express_checkout_preview' ).width( buttonWidth );
|
87 |
$( '.cpsw_express_checkout_preview' ).css( { margin: '0 auto', float: 'none', width: '100%' } );
|
88 |
}
|
89 |
|
90 |
+
function toggleOptions( page = 'checkout' ) {
|
91 |
+
let handler = '#cpsw_express_checkout_product_checkout_page';
|
92 |
+
let options = '.cpsw_checkout_options';
|
93 |
+
if ( 'product' === page ) {
|
94 |
+
handler = '#cpsw_express_checkout_product_options';
|
95 |
+
options = '.cpsw_product_options';
|
96 |
+
}
|
97 |
+
if ( ! $( handler ).is( ':checked' ) ) {
|
98 |
+
$( options ).each( function() {
|
99 |
$( this ).parents( 'tr' ).hide();
|
100 |
+
if ( 'checkout' === page ) {
|
101 |
+
removeCheckoutPreviewElement();
|
102 |
+
}
|
103 |
} );
|
104 |
} else {
|
105 |
+
$( options ).each( function() {
|
106 |
$( this ).parents( 'tr' ).show();
|
107 |
+
if ( 'checkout' === page ) {
|
108 |
+
addCheckoutPreviewElement();
|
109 |
+
$( '#cpsw_express_checkout_title' ).trigger( 'keyup' );
|
110 |
+
$( '#cpsw_express_checkout_tagline' ).trigger( 'keyup' );
|
111 |
+
}
|
112 |
} );
|
113 |
}
|
114 |
}
|
147 |
generateExpressCheckoutDemo( style );
|
148 |
} );
|
149 |
|
150 |
+
toggleOptions();
|
151 |
+
toggleOptions( 'product' );
|
152 |
|
153 |
$( '#cpsw_express_checkout_product_checkout_page' ).change( function() {
|
154 |
+
toggleOptions();
|
155 |
+
} );
|
156 |
+
|
157 |
+
$( '#cpsw_express_checkout_product_options' ).change( function() {
|
158 |
+
toggleOptions( 'product' );
|
159 |
} );
|
160 |
|
161 |
if ( $( document ).width() > 1200 ) {
|
163 |
buttonPreview.parents( 'tr' ).hide();
|
164 |
$( '.submit' ).after( '<div class="cpsw_floating_preview"><span class="cpsw_button_preview_label">Button preview</div>' );
|
165 |
$( '.cpsw_floating_preview' ).append( buttonPreview );
|
166 |
+
|
167 |
+
const maxTop = $( '#cpsw_express_checkout-description' ).offset().top;
|
168 |
+
const absoluteLeft = 900 - jQuery( '#adminmenuwrap' ).width();
|
169 |
+
$( '.cpsw_floating_preview' ).css(
|
170 |
+
{
|
171 |
+
position: 'absolute',
|
172 |
+
top: maxTop,
|
173 |
+
left: absoluteLeft,
|
174 |
+
},
|
175 |
+
);
|
176 |
+
|
177 |
+
$( window ).scroll( function() {
|
178 |
+
if ( maxTop - 110 < $( window ).scrollTop() ) {
|
179 |
+
$( '.cpsw_floating_preview' ).css(
|
180 |
+
{
|
181 |
+
position: 'fixed',
|
182 |
+
top: '200px',
|
183 |
+
left: 900,
|
184 |
+
},
|
185 |
+
);
|
186 |
+
} else {
|
187 |
+
$( '.cpsw_floating_preview' ).css(
|
188 |
+
{
|
189 |
+
position: 'absolute',
|
190 |
+
top: maxTop,
|
191 |
+
left: absoluteLeft,
|
192 |
+
},
|
193 |
+
);
|
194 |
+
}
|
195 |
+
} );
|
196 |
}
|
197 |
|
198 |
$( '#cpsw_express_checkout_title' ).keyup( function() {
|
203 |
$( '.cpsw_preview_tagline' ).html( $( this ).val() );
|
204 |
} );
|
205 |
|
206 |
+
$( '#cpsw_express_checkout_button_width, #cpsw_express_checkout_product_button_width' ).change( function() {
|
207 |
+
let buttonWidth = $( this ).val();
|
208 |
+
if ( buttonWidth < 150 && buttonWidth !== '' ) {
|
209 |
+
$( this ).val( 150 );
|
210 |
buttonWidth = 150;
|
211 |
alert( 'Express Checkout button width should not be less than 150px' );
|
212 |
}
|
213 |
+
|
214 |
+
if ( '' === buttonWidth ) {
|
215 |
+
buttonWidth = '100%';
|
216 |
+
}
|
217 |
$( '.cpsw_express_checkout_preview' ).width( buttonWidth );
|
218 |
} );
|
219 |
|
assets/css/stripe-elements.css
CHANGED
@@ -1,7 +1,8 @@
|
|
1 |
.cpsw-stripe-error,
|
2 |
.cpsw-number-error,
|
3 |
.cpsw-expiry-error,
|
4 |
-
.cpsw-cvc-error
|
|
|
5 |
padding-top: 3px;
|
6 |
font-weight: 500;
|
7 |
color: #f00;
|
@@ -34,6 +35,10 @@
|
|
34 |
cursor: not-allowed;
|
35 |
}
|
36 |
|
|
|
|
|
|
|
|
|
37 |
#cpsw-payment-request-button {
|
38 |
max-width: 100%;
|
39 |
border-radius: 3px;
|
@@ -43,8 +48,6 @@
|
|
43 |
#cpsw-payment-request-wrapper {
|
44 |
clear: both;
|
45 |
display: none;
|
46 |
-
|
47 |
-
/* padding-top: 1em; */
|
48 |
}
|
49 |
|
50 |
#cpsw-payment-request-wrapper.checkout.center #cpsw-payment-request-title,
|
@@ -82,6 +85,10 @@
|
|
82 |
display: none;
|
83 |
}
|
84 |
|
|
|
|
|
|
|
|
|
85 |
#cpsw-payment-request-wrapper.checkout #cpsw-payment-request-title {
|
86 |
font-weight: 600;
|
87 |
margin-bottom: 0.5em;
|
@@ -92,10 +99,14 @@
|
|
92 |
}
|
93 |
|
94 |
#cpsw-payment-request-wrapper.checkout #cpsw-payment-request-tagline {
|
95 |
-
font-style: italic;
|
96 |
margin-bottom: 1em;
|
97 |
}
|
98 |
|
|
|
|
|
|
|
|
|
|
|
99 |
#cpsw-payment-request-wrapper.product #cpsw-payment-request-title,
|
100 |
#cpsw-payment-request-wrapper.cart #cpsw-payment-request-title {
|
101 |
display: none;
|
@@ -108,19 +119,27 @@
|
|
108 |
|
109 |
@media only screen and (max-width: 600px) {
|
110 |
|
|
|
|
|
|
|
|
|
111 |
#cpsw-payment-request-wrapper.product.sticky {
|
112 |
position: fixed;
|
113 |
bottom: 0;
|
114 |
left: 0;
|
115 |
z-index: 1000000;
|
116 |
clear: both;
|
117 |
-
padding:
|
118 |
border: none;
|
119 |
-
width: 100
|
120 |
margin: 0;
|
121 |
background-color: #88888880;
|
122 |
}
|
123 |
|
|
|
|
|
|
|
|
|
124 |
#cpsw-payment-request-wrapper.product #cpsw-payment-request-title {
|
125 |
display: none;
|
126 |
}
|
1 |
.cpsw-stripe-error,
|
2 |
.cpsw-number-error,
|
3 |
.cpsw-expiry-error,
|
4 |
+
.cpsw-cvc-error,
|
5 |
+
.cpsw_stripe_ideal_error {
|
6 |
padding-top: 3px;
|
7 |
font-weight: 500;
|
8 |
color: #f00;
|
35 |
cursor: not-allowed;
|
36 |
}
|
37 |
|
38 |
+
.cpsw_stripe_ideal_form .cpsw_stripe_ideal_select {
|
39 |
+
margin-top: 10px;
|
40 |
+
}
|
41 |
+
|
42 |
#cpsw-payment-request-button {
|
43 |
max-width: 100%;
|
44 |
border-radius: 3px;
|
48 |
#cpsw-payment-request-wrapper {
|
49 |
clear: both;
|
50 |
display: none;
|
|
|
|
|
51 |
}
|
52 |
|
53 |
#cpsw-payment-request-wrapper.checkout.center #cpsw-payment-request-title,
|
85 |
display: none;
|
86 |
}
|
87 |
|
88 |
+
#cpsw-payment-request-separator.product {
|
89 |
+
padding: 0.5em 0;
|
90 |
+
}
|
91 |
+
|
92 |
#cpsw-payment-request-wrapper.checkout #cpsw-payment-request-title {
|
93 |
font-weight: 600;
|
94 |
margin-bottom: 0.5em;
|
99 |
}
|
100 |
|
101 |
#cpsw-payment-request-wrapper.checkout #cpsw-payment-request-tagline {
|
|
|
102 |
margin-bottom: 1em;
|
103 |
}
|
104 |
|
105 |
+
#cpsw-payment-request-wrapper.product.above .cpsw-payment-request-button-wrapper {
|
106 |
+
display: block;
|
107 |
+
padding-top: 1.5em;
|
108 |
+
}
|
109 |
+
|
110 |
#cpsw-payment-request-wrapper.product #cpsw-payment-request-title,
|
111 |
#cpsw-payment-request-wrapper.cart #cpsw-payment-request-title {
|
112 |
display: none;
|
119 |
|
120 |
@media only screen and (max-width: 600px) {
|
121 |
|
122 |
+
#cpsw-payment-request-wrapper.product.above.sticky .cpsw-payment-request-button-wrapper {
|
123 |
+
padding-top: 0;
|
124 |
+
}
|
125 |
+
|
126 |
#cpsw-payment-request-wrapper.product.sticky {
|
127 |
position: fixed;
|
128 |
bottom: 0;
|
129 |
left: 0;
|
130 |
z-index: 1000000;
|
131 |
clear: both;
|
132 |
+
padding: 0.5em;
|
133 |
border: none;
|
134 |
+
width: 100% !important;
|
135 |
margin: 0;
|
136 |
background-color: #88888880;
|
137 |
}
|
138 |
|
139 |
+
#cpsw-payment-request-wrapper.product.sticky #cpsw-payment-request-separator {
|
140 |
+
display: none;
|
141 |
+
}
|
142 |
+
|
143 |
#cpsw-payment-request-wrapper.product #cpsw-payment-request-title {
|
144 |
display: none;
|
145 |
}
|
assets/icon/alipay.svg
ADDED
@@ -0,0 +1 @@
|
|
|
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>
|
assets/icon/ideal.svg
ADDED
@@ -0,0 +1 @@
|
|
|
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>
|
assets/js/payment-request.js
CHANGED
@@ -8,6 +8,8 @@
|
|
8 |
const style = cpsw_payment_request.style;
|
9 |
const jsNonce = cpsw_payment_request.nonce.js_nonce;
|
10 |
const endpoint = cpsw_payment_request.ajax_endpoint;
|
|
|
|
|
11 |
let smallScreen = true;
|
12 |
|
13 |
let requestType = '';
|
@@ -562,4 +564,22 @@
|
|
562 |
$( document.body ).on( 'updated_checkout', function() {
|
563 |
initializePaymentButton();
|
564 |
} );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
565 |
}( jQuery ) );
|
8 |
const style = cpsw_payment_request.style;
|
9 |
const jsNonce = cpsw_payment_request.nonce.js_nonce;
|
10 |
const endpoint = cpsw_payment_request.ajax_endpoint;
|
11 |
+
const isResponsive = cpsw_payment_request.is_responsive;
|
12 |
+
|
13 |
let smallScreen = true;
|
14 |
|
15 |
let requestType = '';
|
564 |
$( document.body ).on( 'updated_checkout', function() {
|
565 |
initializePaymentButton();
|
566 |
} );
|
567 |
+
|
568 |
+
// Responsive behaviour for product page.
|
569 |
+
$( window ).on( 'resize', function() {
|
570 |
+
if ( $( '#cpsw-payment-request-wrapper' ).hasClass( 'product' ) ) {
|
571 |
+
if ( $( document ).width() > 660 ) {
|
572 |
+
$( '#cpsw-payment-request-wrapper' ).removeClass( 'sticky' );
|
573 |
+
$( '#cpsw-payment-request-separator' ).show();
|
574 |
+
} else {
|
575 |
+
if ( 'no' === cpsw_payment_request.product_advanced_options ) {
|
576 |
+
return;
|
577 |
+
}
|
578 |
+
if ( 'yes' === isResponsive ) {
|
579 |
+
$( '#cpsw-payment-request-wrapper' ).addClass( 'sticky' );
|
580 |
+
$( '#cpsw-payment-request-separator' ).hide();
|
581 |
+
}
|
582 |
+
}
|
583 |
+
}
|
584 |
+
} );
|
585 |
}( jQuery ) );
|
assets/js/stripe-elements.js
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
( function( $ ) {
|
2 |
const pubKey = cpsw_global_settings.public_key;
|
3 |
const inlineCC = cpsw_global_settings.inline_cc;
|
4 |
-
const isSsl = cpsw_global_settings.is_ssl;
|
5 |
const mode = cpsw_global_settings.mode;
|
6 |
const ajaxUrl = cpsw_global_settings.ajax_url;
|
7 |
const jsNonce = cpsw_global_settings.js_nonce;
|
8 |
const allowedCards = cpsw_global_settings.allowed_cards;
|
9 |
const notAllowedString = cpsw_global_settings.not_allowed_string;
|
10 |
const defaultCards = cpsw_global_settings.default_cards;
|
|
|
11 |
|
12 |
-
if ( '' === pubKey || ( 'live' === mode && !
|
13 |
return;
|
14 |
}
|
15 |
|
@@ -22,7 +22,9 @@
|
|
22 |
let cardCvc = null;
|
23 |
let paymentForm = null;
|
24 |
let paymentMethod = '';
|
25 |
-
let isAllowedCard =
|
|
|
|
|
26 |
|
27 |
const style = {
|
28 |
base: {
|
@@ -115,6 +117,28 @@
|
|
115 |
} );
|
116 |
}
|
117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
function mountCard() {
|
119 |
$( '.cpsw-stripe-elements-form' ).show();
|
120 |
if ( 0 === $( '.cpsw-stripe-elements-form' ).length ) {
|
@@ -134,16 +158,19 @@
|
|
134 |
}
|
135 |
}
|
136 |
|
137 |
-
function
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
selectedPaymentMethod = $( '.wc_payment_method input:checked' ).val();
|
142 |
-
} else if ( 0 < $( '#payment_method_cpsw_stripe' ).length && $( '#payment_method_cpsw_stripe' ).is( ':checked' ) ) {
|
143 |
-
selectedPaymentMethod = $( '#payment_method_cpsw_stripe' ).val();
|
144 |
}
|
145 |
|
146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
case 'cpsw_stripe':
|
148 |
if ( 'no' === inlineCC ) {
|
149 |
card = cardNumber;
|
@@ -182,7 +209,11 @@
|
|
182 |
paymentForm.trigger( 'submit' );
|
183 |
}
|
184 |
} else if ( result.error ) {
|
|
|
|
|
185 |
logError( result.error );
|
|
|
|
|
186 |
return false;
|
187 |
}
|
188 |
} );
|
@@ -191,21 +222,46 @@
|
|
191 |
}
|
192 |
|
193 |
function confirmStripePayment( clientSecret, redirectURL ) {
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
}
|
210 |
|
211 |
function confirmCardSetup() {
|
@@ -237,8 +293,11 @@
|
|
237 |
|
238 |
function isAllowedGateway() {
|
239 |
if ( 0 < $( '.wc_payment_method' ).length ) {
|
240 |
-
const selectedPaymentMethod = $( '.wc_payment_method input:checked' ).val();
|
241 |
-
|
|
|
|
|
|
|
242 |
} else if ( 0 < $( '#payment_method_cpsw_stripe' ).length && $( '#payment_method_cpsw_stripe' ).is( ':checked' ) && 'cpsw_stripe' === $( '#payment_method_cpsw_stripe' ).val() ) {
|
243 |
return true;
|
244 |
}
|
@@ -279,7 +338,7 @@
|
|
279 |
const redirectURL = decodeURIComponent( partials[ 3 ] );
|
280 |
|
281 |
// Cleanup the URL
|
282 |
-
window.location.
|
283 |
confirmStripePayment( intentClientSecret, redirectURL );
|
284 |
}
|
285 |
|
@@ -323,8 +382,8 @@
|
|
323 |
}
|
324 |
|
325 |
const processingSubmit = function( e ) {
|
326 |
-
if ( isAllowedGateway() && ! savedCard && '' === paymentMethod ) {
|
327 |
-
if (
|
328 |
return false;
|
329 |
}
|
330 |
e.preventDefault();
|
@@ -332,6 +391,7 @@
|
|
332 |
|
333 |
return false;
|
334 |
}
|
|
|
335 |
return true;
|
336 |
};
|
337 |
|
@@ -339,6 +399,21 @@
|
|
339 |
paymentForm = $( 'form.woocommerce-checkout' );
|
340 |
}
|
341 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
$( 'form.woocommerce-checkout' ).on( 'submit checkout_place_order_cpsw_stripe', processingSubmit );
|
343 |
|
344 |
if ( $( 'form#order_review' ).length ) {
|
@@ -362,6 +437,7 @@
|
|
362 |
hideShowElements();
|
363 |
} );
|
364 |
mountCard();
|
|
|
365 |
$( "input[name='wc-cpsw-payment-token']" ).click( function() {
|
366 |
hideShowCard();
|
367 |
} );
|
@@ -374,4 +450,5 @@
|
|
374 |
|
375 |
window.addEventListener( 'hashchange', onHashChange );
|
376 |
mountCard();
|
|
|
377 |
}( jQuery ) );
|
1 |
( function( $ ) {
|
2 |
const pubKey = cpsw_global_settings.public_key;
|
3 |
const inlineCC = cpsw_global_settings.inline_cc;
|
|
|
4 |
const mode = cpsw_global_settings.mode;
|
5 |
const ajaxUrl = cpsw_global_settings.ajax_url;
|
6 |
const jsNonce = cpsw_global_settings.js_nonce;
|
7 |
const allowedCards = cpsw_global_settings.allowed_cards;
|
8 |
const notAllowedString = cpsw_global_settings.not_allowed_string;
|
9 |
const defaultCards = cpsw_global_settings.default_cards;
|
10 |
+
const homeURL = cpsw_global_settings.get_home_url;
|
11 |
|
12 |
+
if ( '' === pubKey || ( 'live' === mode && ! cpsw_global_settings.is_ssl ) ) {
|
13 |
return;
|
14 |
}
|
15 |
|
22 |
let cardCvc = null;
|
23 |
let paymentForm = null;
|
24 |
let paymentMethod = '';
|
25 |
+
let isAllowedCard = '';
|
26 |
+
let selectedGateway = '';
|
27 |
+
let selectedBank = '';
|
28 |
|
29 |
const style = {
|
30 |
base: {
|
117 |
} );
|
118 |
}
|
119 |
|
120 |
+
const options = {
|
121 |
+
style: {
|
122 |
+
base: {
|
123 |
+
padding: '10px 12px',
|
124 |
+
color: '#32325d',
|
125 |
+
fontSize: '16px',
|
126 |
+
'::placeholder': {
|
127 |
+
color: '#aab7c4',
|
128 |
+
backgroundColor: '#fff',
|
129 |
+
},
|
130 |
+
},
|
131 |
+
},
|
132 |
+
};
|
133 |
+
|
134 |
+
// Create an instance of the idealBank Element
|
135 |
+
const ideal = elements.create( 'idealBank', options );
|
136 |
+
|
137 |
+
ideal.on( 'change', function( event ) {
|
138 |
+
selectedBank = event.value;
|
139 |
+
$( '.cpsw_stripe_ideal_error' ).html( '' );
|
140 |
+
} );
|
141 |
+
|
142 |
function mountCard() {
|
143 |
$( '.cpsw-stripe-elements-form' ).show();
|
144 |
if ( 0 === $( '.cpsw-stripe-elements-form' ).length ) {
|
158 |
}
|
159 |
}
|
160 |
|
161 |
+
function mountIdeal() {
|
162 |
+
$( '.cpsw_stripe_ideal_form' ).show();
|
163 |
+
if ( 0 === $( '.cpsw_stripe_ideal_form' ).length ) {
|
164 |
+
return;
|
|
|
|
|
|
|
165 |
}
|
166 |
|
167 |
+
ideal.mount( '.cpsw_stripe_ideal_form .cpsw_stripe_ideal_select' );
|
168 |
+
$( '.cpsw_stripe_ideal_form .cpsw_stripe_ideal_select' ).css( { backgroundColor: '#fff', borderRadius: '3px' } );
|
169 |
+
}
|
170 |
+
|
171 |
+
function createStripePaymentMethod() {
|
172 |
+
let paymentObject = {};
|
173 |
+
switch ( selectedGateway ) {
|
174 |
case 'cpsw_stripe':
|
175 |
if ( 'no' === inlineCC ) {
|
176 |
card = cardNumber;
|
209 |
paymentForm.trigger( 'submit' );
|
210 |
}
|
211 |
} else if ( result.error ) {
|
212 |
+
$( '.woocommerce-error' ).remove();
|
213 |
+
$( 'form.woocommerce-checkout' ).unblock();
|
214 |
logError( result.error );
|
215 |
+
$( '.woocommerce-notices-wrapper:first-child' ).html( '<div class="woocommerce-error cpsw-errors">' + result.error.message + '</div>' ).show();
|
216 |
+
window.scrollTo( { top: 0, behavior: 'smooth' } );
|
217 |
return false;
|
218 |
}
|
219 |
} );
|
222 |
}
|
223 |
|
224 |
function confirmStripePayment( clientSecret, redirectURL ) {
|
225 |
+
switch ( selectedGateway ) {
|
226 |
+
case 'cpsw_stripe':
|
227 |
+
stripe.confirmCardPayment( clientSecret, {} ).then( function( result ) {
|
228 |
+
if ( result.error ) {
|
229 |
+
// Show error to your customer (e.g., insufficient funds)
|
230 |
+
$( '.woocommerce-error' ).remove();
|
231 |
+
$( 'form.woocommerce-checkout' ).unblock();
|
232 |
+
logError( result.error );
|
233 |
+
$( '.woocommerce-notices-wrapper:first-child' ).html( '<div class="woocommerce-error cpsw-errors">' + result.error.message + '</div>' ).show();
|
234 |
+
window.scrollTo( { top: 0, behavior: 'smooth' } );
|
235 |
+
} else {
|
236 |
+
// The payment has been processed!
|
237 |
+
if ( result.paymentIntent.status === 'succeeded' || result.paymentIntent.status === 'requires_capture' ) {
|
238 |
+
window.location = redirectURL;
|
239 |
+
}
|
240 |
+
}
|
241 |
+
} );
|
242 |
+
break;
|
243 |
+
case 'cpsw_ideal':
|
244 |
+
stripe.confirmIdealPayment(
|
245 |
+
clientSecret,
|
246 |
+
{
|
247 |
+
payment_method: {
|
248 |
+
ideal,
|
249 |
+
},
|
250 |
+
return_url: homeURL + redirectURL,
|
251 |
+
},
|
252 |
+
);
|
253 |
+
break;
|
254 |
+
case 'cpsw_alipay':
|
255 |
+
stripe.confirmAlipayPayment(
|
256 |
+
clientSecret,
|
257 |
+
{
|
258 |
+
return_url: homeURL + redirectURL,
|
259 |
+
},
|
260 |
+
);
|
261 |
+
break;
|
262 |
+
default:
|
263 |
+
break;
|
264 |
+
}
|
265 |
}
|
266 |
|
267 |
function confirmCardSetup() {
|
293 |
|
294 |
function isAllowedGateway() {
|
295 |
if ( 0 < $( '.wc_payment_method' ).length ) {
|
296 |
+
const selectedPaymentMethod = $( '.wc_payment_method input[name="payment_method"]:checked' ).val();
|
297 |
+
if ( -1 === $.inArray( selectedPaymentMethod, [ 'cpsw_stripe', 'cpsw_alipay', 'cpsw_ideal' ] ) ) {
|
298 |
+
return false;
|
299 |
+
}
|
300 |
+
return selectedGateway = selectedPaymentMethod;
|
301 |
} else if ( 0 < $( '#payment_method_cpsw_stripe' ).length && $( '#payment_method_cpsw_stripe' ).is( ':checked' ) && 'cpsw_stripe' === $( '#payment_method_cpsw_stripe' ).val() ) {
|
302 |
return true;
|
303 |
}
|
338 |
const redirectURL = decodeURIComponent( partials[ 3 ] );
|
339 |
|
340 |
// Cleanup the URL
|
341 |
+
history.pushState( {}, '', window.location.pathname );
|
342 |
confirmStripePayment( intentClientSecret, redirectURL );
|
343 |
}
|
344 |
|
382 |
}
|
383 |
|
384 |
const processingSubmit = function( e ) {
|
385 |
+
if ( 'cpsw_stripe' === isAllowedGateway() && ! savedCard && '' === paymentMethod ) {
|
386 |
+
if ( false === isAllowedCard ) {
|
387 |
return false;
|
388 |
}
|
389 |
e.preventDefault();
|
391 |
|
392 |
return false;
|
393 |
}
|
394 |
+
|
395 |
return true;
|
396 |
};
|
397 |
|
399 |
paymentForm = $( 'form.woocommerce-checkout' );
|
400 |
}
|
401 |
|
402 |
+
$( 'form.woocommerce-checkout' ).on( 'submit checkout_place_order_cpsw_ideal', function() {
|
403 |
+
// check for iDEAL.
|
404 |
+
if ( 'cpsw_ideal' === isAllowedGateway() ) {
|
405 |
+
if ( '' === selectedBank ) {
|
406 |
+
$( '.cpsw_stripe_ideal_error' ).html( cpsw_global_settings.empty_ideal_bank_message );
|
407 |
+
$( '.woocommerce-error' ).remove();
|
408 |
+
$( 'form.woocommerce-checkout' ).unblock();
|
409 |
+
$( '.woocommerce-notices-wrapper:first-child' ).html( '<div class="woocommerce-error cpsw-errors">' + cpsw_global_settings.empty_ideal_bank_message + '</div>' ).show();
|
410 |
+
window.scrollTo( { top: 0, behavior: 'smooth' } );
|
411 |
+
return false;
|
412 |
+
}
|
413 |
+
$( '.cpsw_stripe_ideal_error' ).html( '' );
|
414 |
+
}
|
415 |
+
} );
|
416 |
+
|
417 |
$( 'form.woocommerce-checkout' ).on( 'submit checkout_place_order_cpsw_stripe', processingSubmit );
|
418 |
|
419 |
if ( $( 'form#order_review' ).length ) {
|
437 |
hideShowElements();
|
438 |
} );
|
439 |
mountCard();
|
440 |
+
mountIdeal();
|
441 |
$( "input[name='wc-cpsw-payment-token']" ).click( function() {
|
442 |
hideShowCard();
|
443 |
} );
|
450 |
|
451 |
window.addEventListener( 'hashchange', onHashChange );
|
452 |
mountCard();
|
453 |
+
mountIdeal();
|
454 |
}( jQuery ) );
|
autoloader.php
CHANGED
@@ -9,10 +9,13 @@
|
|
9 |
namespace CPSW;
|
10 |
|
11 |
use CPSW\Gateway\Stripe\Card_Payments;
|
|
|
12 |
use CPSW\Gateway\Stripe\Payment_Request_Api;
|
|
|
13 |
use CPSW\Compatibility\Apple_Pay;
|
14 |
use CPSW\Admin\Admin_Controller;
|
15 |
use CPSW\Gateway\Stripe\Webhook;
|
|
|
16 |
|
17 |
/**
|
18 |
* CPSW_Loader
|
@@ -82,6 +85,7 @@ class CPSW_Loader {
|
|
82 |
$this->setup_classes();
|
83 |
add_action( 'plugins_loaded', [ $this, 'load_classes' ] );
|
84 |
add_filter( 'plugin_action_links_' . CPSW_BASE, [ $this, 'action_links' ] );
|
|
|
85 |
}
|
86 |
|
87 |
/**
|
@@ -95,6 +99,21 @@ class CPSW_Loader {
|
|
95 |
Apple_Pay::get_instance();
|
96 |
}
|
97 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
/**
|
99 |
* Adds links in Plugins page
|
100 |
*
|
@@ -120,6 +139,8 @@ class CPSW_Loader {
|
|
120 |
if ( class_exists( 'woocommerce' ) ) {
|
121 |
Card_Payments::get_instance();
|
122 |
Payment_Request_Api::get_instance();
|
|
|
|
|
123 |
} else {
|
124 |
add_action( 'admin_notices', [ $this, 'wc_is_not_active' ] );
|
125 |
}
|
9 |
namespace CPSW;
|
10 |
|
11 |
use CPSW\Gateway\Stripe\Card_Payments;
|
12 |
+
use CPSW\Gateway\Stripe\Alipay;
|
13 |
use CPSW\Gateway\Stripe\Payment_Request_Api;
|
14 |
+
use CPSW\Gateway\Stripe\Ideal;
|
15 |
use CPSW\Compatibility\Apple_Pay;
|
16 |
use CPSW\Admin\Admin_Controller;
|
17 |
use CPSW\Gateway\Stripe\Webhook;
|
18 |
+
use CPSW\Gateway\Stripe\Frontend_Scripts;
|
19 |
|
20 |
/**
|
21 |
* CPSW_Loader
|
85 |
$this->setup_classes();
|
86 |
add_action( 'plugins_loaded', [ $this, 'load_classes' ] );
|
87 |
add_filter( 'plugin_action_links_' . CPSW_BASE, [ $this, 'action_links' ] );
|
88 |
+
add_action( 'woocommerce_init', [ $this, 'frontend_scripts' ] );
|
89 |
}
|
90 |
|
91 |
/**
|
99 |
Apple_Pay::get_instance();
|
100 |
}
|
101 |
|
102 |
+
/**
|
103 |
+
* Includes frontend scripts.
|
104 |
+
*
|
105 |
+
* @since 1.1.0
|
106 |
+
*
|
107 |
+
* @return void
|
108 |
+
*/
|
109 |
+
public function frontend_scripts() {
|
110 |
+
if ( is_admin() ) {
|
111 |
+
return;
|
112 |
+
}
|
113 |
+
|
114 |
+
Frontend_Scripts::get_instance();
|
115 |
+
}
|
116 |
+
|
117 |
/**
|
118 |
* Adds links in Plugins page
|
119 |
*
|
139 |
if ( class_exists( 'woocommerce' ) ) {
|
140 |
Card_Payments::get_instance();
|
141 |
Payment_Request_Api::get_instance();
|
142 |
+
Alipay::get_instance();
|
143 |
+
Ideal::get_instance();
|
144 |
} else {
|
145 |
add_action( 'admin_notices', [ $this, 'wc_is_not_active' ] );
|
146 |
}
|
checkout-plugins-stripe-woo.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Checkout Plugins - Stripe for WooCommerce
|
4 |
* Plugin URI: https://www.checkoutplugins.com/
|
5 |
* Description: Stripe for WooCommerce delivers a simple, secure way to accept credit card payments in your WooCommerce store. Reduce payment friction and boost conversions using this free plugin!
|
6 |
-
* Version: 1.
|
7 |
* Author: Brainstorm Force
|
8 |
* Author URI: https://brainstormforce.com/
|
9 |
* License: GPLv2 or later
|
@@ -20,6 +20,6 @@ define( 'CPSW_FILE', __FILE__ );
|
|
20 |
define( 'CPSW_BASE', plugin_basename( CPSW_FILE ) );
|
21 |
define( 'CPSW_DIR', plugin_dir_path( CPSW_FILE ) );
|
22 |
define( 'CPSW_URL', plugins_url( '/', CPSW_FILE ) );
|
23 |
-
define( 'CPSW_VERSION', '1.
|
24 |
|
25 |
require_once 'autoloader.php';
|
3 |
* Plugin Name: Checkout Plugins - Stripe for WooCommerce
|
4 |
* Plugin URI: https://www.checkoutplugins.com/
|
5 |
* Description: Stripe for WooCommerce delivers a simple, secure way to accept credit card payments in your WooCommerce store. Reduce payment friction and boost conversions using this free plugin!
|
6 |
+
* Version: 1.2.0
|
7 |
* Author: Brainstorm Force
|
8 |
* Author URI: https://brainstormforce.com/
|
9 |
* License: GPLv2 or later
|
20 |
define( 'CPSW_BASE', plugin_basename( CPSW_FILE ) );
|
21 |
define( 'CPSW_DIR', plugin_dir_path( CPSW_FILE ) );
|
22 |
define( 'CPSW_URL', plugins_url( '/', CPSW_FILE ) );
|
23 |
+
define( 'CPSW_VERSION', '1.2.0' );
|
24 |
|
25 |
require_once 'autoloader.php';
|
compatibility/apple-pay.php
CHANGED
@@ -268,7 +268,7 @@ class Apple_Pay {
|
|
268 |
*/
|
269 |
public function apple_pay_verification_failed() {
|
270 |
/* translators: %1s - %3s HTML Entities, %4s Error Message */
|
271 |
-
echo wp_kses_post( '<div class="notice notice-warning is-dismissible"><p>' . sprintf( __( '%1$1sApple Pay domain verification failed
|
272 |
}
|
273 |
|
274 |
/**
|
268 |
*/
|
269 |
public function apple_pay_verification_failed() {
|
270 |
/* translators: %1s - %3s HTML Entities, %4s Error Message */
|
271 |
+
echo wp_kses_post( '<div class="notice notice-warning is-dismissible"><p>' . sprintf( __( '%1$1sApple Pay domain verification failed! %2$2sReason%3$3s: %4$4s', 'checkout-plugins-stripe-woo' ), '<b>', '<br/>', '</b>', $this->failure_message ) . '</p></div>' );
|
272 |
}
|
273 |
|
274 |
/**
|
gateway/abstract-payment-gateway.php
CHANGED
@@ -10,13 +10,39 @@ namespace CPSW\Gateway;
|
|
10 |
|
11 |
use WC_Payment_Gateway;
|
12 |
use CPSW\Inc\Helper;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
/**
|
15 |
-
*
|
16 |
*
|
17 |
-
* @
|
18 |
*/
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
/**
|
22 |
* Adds transaction url in order details page
|
@@ -44,5 +70,470 @@ abstract class Abstract_Payment_Gateway extends WC_Payment_Gateway {
|
|
44 |
return apply_filters( 'cpsw_get_order_description', get_bloginfo( 'name' ) . ' - ' . __( 'Order ', 'checkout-plugins-stripe-woo' ) . $order->get_id() );
|
45 |
}
|
46 |
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
use WC_Payment_Gateway;
|
12 |
use CPSW\Inc\Helper;
|
13 |
+
use CPSW\Inc\Logger;
|
14 |
+
use CPSW\Gateway\Stripe\Stripe_Api;
|
15 |
+
use WP_Error;
|
16 |
+
use Exception;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Abstract Payment Gateway
|
20 |
+
*
|
21 |
+
* @since 0.0.1
|
22 |
+
*/
|
23 |
+
abstract class Abstract_Payment_Gateway extends WC_Payment_Gateway {
|
24 |
|
25 |
/**
|
26 |
+
* Url of assets directory
|
27 |
*
|
28 |
+
* @var string
|
29 |
*/
|
30 |
+
private $assets_url = CPSW_URL . 'assets/';
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Zero currencies accepted by stripe.
|
34 |
+
*
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
private static $zero_currencies = [ 'BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VUV', 'XAF', 'XOF', 'XPF', 'VND' ];
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Constructor
|
41 |
+
*/
|
42 |
+
public function __construct() {
|
43 |
+
add_filter( 'woocommerce_payment_gateways', [ $this, 'add_gateway_class' ] );
|
44 |
+
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
|
45 |
+
}
|
46 |
|
47 |
/**
|
48 |
* Adds transaction url in order details page
|
70 |
return apply_filters( 'cpsw_get_order_description', get_bloginfo( 'name' ) . ' - ' . __( 'Order ', 'checkout-plugins-stripe-woo' ) . $order->get_id() );
|
71 |
}
|
72 |
|
73 |
+
/**
|
74 |
+
* Registering Gateway to WooCommerce
|
75 |
+
*
|
76 |
+
* @param array $methods List of registered gateways.
|
77 |
+
* @return array
|
78 |
+
*/
|
79 |
+
public function add_gateway_class( $methods ) {
|
80 |
+
$methods[] = $this;
|
81 |
+
return $methods;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Get billing countries for gateways
|
86 |
+
*
|
87 |
+
* @since 1.2.0
|
88 |
+
*
|
89 |
+
* @return string $billing_country
|
90 |
+
*/
|
91 |
+
public function get_billing_country() {
|
92 |
+
if ( isset( $wp->query_vars['order-pay'] ) ) {
|
93 |
+
$order = wc_get_order( absint( $wp->query_vars['order-pay'] ) );
|
94 |
+
$billing_country = $order->get_billing_country();
|
95 |
+
$currency = $order->get_currency();
|
96 |
+
} else {
|
97 |
+
$currency = get_woocommerce_currency();
|
98 |
+
$customer = WC()->customer;
|
99 |
+
$billing_country = $customer ? $customer->get_billing_country() : null;
|
100 |
+
|
101 |
+
if ( ! $billing_country ) {
|
102 |
+
$billing_country = WC()->countries->get_base_country();
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
return $billing_country;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Get WooCommerce currency
|
111 |
+
*
|
112 |
+
* @since 1.2.0
|
113 |
+
*
|
114 |
+
* @return string
|
115 |
+
*/
|
116 |
+
public function get_currency() {
|
117 |
+
if ( isset( $wp->query_vars['order-pay'] ) ) {
|
118 |
+
$order = wc_get_order( absint( $wp->query_vars['order-pay'] ) );
|
119 |
+
|
120 |
+
return $order->get_currency();
|
121 |
+
}
|
122 |
+
|
123 |
+
return get_woocommerce_currency();
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Checks whether this gateway is available.
|
128 |
+
*
|
129 |
+
* @since 1.0.0
|
130 |
+
*
|
131 |
+
* @return boolean
|
132 |
+
*/
|
133 |
+
public function is_available() {
|
134 |
+
if ( 'yes' !== $this->enabled ) {
|
135 |
+
return false;
|
136 |
+
}
|
137 |
|
138 |
+
if ( ! Helper::get_payment_mode() && is_checkout() ) {
|
139 |
+
return false;
|
140 |
+
}
|
141 |
+
|
142 |
+
if ( 'test' === Helper::get_payment_mode() ) {
|
143 |
+
if ( empty( Helper::get_setting( 'cpsw_test_pub_key' ) ) || empty( Helper::get_setting( 'cpsw_test_secret_key' ) ) ) {
|
144 |
+
return false;
|
145 |
+
}
|
146 |
+
} else {
|
147 |
+
if ( empty( Helper::get_setting( 'cpsw_pub_key' ) ) || empty( Helper::get_setting( 'cpsw_secret_key' ) ) ) {
|
148 |
+
return false;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
return true;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Get/Retrieve stripe customer id if exists
|
157 |
+
*
|
158 |
+
* @since 1.0.0
|
159 |
+
*
|
160 |
+
* @param mixed $order current woocommerce order.
|
161 |
+
*
|
162 |
+
* @return mixed customer id
|
163 |
+
*/
|
164 |
+
public function get_customer_id( $order = false ) {
|
165 |
+
$user = wp_get_current_user();
|
166 |
+
$user_id = ( $user->ID && $user->ID > 0 ) ? $user->ID : false;
|
167 |
+
$customer_id = false;
|
168 |
+
|
169 |
+
if ( $user_id ) {
|
170 |
+
$customer_id = get_user_option( '_cpsw_customer_id', $user_id );
|
171 |
+
if ( $customer_id ) {
|
172 |
+
return $customer_id;
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
$customer = false;
|
177 |
+
if ( ! $customer_id ) {
|
178 |
+
$customer = $this->create_stripe_customer( $order, $user->email );
|
179 |
+
}
|
180 |
+
|
181 |
+
if ( $customer ) {
|
182 |
+
if ( $user_id ) {
|
183 |
+
update_user_option( $user_id, '_cpsw_customer_id', $customer->id, false );
|
184 |
+
}
|
185 |
+
return $customer->id;
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Creates stripe customer object
|
191 |
+
*
|
192 |
+
* @since 1.0.0
|
193 |
+
*
|
194 |
+
* @param object $order woocommerce order object.
|
195 |
+
* @param boolean|string $user_email user email id.
|
196 |
+
*
|
197 |
+
* @return Stripe::Customer
|
198 |
+
*/
|
199 |
+
public function create_stripe_customer( $order = false, $user_email = false ) {
|
200 |
+
$args = [
|
201 |
+
'email' => $user_email,
|
202 |
+
];
|
203 |
+
if ( $order ) {
|
204 |
+
$args = [
|
205 |
+
'description' => 'Customer for Order #' . $order->get_id(),
|
206 |
+
'email' => $user_email ? $user_email : $order->get_billing_email(),
|
207 |
+
'address' => [ // sending name and billing address to stripe to support indian exports.
|
208 |
+
'city' => method_exists( $order, 'get_billing_city' ) ? $order->get_billing_city() : $order->billing_city,
|
209 |
+
'country' => method_exists( $order, 'get_billing_country' ) ? $order->get_billing_country() : $order->billing_country,
|
210 |
+
'line1' => method_exists( $order, 'get_billing_address_1' ) ? $order->get_billing_address_1() : $order->billing_address_1,
|
211 |
+
'line2' => method_exists( $order, 'get_billing_address_2' ) ? $order->get_billing_address_2() : $order->billing_address_2,
|
212 |
+
'postal_code' => method_exists( $order, 'get_billing_postcode' ) ? $order->get_billing_postcode() : $order->billing_postcode,
|
213 |
+
'state' => method_exists( $order, 'get_billing_state' ) ? $order->get_billing_state() : $order->billing_state,
|
214 |
+
],
|
215 |
+
'name' => ( method_exists( $order, 'get_billing_first_name' ) ? $order->get_billing_first_name() : $order->billing_first_name ) . ( method_exists( $order, 'get_billing_last_name' ) ? $order->get_billing_last_name() : $order->billing_last_name ),
|
216 |
+
];
|
217 |
+
}
|
218 |
+
|
219 |
+
$stripe_api = new Stripe_Api();
|
220 |
+
$response = $stripe_api->customers( 'create', [ $args ] );
|
221 |
+
$response = $response['success'] ? $response['data'] : false;
|
222 |
+
|
223 |
+
if ( empty( $response->id ) ) {
|
224 |
+
return false;
|
225 |
+
}
|
226 |
+
|
227 |
+
return $response;
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Refunds amount from stripe and return true/false as result
|
232 |
+
*
|
233 |
+
* @param string $order_id order id.
|
234 |
+
* @param string $amount refund amount.
|
235 |
+
* @param string $reason reason of refund.
|
236 |
+
* @return bool
|
237 |
+
*/
|
238 |
+
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
239 |
+
if ( 0 >= $amount ) {
|
240 |
+
return false;
|
241 |
+
}
|
242 |
+
|
243 |
+
try {
|
244 |
+
|
245 |
+
$order = wc_get_order( $order_id );
|
246 |
+
$intent_secret = $order->get_meta( '_cpsw_intent_secret', true );
|
247 |
+
|
248 |
+
$response = $this->create_refund_request( $order, $amount, $reason, $intent_secret['id'] );
|
249 |
+
|
250 |
+
$refund_response = $response['success'] ? $response['data'] : false;
|
251 |
+
|
252 |
+
if ( $refund_response ) {
|
253 |
+
$refund_time = gmdate( 'Y-m-d H:i:s', time() );
|
254 |
+
$order->update_meta_data( '_cpsw_refund_id', $refund_response->id );
|
255 |
+
$order->add_order_note( __( 'Reason : ', 'checkout-plugins-stripe-woo' ) . $reason . '.<br>' . __( 'Amount : ', 'checkout-plugins-stripe-woo' ) . get_woocommerce_currency_symbol() . $amount . '.<br>' . __( 'Status : ', 'checkout-plugins-stripe-woo' ) . ( ( 'succeeded' === $refund_response->status ) ? 'Success' : 'Failed' ) . ' [ ' . $refund_time . ' ] ' . ( is_null( $refund_response->id ) ? '' : '<br>' . __( 'Transaction ID : ', 'checkout-plugins-stripe-woo' ) . $refund_response->id ) );
|
256 |
+
Logger::info( __( 'Refund initiated: ', 'checkout-plugins-stripe-woo' ) . __( 'Reason : ', 'checkout-plugins-stripe-woo' ) . $reason . __( 'Amount : ', 'checkout-plugins-stripe-woo' ) . get_woocommerce_currency_symbol() . $amount . __( 'Status : ', 'checkout-plugins-stripe-woo' ) . ( ( 'succeeded' === $refund_response->status ) ? 'Success' : 'Failed' ) . ' [ ' . $refund_time . ' ] ' . ( is_null( $refund_response->id ) ? '' : __( 'Transaction ID : ', 'checkout-plugins-stripe-woo' ) . $refund_response->id ), true );
|
257 |
+
return true;
|
258 |
+
} else {
|
259 |
+
$order->add_order_note( __( 'Reason : ', 'checkout-plugins-stripe-woo' ) . $reason . '.<br>' . __( 'Amount : ', 'checkout-plugins-stripe-woo' ) . get_woocommerce_currency_symbol() . $amount . '.<br>' . __( ' Status : Failed ', 'checkout-plugins-stripe-woo' ) );
|
260 |
+
Logger::error( $response['message'], true );
|
261 |
+
return new WP_Error( 'error', $response['message'] );
|
262 |
+
}
|
263 |
+
} catch ( Exception $e ) {
|
264 |
+
Logger::error( $e->getMessage(), true );
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Process response for saved cards
|
270 |
+
*
|
271 |
+
* @param object $response intent response.
|
272 |
+
* @param object $order order response.
|
273 |
+
* @return array
|
274 |
+
*/
|
275 |
+
public function process_response( $response, $order ) {
|
276 |
+
Logger::info( 'Processing: ' . $response->id );
|
277 |
+
|
278 |
+
$order_id = $order->get_id();
|
279 |
+
$captured = ( isset( $response->captured ) && $response->captured ) ? 'yes' : 'no';
|
280 |
+
|
281 |
+
// Store charge data.
|
282 |
+
$order->update_meta_data( '_cpsw_charge_captured', $captured );
|
283 |
+
|
284 |
+
if ( 'yes' === $captured ) {
|
285 |
+
/**
|
286 |
+
* Charge can be captured but in a pending state. Payment methods
|
287 |
+
* that are asynchronous may take couple days to clear. Webhook will
|
288 |
+
* take care of the status changes.
|
289 |
+
*/
|
290 |
+
if ( 'pending' === $response->status ) {
|
291 |
+
$order_stock_reduced = $order->get_meta( '_order_stock_reduced', true );
|
292 |
+
|
293 |
+
if ( ! $order_stock_reduced ) {
|
294 |
+
wc_reduce_stock_levels( $order_id );
|
295 |
+
}
|
296 |
+
|
297 |
+
$order->set_transaction_id( $response->id );
|
298 |
+
/* translators: transaction id */
|
299 |
+
$order->update_status( 'on-hold', sprintf( __( 'Stripe charge awaiting payment: %s.', 'checkout-plugins-stripe-woo' ), $response->id ) );
|
300 |
+
}
|
301 |
+
|
302 |
+
if ( 'succeeded' === $response->status ) {
|
303 |
+
$order->payment_complete( $response->id );
|
304 |
+
|
305 |
+
/* translators: transaction id */
|
306 |
+
$message = sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'checkout-plugins-stripe-woo' ), $response->id );
|
307 |
+
Logger::info( $message, true );
|
308 |
+
$order->add_order_note( $message );
|
309 |
+
}
|
310 |
+
|
311 |
+
if ( 'failed' === $response->status ) {
|
312 |
+
$message = __( 'Payment processing failed. Please retry.', 'checkout-plugins-stripe-woo' );
|
313 |
+
Logger::error( $message, true );
|
314 |
+
$order->add_order_note( $message );
|
315 |
+
}
|
316 |
+
} else {
|
317 |
+
$order->set_transaction_id( $response->id );
|
318 |
+
|
319 |
+
if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
|
320 |
+
wc_reduce_stock_levels( $order_id );
|
321 |
+
}
|
322 |
+
|
323 |
+
/* translators: transaction id */
|
324 |
+
$order->update_status( 'on-hold', sprintf( __( 'Stripe charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization. Attempting to refund the order in part or in full will release the authorization and cancel the payment.', 'checkout-plugins-stripe-woo' ), $response->id ) );
|
325 |
+
}
|
326 |
+
|
327 |
+
if ( is_callable( [ $order, 'save' ] ) ) {
|
328 |
+
$order->save();
|
329 |
+
}
|
330 |
+
|
331 |
+
do_action( 'cpsw_process_response', $response, $order );
|
332 |
+
|
333 |
+
return $response;
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Basic details of logged in user
|
338 |
+
*
|
339 |
+
* @since 1.0.0
|
340 |
+
*
|
341 |
+
* @return array current user data.
|
342 |
+
*/
|
343 |
+
public function get_clients_details() {
|
344 |
+
return [
|
345 |
+
'ip' => isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : '',
|
346 |
+
'agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : '',
|
347 |
+
'referer' => isset( $_SERVER['HTTP_REFERER'] ) ? sanitize_text_field( $_SERVER['HTTP_REFERER'] ) : '',
|
348 |
+
];
|
349 |
+
}
|
350 |
+
|
351 |
+
/**
|
352 |
+
* Checks if payment intent available for current order or else creates new payment intent.
|
353 |
+
*
|
354 |
+
* @since 1.0.0
|
355 |
+
*
|
356 |
+
* @param int $order_id woocommerce order id.
|
357 |
+
* @param string $idempotency_key unique idempotency key.
|
358 |
+
* @param array $args payment_intent arguments.
|
359 |
+
* @param boolean $return_error_response if true returns complete error response array.
|
360 |
+
*
|
361 |
+
* @return array intent data.
|
362 |
+
*/
|
363 |
+
public function get_payment_intent( $order_id, $idempotency_key, $args, $return_error_response = false ) {
|
364 |
+
$intent_secret = get_post_meta( $order_id, '_cpsw_intent_secret', true );
|
365 |
+
$client_secret = '';
|
366 |
+
|
367 |
+
if ( ! empty( $intent_secret ) ) {
|
368 |
+
$secret = $intent_secret;
|
369 |
+
$stripe_api = new Stripe_Api();
|
370 |
+
$response = $stripe_api->payment_intents( 'retrieve', [ $secret['id'] ] );
|
371 |
+
|
372 |
+
if ( $response['success'] && 'success' === $response['data']->status ) {
|
373 |
+
wc_add_notice( __( 'An error has occurred internally, due to which you are not redirected to the order received page.', 'checkout-plugins-stripe-woo' ), $notice_type = 'error' );
|
374 |
+
wp_safe_redirect( wc_get_checkout_url() );
|
375 |
+
}
|
376 |
+
}
|
377 |
+
|
378 |
+
$args = [
|
379 |
+
[ $args ],
|
380 |
+
[ 'idempotency_key' => $idempotency_key ],
|
381 |
+
];
|
382 |
+
|
383 |
+
$stripe_api = new Stripe_Api();
|
384 |
+
$response = $stripe_api->payment_intents( 'create', $args );
|
385 |
+
|
386 |
+
if ( $response['success'] ) {
|
387 |
+
$intent = $response['data'];
|
388 |
+
} elseif ( $return_error_response ) {
|
389 |
+
return $response;
|
390 |
+
} else {
|
391 |
+
wc_add_notice( $response['message'], 'error' );
|
392 |
+
return false;
|
393 |
+
}
|
394 |
+
|
395 |
+
$intent_data = [
|
396 |
+
'id' => $intent->id,
|
397 |
+
'client_secret' => $intent->client_secret,
|
398 |
+
];
|
399 |
+
|
400 |
+
update_post_meta( $order_id, '_cpsw_intent_secret', $intent_data, );
|
401 |
+
$client_secret = $intent->client_secret;
|
402 |
+
|
403 |
+
return [
|
404 |
+
'client_secret' => $client_secret,
|
405 |
+
];
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* Returns amount as per currency type
|
410 |
+
*
|
411 |
+
* @since 1.0.0
|
412 |
+
*
|
413 |
+
* @param string $total amount to be processed.
|
414 |
+
* @param string $currency transaction currency.
|
415 |
+
*
|
416 |
+
* @return int
|
417 |
+
*/
|
418 |
+
public function get_formatted_amount( $total, $currency = '' ) {
|
419 |
+
if ( ! $currency ) {
|
420 |
+
$currency = get_woocommerce_currency();
|
421 |
+
}
|
422 |
+
|
423 |
+
if ( in_array( strtolower( $currency ), self::$zero_currencies, true ) ) {
|
424 |
+
// Zero decimal currencies accepted by stripe.
|
425 |
+
return absint( $total );
|
426 |
+
} else {
|
427 |
+
return absint( wc_format_decimal( ( (float) $total * 100 ), wc_get_price_decimals() ) ); // In cents.
|
428 |
+
}
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Add metadata to stripe
|
433 |
+
*
|
434 |
+
* @since 1.2.0
|
435 |
+
*
|
436 |
+
* @param int $order_id WooCommerce order Id.
|
437 |
+
*
|
438 |
+
* @return array
|
439 |
+
*/
|
440 |
+
public function get_metadata( $order_id ) {
|
441 |
+
$order = wc_get_order( $order_id );
|
442 |
+
$details = [];
|
443 |
+
$billing_first_name = $order->get_billing_first_name();
|
444 |
+
$billing_last_name = $order->get_billing_last_name();
|
445 |
+
$name = $billing_first_name . ' ' . $billing_last_name;
|
446 |
+
|
447 |
+
if ( ! empty( $name ) ) {
|
448 |
+
$details['name'] = $name;
|
449 |
+
}
|
450 |
+
|
451 |
+
if ( ! empty( $order->get_billing_email() ) ) {
|
452 |
+
$details['email'] = $order->get_billing_email();
|
453 |
+
}
|
454 |
+
|
455 |
+
if ( ! empty( $order->get_billing_phone() ) ) {
|
456 |
+
$details['phone'] = $order->get_billing_phone();
|
457 |
+
}
|
458 |
+
|
459 |
+
if ( ! empty( $order->get_billing_address_1() ) ) {
|
460 |
+
$details['address'] = $order->get_billing_address_1();
|
461 |
+
}
|
462 |
+
|
463 |
+
if ( ! empty( $order->get_billing_city() ) ) {
|
464 |
+
$details['city'] = $order->get_billing_city();
|
465 |
+
}
|
466 |
+
|
467 |
+
if ( ! empty( $order->get_billing_country() ) ) {
|
468 |
+
$details['country'] = $order->get_billing_country();
|
469 |
+
}
|
470 |
+
|
471 |
+
$details['site_url'] = get_site_url();
|
472 |
+
|
473 |
+
return apply_filters( 'cpsw_metadata_details', $details, $order );
|
474 |
+
}
|
475 |
+
|
476 |
+
/**
|
477 |
+
* All payment icons that work with Stripe
|
478 |
+
*
|
479 |
+
* @since 1.2.0
|
480 |
+
*
|
481 |
+
* @param string $gateway_id gateway id to fetch icon.
|
482 |
+
*
|
483 |
+
* @return array
|
484 |
+
*/
|
485 |
+
public function payment_icons( $gateway_id ) {
|
486 |
+
$icons = [
|
487 |
+
'cpsw_alipay' => '<img src="' . $this->assets_url . 'icon/alipay.svg" class="cpsw-alipay-icon stripe-icon" alt="Alipay" width="70px" />',
|
488 |
+
'cpsw_ideal' => '<img src="' . $this->assets_url . 'icon/ideal.svg" class="cpsw-ideal-icon stripe-icon" alt="iDEAL" width="32" />',
|
489 |
+
];
|
490 |
+
|
491 |
+
return apply_filters(
|
492 |
+
'cpsw_payment_icons',
|
493 |
+
isset( $icons[ $gateway_id ] ) ? $icons[ $gateway_id ] : ''
|
494 |
+
);
|
495 |
+
}
|
496 |
+
|
497 |
+
/**
|
498 |
+
* Create refund request.
|
499 |
+
*
|
500 |
+
* @since 1.0.0
|
501 |
+
*
|
502 |
+
* @param object $order order.
|
503 |
+
* @param string $amount refund amount.
|
504 |
+
* @param string $reason reason of refund.
|
505 |
+
* @param string $intent_secret_id secret key.
|
506 |
+
*
|
507 |
+
* @return array
|
508 |
+
*/
|
509 |
+
public function create_refund_request( $order, $amount, $reason, $intent_secret_id ) {
|
510 |
+
$client = $this->get_clients_details();
|
511 |
+
$stripe_api = new Stripe_Api();
|
512 |
+
$response = $stripe_api->payment_intents( 'retrieve', [ $intent_secret_id ] );
|
513 |
+
$status = $response['success'] && isset( $response['data']->charges->data[0]->captured ) ? $response['data']->charges->data[0]->captured : false;
|
514 |
+
|
515 |
+
if ( ! $status ) {
|
516 |
+
Logger::error( __( 'Uncaptured Amount cannot be refunded', 'checkout-plugins-stripe-woo' ), true );
|
517 |
+
return new WP_Error( 'error', __( 'Uncaptured Amount cannot be refunded', 'checkout-plugins-stripe-woo' ) );
|
518 |
+
}
|
519 |
+
|
520 |
+
$intent_response = $response['data'];
|
521 |
+
$currency = $intent_response->currency;
|
522 |
+
|
523 |
+
$refund_params = [
|
524 |
+
'payment_intent' => $intent_secret_id,
|
525 |
+
'amount' => $this->get_formatted_amount( $amount, $currency ),
|
526 |
+
'reason' => 'requested_by_customer',
|
527 |
+
'metadata' => [
|
528 |
+
'order_id' => $order->get_order_number(),
|
529 |
+
'customer_ip' => $client['ip'],
|
530 |
+
'agent' => $client['agent'],
|
531 |
+
'referer' => $client['referer'],
|
532 |
+
'reason_for_refund' => $reason,
|
533 |
+
],
|
534 |
+
];
|
535 |
+
|
536 |
+
$stripe_api = new Stripe_Api();
|
537 |
+
return $stripe_api->refunds( 'create', [ $refund_params ] );
|
538 |
+
}
|
539 |
+
}
|
gateway/local-gateway.php
ADDED
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Local Gateway
|
4 |
+
*
|
5 |
+
* @package checkout-plugins-stripe-woo
|
6 |
+
* @since 1.2.0
|
7 |
+
*/
|
8 |
+
|
9 |
+
namespace CPSW\Gateway;
|
10 |
+
|
11 |
+
use CPSW\Inc\Traits\Get_Instance;
|
12 |
+
use CPSW\Gateway\Abstract_Payment_Gateway;
|
13 |
+
use CPSW\Inc\Notice;
|
14 |
+
use CPSW\Inc\Helper;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Local Gateway
|
18 |
+
*
|
19 |
+
* @since 1.2.0
|
20 |
+
*/
|
21 |
+
class Local_Gateway extends Abstract_Payment_Gateway {
|
22 |
+
|
23 |
+
use Get_Instance;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Constructor
|
27 |
+
*
|
28 |
+
* @since 1.2.0
|
29 |
+
*/
|
30 |
+
public function __construct() {
|
31 |
+
parent::__construct();
|
32 |
+
add_action( 'admin_init', [ $this, 'add_notice' ] );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Registers supported filters for payment gateway
|
37 |
+
*
|
38 |
+
* @since 1.2.0
|
39 |
+
*
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
+
public function init_supports() {
|
43 |
+
$this->supports = apply_filters( 'cpsw_local_payment_supports_' . $this->id, [ 'products', 'refunds' ] );
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Get gateway form fields
|
48 |
+
*
|
49 |
+
* @since 1.2.0
|
50 |
+
*
|
51 |
+
* @return void
|
52 |
+
*/
|
53 |
+
public function init_form_fields() {
|
54 |
+
$this->form_fields = apply_filters( 'cpsw_stripe_form_fields_' . $this->id, $this->get_local_payment_settings() );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Checks whether this gateway is available.
|
59 |
+
*
|
60 |
+
* @since 1.2.0
|
61 |
+
*
|
62 |
+
* @return boolean
|
63 |
+
*/
|
64 |
+
public function is_available() {
|
65 |
+
if ( ! empty( $this->get_option( 'allowed_countries' ) ) && 'all_except' === $this->get_option( 'allowed_countries' ) ) {
|
66 |
+
return ! in_array( $this->get_billing_country(), $this->get_option( 'except_countries', array() ), true );
|
67 |
+
} elseif ( ! empty( $this->get_option( 'allowed_countries' ) ) && 'specific' === $this->get_option( 'allowed_countries' ) ) {
|
68 |
+
return in_array( $this->get_billing_country(), $this->get_option( 'specific_countries', array() ), true );
|
69 |
+
}
|
70 |
+
|
71 |
+
return parent::is_available();
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Return a description for (for admin sections) describing the required currency & or billing country(s).
|
76 |
+
*
|
77 |
+
* @since 1.2.0
|
78 |
+
*
|
79 |
+
* @param string $desc Payment description.
|
80 |
+
*
|
81 |
+
* @return string
|
82 |
+
*/
|
83 |
+
protected function get_payment_description( $desc ) {
|
84 |
+
if ( 'all_except' === $this->get_option( 'allowed_countries' ) ) {
|
85 |
+
// translators: %s: except countries.
|
86 |
+
$desc .= sprintf( __( ' & billing country is not <strong>%s</strong>', 'checkout-plugins-stripe-woo' ), implode( ', ', $this->get_option( 'except_countries', array() ) ) );
|
87 |
+
} elseif ( 'specific' === $this->get_option( 'allowed_countries' ) ) {
|
88 |
+
// translators: %s: specificcountries.
|
89 |
+
$desc .= sprintf( __( ' & billing country is <strong>%s</strong>', 'checkout-plugins-stripe-woo' ), implode( ', ', $this->get_option( 'specific_countries', array() ) ) );
|
90 |
+
}
|
91 |
+
|
92 |
+
return $desc;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Return an array of form fields for the gateway.
|
97 |
+
*
|
98 |
+
* @since 1.2.0
|
99 |
+
*
|
100 |
+
* @return array
|
101 |
+
*/
|
102 |
+
public function get_local_payment_settings() {
|
103 |
+
$method_title = $this->method_title;
|
104 |
+
|
105 |
+
return [
|
106 |
+
'enabled' => [
|
107 |
+
'label' => ' ',
|
108 |
+
'type' => 'checkbox',
|
109 |
+
// translators: %s: Method title.
|
110 |
+
'title' => sprintf( __( 'Enable %s', 'checkout-plugins-stripe-woo' ), $method_title ),
|
111 |
+
'default' => 'no',
|
112 |
+
],
|
113 |
+
'title' => [
|
114 |
+
'title' => __( 'Title', 'checkout-plugins-stripe-woo' ),
|
115 |
+
'type' => 'text',
|
116 |
+
// translators: %s: Method title.
|
117 |
+
'description' => sprintf( __( 'Title of the %s gateway.', 'checkout-plugins-stripe-woo' ), $method_title ),
|
118 |
+
'default' => $method_title,
|
119 |
+
'desc_tip' => true,
|
120 |
+
],
|
121 |
+
'description' => [
|
122 |
+
'title' => __( 'Description', 'checkout-plugins-stripe-woo' ),
|
123 |
+
'type' => 'textarea',
|
124 |
+
'css' => 'width:25em',
|
125 |
+
/* translators: gateway title */
|
126 |
+
'description' => sprintf( __( 'Description of the %1s gateway.', 'checkout-plugins-stripe-woo' ), $method_title ),
|
127 |
+
'desc_tip' => true,
|
128 |
+
],
|
129 |
+
'order_button_text' => [
|
130 |
+
'title' => __( 'Order button label', 'checkout-plugins-stripe-woo' ),
|
131 |
+
'type' => 'text',
|
132 |
+
'description' => __( 'Customize label for order button.', 'checkout-plugins-stripe-woo' ),
|
133 |
+
// translators: %s: Method title.
|
134 |
+
'default' => sprintf( __( 'Pay with %s', 'checkout-plugins-stripe-woo' ), $method_title ),
|
135 |
+
'desc_tip' => true,
|
136 |
+
],
|
137 |
+
'allowed_countries' => [
|
138 |
+
'title' => __( 'Selling location(s)', 'checkout-plugins-stripe-woo' ),
|
139 |
+
'default' => 'all',
|
140 |
+
'type' => 'select',
|
141 |
+
'class' => 'wc-enhanced-select wc-stripe-allowed-countries',
|
142 |
+
'css' => 'min-width: 350px;',
|
143 |
+
'desc_tip' => true,
|
144 |
+
/* translators: gateway title */
|
145 |
+
'description' => sprintf( __( 'Choose the countries where you wish to display the %1$s gateway. The gateway will appear when the customer\'s billing country is in the chosen countries.', 'checkout-plugins-stripe-woo' ), $method_title ),
|
146 |
+
'options' => array(
|
147 |
+
'all' => __( 'Sell to all countries', 'checkout-plugins-stripe-woo' ),
|
148 |
+
'all_except' => __( 'Sell to all countries, except for…', 'checkout-plugins-stripe-woo' ),
|
149 |
+
'specific' => __( 'Sell to specific countries', 'checkout-plugins-stripe-woo' ),
|
150 |
+
),
|
151 |
+
],
|
152 |
+
'except_countries' => [
|
153 |
+
'title' => __( 'Sell to all countries, except for…', 'checkout-plugins-stripe-woo' ),
|
154 |
+
'type' => 'multi_select_countries',
|
155 |
+
'css' => 'min-width: 350px;',
|
156 |
+
'options' => [],
|
157 |
+
'default' => [],
|
158 |
+
'desc_tip' => true,
|
159 |
+
'description' => __( 'When the billing country matches one of these values, the payment method will be hidden on the Checkout page.', 'checkout-plugins-stripe-woo' ),
|
160 |
+
'custom_attributes' => array( 'data-show-if' => array( 'allowed_countries' => 'all_except' ) ),
|
161 |
+
'sanitize_callback' => function ( $value ) {
|
162 |
+
return is_array( $value ) ? $value : array();
|
163 |
+
},
|
164 |
+
],
|
165 |
+
'specific_countries' => [
|
166 |
+
'title' => __( 'Sell to specific countries', 'checkout-plugins-stripe-woo' ),
|
167 |
+
'type' => 'multi_select_countries',
|
168 |
+
'css' => 'min-width: 350px;',
|
169 |
+
'options' => [],
|
170 |
+
'default' => [],
|
171 |
+
'desc_tip' => true,
|
172 |
+
'description' => __( 'When the billing country matches one of these values, the payment method will be shown on the Checkout page.', 'checkout-plugins-stripe-woo' ),
|
173 |
+
'custom_attributes' => array( 'data-show-if' => array( 'allowed_countries' => 'specific' ) ),
|
174 |
+
'sanitize_callback' => function ( $value ) {
|
175 |
+
return is_array( $value ) ? $value : array();
|
176 |
+
},
|
177 |
+
],
|
178 |
+
];
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Generate multi select countries form field
|
183 |
+
*
|
184 |
+
* @since 1.2.0
|
185 |
+
*
|
186 |
+
* @param string $key Selling location field key.
|
187 |
+
* @param array $data Selling location field data.
|
188 |
+
*
|
189 |
+
* @return html
|
190 |
+
*/
|
191 |
+
public function generate_multi_select_countries_html( $key, $data ) {
|
192 |
+
$field_key = $this->get_field_key( $key );
|
193 |
+
$value = (array) $this->get_option( $key );
|
194 |
+
$data = wp_parse_args(
|
195 |
+
$data,
|
196 |
+
array(
|
197 |
+
'title' => '',
|
198 |
+
'class' => '',
|
199 |
+
'style' => '',
|
200 |
+
'description' => '',
|
201 |
+
'desc_tip' => false,
|
202 |
+
'id' => $field_key,
|
203 |
+
'options' => [],
|
204 |
+
)
|
205 |
+
);
|
206 |
+
ob_start();
|
207 |
+
$selections = (array) $value;
|
208 |
+
|
209 |
+
if ( ! empty( $data['options'] ) ) {
|
210 |
+
$countries = array_intersect_key( WC()->countries->countries, array_flip( $data['options'] ) );
|
211 |
+
} else {
|
212 |
+
$countries = WC()->countries->countries;
|
213 |
+
}
|
214 |
+
|
215 |
+
asort( $countries );
|
216 |
+
?>
|
217 |
+
<tr valign="top">
|
218 |
+
<th scope="row" class="titledesc">
|
219 |
+
<label for="<?php echo esc_attr( $data['id'] ); ?>"><?php echo esc_html( $data['title'] ); ?><?php echo $this->get_tooltip_html( $data ); //phpcs:ignore ?></label>
|
220 |
+
</th>
|
221 |
+
<td class="forminp">
|
222 |
+
<select multiple="multiple" name="<?php echo esc_attr( $data['id'] ); ?>[]" style="width:350px"
|
223 |
+
data-placeholder="<?php esc_attr_e( 'Choose countries / regions…', 'checkout-plugins-stripe-woo' ); ?>"
|
224 |
+
aria-label="<?php esc_attr_e( 'Country / Region', 'checkout-plugins-stripe-woo' ); ?>" class="wc-enhanced-select"
|
225 |
+
<?php echo $this->get_custom_attribute_html( $data ); //phpcs:ignore ?>>
|
226 |
+
<?php
|
227 |
+
if ( ! empty( $countries ) ) {
|
228 |
+
foreach ( $countries as $key => $val ) {
|
229 |
+
echo '<option value="' . esc_attr( $key ) . '"' . wc_selected( $key, $selections ) . '>' . esc_html( $val ) . '</option>'; //phpcs:ignore
|
230 |
+
}
|
231 |
+
}
|
232 |
+
?>
|
233 |
+
</select>
|
234 |
+
<?php echo $this->get_description_html( $data ); //phpcs:ignore ?>
|
235 |
+
<br/>
|
236 |
+
<a class="select_all button" href="#"><?php esc_html_e( 'Select all', 'checkout-plugins-stripe-woo' ); ?></a>
|
237 |
+
<a class="select_none button" href="#"><?php esc_html_e( 'Select none', 'checkout-plugins-stripe-woo' ); ?></a>
|
238 |
+
</td>
|
239 |
+
</tr>
|
240 |
+
<?php
|
241 |
+
return ob_get_clean();
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Validate multi select countries form field
|
246 |
+
*
|
247 |
+
* @since 1.2.0
|
248 |
+
*
|
249 |
+
* @param array $attribs Selling location custom attributes.
|
250 |
+
*
|
251 |
+
* @return array
|
252 |
+
*/
|
253 |
+
public function get_custom_attribute_html( $attribs ) {
|
254 |
+
if ( ! empty( $attribs['custom_attributes'] ) && is_array( $attribs['custom_attributes'] ) ) {
|
255 |
+
foreach ( $attribs['custom_attributes'] as $k => $v ) {
|
256 |
+
if ( is_array( $v ) ) {
|
257 |
+
$attribs['custom_attributes'][ $k ] = htmlspecialchars( wp_json_encode( $v ) );
|
258 |
+
}
|
259 |
+
}
|
260 |
+
}
|
261 |
+
|
262 |
+
return parent::get_custom_attribute_html( $attribs );
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Validate multi select countries form field
|
267 |
+
*
|
268 |
+
* @since 1.2.0
|
269 |
+
*
|
270 |
+
* @param string $key Selling location field key.
|
271 |
+
* @param array $value Selling location field data.
|
272 |
+
*
|
273 |
+
* @return array
|
274 |
+
*/
|
275 |
+
public function validate_multi_select_countries_field( $key, $value ) {
|
276 |
+
return is_array( $value ) ? array_map( 'wc_clean', array_map( 'stripslashes', $value ) ) : '';
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Gets payment gateway icons for local gateways.
|
281 |
+
*
|
282 |
+
* @since 1.2.0
|
283 |
+
*
|
284 |
+
* @return string
|
285 |
+
*/
|
286 |
+
public function get_icon() {
|
287 |
+
return $this->payment_icons( $this->id );
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Add notices
|
292 |
+
*
|
293 |
+
* @since 1.2.0
|
294 |
+
*
|
295 |
+
* @return void
|
296 |
+
*/
|
297 |
+
public function add_notice() {
|
298 |
+
$notice = Notice::get_instance();
|
299 |
+
|
300 |
+
if ( ! $notice->is_cpsw_section( $this->id ) ) {
|
301 |
+
return;
|
302 |
+
}
|
303 |
+
|
304 |
+
// Add notice if missing webhook secret key.
|
305 |
+
if (
|
306 |
+
'no' !== get_option( 'cpsw_show_webhook_secret_notice' ) &&
|
307 |
+
! Helper::get_webhook_secret()
|
308 |
+
) {
|
309 |
+
/* translators: %1$s Webhook secret page link, %3$s Payment method, %4$s Webhook guide page link */
|
310 |
+
$notice->add( 'webhook_secret', 'notice notice-warning', sprintf( __( 'Stripe recommends using the %1$swebhook%2$s for %3$s. %4$sWebhook Guide%5$s ', 'checkout-plugins-stripe-woo' ), '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=cpsw_api_settings' ) . '">', '</a>', $this->method_title, '<a href="https://checkoutplugins.com/docs/stripe-card-payments/#webhook" target="_blank">', '</a>' ), true );
|
311 |
+
}
|
312 |
+
|
313 |
+
// Add notice if currency not supported.
|
314 |
+
if (
|
315 |
+
method_exists( $this, 'get_supported_currency' ) &&
|
316 |
+
! in_array( get_woocommerce_currency(), $this->get_supported_currency(), true ) &&
|
317 |
+
'no' !== get_option( 'cpsw_show_' . $this->id . '_currency_notice' )
|
318 |
+
) {
|
319 |
+
/* translators: %1$s Payment method, %2$s List of supported currencies */
|
320 |
+
$notice->add( $this->id . '_currency', 'notice notice-error', sprintf( __( '%1$s is enabled - it requires store currency to be set to %2$s.', 'checkout-plugins-stripe-woo' ), ucfirst( str_replace( 'cpsw_', '', $this->id ) ), implode( ', ', $this->get_supported_currency() ) ), true );
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Return a description for (for admin sections) describing the required currency & or billing country(s).
|
326 |
+
*
|
327 |
+
* @since 1.2.0
|
328 |
+
*
|
329 |
+
* @return string
|
330 |
+
*/
|
331 |
+
public function payment_description() {
|
332 |
+
$desc = '';
|
333 |
+
if ( $this->get_supported_currency() ) {
|
334 |
+
// translators: %s: supported currency.
|
335 |
+
$desc .= sprintf( __( 'This gateway will appear when store currency is <strong>%s</strong>.', 'checkout-plugins-stripe-woo' ), implode( ', ', $this->get_supported_currency() ) );
|
336 |
+
}
|
337 |
+
|
338 |
+
return $this->get_payment_description( $desc );
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Get test mode description for local gateways
|
343 |
+
*
|
344 |
+
* @return string
|
345 |
+
* @since 1.2.0
|
346 |
+
*/
|
347 |
+
public function get_test_mode_description() {
|
348 |
+
/* translators: HTML Entities. */
|
349 |
+
return apply_filters( 'cpsw_local_gateway_test_description', sprintf( esc_html__( '%1$1s%2$2sTest Mode Enabled%3$3s : You will be redirected to an authorization page hosted by Stripe.', 'checkout-plugins-stripe-woo' ), '<br/>', '<strong>', '</strong>' ) );
|
350 |
+
}
|
351 |
+
}
|
gateway/stripe/alipay.php
ADDED
@@ -0,0 +1,336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Alipay Gateway
|
4 |
+
*
|
5 |
+
* @package checkout-plugins-stripe-woo
|
6 |
+
* @since 1.2.0
|
7 |
+
*/
|
8 |
+
|
9 |
+
namespace CPSW\Gateway\Stripe;
|
10 |
+
|
11 |
+
use CPSW\Inc\Helper;
|
12 |
+
use CPSW\Inc\Logger;
|
13 |
+
use CPSW\Inc\Traits\Get_Instance;
|
14 |
+
use CPSW\Gateway\Local_Gateway;
|
15 |
+
use WC_AJAX;
|
16 |
+
use Exception;
|
17 |
+
use WP_Error;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Alipay
|
21 |
+
*
|
22 |
+
* @since 1.2.0
|
23 |
+
*/
|
24 |
+
class Alipay extends Local_Gateway {
|
25 |
+
|
26 |
+
use Get_Instance;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Gateway id
|
30 |
+
*
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
public $id = 'cpsw_alipay';
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Constructor
|
37 |
+
*
|
38 |
+
* @since 1.2.0
|
39 |
+
*/
|
40 |
+
public function __construct() {
|
41 |
+
parent::__construct();
|
42 |
+
|
43 |
+
$this->method_title = __( 'Alipay', 'checkout-plugins-stripe-woo' );
|
44 |
+
$this->method_description = $this->method_description();
|
45 |
+
$this->has_fields = true;
|
46 |
+
$this->init_supports();
|
47 |
+
|
48 |
+
$this->init_form_fields();
|
49 |
+
$this->init_settings();
|
50 |
+
// get_option should be called after init_form_fields().
|
51 |
+
$this->title = $this->get_option( 'title' );
|
52 |
+
$this->description = $this->get_option( 'description' );
|
53 |
+
$this->order_button_text = $this->get_option( 'order_button_text' );
|
54 |
+
|
55 |
+
add_action( 'wc_ajax_cpsw_verify_alipay_payment_intent', [ $this, 'verify_intent' ] );
|
56 |
+
add_filter( 'woocommerce_payment_successful_result', [ $this, 'modify_successful_payment_result' ], 999, 2 );
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Description for alipay gateway
|
61 |
+
*
|
62 |
+
* @since 1.2.0
|
63 |
+
*
|
64 |
+
* @return string
|
65 |
+
*/
|
66 |
+
public function method_description() {
|
67 |
+
$payment_description = $this->payment_description();
|
68 |
+
|
69 |
+
return sprintf(
|
70 |
+
/* translators: %1$s: Break, %2$s: Gateway appear message, %3$s: Break, %4$s: Gateway appear message currency wise, %4$s: HTML entities */
|
71 |
+
__( 'Accept payment using Alipay. %1$s %2$s %3$s %4$s', 'checkout-plugins-stripe-woo' ),
|
72 |
+
'<br/>',
|
73 |
+
$payment_description,
|
74 |
+
'<br/>',
|
75 |
+
/* translators: HTML Entities.*/
|
76 |
+
sprintf( __( '%1$sEUR%2$s is supported only for billing country %1$sDenmark (DK), Norway (NO), Sweden (SE) & Switzerland (CH)%2$s.', 'checkout-plugins-stripe-woo' ), '<strong>', '</strong>' ),
|
77 |
+
);
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Returns all supported currencies for this payment method.
|
82 |
+
*
|
83 |
+
* @since 1.2.0
|
84 |
+
*
|
85 |
+
* @return array
|
86 |
+
*/
|
87 |
+
public function get_supported_currency() {
|
88 |
+
return apply_filters(
|
89 |
+
'cpsw_alipay_supported_currencies',
|
90 |
+
[
|
91 |
+
'EUR',
|
92 |
+
'AUD',
|
93 |
+
'CAD',
|
94 |
+
'CNY',
|
95 |
+
'GBP',
|
96 |
+
'HKD',
|
97 |
+
'JPY',
|
98 |
+
'NZD',
|
99 |
+
'SGD',
|
100 |
+
'USD',
|
101 |
+
'MYR',
|
102 |
+
]
|
103 |
+
);
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Checks whether this gateway is available.
|
108 |
+
*
|
109 |
+
* @since 1.2.0
|
110 |
+
*
|
111 |
+
* @return boolean
|
112 |
+
*/
|
113 |
+
public function is_available() {
|
114 |
+
if ( ! in_array( $this->get_currency(), $this->get_supported_currency(), true ) ) {
|
115 |
+
return false;
|
116 |
+
}
|
117 |
+
|
118 |
+
if ( 'EUR' === $this->get_currency() && ! in_array( $this->get_billing_country(), [ 'DK', 'NO', 'SE', 'CH' ], true ) ) {
|
119 |
+
return false;
|
120 |
+
}
|
121 |
+
|
122 |
+
return parent::is_available();
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Creates markup for payment form for card payments
|
127 |
+
*
|
128 |
+
* @since 1.2.0
|
129 |
+
*
|
130 |
+
* @return void
|
131 |
+
*/
|
132 |
+
public function payment_fields() {
|
133 |
+
global $wp;
|
134 |
+
|
135 |
+
$user = wp_get_current_user();
|
136 |
+
$total = WC()->cart->total;
|
137 |
+
|
138 |
+
// If paying from order, we need to get total from order not cart.
|
139 |
+
if ( isset( $_GET['pay_for_order'] ) && ! empty( $_GET['key'] ) ) { // phpcs:ignore
|
140 |
+
$order = wc_get_order( wc_clean( $wp->query_vars['order-pay'] ) );
|
141 |
+
$total = $order->get_total();
|
142 |
+
}
|
143 |
+
|
144 |
+
if ( is_add_payment_method_page() ) {
|
145 |
+
$pay_button_text = __( 'Add Payment', 'checkout-plugins-stripe-woo' );
|
146 |
+
$total = '';
|
147 |
+
} else {
|
148 |
+
$pay_button_text = '';
|
149 |
+
}
|
150 |
+
|
151 |
+
echo '<div
|
152 |
+
id="cpsw-alipay-payment-data"
|
153 |
+
data-amount="' . esc_attr( $total ) . '"
|
154 |
+
data-currency="' . esc_attr( strtolower( $this->get_currency() ) ) . '">';
|
155 |
+
|
156 |
+
if ( $this->description ) {
|
157 |
+
echo wp_kses_post( $this->description );
|
158 |
+
}
|
159 |
+
|
160 |
+
echo '</div>';
|
161 |
+
if ( 'test' === Helper::get_payment_mode() ) {
|
162 |
+
echo '<div class="cpsw_stripe_alipay_test_description">';
|
163 |
+
echo wp_kses_post( $this->get_test_mode_description() );
|
164 |
+
echo '</div>';
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Verify intent state and redirect.
|
170 |
+
*
|
171 |
+
* @since 1.2.0
|
172 |
+
*
|
173 |
+
* @return void
|
174 |
+
*/
|
175 |
+
public function verify_intent() {
|
176 |
+
$order_id = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
177 |
+
$order = wc_get_order( $order_id );
|
178 |
+
|
179 |
+
$intent_secret = get_post_meta( $order_id, '_cpsw_intent_secret', true );
|
180 |
+
$stripe_api = new Stripe_Api();
|
181 |
+
$response = $stripe_api->payment_intents( 'retrieve', [ $intent_secret['id'] ] );
|
182 |
+
$intent = $response['success'] ? $response['data'] : false;
|
183 |
+
|
184 |
+
if ( 'succeeded' === $intent->status || 'requires_capture' === $intent->status ) {
|
185 |
+
$redirect_to = $this->process_order( end( $intent->charges->data ), $order_id );
|
186 |
+
$redirect_url = apply_filters( 'cpsw_redirect_order_url', $redirect_to, $order );
|
187 |
+
wp_safe_redirect( $redirect_url );
|
188 |
+
} elseif ( isset( $response['data']->last_payment_error ) ) {
|
189 |
+
$message = isset( $response['data']->last_payment_error->message ) ? $response['data']->last_payment_error->message : '';
|
190 |
+
|
191 |
+
// translators: %s: payment fail message.
|
192 |
+
wc_add_notice( sprintf( __( 'Payment failed. %s', 'checkout-plugins-stripe-woo' ), $message ), 'error' );
|
193 |
+
wp_safe_redirect( wc_get_checkout_url() );
|
194 |
+
}
|
195 |
+
exit();
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Process order after stripe payment
|
200 |
+
*
|
201 |
+
* @since 1.2.0
|
202 |
+
*
|
203 |
+
* @param object $response intent response data.
|
204 |
+
* @param string $order_id currnt coocommerce id.
|
205 |
+
*
|
206 |
+
* @return array return data.
|
207 |
+
*/
|
208 |
+
public function process_order( $response, $order_id ) {
|
209 |
+
$order = wc_get_order( $order_id );
|
210 |
+
|
211 |
+
if ( true === $response->captured ) {
|
212 |
+
$order->payment_complete( $response->id );
|
213 |
+
/* translators: order id */
|
214 |
+
Logger::info( sprintf( __( 'Payment successful Order id - %1s', 'checkout-plugins-stripe-woo' ), $order->get_id() ), true );
|
215 |
+
}
|
216 |
+
if ( ! $response->captured ) {
|
217 |
+
/* translators: transaction id */
|
218 |
+
$order->update_status( 'on-hold', sprintf( __( 'Charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization. Attempting to refund the order in part or in full will release the authorization and cancel the payment.', 'checkout-plugins-stripe-woo' ), $response->id ) );
|
219 |
+
/* translators: transaction id */
|
220 |
+
Logger::info( sprintf( __( 'Charge authorized Order id - %1s', 'checkout-plugins-stripe-woo' ), $order->get_id() ), true );
|
221 |
+
}
|
222 |
+
|
223 |
+
$order->add_order_note( __( 'Payment Status : ', 'checkout-plugins-stripe-woo' ) . ucfirst( $response->status ) . __( ' Source : ', 'checkout-plugins-stripe-woo' ) . $response->payment_method_details->type );
|
224 |
+
WC()->cart->empty_cart();
|
225 |
+
|
226 |
+
return $this->get_return_url( $order );
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Modify redirect url
|
231 |
+
*
|
232 |
+
* @since 1.2.0
|
233 |
+
*
|
234 |
+
* @param array $result redirect url array.
|
235 |
+
* @param int $order_id woocommerce order id.
|
236 |
+
*
|
237 |
+
* @return array modified redirect url array.
|
238 |
+
*/
|
239 |
+
public function modify_successful_payment_result( $result, $order_id ) {
|
240 |
+
if ( empty( $order_id ) ) {
|
241 |
+
return $result;
|
242 |
+
}
|
243 |
+
|
244 |
+
$order = wc_get_order( $order_id );
|
245 |
+
|
246 |
+
if ( $this->id !== $order->get_payment_method() ) {
|
247 |
+
return $result;
|
248 |
+
}
|
249 |
+
|
250 |
+
if ( ! isset( $result['intent_secret'] ) ) {
|
251 |
+
return $result;
|
252 |
+
}
|
253 |
+
|
254 |
+
// Put the final thank you page redirect into the verification URL.
|
255 |
+
$verification_url = add_query_arg(
|
256 |
+
[
|
257 |
+
'order' => $order_id,
|
258 |
+
'confirm_payment_nonce' => wp_create_nonce( 'cpsw_confirm_payment_intent' ),
|
259 |
+
'redirect_to' => rawurlencode( $result['redirect'] ),
|
260 |
+
],
|
261 |
+
WC_AJAX::get_endpoint( 'cpsw_verify_alipay_payment_intent' )
|
262 |
+
);
|
263 |
+
|
264 |
+
// Combine into a hash.
|
265 |
+
$redirect = sprintf( '#confirm-pi-%s:%s', $result['intent_secret'], rawurlencode( $verification_url ) );
|
266 |
+
|
267 |
+
return [
|
268 |
+
'result' => 'success',
|
269 |
+
'redirect' => $redirect,
|
270 |
+
];
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Process woocommerce orders after payment is done
|
275 |
+
*
|
276 |
+
* @since 1.2.0
|
277 |
+
*
|
278 |
+
* @param int $order_id wooCommerce order id.
|
279 |
+
*
|
280 |
+
* @return array data to redirect after payment processing.
|
281 |
+
*/
|
282 |
+
public function process_payment( $order_id ) {
|
283 |
+
try {
|
284 |
+
$order = wc_get_order( $order_id );
|
285 |
+
$customer_id = $this->get_customer_id( $order );
|
286 |
+
$idempotency_key = $order->get_order_key() . time();
|
287 |
+
|
288 |
+
$data = [
|
289 |
+
'amount' => $this->get_formatted_amount( $order->get_total() ),
|
290 |
+
'currency' => $this->get_currency(),
|
291 |
+
'description' => $this->get_order_description( $order ),
|
292 |
+
'metadata' => $this->get_metadata( $order_id ),
|
293 |
+
'payment_method_types' => [ 'alipay' ],
|
294 |
+
'customer' => $customer_id,
|
295 |
+
];
|
296 |
+
|
297 |
+
/* translators: %1$1s order id, %2$2s order total amount */
|
298 |
+
Logger::info( sprintf( __( 'Begin processing payment with Alipay for order %1$1s for the amount of %2$2s', 'checkout-plugins-stripe-woo' ), $order_id, $order->get_total() ) );
|
299 |
+
$intent_data = $this->get_payment_intent( $order_id, $idempotency_key, $data, true );
|
300 |
+
|
301 |
+
if ( $intent_data ) {
|
302 |
+
if ( isset( $intent_data['success'] ) && false === $intent_data['success'] ) {
|
303 |
+
$error = '';
|
304 |
+
if ( 'currency' === $intent_data['type'] ) {
|
305 |
+
$error = __( 'Contact seller. ', 'checkout-plugins-stripe-woo' );
|
306 |
+
|
307 |
+
if ( 'test' === Helper::get_payment_mode() ) {
|
308 |
+
$error = __( 'Store currency doesn\'t match stripe currency. ', 'checkout-plugins-stripe-woo' );
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
wc_add_notice( $error . $intent_data['message'], 'error' );
|
313 |
+
|
314 |
+
return [
|
315 |
+
'result' => 'fail',
|
316 |
+
'redirect' => '',
|
317 |
+
];
|
318 |
+
}
|
319 |
+
|
320 |
+
return [
|
321 |
+
'result' => 'success',
|
322 |
+
'redirect' => false,
|
323 |
+
'intent_secret' => $intent_data['client_secret'],
|
324 |
+
];
|
325 |
+
} else {
|
326 |
+
return [
|
327 |
+
'result' => 'fail',
|
328 |
+
'redirect' => '',
|
329 |
+
];
|
330 |
+
}
|
331 |
+
} catch ( Exception $e ) {
|
332 |
+
Logger::error( $e->getMessage(), true );
|
333 |
+
return new WP_Error( 'order-error', '<div class="woocommerce-error">' . $e->getMessage() . '</div>', [ 'status' => 200 ] );
|
334 |
+
}
|
335 |
+
}
|
336 |
+
}
|
gateway/stripe/card-payments.php
CHANGED
@@ -13,7 +13,6 @@ use CPSW\Inc\Logger;
|
|
13 |
use CPSW\Inc\Traits\Get_Instance;
|
14 |
use CPSW\Inc\Traits\Subscriptions;
|
15 |
use CPSW\Gateway\Abstract_Payment_Gateway;
|
16 |
-
use CPSW\Gateway\Stripe\Frontend_Scripts;
|
17 |
use CPSW\Gateway\Stripe\Stripe_Api;
|
18 |
use WC_AJAX;
|
19 |
use WC_HTTPS;
|
@@ -31,19 +30,6 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
31 |
use Get_Instance;
|
32 |
use Subscriptions;
|
33 |
|
34 |
-
/**
|
35 |
-
* Zero currencies accepted by stripe.
|
36 |
-
*
|
37 |
-
* @var array
|
38 |
-
*/
|
39 |
-
private static $zero_currencies = [ 'BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VUV', 'XAF', 'XOF', 'XPF', 'VND' ];
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Temporary array of allowed cards, further data will be taken from user
|
43 |
-
*
|
44 |
-
* @var array
|
45 |
-
*/
|
46 |
-
|
47 |
/**
|
48 |
* Gateway id
|
49 |
*
|
@@ -57,7 +43,7 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
57 |
* @since 0.0.1
|
58 |
*/
|
59 |
public function __construct() {
|
60 |
-
|
61 |
|
62 |
$this->method_title = __( 'Stripe Card Processing', 'checkout-plugins-stripe-woo' );
|
63 |
$this->method_description = __( 'Accepts payments via Credit/Debit Cards', 'checkout-plugins-stripe-woo' );
|
@@ -77,12 +63,9 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
77 |
$this->allowed_cards = empty( $this->get_option( 'allowed_cards' ) ) ? [ 'mastercard', 'visa', 'diners', 'discover', 'amex', 'jcb', 'unionpay' ] : $this->get_option( 'allowed_cards' );
|
78 |
$this->statement_descriptor = $this->clean_statement_descriptor( $this->get_option( 'statement_descriptor' ) );
|
79 |
|
80 |
-
add_action( 'woocommerce_init', [ $this, 'woocommerce_dependencies' ] );
|
81 |
-
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
|
82 |
add_filter( 'woocommerce_payment_successful_result', [ $this, 'modify_successful_payment_result' ], 999, 2 );
|
83 |
add_action( 'wc_ajax_cpsw_verify_payment_intent', [ $this, 'verify_intent' ] );
|
84 |
add_filter( 'woocommerce_payment_complete_order_status', [ $this, 'cpsw_payment_complete_order_status' ], 10, 3 );
|
85 |
-
|
86 |
}
|
87 |
|
88 |
/**
|
@@ -100,62 +83,15 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
100 |
];
|
101 |
}
|
102 |
|
103 |
-
/**
|
104 |
-
* Registering Gateway to WooCommerce
|
105 |
-
*
|
106 |
-
* @param array $methods List of registered gateways.
|
107 |
-
* @return array
|
108 |
-
*/
|
109 |
-
public function add_gateway_class( $methods ) {
|
110 |
-
$methods[] = $this;
|
111 |
-
return $methods;
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* Includes woocomerce dependencies.
|
116 |
-
*
|
117 |
-
* @return void
|
118 |
-
*/
|
119 |
-
public function woocommerce_dependencies() {
|
120 |
-
if ( is_admin() ) {
|
121 |
-
return;
|
122 |
-
}
|
123 |
-
Frontend_Scripts::get_instance();
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Checks whether this gateway is available.
|
128 |
-
*
|
129 |
-
* @return boolean
|
130 |
-
*/
|
131 |
-
public function is_available() {
|
132 |
-
if ( 'yes' === $this->enabled ) {
|
133 |
-
if ( ! Helper::get_payment_mode() && is_checkout() ) {
|
134 |
-
return false;
|
135 |
-
}
|
136 |
-
if ( 'test' === Helper::get_payment_mode() ) {
|
137 |
-
if ( empty( Helper::get_setting( 'cpsw_test_pub_key' ) ) || empty( Helper::get_setting( 'cpsw_test_secret_key' ) ) ) {
|
138 |
-
return false;
|
139 |
-
}
|
140 |
-
} else {
|
141 |
-
if ( empty( Helper::get_setting( 'cpsw_pub_key' ) ) || empty( Helper::get_setting( 'cpsw_secret_key' ) ) ) {
|
142 |
-
return false;
|
143 |
-
}
|
144 |
-
}
|
145 |
-
return true;
|
146 |
-
}
|
147 |
-
return false;
|
148 |
-
}
|
149 |
-
|
150 |
/**
|
151 |
* Gateway form fields
|
152 |
*
|
153 |
* @return void
|
154 |
-
*/
|
155 |
public function init_form_fields() {
|
156 |
$this->form_fields = [
|
157 |
'enabled' => [
|
158 |
-
'label' =>
|
159 |
'type' => 'checkbox',
|
160 |
'title' => __( 'Enable Stripe Gateway', 'checkout-plugins-stripe-woo' ),
|
161 |
'default' => 'no',
|
@@ -276,6 +212,7 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
276 |
'description' => $this->get_order_description( $order ),
|
277 |
'payment_method_types' => [ 'card' ],
|
278 |
'payment_method' => $payment_method,
|
|
|
279 |
'customer' => $customer_id,
|
280 |
'capture_method' => $this->capture_method,
|
281 |
];
|
@@ -290,12 +227,12 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
290 |
|
291 |
/* translators: %1$1s order id, %2$2s order total amount */
|
292 |
Logger::info( sprintf( __( 'Begin processing payment with new payment method for order %1$1s for the amount of %2$2s', 'checkout-plugins-stripe-woo' ), $order_id, $order->get_total() ) );
|
293 |
-
$intent_data = $this->get_payment_intent( $order_id, $
|
294 |
if ( $intent_data ) {
|
295 |
return [
|
296 |
'result' => 'success',
|
297 |
'redirect' => $this->get_return_url( $order ),
|
298 |
-
'payment_method' => $
|
299 |
'intent_secret' => $intent_data['client_secret'],
|
300 |
'save_card' => $this->should_save_card( $order_id ),
|
301 |
];
|
@@ -350,6 +287,7 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
350 |
'currency' => strtolower( $order->get_currency() ),
|
351 |
'description' => $this->get_order_description( $order ),
|
352 |
'customer' => $payment_method->customer,
|
|
|
353 |
'confirm' => true,
|
354 |
'capture_method' => $this->capture_method,
|
355 |
];
|
@@ -506,74 +444,6 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
506 |
return ( isset( $_POST[ 'wc-' . $payment_method . '-payment-token' ] ) && 'new' !== $_POST[ 'wc-' . $payment_method . '-payment-token' ] ); //phpcs:ignore WordPress.Security.NonceVerification.Missing
|
507 |
}
|
508 |
|
509 |
-
/**
|
510 |
-
* Process response for saved cards
|
511 |
-
*
|
512 |
-
* @param object $response intent response.
|
513 |
-
* @param object $order order response.
|
514 |
-
* @return array
|
515 |
-
*/
|
516 |
-
public function process_response( $response, $order ) {
|
517 |
-
Logger::info( 'Processing: ' . $response->id );
|
518 |
-
|
519 |
-
$order_id = $order->get_id();
|
520 |
-
$captured = ( isset( $response->captured ) && $response->captured ) ? 'yes' : 'no';
|
521 |
-
|
522 |
-
// Store charge data.
|
523 |
-
$order->update_meta_data( '_cpsw_charge_captured', $captured );
|
524 |
-
|
525 |
-
if ( 'yes' === $captured ) {
|
526 |
-
/**
|
527 |
-
* Charge can be captured but in a pending state. Payment methods
|
528 |
-
* that are asynchronous may take couple days to clear. Webhook will
|
529 |
-
* take care of the status changes.
|
530 |
-
*/
|
531 |
-
if ( 'pending' === $response->status ) {
|
532 |
-
$order_stock_reduced = $order->get_meta( '_order_stock_reduced', true );
|
533 |
-
|
534 |
-
if ( ! $order_stock_reduced ) {
|
535 |
-
wc_reduce_stock_levels( $order_id );
|
536 |
-
}
|
537 |
-
|
538 |
-
$order->set_transaction_id( $response->id );
|
539 |
-
/* translators: transaction id */
|
540 |
-
$order->update_status( 'on-hold', sprintf( __( 'Stripe charge awaiting payment: %s.', 'checkout-plugins-stripe-woo' ), $response->id ) );
|
541 |
-
}
|
542 |
-
|
543 |
-
if ( 'succeeded' === $response->status ) {
|
544 |
-
$order->payment_complete( $response->id );
|
545 |
-
|
546 |
-
/* translators: transaction id */
|
547 |
-
$message = sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'checkout-plugins-stripe-woo' ), $response->id );
|
548 |
-
Logger::info( $message, true );
|
549 |
-
$order->add_order_note( $message );
|
550 |
-
}
|
551 |
-
|
552 |
-
if ( 'failed' === $response->status ) {
|
553 |
-
$message = __( 'Payment processing failed. Please retry.', 'checkout-plugins-stripe-woo' );
|
554 |
-
Logger::error( $message, true );
|
555 |
-
$order->add_order_note( $message );
|
556 |
-
}
|
557 |
-
} else {
|
558 |
-
$order->set_transaction_id( $response->id );
|
559 |
-
|
560 |
-
if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
|
561 |
-
wc_reduce_stock_levels( $order_id );
|
562 |
-
}
|
563 |
-
|
564 |
-
/* translators: transaction id */
|
565 |
-
$order->update_status( 'on-hold', sprintf( __( 'Stripe charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization. Attempting to refund the order in part or in full will release the authorization and cancel the payment.', 'checkout-plugins-stripe-woo' ), $response->id ) );
|
566 |
-
}
|
567 |
-
|
568 |
-
if ( is_callable( [ $order, 'save' ] ) ) {
|
569 |
-
$order->save();
|
570 |
-
}
|
571 |
-
|
572 |
-
do_action( 'cpsw_process_response', $response, $order );
|
573 |
-
|
574 |
-
return $response;
|
575 |
-
}
|
576 |
-
|
577 |
/**
|
578 |
* Get token object for selected saved card payment
|
579 |
*
|
@@ -640,58 +510,6 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
640 |
];
|
641 |
}
|
642 |
|
643 |
-
/**
|
644 |
-
* Checks if payment intent available for current order or else creates new payment intent.
|
645 |
-
*
|
646 |
-
* @param int $order_id woocommerce order id.
|
647 |
-
* @param string $payment_method cc payment method id.
|
648 |
-
* @param string $customer_id customer id.
|
649 |
-
* @param string $idempotency_key unique idempotency key.
|
650 |
-
* @param array $args payment_intent arguments.
|
651 |
-
* @return array intent data.
|
652 |
-
*/
|
653 |
-
public function get_payment_intent( $order_id, $payment_method, $customer_id, $idempotency_key, $args ) {
|
654 |
-
$intent_secret = get_post_meta( $order_id, '_cpsw_intent_secret', true );
|
655 |
-
$client_secret = '';
|
656 |
-
|
657 |
-
if ( ! empty( $intent_secret ) ) {
|
658 |
-
$secret = $intent_secret;
|
659 |
-
$stripe_api = new Stripe_Api();
|
660 |
-
$response = $stripe_api->payment_intents( 'retrieve', [ $secret['id'] ] );
|
661 |
-
if ( $response['success'] && 'success' === $response['data']->status ) {
|
662 |
-
wc_add_notice( __( 'An error has occurred internally, due to which you are not redirected to the order received page.', 'checkout-plugins-stripe-woo' ), $notice_type = 'error' );
|
663 |
-
wp_safe_redirect( wc_get_checkout_url() );
|
664 |
-
}
|
665 |
-
}
|
666 |
-
|
667 |
-
$args = [
|
668 |
-
[ $args ],
|
669 |
-
[ 'idempotency_key' => $idempotency_key ],
|
670 |
-
];
|
671 |
-
|
672 |
-
$stripe_api = new Stripe_Api();
|
673 |
-
$response = $stripe_api->payment_intents( 'create', $args );
|
674 |
-
|
675 |
-
if ( $response['success'] ) {
|
676 |
-
$intent = $response['data'];
|
677 |
-
} else {
|
678 |
-
wc_add_notice( $response['message'], 'error' );
|
679 |
-
return false;
|
680 |
-
}
|
681 |
-
|
682 |
-
$intent_data = [
|
683 |
-
'id' => $intent->id,
|
684 |
-
'client_secret' => $intent->client_secret,
|
685 |
-
];
|
686 |
-
update_post_meta( $order_id, '_cpsw_intent_secret', $intent_data, );
|
687 |
-
$client_secret = $intent->client_secret;
|
688 |
-
|
689 |
-
return [
|
690 |
-
'payment_method' => $payment_method,
|
691 |
-
'client_secret' => $client_secret,
|
692 |
-
];
|
693 |
-
}
|
694 |
-
|
695 |
/**
|
696 |
* Verify intent state and redirect.
|
697 |
*
|
@@ -786,7 +604,7 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
786 |
* Process order after stripe payment
|
787 |
*
|
788 |
* @param object $response intent response data.
|
789 |
-
* @param string $order_id
|
790 |
* @return array return data.
|
791 |
*/
|
792 |
public function process_order( $response, $order_id ) {
|
@@ -808,10 +626,7 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
808 |
$order->add_order_note( __( 'Payment Status : ', 'checkout-plugins-stripe-woo' ) . ucfirst( $response->status ) . __( ' Source : ', 'checkout-plugins-stripe-woo' ) . $response->payment_method_details->card->brand );
|
809 |
WC()->cart->empty_cart();
|
810 |
|
811 |
-
return
|
812 |
-
'result' => 'success',
|
813 |
-
'redirect' => $this->get_return_url( $order ),
|
814 |
-
];
|
815 |
}
|
816 |
|
817 |
/**
|
@@ -822,6 +637,15 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
822 |
* @return array modified redirect url array.
|
823 |
*/
|
824 |
public function modify_successful_payment_result( $result, $order_id ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
825 |
if ( ! isset( $result['intent_secret'] ) ) {
|
826 |
return $result;
|
827 |
}
|
@@ -846,125 +670,6 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
846 |
];
|
847 |
}
|
848 |
|
849 |
-
/**
|
850 |
-
* Creates stripe customer object
|
851 |
-
*
|
852 |
-
* @param object $order woocommerce order object.
|
853 |
-
* @param boolean|string $user_email user email id.
|
854 |
-
* @return Stripe::Customer
|
855 |
-
*/
|
856 |
-
public function create_stripe_customer( $order = false, $user_email = false ) {
|
857 |
-
$args = [
|
858 |
-
'email' => $user_email,
|
859 |
-
];
|
860 |
-
if ( $order ) {
|
861 |
-
$args = [
|
862 |
-
'description' => 'Customer for Order #' . $order->get_id(),
|
863 |
-
'email' => $user_email ? $user_email : $order->get_billing_email(),
|
864 |
-
'address' => [ // sending name and billing address to stripe to support indian exports.
|
865 |
-
'city' => method_exists( $order, 'get_billing_city' ) ? $order->get_billing_city() : $order->billing_city,
|
866 |
-
'country' => method_exists( $order, 'get_billing_country' ) ? $order->get_billing_country() : $order->billing_country,
|
867 |
-
'line1' => method_exists( $order, 'get_billing_address_1' ) ? $order->get_billing_address_1() : $order->billing_address_1,
|
868 |
-
'line2' => method_exists( $order, 'get_billing_address_2' ) ? $order->get_billing_address_2() : $order->billing_address_2,
|
869 |
-
'postal_code' => method_exists( $order, 'get_billing_postcode' ) ? $order->get_billing_postcode() : $order->billing_postcode,
|
870 |
-
'state' => method_exists( $order, 'get_billing_state' ) ? $order->get_billing_state() : $order->billing_state,
|
871 |
-
],
|
872 |
-
'name' => ( method_exists( $order, 'get_billing_first_name' ) ? $order->get_billing_first_name() : $order->billing_first_name ) . ( method_exists( $order, 'get_billing_last_name' ) ? $order->get_billing_last_name() : $order->billing_last_name ),
|
873 |
-
];
|
874 |
-
}
|
875 |
-
|
876 |
-
$stripe_api = new Stripe_Api();
|
877 |
-
$response = $stripe_api->customers( 'create', [ $args ] );
|
878 |
-
$response = $response['success'] ? $response['data'] : false;
|
879 |
-
|
880 |
-
if ( empty( $response->id ) ) {
|
881 |
-
return false;
|
882 |
-
}
|
883 |
-
|
884 |
-
return $response;
|
885 |
-
}
|
886 |
-
|
887 |
-
/**
|
888 |
-
* Refunds amount from stripe and return true/false as result
|
889 |
-
*
|
890 |
-
* @param string $order_id order id.
|
891 |
-
* @param string $amount refund amount.
|
892 |
-
* @param string $reason reason of refund.
|
893 |
-
* @return bool
|
894 |
-
*/
|
895 |
-
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
896 |
-
|
897 |
-
if ( 0 >= $amount ) {
|
898 |
-
return false;
|
899 |
-
}
|
900 |
-
|
901 |
-
try {
|
902 |
-
|
903 |
-
$order = wc_get_order( $order_id );
|
904 |
-
$intent_secret = $order->get_meta( '_cpsw_intent_secret', true );
|
905 |
-
|
906 |
-
$response = $this->create_refund_request( $order, $amount, $reason, $intent_secret['id'] );
|
907 |
-
|
908 |
-
$refund_response = $response['success'] ? $response['data'] : false;
|
909 |
-
|
910 |
-
if ( $refund_response ) {
|
911 |
-
$refund_time = gmdate( 'Y-m-d H:i:s', time() );
|
912 |
-
$order->add_order_note( __( 'Reason : ', 'checkout-plugins-stripe-woo' ) . $reason . '.<br>' . __( 'Amount : ', 'checkout-plugins-stripe-woo' ) . get_woocommerce_currency_symbol() . $amount . '.<br>' . __( 'Status : ', 'checkout-plugins-stripe-woo' ) . ( ( 'succeeded' === $refund_response->status ) ? 'Success' : 'Failed' ) . ' [ ' . $refund_time . ' ] ' . ( is_null( $refund_response->id ) ? '' : '<br>' . __( 'Transaction ID : ', 'checkout-plugins-stripe-woo' ) . $refund_response->id ) );
|
913 |
-
Logger::info( __( 'Refund initiated: ', 'checkout-plugins-stripe-woo' ) . __( 'Reason : ', 'checkout-plugins-stripe-woo' ) . $reason . __( 'Amount : ', 'checkout-plugins-stripe-woo' ) . get_woocommerce_currency_symbol() . $amount . __( 'Status : ', 'checkout-plugins-stripe-woo' ) . ( ( 'succeeded' === $refund_response->status ) ? 'Success' : 'Failed' ) . ' [ ' . $refund_time . ' ] ' . ( is_null( $refund_response->id ) ? '' : __( 'Transaction ID : ', 'checkout-plugins-stripe-woo' ) . $refund_response->id ), true );
|
914 |
-
return true;
|
915 |
-
} else {
|
916 |
-
$order->add_order_note( __( 'Reason : ', 'checkout-plugins-stripe-woo' ) . $reason . '.<br>' . __( 'Amount : ', 'checkout-plugins-stripe-woo' ) . get_woocommerce_currency_symbol() . $amount . '.<br>' . __( ' Status : Failed ', 'checkout-plugins-stripe-woo' ) );
|
917 |
-
Logger::error( $response['message'], true );
|
918 |
-
return new WP_Error( 'error', $response['message'] );
|
919 |
-
}
|
920 |
-
} catch ( Exception $e ) {
|
921 |
-
Logger::error( $e->getMessage(), true );
|
922 |
-
}
|
923 |
-
}
|
924 |
-
|
925 |
-
/**
|
926 |
-
* Create refund request.
|
927 |
-
*
|
928 |
-
* @param object $order order.
|
929 |
-
* @param string $amount refund amount.
|
930 |
-
* @param string $reason reason of refund.
|
931 |
-
* @param string $intent_secret_id secret key.
|
932 |
-
*
|
933 |
-
* @return array
|
934 |
-
*/
|
935 |
-
public function create_refund_request( $order, $amount, $reason, $intent_secret_id ) {
|
936 |
-
|
937 |
-
$client = $this->get_clients_details();
|
938 |
-
|
939 |
-
$stripe_api = new Stripe_Api();
|
940 |
-
$response = $stripe_api->payment_intents( 'retrieve', [ $intent_secret_id ] );
|
941 |
-
$status = $response['success'] ? $response['data']->charges->data[0]->captured : false;
|
942 |
-
|
943 |
-
if ( ! $status ) {
|
944 |
-
Logger::error( __( 'Uncaptured Amount cannot be refunded', 'checkout-plugins-stripe-woo' ), true );
|
945 |
-
return new WP_Error( 'error', __( 'Uncaptured Amount cannot be refunded', 'checkout-plugins-stripe-woo' ) );
|
946 |
-
}
|
947 |
-
|
948 |
-
$intent_response = $response['data'];
|
949 |
-
$currency = $intent_response->currency;
|
950 |
-
|
951 |
-
$refund_params = [
|
952 |
-
'payment_intent' => $intent_secret_id,
|
953 |
-
'amount' => $this->get_formatted_amount( $amount, $currency ),
|
954 |
-
'reason' => 'requested_by_customer',
|
955 |
-
'metadata' => [
|
956 |
-
'order_id' => $order->get_order_number(),
|
957 |
-
'Customer IP' => $client['IP'],
|
958 |
-
'Agent' => $client['Agent'],
|
959 |
-
'Referer' => $client['Referer'],
|
960 |
-
'Reason for Refund' => $reason,
|
961 |
-
],
|
962 |
-
];
|
963 |
-
|
964 |
-
$stripe_api = new Stripe_Api();
|
965 |
-
return $stripe_api->refunds( 'create', [ $refund_params ] );
|
966 |
-
}
|
967 |
-
|
968 |
/**
|
969 |
* Get stripe activated payment cards icon.
|
970 |
*/
|
@@ -996,41 +701,6 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
996 |
return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
|
997 |
}
|
998 |
|
999 |
-
|
1000 |
-
/**
|
1001 |
-
* Returns amount as per currency type
|
1002 |
-
*
|
1003 |
-
* @param string $total amount to be processed.
|
1004 |
-
* @param string $currency transaction currency.
|
1005 |
-
* @return int
|
1006 |
-
*/
|
1007 |
-
public function get_formatted_amount( $total, $currency = '' ) {
|
1008 |
-
if ( ! $currency ) {
|
1009 |
-
$currency = get_woocommerce_currency();
|
1010 |
-
}
|
1011 |
-
|
1012 |
-
if ( in_array( strtoupper( $currency ), self::$zero_currencies, true ) ) {
|
1013 |
-
// Zero decimal currencies accepted by stripe.
|
1014 |
-
$total = absint( $total );
|
1015 |
-
} else {
|
1016 |
-
$total = round( $total, 2 ) * 100;
|
1017 |
-
}
|
1018 |
-
return $total;
|
1019 |
-
}
|
1020 |
-
|
1021 |
-
/**
|
1022 |
-
* Basic details of logged in user
|
1023 |
-
*
|
1024 |
-
* @return array current user data.
|
1025 |
-
*/
|
1026 |
-
public function get_clients_details() {
|
1027 |
-
return [
|
1028 |
-
'IP' => isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : '',
|
1029 |
-
'Agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : '',
|
1030 |
-
'Referer' => isset( $_SERVER['HTTP_REFERER'] ) ? sanitize_text_field( $_SERVER['HTTP_REFERER'] ) : '',
|
1031 |
-
];
|
1032 |
-
}
|
1033 |
-
|
1034 |
/**
|
1035 |
* Creates markup for payment form for card payments
|
1036 |
*
|
@@ -1046,12 +716,7 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
1046 |
echo '<div class="status-box"></div>';
|
1047 |
echo '<div class="cpsw-stipe-pay-data">';
|
1048 |
echo '<div class="cpsw-stripe-info">';
|
1049 |
-
|
1050 |
-
/* translators: %1$1s - %6$6s: HTML Markup */
|
1051 |
-
printf( esc_html__( '%1$1s Test Mode Enabled %2$2s : Use demo card 4242424242424242 with any future date and CVV. %3$3s Check more %4$4sDemo Cards%5$5s %6$6s', 'checkout-plugins-stripe-woo' ), '<b>', '</b>', '</br>', "<a href='https://stripe.com/docs/testing' referrer='noopener' target='_blank'>", '</a>', '</br></br>' );
|
1052 |
-
} else {
|
1053 |
-
echo wp_kses_post( wpautop( $this->description ) );
|
1054 |
-
}
|
1055 |
echo '</div>';
|
1056 |
if ( $display_tokenization ) {
|
1057 |
$this->tokenization_script();
|
@@ -1081,37 +746,13 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
1081 |
echo ( apply_filters( 'cpsw_display_save_payment_method_checkbox', $display_tokenization ) && $this->enable_saved_cards() ) ? '<span class="cpsw-save-cards"><label><input type="checkbox" name="enable_saved_card" value="on"/>' . wp_kses_post( apply_filters( 'cpsw_saved_cards_label', __( 'Save Card for Future Payments', 'checkout-plugins-stripe-woo' ) ) ) . '</label></span>' : '';
|
1082 |
do_action( 'cpsw_payment_fields_cpsw_stripe', $this->id );
|
1083 |
echo '</div>';
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
*
|
1090 |
-
* @param mixed $order current woocommerce order.
|
1091 |
-
* @return mixed customer id
|
1092 |
-
*/
|
1093 |
-
public function get_customer_id( $order = false ) {
|
1094 |
-
$user = wp_get_current_user();
|
1095 |
-
$user_id = ( $user->ID && $user->ID > 0 ) ? $user->ID : false;
|
1096 |
-
$customer_id = false;
|
1097 |
-
if ( $user_id ) {
|
1098 |
-
$customer_id = get_user_option( '_cpsw_customer_id', $user_id );
|
1099 |
-
if ( $customer_id ) {
|
1100 |
-
return $customer_id;
|
1101 |
-
}
|
1102 |
-
}
|
1103 |
-
|
1104 |
-
$customer = false;
|
1105 |
-
if ( ! $customer_id ) {
|
1106 |
-
$customer = $this->create_stripe_customer( $order, $user->email );
|
1107 |
-
}
|
1108 |
-
|
1109 |
-
if ( $customer ) {
|
1110 |
-
if ( $user_id ) {
|
1111 |
-
update_user_option( $user_id, '_cpsw_customer_id', $customer->id, false );
|
1112 |
-
}
|
1113 |
-
return $customer->id;
|
1114 |
}
|
|
|
1115 |
}
|
1116 |
|
1117 |
/**
|
@@ -1182,4 +823,3 @@ class Card_Payments extends Abstract_Payment_Gateway {
|
|
1182 |
];
|
1183 |
}
|
1184 |
}
|
1185 |
-
|
13 |
use CPSW\Inc\Traits\Get_Instance;
|
14 |
use CPSW\Inc\Traits\Subscriptions;
|
15 |
use CPSW\Gateway\Abstract_Payment_Gateway;
|
|
|
16 |
use CPSW\Gateway\Stripe\Stripe_Api;
|
17 |
use WC_AJAX;
|
18 |
use WC_HTTPS;
|
30 |
use Get_Instance;
|
31 |
use Subscriptions;
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
/**
|
34 |
* Gateway id
|
35 |
*
|
43 |
* @since 0.0.1
|
44 |
*/
|
45 |
public function __construct() {
|
46 |
+
parent::__construct();
|
47 |
|
48 |
$this->method_title = __( 'Stripe Card Processing', 'checkout-plugins-stripe-woo' );
|
49 |
$this->method_description = __( 'Accepts payments via Credit/Debit Cards', 'checkout-plugins-stripe-woo' );
|
63 |
$this->allowed_cards = empty( $this->get_option( 'allowed_cards' ) ) ? [ 'mastercard', 'visa', 'diners', 'discover', 'amex', 'jcb', 'unionpay' ] : $this->get_option( 'allowed_cards' );
|
64 |
$this->statement_descriptor = $this->clean_statement_descriptor( $this->get_option( 'statement_descriptor' ) );
|
65 |
|
|
|
|
|
66 |
add_filter( 'woocommerce_payment_successful_result', [ $this, 'modify_successful_payment_result' ], 999, 2 );
|
67 |
add_action( 'wc_ajax_cpsw_verify_payment_intent', [ $this, 'verify_intent' ] );
|
68 |
add_filter( 'woocommerce_payment_complete_order_status', [ $this, 'cpsw_payment_complete_order_status' ], 10, 3 );
|
|
|
69 |
}
|
70 |
|
71 |
/**
|
83 |
];
|
84 |
}
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
/**
|
87 |
* Gateway form fields
|
88 |
*
|
89 |
* @return void
|
90 |
+
$ */
|
91 |
public function init_form_fields() {
|
92 |
$this->form_fields = [
|
93 |
'enabled' => [
|
94 |
+
'label' => ' ',
|
95 |
'type' => 'checkbox',
|
96 |
'title' => __( 'Enable Stripe Gateway', 'checkout-plugins-stripe-woo' ),
|
97 |
'default' => 'no',
|
212 |
'description' => $this->get_order_description( $order ),
|
213 |
'payment_method_types' => [ 'card' ],
|
214 |
'payment_method' => $payment_method,
|
215 |
+
'metadata' => $this->get_metadata( $order_id ),
|
216 |
'customer' => $customer_id,
|
217 |
'capture_method' => $this->capture_method,
|
218 |
];
|
227 |
|
228 |
/* translators: %1$1s order id, %2$2s order total amount */
|
229 |
Logger::info( sprintf( __( 'Begin processing payment with new payment method for order %1$1s for the amount of %2$2s', 'checkout-plugins-stripe-woo' ), $order_id, $order->get_total() ) );
|
230 |
+
$intent_data = $this->get_payment_intent( $order_id, $idempotency_key, $data );
|
231 |
if ( $intent_data ) {
|
232 |
return [
|
233 |
'result' => 'success',
|
234 |
'redirect' => $this->get_return_url( $order ),
|
235 |
+
'payment_method' => $payment_method,
|
236 |
'intent_secret' => $intent_data['client_secret'],
|
237 |
'save_card' => $this->should_save_card( $order_id ),
|
238 |
];
|
287 |
'currency' => strtolower( $order->get_currency() ),
|
288 |
'description' => $this->get_order_description( $order ),
|
289 |
'customer' => $payment_method->customer,
|
290 |
+
'metadata' => $this->get_metadata( $order_id ),
|
291 |
'confirm' => true,
|
292 |
'capture_method' => $this->capture_method,
|
293 |
];
|
444 |
return ( isset( $_POST[ 'wc-' . $payment_method . '-payment-token' ] ) && 'new' !== $_POST[ 'wc-' . $payment_method . '-payment-token' ] ); //phpcs:ignore WordPress.Security.NonceVerification.Missing
|
445 |
}
|
446 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
/**
|
448 |
* Get token object for selected saved card payment
|
449 |
*
|
510 |
];
|
511 |
}
|
512 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
513 |
/**
|
514 |
* Verify intent state and redirect.
|
515 |
*
|
604 |
* Process order after stripe payment
|
605 |
*
|
606 |
* @param object $response intent response data.
|
607 |
+
* @param string $order_id current WooCommerce id.
|
608 |
* @return array return data.
|
609 |
*/
|
610 |
public function process_order( $response, $order_id ) {
|
626 |
$order->add_order_note( __( 'Payment Status : ', 'checkout-plugins-stripe-woo' ) . ucfirst( $response->status ) . __( ' Source : ', 'checkout-plugins-stripe-woo' ) . $response->payment_method_details->card->brand );
|
627 |
WC()->cart->empty_cart();
|
628 |
|
629 |
+
return $this->get_return_url( $order );
|
|
|
|
|
|
|
630 |
}
|
631 |
|
632 |
/**
|
637 |
* @return array modified redirect url array.
|
638 |
*/
|
639 |
public function modify_successful_payment_result( $result, $order_id ) {
|
640 |
+
if ( empty( $order_id ) ) {
|
641 |
+
return $result;
|
642 |
+
}
|
643 |
+
|
644 |
+
$order = wc_get_order( $order_id );
|
645 |
+
if ( 'cpsw_stripe' !== $order->get_payment_method() ) {
|
646 |
+
return $result;
|
647 |
+
}
|
648 |
+
|
649 |
if ( ! isset( $result['intent_secret'] ) ) {
|
650 |
return $result;
|
651 |
}
|
670 |
];
|
671 |
}
|
672 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
673 |
/**
|
674 |
* Get stripe activated payment cards icon.
|
675 |
*/
|
701 |
return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
|
702 |
}
|
703 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
704 |
/**
|
705 |
* Creates markup for payment form for card payments
|
706 |
*
|
716 |
echo '<div class="status-box"></div>';
|
717 |
echo '<div class="cpsw-stipe-pay-data">';
|
718 |
echo '<div class="cpsw-stripe-info">';
|
719 |
+
echo wp_kses_post( wpautop( $this->description ) );
|
|
|
|
|
|
|
|
|
|
|
720 |
echo '</div>';
|
721 |
if ( $display_tokenization ) {
|
722 |
$this->tokenization_script();
|
746 |
echo ( apply_filters( 'cpsw_display_save_payment_method_checkbox', $display_tokenization ) && $this->enable_saved_cards() ) ? '<span class="cpsw-save-cards"><label><input type="checkbox" name="enable_saved_card" value="on"/>' . wp_kses_post( apply_filters( 'cpsw_saved_cards_label', __( 'Save Card for Future Payments', 'checkout-plugins-stripe-woo' ) ) ) . '</label></span>' : '';
|
747 |
do_action( 'cpsw_payment_fields_cpsw_stripe', $this->id );
|
748 |
echo '</div>';
|
749 |
+
if ( 'test' === Helper::get_payment_mode() ) {
|
750 |
+
echo '<div class="cpsw-test-description">';
|
751 |
+
/* translators: %1$1s - %6$6s: HTML Markup */
|
752 |
+
printf( esc_html__( '%1$1s Test Mode Enabled %2$2s : Use demo card 4242424242424242 with any future date and CVV. %3$3s Check more %4$4sDemo Cards%5$5s', 'checkout-plugins-stripe-woo' ), '<b>', '</b>', '</br>', "<a href='https://stripe.com/docs/testing' referrer='noopener' target='_blank'>", '</a>' );
|
753 |
+
echo '</div>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
754 |
}
|
755 |
+
echo '</div>';
|
756 |
}
|
757 |
|
758 |
/**
|
823 |
];
|
824 |
}
|
825 |
}
|
|
gateway/stripe/frontend-scripts.php
CHANGED
@@ -26,6 +26,13 @@ class Frontend_Scripts {
|
|
26 |
*/
|
27 |
private $prefix = 'cpsw-';
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
/**
|
30 |
* Url of assets directory
|
31 |
*
|
@@ -37,38 +44,60 @@ class Frontend_Scripts {
|
|
37 |
* Constructor
|
38 |
*/
|
39 |
public function __construct() {
|
|
|
40 |
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
|
41 |
}
|
42 |
|
43 |
/**
|
44 |
* Enqueue scripts
|
45 |
*
|
|
|
|
|
46 |
* @return void
|
47 |
*/
|
48 |
public function enqueue_scripts() {
|
49 |
-
|
50 |
$public_key = ( 'live' === Helper::get_payment_mode() ) ? Helper::get_setting( 'cpsw_pub_key' ) : Helper::get_setting( 'cpsw_test_pub_key' );
|
51 |
-
|
|
|
52 |
wp_enqueue_script( $this->prefix . 'stripe-external' );
|
53 |
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
wp_enqueue_script( $this->prefix . 'stripe-elements' );
|
56 |
|
57 |
-
wp_register_style( $this->prefix . 'stripe-elements', $this->assets_url . 'css/stripe-elements.css', [],
|
58 |
wp_enqueue_style( $this->prefix . 'stripe-elements' );
|
59 |
|
60 |
wp_localize_script(
|
61 |
$this->prefix . 'stripe-elements',
|
62 |
'cpsw_global_settings',
|
63 |
[
|
64 |
-
'public_key'
|
65 |
-
'inline_cc'
|
66 |
-
'is_ssl'
|
67 |
-
'mode'
|
68 |
-
'ajax_url'
|
69 |
-
'js_nonce'
|
70 |
-
'allowed_cards'
|
71 |
-
'default_cards'
|
72 |
'mastercard' => __( 'MasterCard', 'checkout-plugins-stripe-woo' ),
|
73 |
'visa' => __( 'Visa', 'checkout-plugins-stripe-woo' ),
|
74 |
'amex' => __( 'American Express', 'checkout-plugins-stripe-woo' ),
|
@@ -77,15 +106,18 @@ class Frontend_Scripts {
|
|
77 |
'diners' => __( 'Diners Club', 'checkout-plugins-stripe-woo' ),
|
78 |
'unionpay' => __( 'UnionPay', 'checkout-plugins-stripe-woo' ),
|
79 |
],
|
80 |
-
'not_allowed_string'
|
|
|
|
|
81 |
]
|
82 |
);
|
83 |
|
84 |
if ( 'yes' === Helper::get_setting( 'express_checkout_enabled', 'cpsw_stripe' ) ) {
|
85 |
-
wp_register_script( $this->prefix . 'payment-request', $this->assets_url . 'js/payment-request.js', [ 'jquery', $this->prefix . 'stripe-external', $this->prefix . 'stripe-elements' ],
|
86 |
wp_enqueue_script( $this->prefix . 'payment-request' );
|
87 |
|
88 |
$needs_shipping = false;
|
|
|
89 |
if ( ! is_null( WC()->cart ) && WC()->cart->needs_shipping() ) {
|
90 |
$needs_shipping = true;
|
91 |
}
|
@@ -96,15 +128,15 @@ class Frontend_Scripts {
|
|
96 |
apply_filters(
|
97 |
'cpsw_payment_request_localization',
|
98 |
[
|
99 |
-
'ajax_url'
|
100 |
-
'ajax_endpoint'
|
101 |
-
'public_key'
|
102 |
-
'mode'
|
103 |
-
'currency_code'
|
104 |
-
'country_code'
|
105 |
-
'needs_shipping'
|
106 |
-
'phone_required'
|
107 |
-
'nonce'
|
108 |
'checkout' => wp_create_nonce( 'cpsw_checkout' ),
|
109 |
'payment' => wp_create_nonce( 'cpsw_payment_request' ),
|
110 |
'add_to_cart' => wp_create_nonce( 'cpsw_add_to_cart' ),
|
@@ -113,12 +145,14 @@ class Frontend_Scripts {
|
|
113 |
'shipping_option' => wp_create_nonce( 'cpsw_shipping_option' ),
|
114 |
'js_nonce' => wp_create_nonce( 'cpsw_js_error_nonce' ),
|
115 |
],
|
116 |
-
'style'
|
117 |
'type' => Helper::get_setting( 'express_checkout_button_type', 'cpsw_stripe' ),
|
118 |
'theme' => Helper::get_setting( 'express_checkout_button_theme', 'cpsw_stripe' ),
|
119 |
'height' => (int) Helper::get_setting( 'express_checkout_button_height', 'cpsw_stripe' ),
|
120 |
],
|
121 |
-
'is_product_page'
|
|
|
|
|
122 |
]
|
123 |
)
|
124 |
);
|
26 |
*/
|
27 |
private $prefix = 'cpsw-';
|
28 |
|
29 |
+
/**
|
30 |
+
* Version
|
31 |
+
*
|
32 |
+
* @var string
|
33 |
+
*/
|
34 |
+
private $version = '';
|
35 |
+
|
36 |
/**
|
37 |
* Url of assets directory
|
38 |
*
|
44 |
* Constructor
|
45 |
*/
|
46 |
public function __construct() {
|
47 |
+
$this->version = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? time() : CPSW_VERSION;
|
48 |
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
|
49 |
}
|
50 |
|
51 |
/**
|
52 |
* Enqueue scripts
|
53 |
*
|
54 |
+
* @since 1.0.0
|
55 |
+
*
|
56 |
* @return void
|
57 |
*/
|
58 |
public function enqueue_scripts() {
|
|
|
59 |
$public_key = ( 'live' === Helper::get_payment_mode() ) ? Helper::get_setting( 'cpsw_pub_key' ) : Helper::get_setting( 'cpsw_test_pub_key' );
|
60 |
+
|
61 |
+
wp_register_script( $this->prefix . 'stripe-external', 'https://js.stripe.com/v3/', [], $this->version, true );
|
62 |
wp_enqueue_script( $this->prefix . 'stripe-external' );
|
63 |
|
64 |
+
if (
|
65 |
+
'yes' === Helper::get_setting( 'enabled', 'cpsw_stripe' ) ||
|
66 |
+
'yes' === Helper::get_setting( 'enabled', 'cpsw_alipay' ) ||
|
67 |
+
'yes' === Helper::get_setting( 'enabled', 'cpsw_ideal' )
|
68 |
+
) {
|
69 |
+
$this->enqueue_card_payments_scripts( $public_key );
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Enqueue card payments scripts
|
75 |
+
*
|
76 |
+
* @since 1.0.0
|
77 |
+
*
|
78 |
+
* @param string $public_key Stripe public key.
|
79 |
+
*
|
80 |
+
* @return void
|
81 |
+
*/
|
82 |
+
private function enqueue_card_payments_scripts( $public_key ) {
|
83 |
+
wp_register_script( $this->prefix . 'stripe-elements', $this->assets_url . 'js/stripe-elements.js', [ 'jquery', $this->prefix . 'stripe-external' ], $this->version, true );
|
84 |
wp_enqueue_script( $this->prefix . 'stripe-elements' );
|
85 |
|
86 |
+
wp_register_style( $this->prefix . 'stripe-elements', $this->assets_url . 'css/stripe-elements.css', [], $this->version );
|
87 |
wp_enqueue_style( $this->prefix . 'stripe-elements' );
|
88 |
|
89 |
wp_localize_script(
|
90 |
$this->prefix . 'stripe-elements',
|
91 |
'cpsw_global_settings',
|
92 |
[
|
93 |
+
'public_key' => $public_key,
|
94 |
+
'inline_cc' => Helper::get_setting( 'inline_cc', 'cpsw_stripe' ),
|
95 |
+
'is_ssl' => is_ssl(),
|
96 |
+
'mode' => Helper::get_payment_mode(),
|
97 |
+
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
98 |
+
'js_nonce' => wp_create_nonce( 'cpsw_js_error_nonce' ),
|
99 |
+
'allowed_cards' => Helper::get_setting( 'allowed_cards', 'cpsw_stripe' ),
|
100 |
+
'default_cards' => [
|
101 |
'mastercard' => __( 'MasterCard', 'checkout-plugins-stripe-woo' ),
|
102 |
'visa' => __( 'Visa', 'checkout-plugins-stripe-woo' ),
|
103 |
'amex' => __( 'American Express', 'checkout-plugins-stripe-woo' ),
|
106 |
'diners' => __( 'Diners Club', 'checkout-plugins-stripe-woo' ),
|
107 |
'unionpay' => __( 'UnionPay', 'checkout-plugins-stripe-woo' ),
|
108 |
],
|
109 |
+
'not_allowed_string' => __( 'is not allowed', 'checkout-plugins-stripe-woo' ),
|
110 |
+
'get_home_url' => get_home_url(),
|
111 |
+
'empty_ideal_bank_message' => __( 'Please select a bank to proceed.', 'checkout-plugins-stripe-woo' ),
|
112 |
]
|
113 |
);
|
114 |
|
115 |
if ( 'yes' === Helper::get_setting( 'express_checkout_enabled', 'cpsw_stripe' ) ) {
|
116 |
+
wp_register_script( $this->prefix . 'payment-request', $this->assets_url . 'js/payment-request.js', [ 'jquery', $this->prefix . 'stripe-external', $this->prefix . 'stripe-elements' ], $this->version, true );
|
117 |
wp_enqueue_script( $this->prefix . 'payment-request' );
|
118 |
|
119 |
$needs_shipping = false;
|
120 |
+
|
121 |
if ( ! is_null( WC()->cart ) && WC()->cart->needs_shipping() ) {
|
122 |
$needs_shipping = true;
|
123 |
}
|
128 |
apply_filters(
|
129 |
'cpsw_payment_request_localization',
|
130 |
[
|
131 |
+
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
132 |
+
'ajax_endpoint' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
|
133 |
+
'public_key' => $public_key,
|
134 |
+
'mode' => Helper::get_payment_mode(),
|
135 |
+
'currency_code' => strtolower( get_woocommerce_currency() ),
|
136 |
+
'country_code' => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
|
137 |
+
'needs_shipping' => $needs_shipping,
|
138 |
+
'phone_required' => 'required' === get_option( 'woocommerce_checkout_phone_field', 'required' ),
|
139 |
+
'nonce' => [
|
140 |
'checkout' => wp_create_nonce( 'cpsw_checkout' ),
|
141 |
'payment' => wp_create_nonce( 'cpsw_payment_request' ),
|
142 |
'add_to_cart' => wp_create_nonce( 'cpsw_add_to_cart' ),
|
145 |
'shipping_option' => wp_create_nonce( 'cpsw_shipping_option' ),
|
146 |
'js_nonce' => wp_create_nonce( 'cpsw_js_error_nonce' ),
|
147 |
],
|
148 |
+
'style' => [
|
149 |
'type' => Helper::get_setting( 'express_checkout_button_type', 'cpsw_stripe' ),
|
150 |
'theme' => Helper::get_setting( 'express_checkout_button_theme', 'cpsw_stripe' ),
|
151 |
'height' => (int) Helper::get_setting( 'express_checkout_button_height', 'cpsw_stripe' ),
|
152 |
],
|
153 |
+
'is_product_page' => is_product() || wc_post_content_has_shortcode( 'product_page' ),
|
154 |
+
'product_advanced_options' => Helper::get_setting( 'express_checkout_product_options', 'cpsw_stripe' ),
|
155 |
+
'is_responsive' => Helper::get_setting( 'express_checkout_product_sticky_footer', 'cpsw_stripe' ),
|
156 |
]
|
157 |
)
|
158 |
);
|
gateway/stripe/ideal.php
ADDED
@@ -0,0 +1,264 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* IDEAL Gateway
|
4 |
+
*
|
5 |
+
* @package checkout-plugins-stripe-woo
|
6 |
+
* @since 1.2.0
|
7 |
+
*/
|
8 |
+
|
9 |
+
namespace CPSW\Gateway\Stripe;
|
10 |
+
|
11 |
+
use CPSW\Inc\Helper;
|
12 |
+
use CPSW\Inc\Logger;
|
13 |
+
use CPSW\Inc\Traits\Get_Instance;
|
14 |
+
use CPSW\Gateway\Local_Gateway;
|
15 |
+
use WC_AJAX;
|
16 |
+
use Exception;
|
17 |
+
use WP_Error;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* IDEAL gateway
|
21 |
+
*
|
22 |
+
* @since 1.2.0
|
23 |
+
*/
|
24 |
+
class Ideal extends Local_Gateway {
|
25 |
+
|
26 |
+
use Get_Instance;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Gateway id
|
30 |
+
*
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
public $id = 'cpsw_ideal';
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Constructor
|
37 |
+
*
|
38 |
+
* @since 1.2.0
|
39 |
+
*/
|
40 |
+
public function __construct() {
|
41 |
+
parent::__construct();
|
42 |
+
$this->method_title = __( 'iDEAL', 'checkout-plugins-stripe-woo' );
|
43 |
+
$this->method_description = $this->method_description();
|
44 |
+
$this->has_fields = true;
|
45 |
+
|
46 |
+
$this->init_supports();
|
47 |
+
$this->init_form_fields();
|
48 |
+
$this->init_settings();
|
49 |
+
|
50 |
+
$this->title = $this->get_option( 'title' );
|
51 |
+
$this->description = $this->get_option( 'description' );
|
52 |
+
$this->order_button_text = $this->get_option( 'order_button_text' );
|
53 |
+
|
54 |
+
add_action( 'wc_ajax_cpsw_verify_ideal_payment_intent', [ $this, 'verify_ideal_intent' ] );
|
55 |
+
add_filter( 'woocommerce_payment_successful_result', [ $this, 'modify_successful_payment_result' ], 999, 2 );
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Description for ideal gateway
|
60 |
+
*
|
61 |
+
* @since 1.2.0
|
62 |
+
*
|
63 |
+
* @return string
|
64 |
+
*/
|
65 |
+
public function method_description() {
|
66 |
+
$payment_description = $this->payment_description();
|
67 |
+
|
68 |
+
return sprintf(
|
69 |
+
/* translators: %1$s: Break, %2$s: HTML entities */
|
70 |
+
__( 'Accept payment using iDEAL. %1$s %2$s', 'checkout-plugins-stripe-woo' ),
|
71 |
+
'<br/>',
|
72 |
+
$payment_description
|
73 |
+
);
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Checks whether this gateway is available.
|
78 |
+
*
|
79 |
+
* @return boolean
|
80 |
+
*/
|
81 |
+
public function is_available() {
|
82 |
+
if ( 'eur' !== strtolower( get_woocommerce_currency() ) ) {
|
83 |
+
return false;
|
84 |
+
}
|
85 |
+
return parent::is_available();
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Returns all supported currencies for this payment method.
|
90 |
+
*
|
91 |
+
* @since 1.2.0
|
92 |
+
*
|
93 |
+
* @return array
|
94 |
+
*/
|
95 |
+
public function get_supported_currency() {
|
96 |
+
return apply_filters(
|
97 |
+
'cpsw_ideal_supported_currencies',
|
98 |
+
[
|
99 |
+
'EUR',
|
100 |
+
]
|
101 |
+
);
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Creates markup for payment form for iDEAL
|
106 |
+
*
|
107 |
+
* @return void
|
108 |
+
*/
|
109 |
+
public function payment_fields() {
|
110 |
+
echo '<div class="status-box"></div>';
|
111 |
+
echo '<div class="cpsw_stripe_ideal_form">';
|
112 |
+
if ( $this->description ) {
|
113 |
+
echo wp_kses_post( $this->description );
|
114 |
+
}
|
115 |
+
echo '<div class="cpsw_stripe_ideal_select"></div>';
|
116 |
+
echo '<div class="cpsw_stripe_ideal_error"></div>';
|
117 |
+
if ( 'test' === Helper::get_payment_mode() ) {
|
118 |
+
echo '<div class="cpsw_stripe_ideal_test_description">';
|
119 |
+
echo wp_kses_post( $this->get_test_mode_description() );
|
120 |
+
echo '</div>';
|
121 |
+
}
|
122 |
+
echo '</div>';
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Modify redirect url
|
127 |
+
*
|
128 |
+
* @param array $result redirect url array.
|
129 |
+
* @param int $order_id woocommerce order id.
|
130 |
+
* @return array modified redirect url array.
|
131 |
+
*/
|
132 |
+
public function modify_successful_payment_result( $result, $order_id ) {
|
133 |
+
if ( empty( $order_id ) ) {
|
134 |
+
return $result;
|
135 |
+
}
|
136 |
+
|
137 |
+
$order = wc_get_order( $order_id );
|
138 |
+
if ( $this->id !== $order->get_payment_method() ) {
|
139 |
+
return $result;
|
140 |
+
}
|
141 |
+
|
142 |
+
if ( ! isset( $result['intent_secret'] ) ) {
|
143 |
+
return $result;
|
144 |
+
}
|
145 |
+
|
146 |
+
// Put the final thank you page redirect into the verification URL.
|
147 |
+
$verification_url = add_query_arg(
|
148 |
+
[
|
149 |
+
'order' => $order_id,
|
150 |
+
'confirm_payment_nonce' => wp_create_nonce( 'cpsw_confirm_payment_intent' ),
|
151 |
+
'redirect_to' => rawurlencode( $result['redirect'] ),
|
152 |
+
],
|
153 |
+
WC_AJAX::get_endpoint( 'cpsw_verify_ideal_payment_intent' )
|
154 |
+
);
|
155 |
+
|
156 |
+
// Combine into a hash.
|
157 |
+
$redirect = sprintf( '#confirm-pi-%s:%s', $result['intent_secret'], rawurlencode( $verification_url ) );
|
158 |
+
|
159 |
+
return [
|
160 |
+
'result' => 'success',
|
161 |
+
'redirect' => $redirect,
|
162 |
+
];
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Verify intent state and redirect.
|
167 |
+
*
|
168 |
+
* @return void
|
169 |
+
*/
|
170 |
+
public function verify_ideal_intent() {
|
171 |
+
$order_id = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
172 |
+
$order = wc_get_order( $order_id );
|
173 |
+
|
174 |
+
$intent_secret = get_post_meta( $order_id, '_cpsw_intent_secret', true );
|
175 |
+
$stripe_api = new Stripe_Api();
|
176 |
+
$response = $stripe_api->payment_intents( 'retrieve', [ $intent_secret['id'] ] );
|
177 |
+
$intent = $response['success'] ? $response['data'] : false;
|
178 |
+
|
179 |
+
if ( 'succeeded' === $intent->status || 'requires_capture' === $intent->status ) {
|
180 |
+
$redirect_to = $this->process_order( end( $intent->charges->data ), $order_id );
|
181 |
+
$redirect_url = apply_filters( 'cpsw_redirect_order_url', $redirect_to, $order );
|
182 |
+
wp_safe_redirect( $redirect_url );
|
183 |
+
} elseif ( isset( $response['data']->last_payment_error ) ) {
|
184 |
+
$message = isset( $response['data']->last_payment_error->message ) ? $response['data']->last_payment_error->message : '';
|
185 |
+
$order->update_status( 'wc-failed' );
|
186 |
+
// translators: %s: payment fail message.
|
187 |
+
wc_add_notice( sprintf( __( 'Payment failed. %s', 'checkout-plugins-stripe-woo' ), $message ), 'error' );
|
188 |
+
wp_safe_redirect( wc_get_checkout_url() );
|
189 |
+
}
|
190 |
+
exit();
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Process order after stripe payment
|
195 |
+
*
|
196 |
+
* @param object $response intent response data.
|
197 |
+
* @param string $order_id currnt coocommerce id.
|
198 |
+
* @return array return data.
|
199 |
+
*/
|
200 |
+
public function process_order( $response, $order_id ) {
|
201 |
+
|
202 |
+
$order = wc_get_order( $order_id );
|
203 |
+
|
204 |
+
if ( true === $response->captured ) {
|
205 |
+
$order->payment_complete( $response->id );
|
206 |
+
/* translators: order id */
|
207 |
+
Logger::info( sprintf( __( 'Payment successful Order id - %1s', 'checkout-plugins-stripe-woo' ), $order->get_id() ), true );
|
208 |
+
}
|
209 |
+
if ( ! $response->captured ) {
|
210 |
+
/* translators: transaction id */
|
211 |
+
$order->update_status( 'on-hold', sprintf( __( 'Charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization. Attempting to refund the order in part or in full will release the authorization and cancel the payment.', 'checkout-plugins-stripe-woo' ), $response->id ) );
|
212 |
+
/* translators: transaction id */
|
213 |
+
Logger::info( sprintf( __( 'Charge authorized Order id - %1s', 'checkout-plugins-stripe-woo' ), $order->get_id() ), true );
|
214 |
+
}
|
215 |
+
|
216 |
+
$order->add_order_note( __( 'Payment Status : ', 'checkout-plugins-stripe-woo' ) . ucfirst( $response->status ) . __( ' Source : ', 'checkout-plugins-stripe-woo' ) . $response->payment_method_details->type );
|
217 |
+
WC()->cart->empty_cart();
|
218 |
+
|
219 |
+
return $this->get_return_url( $order );
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Process woocommerce orders after payment is done
|
224 |
+
*
|
225 |
+
* @param int $order_id wooCommerce order id.
|
226 |
+
* @return array data to redirect after payment processing.
|
227 |
+
*/
|
228 |
+
public function process_payment( $order_id ) {
|
229 |
+
try {
|
230 |
+
$order = wc_get_order( $order_id );
|
231 |
+
$customer_id = $this->get_customer_id( $order );
|
232 |
+
$idempotency_key = $order->get_order_key() . time();
|
233 |
+
|
234 |
+
$data = [
|
235 |
+
'amount' => $this->get_formatted_amount( $order->get_total() ),
|
236 |
+
'currency' => get_woocommerce_currency(),
|
237 |
+
'description' => $this->get_order_description( $order ),
|
238 |
+
'metadata' => $this->get_metadata( $order_id ),
|
239 |
+
'payment_method_types' => [ 'ideal' ],
|
240 |
+
'customer' => $customer_id,
|
241 |
+
];
|
242 |
+
|
243 |
+
/* translators: %1$1s order id, %2$2s order total amount */
|
244 |
+
Logger::info( sprintf( __( 'Begin processing payment with iDEAL for order %1$1s for the amount of %2$2s', 'checkout-plugins-stripe-woo' ), $order_id, $order->get_total() ) );
|
245 |
+
$intent_data = $this->get_payment_intent( $order_id, $idempotency_key, $data );
|
246 |
+
if ( $intent_data ) {
|
247 |
+
return [
|
248 |
+
'result' => 'success',
|
249 |
+
'redirect' => false,
|
250 |
+
'intent_secret' => $intent_data['client_secret'],
|
251 |
+
];
|
252 |
+
} else {
|
253 |
+
return [
|
254 |
+
'result' => 'fail',
|
255 |
+
'redirect' => '',
|
256 |
+
];
|
257 |
+
}
|
258 |
+
} catch ( Exception $e ) {
|
259 |
+
Logger::error( $e->getMessage(), true );
|
260 |
+
return new WP_Error( 'order-error', '<div class="woocommerce-error">' . $e->getMessage() . '</div>', [ 'status' => 200 ] );
|
261 |
+
}
|
262 |
+
}
|
263 |
+
}
|
264 |
+
|
gateway/stripe/payment-request-api.php
CHANGED
@@ -35,15 +35,27 @@ class Payment_Request_Api extends Card_Payments {
|
|
35 |
|
36 |
$this->capture_method = Helper::get_setting( 'charge_type', 'cpsw_stripe' );
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
|
|
|
|
42 |
}
|
43 |
|
|
|
|
|
44 |
add_action( 'woocommerce_proceed_to_checkout', [ $this, 'payment_request_button' ], 1 );
|
45 |
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
add_filter( 'cpsw_payment_request_localization', [ $this, 'localize_product_data' ] );
|
49 |
|
@@ -75,11 +87,7 @@ class Payment_Request_Api extends Card_Payments {
|
|
75 |
*/
|
76 |
private function is_selected_location() {
|
77 |
$location = Helper::get_setting( 'express_checkout_location', 'cpsw_stripe' );
|
78 |
-
if ( is_array( $location ) ) {
|
79 |
-
if ( empty( $location ) ) {
|
80 |
-
return true;
|
81 |
-
}
|
82 |
-
|
83 |
if ( $this->is_product() && in_array( 'product', $location, true ) ) {
|
84 |
return true;
|
85 |
}
|
@@ -126,19 +134,13 @@ class Payment_Request_Api extends Card_Payments {
|
|
126 |
$container_class = 'cart';
|
127 |
}
|
128 |
|
129 |
-
$separator_below = true;
|
130 |
-
$position_class = 'above';
|
131 |
-
|
132 |
-
if ( 'below' === Helper::get_setting( 'express_checkout_product_page_position', 'cpsw_stripe' ) && 'product' === $container_class ) {
|
133 |
-
$this->payment_request_button_separator();
|
134 |
-
$separator_below = false;
|
135 |
-
$position_class = 'below';
|
136 |
-
}
|
137 |
-
|
138 |
$options = Helper::get_gateway_settings( 'cpsw_stripe' );
|
139 |
|
|
|
|
|
140 |
$alignment_class = '';
|
141 |
$button_width = '';
|
|
|
142 |
|
143 |
if ( 'checkout' === $container_class ) {
|
144 |
if ( 'yes' === $options['express_checkout_product_checkout_page'] ) {
|
@@ -150,13 +152,29 @@ class Payment_Request_Api extends Card_Payments {
|
|
150 |
}
|
151 |
|
152 |
if ( 'product' === $container_class ) {
|
153 |
-
if ( 'yes' === $options['
|
154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
}
|
156 |
}
|
157 |
|
158 |
?>
|
159 |
-
<div id="cpsw-payment-request-wrapper" class="<?php echo esc_attr( $container_class . ' ' . $position_class . ' ' . $alignment_class ); ?>">
|
|
|
|
|
|
|
|
|
|
|
160 |
<div class="cpsw-payment-request-button-wrapper">
|
161 |
<?php
|
162 |
if ( ! empty( trim( $options['express_checkout_title'] ) && 'yes' === $options['express_checkout_product_checkout_page'] ) ) {
|
@@ -166,7 +184,7 @@ class Payment_Request_Api extends Card_Payments {
|
|
166 |
}
|
167 |
if ( ! empty( trim( $options['express_checkout_tagline'] ) && 'yes' === $options['express_checkout_product_checkout_page'] ) ) {
|
168 |
?>
|
169 |
-
<p id="cpsw-payment-request-tagline"><?php echo wp_kses_post( Helper::get_setting( 'express_checkout_tagline', 'cpsw_stripe' ) ); ?></p>
|
170 |
<?php
|
171 |
}
|
172 |
?>
|
@@ -228,12 +246,13 @@ class Payment_Request_Api extends Card_Payments {
|
|
228 |
}
|
229 |
}
|
230 |
}
|
231 |
-
|
232 |
-
|
233 |
<div id="cpsw-payment-request-separator" class="<?php echo esc_html( $container_class . ' ' . $alignment_class ); ?>">
|
234 |
-
|
235 |
</div>
|
236 |
-
|
|
|
237 |
}
|
238 |
}
|
239 |
|
35 |
|
36 |
$this->capture_method = Helper::get_setting( 'charge_type', 'cpsw_stripe' );
|
37 |
|
38 |
+
$product_page_action = 'woocommerce_after_add_to_cart_quantity';
|
39 |
+
$product_page_priority = 10;
|
40 |
+
|
41 |
+
if ( 'yes' === $settings['express_checkout_product_options'] && 'below' === $settings['express_checkout_product_page_position'] ) {
|
42 |
+
$product_page_action = 'woocommerce_after_add_to_cart_button';
|
43 |
+
$product_page_priority = 1;
|
44 |
}
|
45 |
|
46 |
+
add_action( $product_page_action, [ $this, 'payment_request_button' ], $product_page_priority );
|
47 |
+
|
48 |
add_action( 'woocommerce_proceed_to_checkout', [ $this, 'payment_request_button' ], 1 );
|
49 |
|
50 |
+
$checkout_page_action = 'woocommerce_checkout_before_customer_details';
|
51 |
+
$checkout_page_priority = 5;
|
52 |
+
|
53 |
+
if ( 'yes' === $settings['express_checkout_product_checkout_page'] && 'above-billing' === $settings['express_checkout_checkout_page_position'] ) {
|
54 |
+
$checkout_page_action = 'woocommerce_checkout_billing';
|
55 |
+
$checkout_page_priority = 1;
|
56 |
+
}
|
57 |
+
|
58 |
+
add_action( $checkout_page_action, [ $this, 'payment_request_button' ], $checkout_page_priority );
|
59 |
|
60 |
add_filter( 'cpsw_payment_request_localization', [ $this, 'localize_product_data' ] );
|
61 |
|
87 |
*/
|
88 |
private function is_selected_location() {
|
89 |
$location = Helper::get_setting( 'express_checkout_location', 'cpsw_stripe' );
|
90 |
+
if ( is_array( $location ) && ! empty( $location ) ) {
|
|
|
|
|
|
|
|
|
91 |
if ( $this->is_product() && in_array( 'product', $location, true ) ) {
|
92 |
return true;
|
93 |
}
|
134 |
$container_class = 'cart';
|
135 |
}
|
136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
$options = Helper::get_gateway_settings( 'cpsw_stripe' );
|
138 |
|
139 |
+
$separator_below = true;
|
140 |
+
$position_class = 'above';
|
141 |
$alignment_class = '';
|
142 |
$button_width = '';
|
143 |
+
$inline_style = '';
|
144 |
|
145 |
if ( 'checkout' === $container_class ) {
|
146 |
if ( 'yes' === $options['express_checkout_product_checkout_page'] ) {
|
152 |
}
|
153 |
|
154 |
if ( 'product' === $container_class ) {
|
155 |
+
if ( 'yes' === $options['express_checkout_product_options'] ) {
|
156 |
+
if ( 'below' === $options['express_checkout_product_page_position'] ) {
|
157 |
+
$separator_below = false;
|
158 |
+
$position_class = 'below';
|
159 |
+
}
|
160 |
+
|
161 |
+
if ( ! empty( $options['express_checkout_product_button_width'] ) ) {
|
162 |
+
$inline_style = 'width:' . (int) $options['express_checkout_product_button_width'] . 'px';
|
163 |
+
}
|
164 |
+
|
165 |
+
if ( 'yes' === $options['express_checkout_product_sticky_footer'] ) {
|
166 |
+
$container_class .= ' sticky';
|
167 |
+
}
|
168 |
}
|
169 |
}
|
170 |
|
171 |
?>
|
172 |
+
<div id="cpsw-payment-request-wrapper" class="<?php echo esc_attr( $container_class . ' ' . $position_class . ' ' . $alignment_class ); ?>" style="<?php echo esc_attr( $inline_style ); ?>">
|
173 |
+
<?php
|
174 |
+
if ( ! $separator_below ) {
|
175 |
+
$this->payment_request_button_separator();
|
176 |
+
}
|
177 |
+
?>
|
178 |
<div class="cpsw-payment-request-button-wrapper">
|
179 |
<?php
|
180 |
if ( ! empty( trim( $options['express_checkout_title'] ) && 'yes' === $options['express_checkout_product_checkout_page'] ) ) {
|
184 |
}
|
185 |
if ( ! empty( trim( $options['express_checkout_tagline'] ) && 'yes' === $options['express_checkout_product_checkout_page'] ) ) {
|
186 |
?>
|
187 |
+
<p id="cpsw-payment-request-tagline"><?php echo wp_kses_post( Helper::get_setting( 'express_checkout_tagline', 'cpsw_stripe' ) ); ?></p>
|
188 |
<?php
|
189 |
}
|
190 |
?>
|
246 |
}
|
247 |
}
|
248 |
}
|
249 |
+
if ( ! empty( $separator_text ) ) {
|
250 |
+
?>
|
251 |
<div id="cpsw-payment-request-separator" class="<?php echo esc_html( $container_class . ' ' . $alignment_class ); ?>">
|
252 |
+
<?php echo esc_html( $separator_text ); ?>
|
253 |
</div>
|
254 |
+
<?php
|
255 |
+
}
|
256 |
}
|
257 |
}
|
258 |
|
gateway/stripe/stripe-api.php
CHANGED
@@ -61,38 +61,46 @@ class Stripe_Api {
|
|
61 |
|
62 |
$error_message = false;
|
63 |
$response = false;
|
|
|
64 |
|
65 |
try {
|
66 |
$response = $this->stripe->{$api}->{$method}( ...$args );
|
67 |
} catch ( \Stripe\Exception\CardException $e ) {
|
68 |
Logger::error( $e->getError()->message, true );
|
69 |
$error_message = $e->getError()->message;
|
|
|
70 |
} catch ( \Stripe\Exception\RateLimitException $e ) {
|
71 |
// Too many requests made to the API too quickly.
|
72 |
Logger::error( $e->getError()->message, true );
|
73 |
$error_message = $e->getError()->message;
|
|
|
74 |
} catch ( \Stripe\Exception\InvalidRequestException $e ) {
|
75 |
// Invalid parameters were supplied to Stripe's API.
|
76 |
Logger::error( $e->getError()->message, true );
|
77 |
$error_message = $e->getError()->message;
|
|
|
78 |
} catch ( \Stripe\Exception\AuthenticationException $e ) {
|
79 |
// Authentication with Stripe's API failed.
|
80 |
// (maybe you changed API keys recently).
|
81 |
Logger::error( $e->getError()->message, true );
|
82 |
$error_message = $e->getError()->message;
|
|
|
83 |
} catch ( \Stripe\Exception\ApiConnectionException $e ) {
|
84 |
// Network communication with Stripe failed.
|
85 |
$error_message = is_null( $e->getError() ) ? $e->getMessage() : $e->getError()->message;
|
86 |
Logger::error( $error_message, true );
|
|
|
87 |
} catch ( \Stripe\Exception\ApiErrorException $e ) {
|
88 |
Logger::error( $e->getError()->message, true );
|
89 |
$error_message = $e->getError()->message;
|
|
|
90 |
// Display a very generic error to the user, and maybe send.
|
91 |
// yourself an email.
|
92 |
} catch ( Exception $e ) {
|
93 |
// Something else happened, completely unrelated to Stripe.
|
94 |
Logger::error( $e->getError()->message, true );
|
95 |
$error_message = $e->getError()->message;
|
|
|
96 |
}
|
97 |
|
98 |
if ( is_wp_error( $response ) ) {
|
@@ -109,6 +117,7 @@ class Stripe_Api {
|
|
109 |
return [
|
110 |
'success' => false,
|
111 |
'message' => $error_message,
|
|
|
112 |
];
|
113 |
}
|
114 |
}
|
@@ -118,6 +127,7 @@ class Stripe_Api {
|
|
118 |
*
|
119 |
* @param string $method method to be used.
|
120 |
* @param array $args parameter.
|
|
|
121 |
* @return array
|
122 |
*/
|
123 |
public function payment_intents( $method, $args ) {
|
61 |
|
62 |
$error_message = false;
|
63 |
$response = false;
|
64 |
+
$error_type = '';
|
65 |
|
66 |
try {
|
67 |
$response = $this->stripe->{$api}->{$method}( ...$args );
|
68 |
} catch ( \Stripe\Exception\CardException $e ) {
|
69 |
Logger::error( $e->getError()->message, true );
|
70 |
$error_message = $e->getError()->message;
|
71 |
+
$error_type = $e->getError()->param;
|
72 |
} catch ( \Stripe\Exception\RateLimitException $e ) {
|
73 |
// Too many requests made to the API too quickly.
|
74 |
Logger::error( $e->getError()->message, true );
|
75 |
$error_message = $e->getError()->message;
|
76 |
+
$error_type = $e->getError()->param;
|
77 |
} catch ( \Stripe\Exception\InvalidRequestException $e ) {
|
78 |
// Invalid parameters were supplied to Stripe's API.
|
79 |
Logger::error( $e->getError()->message, true );
|
80 |
$error_message = $e->getError()->message;
|
81 |
+
$error_type = $e->getError()->param;
|
82 |
} catch ( \Stripe\Exception\AuthenticationException $e ) {
|
83 |
// Authentication with Stripe's API failed.
|
84 |
// (maybe you changed API keys recently).
|
85 |
Logger::error( $e->getError()->message, true );
|
86 |
$error_message = $e->getError()->message;
|
87 |
+
$error_type = $e->getError()->param;
|
88 |
} catch ( \Stripe\Exception\ApiConnectionException $e ) {
|
89 |
// Network communication with Stripe failed.
|
90 |
$error_message = is_null( $e->getError() ) ? $e->getMessage() : $e->getError()->message;
|
91 |
Logger::error( $error_message, true );
|
92 |
+
$error_type = is_null( $e->getError() ) ? '' : $e->getError()->param;
|
93 |
} catch ( \Stripe\Exception\ApiErrorException $e ) {
|
94 |
Logger::error( $e->getError()->message, true );
|
95 |
$error_message = $e->getError()->message;
|
96 |
+
$error_type = $e->getError()->param;
|
97 |
// Display a very generic error to the user, and maybe send.
|
98 |
// yourself an email.
|
99 |
} catch ( Exception $e ) {
|
100 |
// Something else happened, completely unrelated to Stripe.
|
101 |
Logger::error( $e->getError()->message, true );
|
102 |
$error_message = $e->getError()->message;
|
103 |
+
$error_type = $e->getError()->param;
|
104 |
}
|
105 |
|
106 |
if ( is_wp_error( $response ) ) {
|
117 |
return [
|
118 |
'success' => false,
|
119 |
'message' => $error_message,
|
120 |
+
'type' => $error_type,
|
121 |
];
|
122 |
}
|
123 |
}
|
127 |
*
|
128 |
* @param string $method method to be used.
|
129 |
* @param array $args parameter.
|
130 |
+
*
|
131 |
* @return array
|
132 |
*/
|
133 |
public function payment_intents( $method, $args ) {
|
gateway/stripe/webhook.php
CHANGED
@@ -152,7 +152,7 @@ class Webhook {
|
|
152 |
}
|
153 |
|
154 |
$payload = file_get_contents( 'php://input' );
|
155 |
-
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
|
156 |
$event = null;
|
157 |
|
158 |
try {
|
@@ -186,6 +186,35 @@ class Webhook {
|
|
186 |
$charge = $event->data->object;
|
187 |
$this->charge_capture( $charge );
|
188 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
|
190 |
}
|
191 |
$success = constant( 'self::CPSW_' . strtoupper( $mode ) . '_LAST_SUCCESS_AT' );
|
@@ -200,9 +229,8 @@ class Webhook {
|
|
200 |
* @return void
|
201 |
*/
|
202 |
public function charge_capture( $charge ) {
|
203 |
-
global $wpdb;
|
204 |
$payment_intent = sanitize_text_field( $charge->payment_intent );
|
205 |
-
$order_id = $
|
206 |
if ( ! $order_id ) {
|
207 |
Logger::error( 'Could not find order via charge ID: ' . $charge->id );
|
208 |
return;
|
@@ -240,12 +268,331 @@ class Webhook {
|
|
240 |
|
241 |
}
|
242 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
/**
|
244 |
* Shows time difference as - XX minutes ago.
|
245 |
*
|
246 |
* @param datetime $datetime time of last event.
|
247 |
* @param boolean $full show full time difference.
|
248 |
* @return string
|
|
|
249 |
*/
|
250 |
public function time_elapsed_string( $datetime, $full = false ) {
|
251 |
$now = new DateTime();
|
152 |
}
|
153 |
|
154 |
$payload = file_get_contents( 'php://input' );
|
155 |
+
$sig_header = isset( $_SERVER['HTTP_STRIPE_SIGNATURE'] ) ? $_SERVER['HTTP_STRIPE_SIGNATURE'] : '';
|
156 |
$event = null;
|
157 |
|
158 |
try {
|
186 |
$charge = $event->data->object;
|
187 |
$this->charge_capture( $charge );
|
188 |
break;
|
189 |
+
case 'charge.refunded':
|
190 |
+
$charge = $event->data->object;
|
191 |
+
$this->charge_refund( $charge );
|
192 |
+
break;
|
193 |
+
case 'charge.dispute.created':
|
194 |
+
$charge = $event->data->object;
|
195 |
+
$this->charge_dispute_created( $charge );
|
196 |
+
break;
|
197 |
+
case 'charge.dispute.closed':
|
198 |
+
$dispute = $event->data->object;
|
199 |
+
$this->charge_dispute_closed( $dispute );
|
200 |
+
break;
|
201 |
+
case 'payment_intent.succeeded':
|
202 |
+
case 'payment_intent.amount_capturable_updated':
|
203 |
+
$intent = $event->data->object;
|
204 |
+
$this->payment_intent_succeeded( $intent );
|
205 |
+
break;
|
206 |
+
case 'payment_intent.payment_failed':
|
207 |
+
$intent = $event->data->object;
|
208 |
+
$this->payment_intent_failed( $intent );
|
209 |
+
break;
|
210 |
+
case 'review.opened':
|
211 |
+
$review = $event->data->object;
|
212 |
+
$this->review_opened( $review );
|
213 |
+
break;
|
214 |
+
case 'review.closed':
|
215 |
+
$review = $event->data->object;
|
216 |
+
$this->review_closed( $review );
|
217 |
+
break;
|
218 |
|
219 |
}
|
220 |
$success = constant( 'self::CPSW_' . strtoupper( $mode ) . '_LAST_SUCCESS_AT' );
|
229 |
* @return void
|
230 |
*/
|
231 |
public function charge_capture( $charge ) {
|
|
|
232 |
$payment_intent = sanitize_text_field( $charge->payment_intent );
|
233 |
+
$order_id = $this->get_order_id_from_intent( $payment_intent );
|
234 |
if ( ! $order_id ) {
|
235 |
Logger::error( 'Could not find order via charge ID: ' . $charge->id );
|
236 |
return;
|
268 |
|
269 |
}
|
270 |
|
271 |
+
/**
|
272 |
+
* Refunds WooCommerce order via webhook call
|
273 |
+
*
|
274 |
+
* @param object $charge Stripe Charge object.
|
275 |
+
* @return void
|
276 |
+
*/
|
277 |
+
public function charge_refund( $charge ) {
|
278 |
+
$payment_intent = sanitize_text_field( $charge->payment_intent );
|
279 |
+
$order_id = $this->get_order_id_from_intent( $payment_intent );
|
280 |
+
if ( ! $order_id ) {
|
281 |
+
Logger::error( 'Could not find order via charge ID: ' . $charge->id );
|
282 |
+
return;
|
283 |
+
}
|
284 |
+
|
285 |
+
$order = wc_get_order( $order_id );
|
286 |
+
|
287 |
+
if ( 'cpsw_stripe' === $order->get_payment_method() ) {
|
288 |
+
$transaction_id = $order->get_transaction_id();
|
289 |
+
$captured = $charge->captured;
|
290 |
+
$refund_id = $order->get_meta( '_cpsw_refund_id' );
|
291 |
+
$currency = strtoupper( $charge->currency );
|
292 |
+
$raw_amount = $charge->refunds->data[0]->amount;
|
293 |
+
|
294 |
+
if ( ! in_array( $currency, self::$zero_currencies, true ) ) {
|
295 |
+
$raw_amount = $raw_amount / 100;
|
296 |
+
}
|
297 |
+
|
298 |
+
$amount = wc_price( $raw_amount, [ 'currency' => $currency ] );
|
299 |
+
|
300 |
+
// If charge wasn't captured, no need to refund.
|
301 |
+
if ( ! $captured ) {
|
302 |
+
// Handling cancellation of unauthorized charge.
|
303 |
+
if ( 'cancelled' !== $order->get_status() ) {
|
304 |
+
/* translators: amount (including currency symbol) */
|
305 |
+
$order->add_order_note( sprintf( __( 'Pre-Authorization for %s voided from the Stripe Dashboard.', 'checkout-plugins-stripe-woo' ), $amount ) );
|
306 |
+
$order->update_status( 'cancelled' );
|
307 |
+
}
|
308 |
+
|
309 |
+
return;
|
310 |
+
}
|
311 |
+
|
312 |
+
// If the refund ID matches, don't continue to prevent double refunding.
|
313 |
+
if ( $charge->refunds->data[0]->id === $refund_id ) {
|
314 |
+
return;
|
315 |
+
}
|
316 |
+
|
317 |
+
if ( $transaction_id ) {
|
318 |
+
$reason = __( 'Refunded via stripe dashboard', 'checkout-plugins-stripe-woo' );
|
319 |
+
|
320 |
+
// Create the refund.
|
321 |
+
$refund = wc_create_refund(
|
322 |
+
[
|
323 |
+
'order_id' => $order_id,
|
324 |
+
'amount' => ( $charge->amount_refunded > 0 ) ? $raw_amount : false,
|
325 |
+
'reason' => $reason,
|
326 |
+
]
|
327 |
+
);
|
328 |
+
|
329 |
+
if ( is_wp_error( $refund ) ) {
|
330 |
+
Logger::error( $refund->get_error_message() );
|
331 |
+
}
|
332 |
+
|
333 |
+
$refund_id = $charge->refunds->data[0]->id;
|
334 |
+
$order->update_meta_data( '_cpsw_refund_id', $refund_id );
|
335 |
+
|
336 |
+
$refund_time = gmdate( 'Y-m-d H:i:s', time() );
|
337 |
+
$order->add_order_note( __( 'Reason : ', 'checkout-plugins-stripe-woo' ) . $reason . '.<br>' . __( 'Amount : ', 'checkout-plugins-stripe-woo' ) . $amount . '.<br>' . __( 'Status : Success', 'checkout-plugins-stripe-woo' ) . ' [ ' . $refund_time . ' ] <br>' . __( 'Transaction ID : ', 'checkout-plugins-stripe-woo' ) . $refund_id );
|
338 |
+
Logger::info( $reason . ' : ' . __( 'Amount : ', 'checkout-plugins-stripe-woo' ) . get_woocommerce_currency_symbol() . str_pad( $raw_amount, 2, 0 ) . __( ' Transaction ID : ', 'checkout-plugins-stripe-woo' ) . $refund_id, true );
|
339 |
+
}
|
340 |
+
}
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Handles charge.dispute.create webhook and changes order status to 'On Hold'
|
345 |
+
*
|
346 |
+
* @param int $charge stripe webhook object.
|
347 |
+
* @return void
|
348 |
+
* @since 1.2.0
|
349 |
+
*/
|
350 |
+
public function charge_dispute_created( $charge ) {
|
351 |
+
$payment_intent = sanitize_text_field( $charge->payment_intent );
|
352 |
+
$order_id = $this->get_order_id_from_intent( $payment_intent );
|
353 |
+
if ( ! $order_id ) {
|
354 |
+
Logger::error( 'Could not find order via charge ID: ' . $charge->id );
|
355 |
+
return;
|
356 |
+
}
|
357 |
+
|
358 |
+
$order = wc_get_order( $order_id );
|
359 |
+
$order->update_status( 'on-hold', __( 'This order is under dispute. Please respond via stripe dashboard.', 'checkout-plugins-stripe-woo' ) );
|
360 |
+
$order->update_meta_data( 'cpsw_status_before_dispute', $order->get_status() );
|
361 |
+
$this->send_failed_order_email( $order_id );
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Handles carge.dispute.closed webhook and update order status accordingly
|
366 |
+
*
|
367 |
+
* @param object $dispute dispute object recevied from stripe webhook.
|
368 |
+
* @return void
|
369 |
+
* @since 1.2.0
|
370 |
+
*/
|
371 |
+
public function charge_dispute_closed( $dispute ) {
|
372 |
+
$payment_intent = sanitize_text_field( $dispute->payment_intent );
|
373 |
+
$order_id = $this->get_order_id_from_intent( $payment_intent );
|
374 |
+
if ( ! $order_id ) {
|
375 |
+
Logger::error( 'Could not find order for dispute ID: ' . $dispute->id );
|
376 |
+
return;
|
377 |
+
}
|
378 |
+
|
379 |
+
$order = wc_get_order( $order_id );
|
380 |
+
|
381 |
+
switch ( $dispute->status ) {
|
382 |
+
case 'lost':
|
383 |
+
$message = __( 'The disputed order lost or accepted.', 'checkout-plugins-stripe-woo' );
|
384 |
+
break;
|
385 |
+
|
386 |
+
case 'won':
|
387 |
+
$message = __( 'The disputed order resolved in your favour.', 'checkout-plugins-stripe-woo' );
|
388 |
+
break;
|
389 |
+
|
390 |
+
case 'warning_closed':
|
391 |
+
$message = __( 'The inquiry or retrieval closed.', 'checkout-plugins-stripe-woo' );
|
392 |
+
break;
|
393 |
+
}
|
394 |
+
|
395 |
+
$status = 'lost' === $dispute->status ? 'failed' : $order->get_meta( 'cpsw_status_before_dispute' );
|
396 |
+
$order->update_status( $status, $message );
|
397 |
+
}
|
398 |
+
|
399 |
+
/**
|
400 |
+
* Handles webhook call of event payment_intent.succeeded
|
401 |
+
*
|
402 |
+
* @param object $intent intent object received from stripe.
|
403 |
+
* @return void
|
404 |
+
*/
|
405 |
+
public function payment_intent_succeeded( $intent ) {
|
406 |
+
$payment_intent = sanitize_text_field( $intent->id );
|
407 |
+
$order_id = $this->get_order_id_from_intent( $payment_intent );
|
408 |
+
if ( ! $order_id ) {
|
409 |
+
Logger::error( 'Could not find order via payment intent: ' . $intent->id );
|
410 |
+
return;
|
411 |
+
}
|
412 |
+
|
413 |
+
$order = wc_get_order( $order_id );
|
414 |
+
|
415 |
+
if ( ! $order->has_status(
|
416 |
+
[ 'pending', 'failed' ],
|
417 |
+
$order
|
418 |
+
) ) {
|
419 |
+
return;
|
420 |
+
}
|
421 |
+
|
422 |
+
$charge = end( $intent->charges->data );
|
423 |
+
/* translators: transaction id, order id */
|
424 |
+
Logger::info( sprintf( __( 'Stripe PaymentIntent %1$1s succeeded for order %2$2s', 'checkout-plugins-stripe-woo' ), $charge->id, $order_id ) );
|
425 |
+
$this->process_response( $charge, $order );
|
426 |
+
}
|
427 |
+
|
428 |
+
/**
|
429 |
+
* Handles webhook call payment_intent.payment_failed
|
430 |
+
*
|
431 |
+
* @param object $intent stripe webhook object.
|
432 |
+
* @return void
|
433 |
+
* @since 1.2.0
|
434 |
+
*/
|
435 |
+
public function payment_intent_failed( $intent ) {
|
436 |
+
$payment_intent = sanitize_text_field( $intent->id );
|
437 |
+
$order_id = $this->get_order_id_from_intent( $payment_intent );
|
438 |
+
if ( ! $order_id ) {
|
439 |
+
Logger::error( 'Could not find order via payment intent: ' . $intent->id );
|
440 |
+
return;
|
441 |
+
}
|
442 |
+
|
443 |
+
$order = wc_get_order( $order_id );
|
444 |
+
/* translators: The error message that was received from Stripe. */
|
445 |
+
$error_message = $intent->last_payment_error ? sprintf( __( 'Reason: %s', 'checkout-plugins-stripe-woo' ), $intent->last_payment_error->message ) : '';
|
446 |
+
/* translators: The error message that was received from Stripe. */
|
447 |
+
$message = sprintf( __( 'Stripe SCA authentication failed. %s', 'checkout-plugins-stripe-woo' ), $error_message );
|
448 |
+
$order->update_status( 'failed', $message );
|
449 |
+
|
450 |
+
$this->send_failed_order_email( $order_id );
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* Handles review.opened webhook
|
455 |
+
*
|
456 |
+
* @param int $review stripe webhook object.
|
457 |
+
* @return void
|
458 |
+
* @since 1.2.0
|
459 |
+
*/
|
460 |
+
public function review_opened( $review ) {
|
461 |
+
$payment_intent = sanitize_text_field( $review->payment_intent );
|
462 |
+
$order_id = $this->get_order_id_from_intent( $payment_intent );
|
463 |
+
if ( ! $order_id ) {
|
464 |
+
Logger::error( 'Could not find order via review ID: ' . $review->id );
|
465 |
+
return;
|
466 |
+
}
|
467 |
+
|
468 |
+
$order = wc_get_order( $order_id );
|
469 |
+
$order->update_status( 'on-hold', __( 'This order is under review. Please respond via stripe dashboard.', 'checkout-plugins-stripe-woo' ) );
|
470 |
+
$order->update_meta_data( 'cpsw_status_before_review', $order->get_status() );
|
471 |
+
$this->send_failed_order_email( $order_id );
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Handles review.closed webhook
|
476 |
+
*
|
477 |
+
* @param int $review stripe webhook object.
|
478 |
+
* @return void
|
479 |
+
* @since 1.2.0
|
480 |
+
*/
|
481 |
+
public function review_closed( $review ) {
|
482 |
+
$payment_intent = sanitize_text_field( $review->payment_intent );
|
483 |
+
$order_id = $this->get_order_id_from_intent( $payment_intent );
|
484 |
+
if ( ! $order_id ) {
|
485 |
+
Logger::error( 'Could not find order via review ID: ' . $review->id );
|
486 |
+
return;
|
487 |
+
}
|
488 |
+
|
489 |
+
$order = wc_get_order( $order_id );
|
490 |
+
/* translators: Review reson from stripe */
|
491 |
+
$message = sprintf( __( 'Review for this order has been resolved. Reason: %s', 'checkout-plugins-stripe-woo' ), $review->reason );
|
492 |
+
$order->update_status( $order->get_meta( 'cpsw_status_before_review' ), $message );
|
493 |
+
}
|
494 |
+
|
495 |
+
/**
|
496 |
+
* Fetch WooCommerce order id from payment intent
|
497 |
+
*
|
498 |
+
* @param string $payment_intent payment intent received from stripe.
|
499 |
+
* @return int order id.
|
500 |
+
* @since 1.2.0
|
501 |
+
*/
|
502 |
+
public function get_order_id_from_intent( $payment_intent ) {
|
503 |
+
global $wpdb;
|
504 |
+
return $wpdb->get_var( $wpdb->prepare( "SELECT post_id from {$wpdb->prefix}postmeta where meta_key = '_cpsw_intent_secret' and meta_value like %s", '%' . $payment_intent . '%' ) );
|
505 |
+
}
|
506 |
+
|
507 |
+
/**
|
508 |
+
* Process response for saved cards
|
509 |
+
*
|
510 |
+
* @param object $response intent response.
|
511 |
+
* @param object $order order response.
|
512 |
+
* @return array
|
513 |
+
*/
|
514 |
+
public function process_response( $response, $order ) {
|
515 |
+
Logger::info( 'Processing: ' . $response->id );
|
516 |
+
|
517 |
+
$order_id = $order->get_id();
|
518 |
+
$captured = ( isset( $response->captured ) && $response->captured ) ? 'yes' : 'no';
|
519 |
+
|
520 |
+
// Store charge data.
|
521 |
+
$order->update_meta_data( '_cpsw_charge_captured', $captured );
|
522 |
+
|
523 |
+
if ( 'yes' === $captured ) {
|
524 |
+
/**
|
525 |
+
* Charge can be captured but in a pending state. Payment methods
|
526 |
+
* that are asynchronous may take couple days to clear. Webhook will
|
527 |
+
* take care of the status changes.
|
528 |
+
*/
|
529 |
+
if ( 'pending' === $response->status ) {
|
530 |
+
$order_stock_reduced = $order->get_meta( '_order_stock_reduced', true );
|
531 |
+
|
532 |
+
if ( ! $order_stock_reduced ) {
|
533 |
+
wc_reduce_stock_levels( $order_id );
|
534 |
+
}
|
535 |
+
|
536 |
+
$order->set_transaction_id( $response->id );
|
537 |
+
/* translators: transaction id */
|
538 |
+
$order->update_status( 'on-hold', sprintf( __( 'Stripe charge awaiting payment: %s.', 'checkout-plugins-stripe-woo' ), $response->id ) );
|
539 |
+
}
|
540 |
+
|
541 |
+
if ( 'succeeded' === $response->status ) {
|
542 |
+
$order->payment_complete( $response->id );
|
543 |
+
|
544 |
+
/* translators: transaction id */
|
545 |
+
$message = sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'checkout-plugins-stripe-woo' ), $response->id );
|
546 |
+
Logger::info( $message, true );
|
547 |
+
$order->add_order_note( $message );
|
548 |
+
}
|
549 |
+
|
550 |
+
if ( 'failed' === $response->status ) {
|
551 |
+
$message = __( 'Payment processing failed. Please retry.', 'checkout-plugins-stripe-woo' );
|
552 |
+
Logger::error( $message, true );
|
553 |
+
$order->add_order_note( $message );
|
554 |
+
}
|
555 |
+
} else {
|
556 |
+
$order->set_transaction_id( $response->id );
|
557 |
+
|
558 |
+
if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
|
559 |
+
wc_reduce_stock_levels( $order_id );
|
560 |
+
}
|
561 |
+
|
562 |
+
/* translators: transaction id */
|
563 |
+
$order->update_status( 'on-hold', sprintf( __( 'Stripe charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization. Attempting to refund the order in part or in full will release the authorization and cancel the payment.', 'checkout-plugins-stripe-woo' ), $response->id ) );
|
564 |
+
}
|
565 |
+
|
566 |
+
if ( is_callable( [ $order, 'save' ] ) ) {
|
567 |
+
$order->save();
|
568 |
+
}
|
569 |
+
|
570 |
+
do_action( 'cpsw_process_response', $response, $order );
|
571 |
+
|
572 |
+
return $response;
|
573 |
+
}
|
574 |
+
|
575 |
+
/**
|
576 |
+
* Sends order failure email.
|
577 |
+
*
|
578 |
+
* @param int $order_id WooCommerce order id.
|
579 |
+
* @return void
|
580 |
+
* @since 1.2.0
|
581 |
+
*/
|
582 |
+
public function send_failed_order_email( $order_id ) {
|
583 |
+
$emails = WC()->mailer()->get_emails();
|
584 |
+
if ( ! empty( $emails ) && ! empty( $order_id ) ) {
|
585 |
+
$emails['WC_Email_Failed_Order']->trigger( $order_id );
|
586 |
+
}
|
587 |
+
}
|
588 |
+
|
589 |
/**
|
590 |
* Shows time difference as - XX minutes ago.
|
591 |
*
|
592 |
* @param datetime $datetime time of last event.
|
593 |
* @param boolean $full show full time difference.
|
594 |
* @return string
|
595 |
+
* @since 0.0.1
|
596 |
*/
|
597 |
public function time_elapsed_string( $datetime, $full = false ) {
|
598 |
$now = new DateTime();
|
inc/helper.php
CHANGED
@@ -8,6 +8,8 @@
|
|
8 |
|
9 |
namespace CPSW\Inc;
|
10 |
|
|
|
|
|
11 |
/**
|
12 |
* Stripe Webhook.
|
13 |
*/
|
@@ -20,10 +22,10 @@ class Helper {
|
|
20 |
*/
|
21 |
private static $gateway_defaults = [
|
22 |
'woocommerce_cpsw_stripe_settings' => [
|
23 |
-
'enabled'
|
24 |
-
'inline_cc'
|
25 |
-
'order_status'
|
26 |
-
'allowed_cards'
|
27 |
'mastercard',
|
28 |
'visa',
|
29 |
'diners',
|
@@ -32,24 +34,30 @@ class Helper {
|
|
32 |
'jcb',
|
33 |
'unionpay',
|
34 |
],
|
35 |
-
'express_checkout_location'
|
36 |
'product',
|
37 |
'cart',
|
38 |
'checkout',
|
39 |
],
|
40 |
-
'express_checkout_enabled'
|
41 |
-
'express_checkout_button_type'
|
42 |
-
'express_checkout_button_theme'
|
43 |
-
'express_checkout_button_height'
|
44 |
-
'express_checkout_title'
|
45 |
-
'express_checkout_tagline'
|
46 |
-
'
|
47 |
-
'
|
48 |
-
'
|
49 |
-
'
|
50 |
-
'
|
51 |
-
'
|
52 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
],
|
54 |
];
|
55 |
|
@@ -122,8 +130,7 @@ class Helper {
|
|
122 |
*/
|
123 |
public static function get_gateway_setting( $key = '', $gateway = 'cpsw_stripe' ) {
|
124 |
$settings = self::get_gateway_settings( $gateway );
|
125 |
-
|
126 |
-
$value = false;
|
127 |
|
128 |
if ( isset( $settings[ $key ] ) ) {
|
129 |
$value = $settings[ $key ];
|
@@ -148,6 +155,7 @@ class Helper {
|
|
148 |
*
|
149 |
* @param string $key Name of the key to get the value.
|
150 |
* @param mixed $gateway Name of the payment gateway to get options from the database.
|
|
|
151 |
* @return array $global_settings It returns all stripe settings in an array.
|
152 |
*/
|
153 |
public static function get_setting( $key = '', $gateway = false ) {
|
@@ -168,4 +176,25 @@ class Helper {
|
|
168 |
public static function get_payment_mode() {
|
169 |
return apply_filters( 'cpsw_payment_mode', self::get_setting( 'cpsw_mode' ) );
|
170 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
}
|
8 |
|
9 |
namespace CPSW\Inc;
|
10 |
|
11 |
+
use Exception;
|
12 |
+
|
13 |
/**
|
14 |
* Stripe Webhook.
|
15 |
*/
|
22 |
*/
|
23 |
private static $gateway_defaults = [
|
24 |
'woocommerce_cpsw_stripe_settings' => [
|
25 |
+
'enabled' => 'no',
|
26 |
+
'inline_cc' => 'yes',
|
27 |
+
'order_status' => '',
|
28 |
+
'allowed_cards' => [
|
29 |
'mastercard',
|
30 |
'visa',
|
31 |
'diners',
|
34 |
'jcb',
|
35 |
'unionpay',
|
36 |
],
|
37 |
+
'express_checkout_location' => [
|
38 |
'product',
|
39 |
'cart',
|
40 |
'checkout',
|
41 |
],
|
42 |
+
'express_checkout_enabled' => 'no',
|
43 |
+
'express_checkout_button_type' => 'default',
|
44 |
+
'express_checkout_button_theme' => 'dark',
|
45 |
+
'express_checkout_button_height' => '40',
|
46 |
+
'express_checkout_title' => 'Express Checkout',
|
47 |
+
'express_checkout_tagline' => 'Checkout quickly to use you favourite tool.',
|
48 |
+
'express_checkout_product_options' => 'no',
|
49 |
+
'express_checkout_product_page_position' => 'above',
|
50 |
+
'express_checkout_product_button_width' => '',
|
51 |
+
'express_checkout_product_sticky_footer' => 'yes',
|
52 |
+
'express_checkout_separator' => 'OR',
|
53 |
+
'express_checkout_product_checkout_page' => 'no',
|
54 |
+
'express_checkout_button_width' => '',
|
55 |
+
'express_checkout_button_alignment' => 'left',
|
56 |
+
'express_checkout_separator_checkout' => 'OR',
|
57 |
+
'express_checkout_checkout_page_position' => 'above-checkout',
|
58 |
+
],
|
59 |
+
'woocommerce_cpsw_alipay_settings' => [
|
60 |
+
'enabled' => 'no',
|
61 |
],
|
62 |
];
|
63 |
|
130 |
*/
|
131 |
public static function get_gateway_setting( $key = '', $gateway = 'cpsw_stripe' ) {
|
132 |
$settings = self::get_gateway_settings( $gateway );
|
133 |
+
$value = false;
|
|
|
134 |
|
135 |
if ( isset( $settings[ $key ] ) ) {
|
136 |
$value = $settings[ $key ];
|
155 |
*
|
156 |
* @param string $key Name of the key to get the value.
|
157 |
* @param mixed $gateway Name of the payment gateway to get options from the database.
|
158 |
+
*
|
159 |
* @return array $global_settings It returns all stripe settings in an array.
|
160 |
*/
|
161 |
public static function get_setting( $key = '', $gateway = false ) {
|
176 |
public static function get_payment_mode() {
|
177 |
return apply_filters( 'cpsw_payment_mode', self::get_setting( 'cpsw_mode' ) );
|
178 |
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Get webhook secret key.
|
182 |
+
*
|
183 |
+
* @since 1.2.0
|
184 |
+
*
|
185 |
+
* @return mixed
|
186 |
+
*/
|
187 |
+
public static function get_webhook_secret() {
|
188 |
+
if ( 'live' === self::get_payment_mode() ) {
|
189 |
+
$endpoint_secret = self::get_setting( 'cpsw_live_webhook_secret' );
|
190 |
+
} elseif ( 'test' === self::get_payment_mode() ) {
|
191 |
+
$endpoint_secret = self::get_setting( 'cpsw_test_webhook_secret' );
|
192 |
+
}
|
193 |
+
|
194 |
+
if ( empty( trim( $endpoint_secret ) ) ) {
|
195 |
+
return false;
|
196 |
+
}
|
197 |
+
|
198 |
+
return $endpoint_secret;
|
199 |
+
}
|
200 |
}
|
inc/notice.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Notice helper.
|
4 |
+
*
|
5 |
+
* @package checkout-plugins-stripe-woo
|
6 |
+
*
|
7 |
+
* @since 1.2.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace CPSW\Inc;
|
11 |
+
|
12 |
+
use CPSW\Inc\Traits\Get_Instance;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class that represents admin notices.
|
16 |
+
*
|
17 |
+
* @since 1.2.0
|
18 |
+
*/
|
19 |
+
class Notice {
|
20 |
+
|
21 |
+
use Get_Instance;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Notices (array)
|
25 |
+
*
|
26 |
+
* @var array
|
27 |
+
*/
|
28 |
+
public $notices = [];
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Constructor
|
32 |
+
*
|
33 |
+
* @since 1.2.0
|
34 |
+
*/
|
35 |
+
public function __construct() {
|
36 |
+
add_action( 'admin_notices', [ $this, 'get_notices' ] );
|
37 |
+
add_action( 'wp_loaded', [ $this, 'hide' ] );
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Allow this class and other classes to add slug keyed notices (to avoid duplication).
|
42 |
+
*
|
43 |
+
* @since 1.2.0
|
44 |
+
*
|
45 |
+
* @param string $slug Class slug.
|
46 |
+
* @param string $class CSS class name.
|
47 |
+
* @param string $message Notice message.
|
48 |
+
* @param string $dismissible Dismissible icon.
|
49 |
+
*
|
50 |
+
* @return void
|
51 |
+
*/
|
52 |
+
public function add( $slug, $class, $message, $dismissible = false ) {
|
53 |
+
$this->notices[ $slug ] = [
|
54 |
+
'class' => $class,
|
55 |
+
'message' => $message,
|
56 |
+
'dismissible' => $dismissible,
|
57 |
+
];
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Display any notices we've collected thus far.
|
62 |
+
*
|
63 |
+
* @since 1.2.0
|
64 |
+
*
|
65 |
+
* @return void
|
66 |
+
*/
|
67 |
+
public function get_notices() {
|
68 |
+
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
69 |
+
return;
|
70 |
+
}
|
71 |
+
|
72 |
+
foreach ( (array) $this->notices as $notice_key => $notice ) {
|
73 |
+
echo '<div class="' . esc_attr( $notice['class'] ) . '" style="position:relative;">';
|
74 |
+
|
75 |
+
if ( $notice['dismissible'] ) {
|
76 |
+
?>
|
77 |
+
<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'cpsw-stripe-hide-notice', $notice_key ), 'cpsw_stripe_hide_notices_nonce', '_cpsw_stripe_notice_nonce' ) ); ?>" class="woocommerce-message-close notice-dismiss" style="position:relative;float:right;padding:9px 0px 9px 9px 9px;text-decoration:none;"></a>
|
78 |
+
<?php
|
79 |
+
}
|
80 |
+
|
81 |
+
echo '<p>';
|
82 |
+
echo wp_kses(
|
83 |
+
$notice['message'],
|
84 |
+
[
|
85 |
+
'a' => [
|
86 |
+
'href' => [],
|
87 |
+
'target' => [],
|
88 |
+
],
|
89 |
+
]
|
90 |
+
);
|
91 |
+
echo '</p></div>';
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Hides any notice.
|
97 |
+
*
|
98 |
+
* @since 1.2.0
|
99 |
+
*
|
100 |
+
* @return void
|
101 |
+
*/
|
102 |
+
public function hide() {
|
103 |
+
if (
|
104 |
+
! isset( $_GET['_cpsw_stripe_notice_nonce'] )
|
105 |
+
|| ! wp_verify_nonce( $_GET['_cpsw_stripe_notice_nonce'], 'cpsw_stripe_hide_notices_nonce' )
|
106 |
+
) {
|
107 |
+
return;
|
108 |
+
}
|
109 |
+
|
110 |
+
$notice = wc_clean( wp_unslash( $_GET['cpsw-stripe-hide-notice'] ) );
|
111 |
+
|
112 |
+
update_option( 'cpsw_show_' . $notice . '_notice', 'no' );
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Check current page is cpsw setting page.
|
117 |
+
*
|
118 |
+
* @since 1.2.0
|
119 |
+
*
|
120 |
+
* @param string $section gateway section.
|
121 |
+
*
|
122 |
+
* @return boolean
|
123 |
+
*/
|
124 |
+
public function is_cpsw_section( $section ) {
|
125 |
+
if ( isset( $_GET['page'] ) && 'wc-settings' === sanitize_text_field( $_GET['page'] ) && isset( $_GET['tab'] ) && isset( $_GET['section'] ) && sanitize_text_field( $_GET['section'] ) === $section ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
126 |
+
return true;
|
127 |
+
}
|
128 |
+
|
129 |
+
return false;
|
130 |
+
}
|
131 |
+
}
|
inc/traits/subscriptions.php
CHANGED
@@ -296,6 +296,8 @@ trait Subscriptions {
|
|
296 |
* @return array
|
297 |
*/
|
298 |
public function create_and_confirm_intent_for_off_session( $order, $source, $amount ) {
|
|
|
|
|
299 |
$request = [
|
300 |
'amount' => $amount ? $this->get_formatted_amount( $order->get_total() ) : 0,
|
301 |
'currency' => $order->get_currency(),
|
@@ -305,6 +307,7 @@ trait Subscriptions {
|
|
305 |
'confirm' => 'true',
|
306 |
'confirmation_method' => 'automatic',
|
307 |
'customer' => $source->customer,
|
|
|
308 |
'payment_method' => $source->source,
|
309 |
'capture_method' => $this->capture_method,
|
310 |
];
|
@@ -312,8 +315,6 @@ trait Subscriptions {
|
|
312 |
if ( ! empty( trim( $this->statement_descriptor ) ) ) {
|
313 |
$request['statement_descriptor'] = $this->statement_descriptor;
|
314 |
}
|
315 |
-
|
316 |
-
$order_id = $order->get_id();
|
317 |
Logger::info( "Stripe Payment initiated for order $order_id" );
|
318 |
$stripe_api = new Stripe_Api();
|
319 |
$response = $stripe_api->payment_intents( 'create', [ $request ] );
|
296 |
* @return array
|
297 |
*/
|
298 |
public function create_and_confirm_intent_for_off_session( $order, $source, $amount ) {
|
299 |
+
$order_id = $order->get_id();
|
300 |
+
|
301 |
$request = [
|
302 |
'amount' => $amount ? $this->get_formatted_amount( $order->get_total() ) : 0,
|
303 |
'currency' => $order->get_currency(),
|
307 |
'confirm' => 'true',
|
308 |
'confirmation_method' => 'automatic',
|
309 |
'customer' => $source->customer,
|
310 |
+
'metadata' => $this->get_metadata( $order_id ),
|
311 |
'payment_method' => $source->source,
|
312 |
'capture_method' => $this->capture_method,
|
313 |
];
|
315 |
if ( ! empty( trim( $this->statement_descriptor ) ) ) {
|
316 |
$request['statement_descriptor'] = $this->statement_descriptor;
|
317 |
}
|
|
|
|
|
318 |
Logger::info( "Stripe Payment initiated for order $order_id" );
|
319 |
$stripe_api = new Stripe_Api();
|
320 |
$response = $stripe_api->payment_intents( 'create', [ $request ] );
|
readme.txt
CHANGED
@@ -3,27 +3,64 @@ Contributors: brainstormforce
|
|
3 |
Tags: stripe, credit card
|
4 |
Requires at least: 5.4
|
5 |
Tested up to: 5.8
|
6 |
-
Stable tag: 1.
|
7 |
Requires PHP: 5.6
|
8 |
License: GPLv2 or later
|
9 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
-
Stripe for WooCommerce delivers a simple, secure way to accept credit card payments
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
<strong>Accept credit card payments in your store with Stripe for WooCommerce.<strong>
|
16 |
|
17 |
-
The smoother the checkout process, the higher the chance of a sale, and offering multiple payment options is a proven way to boost sales.
|
18 |
|
19 |
-
Stripe for WooCommerce is
|
20 |
|
21 |
With Stripe you can accept payments from several card brands, from large global networks like Visa and Mastercard to local networks like Cartes Bancaires in France or Interac in Canada. Stripe also supports American Express, Discover, JCB, Diners Club and UnionPay.
|
22 |
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
-
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
== Installation ==
|
29 |
|
@@ -46,6 +83,12 @@ Here are easy steps
|
|
46 |
4. Disable the existing Stripe method from WooCommerce payment settings.
|
47 |
NOTE: NOT to deactivate your old payment gateway plugin. Your old subscription's renewal will be processed through the old plugin automatically.
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
== Screenshots ==
|
50 |
|
51 |
1. API Settings
|
@@ -55,11 +98,17 @@ NOTE: NOT to deactivate your old payment gateway plugin. Your old subscription's
|
|
55 |
|
56 |
== Changelog ==
|
57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
= 1.1.1 – WEDNESDAY, 22ND DECEMBER 2021 =
|
59 |
* Fix: Express Checkout buttons were not appearing in live mode.
|
60 |
|
61 |
= 1.1.0 – TUESDAY, 21ST DECEMBER 2021 =
|
62 |
-
* New: Express Checkout
|
63 |
|
64 |
= 1.0.0 – TUESDAY, 23RD NOVEMBER 2021 =
|
65 |
-
* Initial release
|
3 |
Tags: stripe, credit card
|
4 |
Requires at least: 5.4
|
5 |
Tested up to: 5.8
|
6 |
+
Stable tag: 1.2.0
|
7 |
Requires PHP: 5.6
|
8 |
License: GPLv2 or later
|
9 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
+
Stripe for WooCommerce delivers a simple, secure way to accept credit card payments, Apple Pay, and Google Pay on your WooCommerce store. Reduce payment friction and boost conversions using this free plugin!
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
<strong>Accept credit card payments in your store with Stripe for WooCommerce.<strong>
|
16 |
|
17 |
+
The smoother the checkout process, the higher the chance of a sale, and offering multiple payment options is a proven way to boost sales. This is where Stripe for WooCommerce comes in.
|
18 |
|
19 |
+
Stripe for WooCommerce is a payment plugin that delivers a simple, secure way to accept credit card payments using the Stripe service.
|
20 |
|
21 |
With Stripe you can accept payments from several card brands, from large global networks like Visa and Mastercard to local networks like Cartes Bancaires in France or Interac in Canada. Stripe also supports American Express, Discover, JCB, Diners Club and UnionPay.
|
22 |
|
23 |
+
## OFFER ONE CLICK CHECKOUT WITH EXPRESS PAY ##
|
24 |
+
|
25 |
+
The future of ecommerce checkout is express pay options that make it fast to place orders because your buyers don’t need to fill out the checkout form. All your buyers have to do is click one button and their order is complete.
|
26 |
+
|
27 |
+
Stripe For WooCommerce makes it easy to start offering express payment options such as Apple Pay and Google Pay and fully customize the style, design, and location of these express pay buttons.
|
28 |
+
|
29 |
+
You will be able to visually style the express pay buttons to match your brand. Next you can choose where you want to show the express pay buttons, on the product page, on the cart page, and on the checkout page.
|
30 |
+
|
31 |
+
Stripe for WooCommerce offers complete flexibility without needing to understand a single line of code.
|
32 |
+
|
33 |
+
### ABOUT CHECKOUT PLUGINS ###
|
34 |
+
|
35 |
+
## WE ARE AN OFFICIAL STRIPE PARTNER ##
|
36 |
+
|
37 |
+
Checkout Plugins is an official Stripe partner!
|
38 |
+
|
39 |
+
We also make some of the most popular and loved WordPress & WooCommerce products.
|
40 |
+
|
41 |
+
## ABOUT US ##
|
42 |
+
|
43 |
+
Checkout Plugins is part of the Brainstorm Force family of products which are used on millions of websites.
|
44 |
|
45 |
+
Here are some of our products:
|
46 |
|
47 |
+
* **Astra Theme**
|
48 |
+
Currently used by nearly 2 million websites, Astra Theme is the most popular WordPress theme and is also the most popular WooCommerce theme. Stripe for WooCommerce was made to work perfectly with Astra Theme. [Visit Astra Theme](https://wpastra.com)
|
49 |
+
|
50 |
+
* **CartFlows**
|
51 |
+
Currently used by nearly 300,000 store owners to get more orders and increase the order value through our conversion optimized checkout replacement for WooCommerce, checkout order bumps, one-click post purchase upsells, and A/B split testing engine. [Visit CartFlows](https://cartflows.com)
|
52 |
+
|
53 |
+
* **Cart Abandonment Recovery**
|
54 |
+
Currently used by nearly 400,000 store owners to capture lost revenue caused by buyers that don’t complete their checkout. Cart Abandonment Recovery captures these lost orders and automatically contacts the lost buyers to get them to complete their order. [Visit Cart Abandonment Recovery](https://wordpress.org/plugins/woo-cart-abandonment-recovery/)
|
55 |
+
|
56 |
+
* **Starter Templates**
|
57 |
+
Currently used by nearly 2 million websites, Starter Templates offers hundreds of complete website templates, including over 50 website designs for WooCommerce stores. [Visit Starter Templates](https://wordpress.org/plugins/astra-sites/)
|
58 |
+
|
59 |
+
As you can see, we know WooCommerce inside and out and help thousands of store owners build highly profitable stores everyday.
|
60 |
+
|
61 |
+
Stripe for WooCommerce will also bring support for Apple pay, Google pay, ACH and iDeal in upcoming updates.
|
62 |
+
|
63 |
+
Stripe for WooCommerce supports WooCommerce Subscriptions where users can make recurring payments for products and services. It’s the only payment plugin you need for your store!
|
64 |
|
65 |
== Installation ==
|
66 |
|
83 |
4. Disable the existing Stripe method from WooCommerce payment settings.
|
84 |
NOTE: NOT to deactivate your old payment gateway plugin. Your old subscription's renewal will be processed through the old plugin automatically.
|
85 |
|
86 |
+
= Does this plugin work with my theme? =
|
87 |
+
Yes, Stripe for WooCommerce will work with all themes. If you run into any trouble, please let us know and we will be happy to resolve any issues.
|
88 |
+
|
89 |
+
= Do you offer support for this plugin? =
|
90 |
+
Yes, this plugin is fully supported. You can open a request here on the plugin page or visit our website to fill out our support request form.
|
91 |
+
|
92 |
== Screenshots ==
|
93 |
|
94 |
1. API Settings
|
98 |
|
99 |
== Changelog ==
|
100 |
|
101 |
+
= 1.2.0 – TUESDAY, 4TH JANUARY 2022 =
|
102 |
+
* New: Supports Alipay payment method.
|
103 |
+
* New: Supports iDEAL payment method.
|
104 |
+
* Improvement: More customization options for Express Checkout.
|
105 |
+
* Improvement: Webhook integration for multiple events - charge.refunded, charge.dispute.created, charge.dispute.closed, payment_intent.succeeded, payment_intent.amount_capturable_updated, payment_intent.payment_failed, review.opened, review.closed.
|
106 |
+
|
107 |
= 1.1.1 – WEDNESDAY, 22ND DECEMBER 2021 =
|
108 |
* Fix: Express Checkout buttons were not appearing in live mode.
|
109 |
|
110 |
= 1.1.0 – TUESDAY, 21ST DECEMBER 2021 =
|
111 |
+
* New: Express Checkout.
|
112 |
|
113 |
= 1.0.0 – TUESDAY, 23RD NOVEMBER 2021 =
|
114 |
+
* Initial release.
|