id, $args = array() ) { // Check for 0, false, null and other empty values. if ( empty( $config_id ) ) { return null; } $config_id = intval( $config_id ); // Check if config is trashed. if ( 'trash' === get_post_status( $config_id ) ) { return null; } // Arguments. $args = wp_parse_args( $args, array( 'gateway_id' => get_post_meta( $config_id, '_pronamic_gateway_id', true ), 'mode' => get_post_meta( $config_id, '_pronamic_gateway_mode', true ), ) ); // Get config. $gateway_id = $args['gateway_id']; $mode = $args['mode']; $integration = pronamic_pay_plugin()->gateway_integrations->get_integration( $gateway_id ); if ( null === $integration ) { return null; } $gateway = $integration->get_gateway( $config_id ); return $gateway; } /** * Complement payment. * * @param Payment $payment Payment. * @return void */ private static function complement_payment( Payment $payment ) { // Entrance Code. if ( null === $payment->entrance_code ) { $payment->entrance_code = uniqid(); } // Key. if ( null === $payment->key ) { $payment->key = uniqid( 'pay_' ); } // User ID. if ( null === $payment->user_id && is_user_logged_in() ) { $payment->user_id = get_current_user_id(); } $origin_id = $payment->get_origin_id(); if ( null === $origin_id ) { // Queried object. $queried_object = \get_queried_object(); $queried_object_id = \get_queried_object_id(); if ( null !== $queried_object && $queried_object_id > 0 ) { $origin_id = $queried_object_id; } // Referer. $referer = \wp_get_referer(); if ( null === $origin_id && false !== $referer ) { $post_id = \url_to_postid( $referer ); if ( $post_id > 0 ) { $origin_id = $post_id; } } // Set origin ID. $payment->set_origin_id( $origin_id ); } // Google Analytics client ID. if ( null === $payment->analytics_client_id ) { $payment->analytics_client_id = GoogleAnalyticsEcommerce::get_cookie_client_id(); } // Customer. $customer = $payment->get_customer(); if ( null === $customer ) { $customer = new Customer(); $payment->set_customer( $customer ); } CustomerHelper::complement_customer( $customer ); // Email. if ( null === $payment->get_email() ) { $payment->email = $customer->get_email(); } // Billing address. $billing_address = $payment->get_billing_address(); if ( null !== $billing_address ) { AddressHelper::complement_address( $billing_address ); } // Shipping address. $shipping_address = $payment->get_shipping_address(); if ( null !== $shipping_address ) { AddressHelper::complement_address( $shipping_address ); } // Version. if ( null === $payment->get_version() ) { $payment->set_version( pronamic_pay_plugin()->get_version() ); } // Mode. $config_id = $payment->get_config_id(); if ( null === $payment->get_mode() && null !== $config_id ) { $mode = get_post_meta( $config_id, '_pronamic_gateway_mode', true ); $payment->set_mode( $mode ); } // Issuer. if ( null === $payment->issuer ) { // Credit card. if ( PaymentMethods::CREDIT_CARD === $payment->method && filter_has_var( INPUT_POST, 'pronamic_credit_card_issuer_id' ) ) { $payment->issuer = filter_input( INPUT_POST, 'pronamic_credit_card_issuer_id', FILTER_SANITIZE_STRING ); } // iDEAL. $ideal_methods = array( PaymentMethods::IDEAL, PaymentMethods::DIRECT_DEBIT_IDEAL ); if ( \in_array( $payment->method, $ideal_methods, true ) && filter_has_var( INPUT_POST, 'pronamic_ideal_issuer_id' ) ) { $payment->issuer = filter_input( INPUT_POST, 'pronamic_ideal_issuer_id', FILTER_SANITIZE_STRING ); } } /** * If an issuer has been specified and the payment * method is unknown, we set the payment method to * iDEAL. This may not be correct in all cases, * but for now Pronamic Pay works this way. * * @link https://github.com/wp-pay-extensions/gravityforms/blob/2.4.0/src/Processor.php#L251-L256 * @link https://github.com/wp-pay-extensions/contact-form-7/blob/1.0.0/src/Pronamic.php#L181-L187 * @link https://github.com/wp-pay-extensions/formidable-forms/blob/2.1.0/src/Extension.php#L318-L329 * @link https://github.com/wp-pay-extensions/ninjaforms/blob/1.2.0/src/PaymentGateway.php#L80-L83 * @link https://github.com/wp-pay/core/blob/2.4.0/src/Forms/FormProcessor.php#L131-L134 */ if ( null !== $payment->issuer && null === $payment->method ) { $payment->method = PaymentMethods::IDEAL; } // Consumer bank details. $consumer_bank_details = $payment->get_consumer_bank_details(); if ( null === $consumer_bank_details ) { $consumer_bank_details = new BankAccountDetails(); } if ( null === $consumer_bank_details->get_name() && filter_has_var( INPUT_POST, 'pronamic_pay_consumer_bank_details_name' ) ) { $consumer_bank_details->set_name( filter_input( INPUT_POST, 'pronamic_pay_consumer_bank_details_name', FILTER_SANITIZE_STRING ) ); } if ( null === $consumer_bank_details->get_iban() && filter_has_var( INPUT_POST, 'pronamic_pay_consumer_bank_details_iban' ) ) { $consumer_bank_details->set_iban( filter_input( INPUT_POST, 'pronamic_pay_consumer_bank_details_iban', FILTER_SANITIZE_STRING ) ); } $payment->set_consumer_bank_details( $consumer_bank_details ); // Payment lines payment. $lines = $payment->get_lines(); if ( null !== $lines ) { foreach ( $lines as $line ) { $line->set_payment( $payment ); } } } /** * Start payment. * * @param Payment $payment The payment to start at the specified gateway. * @param Gateway $gateway The gateway to start the payment at. * * @return Payment * * @throws \Exception Throws exception if gateway payment start fails. */ public static function start_payment( Payment $payment, $gateway = null ) { global $pronamic_ideal; // Complement payment. self::complement_payment( $payment ); /** * Filters the payment gateway configuration ID. * * @param int $configuration_id Gateway configuration ID. * @param Payment $payment The payment resource data. */ $config_id = \apply_filters( 'pronamic_payment_gateway_configuration_id', $payment->get_config_id(), $payment ); $payment->set_config_id( $config_id ); // Create payment. $pronamic_ideal->payments_data_store->create( $payment ); // Prevent payment start at gateway if amount is empty. $amount = $payment->get_total_amount()->get_value(); if ( empty( $amount ) ) { $payment->set_status( PaymentStatus::SUCCESS ); $payment->save(); /** * Return or throw exception? * * @link https://github.com/wp-pay/core/commit/aa6422f0963d9718edd11ac41edbadfd6cd07d49 * @todo Throw exception? */ return $payment; } // Gateway. $gateway = self::get_gateway( $payment->get_config_id() ); if ( null === $gateway ) { $payment->set_status( PaymentStatus::FAILURE ); $payment->save(); return $payment; } // Recurring. if ( true === $payment->get_recurring() && ! $gateway->supports( 'recurring' ) ) { throw new \Exception( 'Gateway does not support recurring payments.' ); } // Start payment at the gateway. try { $gateway->start( $payment ); // Add gateway errors as payment notes. $error = $gateway->get_error(); if ( $error instanceof \WP_Error ) { $message = $error->get_error_message(); $code = $error->get_error_code(); if ( ! \is_int( $code ) ) { $message = sprintf( '%s: %s', $code, $message ); $code = 0; } throw new \Exception( $message, $code ); } } catch ( \Exception $error ) { $message = $error->getMessage(); // Maybe include error code in message. $code = $error->getCode(); if ( $code > 0 ) { $message = \sprintf( '%s: %s', $code, $message ); } // Add note. $payment->add_note( $message ); // Set payment status. $payment->set_status( PaymentStatus::FAILURE ); } // Save payment. $payment->save(); // Schedule payment status check. if ( $gateway->supports( 'payment_status_request' ) ) { StatusChecker::schedule_event( $payment ); } // Throw/rethrow exception. if ( $error instanceof \Exception ) { throw $error; } return $payment; } /** * Get pages. * * @return array */ public function get_pages() { $return = array(); $pages = array( 'completed' => __( 'Completed', 'pronamic_ideal' ), 'cancel' => __( 'Canceled', 'pronamic_ideal' ), 'expired' => __( 'Expired', 'pronamic_ideal' ), 'error' => __( 'Error', 'pronamic_ideal' ), 'unknown' => __( 'Unknown', 'pronamic_ideal' ), ); foreach ( $pages as $key => $label ) { $id = sprintf( 'pronamic_pay_%s_page_id', $key ); $return[ $id ] = $label; } return $return; } /** * Payment redirect URL. * * @param string $url Redirect URL. * @param Payment $payment Payment. * @return string */ public function payment_redirect_url( $url, Payment $payment ) { $url = \apply_filters( 'pronamic_payment_redirect_url_' . $payment->get_source(), $url, $payment ); return $url; } /** * Is debug mode. * * @link https://github.com/easydigitaldownloads/easy-digital-downloads/blob/2.9.26/includes/misc-functions.php#L26-L38 * @return bool True if debug mode is enabled, false otherwise. */ public function is_debug_mode() { $value = \get_option( 'pronamic_pay_debug_mode', false ); if ( PRONAMIC_PAY_DEBUG ) { $value = true; } return (bool) $value; } }