diff --git a/phpunit.xml b/phpunit.xml index 6fe6ed779..b3baf8eb9 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -12,7 +12,8 @@ > - ./tests/unit + ./tests/unit/ + ./tests/unit/* ./tests/integration diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 5707dfdc9..e6318ae9f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -69,10 +69,19 @@ public function load_framework() { require_once( $this->framework_dir . '/woocommerce/compatibility/abstract-sv-wc-data-compatibility.php' ); require_once( $this->framework_dir . '/woocommerce/compatibility/class-sv-wc-order-compatibility.php' ); + // API + require_once( $this->framework_dir . '/woocommerce/api/interface-sv-wc-api-request.php' ); + require_once( $this->framework_dir . '/woocommerce/api/interface-sv-wc-api-response.php' ); + require_once( $this->framework_dir . '/woocommerce/api/abstract-sv-wc-api-json-request.php' ); + require_once( $this->framework_dir . '/woocommerce/api/abstract-sv-wc-api-json-response.php' ); + // payment gateways require_once( $this->framework_dir . '/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php' ); require_once( $this->framework_dir . '/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-token.php' ); require_once( $this->framework_dir . '/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php' ); + require_once( $this->framework_dir . '/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-request.php' ); + require_once( $this->framework_dir . '/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-response.php' ); + require_once( $this->framework_dir . '/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-payment-response.php' ); echo "Loaded Framework..." . PHP_EOL; diff --git a/tests/unit/payment-gateway/apple-pay-api-request.php b/tests/unit/payment-gateway/apple-pay-api-request.php new file mode 100644 index 000000000..2696c43c8 --- /dev/null +++ b/tests/unit/payment-gateway/apple-pay-api-request.php @@ -0,0 +1,66 @@ +getMock( 'SV_WC_Payment_Gateway' ); + + $request = new \SV_WC_Payment_Gateway_Apple_Pay_API_Request( $gateway ); + + $request->set_merchant_data( $merchant_id, $domain_name, $display_name ); + + $this->assertEquals( $expected, $request->to_string() ); + } + + + /** + * Data provider for test_set_merchant_data() + * + * @since 4.5.0 + * @return array + */ + public function provider_test_set_merchant_data() { + + return array( + array( + 'merchant', + 'https://domain.com', + 'Domain', + json_encode( array( + 'merchantIdentifier' => 'merchant', + 'domainName' => 'domain.com', + 'displayName' => 'Domain', + ) ), + ), + array( + 'merchant', + 'http://domain.com', + 'Domain', + json_encode( array( + 'merchantIdentifier' => 'merchant', + 'domainName' => 'domain.com', + 'displayName' => 'Domain', + ) ), + ), + ); + } + + +} diff --git a/tests/unit/payment-gateway/apple-pay-api-response.php b/tests/unit/payment-gateway/apple-pay-api-response.php new file mode 100644 index 000000000..65ce7774a --- /dev/null +++ b/tests/unit/payment-gateway/apple-pay-api-response.php @@ -0,0 +1,112 @@ +get_error_response_data() ); + + $this->assertEquals( '123', $response->get_status_code() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_status_code() + * + * @since 4.7.0-dev + */ + public function test_get_status_code_blank() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_API_Response( '' ); + + $this->assertNull( $response->get_status_code() ); + } + + + /** + * Test for \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_status_message() + * + * @since 4.7.0-dev + */ + public function test_get_status_message() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_API_Response( $this->get_error_response_data() ); + + $this->assertEquals( 'Error', $response->get_status_message() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_status_message() + * + * @since 4.7.0-dev + */ + public function test_get_status_message_blank() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_API_Response( '' ); + + $this->assertNull( $response->get_status_message() ); + } + + + /** + * Test for \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_merchant_session() + * + * @since 4.7.0-dev + */ + public function test_get_merchant_session() { + + $data = json_encode( array( 'response' ) ); + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_API_Response( $data ); + + $this->assertEquals( $data, $response->get_merchant_session() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_merchant_session() + * + * @since 4.7.0-dev + */ + public function test_get_merchant_session_blank() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_API_Response( '' ); + + $this->assertEquals( '', $response->get_merchant_session() ); + } + + + /** + * Gets an example error response. + * + * @since 4.7.0-dev + * @return string + */ + private function get_error_response_data() { + + $data = array( + 'statusCode' => '123', + 'statusMessage' => 'Error', + ); + + return json_encode( $data ); + } + + +} diff --git a/tests/unit/payment-gateway/apple-pay-payment-response.php b/tests/unit/payment-gateway/apple-pay-payment-response.php new file mode 100644 index 000000000..cbb3839c8 --- /dev/null +++ b/tests/unit/payment-gateway/apple-pay-payment-response.php @@ -0,0 +1,265 @@ +get_valid_response_data() ); + + $this->assertEquals( array( 'This is the payment data.' ), $response->get_payment_data() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_payment_data() + * + * @since 4.7.0-dev + */ + public function test_get_payment_data_blank() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( '' ); + + $this->assertEquals( array(), $response->get_payment_data() ); + } + + + /** + * Test for \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_transaction_id() + * + * @since 4.7.0-dev + */ + public function test_get_transaction_id() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( $this->get_valid_response_data() ); + + $this->assertEquals( '12345', $response->get_transaction_id() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_transaction_id() + * + * @since 4.7.0-dev + */ + public function test_get_transaction_id_blank() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( '' ); + + $this->assertEquals( '', $response->get_transaction_id() ); + } + + + /** + * Test for \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_card_type() + * + * @since 4.7.0-dev + */ + public function test_get_card_type() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( $this->get_valid_response_data() ); + + $this->assertEquals( 'visa', $response->get_card_type() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_card_type() + * + * @since 4.7.0-dev + */ + public function test_get_card_type_blank() { + + Mock::wpFunction( 'wp_list_pluck', array( + 'return' => array( + 'visa' => array( 'Visa' ), + ), + ) ); + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( '' ); + + $this->assertEquals( 'card', $response->get_card_type() ); + } + + + /** + * Test for \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_last_four() + * + * @since 4.7.0-dev + */ + public function test_get_last_four() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( $this->get_valid_response_data() ); + + $this->assertEquals( '1234', $response->get_last_four() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_last_four() + * + * @since 4.7.0-dev + */ + public function test_get_last_four_blank() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( '' ); + + $this->assertEquals( '', $response->get_last_four() ); + } + + + /** + * Test for \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_billing_address() + * + * @since 4.7.0-dev + */ + public function test_get_billing_address() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( $this->get_valid_response_data() ); + + $expected = array( + 'first_name' => 'Lloyd', + 'last_name' => 'Christmas', + 'address_1' => '333 E Wonderview Ave.', + 'address_2' => 'Room 217', + 'city' => 'Estes Park', + 'state' => 'CO', + 'postcode' => '80517', + 'country' => 'US', + 'email' => 'lloyd@igotworms.com', + 'phone' => '(123) 555-1234', + ); + + $this->assertEquals( $expected, $response->get_billing_address() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_billing_address() + * + * @since 4.7.0-dev + */ + public function test_get_billing_address_blank() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( '' ); + + $expected = array( + 'first_name' => '', + 'last_name' => '', + 'address_1' => '', + 'address_2' => '', + 'city' => '', + 'state' => '', + 'postcode' => '', + 'country' => '', + ); + + $this->assertEquals( $expected, $response->get_billing_address() ); + } + + + /** + * Test for \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_shipping_address() + * + * @since 4.7.0-dev + */ + public function test_get_shipping_address() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( $this->get_valid_response_data() ); + + $expected = array( + 'first_name' => 'Mary', + 'last_name' => 'Swanson', + 'address_1' => '2250 Deer Valley Drive', + 'address_2' => '', + 'city' => 'Aspen', + 'state' => 'CO', + 'postcode' => '81611', + 'country' => 'US', + ); + + $this->assertEquals( $expected, $response->get_shipping_address() ); + } + + + /** + * Test for blank \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response::get_shipping_address() + * + * @since 4.7.0-dev + */ + public function test_get_shipping_address_blank() { + + $response = new \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( '' ); + + $expected = array( + 'first_name' => '', + 'last_name' => '', + 'address_1' => '', + 'address_2' => '', + 'city' => '', + 'state' => '', + 'postcode' => '', + 'country' => '', + ); + + $this->assertEquals( $expected, $response->get_shipping_address() ); + } + + + private function get_valid_response_data() { + + $data = array( + 'token' => array( + 'paymentData' => array( 'This is the payment data.' ), + 'transactionIdentifier' => '12345', + 'paymentMethod' => array( + 'network' => 'Visa', + 'displayName' => 'Visa 1234', + ), + ), + 'billingContact' => array( + 'givenName' => 'Lloyd', + 'familyName' => 'Christmas', + 'addressLines' => array( + '333 E Wonderview Ave.', + 'Room 217', + ), + 'locality' => 'Estes Park', + 'administrativeArea' => 'CO', + 'postalCode' => '80517', + 'countryCode' => 'us', // Apple returns this as lowercase + ), + 'shippingContact' => array( + 'givenName' => 'Mary', + 'familyName' => 'Swanson', + 'addressLines' => array( + '2250 Deer Valley Drive', + ), + 'locality' => 'Aspen', + 'administrativeArea' => 'CO', + 'postalCode' => '81611', + 'countryCode' => 'us', + 'emailAddress' => 'lloyd@igotworms.com', // The shipping address contains the email & phone + 'phoneNumber' => '(123) 555-1234', // The tests ensure they end up with the billing address as per WC standards + ), + ); + + return json_encode( $data ); + } + + +} diff --git a/woocommerce/class-sv-wc-plugin-compatibility.php b/woocommerce/class-sv-wc-plugin-compatibility.php index fe28a01af..804970483 100644 --- a/woocommerce/class-sv-wc-plugin-compatibility.php +++ b/woocommerce/class-sv-wc-plugin-compatibility.php @@ -121,6 +121,25 @@ public static function product_get_id( WC_Product $product ) { } + /** + * Backports wc_shipping_enabled() to < 2.6.0 + * + * @since 4.7.0-dev + * @return bool + */ + public static function wc_shipping_enabled() { + + if ( self::is_wc_version_gte_2_6() ) { + + return wc_shipping_enabled(); + + } else { + + return 'yes' === get_option( 'woocommerce_calc_shipping' ); + } + } + + /** * Backports wc_help_tip() to WC 2.4.x * @@ -269,8 +288,8 @@ public static function is_wc_version_gt( $version ) { * TODO: Add WP version check when https://core.trac.wordpress.org/ticket/18857 is addressed {BR 2016-12-12} * * @since 4.6.0 - * @param string $slug The slug for the screen ID to normalize (minus `woocommerce_page_`). - * @return string Normalized screen ID. + * @param string $slug slug for the screen ID to normalize (minus `woocommerce_page_`) + * @return string normalized screen ID */ public static function normalize_wc_screen_id( $slug = 'wc-settings' ) { diff --git a/woocommerce/compatibility/class-sv-wc-order-compatibility.php b/woocommerce/compatibility/class-sv-wc-order-compatibility.php index d6748d89e..c6b089b63 100644 --- a/woocommerce/compatibility/class-sv-wc-order-compatibility.php +++ b/woocommerce/compatibility/class-sv-wc-order-compatibility.php @@ -281,6 +281,84 @@ public static function add_fee( WC_Order $order, $fee ) { } + /** + * Order item CRUD compatibility method to add a shipping line to an order. + * + * @since 4.7.0-dev + * + * @param \WC_Order $order order object + * @param \WC_Shipping_Rate $shipping_rate shipping rate to add + * @return int the order item ID + */ + public static function add_shipping( WC_Order $order, $shipping_rate ) { + + if ( SV_WC_Plugin_Compatibility::is_wc_version_gte_3_0() ) { + + $item = new WC_Order_Item_Shipping(); + + $item->set_props( array( + 'method_title' => $shipping_rate->label, + 'method_id' => $shipping_rate->id, + 'total' => wc_format_decimal( $shipping_rate->cost ), + 'taxes' => $shipping_rate->taxes, + 'order_id' => $order->get_id(), + ) ); + + foreach ( $shipping_rate->get_meta_data() as $key => $value ) { + $item->add_meta_data( $key, $value, true ); + } + + $item->save(); + + $order->add_item( $item ); + + return $item->get_id(); + + } else { + + return $order->add_shipping( $shipping_rate ); + } + } + + + /** + * Order item CRUD compatibility method to add a tax line to an order. + * + * @since 4.7.0-dev + * + * @param \WC_Order $order order object + * @param int $tax_rate_id tax rate ID + * @param float $tax_amount cart tax amount + * @param float $shipping_tax_amount shipping tax amount + * @return int order item ID + */ + public static function add_tax( WC_Order $order, $tax_rate_id, $tax_amount = 0, $shipping_tax_amount = 0 ) { + + if ( SV_WC_Plugin_Compatibility::is_wc_version_gte_3_0() ) { + + $item = new WC_Order_Item_Tax(); + + $item->set_props( array( + 'rate_id' => $tax_rate_id, + 'tax_total' => $tax_amount, + 'shipping_tax_total' => $shipping_tax_amount, + ) ); + + $item->set_rate( $tax_rate_id ); + $item->set_order_id( $order->get_id() ); + $item->save(); + + $order->add_item( $item ); + + return $item->get_id(); + + } else { + + return $order->add_tax( $tax_rate_id, $tax_amount, $shipping_tax_amount ); + } + } + + /** * Order item CRUD compatibility method to update an order coupon. * diff --git a/woocommerce/i18n/languages/woocommerce-plugin-framework.pot b/woocommerce/i18n/languages/woocommerce-plugin-framework.pot index 2e1e6a097..292bad9ff 100644 --- a/woocommerce/i18n/languages/woocommerce-plugin-framework.pot +++ b/woocommerce/i18n/languages/woocommerce-plugin-framework.pot @@ -1,4 +1,4 @@ -# Copyright (C) 2017 +# Copyright (C) 2017 # This file is distributed under the same license as the package. msgid "" msgstr "" @@ -64,17 +64,17 @@ msgstr "" msgid "WooCommerce" msgstr "" -#: class-sv-wc-plugin.php:179 +#: class-sv-wc-plugin.php:168 #. translators: Placeholders: %s - plugin name msgid "You cannot clone instances of %s." msgstr "" -#: class-sv-wc-plugin.php:189 +#: class-sv-wc-plugin.php:178 #. translators: Placeholders: %s - plugin name msgid "You cannot unserialize instances of %s." msgstr "" -#: class-sv-wc-plugin.php:400 +#: class-sv-wc-plugin.php:385 #. translators: Placeholders: %1$s - plugin name, %2$s - a PHP #. extension/comma-separated list of PHP extensions msgid "" @@ -87,7 +87,7 @@ msgid_plural "" msgstr[0] "" msgstr[1] "" -#: class-sv-wc-plugin.php:423 +#: class-sv-wc-plugin.php:408 #. translators: Placeholders: %1$s - plugin name, %2$s - a PHP #. function/comma-separated list of PHP functions msgid "" @@ -99,54 +99,37 @@ msgid_plural "" msgstr[0] "" msgstr[1] "" -#: class-sv-wc-plugin.php:448 +#: class-sv-wc-plugin.php:433 #. translators: Placeholders: %s - plugin name msgid "" "%s may behave unexpectedly because the following PHP configuration settings " "are required:" msgstr "" -#: class-sv-wc-plugin.php:462 +#: class-sv-wc-plugin.php:447 msgid "%s or higher" msgstr "" -#: class-sv-wc-plugin.php:472 +#: class-sv-wc-plugin.php:457 msgid "" "Please contact your hosting provider or server administrator to configure " "these settings." msgstr "" -#: class-sv-wc-plugin.php:485 -#. translators: Placeholders: %1$s -

, %2$s -

, %3$s - , %4$s - -#. , %5$s - plugin name, %6$s - link, %7$s - -msgid "" -"%1$sHey there! We've noticed that your server is running %3$san outdated " -"version of PHP%4$s, which is the programming language that WooCommerce and " -"its extensions are built on.\n" -"\t\t\t\t\tThe PHP version that is currently used for your site is no longer " -"maintained, nor %3$sreceives security updates%4$s; newer versions are " -"faster and more secure.%2$s\n" -"\t\t\t\t\t%1$sAs a result, %5$s will no longer support this version on July " -"1, so you should upgrade PHP prior to this date. Your hosting provider can " -"do this for you.\n" -"\t\t\t\t\t%6$sHere are some resources to help you upgrade%7$s and to " -"explain PHP versions further.%2$s" -msgstr "" - -#: class-sv-wc-plugin.php:525 +#: class-sv-wc-plugin.php:487 #. translators: Docs as in Documentation msgid "Docs" msgstr "" -#: class-sv-wc-plugin.php:718 +#: class-sv-wc-plugin.php:680 msgid "%1$s - A minimum of %2$s is required." msgstr "" -#: class-sv-wc-plugin.php:727 +#: class-sv-wc-plugin.php:689 msgid "Set as %1$s - %2$s is required." msgstr "" -#: class-sv-wc-plugin.php:964 +#: class-sv-wc-plugin.php:926 msgid "Configure" msgstr "" @@ -221,7 +204,7 @@ msgid "%s Payment Tokens" msgstr "" #: payment-gateway/admin/class-sv-wc-payment-gateway-admin-user-handler.php:287 -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:673 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:602 msgid "Customer ID" msgstr "" @@ -230,7 +213,7 @@ msgid "This section contains configuration settings for this gateway." msgstr "" #: payment-gateway/admin/views/html-admin-gateway-status.php:52 -#: payment-gateway/class-sv-wc-payment-gateway.php:876 +#: payment-gateway/class-sv-wc-payment-gateway.php:948 #. translators: environment as in a software environment (test/production) msgid "Environment" msgstr "" @@ -248,7 +231,7 @@ msgid "Displays whether or not tokenization is enabled for this gateway." msgstr "" #: payment-gateway/admin/views/html-admin-gateway-status.php:74 -#: payment-gateway/class-sv-wc-payment-gateway.php:806 +#: payment-gateway/class-sv-wc-payment-gateway.php:878 msgid "Debug Mode" msgstr "" @@ -265,12 +248,12 @@ msgid "Display at Checkout" msgstr "" #: payment-gateway/admin/views/html-admin-gateway-status.php:82 -#: payment-gateway/class-sv-wc-payment-gateway.php:814 +#: payment-gateway/class-sv-wc-payment-gateway.php:886 msgid "Save to Log" msgstr "" #: payment-gateway/admin/views/html-admin-gateway-status.php:84 -#: payment-gateway/class-sv-wc-payment-gateway.php:812 +#: payment-gateway/class-sv-wc-payment-gateway.php:884 msgid "Off" msgstr "" @@ -287,6 +270,7 @@ msgid "The gateway customer ID for the user. Only edit this if necessary." msgstr "" #: payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:95 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:127 msgid "An error occurred, please try again or try an alternate form of payment" msgstr "" @@ -406,6 +390,178 @@ msgid "" "Please verify the address and try again." msgstr "" +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:74 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:91 +msgid "Apple Pay" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:97 +#: payment-gateway/class-sv-wc-payment-gateway.php:824 +msgid "Enable / Disable" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:98 +msgid "Accept Apple Pay" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:105 +msgid "Allow Apple Pay on" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:115 +msgid "Button Style" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:118 +msgid "Black" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:119 +msgid "White" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:120 +msgid "White with outline" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:134 +msgid "Buy Now" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:137 +msgid "" +"The %1$sBuy Now with Apple Pay%2$s button is displayed on single product " +"pages, and is only available for simple products. Use these settings to set " +"an optional tax rate and shipping cost for customers who use Buy Now." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:147 +msgid "Tax Rate" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:149 +msgid "The optional tax rate percentage to apply to Buy Now orders." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:157 +msgid "Shipping Cost" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:159 +msgid "The optional flat-rate shipping cost to add to Buy Now orders." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:172 +#: payment-gateway/class-sv-wc-payment-gateway.php:999 +msgid "Connection Settings" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:178 +msgid "Apple Merchant ID" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:182 +msgid "This is found in your %1$sApple developer account%2$s" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:189 +msgid "Certificate Path" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:194 +#. translators: Placeholders: %s - the server's web root path +msgid "For reference, your current web root path is: %s" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:207 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:217 +msgid "Processing Gateway" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:346 +msgid "Your site must be served over HTTPS with a valid SSL certificate." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:356 +#. translators: Placeholders: %1$s - plugin name, %2$s - a +#. currency/comma-separated list of currencies, %3$s - tag, %4$s - tag +msgid "" +"Accepts payment in %1$s only. %2$sConfigure%3$s WooCommerce to accept %1$s " +"to enable Apple Pay." +msgid_plural "" +"Accepts payment in one of %1$s only. %2$sConfigure%3$s WooCommerce to " +"accept one of %1$s to enable Apple Pay." +msgstr[0] "" +msgstr[1] "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:375 +msgid "" +"Your %1$sMerchant Identity Certificate%2$s cannot be found. Please check " +"your path configuration." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:382 +msgid "Apple Pay is disabled." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:419 +msgid "Single products" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:420 +msgid "Cart" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:421 +msgid "Checkout" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:164 +msgid "Buy with" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:419 +msgid "No shipping method chosen." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:478 +msgid "Apple Pay is currently unavailable." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:566 +msgid "Discount" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:580 +msgid "Shipping" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:590 +msgid "Taxes" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:167 +msgid "Apple Pay payment authorized." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:190 +msgid "Apple Pay payment failed. %s" +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:307 +msgid "The product is out of stock." +msgstr "" + +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:402 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:415 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:432 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:444 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:487 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:502 +#: payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:504 +msgid "Error %d: Unable to create order. Please try again." +msgstr "" + #: payment-gateway/class-sv-wc-payment-gateway-direct.php:99 msgid "" "Payment error, please try another payment method or contact us to complete " @@ -413,82 +569,82 @@ msgid "" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:199 -#: payment-gateway/class-sv-wc-payment-gateway.php:410 +#: payment-gateway/class-sv-wc-payment-gateway.php:413 msgid "Card expiration date is invalid" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:223 -#: payment-gateway/class-sv-wc-payment-gateway.php:403 +#: payment-gateway/class-sv-wc-payment-gateway.php:406 msgid "Card number is missing" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:229 -#: payment-gateway/class-sv-wc-payment-gateway.php:406 +#: payment-gateway/class-sv-wc-payment-gateway.php:409 msgid "Card number is invalid (wrong length)" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:234 -#: payment-gateway/class-sv-wc-payment-gateway.php:405 +#: payment-gateway/class-sv-wc-payment-gateway.php:408 msgid "Card number is invalid (only digits allowed)" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:239 -#: payment-gateway/class-sv-wc-payment-gateway.php:404 +#: payment-gateway/class-sv-wc-payment-gateway.php:407 msgid "Card number is invalid" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:266 -#: payment-gateway/class-sv-wc-payment-gateway.php:408 +#: payment-gateway/class-sv-wc-payment-gateway.php:411 msgid "Card security code is invalid (only digits are allowed)" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:272 -#: payment-gateway/class-sv-wc-payment-gateway.php:409 +#: payment-gateway/class-sv-wc-payment-gateway.php:412 msgid "Card security code is invalid (must be 3 or 4 digits)" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:278 -#: payment-gateway/class-sv-wc-payment-gateway.php:407 +#: payment-gateway/class-sv-wc-payment-gateway.php:410 msgid "Card security code is missing" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:305 -#: payment-gateway/class-sv-wc-payment-gateway.php:419 +#: payment-gateway/class-sv-wc-payment-gateway.php:422 msgid "Routing Number is missing" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:312 -#: payment-gateway/class-sv-wc-payment-gateway.php:420 +#: payment-gateway/class-sv-wc-payment-gateway.php:423 msgid "Routing Number is invalid (only digits are allowed)" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:318 -#: payment-gateway/class-sv-wc-payment-gateway.php:421 +#: payment-gateway/class-sv-wc-payment-gateway.php:424 msgid "Routing number is invalid (must be 9 digits)" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:327 -#: payment-gateway/class-sv-wc-payment-gateway.php:416 +#: payment-gateway/class-sv-wc-payment-gateway.php:419 msgid "Account Number is missing" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:334 -#: payment-gateway/class-sv-wc-payment-gateway.php:417 +#: payment-gateway/class-sv-wc-payment-gateway.php:420 msgid "Account Number is invalid (only digits are allowed)" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:340 -#: payment-gateway/class-sv-wc-payment-gateway.php:418 +#: payment-gateway/class-sv-wc-payment-gateway.php:421 msgid "Account number is invalid (must be between 5 and 17 digits)" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:347 -#: payment-gateway/class-sv-wc-payment-gateway.php:415 +#: payment-gateway/class-sv-wc-payment-gateway.php:418 msgid "Drivers license number is invalid" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:353 -#: payment-gateway/class-sv-wc-payment-gateway.php:411 +#: payment-gateway/class-sv-wc-payment-gateway.php:414 msgid "Check Number is invalid (only digits are allowed)" msgstr "" @@ -505,11 +661,11 @@ msgid "Check number %s" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:613 -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:688 -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:703 -#: payment-gateway/class-sv-wc-payment-gateway.php:1308 -#: payment-gateway/class-sv-wc-payment-gateway.php:1618 -#: payment-gateway/class-sv-wc-payment-gateway.php:1839 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:697 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:694 +#: payment-gateway/class-sv-wc-payment-gateway.php:1375 +#: payment-gateway/class-sv-wc-payment-gateway.php:1685 +#: payment-gateway/class-sv-wc-payment-gateway.php:1906 #: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:313 #. translators: Placeholders: %s - transaction ID msgid "(Transaction ID %s)" @@ -518,57 +674,62 @@ msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:676 #. translators: Placeholders: %1$s - payment method title, %2$s - environment #. ("Test"), %3$s - transaction type (authorization/charge), %4$s - card type -#. (mastercard, visa, ...), %5$s - last four digits of the card, %6$s - expiry -#. date -msgid "%1$s %2$s %3$s Approved: %4$s ending in %5$s (expires %6$s)" +#. (mastercard, visa, ...), %5$s - last four digits of the card +msgid "%1$s %2$s %3$s Approved: %4$s ending in %5$s" +msgstr "" + +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:689 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:565 +#: payment-gateway/class-sv-wc-payment-gateway-payment-form.php:659 +#. translators: Placeholders: %s - expiry date +msgid "(expires %s)" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:750 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:759 #. translators: Placeholders: %s - failure message msgid "Tokenization Request Failed: %s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:761 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:770 #. translators: Placeholders: %1$s - payment method title, %2$s - failure #. message msgid "%1$s Tokenization Request Failed: %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:782 -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:452 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:791 #: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:330 #. translators: This is a message describing that the transaction in question #. only performed a credit card authorization and did not capture any funds. msgid "Authorization only transaction" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1141 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1150 #. translators: Placeholders: %s - failure message. Payment method as in a #. specific credit card, e-check or bank account msgid "Oops, adding your new payment method failed: %s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1193 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1202 #. translators: Payment method as in a specific credit card. Placeholders: %1$s #. - card type (visa, mastercard, ...), %2$s - last four digits of the card, #. %3$s - card expiry date msgid "Nice! New payment method added: %1$s ending in %2$s (expires %3$s)" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1203 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1212 #. translators: Payment method as in a specific e-check account. Placeholders: #. %1$s - account type (checking/savings), %2$s - last four digits of the #. account msgid "Nice! New payment method added: %1$s account ending in %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1210 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1219 #. translators: Payment method as in a specific credit card, e-check or bank #. account msgid "Nice! New payment method added." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1317 +#: payment-gateway/class-sv-wc-payment-gateway-direct.php:1326 #. translators: Placeholders: %1$s - site title, %2$s - customer email. Payment #. method as in a specific credit card, e-check or bank account msgid "%1$s - Add Payment Method for %2$s" @@ -626,26 +787,20 @@ msgstr "" msgid "Order %s is already paid for." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:567 -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:612 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:558 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:603 msgid "%1$s ending in %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:574 -#: payment-gateway/class-sv-wc-payment-gateway-payment-form.php:659 -#. translators: Placeholders: %s - expiry date -msgid "(expires %s)" -msgstr "" - -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:620 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:611 msgid "(check number %s)" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:682 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:673 msgid "Transaction" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:683 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:674 msgid "Approved" msgstr "" @@ -856,137 +1011,129 @@ msgstr "" msgid "Capture Charge" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:412 +#: payment-gateway/class-sv-wc-payment-gateway.php:415 msgid "Check Number is missing" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:413 +#: payment-gateway/class-sv-wc-payment-gateway.php:416 msgid "Drivers license state is missing" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:414 +#: payment-gateway/class-sv-wc-payment-gateway.php:417 msgid "Drivers license number is missing" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:590 +#: payment-gateway/class-sv-wc-payment-gateway.php:593 msgid "Continue" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:590 +#: payment-gateway/class-sv-wc-payment-gateway.php:593 msgid "Place order" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:622 +#: payment-gateway/class-sv-wc-payment-gateway.php:625 msgid "Thank you for your order." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:711 +#: payment-gateway/class-sv-wc-payment-gateway.php:783 msgid "Credit Card" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:713 +#: payment-gateway/class-sv-wc-payment-gateway.php:785 msgid "eCheck" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:731 +#: payment-gateway/class-sv-wc-payment-gateway.php:803 msgid "Pay securely using your credit card." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:733 +#: payment-gateway/class-sv-wc-payment-gateway.php:805 msgid "Pay securely using your checking account." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:752 -msgid "Enable / Disable" -msgstr "" - -#: payment-gateway/class-sv-wc-payment-gateway.php:753 +#: payment-gateway/class-sv-wc-payment-gateway.php:825 msgid "Enable this gateway" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:759 +#: payment-gateway/class-sv-wc-payment-gateway.php:831 msgid "Title" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:761 +#: payment-gateway/class-sv-wc-payment-gateway.php:833 msgid "Payment method title that the customer will see during checkout." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:766 +#: payment-gateway/class-sv-wc-payment-gateway.php:838 msgid "Description" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:768 +#: payment-gateway/class-sv-wc-payment-gateway.php:840 msgid "Payment method description that the customer will see during checkout." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:797 +#: payment-gateway/class-sv-wc-payment-gateway.php:869 msgid "Detailed Decline Messages" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:799 +#: payment-gateway/class-sv-wc-payment-gateway.php:871 msgid "" "Check to enable detailed decline messages to the customer during checkout " "when possible, rather than a generic decline message." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:809 +#: payment-gateway/class-sv-wc-payment-gateway.php:881 #. translators: Placeholders: %1$s - tag, %2$s - tag msgid "" "Show Detailed Error Messages and API requests/responses on the checkout " "page and/or save them to the %1$sdebug log%2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:813 +#: payment-gateway/class-sv-wc-payment-gateway.php:885 msgid "Show on Checkout Page" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:816 +#: payment-gateway/class-sv-wc-payment-gateway.php:888 #. translators: show debugging information on both checkout page and in the log msgid "Both" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:879 +#: payment-gateway/class-sv-wc-payment-gateway.php:951 msgid "Select the gateway environment to use for transactions." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:927 -msgid "Connection Settings" -msgstr "" - -#: payment-gateway/class-sv-wc-payment-gateway.php:933 +#: payment-gateway/class-sv-wc-payment-gateway.php:1005 msgid "Share connection settings" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:935 +#: payment-gateway/class-sv-wc-payment-gateway.php:1007 msgid "Use connection/authentication settings from other gateway" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:938 +#: payment-gateway/class-sv-wc-payment-gateway.php:1010 msgid "Disabled because the other gateway is using these settings" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:955 +#: payment-gateway/class-sv-wc-payment-gateway.php:1027 msgid "Card Verification (CSC)" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:956 +#: payment-gateway/class-sv-wc-payment-gateway.php:1028 msgid "Display the Card Security Code (CV2) field on checkout" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1261 +#: payment-gateway/class-sv-wc-payment-gateway.php:1328 #. translators: Placeholders: %1$s - site title, %2$s - order number msgid "%1$s - Order %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1301 +#: payment-gateway/class-sv-wc-payment-gateway.php:1368 #. translators: Placeholders: %1$s - payment gateway title (such as #. Authorize.net, Braintree, etc), %2$s - transaction amount. Definitions: #. Capture, as in capture funds from a credit card. msgid "%1$s Capture of %2$s Approved" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1329 +#: payment-gateway/class-sv-wc-payment-gateway.php:1396 #. translators: Placeholders: %1$s - payment gateway title (such as #. Authorize.net, Braintree, etc), %2$s - transaction amount, %3$s - #. transaction status message. Definitions: Capture, as in capture funds from a @@ -994,73 +1141,73 @@ msgstr "" msgid "%1$s Capture Failed: %2$s - %3$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1345 +#: payment-gateway/class-sv-wc-payment-gateway.php:1412 #. translators: Placeholders: %1$s - payment gateway title (such as #. Authorize.net, Braintree, etc), %2$s - failure message. Definitions: #. "capture" as in capturing funds from a credit card. msgid "%1$s Capture Failed: %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1384 +#: payment-gateway/class-sv-wc-payment-gateway.php:1451 #. translators: Placeholders: %1$s - site title, %2$s - order number. #. Definitions: Capture as in capture funds from a credit card. msgid "%1$s - Capture for Order %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1548 +#: payment-gateway/class-sv-wc-payment-gateway.php:1615 #. translators: Placeholders: %1$s - site title, %2$s - order number msgid "%1$s - Refund for Order %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1611 +#: payment-gateway/class-sv-wc-payment-gateway.php:1678 #. translators: Placeholders: %1$s - payment gateway title (such as #. Authorize.net, Braintree, etc), %2$s - a monetary amount msgid "%1$s Refund in the amount of %2$s approved." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1638 +#: payment-gateway/class-sv-wc-payment-gateway.php:1705 #. translators: Placeholders: %1$s - payment gateway title (such as #. Authorize.net, Braintree, etc), %2$s - error code, %3$s - error message msgid "%1$s Refund Failed: %2$s - %3$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1646 +#: payment-gateway/class-sv-wc-payment-gateway.php:1713 #. translators: Placeholders: %1$s - payment gateway title (such as #. Authorize.net, Braintree, etc), %2$s - error message msgid "%1$s Refund Failed: %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1666 +#: payment-gateway/class-sv-wc-payment-gateway.php:1733 #. translators: Placeholders: %s - payment gateway title (such as #. Authorize.net, Braintree, etc) msgid "%s Order completely refunded." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1719 +#: payment-gateway/class-sv-wc-payment-gateway.php:1786 msgid "" "Oops, you cannot partially void this order. Please use the full order " "amount." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1803 +#: payment-gateway/class-sv-wc-payment-gateway.php:1870 #. translators: Placeholders: %1$s - payment gateway title, %2$s - error code, #. %3$s - error message. Void as in to void an order. msgid "%1$s Void Failed: %2$s - %3$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1811 +#: payment-gateway/class-sv-wc-payment-gateway.php:1878 #. translators: Placeholders: %1$s - payment gateway title, %2$s - error #. message. Void as in to void an order. msgid "%1$s Void Failed: %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1832 +#: payment-gateway/class-sv-wc-payment-gateway.php:1899 #. translators: Placeholders: %1$s - payment gateway title, %2$s - a monetary #. amount. Void as in to void an order. msgid "%1$s Void in the amount of %2$s approved." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1927 +#: payment-gateway/class-sv-wc-payment-gateway.php:1994 #: payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:144 #. translators: Placeholders: %1$s - status code, %2$s - status message #. translators: Placeholders: %1$s - payment request response status code, %2$s @@ -1068,91 +1215,90 @@ msgstr "" msgid "Status code %1$s: %2$s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1930 +#: payment-gateway/class-sv-wc-payment-gateway.php:1997 #: payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:147 #. translators: Placeholders: %s - status code #. translators: Placeholders: %s - payment request response status code msgid "Status code: %s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1933 +#: payment-gateway/class-sv-wc-payment-gateway.php:2000 #: payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:150 #. translators: Placeholders; %s - status message #. translators: Placeholders: %s - payment request response status message msgid "Status message: %s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1938 +#: payment-gateway/class-sv-wc-payment-gateway.php:2005 #: payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:157 msgid "Transaction ID %s" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2049 +#: payment-gateway/class-sv-wc-payment-gateway.php:2116 #. translators: Placeholders: %1$s - payment gateway title, %2$s - message #. (probably reason for the transaction being held for review) msgid "%1$s Transaction Held for Review (%2$s)" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2080 +#: payment-gateway/class-sv-wc-payment-gateway.php:2147 msgid "" "Your order has been received and is being reviewed. Thank you for your " "business." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2125 +#: payment-gateway/class-sv-wc-payment-gateway.php:2192 #. translators: Placeholders: %1$s - payment gateway title, %2$s - error #. message; e.g. Order Note: [Payment method] Payment failed [error] msgid "%1$s Payment Failed (%2$s)" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2142 -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:382 +#: payment-gateway/class-sv-wc-payment-gateway.php:2209 msgid "An error occurred, please try again or try an alternate form of payment." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2159 +#: payment-gateway/class-sv-wc-payment-gateway.php:2226 #. translators: Placeholders: %1$s - payment gateway title, %2$s - #. message/error msgid "%1$s Transaction Cancelled (%2$s)" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2391 +#: payment-gateway/class-sv-wc-payment-gateway.php:2458 msgid "Transaction Type" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2393 +#: payment-gateway/class-sv-wc-payment-gateway.php:2460 msgid "" "Select how transactions should be processed. Charge submits all " "transactions for settlement, Authorization simply authorizes the order " "total for capture later." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2404 +#: payment-gateway/class-sv-wc-payment-gateway.php:2471 msgid "Charge Virtual-Only Orders" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2406 +#: payment-gateway/class-sv-wc-payment-gateway.php:2473 msgid "" "If the order contains exclusively virtual items, enable this to immediately " "charge, rather than authorize, the transaction." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2576 +#: payment-gateway/class-sv-wc-payment-gateway.php:2643 msgid "Accepted Card Types" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2578 +#: payment-gateway/class-sv-wc-payment-gateway.php:2645 msgid "Select which card types you accept." msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2666 +#: payment-gateway/class-sv-wc-payment-gateway.php:2733 #. translators: #. http:www.cybersource.com/products/payment_security/payment_tokenization/ and #. https:en.wikipedia.org/wiki/Tokenization_(data_security) msgid "Tokenization" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2667 +#: payment-gateway/class-sv-wc-payment-gateway.php:2734 msgid "Allow customers to securely save their payment details for future checkout." msgstr "" @@ -1180,53 +1326,47 @@ msgstr "" msgid "Pre-Order Release Payment Failed: %s" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:219 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:216 msgid "Subscription Renewal: payment token is missing/invalid." msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:245 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:242 msgid "%1$s - Subscription Renewal Order %2$s" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:377 -#. translators: Placeholders: %1$s - payment gateway title, %2$s - error -#. message; e.g. Order Note: [Payment method] Payment Change failed [error] -msgid "%1$s Payment Change Failed (%2$s)" -msgstr "" - -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:508 -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:1028 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:438 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:957 msgid "Via %s ending in %s" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:535 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:465 msgid "Subscriptions" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:605 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:535 msgid "" "This payment method is tied to a subscription and cannot be deleted. Please " "switch the subscription to another method first." msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:615 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:545 msgid "View Subscription" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:669 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:598 msgid "Payment Token" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:697 -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:702 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:626 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:631 msgid "%s is required." msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:857 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:786 msgid "%s0 Subscription Renewal Approved" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:905 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:834 msgid "%s Check Subscription Renewal Payment Approved: %s account ending in %s" msgstr "" @@ -1249,39 +1389,39 @@ msgstr "" msgid "%1$s eCheck Payment Method Saved: %2$s account ending in %3$s" msgstr "" -#: utilities/class-sv-wp-background-job-handler.php:581 +#: utilities/class-sv-wp-background-job-handler.php:571 msgid "Job data key \"%s\" not set" msgstr "" -#: utilities/class-sv-wp-background-job-handler.php:585 +#: utilities/class-sv-wp-background-job-handler.php:575 msgid "Job data key \"%s\" is not an array" msgstr "" -#: utilities/class-sv-wp-background-job-handler.php:798 +#: utilities/class-sv-wp-background-job-handler.php:787 msgid "Every %d Minutes" msgstr "" -#: class-sv-wc-plugin.php:530 +#: class-sv-wc-plugin.php:492 msgctxt "noun" msgid "Support" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:678 -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:684 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:675 msgctxt "noun, software environment" msgid "Test" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:679 -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:587 -#: payment-gateway/class-sv-wc-payment-gateway.php:2397 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:578 +#: payment-gateway/class-sv-wc-payment-gateway.php:2464 msgctxt "credit card transaction type" msgid "Authorization" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-direct.php:679 -#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:589 -#: payment-gateway/class-sv-wc-payment-gateway.php:2396 +#: payment-gateway/class-sv-wc-payment-gateway-hosted.php:580 +#: payment-gateway/class-sv-wc-payment-gateway.php:2463 msgctxt "noun, credit card transaction type" msgid "Charge" msgstr "" @@ -1292,19 +1432,19 @@ msgid "Account" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-helper.php:232 -#: payment-gateway/class-sv-wc-payment-gateway.php:2603 +#: payment-gateway/class-sv-wc-payment-gateway.php:2670 msgctxt "credit card type" msgid "Visa" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-helper.php:236 -#: payment-gateway/class-sv-wc-payment-gateway.php:2604 +#: payment-gateway/class-sv-wc-payment-gateway.php:2671 msgctxt "credit card type" msgid "MasterCard" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-helper.php:240 -#: payment-gateway/class-sv-wc-payment-gateway.php:2605 +#: payment-gateway/class-sv-wc-payment-gateway.php:2672 msgctxt "credit card type" msgid "American Express" msgstr "" @@ -1315,13 +1455,13 @@ msgid "Diners Club" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-helper.php:248 -#: payment-gateway/class-sv-wc-payment-gateway.php:2606 +#: payment-gateway/class-sv-wc-payment-gateway.php:2673 msgctxt "credit card type" msgid "Discover" msgstr "" #: payment-gateway/class-sv-wc-payment-gateway-helper.php:252 -#: payment-gateway/class-sv-wc-payment-gateway.php:2608 +#: payment-gateway/class-sv-wc-payment-gateway.php:2675 msgctxt "credit card type" msgid "JCB" msgstr "" @@ -1341,7 +1481,7 @@ msgctxt "credit card type" msgid "Laser" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:2607 +#: payment-gateway/class-sv-wc-payment-gateway.php:2674 msgctxt "credit card type" msgid "Diners" msgstr "" @@ -1358,12 +1498,12 @@ msgctxt "account type" msgid "Savings" msgstr "" -#: payment-gateway/class-sv-wc-payment-gateway.php:1906 +#: payment-gateway/class-sv-wc-payment-gateway.php:1973 msgctxt "hash before order number" msgid "#" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:565 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:495 msgctxt "hash before order number" msgid "#%s" msgstr "" @@ -1374,12 +1514,12 @@ msgctxt "software environment" msgid "Production" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:895 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:824 msgctxt "woocommerce-plugin-framework" msgid "%s %s Subscription Renewal Payment Approved: %s ending in %s (expires %s)" msgstr "" -#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:928 +#: payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:857 msgctxt "woocommerce-plugin-framework" msgid "%s Renewal Payment Failed (%s)" -msgstr "" \ No newline at end of file +msgstr "" diff --git a/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-request.php b/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-request.php new file mode 100644 index 000000000..e06be97a0 --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-request.php @@ -0,0 +1,109 @@ +gateway = $gateway; + } + + + /** + * Sets the data for merchant validation. + * + * @since 4.7.0-dev + * + * @param string $merchant_id the merchant ID to validate + * @param string $domain_name the verified domain name + * @param string $display_name the merchant display name + */ + public function set_merchant_data( $merchant_id, $domain_name, $display_name ) { + + $data = array( + 'merchantIdentifier' => $merchant_id, + 'domainName' => str_replace( array( 'http://', 'https://' ), '', $domain_name ), + 'displayName' => $display_name, + ); + + /** + * Filters the data for merchant validation. + * + * @since 4.7.0-dev + * + * @param array $data { + * The merchant data. + * + * @var string $merchantIdentifier the merchant ID + * @var string $domainName the verified domain name + * @var string $displayName the merchant display name + * } + * @param \SV_WC_Payment_Gateway_Apple_Pay_API_Request the request object + */ + $this->data = apply_filters( 'sv_wc_apple_pay_api_merchant_data', $data, $this ); + } + + + /** + * Get the string representation of this response with any and all sensitive + * elements masked or removed. + * + * @since 4.7.0-dev + * @see SV_WC_API_Response::to_string_safe() + * + * @return string + */ + public function to_string_safe() { + + // mask the merchant ID + $string = str_replace( $this->data['merchantIdentifier'], str_repeat( '*', strlen( $this->data['merchantIdentifier'] ) ), $this->to_string() ); + + return $string; + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-response.php b/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-response.php new file mode 100644 index 000000000..d56b1ec75 --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-response.php @@ -0,0 +1,108 @@ +statusCode; + } + + + /** + * Gets the status message. + * + * @since 4.7.0-dev + * + * @return string + */ + public function get_status_message() { + + return $this->statusMessage; + } + + + /** + * Gets the validated merchant session. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_merchant_session() { + + return $this->raw_response_json; + } + + + /** + * Get the string representation of this response with any and all sensitive + * elements masked or removed. + * + * No strong indication from the Apple documentation that these _need_ to be + * masked, but they don't provide any useful info and only make the debug + * logs unnecessarily huge. + * + * @since 4.7.0-dev + * @see SV_WC_API_Response::to_string_safe() + * + * @return string + */ + public function to_string_safe() { + + $string = $this->to_string(); + + // mask the merchant session ID + $string = str_replace( $this->merchantSessionIdentifier, str_repeat( '*', 10 ), $string ); + + // mask the merchant ID + $string = str_replace( $this->merchantIdentifier, str_repeat( '*', 10 ), $string ); + + // mask the signature + $string = str_replace( $this->signature, str_repeat( '*', 10 ), $string ); + + return $string; + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api.php b/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api.php new file mode 100644 index 000000000..58e7c15cf --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api.php @@ -0,0 +1,193 @@ +gateway = $gateway; + + $this->request_uri = 'https://apple-pay-gateway-cert.apple.com/paymentservices/startSession'; + + $this->set_request_content_type_header( 'application/json' ); + $this->set_request_accept_header( 'application/json' ); + + $this->set_response_handler( 'SV_WC_Payment_Gateway_Apple_Pay_API_Response' ); + } + + + /** + * Validates the Apple Pay merchant. + * + * @since 4.7.0-dev + * + * @param string $url the validation URL + * @param string $merchant_id the merchant ID to validate + * @param string $domain_name the verified domain name + * @param string $display_name the merchant display name + * @return \SV_WC_Payment_Gateway_Apple_Pay_API_Response the response object + * + * @throws \SV_WC_API_Exception + */ + public function validate_merchant( $url, $merchant_id, $domain_name, $display_name ) { + + $this->request_uri = $url; + + $request = $this->get_new_request(); + + $request->set_merchant_data( $merchant_id, $domain_name, $display_name ); + + return $this->perform_request( $request ); + } + + + /** + * Performs the request and return the parsed response. + * + * @since 4.7.0-dev + * + * @param \SV_WC_API_Request + * @return \SV_WC_API_Response + * + * @throws \SV_WC_API_Exception + */ + protected function perform_request( $request ) { + + // set PEM file cert for requests + add_action( 'http_api_curl', array( $this, 'set_cert_file' ) ); + + return parent::perform_request( $request ); + } + + + /** + * Sets the PEM file required for authentication. + * + * @internal + * + * @since 4.7.0-dev + * + * @param resource $curl_handle + */ + public function set_cert_file( $curl_handle ) { + + if ( ! $curl_handle ) { + return; + } + + curl_setopt( $curl_handle, CURLOPT_SSLCERT, get_option( 'sv_wc_apple_pay_cert_path' ) ); + } + + + /** Validation methods ****************************************************/ + + + /** + * Validates the post-parsed response. + * + * @since 4.7.0-dev + * + * @return bool + * + * @throws \SV_WC_API_Exception + */ + protected function do_post_parse_response_validation() { + + $response = $this->get_response(); + + if ( $response->get_status_code() && 200 !== $response->get_status_code() ) { + throw new SV_WC_API_Exception( $response->get_status_message() ); + } + + return true; + } + + + /** Helper methods ********************************************************/ + + + /** + * Gets a new request object. + * + * @since 4.7.0-dev + * + * @param array $type Optional. The desired request type + * @return \SV_WC_Payment_Gateway_Apple_Pay_API_Request the request object + */ + protected function get_new_request( $type = array() ) { + + return new SV_WC_Payment_Gateway_Apple_Pay_API_Request( $this->get_gateway() ); + } + + + /** + * Gets the gateway instance. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway + */ + protected function get_gateway() { + + return $this->gateway; + } + + + /** + * Gets the plugin instance. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Plugin + */ + protected function get_plugin() { + + return $this->get_gateway()->get_plugin(); + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-payment-response.php b/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-payment-response.php new file mode 100644 index 000000000..55eb8e936 --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-payment-response.php @@ -0,0 +1,203 @@ +token->paymentData ) ? (array) $this->token->paymentData : array(); + } + + + /** + * Gets the authorization transaction ID. + * + * @since 4.7.0-dev + * + * @return string + */ + public function get_transaction_id() { + + return ! empty( $this->token->transactionIdentifier ) ? $this->token->transactionIdentifier : ''; + } + + + /** + * Gets the authorized card type. + * + * @since 4.7.0-dev + * + * @return string + */ + public function get_card_type() { + + $card_type = ! empty( $this->token->paymentMethod->network ) ? $this->token->paymentMethod->network : 'card'; + + return SV_WC_Payment_Gateway_Helper::normalize_card_type( $card_type ); + } + + + /** + * Gets the last four digits of the authorized card. + * + * @since 4.7.0-dev + * + * @return string + */ + public function get_last_four() { + + $last_four = ''; + + if ( ! empty( $this->token->paymentMethod->displayName ) ) { + $last_four = substr( $this->token->paymentMethod->displayName, -4 ); + } + + return $last_four; + } + + + /** + * Gets the billing address. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_billing_address() { + + $address = ! empty( $this->response_data->billingContact ) ? $this->response_data->billingContact : null; + + $billing_address = $this->prepare_address( $address ); + + // set the billing email + if ( ! empty( $this->response_data->shippingContact->emailAddress ) ) { + $billing_address['email'] = $this->shippingContact->emailAddress; + } + + // set the billing phone number + if ( ! empty( $this->response_data->shippingContact->phoneNumber ) ) { + $billing_address['phone'] = $this->shippingContact->phoneNumber; + } + + return $billing_address; + } + + + /** + * Gets the shipping address. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_shipping_address() { + + $address = ! empty( $this->response_data->shippingContact ) ? $this->response_data->shippingContact : null; + + $shipping_address = $this->prepare_address( $address ); + + return $shipping_address; + } + + + /** + * Prepare an address to WC formatting. + * + * @since 4.7.0-dev + * + * @param object $contact the address to prepare + * @return array + */ + protected function prepare_address( $contact ) { + + $address = array( + 'first_name' => isset( $contact->givenName ) ? $contact->givenName : '', + 'last_name' => isset( $contact->familyName ) ? $contact->familyName : '', + 'address_1' => isset( $contact->addressLines[0] ) ? $contact->addressLines[0] : '', + 'address_2' => '', + 'city' => isset( $contact->locality ) ? $contact->locality : '', + 'state' => isset( $contact->administrativeArea ) ? $contact->administrativeArea : '', + 'postcode' => isset( $contact->postalCode ) ? $contact->postalCode : '', + 'country' => isset( $contact->countryCode ) ? $contact->countryCode : '', + ); + + if ( ! empty( $contact->addressLines[1] ) ) { + $address['address_2'] = $contact->addressLines[1]; + } + + $address['country'] = strtoupper( $address['country'] ); + + return $address; + } + + + /** + * Get the string representation of this response with any and all sensitive + * elements masked or removed. + * + * No strong indication from the Apple documentation that these _need_ to be + * masked, but they don't provide any useful info and only make the debug + * logs unnecessarily huge. + * + * @since 4.7.0-dev + * + * @see SV_WC_API_Response::to_string_safe() + * @return string + */ + public function to_string_safe() { + + $string = $this->to_string(); + + if ( ! empty( $this->token->paymentData->data ) ) { + $string = str_replace( $this->token->paymentData->data, str_repeat( '*', 10 ), $string ); + } + + if ( ! empty( $this->token->paymentData->signature ) ) { + $string = str_replace( $this->token->paymentData->signature, str_repeat( '*', 10 ), $string ); + } + + return $string; + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php new file mode 100644 index 000000000..53bd28632 --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php @@ -0,0 +1,407 @@ +handler = $handler; + + // add Apple Pay to the checkout settings sections + add_filter( 'woocommerce_get_sections_checkout', array( $this, 'add_settings_section' ), 99 ); + + // output the settings + add_action( 'woocommerce_settings_checkout', array( $this, 'add_settings' ) ); + + // render the special "static" gateway select + add_action( 'woocommerce_admin_field_static', array( $this, 'render_static_setting' ) ); + + // save the settings + add_action( 'woocommerce_settings_save_checkout', array( $this, 'save_settings' ) ); + + // add admin notices for configuration options that need attention + add_action( 'admin_footer', array( $this, 'add_admin_notices' ), 10 ); + } + + + /** + * Adds Apple Pay to the checkout settings sections. + * + * @internal + * + * @since 4.7.0-dev + * + * @param array $sections the existing sections + * @return array + */ + public function add_settings_section( $sections ) { + + $sections['apple-pay'] = __( 'Apple Pay', 'woocommerce-plugin-framework' ); + + return $sections; + } + + + /** + * Gets all of the combined settings. + * + * @since 4.7.0-dev + * + * @return array $settings The combined settings. + */ + public function get_settings() { + + $settings = array( + + array( + 'title' => __( 'Apple Pay', 'woocommerce-plugin-framework' ), + 'type' => 'title', + ), + + array( + 'id' => 'sv_wc_apple_pay_enabled', + 'title' => __( 'Enable / Disable', 'woocommerce-plugin-framework' ), + 'desc' => __( 'Accept Apple Pay', 'woocommerce-plugin-framework' ), + 'type' => 'checkbox', + 'default' => 'no', + ), + + array( + 'id' => 'sv_wc_apple_pay_display_locations', + 'title' => __( 'Allow Apple Pay on', 'woocommerce-plugin-framework' ), + 'type' => 'multiselect', + 'class' => 'wc-enhanced-select', + 'css' => 'width: 350px;', + 'options' => $this->get_display_location_options(), + 'default' => array_keys( $this->get_display_location_options() ), + ), + + array( + 'id' => 'sv_wc_apple_pay_button_style', + 'title' => __( 'Button Style', 'woocommerce-plugin-framework' ), + 'type' => 'select', + 'options' => array( + 'black' => __( 'Black', 'woocommerce-plugin-framework' ), + 'white' => __( 'White', 'woocommerce-plugin-framework' ), + 'white-with-line' => __( 'White with outline', 'woocommerce-plugin-framework' ), + ), + 'default' => 'black', + ), + + array( + 'type' => 'sectionend', + ), + ); + + $connection_settings = array( + array( + 'title' => __( 'Connection Settings', 'woocommerce-plugin-framework' ), + 'type' => 'title', + ), + + array( + 'id' => 'sv_wc_apple_pay_merchant_id', + 'title' => __( 'Apple Merchant ID', 'woocommerce-plugin-framework' ), + 'type' => 'text', + 'desc' => sprintf( + /** translators: Placeholders: %1$s - tag, %2$s - tag */ + __( 'This is found in your %1$sApple developer account%2$s', 'woocommerce-plugin-framework' ), + '', '' + ), + ), + + array( + 'id' => 'sv_wc_apple_pay_cert_path', + 'title' => __( 'Certificate Path', 'woocommerce-plugin-framework' ), + 'type' => 'text', + 'desc_tip' => 'The full system path to your certificate file from Apple. For security reasons you should store this outside of your web root.', + 'desc' => sprintf( + /* translators: Placeholders: %s - the server's web root path */ + __( 'For reference, your current web root path is: %s', 'woocommerce-plugin-framework' ), + '' . ABSPATH . '' + ), + ), + ); + + $gateway_setting_id = 'sv_wc_apple_pay_payment_gateway'; + $gateway_options = $this->get_gateway_options(); + + if ( 1 === count( $gateway_options ) ) { + + $connection_settings[] = array( + 'id' => $gateway_setting_id, + 'title' => __( 'Processing Gateway', 'woocommerce-plugin-framework' ), + 'type' => 'static', + 'value' => key( $gateway_options ), + 'label' => current( $gateway_options ), + ); + + } else { + + $connection_settings[] = array( + 'id' => $gateway_setting_id, + 'title' => __( 'Processing Gateway', 'woocommerce-plugin-framework' ), + 'type' => 'select', + 'options' => $this->get_gateway_options(), + ); + } + + $connection_settings[] = array( + 'id' => 'sv_wc_apple_pay_test_mode', + 'title' => __( 'Test Mode', 'woocommerce-plugin-framework' ), + 'desc' => __( 'Enable to test Apple Pay functionality throughout your sites without processing real payments.', 'woocommerce-plugin-framework' ), + 'type' => 'checkbox', + 'default' => 'no', + ); + + $connection_settings[] = array( + 'type' => 'sectionend', + ); + + $settings = array_merge( $settings, $connection_settings ); + + /** + * Filter the combined settings. + * + * @since 1.0.0 + * @param array $settings The combined settings. + */ + return apply_filters( 'woocommerce_get_settings_apple_pay', $settings ); + } + + + /** + * Outputs the settings fields. + * + * @internal + * + * @since 4.7.0-dev + * + * @return array + */ + public function add_settings() { + global $current_section; + + if ( 'apple-pay' === $current_section ) { + WC_Admin_Settings::output_fields( $this->get_settings() ); + } + } + + + /** + * Saves the settings. + * + * @internal + * + * @since 4.7.0-dev + * + * @global string $current_section The current settings section. + */ + public function save_settings() { + + global $current_section; + + // Output the general settings + if ( 'apple-pay' == $current_section ) { + + WC_Admin_Settings::save_fields( $this->get_settings() ); + } + } + + + /** + * Renders a static setting. + * + * This "setting" just displays simple text instead of a + + handler->is_enabled() ) { + return; + } + + // if not on the settings screen, bail + if ( ! $this->is_settings_screen() ) { + return; + } + + $errors = array(); + + // HTTPS notice + if ( ! wc_site_is_https() ) { + $errors[] = __( 'Your site must be served over HTTPS with a valid SSL certificate.', 'woocommerce-plugin-framework' ); + } + + // Currency notice + if ( ! in_array( get_woocommerce_currency(), $this->handler->get_accepted_currencies(), true ) ) { + + $accepted_currencies = $this->handler->get_accepted_currencies(); + + $errors[] = sprintf( + /* translators: Placeholders: %1$s - plugin name, %2$s - a currency/comma-separated list of currencies, %3$s - tag, %4$s - tag */ + _n( + 'Accepts payment in %1$s only. %2$sConfigure%3$s WooCommerce to accept %1$s to enable Apple Pay.', + 'Accepts payment in one of %1$s only. %2$sConfigure%3$s WooCommerce to accept one of %1$s to enable Apple Pay.', + count( $accepted_currencies ), + 'woocommerce-plugin-framework' + ), + '' . implode( ', ', $accepted_currencies ) . '', + '', + '' + ); + } + + // bad cert config notice + // this first checks if the option has been set so the notice is not + // displayed without the user having the chance to set it. + if ( false !== $this->handler->get_cert_path() && ! $this->handler->is_cert_configured() ) { + + $errors[] = sprintf( + /** translators: Placeholders: %1$s - tag, %2$s - tag */ + __( 'Your %1$sMerchant Identity Certificate%2$s cannot be found. Please check your path configuration.', 'woocommerce-plugin-framework' ), + '', '' + ); + } + + if ( ! empty( $errors ) ) { + + $message = '' . __( 'Apple Pay is disabled.', 'woocommerce-plugin-framework' ) . ''; + + if ( 1 === count( $errors ) ) { + $message .= ' ' . current( $errors ); + } else { + $message .= ''; + } + + $this->handler->get_plugin()->get_admin_notice_handler()->add_admin_notice( $message, 'apple-pay-https-required', array( + 'notice_class' => 'error', + 'dismissible' => false, + ) ); + } + } + + + /** + * Determines if the user is currently on the settings screen. + * + * @since 4.7.0-dev + * + * @return bool + */ + protected function is_settings_screen() { + + return 'wc-settings' === SV_WC_Helper::get_request( 'page' ) && 'apple-pay' === SV_WC_Helper::get_request( 'section' ); + } + + + /** + * Gets the available display location options. + * + * @since 4.7.0-dev + * + * @return array + */ + protected function get_display_location_options() { + + return array( + 'product' => __( 'Single products', 'woocommerce-plugin-framework' ), + 'cart' => __( 'Cart', 'woocommerce-plugin-framework' ), + 'checkout' => __( 'Checkout', 'woocommerce-plugin-framework' ), + ); + } + + + /** + * Gets the available gateway options. + * + * @since 4.7.0-dev + * + * @return array + */ + protected function get_gateway_options() { + + $gateways = $this->handler->get_supporting_gateways(); + + foreach ( $gateways as $id => $gateway ) { + $gateways[ $id ] = $gateway->get_method_title(); + } + + return $gateways; + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-ajax.php b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-ajax.php new file mode 100644 index 000000000..2f296482d --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-ajax.php @@ -0,0 +1,259 @@ +handler = $handler; + + if ( $this->get_handler()->is_available() ) { + + add_action( 'wp_ajax_sv_wc_apple_pay_get_payment_request', array( $this, 'get_payment_request' ) ); + add_action( 'wp_ajax_nopriv_sv_wc_apple_pay_get_payment_request', array( $this, 'get_payment_request' ) ); + + // validate the merchant + add_action( 'wp_ajax_sv_wc_apple_pay_validate_merchant', array( $this, 'validate_merchant' ) ); + add_action( 'wp_ajax_nopriv_sv_wc_apple_pay_validate_merchant', array( $this, 'validate_merchant' ) ); + + // recalculate the payment request totals + add_action( 'wp_ajax_sv_wc_apple_pay_recalculate_totals', array( $this, 'recalculate_totals' ) ); + add_action( 'wp_ajax_nopriv_sv_wc_apple_pay_recalculate_totals', array( $this, 'recalculate_totals' ) ); + + // process the payment + add_action( 'wp_ajax_sv_wc_apple_pay_process_payment', array( $this, 'process_payment' ) ); + add_action( 'wp_ajax_nopriv_sv_wc_apple_pay_process_payment', array( $this, 'process_payment' ) ); + } + } + + + /** + * Gets a payment request for the specified type. + * + * @internal + * + * @since 4.7.0-dev + */ + public function get_payment_request() { + + $this->get_handler()->log( 'Getting payment request' ); + + try { + + $request = $this->get_handler()->get_cart_payment_request( WC()->cart ); + + $this->get_handler()->log( "Payment Request:\n" . print_r( $request, true ) ); + + wp_send_json_success( json_encode( $request ) ); + + } catch ( SV_WC_Payment_Gateway_Exception $e ) { + + $this->get_handler()->log( 'Could not build payment request. ' . $e->getMessage() ); + + wp_send_json_error( array( + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ) ); + } + } + + + /** + * Validates the merchant. + * + * @internal + * + * @since 4.7.0-dev + */ + public function validate_merchant() { + + $this->get_handler()->log( 'Validating merchant' ); + + check_ajax_referer( 'sv_wc_apple_pay_validate_merchant', 'nonce' ); + + $merchant_id = SV_WC_Helper::get_post( 'merchant_id' ); + $url = SV_WC_Helper::get_post( 'url' ); + + try { + + $response = $this->get_handler()->get_api()->validate_merchant( $url, $merchant_id, home_url(), get_bloginfo( 'name' ) ); + + wp_send_json_success( $response->get_merchant_session() ); + + } catch ( SV_WC_API_Exception $e ) { + + $this->get_handler()->log( 'Could not validate merchant. ' . $e->getMessage() ); + + wp_send_json_error( array( + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ) ); + } + } + + + /** + * Recalculates the totals for the current payment request. + * + * @internal + * + * @since 4.7.0-dev + */ + public function recalculate_totals() { + + $this->get_handler()->log( 'Recalculating totals' ); + + check_ajax_referer( 'sv_wc_apple_pay_recalculate_totals', 'nonce' ); + + try { + + // if a contact is passed, set the customer address data + if ( isset( $_REQUEST['contact'] ) && is_array( $_REQUEST['contact'] ) ) { + + $contact = wp_parse_args( $_REQUEST['contact'], array( + 'administrativeArea' => null, + 'countryCode' => null, + 'locality' => null, + 'postalCode' => null, + ) ); + + $state = $contact['administrativeArea']; + $country = strtoupper( $contact['countryCode'] ); + $city = $contact['locality']; + $postcode = $contact['postalCode']; + + WC()->customer->set_shipping_city( $city ); + WC()->customer->set_shipping_state( $state ); + WC()->customer->set_shipping_country( $country ); + WC()->customer->set_shipping_postcode( $postcode ); + + if ( $country ) { + + if ( SV_WC_Plugin_Compatibility::is_wc_version_gte_3_0() ) { + WC()->customer->set_calculated_shipping( true ); + } else { + WC()->customer->calculated_shipping( true ); + } + } + } + + $chosen_shipping_methods = ( $method = SV_WC_Helper::get_request( 'method' ) ) ? array( wc_clean( $method ) ) : array(); + + WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods ); + + $payment_request = $this->get_handler()->recalculate_totals(); + + $data = array( + 'shipping_methods' => $payment_request['shippingMethods'], + 'line_items' => array_values( $payment_request['lineItems'] ), + 'total' => $payment_request['total'], + ); + + $this->get_handler()->log( "New totals:\n" . print_r( $data, true ) ); + + wp_send_json_success( $data ); + + } catch ( SV_WC_Payment_Gateway_Exception $e ) { + + $this->get_handler()->log( $e->getMessage() ); + + wp_send_json_error( array( + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ) ); + } + } + + + /** + * Processes the payment after the Apple Pay authorization. + * + * @internal + * + * @since 4.7.0-dev + */ + public function process_payment() { + + $this->get_handler()->log( 'Processing payment' ); + + $type = SV_WC_Helper::get_post( 'type' ); + $response = stripslashes( SV_WC_Helper::get_post( 'payment' ) ); + + $this->get_handler()->store_payment_response( $response ); + + try { + + $result = $this->get_handler()->process_payment( $type, $response ); + + wp_send_json_success( $result ); + + } catch ( SV_WC_Payment_Gateway_Exception $e ) { + + $this->get_handler()->log( 'Payment failed. ' . $e->getMessage() ); + + wp_send_json_error( array( + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ) ); + } + } + + + /** + * Gets the Apple Pay handler instance. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Apple_Pay + */ + protected function get_handler() { + + return $this->handler; + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php new file mode 100644 index 000000000..1d36cf40a --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php @@ -0,0 +1,355 @@ +plugin = $plugin; + + $this->handler = $handler; + + $this->gateway = $this->get_handler()->get_processing_gateway(); + + if ( $this->get_handler()->is_available() ) { + + add_action( 'wp', array( $this, 'init' ) ); + + add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); + } + } + + + /** + * Initializes the scripts and hooks. + * + * @since 4.7.0-dev + */ + public function init() { + + $locations = $this->get_display_locations(); + + if ( is_product() && in_array( 'product', $locations, true ) ) { + $this->init_product(); + } else if ( is_cart() && in_array( 'cart', $locations, true ) ) { + $this->init_cart(); + } else if ( is_checkout() && in_array( 'checkout', $locations, true ) ) { + $this->init_checkout(); + } + } + + + /** + * Gets the configured display locations. + * + * @since 4.7.0-dev + * + * @return array + */ + protected function get_display_locations() { + + return get_option( 'sv_wc_apple_pay_display_locations', array() ); + } + + + /** + * Enqueues the scripts. + * + * @since 4.7.0-dev + */ + public function enqueue_scripts() { + + wp_enqueue_style( 'sv-wc-apple-pay', $this->get_plugin()->get_payment_gateway_framework_assets_url() . '/css/frontend/sv-wc-payment-gateway-apple-pay.css', array(), $this->get_plugin()->get_version() ); // TODO: min + + wp_enqueue_script( 'sv-wc-apple-pay', $this->get_plugin()->get_payment_gateway_framework_assets_url() . '/js/frontend/sv-wc-payment-gateway-apple-pay.min.js', array( 'jquery' ), $this->get_plugin()->get_version(), true ); + + /** + * Filters the Apple Pay JS handler params. + * + * @since 4.7.0-dev + * @param array $params the JS params + */ + $params = apply_filters( 'sv_wc_apple_pay_js_handler_params', array( + 'gateway_id' => $this->get_gateway()->get_id(), + 'gateway_id_dasherized' => $this->get_gateway()->get_id_dasherized(), + 'merchant_id' => $this->get_handler()->get_merchant_id(), + 'ajax_url' => admin_url( 'admin-ajax.php' ), + 'validate_nonce' => wp_create_nonce( 'sv_wc_apple_pay_validate_merchant' ), + 'recalculate_totals_nonce' => wp_create_nonce( 'sv_wc_apple_pay_recalculate_totals' ), + 'process_nonce' => wp_create_nonce( 'sv_wc_apple_pay_process_payment' ), + 'generic_error' => __( 'An error occurred, please try again or try an alternate form of payment', 'woocommerce-plugin-framework' ), + ) ); + + wp_localize_script( 'sv-wc-apple-pay', 'sv_wc_apple_pay_params', $params ); + } + + + /** + * Renders an Apple Pay button. + * + * @since 4.7.0-dev + */ + public function render_button() { + + $button_text = ''; + $classes = array( + 'sv-wc-apple-pay-button', + ); + + switch ( $this->get_handler()->get_button_style() ) { + + case 'black': + $classes[] = 'apple-pay-button-black'; + break; + + case 'white': + $classes[] = 'apple-pay-button-white'; + break; + + case 'white-with-line': + $classes[] = 'apple-pay-button-white-with-line'; + break; + } + + // if on the single product page, add some text + if ( is_product() ) { + $classes[] = 'apple-pay-button-buy-now'; + $button_text = __( 'Buy with', 'woocommerce-plugin-framework' ); + } + + if ( $button_text ) { + $classes[] = 'apple-pay-button-with-text'; + } + + echo ''; + } + + + /** + * Initializes Apple Pay on the single product page. + * + * @since 4.7.0-dev + */ + public function init_product() { + + $args = array(); + + try { + + $product = wc_get_product( get_the_ID() ); + + if ( ! $product ) { + throw new SV_WC_Payment_Gateway_Exception( 'Product does not exist.' ); + } + + $payment_request = $this->get_handler()->get_product_payment_request( $product ); + + $args['payment_request'] = $payment_request; + + } catch ( SV_WC_Payment_Gateway_Exception $e ) { + + $this->get_handler()->log( 'Could not initialize Apple Pay. ' . $e->getMessage() ); + } + + /** + * Filters the Apple Pay product handler args. + * + * @since 4.7.0-dev + * @param array $args + */ + $args = apply_filters( 'sv_wc_apple_pay_product_handler_args', $args ); + + wc_enqueue_js( sprintf( 'window.sv_wc_apple_pay_handler = new SV_WC_Apple_Pay_Product_Handler(%s);', json_encode( $args ) ) ); + + add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'render_button' ) ); + } + + + /** Cart functionality ****************************************************/ + + + /** + * Initializes Apple Pay on the cart page. + * + * @since 4.7.0-dev + */ + public function init_cart() { + + $args = array(); + + try { + + $payment_request = $this->get_handler()->get_cart_payment_request( WC()->cart ); + + $args['payment_request'] = $payment_request; + + } catch ( SV_WC_Payment_Gateway_Exception $e ) { + + $args['payment_request'] = false; + } + + /** + * Filters the Apple Pay cart handler args. + * + * @since 4.7.0-dev + * @param array $args + */ + $args = apply_filters( 'sv_wc_apple_pay_cart_handler_args', $args ); + + wc_enqueue_js( sprintf( 'window.sv_wc_apple_pay_handler = new SV_WC_Apple_Pay_Cart_Handler(%s);', json_encode( $args ) ) ); + + add_action( 'woocommerce_proceed_to_checkout', array( $this, 'render_button' ) ); + } + + + /** Checkout functionality ************************************************/ + + + /** + * Initializes Apple Pay on the checkout page. + * + * @since 4.7.0-dev + */ + public function init_checkout() { + + /** + * Filters the Apple Pay checkout handler args. + * + * @since 4.7.0-dev + * @param array $args + */ + $args = apply_filters( 'sv_wc_apple_pay_checkout_handler_args', array() ); + + wc_enqueue_js( sprintf( 'window.sv_wc_apple_pay_handler = new SV_WC_Apple_Pay_Checkout_Handler(%s);', json_encode( $args ) ) ); + + if ( $this->get_plugin()->is_plugin_active( 'woocommerce-checkout-add-ons.php' ) ) { + add_action( 'woocommerce_review_order_before_payment', array( $this, 'render_button' ) ); + } else { + add_action( 'woocommerce_before_checkout_form', array( $this, 'render_checkout_button' ), 15 ); + } + } + + + /** + * Renders the Apple Pay button for checkout. + * + * @since 4.7.0-dev + */ + public function render_checkout_button() { + + ?> + +
+ + render_button(); ?> + + + + + +
+ + gateway; + } + + + /** + * Gets the gateway plugin instance. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Plugin + */ + protected function get_plugin() { + + return $this->plugin; + } + + /** + * Gets the Apple Pay handler instance. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Apple_Pay + */ + protected function get_handler() { + + return $this->handler; + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php new file mode 100644 index 000000000..98c8c740f --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php @@ -0,0 +1,189 @@ +calculate_totals(); + + try { + + wc_transaction_query( 'start' ); + + $order_data = array( + 'status' => apply_filters( 'woocommerce_default_order_status', 'pending' ), + 'customer_id' => get_current_user_id(), + 'cart_hash' => md5( json_encode( wc_clean( $cart->get_cart_for_session() ) ) . $cart->total ), + 'created_via' => 'apple_pay', + ); + + $order = self::get_order_object( $order_data ); + + foreach ( $cart->get_cart() as $cart_item_key => $item ) { + + $args = array( + 'variation' => $item['variation'], + 'totals' => array( + 'subtotal' => $item['line_subtotal'], + 'subtotal_tax' => $item['line_subtotal_tax'], + 'total' => $item['line_total'], + 'tax' => $item['line_tax'], + 'tax_data' => $item['line_tax_data'] + ), + ); + + if ( ! $order->add_product( $item['data'], $item['quantity'], $args ) ) { + throw new SV_WC_Payment_Gateway_Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-plugin-framework' ), 525 ) ); + } + } + + foreach ( $cart->get_coupons() as $code => $coupon ) { + + if ( ! SV_WC_Order_Compatibility::add_coupon( $order, $code, $cart->get_coupon_discount_amount( $code ), $cart->get_coupon_discount_tax_amount( $code ) ) ) { + throw new SV_WC_Payment_Gateway_Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-plugin-framework' ), 529 ) ); + } + } + + $chosen_methods = WC()->session->get( 'chosen_shipping_methods', array() ); + + foreach ( WC()->shipping->get_packages() as $key => $package ) { + + if ( isset( $package['rates'][ $chosen_methods[ $key ] ] ) ) { + + $method = $package['rates'][ $chosen_methods[ $key ] ]; + + if ( ! SV_WC_Order_Compatibility::add_shipping( $order, $method ) ) { + throw new SV_WC_Payment_Gateway_Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-plugin-framework' ), 527 ) ); + } + } + } + + // add fees + foreach ( $cart->get_fees() as $key => $fee ) { + + if ( ! SV_WC_Order_Compatibility::add_fee( $order, $fee ) ) { + throw new SV_WC_Payment_Gateway_Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-plugin-framework' ), 526 ) ); + } + } + + foreach ( array_keys( $cart->taxes + $cart->shipping_taxes ) as $rate_id ) { + + if ( $rate_id && apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) !== $rate_id ) { + + if ( ! SV_WC_Order_Compatibility::add_tax( $order, $rate_id, $cart->get_tax_amount( $rate_id ), $cart->get_shipping_tax_amount( $rate_id ) ) ) { + throw new SV_WC_Payment_Gateway_Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-plugin-framework' ), 526 ) ); + } + } + } + + wc_transaction_query( 'commit' ); + + $order->update_taxes(); + + $order->calculate_totals( false ); // false to skip recalculating taxes + + do_action( 'woocommerce_checkout_update_order_meta', SV_WC_Order_Compatibility::get_prop( $order, 'id' ), array() ); + + return $order; + + } catch ( SV_WC_Payment_Gateway_Exception $e ) { + + wc_transaction_query( 'rollback' ); + + throw $e; + } + } + + + /** + * Gets an order object for payment. + * + * @since 4.7.0-dev + * + * @param array $order_data the order data + * @return \WC_Order + * + * @throws \SV_WC_Payment_Gateway_Exception + */ + public static function get_order_object( $order_data ) { + + $order_id = (int) WC()->session->get( 'order_awaiting_payment', 0 ); + + if ( $order_id && $order_data['cart_hash'] === get_post_meta( $order_id, '_cart_hash', true ) && ( $order = wc_get_order( $order_id ) ) && $order->has_status( array( 'pending', 'failed' ) ) ) { + + $order_data['order_id'] = $order_id; + + $order = wc_update_order( $order_data ); + + if ( is_wp_error( $order ) ) { + throw new SV_WC_Payment_Gateway_Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-plugin-framework' ), 522 ) ); + } else { + $order->remove_order_items(); + } + + } else { + + $order = wc_create_order( $order_data ); + + if ( is_wp_error( $order ) ) { + throw new SV_WC_Payment_Gateway_Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-plugin-framework' ), 520 ) ); + } elseif ( false === $order ) { + throw new SV_WC_Payment_Gateway_Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-plugin-framework' ), 521 ) ); + } + + // set the new order ID so it can be resumed in case of failure + WC()->session->set( 'order_awaiting_payment', SV_WC_Order_Compatibility::get_prop( $order, 'id' ) ); + } + + return $order; + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php new file mode 100644 index 000000000..1e460ba27 --- /dev/null +++ b/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php @@ -0,0 +1,1041 @@ +plugin = $plugin; + + $this->init(); + + if ( $this->is_available() ) { + add_filter( 'woocommerce_customer_taxable_address', array( $this, 'set_customer_taxable_address' ) ); + } + } + + + /** + * Initializes the Apple Pay handlers. + * + * @since 4.7.0-dev + */ + protected function init() { + + if ( is_admin() && ! is_ajax() ) { + $this->admin = new SV_WC_Payment_Gateway_Apple_Pay_Admin( $this ); + } else { + $this->ajax = new SV_WC_Payment_Gateway_Apple_Pay_AJAX( $this ); + $this->frontend = new SV_WC_Payment_Gateway_Apple_Pay_Frontend( $this->get_plugin(), $this ); + } + } + + + /** + * Processes the payment after an Apple Pay authorization. + * + * This method creates a new order and calls the gateway for processing. + * + * @since 4.7.0-dev + * + * @return array + * @throws \SV_WC_Payment_Gateway_Exception + */ + public function process_payment() { + + $order = null; + + try { + + $payment_response = $this->get_stored_payment_response(); + + if ( ! $payment_response ) { + throw new SV_WC_Payment_Gateway_Exception( 'Invalid payment response data' ); + } + + $this->log( "Payment Response:\n" . $payment_response->to_string_safe() . "\n" ); + + $order = SV_WC_Payment_Gateway_Apple_Pay_Orders::create_order( WC()->cart ); + + $order->set_payment_method( $this->get_processing_gateway() ); + + // if we got to this point, the payment was authorized by Apple Pay + // from here on out, it's up to the gateway to not screw things up. + $order->add_order_note( __( 'Apple Pay payment authorized.', 'woocommerce-plugin-framework' ) ); + + $order->set_address( $payment_response->get_billing_address(), 'billing' ); + $order->set_address( $payment_response->get_shipping_address(), 'shipping' ); + + if ( SV_WC_Plugin_Compatibility::is_wc_version_gte_3_0() ) { + $order->save(); + } + + // add Apple Pay response data to the order + add_filter( 'wc_payment_gateway_' . $this->get_processing_gateway()->get_id() . '_get_order', array( $this, 'add_order_data' ) ); + + if ( $this->is_test_mode() ) { + $result = $this->process_test_payment( $order ); + } else { + $result = $this->get_processing_gateway()->process_payment( SV_WC_Order_Compatibility::get_prop( $order, 'id' ) ); + } + + if ( isset( $result['result'] ) && 'success' !== $result['result'] ) { + throw new SV_WC_Payment_Gateway_Exception( 'Gateway processing error.' ); + } + + if ( $user_id = $order->get_user_id() ) { + $this->update_customer_addresses( $user_id, $payment_response ); + } + + $this->clear_payment_data(); + + return $result; + + } catch ( SV_WC_Payment_Gateway_Exception $e ) { + + if ( $order ) { + + $order->add_order_note( sprintf( + /** translators: Placeholders: %s - the error message */ + __( 'Apple Pay payment failed. %s', 'woocommerce-plugin-framework' ), + $e->getMessage() + ) ); + } + + throw $e; + } + } + + + /** + * Updates a customer's stored billing & shipping addresses based on the + * Apple Pay payment response. + * + * @since 4.7.0-dev + * + * @param int $user_id WordPress user ID + * @param \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response $payment_response payment response object + */ + protected function update_customer_addresses( $user_id, SV_WC_Payment_Gateway_Apple_Pay_Payment_Response $payment_response ) { + + foreach ( $payment_response->get_billing_address() as $key => $value ) { + update_user_meta( $user_id, 'billing_' . $key, $value ); + } + + $shipping_address = $payment_response->get_shipping_address(); + + if ( ! empty( $shipping_address['address_1'] ) ) { + + foreach ( $payment_response->get_shipping_address() as $key => $value ) { + update_user_meta( $user_id, 'shipping_' . $key, $value ); + } + } + } + + + /** + * Simulates a successful gateway payment response. + * + * This provides an easy way for merchants to test that their certificates + * and other settings are correctly configured and communicating with Apple + * without processing actual payments to test. + * + * @since 4.7.0-dev + * + * @param \WC_Order $order order object + * @return array + */ + protected function process_test_payment( WC_Order $order ) { + + $order->payment_complete(); + + WC()->cart->empty_cart(); + + return array( + 'result' => 'success', + 'redirect' => $this->get_processing_gateway()->get_return_url( $order ), + ); + } + + + /** + * Gets a single product payment request. + * + * @since 4.7.0-dev + * @see \SV_WC_Payment_Gateway_Apple_Pay::build_payment_request() + * + * @param \WC_Product $product product object + * @param bool $in_cart whether to generate a cart for this request + * @return array + * + * @throws \SV_WC_Payment_Gateway_Exception + */ + public function get_product_payment_request( WC_Product $product, $in_cart = false ) { + + if ( ! is_user_logged_in() ) { + WC()->session->set_customer_session_cookie( true ); + } + + // no subscription products + if ( $this->get_plugin()->is_subscriptions_active() && WC_Subscriptions_Product::is_subscription( $product ) ) { + throw new SV_WC_Payment_Gateway_Exception( 'Not available for subscription products.' ); + } + + // no pre-order "charge upon release" products + if ( $this->get_plugin()->is_pre_orders_active() && WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) { + throw new SV_WC_Payment_Gateway_Exception( 'Not available for pre-order products that are set to charge upon release.' ); + } + + // only simple products + if ( ! $product->is_type( 'simple' ) ) { + throw new SV_WC_Payment_Gateway_Exception( 'Buy Now is only available for simple products' ); + } + + // if this product can't be purchased, bail + if ( ! $product->is_purchasable() || ! $product->is_in_stock() || ! $product->has_enough_stock( 1 ) ) { + throw new SV_WC_Payment_Gateway_Exception( 'Product is not available for purchase.' ); + } + + if ( $in_cart ) { + + WC()->cart->empty_cart(); + + WC()->cart->add_to_cart( $product->get_id() ); + + $request = $this->get_cart_payment_request( WC()->cart ); + + } else { + + $request = $this->build_payment_request( $product->get_price(), array( 'needs_shipping' => $product->needs_shipping() ) ); + + $stored_request = $this->get_stored_payment_request(); + + $stored_request['product_id'] = $product->get_id(); + + $this->store_payment_request( $stored_request ); + } + + /** + * Filters the Apple Pay Buy Now JS payment request. + * + * @since 4.7.0-dev + * @param array $request request data + * @param \WC_Product $product product object + */ + return apply_filters( 'sv_wc_apple_pay_buy_now_payment_request', $request, $product ); + } + + + /** + * Gets a payment request based on WooCommerce cart data. + * + * @since 4.7.0-dev + * @see \SV_WC_Payment_Gateway_Apple_Pay::build_payment_request() + * + * @param \WC_Cart $cart cart object + * @return array + * + * @throws \SV_WC_Payment_Gateway_Exception + */ + public function get_cart_payment_request( WC_Cart $cart ) { + + if ( $this->get_plugin()->is_subscriptions_active() && WC_Subscriptions_Cart::cart_contains_subscription() ) { + throw new SV_WC_Payment_Gateway_Exception( 'Cart contains subscriptions.' ); + } + + if ( $this->get_plugin()->is_pre_orders_active() && WC_Pre_Orders_Cart::cart_contains_pre_order() ) { + throw new SV_WC_Payment_Gateway_Exception( 'Cart contains pre-orders.' ); + } + + // ensure totals are fully calculated by simulating checkout + if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) { + define( 'WOOCOMMERCE_CHECKOUT', true ); + } + + $cart->calculate_totals(); + + if ( count( WC()->shipping->get_packages() ) > 1 ) { + throw new SV_WC_Payment_Gateway_Exception( 'Apple Pay cannot be used for multiple shipments.' ); + } + + $args = array( + 'line_totals' => $this->get_cart_totals( $cart ), + 'needs_shipping' => $cart->needs_shipping(), + ); + + // build it! + $request = $this->build_payment_request( $cart->total, $args ); + + /** + * Filters the Apple Pay cart JS payment request. + * + * @since 4.7.0-dev + * @param array $args the cart JS payment request + * @param \WC_Cart $cart the cart object + */ + return apply_filters( 'sv_wc_apple_pay_cart_payment_request', $request, $cart ); + } + + + /** + * Recalculates the lines and totals for the current payment request. + * + * @since 4.7.0-dev + * + * @return array + * + * @throws \SV_WC_Payment_Gateway_Exception + */ + public function recalculate_totals() { + + $payment_request = $this->get_stored_payment_request(); + + if ( empty( $payment_request ) ){ + throw new SV_WC_Payment_Gateway_Exception( 'Payment request data is missing.' ); + } + + // if this is a single product request, make sure the cart gets populated + if ( ! empty( $payment_request['product_id'] ) && $product = wc_get_product( $payment_request['product_id'] ) ) { + $payment_request = $this->get_product_payment_request( $product, true ); + } + + if ( ! WC()->cart ) { + throw new SV_WC_Payment_Gateway_Exception( 'Cart data is missing.' ); + } + + $totals = $this->get_cart_totals( WC()->cart ); + + $payment_request['lineItems'] = $this->build_payment_request_lines( $totals ); + $payment_request['shippingMethods'] = array(); + + $packages = WC()->shipping->get_packages(); + + if ( ! empty( $packages ) ) { + + foreach ( $packages[0]['rates'] as $method ) { + + /** + * Filters a shipping method's description for the Apple Pay payment card. + * + * @since 4.7.0-dev + * + * @param string $detail shipping method detail, such as delivery estimation + * @param object $method shipping method object + */ + $method_detail = apply_filters( 'wc_payment_gateway_apple_pay_shipping_method_detail', '', $method ); + + $payment_request['shippingMethods'][] = array( + 'label' => $method->get_label(), + 'detail' => $method_detail, + 'amount' => $this->format_price( $method->cost ), + 'identifier' => $method->id, + ); + } + } + + // reset the order total based on the new line items + $payment_request['total']['amount'] = $this->format_price( array_sum( wp_list_pluck( $payment_request['lineItems'], 'amount' ) ) ); + + // update the stored payment request session with the new line items & totals + $this->store_payment_request( $payment_request ); + + return $payment_request; + } + + + /** + * Gets the line totals for a cart. + * + * @since 4.7.0-dev + * @see \SV_WC_Payment_Gateway_Apple_Pay::build_payment_request_lines() + * + * @param \WC_Cart $cart cart object + * @return array + */ + protected function get_cart_totals( WC_Cart $cart ) { + + // ensure totals are fully calculated by simulating checkout + if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) { + define( 'WOOCOMMERCE_CHECKOUT', true ); + } + + $cart->calculate_totals(); + + return array( + 'subtotal' => $cart->subtotal_ex_tax, + 'discount' => $cart->get_cart_discount_total(), + 'shipping' => $cart->shipping_total, + 'fees' => $cart->fee_total, + 'taxes' => $cart->tax_total + $cart->shipping_tax_total, + ); + } + + + /** + * Builds a payment request for the Apple Pay JS. + * + * This contains all of the data necessary to complete a payment. + * + * @since 4.7.0-dev + * + * @param float|int $amount amount to be charged by Apple Pay + * @param array $args { + * Optional. The payment request args. + * + * @type string $currency_code Payment currency code. Defaults to the shop currency. + * @type string $country_code Payment country code. Defaults to the shop base country. + * @type string $merchant_name Merchant name. Defaults to the shop name. + * @type array $merchant_capabilities merchant capabilities + * @type array $supported_networks supported networks or card types + * @type bool $needs_shipping whether the payment needs shipping + * @type array $line_totals request line totals. @see \SV_WC_Payment_Gateway_Apple_Pay::build_payment_request_lines() + * } + * + * @return array + */ + public function build_payment_request( $amount, $args = array() ) { + + $args = wp_parse_args( $args, array( + 'currency_code' => get_woocommerce_currency(), + 'country_code' => get_option( 'woocommerce_default_country' ), + 'merchant_name' => get_bloginfo( 'name', 'display' ), + 'merchant_capabilities' => $this->get_capabilities(), + 'supported_networks' => $this->get_supported_networks(), + 'line_totals' => array(), + 'needs_shipping' => false, + ) ); + + // set the base required defaults + $request = array( + 'currencyCode' => $args['currency_code'], + 'countryCode' => substr( $args['country_code'], 0, 2 ), + 'merchantCapabilities' => $args['merchant_capabilities'], + 'supportedNetworks' => $args['supported_networks'], + 'requiredBillingContactFields' => array( 'postalAddress' ), + 'requiredShippingContactFields' => array( + 'phone', + 'email', + 'name', + ), + ); + + if ( $args['needs_shipping'] ) { + $request['requiredShippingContactFields'][] = 'postalAddress'; + } + + if ( is_array( $args['line_totals'] ) && ! empty( $args['line_totals'] ) ) { + $request['lineItems'] = $this->build_payment_request_lines( $args['line_totals'] ); + } + + // order total + $request['total'] = array( + 'type' => 'final', + 'label' => $args['merchant_name'], + 'amount' => $this->format_price( $amount ), + ); + + $this->store_payment_request( $request ); + + // remove line item keys that are only useful for us later + if ( ! empty( $request['lineItems'] ) ) { + $request['lineItems'] = array_values( $request['lineItems'] ); + } + + return $request; + } + + + /** + * Builds payment request lines for the Apple Pay JS. + * + * Apple guidelines prefer that the "lines" displayed on the Apple Pay card + * should be overall order totals, instead of listing actual product lines. + * This method standardizes the main breakdowns which are: + * + Subtotal + * + Discounts (represented as a single negative amount) + * + Shipping + * + Fees + * + Taxes + * + * @since 4.7.0-dev + * + * @param array $totals { + * Payment line totals. + * + * @type float $subtotal items subtotal + * @type float $discount discounts total + * @type float $shipping shipping total + * @type float $fees fees total + * @type float $taxes tax total + * } + */ + public function build_payment_request_lines( $totals ) { + + $totals = wp_parse_args( $totals, array( + 'subtotal' => 0.00, + 'discount' => 0.00, + 'shipping' => 0.00, + 'fees' => 0.00, + 'taxes' => 0.00, + ) ); + + $lines = array(); + + // subtotal + if ( $totals['subtotal'] > 0 ) { + + $lines['subtotal'] = array( + 'type' => 'final', + 'label' => __( 'Subtotal', 'woocommerce-plugin-framework' ), + 'amount' => $this->format_price( $totals['subtotal'] ), + ); + } + + // discounts + if ( $totals['discount'] > 0 ) { + + $lines['discount'] = array( + 'type' => 'final', + 'label' => __( 'Discount', 'woocommerce-plugin-framework' ), + 'amount' => abs( $this->format_price( $totals['discount'] ) ) * -1, + ); + } + + // shipping + if ( $totals['shipping'] > 0 ) { + + $lines['shipping'] = array( + 'type' => 'final', + 'label' => __( 'Shipping', 'woocommerce-plugin-framework' ), + 'amount' => $this->format_price( $totals['shipping'] ), + ); + } + + // fees + if ( $totals['fees'] > 0 ) { + + $lines['fees'] = array( + 'type' => 'final', + 'label' => __( 'Fees', 'woocommerce-plugin-framework' ), + 'amount' => $this->format_price( $totals['fees'] ), + ); + } + + // taxes + if ( $totals['taxes'] > 0 ) { + + $lines['taxes'] = array( + 'type' => 'final', + 'label' => __( 'Taxes', 'woocommerce-plugin-framework' ), + 'amount' => $this->format_price( $totals['taxes'] ), + ); + } + + return $lines; + } + + + /** + * Formats a total price for use with Apple Pay JS. + * + * @since 4.7.0-dev + * + * @param string|float $price the price to format + * @return string + */ + protected function format_price( $price ) { + + return wc_format_decimal( $price, 2 ); + } + + + /** + * Gets the stored payment request data. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_stored_payment_request() { + + return WC()->session->get( 'apple_pay_payment_request', array() ); + } + + + /** + * Gets the stored payment response data. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response|false + */ + public function get_stored_payment_response() { + + $response_data = WC()->session->get( 'apple_pay_payment_response', array() ); + + if ( ! empty( $response_data ) ) { + return new SV_WC_Payment_Gateway_Apple_Pay_Payment_Response( $response_data ); + } else { + return false; + } + } + + + /** + * Stores payment request data for later use. + * + * @since 4.7.0-dev + */ + public function store_payment_request( $data ) { + + WC()->session->set( 'apple_pay_payment_request', $data ); + } + + + /** + * Stores payment response data for later use. + * + * @since 4.7.0-dev + */ + public function store_payment_response( $data ) { + + WC()->session->set( 'apple_pay_payment_response', $data ); + } + + + /** + * Clears all payment request & response data from the session. + * + * @since 4.7.0-dev + */ + public function clear_payment_data() { + + unset( WC()->session->apple_pay_payment_request ); + unset( WC()->session->apple_pay_payment_response ); + unset( WC()->session->order_awaiting_payment ); + } + + + /** + * Filters and sets the customer's taxable address. + * + * This is necessary because Apple Pay doesn't ever provide a billing + * address until after payment is complete. If the shop is set to calculate + * tax based on the billing address, we need to use the shipping address + * to at least get some rates for new customers. + * + * @internal + * + * @since 4.7.0-dev + * + * @param array $address taxable address + * @return array + */ + public function set_customer_taxable_address( $address ) { + + $billing_country = SV_WC_Plugin_Compatibility::is_wc_version_gte_3_0() ? WC()->customer->get_billing_country() : WC()->customer->get_country(); + + // set to the shipping address provided by Apple Pay if: + // 1. shipping is available + // 2. billing is not available + // 3. taxes aren't configured to use the shop base + if ( WC()->customer->get_shipping_country() && ! $billing_country && $address[0] !== WC()->countries->get_base_country() ) { + + $address = array( + WC()->customer->get_shipping_country(), + WC()->customer->get_shipping_state(), + WC()->customer->get_shipping_postcode(), + WC()->customer->get_shipping_city(), + ); + } + + return $address; + } + + + /** + * Allows the processing gateway to add Apple Pay details to the payment data. + * + * @internal + * + * @since 4.7.0-dev + * + * @param \WC_Order $order the order object + * @return \WC_Order + */ + public function add_order_data( $order ) { + + if ( $response = $this->get_stored_payment_response() ) { + $order = $this->get_processing_gateway()->get_order_for_apple_pay( $order, $response ); + } + + return $order; + } + + + /** + * Gets the Apple Pay API. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Apple_Pay_API + */ + public function get_api() { + + if ( ! $this->api instanceof SV_WC_Payment_Gateway_Apple_Pay_API ) { + + require_once( $this->get_plugin()->get_payment_gateway_framework_path() . '/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api.php'); + require_once( $this->get_plugin()->get_payment_gateway_framework_path() . '/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-request.php'); + require_once( $this->get_plugin()->get_payment_gateway_framework_path() . '/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-response.php'); + + $this->api = new SV_WC_Payment_Gateway_Apple_Pay_API( $this->get_processing_gateway() ); + } + + return $this->api; + } + + + /** + * Adds a log entry to the gateway's debug log. + * + * @since 4.7.0-dev + * + * @param string $message the log message to add + */ + public function log( $message ) { + + $gateway = $this->get_processing_gateway(); + + if ( ! $gateway ) { + return; + } + + if ( $gateway->debug_log() ) { + $gateway->get_plugin()->log( '[Apple Pay] ' . $message, $gateway->get_id() ); + } + } + + + /** + * Determines if Apple Pay is available. + * + * This does not indicate browser support or a user's ability, but rather + * that Apple Pay is properly configured and ready to be initiated by the + * Apple Pay JS. + * + * @since 4.7.0-dev + * + * @return bool + */ + public function is_available() { + + $is_available = wc_site_is_https() && $this->is_configured(); + + $is_available = $is_available && in_array( get_woocommerce_currency(), $this->get_accepted_currencies(), true ); + + /** + * Filters whether Apple Pay should be made available to users. + * + * @since 4.7.0-dev + * @param bool $is_available + */ + return apply_filters( 'sv_wc_apple_pay_is_available', $is_available ); + } + + + /** + * Determines if Apple Pay settings are properly configured. + * + * @since 4.7.0-dev + * + * @return bool + */ + public function is_configured() { + + if ( ! $this->get_processing_gateway() ) { + return false; + } + + $is_configured = $this->is_enabled() && $this->get_merchant_id() && $this->get_processing_gateway()->is_enabled(); + + $is_configured = $is_configured && $this->is_cert_configured(); + + return $is_configured; + } + + + /** + * Determines if the certification path is set and valid. + * + * @since 4.7.0-dev + * + * @return bool + */ + public function is_cert_configured() { + + return is_readable( $this->get_cert_path() ); + } + + + /** + * Determines if Apple Pay is enabled. + * + * @since 4.7.0-dev + * + * @return bool + */ + public function is_enabled() { + + return 'yes' === get_option( 'sv_wc_apple_pay_enabled' ); + } + + + /** + * Determines if test mode is enabled. + * + * @since 4.7.0-dev + * + * @return bool + */ + public function is_test_mode() { + + return 'yes' === get_option( 'sv_wc_apple_pay_test_mode' ); + } + + + /** + * Gets the configured Apple merchant ID. + * + * @since 4.7.0-dev + * @return string + */ + public function get_merchant_id() { + + return get_option( 'sv_wc_apple_pay_merchant_id' ); + } + + + /** + * Gets the certificate file path. + * + * @since 4.7.0-dev + * + * @return string + */ + public function get_cert_path() { + + return get_option( 'sv_wc_apple_pay_cert_path' ); + } + + + /** + * Gets the currencies accepted by the gateway's Apple Pay integration. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_accepted_currencies() { + + $currencies = ( $this->get_processing_gateway() ) ? $this->get_processing_gateway()->get_apple_pay_currencies() : array(); + + /** + * Filters the currencies accepted by the gateway's Apple Pay integration. + * + * @since 4.7.0-dev + * @return array + */ + return apply_filters( 'sv_wc_apple_pay_accepted_currencies', $currencies ); + } + + + /** + * Gets the gateway's Apple Pay capabilities. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_capabilities() { + + $valid_capabilities = array( + 'supports3DS', + 'supportsEMV', + 'supportsCredit', + 'supportsDebit', + ); + + $gateway_capabilities = ( $this->get_processing_gateway() ) ? $this->get_processing_gateway()->get_apple_pay_capabilities() : array(); + + $capabilities = array_intersect( $valid_capabilities, $gateway_capabilities ); + + /** + * Filters the gateway's Apple Pay capabilities. + * + * @since 4.7.0-dev + * + * @param array $capabilities the gateway capabilities + * @param \SV_WC_Payment_Gateway_Apple_Pay $handler the Apple Pay handler + */ + return apply_filters( 'sv_wc_apple_pay_capabilities', array_values( $capabilities ), $this ); + } + + + /** + * Gets the supported networks for Apple Pay. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_supported_networks() { + + $accepted_card_types = ( $this->get_processing_gateway() ) ? $this->get_processing_gateway()->get_card_types() : array(); + + $accepted_card_types = array_map( 'SV_WC_Payment_Gateway_Helper::normalize_card_type', $accepted_card_types ); + + $valid_networks = array( + SV_WC_Payment_Gateway_Helper::CARD_TYPE_AMEX => 'amex', + SV_WC_Payment_Gateway_Helper::CARD_TYPE_DISCOVER => 'discover', + SV_WC_Payment_Gateway_Helper::CARD_TYPE_MASTERCARD => 'masterCard', + SV_WC_Payment_Gateway_Helper::CARD_TYPE_VISA => 'visa', + 'privateLabel' => 'privateLabel', // ? + ); + + $networks = array_intersect_key( $valid_networks, array_flip( $accepted_card_types ) ); + + /** + * Filters the supported Apple Pay networks (card types). + * + * @since 4.7.0-dev + * + * @param array $networks the supported networks + * @param \SV_WC_Payment_Gateway_Apple_Pay $handler the Apple Pay handler + */ + return apply_filters( 'sv_wc_apple_pay_supported_networks', array_values( $networks ), $this ); + } + + + /** + * Gets the gateways that declare Apple Pay support. + * + * @since 4.7.0-dev + * + * @return array the supporting gateways as `$gateway_id => \SV_WC_Payment_Gateway` + */ + public function get_supporting_gateways() { + + $available_gateways = $this->get_plugin()->get_gateways(); + $supporting_gateways = array(); + + foreach ( $available_gateways as $key => $gateway ) { + + if ( $gateway->supports_apple_pay() ) { + $supporting_gateways[ $gateway->get_id() ] = $gateway; + } + } + + return $supporting_gateways; + } + + + /** + * Gets the gateway set to process Apple Pay transactions. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway|null + */ + public function get_processing_gateway() { + + $gateways = $this->get_supporting_gateways(); + + $gateway_id = get_option( 'sv_wc_apple_pay_payment_gateway' ); + + return isset( $gateways[ $gateway_id ] ) ? $gateways[ $gateway_id ] : null; + } + + + /** + * Gets the Apple Pay button style. + * + * @since 4.7.0-dev + * + * @return string + */ + public function get_button_style() { + + return get_option( 'sv_wc_apple_pay_button_style', 'black' ); + } + + + /** + * Gets the gateway plugin instance. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Plugin + */ + public function get_plugin() { + + return $this->plugin; + } + + +} + +endif; diff --git a/woocommerce/payment-gateway/assets/css/frontend/sv-wc-payment-gateway-apple-pay.css b/woocommerce/payment-gateway/assets/css/frontend/sv-wc-payment-gateway-apple-pay.css new file mode 100644 index 000000000..7c14436b6 --- /dev/null +++ b/woocommerce/payment-gateway/assets/css/frontend/sv-wc-payment-gateway-apple-pay.css @@ -0,0 +1,121 @@ +.sv-wc-apple-pay-button { + display: none; + width: 100%; + height: 44px; + margin: 0 0 1em 0; +} + +@supports ( -webkit-appearance: -apple-pay-button ) { + + .sv-wc-apple-pay-button { + -webkit-appearance: -apple-pay-button; + } + + .sv-wc-apple-pay-button.apple-pay-button-black { + -apple-pay-button-style: black; + } + + .sv-wc-apple-pay-button.apple-pay-button-white { + -apple-pay-button-style: white; + } + + .sv-wc-apple-pay-button.apple-pay-button-white-with-line { + -apple-pay-button-style: white-outline; + } + + .sv-wc-apple-pay-button.apple-pay-button-buy-now { + -apple-pay-button-type: buy; + } + + .sv-wc-apple-pay-button.apple-pay-button-buy-now > * { + display: none; + } +} + +@supports not ( -webkit-appearance: -apple-pay-button ) { + + .sv-wc-apple-pay-button { + background-size: 100% 60%; + background-repeat: no-repeat; + background-position: 50% 50%; + border-radius: 5px; + padding: 0px; + box-sizing: border-box; + min-width: 100px; + min-height: 40px; + max-height: 64px; + width: 100%; + } + + .sv-wc-apple-pay-button.apple-pay-button-black { + background-image: -webkit-named-image( apple-pay-logo-white ); + background-color: black; + color: white; + } + + .sv-wc-apple-pay-button.apple-pay-button-white, + .sv-wc-apple-pay-button.apple-pay-button-white-with-line { + background-image: -webkit-named-image( apple-pay-logo-black ); + background-color: white; + color: black; + } + + .sv-wc-apple-pay-button.apple-pay-button-white-with-line { + border: .5px solid black; + } + + .sv-wc-apple-pay-button.apple-pay-button-with-text { + --apple-pay-scale: 1; /* (height / 32) */ + justify-content: center; + font-size: 12px; + background: none; + } + + .sv-wc-apple-pay-button.apple-pay-button-with-text > .text { + font-family: -apple-system; + font-size: calc( 1em * var( --apple-pay-scale ) ); + font-weight: 300; + align-self: center; + margin-right: calc( 2px * var( --apple-pay-scale ) ); + } + + .sv-wc-apple-pay-button.apple-pay-button-with-text > .logo { + width: calc( 35px * var( --scale ) ); + height: 100%; + background-size: 100% 60%; + background-repeat: no-repeat; + background-position: 0 50%; + margin-left: calc( 2px * var( --apple-pay-scale ) ); + border: none; + } + + .sv-wc-apple-pay-button.apple-pay-button-black .apple-pay-button-with-text > .logo { + background-image: -webkit-named-image( apple-pay-logo-white ); + background-color: black; + } + + .sv-wc-apple-pay-button.apple-pay-button-white .apple-pay-button-with-text > .logo, + .sv-wc-apple-pay-button.apple-pay-button-white-with-line .apple-pay-button-with-text > .logo { + background-image: -webkit-named-image( apple-pay-logo-black ); + background-color: white; + } +} + +.sv-wc-apply-pay-checkout { + display: none; + max-width: 510px; + margin: 0 auto 2em; + text-align: center; +} +.sv-wc-apply-pay-checkout .sv-wc-apple-pay-button { + display: block; +} +.sv-wc-apply-pay-checkout .divider { + font-size: 1.15em; + font-style: italic; + text-transform: uppercase; +} +.sv-wc-apply-pay-checkout .divider::before, +.sv-wc-apply-pay-checkout .divider::after { + content: "\2014"; +} diff --git a/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-apple-pay.coffee b/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-apple-pay.coffee new file mode 100644 index 000000000..1a59b60d4 --- /dev/null +++ b/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-apple-pay.coffee @@ -0,0 +1,442 @@ +### + WooCommerce Apple Pay Handler + Version 4.7.0-dev + + Copyright (c) 2016, SkyVerge, Inc. + Licensed under the GNU General Public License v3.0 + http://www.gnu.org/licenses/gpl-3.0.html +### + +jQuery( document ).ready ($) -> + + "use strict" + + # The WooCommerce Apple Pay handler base class. + # + # @since 4.7.0-dev + class window.SV_WC_Apple_Pay_Handler + + + # Constructs the handler. + # + # @since 4.7.0-dev + constructor: (args) -> + + @params = sv_wc_apple_pay_params + + @payment_request = args.payment_request + + @buttons = '.sv-wc-apple-pay-button' + + if this.is_available() + + if @payment_request + $( @buttons ).show() + + this.init() + + this.attach_update_events() + + + # Determines if Apple Pay is available. + # + # @since 4.7.0-dev + # @return bool + is_available: -> + + return false unless window.ApplePaySession + + ApplePaySession.canMakePaymentsWithActiveCard( @params.merchant_id ).then ( canMakePayments ) => + + return canMakePayments + + + # Initializes the handler. + # + # @since 4.7.0-dev + init: -> + + $( document.body ).on 'click', '.sv-wc-apple-pay-button', ( e ) => + + e.preventDefault() + + this.block_ui() + + try + + @session = new ApplePaySession( 1, @payment_request ) + + # set the payment card events + @session.onvalidatemerchant = ( event ) => this.on_validate_merchant( event ) + @session.onpaymentmethodselected = ( event ) => this.on_payment_method_selected( event ) + @session.onshippingcontactselected = ( event ) => this.on_shipping_contact_selected( event ) + @session.onshippingmethodselected = ( event ) => this.on_shipping_method_selected( event ) + @session.onpaymentauthorized = ( event ) => this.on_payment_authorized( event ) + @session.oncancel = ( event ) => this.on_cancel_payment( event ) + + @session.begin() + + catch error + + this.fail_payment( error ) + + + # The callback for after the merchant data is validated. + # + # @since 4.7.0-dev + on_validate_merchant: ( event ) => + + this.validate_merchant( event.validationURL ).then ( merchant_session ) => + + merchant_session = $.parseJSON( merchant_session ) + + @session.completeMerchantValidation( merchant_session ) + + , ( response ) => + + @session.abort() + + this.fail_payment 'Merchant could no be validated. ' + response.message + + + # Validates the merchant data. + # + # @since 4.7.0-dev + # @return object + validate_merchant: ( url ) => new Promise ( resolve, reject ) => + + data = { + 'action': 'sv_wc_apple_pay_validate_merchant', + 'nonce': @params.validate_nonce, + 'merchant_id': @params.merchant_id, + 'url': url + } + + # retrieve a payment request object + $.post @params.ajax_url, data, ( response ) => + + if response.success + resolve response.data + else + reject response.data + + + # Fires after a payment method has been selected. + # + # @since 4.7.0-dev + on_payment_method_selected: ( event ) => + + new Promise ( resolve, reject ) => + + data = { + 'action': 'sv_wc_apple_pay_recalculate_totals', + 'nonce': @params.recalculate_totals_nonce, + } + + # retrieve a payment request object + $.post @params.ajax_url, data, ( response ) => + + if response.success + + data = response.data + + resolve @session.completePaymentMethodSelection( data.total, data.line_items ) + + else + + console.error '[Apple Pay] Error selecting a shipping contact. ' + response.data.message + + reject @session.completePaymentMethodSelection( @payment_request.total, @payment_request.lineItems ) + + + # Fires after a shipping contact has been selected. + # + # @since 4.7.0-dev + on_shipping_contact_selected: ( event ) => + + new Promise ( resolve, reject ) => + + data = { + 'action': 'sv_wc_apple_pay_recalculate_totals', + 'nonce': @params.recalculate_totals_nonce, + 'contact': event.shippingContact + } + + # retrieve a payment request object + $.post @params.ajax_url, data, ( response ) => + + if response.success + + data = response.data + + resolve @session.completeShippingContactSelection( ApplePaySession.STATUS_SUCCESS, data.shipping_methods, data.total, data.line_items ) + + else + + console.error '[Apple Pay] Error selecting a shipping contact. ' + response.data.message + + reject @session.completeShippingContactSelection( ApplePaySession.STATUS_FAILURE, [], @payment_request.total, @payment_request.lineItems ) + + + # Fires after a shipping method has been selected. + # + # @since 4.7.0-dev + on_shipping_method_selected: ( event ) => + + new Promise ( resolve, reject ) => + + data = { + 'action': 'sv_wc_apple_pay_recalculate_totals', + 'nonce': @params.recalculate_totals_nonce, + 'method': event.shippingMethod.identifier + } + + # retrieve a payment request object + $.post @params.ajax_url, data, ( response ) => + + if response.success + + data = response.data + + resolve @session.completeShippingMethodSelection( ApplePaySession.STATUS_SUCCESS, data.total, data.line_items ) + + else + + console.error '[Apple Pay] Error selecting a shipping method. ' + response.data.message + + reject @session.completeShippingMethodSelection( ApplePaySession.STATUS_FAILURE, @payment_request.total, @payment_request.lineItems ) + + + # The callback for after the payment data is authorized. + # + # @since 4.7.0-dev + on_payment_authorized: ( event ) => + + this.process_authorization( event.payment ).then ( response ) => + + this.set_payment_status( true ) + + this.complete_purchase( response ) + + , ( response ) => + + this.set_payment_status( false ) + + this.fail_payment 'Payment could no be processed. ' + response.message + + + # Processes the transaction data. + # + # @since 4.7.0-dev + process_authorization: ( payment ) => new Promise ( resolve, reject ) => + + data = { + action: 'sv_wc_apple_pay_process_payment', + nonce: @params.process_nonce, + type: @type, + payment: JSON.stringify( payment ) + } + + $.post @params.ajax_url, data, ( response ) => + + if response.success + resolve response.data + else + reject response.data + + + # The callback for when the payment card is cancelled/dismissed. + # + # @since 4.7.0-dev + on_cancel_payment: ( event ) => + + this.unblock_ui() + + + # Completes the purchase based on the gateway result. + # + # @since 4.7.0-dev + complete_purchase: ( response ) -> + + window.location = response.redirect + + + # Fails the purchase based on the gateway result. + # + # @since 4.7.0-dev + fail_payment: ( error ) -> + + console.error '[Apple Pay] ' + error + + this.unblock_ui() + + this.render_errors( [ @params.generic_error ] ) + + + # Sets the Apple Pay payment status depending on the gateway result. + # + # @since 4.7.0-dev + set_payment_status: ( success ) -> + + if success + status = ApplePaySession.STATUS_SUCCESS + else + status = ApplePaySession.STATUS_FAILURE + + @session.completePayment( status ) + + + # Attaches any update events required by the implementing class. + # + # @since 4.7.0-dev + attach_update_events: => + + # Optional, for resetting the request data + + + # Resets the payment request via AJAX. + # + # Extending handlers can call this on change events to refresh the data. + # + # @since 4.7.0-dev + reset_payment_request: ( data = {} ) => + + this.block_ui() + + this.get_payment_request( data ).then ( response ) => + + $( @buttons ).show() + + @payment_request = $.parseJSON( response ) + + this.unblock_ui() + + , ( response ) => + + console.error '[Apple Pay] Could not build payment request. ' + response.message + + $( @buttons ).hide() + + this.unblock_ui() + + + # Gets the payment request via AJAX. + # + # @since 4.7.0-dev + get_payment_request: ( data ) => new Promise ( resolve, reject ) => + + base_data = { + 'action': 'sv_wc_apple_pay_get_payment_request' + 'type' : @type + } + + $.extend data, base_data + + # retrieve a payment request object + $.post @params.ajax_url, data, ( response ) => + + if response.success + resolve response.data + else + reject response.data + + + # Renders any new errors and bring them into the viewport. + # + # @since 4.7.0-dev + render_errors: ( errors ) -> + + # hide and remove any previous errors + $( '.woocommerce-error, .woocommerce-message' ).remove() + + # add errors + @ui_element.prepend '' + + # unblock UI + @ui_element.removeClass( 'processing' ).unblock() + + # scroll to top + $( 'html, body' ).animate( { scrollTop: @ui_element.offset().top - 100 }, 1000 ) + + + # Blocks the payment form UI. + # + # @since 4.7.0-dev + block_ui: -> @ui_element.block( message: null, overlayCSS: background: '#fff', opacity: 0.6 ) + + + # Unblocks the payment form UI. + # + # @since 4.7.0-dev + unblock_ui: -> @ui_element.unblock() + + + # The WooCommerce Apple Pay cart handler class. + # + # @since 4.7.0-dev + class window.SV_WC_Apple_Pay_Cart_Handler extends SV_WC_Apple_Pay_Handler + + + # Constructs the handler. + # + # @since 4.7.0-dev + constructor: ( args ) -> + + @type = 'cart' + + @ui_element = $( 'form.woocommerce-cart-form' ).parents( 'div.woocommerce' ) + + super( args ) + + attach_update_events: => + + # re-init if the cart totals are updated + $( document.body ).on 'updated_cart_totals', => + + this.reset_payment_request() + + + # The WooCommerce Apple Pay checkout handler class. + # + # @since 4.7.0-dev + class window.SV_WC_Apple_Pay_Checkout_Handler extends SV_WC_Apple_Pay_Handler + + + # Constructs the handler. + # + # @since 4.7.0-dev + constructor: ( args ) -> + + @type = 'checkout' + + @ui_element = $( 'form.woocommerce-checkout' ) + + super( args ) + + @buttons = '.sv-wc-apply-pay-checkout' + + + attach_update_events: => + + # re-init if the cart totals are updated + $( document.body ).on 'updated_checkout', => + + this.reset_payment_request() + + + # The WooCommerce Apple Pay product handler class. + # + # @since 4.7.0-dev + class window.SV_WC_Apple_Pay_Product_Handler extends SV_WC_Apple_Pay_Handler + + + # Constructs the handler. + # + # @since 4.7.0-dev + constructor: ( args ) -> + + @type = 'product' + + @ui_element = $( 'form.cart' ) + + super( args ) diff --git a/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-apple-pay.min.js b/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-apple-pay.min.js new file mode 100644 index 000000000..b941257cf --- /dev/null +++ b/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-apple-pay.min.js @@ -0,0 +1,375 @@ + +/* + WooCommerce Apple Pay Handler + Version 4.7.0-dev + + Copyright (c) 2016, SkyVerge, Inc. + Licensed under the GNU General Public License v3.0 + http://www.gnu.org/licenses/gpl-3.0.html + */ + +(function() { + var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + hasProp = {}.hasOwnProperty; + + jQuery(document).ready(function($) { + "use strict"; + window.SV_WC_Apple_Pay_Handler = (function() { + function SV_WC_Apple_Pay_Handler(args) { + this.get_payment_request = bind(this.get_payment_request, this); + this.reset_payment_request = bind(this.reset_payment_request, this); + this.attach_update_events = bind(this.attach_update_events, this); + this.on_cancel_payment = bind(this.on_cancel_payment, this); + this.process_authorization = bind(this.process_authorization, this); + this.on_payment_authorized = bind(this.on_payment_authorized, this); + this.on_shipping_method_selected = bind(this.on_shipping_method_selected, this); + this.on_shipping_contact_selected = bind(this.on_shipping_contact_selected, this); + this.on_payment_method_selected = bind(this.on_payment_method_selected, this); + this.validate_merchant = bind(this.validate_merchant, this); + this.on_validate_merchant = bind(this.on_validate_merchant, this); + this.params = sv_wc_apple_pay_params; + this.payment_request = args.payment_request; + this.buttons = '.sv-wc-apple-pay-button'; + if (this.is_available()) { + if (this.payment_request) { + $(this.buttons).show(); + } + this.init(); + this.attach_update_events(); + } + } + + SV_WC_Apple_Pay_Handler.prototype.is_available = function() { + if (!window.ApplePaySession) { + return false; + } + return ApplePaySession.canMakePaymentsWithActiveCard(this.params.merchant_id).then((function(_this) { + return function(canMakePayments) { + return canMakePayments; + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.init = function() { + return $(document.body).on('click', '.sv-wc-apple-pay-button', (function(_this) { + return function(e) { + var error; + e.preventDefault(); + _this.block_ui(); + try { + _this.session = new ApplePaySession(1, _this.payment_request); + _this.session.onvalidatemerchant = function(event) { + return _this.on_validate_merchant(event); + }; + _this.session.onpaymentmethodselected = function(event) { + return _this.on_payment_method_selected(event); + }; + _this.session.onshippingcontactselected = function(event) { + return _this.on_shipping_contact_selected(event); + }; + _this.session.onshippingmethodselected = function(event) { + return _this.on_shipping_method_selected(event); + }; + _this.session.onpaymentauthorized = function(event) { + return _this.on_payment_authorized(event); + }; + _this.session.oncancel = function(event) { + return _this.on_cancel_payment(event); + }; + return _this.session.begin(); + } catch (_error) { + error = _error; + return _this.fail_payment(error); + } + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.on_validate_merchant = function(event) { + return this.validate_merchant(event.validationURL).then((function(_this) { + return function(merchant_session) { + merchant_session = $.parseJSON(merchant_session); + return _this.session.completeMerchantValidation(merchant_session); + }; + })(this), (function(_this) { + return function(response) { + _this.session.abort(); + return _this.fail_payment('Merchant could no be validated. ' + response.message); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.validate_merchant = function(url) { + return new Promise((function(_this) { + return function(resolve, reject) { + var data; + data = { + 'action': 'sv_wc_apple_pay_validate_merchant', + 'nonce': _this.params.validate_nonce, + 'merchant_id': _this.params.merchant_id, + 'url': url + }; + return $.post(_this.params.ajax_url, data, function(response) { + if (response.success) { + return resolve(response.data); + } else { + return reject(response.data); + } + }); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.on_payment_method_selected = function(event) { + return new Promise((function(_this) { + return function(resolve, reject) { + var data; + data = { + 'action': 'sv_wc_apple_pay_recalculate_totals', + 'nonce': _this.params.recalculate_totals_nonce + }; + return $.post(_this.params.ajax_url, data, function(response) { + if (response.success) { + data = response.data; + return resolve(_this.session.completePaymentMethodSelection(data.total, data.line_items)); + } else { + console.error('[Apple Pay] Error selecting a shipping contact. ' + response.data.message); + return reject(_this.session.completePaymentMethodSelection(_this.payment_request.total, _this.payment_request.lineItems)); + } + }); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.on_shipping_contact_selected = function(event) { + return new Promise((function(_this) { + return function(resolve, reject) { + var data; + data = { + 'action': 'sv_wc_apple_pay_recalculate_totals', + 'nonce': _this.params.recalculate_totals_nonce, + 'contact': event.shippingContact + }; + return $.post(_this.params.ajax_url, data, function(response) { + if (response.success) { + data = response.data; + return resolve(_this.session.completeShippingContactSelection(ApplePaySession.STATUS_SUCCESS, data.shipping_methods, data.total, data.line_items)); + } else { + console.error('[Apple Pay] Error selecting a shipping contact. ' + response.data.message); + return reject(_this.session.completeShippingContactSelection(ApplePaySession.STATUS_FAILURE, [], _this.payment_request.total, _this.payment_request.lineItems)); + } + }); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.on_shipping_method_selected = function(event) { + return new Promise((function(_this) { + return function(resolve, reject) { + var data; + data = { + 'action': 'sv_wc_apple_pay_recalculate_totals', + 'nonce': _this.params.recalculate_totals_nonce, + 'method': event.shippingMethod.identifier + }; + return $.post(_this.params.ajax_url, data, function(response) { + if (response.success) { + data = response.data; + return resolve(_this.session.completeShippingMethodSelection(ApplePaySession.STATUS_SUCCESS, data.total, data.line_items)); + } else { + console.error('[Apple Pay] Error selecting a shipping method. ' + response.data.message); + return reject(_this.session.completeShippingMethodSelection(ApplePaySession.STATUS_FAILURE, _this.payment_request.total, _this.payment_request.lineItems)); + } + }); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.on_payment_authorized = function(event) { + return this.process_authorization(event.payment).then((function(_this) { + return function(response) { + _this.set_payment_status(true); + return _this.complete_purchase(response); + }; + })(this), (function(_this) { + return function(response) { + _this.set_payment_status(false); + return _this.fail_payment('Payment could no be processed. ' + response.message); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.process_authorization = function(payment) { + return new Promise((function(_this) { + return function(resolve, reject) { + var data; + data = { + action: 'sv_wc_apple_pay_process_payment', + nonce: _this.params.process_nonce, + type: _this.type, + payment: JSON.stringify(payment) + }; + return $.post(_this.params.ajax_url, data, function(response) { + if (response.success) { + return resolve(response.data); + } else { + return reject(response.data); + } + }); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.on_cancel_payment = function(event) { + return this.unblock_ui(); + }; + + SV_WC_Apple_Pay_Handler.prototype.complete_purchase = function(response) { + return window.location = response.redirect; + }; + + SV_WC_Apple_Pay_Handler.prototype.fail_payment = function(error) { + console.error('[Apple Pay] ' + error); + this.unblock_ui(); + return this.render_errors([this.params.generic_error]); + }; + + SV_WC_Apple_Pay_Handler.prototype.set_payment_status = function(success) { + var status; + if (success) { + status = ApplePaySession.STATUS_SUCCESS; + } else { + status = ApplePaySession.STATUS_FAILURE; + } + return this.session.completePayment(status); + }; + + SV_WC_Apple_Pay_Handler.prototype.attach_update_events = function() {}; + + SV_WC_Apple_Pay_Handler.prototype.reset_payment_request = function(data) { + if (data == null) { + data = {}; + } + this.block_ui(); + return this.get_payment_request(data).then((function(_this) { + return function(response) { + $(_this.buttons).show(); + _this.payment_request = $.parseJSON(response); + return _this.unblock_ui(); + }; + })(this), (function(_this) { + return function(response) { + console.error('[Apple Pay] Could not build payment request. ' + response.message); + $(_this.buttons).hide(); + return _this.unblock_ui(); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.get_payment_request = function(data) { + return new Promise((function(_this) { + return function(resolve, reject) { + var base_data; + base_data = { + 'action': 'sv_wc_apple_pay_get_payment_request', + 'type': _this.type + }; + $.extend(data, base_data); + return $.post(_this.params.ajax_url, data, function(response) { + if (response.success) { + return resolve(response.data); + } else { + return reject(response.data); + } + }); + }; + })(this)); + }; + + SV_WC_Apple_Pay_Handler.prototype.render_errors = function(errors) { + $('.woocommerce-error, .woocommerce-message').remove(); + this.ui_element.prepend(''); + this.ui_element.removeClass('processing').unblock(); + return $('html, body').animate({ + scrollTop: this.ui_element.offset().top - 100 + }, 1000); + }; + + SV_WC_Apple_Pay_Handler.prototype.block_ui = function() { + return this.ui_element.block({ + message: null, + overlayCSS: { + background: '#fff', + opacity: 0.6 + } + }); + }; + + SV_WC_Apple_Pay_Handler.prototype.unblock_ui = function() { + return this.ui_element.unblock(); + }; + + return SV_WC_Apple_Pay_Handler; + + })(); + window.SV_WC_Apple_Pay_Cart_Handler = (function(superClass) { + extend(SV_WC_Apple_Pay_Cart_Handler, superClass); + + function SV_WC_Apple_Pay_Cart_Handler(args) { + this.attach_update_events = bind(this.attach_update_events, this); + this.type = 'cart'; + this.ui_element = $('form.woocommerce-cart-form').parents('div.woocommerce'); + SV_WC_Apple_Pay_Cart_Handler.__super__.constructor.call(this, args); + } + + SV_WC_Apple_Pay_Cart_Handler.prototype.attach_update_events = function() { + return $(document.body).on('updated_cart_totals', (function(_this) { + return function() { + return _this.reset_payment_request(); + }; + })(this)); + }; + + return SV_WC_Apple_Pay_Cart_Handler; + + })(SV_WC_Apple_Pay_Handler); + window.SV_WC_Apple_Pay_Checkout_Handler = (function(superClass) { + extend(SV_WC_Apple_Pay_Checkout_Handler, superClass); + + function SV_WC_Apple_Pay_Checkout_Handler(args) { + this.attach_update_events = bind(this.attach_update_events, this); + this.type = 'checkout'; + this.ui_element = $('form.woocommerce-checkout'); + SV_WC_Apple_Pay_Checkout_Handler.__super__.constructor.call(this, args); + this.buttons = '.sv-wc-apply-pay-checkout'; + } + + SV_WC_Apple_Pay_Checkout_Handler.prototype.attach_update_events = function() { + return $(document.body).on('updated_checkout', (function(_this) { + return function() { + return _this.reset_payment_request(); + }; + })(this)); + }; + + return SV_WC_Apple_Pay_Checkout_Handler; + + })(SV_WC_Apple_Pay_Handler); + return window.SV_WC_Apple_Pay_Product_Handler = (function(superClass) { + extend(SV_WC_Apple_Pay_Product_Handler, superClass); + + function SV_WC_Apple_Pay_Product_Handler(args) { + this.type = 'product'; + this.ui_element = $('form.cart'); + SV_WC_Apple_Pay_Product_Handler.__super__.constructor.call(this, args); + } + + return SV_WC_Apple_Pay_Product_Handler; + + })(SV_WC_Apple_Pay_Handler); + }); + +}).call(this); + +//# sourceMappingURL=sv-wc-payment-gateway-apple-pay.min.js.map diff --git a/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-frontend.min.map b/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-frontend.min.map new file mode 100644 index 000000000..00077b35b --- /dev/null +++ b/woocommerce/payment-gateway/assets/js/frontend/sv-wc-payment-gateway-frontend.min.map @@ -0,0 +1 @@ +{"version":3,"sources":["sv-wc-payment-gateway-frontend.coffee"],"names":["jQuery","document","ready","$","window","SV_WC_Payment_Form_Handler","args","this","id","id_dasherized","plugin_id","type","csc_required","length","form","handle_checkout_page","handle_pay_page","console","log","handle_add_payment_method_page","params","on","_this","handle_sample_check_hint","trigger","instance","body","format_credit_card_inputs","set_payment_fields","handle_saved_payment_methods","validate_payment_data","submit","val","payment_fields","tokenized_payment_method_selected","is","find","validate_card_data","validate_account_data","payment","change","do_inline_credit_card_validation","$csc","$expiry","validateCardExpiry","addClass","removeClass","validateCardCVC","account_number","csc","errors","expiry","cardExpiryVal","replace","push","card_number_length_invalid","test","card_number_digits_invalid","validateCardNumber","card_number_invalid","card_number_missing","card_exp_date_invalid","cvv_digits_invalid","cvv_length_invalid","cvv_missing","render_errors","routing_number","routing_number_length_invalid","routing_number_digits_invalid","routing_number_missing","account_number_length_invalid","account_number_invalid","account_number_missing","remove","prepend","join","unblock","blur","animate","scrollTop","offset","top","$csc_field","$new_payment_method_selection","parent","slideUp","after","slideDown","$parent_row","closest","next","show","hide","$sample_check"],"mappings":"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","file":"sv-wc-payment-gateway-frontend.min.js","sourceRoot":"","sourcesContent":[null]} \ No newline at end of file diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php index cf3d2307e..1ae8b3150 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php @@ -672,16 +672,25 @@ protected function do_credit_card_transaction( $order, $response = null ) { // credit card order note $message = sprintf( - /* translators: Placeholders: %1$s - payment method title, %2$s - environment ("Test"), %3$s - transaction type (authorization/charge), %4$s - card type (mastercard, visa, ...), %5$s - last four digits of the card, %6$s - expiry date */ - esc_html__( '%1$s %2$s %3$s Approved: %4$s ending in %5$s (expires %6$s)', 'woocommerce-plugin-framework' ), + /* translators: Placeholders: %1$s - payment method title, %2$s - environment ("Test"), %3$s - transaction type (authorization/charge), %4$s - card type (mastercard, visa, ...), %5$s - last four digits of the card */ + esc_html__( '%1$s %2$s %3$s Approved: %4$s ending in %5$s', 'woocommerce-plugin-framework' ), $this->get_method_title(), $this->is_test_environment() ? esc_html_x( 'Test', 'noun, software environment', 'woocommerce-plugin-framework' ) : '', $this->perform_credit_card_authorization( $order ) ? esc_html_x( 'Authorization', 'credit card transaction type', 'woocommerce-plugin-framework' ) : esc_html_x( 'Charge', 'noun, credit card transaction type', 'woocommerce-plugin-framework' ), SV_WC_Payment_Gateway_Helper::payment_type_to_name( $card_type ), - $last_four, - $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 ) + $last_four ); + // add the expiry date if it is available + if ( ! empty( $order->payment->exp_month ) && ! empty( $order->payment->exp_year ) ) { + + $message .= ' ' . sprintf( + /** translators: Placeholders: %s - credit card expiry date */ + __( '(expires %s)', 'woocommerce-plugin-framework' ), + $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 ) + ); + } + // adds the transaction id (if any) to the order note if ( $response->get_transaction_id() ) { /* translators: Placeholders: %s - transaction ID */ diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php index c5b2f9cfc..8c5f0352c 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php @@ -91,6 +91,9 @@ abstract class SV_WC_Payment_Gateway_Plugin extends SV_WC_Plugin { /** @var SV_WC_Payment_Gateway_My_Payment_Methods adds My Payment Method functionality */ private $my_payment_methods; + /** @var \SV_WC_Payment_Gateway_Apple_Pay the Apple Pay handler instance */ + private $apple_pay; + /** * Initialize the plugin @@ -136,6 +139,9 @@ public function __construct( $id, $version, $args ) { add_action( 'wp', array( $this, 'maybe_init_my_payment_methods' ) ); } + // Apple Pay feature + add_action( 'init', array( $this, 'maybe_init_apple_pay' ) ); + // Admin if ( is_admin() && ! is_ajax() ) { @@ -240,6 +246,15 @@ public function lib_includes() { require_once( $payment_gateway_framework_path . '/class-sv-wc-payment-gateway-payment-form.php' ); require_once( $payment_gateway_framework_path . '/class-sv-wc-payment-gateway-my-payment-methods.php' ); + // apple pay + require_once( "{$payment_gateway_framework_path}/apple-pay/class-sv-wc-payment-gateway-apple-pay.php" ); + require_once( "{$payment_gateway_framework_path}/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php" ); + require_once( "{$payment_gateway_framework_path}/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php" ); + require_once( "{$payment_gateway_framework_path}/apple-pay/class-sv-wc-payment-gateway-apple-pay-ajax.php" ); + require_once( "{$payment_gateway_framework_path}/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php" ); + require_once( "{$payment_gateway_framework_path}/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-payment-response.php" ); + + // payment tokens require_once( $payment_gateway_framework_path . '/payment-tokens/class-sv-wc-payment-gateway-payment-token.php' ); require_once( $payment_gateway_framework_path . '/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php' ); @@ -322,6 +337,81 @@ protected function get_my_payment_methods_instance() { } + /** Apple Pay *************************************************************/ + + + /** + * Initializes Apple Pay if it's supported. + * + * @since 4.7.0-dev + */ + public function maybe_init_apple_pay() { + + /** + * Filters whether Apple Pay is activated. + * + * @since 4.7.0-dev + * + * @param bool $activated whether Apple Pay is activated + */ + $activated = (bool) apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_activate_apple_pay', false ); + + if ( $this->supports_apple_pay() && $activated ) { + $this->apple_pay = $this->build_apple_pay_instance(); + } + } + + + /** + * Builds the Apple Pay handler instance. + * + * Gateways can override this to define their own Apple Pay class. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Apple_Pay + */ + protected function build_apple_pay_instance() { + + return new SV_WC_Payment_Gateway_Apple_Pay( $this ); + } + + + /** + * Gets the Apple Pay handler instance. + * + * @since 4.7.0-dev + * + * @return \SV_WC_Payment_Gateway_Apple_Pay + */ + public function get_apple_pay_instance() { + + return $this->apple_pay; + } + + + /** + * Determines if this plugin has any gateways with Apple Pay support. + * + * @since 4.7.0-dev + * + * @return bool + */ + public function supports_apple_pay() { + + $is_supported = false; + + foreach ( $this->get_gateways() as $gateway ) { + + if ( $gateway->supports_apple_pay() ) { + $is_supported = true; + } + } + + return $is_supported; + } + + /** Admin methods ******************************************************/ diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php index c61b1472f..137f68ea5 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php @@ -112,6 +112,9 @@ abstract class SV_WC_Payment_Gateway extends WC_Payment_Gateway { /** Customer ID feature */ const FEATURE_CUSTOMER_ID = 'customer_id'; + /** Apple Pay feature */ + const FEATURE_APPLE_PAY = 'apple_pay'; + /** @var SV_WC_Payment_Gateway_Plugin the parent plugin class */ private $plugin; @@ -697,6 +700,78 @@ public function get_payment_method_defaults() { } + /** Apple Pay Feature *****************************************************/ + + + /** + * Determines whether this gateway supports Apple Pay. + * + * @since 4.7.0-dev + * + * @return bool + */ + public function supports_apple_pay() { + + return $this->supports( self::FEATURE_APPLE_PAY ); + } + + + /** + * Gets the Apple Pay gateway capabilities. + * + * Gateways should override this if they have more or less capabilities than + * the default. See https://developer.apple.com/reference/applepayjs/paymentrequest/1916123-merchantcapabilities + * for valid values. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_apple_pay_capabilities() { + + return array( + 'supports3DS', + 'supportsCredit', + 'supportsDebit', + ); + } + + + /** + * Gets the currencies supported by Apple Pay. + * + * @since 4.7.0-dev + * + * @return array + */ + public function get_apple_pay_currencies() { + + return array( 'USD' ); + } + + + /** + * Adds the Apple Pay payment data to the order object. + * + * Gateways should override this to set the appropriate values depending on + * how their processing API needs to handle the data. + * + * @since 4.7.0-dev + * + * @param \WC_Order the order object + * @param \SV_WC_Payment_Gateway_Apple_Pay_Payment_Response authorized payment response + * @return \WC_Order + */ + public function get_order_for_apple_pay( WC_Order $order, SV_WC_Payment_Gateway_Apple_Pay_Payment_Response $response ) { + + $order->payment->account_number = $response->get_last_four(); + $order->payment->last_four = $response->get_last_four(); + $order->payment->card_type = $response->get_card_type(); + + return $order; + } + + /** * Get the default payment method title, which is configurable within the * admin and displayed on checkout