diff --git a/src/inc/payment-gateways/lib/stripe.php b/src/inc/payment-gateways/lib/stripe.php index 4ce58f8..4e5ca92 100644 --- a/src/inc/payment-gateways/lib/stripe.php +++ b/src/inc/payment-gateways/lib/stripe.php @@ -6,125 +6,6 @@ * A class to share Stripe-specific logic with payment gateways that use Stripe in some way. */ class Stripe { - /** - * Get all payment methods for customer from order. - * - * @param \WC_Order $order The WC Order. - * - * @return array|null - */ - public static function get_all_payment_methods_for_customer_from_order( \WC_Order $order ): ?array { - $stripe_customer_id = $order->get_meta( '_stripe_customer_id', true ); - - $stripe_customer = new \WC_Stripe_Customer(); - $stripe_customer->set_id( $stripe_customer_id ); - - $sources = array_merge( - $stripe_customer->get_payment_methods( 'card' ), - $stripe_customer->get_payment_methods( 'sepa_debit' ) - ); - - if ( $sources ) { - return $sources; - } - } - - /** - * Get payment method from order. - * - * @param \WC_Order $order The WC Order. - * - * @return object The payment method from the order. - */ - public static function get_payment_method_from_order( \WC_Order $order ) { - $stripe_source_id = $order->get_meta( '_stripe_source_id', true ); - $sources = static::get_all_payment_methods_for_customer_from_order( $order ); - - if ( $sources ) { - foreach ( $sources as $source ) { - if ( $source->id === $stripe_source_id ) { - return $source; - } - } - } - } - - /** - * Get payment intent from order. - * - * @param \WC_Order $order The WC Order. - * - * @return object The payment intent from the order. - */ - public static function get_intent_from_order( \WC_Order $order ) { - $intent_id = $order->get_meta( '_stripe_intent_id' ); - - if ( $intent_id ) { - return static::get_intent( 'payment_intents', $intent_id ); - } - - // The order doesn't have a payment intent, but it may have a setup intent. - $intent_id = $order->get_meta( '_stripe_setup_intent' ); - - if ( $intent_id ) { - return static::get_intent( 'setup_intents', $intent_id ); - } - - return false; - } - - /** - * Get the intent by ID from the Stripe API. - * - * @param string $intent_type The intent type. - * @param string $intent_id The intent's ID. - * - * @return object The intent from the API. - */ - public static function get_intent( string $intent_type, string $intent_id ) { - if ( ! in_array( $intent_type, array( 'payment_intents', 'setup_intents' ), true ) ) { - throw new \Exception( sprintf( 'Failed to get intent of type %s. Type is not allowed', esc_attr( $intent_type ) ) ); - } - - $response = \WC_Stripe_API::request( array(), "$intent_type/$intent_id?expand[]=payment_method", 'GET' ); - - if ( $response && isset( $response->{ 'error' } ) ) { - return false; - } - - return $response; - } - - /** - * Get the charge for a payment intent from a WC_Order object. - * - * @param \WC_Order $order The WC Order. - * - * @return object The charge for the intent from the order. - */ - public static function get_charge_for_intent_from_order( \WC_Order $order ) { - $intent = self::get_intent_from_order( $order ); - if ( ! empty( $intent ) ) { - $result = \WC_Stripe_API::request( - array(), - 'payment_intents/' . $intent->id - ); - if ( empty( $result->error ) ) { - return end( $result->charges->data ); - } - } - } - - /** - * Get the Stripe UPE payment type from Order metadata. - * - * @param \WC_Order $order The WC Order. - * - * @return null|string - */ - public static function get_payment_type_from_order( \WC_Order $order ): ?string { - return $order->get_meta( '_stripe_upe_payment_type' ); - } /** * Convert a payment method string from a string Stripe would use to a string Sift would use. diff --git a/src/inc/payment-gateways/load.php b/src/inc/payment-gateways/load.php index 99114a9..28175f9 100644 --- a/src/inc/payment-gateways/load.php +++ b/src/inc/payment-gateways/load.php @@ -14,6 +14,10 @@ function () { case 'woopayments': require_once __DIR__ . '/transact.php'; break; + case 'woocommerce_payments': + require_once __DIR__ . '/lib/stripe.php'; + require_once __DIR__ . '/woocommerce-payments.php'; + break; } } } diff --git a/src/inc/payment-gateways/stripe.php b/src/inc/payment-gateways/stripe.php index 2723008..960b329 100644 --- a/src/inc/payment-gateways/stripe.php +++ b/src/inc/payment-gateways/stripe.php @@ -1,20 +1,148 @@ get_meta( '_stripe_customer_id', true ); + + $stripe_customer = new \WC_Stripe_Customer(); + $stripe_customer->set_id( $stripe_customer_id ); + + $sources = array_merge( + $stripe_customer->get_payment_methods( 'card' ), + $stripe_customer->get_payment_methods( 'sepa_debit' ) + ); + + if ( $sources ) { + return $sources; + } + } + + /** + * Get payment method from order. + * + * @param \WC_Order $order The WC Order. + * + * @return object The payment method from the order. + */ + public static function get_payment_method_from_order( \WC_Order $order ) { + $stripe_source_id = $order->get_meta( '_stripe_source_id', true ); + $sources = static::get_all_payment_methods_for_customer_from_order( $order ); + + if ( $sources ) { + foreach ( $sources as $source ) { + if ( $source->id === $stripe_source_id ) { + return $source; + } + } + } + } + + /** + * Get payment intent from order. + * + * @param \WC_Order $order The WC Order. + * + * @return object The payment intent from the order. + */ + public static function get_intent_from_order( \WC_Order $order ) { + $intent_id = $order->get_meta( '_stripe_intent_id' ); + + if ( $intent_id ) { + return static::get_intent( 'payment_intents', $intent_id ); + } + + // The order doesn't have a payment intent, but it may have a setup intent. + $intent_id = $order->get_meta( '_stripe_setup_intent' ); + + if ( $intent_id ) { + return static::get_intent( 'setup_intents', $intent_id ); + } + + return false; + } + + /** + * Get the intent by ID from the Stripe API. + * + * @param string $intent_type The intent type. + * @param string $intent_id The intent's ID. + * + * @return object The intent from the API. + */ + public static function get_intent( string $intent_type, string $intent_id ) { + if ( ! in_array( $intent_type, array( 'payment_intents', 'setup_intents' ), true ) ) { + throw new \Exception( sprintf( 'Failed to get intent of type %s. Type is not allowed', esc_attr( $intent_type ) ) ); + } + + $response = \WC_Stripe_API::request( array(), "$intent_type/$intent_id?expand[]=payment_method", 'GET' ); + + if ( $response && isset( $response->{ 'error' } ) ) { + return false; + } + + return $response; + } + + /** + * Get the charge for a payment intent from a WC_Order object. + * + * @param \WC_Order $order The WC Order. + * + * @return object The charge for the intent from the order. + */ + public static function get_charge_for_intent_from_order( \WC_Order $order ) { + $intent = self::get_intent_from_order( $order ); + if ( ! empty( $intent ) ) { + $result = \WC_Stripe_API::request( + array(), + 'payment_intents/' . $intent->id + ); + if ( empty( $result->error ) ) { + return end( $result->charges->data ); + } + } + } + + /** + * Get the Stripe UPE payment type from Order metadata. + * + * @param \WC_Order $order The WC Order. + * + * @return null|string + */ + public static function get_payment_type_from_order( \WC_Order $order ): ?string { + return $order->get_meta( '_stripe_upe_payment_type' ); + } +} + add_filter( 'sift_for_woocommerce_stripe_payment_gateway_string', fn() => '$stripe' ); add_filter( 'sift_for_woocommerce_stripe_payment_method_details_from_order', function ( \WC_Order $order ) { - return Stripe::get_payment_method_from_order( $order ); + return WooCommerce_Gateway_Stripe_Utils::get_payment_method_from_order( $order ); } ); add_filter( 'sift_for_woocommerce_stripe_charge_details_from_order', function ( \WC_Order $order ) { - return Stripe::get_charge_for_intent_from_order( $order ); + return WooCommerce_Gateway_Stripe_Utils::get_charge_for_intent_from_order( $order ); } ); diff --git a/src/inc/payment-gateways/transact.php b/src/inc/payment-gateways/transact.php index 8d27a61..c5ea1f5 100644 --- a/src/inc/payment-gateways/transact.php +++ b/src/inc/payment-gateways/transact.php @@ -2,15 +2,7 @@ add_filter( 'sift_for_woocommerce_woopayments_payment_gateway_string', fn() => '$stripe' ); -add_filter( - 'sift_for_woocommerce_woopayments_payment_type_string', - function ( $payment_type ) { - switch ( strtolower( $payment_type ) ) { - case 'card': - return '$credit_card'; - } - } -); +add_filter( 'sift_for_woocommerce_woopayments_payment_type_string', array( \Sift_For_WooCommerce\Sift_For_WooCommerce\PaymentGateways\Lib\Stripe::class, 'convert_payment_type_to_sift_payment_type' ) ); add_filter( 'sift_for_woocommerce_woopayments_payment_method_details_from_order', fn( $value, $order ) => $order ?? $value, 10, 2 ); diff --git a/src/inc/payment-gateways/woocommerce-payments.php b/src/inc/payment-gateways/woocommerce-payments.php new file mode 100644 index 0000000..bb6a13b --- /dev/null +++ b/src/inc/payment-gateways/woocommerce-payments.php @@ -0,0 +1,44 @@ + '$stripe' ); + +add_filter( + 'sift_for_woocommerce_woocommerce_payments_payment_method_details_from_order', + function ( $value, \WC_Order $order ) { + try { + $charge_id = \WC_Payments::get_order_service()->get_charge_id_for_order( $order ); + $api_client = \WC_Payments::get_payments_api_client(); + $charge = $api_client->get_charge( $charge_id ); + return $charge->get_payment_method_details(); + } catch ( \Exception ) { + return $value; + } + } +); + +add_filter( + 'sift_for_woocommerce_woocommerce_payments_charge_details_from_order', + function ( $value, \WC_Order $order ) { + try { + $charge_id = \WC_Payments::get_order_service()->get_charge_id_for_order( $order ); + $api_client = \WC_Payments::get_payments_api_client(); + return $api_client->get_charge( $charge_id ); + } catch ( \Exception ) { + return $value; + } + } +); + +add_filter( 'sift_for_woocommerce_woocommerce_payments_payment_type_string', array( \Sift_For_WooCommerce\Sift_For_WooCommerce\PaymentGateways\Lib\Stripe::class, 'convert_payment_type_to_sift_payment_type' ) ); +add_filter( 'sift_for_woocommerce_woocommerce_payments_card_last4', fn( $value, $woocommerce_payments_payment_method_details ) => $woocommerce_payments_payment_method_details['card']['last4'] ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_woocommerce_payments_card_bin', fn( $value, $woocommerce_payments_payment_method_details ) => $woocommerce_payments_payment_method_details['card']['iin'] ?? $value, 10, 2 ); + +add_filter( 'sift_for_woocommerce_woocommerce_payments_cvv_result_code', fn( $value, $woocommerce_payments_charge ) => $woocommerce_payments_charge->get_payment_method_details()['card']['checks']['cvc_check'] ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_woocommerce_payments_sepa_direct_debit_mandate', fn( $value, $woocommerce_payments_charge ) => $woocommerce_payments_charge->get_payment_method_details()['sepa_debit']['mandate'] ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_woocommerce_payments_wallet_type', fn( $value, $woocommerce_payments_charge ) => $woocommerce_payments_charge->get_payment_method_details()['card']['wallet']['type'] ?? $value, 10, 2 ); + +add_filter( 'sift_for_woocommerce_woocommerce_payments_stripe_cvc_check', fn( $value, $woocommerce_payments_charge ) => $woocommerce_payments_charge->get_payment_method_details()['card']['checks']['cvc_check'] ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_woocommerce_payments_stripe_address_line1_check', fn( $value, $woocommerce_payments_charge ) => $woocommerce_payments_charge->get_payment_method_details()['card']['checks']['address_line1_check'] ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_woocommerce_payments_stripe_address_zip_check', fn( $value, $woocommerce_payments_charge ) => $woocommerce_payments_charge->get_payment_method_details()['card']['checks']['address_postal_code_check'] ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_woocommerce_payments_stripe_funding', fn( $value, $woocommerce_payments_charge ) => $woocommerce_payments_charge->get_payment_method_details()['card']['funding'] ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_woocommerce_payments_stripe_brand', fn( $value, $woocommerce_payments_charge ) => $woocommerce_payments_charge->get_payment_method_details()['card']['brand'] ?? $value, 10, 2 ); diff --git a/tests/PaymentGatewayTest.php b/tests/PaymentGatewayTest.php index 84262ec..e740c1c 100644 --- a/tests/PaymentGatewayTest.php +++ b/tests/PaymentGatewayTest.php @@ -1,16 +1,16 @@ true, 'sift_slug' => '$stripe', ), + 'WooCommerce Payments is a valid payment gateway' => array( + 'woo_gateway_id' => 'woocommerce_payments', + 'expected_woo_gateway_id' => 'woocommerce_payments', + 'is_valid' => true, + 'sift_slug' => '$stripe', + ), 'WooPayments is a valid payment gateway' => array( 'woo_gateway_id' => 'woopayments', 'expected_woo_gateway_id' => 'woopayments', diff --git a/tests/PaymentMethodTest.php b/tests/PaymentMethodTest.php index 09ae985..2c293fb 100644 --- a/tests/PaymentMethodTest.php +++ b/tests/PaymentMethodTest.php @@ -1,24 +1,27 @@ - (object) array( + $stripe_card_last4 = '4242'; + $transact_card_last4 = '1111'; + $woocommerce_payments_card_last4 = '4001'; + $stripe_payment_method = build_mock_stripe_payment_method_object( + array( 'last4' => $stripe_card_last4, + ) + ); + $woocommerce_payments_payment_method = build_mock_stripe_payment_method_object( + array( + 'last4' => $woocommerce_payments_card_last4, ), + true ); - $mock_order = $this->getMockBuilder( \WC_Order::class ) + $mock_order = $this->getMockBuilder( \WC_Order::class ) ->disableOriginalConstructor() ->onlyMethods( array( 'get_meta' ) ) ->getMock(); @@ -57,8 +67,9 @@ public function get_card_last4_provider(): array { ->method( 'get_meta' ) ->willReturn( $transact_card_last4 ); - $stripe_gateway = new Payment_Gateway( 'stripe', $mock_order ); - $transact_gateway = new Payment_Gateway( 'transact', $mock_order ); + $stripe_gateway = new Payment_Gateway( 'stripe', $mock_order ); + $transact_gateway = new Payment_Gateway( 'transact', $mock_order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $mock_order ); return array( 'Stripe\'s object returns the card_last4 property' => array( 'gateway' => $stripe_gateway, @@ -70,6 +81,11 @@ public function get_card_last4_provider(): array { 'data' => $mock_order, 'expected' => $transact_card_last4, ), + 'WooCommerce Payments\'s object returns the card_last4 property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_payment_method, + 'expected' => $woocommerce_payments_card_last4, + ), ); } @@ -95,16 +111,23 @@ public function test_get_card_bin( Payment_Gateway $gateway, mixed $data, ?strin * @return array An array of test runs and the data associated with each run. */ public function get_card_bin_provider(): array { - $stripe_card_bin = '4242'; - $stripe_payment_method = (object) array( - 'card' => (object) array( + $stripe_card_bin = '4242'; + $woocommerce_payments_card_bin = '411111'; + $stripe_payment_method = build_mock_stripe_payment_method_object( + array( 'iin' => $stripe_card_bin, + ) + ); + $woocommerce_payments_payment_method = build_mock_stripe_payment_method_object( + array( + 'iin' => $woocommerce_payments_card_bin, ), + true ); - $order = new \WC_Order(); - - $stripe_gateway = new Payment_Gateway( 'stripe', $order ); - $transact_gateway = new Payment_Gateway( 'transact', $order ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); return array( 'Stripe\'s object returns the card_bin property' => array( 'gateway' => $stripe_gateway, @@ -116,6 +139,403 @@ public function get_card_bin_provider(): array { 'data' => $order, 'expected' => '', ), + 'WooCommerce Payments\'s object returns the card_bin property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_payment_method, + 'expected' => $woocommerce_payments_card_bin, + ), + ); + } + + /** + * Test getting the cvv_result_code property. + * + * @dataProvider get_cvv_result_code_provider + * + * @param Payment_Gateway $gateway The payment gateway in use. + * @param mixed $data The data which contains the cvv_result_code value. + * @param null|string $expected The expected result if available. + * + * @return void + */ + public function test_get_cvv_result_code( Payment_Gateway $gateway, mixed $data, ?string $expected ) { + $result = Payment_Method::get_cvv_result_code( $gateway, $data ); + $this->assertEquals( $expected, $result, 'Should return the expected result' ); + } + + /** + * Provide data to the test_get_cvv_result_code test function. + * + * @return array An array of test runs and the data associated with each run. + */ + public function get_cvv_result_code_provider(): array { + $stripe_charge = (object) array( + 'payment_method_details' => build_mock_stripe_payment_method_object( array() ), + ); + $woocommerce_payments_charge = new WC_Payments_API_Charge( array() ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); + return array( + 'Stripe\'s object returns the cvv_result_code property' => array( + 'gateway' => $stripe_gateway, + 'data' => $stripe_charge, + 'expected' => 'OK', + ), + 'Transact\'s object does not return the cvv_result_code property' => array( + 'gateway' => $transact_gateway, + 'data' => $order, + 'expected' => '', + ), + 'WooCommerce Payments\'s object returns the cvv_result_code property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_charge, + 'expected' => 'OK', + ), + ); + } + + /** + * Test getting the sepa_direct_debit_mandate property. + * + * @dataProvider get_sepa_direct_debit_mandate_provider + * + * @param Payment_Gateway $gateway The payment gateway in use. + * @param mixed $data The data which contains the sepa_direct_debit_mandate value. + * @param null|string $expected The expected result if available. + * + * @return void + */ + public function test_get_sepa_direct_debit_mandate( Payment_Gateway $gateway, mixed $data, ?string $expected ) { + $result = Payment_Method::get_sepa_direct_debit_mandate( $gateway, $data ); + $this->assertEquals( $expected, $result, 'Should return the expected result' ); + } + + /** + * Provide data to the test_get_sepa_direct_debit_mandate test function. + * + * @return array An array of test runs and the data associated with each run. + */ + public function get_sepa_direct_debit_mandate_provider(): array { + $stripe_charge = (object) array( + 'payment_method_details' => build_mock_stripe_payment_method_object( array() ), + ); + $woocommerce_payments_charge = new WC_Payments_API_Charge( array() ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); + return array( + 'Stripe\'s object returns the sepa_direct_debit_mandate property' => array( + 'gateway' => $stripe_gateway, + 'data' => $stripe_charge, + 'expected' => 'sepa direct debit mandate code', + ), + 'Transact\'s object does not return the sepa_direct_debit_mandate property' => array( + 'gateway' => $transact_gateway, + 'data' => $order, + 'expected' => '', + ), + 'WooCommerce Payments\'s object returns the sepa_direct_debit_mandate property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_charge, + 'expected' => 'sepa direct debit mandate code', + ), + ); + } + + /** + * Test getting the wallet_type property. + * + * @dataProvider get_wallet_type_provider + * + * @param Payment_Gateway $gateway The payment gateway in use. + * @param mixed $data The data which contains the wallet_type value. + * @param null|string $expected The expected result if available. + * + * @return void + */ + public function test_get_wallet_type( Payment_Gateway $gateway, mixed $data, ?string $expected ) { + $result = Payment_Method::get_wallet_type( $gateway, $data ); + $this->assertEquals( $expected, $result, 'Should return the expected result' ); + } + + /** + * Provide data to the test_get_wallet_type test function. + * + * @return array An array of test runs and the data associated with each run. + */ + public function get_wallet_type_provider(): array { + $stripe_charge = (object) array( + 'payment_method_details' => build_mock_stripe_payment_method_object( array() ), + ); + $woocommerce_payments_charge = new WC_Payments_API_Charge( array() ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); + return array( + 'Stripe\'s object returns the wallet_type property' => array( + 'gateway' => $stripe_gateway, + 'data' => $stripe_charge, + 'expected' => 'crypto', + ), + 'Transact\'s object does not return the wallet_type property' => array( + 'gateway' => $transact_gateway, + 'data' => $order, + 'expected' => '', + ), + 'WooCommerce Payments\'s object returns the wallet_type property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_charge, + 'expected' => 'crypto', + ), + ); + } + + /** + * Test getting the stripe_cvc_check property. + * + * @dataProvider get_stripe_cvc_check_provider + * + * @param Payment_Gateway $gateway The payment gateway in use. + * @param mixed $data The data which contains the stripe_cvc_check value. + * @param null|string $expected The expected result if available. + * + * @return void + */ + public function test_get_stripe_cvc_check( Payment_Gateway $gateway, mixed $data, ?string $expected ) { + $result = Payment_Method::get_stripe_cvc_check( $gateway, $data ); + $this->assertEquals( $expected, $result, 'Should return the expected result' ); + } + + /** + * Provide data to the test_get_stripe_cvc_check test function. + * + * @return array An array of test runs and the data associated with each run. + */ + public function get_stripe_cvc_check_provider(): array { + $stripe_charge = (object) array( + 'payment_method_details' => build_mock_stripe_payment_method_object( array() ), + ); + $woocommerce_payments_charge = new WC_Payments_API_Charge( array() ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); + return array( + 'Stripe\'s object returns the stripe_cvc_check property' => array( + 'gateway' => $stripe_gateway, + 'data' => $stripe_charge, + 'expected' => 'OK', + ), + 'Transact\'s object does not return the stripe_cvc_check property' => array( + 'gateway' => $transact_gateway, + 'data' => $order, + 'expected' => '', + ), + 'WooCommerce Payments\'s object returns the stripe_cvc_check property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_charge, + 'expected' => 'OK', + ), + ); + } + + /** + * Test getting the stripe_address_line1_check property. + * + * @dataProvider get_stripe_address_line1_check_provider + * + * @param Payment_Gateway $gateway The payment gateway in use. + * @param mixed $data The data which contains the stripe_address_line1_check value. + * @param null|string $expected The expected result if available. + * + * @return void + */ + public function test_get_stripe_address_line1_check( Payment_Gateway $gateway, mixed $data, ?string $expected ) { + $result = Payment_Method::get_stripe_address_line1_check( $gateway, $data ); + $this->assertEquals( $expected, $result, 'Should return the expected result' ); + } + + /** + * Provide data to the test_get_stripe_address_line1_check test function. + * + * @return array An array of test runs and the data associated with each run. + */ + public function get_stripe_address_line1_check_provider(): array { + $stripe_charge = (object) array( + 'payment_method_details' => build_mock_stripe_payment_method_object( array() ), + ); + $woocommerce_payments_charge = new WC_Payments_API_Charge( array() ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); + return array( + 'Stripe\'s object returns the stripe_address_line1_check property' => array( + 'gateway' => $stripe_gateway, + 'data' => $stripe_charge, + 'expected' => 'OK', + ), + 'Transact\'s object does not return the stripe_address_line1_check property' => array( + 'gateway' => $transact_gateway, + 'data' => $order, + 'expected' => '', + ), + 'WooCommerce Payments\'s object returns the stripe_address_line1_check property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_charge, + 'expected' => 'OK', + ), + ); + } + + /** + * Test getting the stripe_address_zip_check property. + * + * @dataProvider get_stripe_address_zip_check_provider + * + * @param Payment_Gateway $gateway The payment gateway in use. + * @param mixed $data The data which contains the stripe_address_zip_check value. + * @param null|string $expected The expected result if available. + * + * @return void + */ + public function test_get_stripe_address_zip_check( Payment_Gateway $gateway, mixed $data, ?string $expected ) { + $result = Payment_Method::get_stripe_address_zip_check( $gateway, $data ); + $this->assertEquals( $expected, $result, 'Should return the expected result' ); + } + + /** + * Provide data to the test_get_stripe_address_zip_check test function. + * + * @return array An array of test runs and the data associated with each run. + */ + public function get_stripe_address_zip_check_provider(): array { + $stripe_charge = (object) array( + 'payment_method_details' => build_mock_stripe_payment_method_object( array() ), + ); + $woocommerce_payments_charge = new WC_Payments_API_Charge( array() ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); + return array( + 'Stripe\'s object returns the stripe_address_zip_check property' => array( + 'gateway' => $stripe_gateway, + 'data' => $stripe_charge, + 'expected' => 'OK', + ), + 'Transact\'s object does not return the stripe_address_zip_check property' => array( + 'gateway' => $transact_gateway, + 'data' => $order, + 'expected' => '', + ), + 'WooCommerce Payments\'s object returns the stripe_address_zip_check property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_charge, + 'expected' => 'OK', + ), + ); + } + + /** + * Test getting the stripe_funding property. + * + * @dataProvider get_stripe_funding_provider + * + * @param Payment_Gateway $gateway The payment gateway in use. + * @param mixed $data The data which contains the stripe_funding value. + * @param null|string $expected The expected result if available. + * + * @return void + */ + public function test_get_stripe_funding( Payment_Gateway $gateway, mixed $data, ?string $expected ) { + $result = Payment_Method::get_stripe_funding( $gateway, $data ); + $this->assertEquals( $expected, $result, 'Should return the expected result' ); + } + + /** + * Provide data to the test_get_stripe_funding test function. + * + * @return array An array of test runs and the data associated with each run. + */ + public function get_stripe_funding_provider(): array { + $stripe_charge = (object) array( + 'payment_method_details' => build_mock_stripe_payment_method_object( array() ), + ); + $woocommerce_payments_charge = new WC_Payments_API_Charge( array() ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); + return array( + 'Stripe\'s object returns the stripe_funding property' => array( + 'gateway' => $stripe_gateway, + 'data' => $stripe_charge, + 'expected' => 'card funding', + ), + 'Transact\'s object does not return the stripe_funding property' => array( + 'gateway' => $transact_gateway, + 'data' => $order, + 'expected' => '', + ), + 'WooCommerce Payments\'s object returns the stripe_funding property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_charge, + 'expected' => 'card funding', + ), + ); + } + + /** + * Test getting the stripe_brand property. + * + * @dataProvider get_stripe_brand_provider + * + * @param Payment_Gateway $gateway The payment gateway in use. + * @param mixed $data The data which contains the stripe_brand value. + * @param null|string $expected The expected result if available. + * + * @return void + */ + public function test_get_stripe_brand( Payment_Gateway $gateway, mixed $data, ?string $expected ) { + $result = Payment_Method::get_stripe_brand( $gateway, $data ); + $this->assertEquals( $expected, $result, 'Should return the expected result' ); + } + + /** + * Provide data to the test_get_stripe_brand test function. + * + * @return array An array of test runs and the data associated with each run. + */ + public function get_stripe_brand_provider(): array { + $stripe_charge = (object) array( + 'payment_method_details' => build_mock_stripe_payment_method_object( array() ), + ); + $woocommerce_payments_charge = new WC_Payments_API_Charge( array() ); + $order = new \WC_Order(); + $stripe_gateway = new Payment_Gateway( 'stripe', $order ); + $transact_gateway = new Payment_Gateway( 'transact', $order ); + $woocommerce_payments_gateway = new Payment_Gateway( 'woocommerce_payments', $order ); + return array( + 'Stripe\'s object returns the stripe_brand property' => array( + 'gateway' => $stripe_gateway, + 'data' => $stripe_charge, + 'expected' => 'FakeCard', + ), + 'Transact\'s object does not return the stripe_brand property' => array( + 'gateway' => $transact_gateway, + 'data' => $order, + 'expected' => '', + ), + 'WooCommerce Payments\'s object returns the stripe_brand property' => array( + 'gateway' => $woocommerce_payments_gateway, + 'data' => $woocommerce_payments_charge, + 'expected' => 'FakeCard', + ), ); } } diff --git a/tests/PaymentTypeTest.php b/tests/PaymentTypeTest.php index 71658b2..2c55d52 100644 --- a/tests/PaymentTypeTest.php +++ b/tests/PaymentTypeTest.php @@ -70,11 +70,11 @@ public function payment_type_provider(): array { 'is_valid' => true, 'sift_slug' => '$credit_card', ), - 'Transact\'s "sepa_debit" type is an invalid payment type' => array( + 'Transact\'s "sepa_debit" type is a valid payment type' => array( 'gateway' => $transact_gateway, 'payment_type' => 'sepa_debit', - 'is_valid' => false, - 'sift_slug' => null, + 'is_valid' => true, + 'sift_slug' => '$sepa_direct_debit', ), ); } diff --git a/tests/StripeLibTest.php b/tests/StripeLibTest.php new file mode 100644 index 0000000..d78f6b4 --- /dev/null +++ b/tests/StripeLibTest.php @@ -0,0 +1,152 @@ +assertEquals( $expected_sift_slug, $result, 'The expected result should be returned' ); + } + + /** + * Provide data to the test_convert_payment_method_to_sift_payment_gateway test. + * + * @return array + */ + public function convert_payment_method_to_sift_payment_gateway_provider(): array { + return array( + 'affirm is $affirm' => array( + 'payment_method' => 'affirm', + 'expected_sift_slug' => '$affirm', + ), + 'afterpay is $afterpay' => array( + 'payment_method' => 'afterpay', + 'expected_sift_slug' => '$afterpay', + ), + 'bancontact is $bancontact' => array( + 'payment_method' => 'bancontact', + 'expected_sift_slug' => '$bancontact', + ), + 'boleto is $boleto' => array( + 'payment_method' => 'boleto', + 'expected_sift_slug' => '$boleto', + ), + 'card is $stripe' => array( + 'payment_method' => 'card', + 'expected_sift_slug' => '$stripe', + ), + 'clearpay is $afterpay' => array( + 'payment_method' => 'clearpay', + 'expected_sift_slug' => '$afterpay', + ), + 'eps is $eps' => array( + 'payment_method' => 'eps', + 'expected_sift_slug' => '$eps', + ), + 'ideal is $ideal' => array( + 'payment_method' => 'ideal', + 'expected_sift_slug' => '$ideal', + ), + 'link is $stripe' => array( + 'payment_method' => 'link', + 'expected_sift_slug' => '$stripe', + ), + 'klarna is $klarna' => array( + 'payment_method' => 'klarna', + 'expected_sift_slug' => '$klarna', + ), + 'oxxo is $cash' => array( + 'payment_method' => 'oxxo', + 'expected_sift_slug' => '$cash', + ), + 'stripe_boleto is $boleto' => array( + 'payment_method' => 'stripe_boleto', + 'expected_sift_slug' => '$boleto', + ), + 'przelewy24 is $przelewy24' => array( + 'payment_method' => 'przelewy24', + 'expected_sift_slug' => '$przelewy24', + ), + 'p24 is $przelewy24' => array( + 'payment_method' => 'p24', + 'expected_sift_slug' => '$przelewy24', + ), + 'stripe_p24 is $przelewy24' => array( + 'payment_method' => 'stripe_p24', + 'expected_sift_slug' => '$przelewy24', + ), + 'fakepay does not exist' => array( + 'payment_method' => 'fakepay', + 'expected_sift_slug' => null, + ), + ); + } + + /** + * Test the convert_payment_type_to_sift_payment_type function. + * + * @dataProvider convert_payment_type_to_sift_payment_type_provider + * + * @param string $payment_type The payment type as the payment gateway plugin calls it. + * @param string|null $expected_sift_slug The expected sift-compatible slug. + * + * @return void + */ + public function test_convert_payment_type_to_sift_payment_type( string $payment_type, ?string $expected_sift_slug ) { + $result = Stripe::convert_payment_type_to_sift_payment_type( $payment_type ); + $this->assertEquals( $expected_sift_slug, $result, 'The expected result should be returned' ); + } + + /** + * Provide data to the test_convert_payment_type_to_sift_payment_type test. + * + * @return array + */ + public function convert_payment_type_to_sift_payment_type_provider(): array { + return array( + 'affirm is $financing' => array( + 'payment_type' => 'affirm', + 'expected_sift_slug' => '$financing', + ), + 'afterpay is $financing' => array( + 'payment_type' => 'afterpay', + 'expected_sift_slug' => '$financing', + ), + 'card is $credit_card' => array( + 'payment_type' => 'card', + 'expected_sift_slug' => '$credit_card', + ), + 'stripe_boleto is $voucher' => array( + 'payment_type' => 'stripe_boleto', + 'expected_sift_slug' => '$voucher', + ), + 'sepa_debit is $sepa_direct_debit' => array( + 'payment_type' => 'sepa_debit', + 'expected_sift_slug' => '$sepa_direct_debit', + ), + 'fakemethod does not exist' => array( + 'payment_method' => 'fakemethod', + 'expected_sift_slug' => null, + ), + ); + } +} diff --git a/tests/mocks/utils.php b/tests/mocks/utils.php new file mode 100644 index 0000000..dd4ed79 --- /dev/null +++ b/tests/mocks/utils.php @@ -0,0 +1,54 @@ + array( + 'last4' => $config['last4'] ?? '0000', + 'iin' => $config['iin'] ?? '000000', + 'checks' => $config['checks'] ?? array( + 'cvc_check' => 'OK', + 'address_line1_check' => 'OK', + 'address_postal_code_check' => 'OK', + ), + 'wallet' => array( + 'type' => 'crypto', + ), + 'funding' => 'card funding', + 'brand' => 'FakeCard', + ), + 'sepa_debit' => array( + 'mandate' => 'sepa direct debit mandate code', + ), + ); + } + return (object) array( + 'card' => (object) array( + 'last4' => $config['last4'] ?? '0000', + 'iin' => $config['iin'] ?? '000000', + 'checks' => $config['checks'] ?? (object) array( + 'cvc_check' => 'OK', + 'address_line1_check' => 'OK', + 'address_postal_code_check' => 'OK', + ), + 'wallet' => (object) array( + 'type' => 'crypto', + ), + 'funding' => 'card funding', + 'brand' => 'FakeCard', + ), + 'sepa_debit' => (object) array( + 'mandate' => 'sepa direct debit mandate code', + ), + ); +} diff --git a/tests/mocks/wc-payments-api-charge-mock.php b/tests/mocks/wc-payments-api-charge-mock.php new file mode 100644 index 0000000..5efda02 --- /dev/null +++ b/tests/mocks/wc-payments-api-charge-mock.php @@ -0,0 +1,33 @@ +config = $config; + } + + /** + * Mock get_payment_method_details function which returns a built stripe-api-shaped array. + * + * @return array An array representing a result from the Stripe API. + */ + public function get_payment_method_details(): array { + return build_mock_stripe_payment_method_object( $this->config, true ); + } +}