| @@ -8,9 +8,11 @@ | ||
| 8 | 8 | namespace WCPOS\WooCommercePOS\Payments; |
| 9 | 9 | |
| 10 | 10 | \defined( 'ABSPATH' ) || die; |
| 11 | 11 | |
| 12 | +use WC_Order; | |
| 12 | 13 | use WC_Payment_Gateway; |
| 14 | +use WP_Error; | |
| 13 | 15 | use WP_REST_Request; |
| 14 | 16 | |
| 15 | 17 | /** |
| 16 | 18 | * Shared helper for the POS payment-gateway contract. |
| @@ -16,13 +18,8 @@ | ||
| 16 | 18 | * Shared helper for the POS payment-gateway contract. |
| 17 | 19 | */ |
| 18 | 20 | class Gateway_Contract { |
| 19 | 21 | /** |
| 20 | - * Built-in gateways with manual POS handling. | |
| 21 | - */ | |
| 22 | - private const MANUAL_GATEWAYS = array( 'pos_cash', 'pos_card' ); | |
| 23 | - | |
| 24 | - /** | |
| 25 | 22 | * Infer POS type for a gateway. |
| 26 | 23 | * |
| 27 | 24 | * @param WC_Payment_Gateway $gateway Gateway object. |
| 28 | 25 | * @param WP_REST_Request $request Request object. |
| @@ -27,11 +24,9 @@ | ||
| 27 | 24 | * @param WC_Payment_Gateway $gateway Gateway object. |
| 28 | 25 | * @param WP_REST_Request $request Request object. |
| 29 | 26 | */ |
| 30 | 27 | public function infer_pos_type( WC_Payment_Gateway $gateway, WP_REST_Request $request ): string { |
| 31 | - $default = in_array( $gateway->id, self::MANUAL_GATEWAYS, true ) ? 'manual' : 'manual'; | |
| 32 | - | |
| 33 | - return (string) apply_filters( 'wcpos_payment_gateway_pos_type', $default, $gateway, $request ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Public POS gateway contract filter. | |
| 28 | + return $this->get_adapter( $gateway )->get_pos_type( $request ); | |
| 34 | 29 | } |
| 35 | 30 | |
| 36 | 31 | /** |
| 37 | 32 | * Provider family identifier. |
| @@ -39,9 +34,9 @@ | ||
| 39 | 34 | * @param WC_Payment_Gateway $gateway Gateway object. |
| 40 | 35 | * @param WP_REST_Request $request Request object. |
| 41 | 36 | */ |
| 42 | 37 | public function get_provider( WC_Payment_Gateway $gateway, WP_REST_Request $request ): string { |
| 43 | - return (string) apply_filters( 'wcpos_payment_gateway_provider', $gateway->id, $gateway, $request ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Public POS gateway contract filter. | |
| 38 | + return $this->get_adapter( $gateway )->get_pos_provider( $request ); | |
| 44 | 39 | } |
| 45 | 40 | |
| 46 | 41 | /** |
| 47 | 42 | * Provider-specific public metadata. |
| @@ -49,9 +44,9 @@ | ||
| 49 | 44 | * @param WC_Payment_Gateway $gateway Gateway object. |
| 50 | 45 | * @param WP_REST_Request $request Request object. |
| 51 | 46 | */ |
| 52 | 47 | public function get_provider_data( WC_Payment_Gateway $gateway, WP_REST_Request $request ): array { |
| 53 | - return (array) apply_filters( 'wcpos_payment_gateway_provider_data', array(), $gateway, $request ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Public POS gateway contract filter. | |
| 48 | + return $this->get_adapter( $gateway )->get_pos_provider_data( $request ); | |
| 54 | 49 | } |
| 55 | 50 | |
| 56 | 51 | /** |
| 57 | 52 | * Whether a gateway is enabled for POS. |
| @@ -76,11 +71,9 @@ | ||
| 76 | 71 | * @param WC_Payment_Gateway $gateway Gateway object. |
| 77 | 72 | * @param WP_REST_Request $request Request object. |
| 78 | 73 | */ |
| 79 | 74 | public function supports_checkout( WC_Payment_Gateway $gateway, WP_REST_Request $request ): bool { |
| 80 | - $has_handler = false !== has_action( 'wcpos_process_checkout_action_' . $gateway->id ); | |
| 81 | - | |
| 82 | - return (bool) apply_filters( 'wcpos_payment_gateway_supports_checkout', $has_handler, $gateway, $request ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Public POS gateway contract filter. | |
| 75 | + return $this->get_adapter( $gateway )->supports_pos_checkout( $request ); | |
| 83 | 76 | } |
| 84 | 77 | |
| 85 | 78 | /** |
| 86 | 79 | * Capabilities exposed to the POS app. |
| @@ -88,15 +81,15 @@ | ||
| 88 | 81 | * @param WC_Payment_Gateway $gateway Gateway object. |
| 89 | 82 | * @param WP_REST_Request $request Request object. |
| 90 | 83 | */ |
| 91 | 84 | public function get_capabilities( WC_Payment_Gateway $gateway, WP_REST_Request $request ): array { |
| 92 | - $pos_type = $this->infer_pos_type( $gateway, $request ); | |
| 93 | - $supports_provider_refunds = ! in_array( $gateway->id, self::MANUAL_GATEWAYS, true ) && $gateway->supports( 'refunds' ); | |
| 85 | + $adapter = $this->get_adapter( $gateway ); | |
| 86 | + $pos_type = $adapter->get_pos_type( $request ); | |
| 94 | 87 | |
| 95 | 88 | return array( |
| 96 | - 'supports_checkout' => $this->supports_checkout( $gateway, $request ), | |
| 97 | - 'supports_automatic_refunds' => (bool) apply_filters( 'wcpos_payment_gateway_supports_automatic_refunds', $supports_provider_refunds, $gateway, $request ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Public POS gateway contract filter. | |
| 98 | - 'supports_provider_refunds' => (bool) apply_filters( 'wcpos_payment_gateway_supports_provider_refunds', $supports_provider_refunds, $gateway, $request ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Public POS gateway contract filter. | |
| 89 | + 'supports_checkout' => $adapter->supports_pos_checkout( $request ), | |
| 90 | + 'supports_automatic_refunds' => $adapter->supports_pos_automatic_refunds( $request ), | |
| 91 | + 'supports_provider_refunds' => $adapter->supports_pos_provider_refunds( $request ), | |
| 99 | 92 | 'requires_hardware' => 'terminal' === $pos_type, |
| 100 | 93 | ); |
| 101 | 94 | } |
| 102 | 95 | |
| @@ -102,13 +95,22 @@ | ||
| 102 | 95 | |
| 103 | 96 | /** |
| 104 | 97 | * Default bootstrap response. |
| 105 | 98 | * |
| 106 | - * @param string $gateway_id Gateway ID. | |
| 107 | - * @param array $context Bootstrap context. | |
| 108 | - * @param WP_REST_Request $request Request object. | |
| 99 | + * The optional gateway parameter allows direct PHP adapters to provide the | |
| 100 | + * response while preserving the existing public method signature for callers | |
| 101 | + * that only have a gateway ID and depend on the legacy filter contract. | |
| 102 | + * | |
| 103 | + * @param string $gateway_id Gateway ID. | |
| 104 | + * @param array $context Bootstrap context. | |
| 105 | + * @param WP_REST_Request $request Request object. | |
| 106 | + * @param WC_Payment_Gateway|null $gateway Gateway object. | |
| 109 | 107 | */ |
| 110 | - public function get_bootstrap_response( string $gateway_id, array $context, WP_REST_Request $request ): array { | |
| 108 | + public function get_bootstrap_response( string $gateway_id, array $context, WP_REST_Request $request, ?WC_Payment_Gateway $gateway = null ): array { | |
| 109 | + if ( $gateway instanceof WC_Payment_Gateway ) { | |
| 110 | + return $this->get_adapter( $gateway )->get_pos_bootstrap_response( $context, $request ); | |
| 111 | + } | |
| 112 | + | |
| 111 | 113 | // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Public POS gateway contract filter. |
| 112 | 114 | return (array) apply_filters( |
| 113 | 115 | 'wcpos_payment_gateway_bootstrap', |
| 114 | 116 | array( |
| @@ -124,8 +126,33 @@ | ||
| 124 | 126 | // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound |
| 125 | 127 | } |
| 126 | 128 | |
| 127 | 129 | /** |
| 130 | + * Process a POS checkout action through the gateway adapter. | |
| 131 | + * | |
| 132 | + * @param WC_Payment_Gateway $gateway Gateway object. | |
| 133 | + * @param int $order_id Order ID. | |
| 134 | + * @param string $action Checkout action. | |
| 135 | + * @param array $payment_data Payment data. | |
| 136 | + * @param WC_Order $order Order object. | |
| 137 | + * @param WP_REST_Request $request Request object. | |
| 138 | + * | |
| 139 | + * @return array|WP_Error | |
| 140 | + */ | |
| 141 | + public function process_checkout_action( WC_Payment_Gateway $gateway, int $order_id, string $action, array $payment_data, WC_Order $order, WP_REST_Request $request ) { | |
| 142 | + $state = array( | |
| 143 | + 'checkout_id' => wp_generate_uuid4(), | |
| 144 | + 'order_id' => $order_id, | |
| 145 | + 'gateway_id' => $gateway->id, | |
| 146 | + 'status' => 'processing', | |
| 147 | + 'provider_data' => array(), | |
| 148 | + 'terminal' => false, | |
| 149 | + ); | |
| 150 | + | |
| 151 | + return $this->get_adapter( $gateway )->process_pos_checkout_action( $state, $action, $payment_data, $order, $request ); | |
| 152 | + } | |
| 153 | + | |
| 154 | + /** | |
| 128 | 155 | * Whether a checkout status is terminal. |
| 129 | 156 | * |
| 130 | 157 | * @param string $status Checkout status. |
| 131 | 158 | */ |
| @@ -130,6 +157,15 @@ | ||
| 130 | 157 | * @param string $status Checkout status. |
| 131 | 158 | */ |
| 132 | 159 | public function is_terminal_status( string $status ): bool { |
| 133 | 160 | return in_array( $status, array( 'completed', 'failed', 'cancelled', 'awaiting_customer' ), true ); |
| 161 | + } | |
| 162 | + | |
| 163 | + /** | |
| 164 | + * Wrap a WooCommerce gateway with the POS adapter shim. | |
| 165 | + * | |
| 166 | + * @param WC_Payment_Gateway $gateway Gateway object. | |
| 167 | + */ | |
| 168 | + private function get_adapter( WC_Payment_Gateway $gateway ): Gateway_Adapter_Interface { | |
| 169 | + return new Filter_Gateway_Adapter( $gateway ); | |
| 134 | 170 | } |
| 135 | 171 | } |