Closed remcotolsma closed 2 years ago
Sounds like a good enhancement. First thoughts:
$supported
parameter makes sense if payment methods are registered this way?$active
parameter here. We might want do something different for the 'active' part, as we probably also want to be able to determine that based on other parameters (country, currency, etc.). Also, it would be convenient if payment methods can just be registered as in the Bancontact example without parameters:
$this->register_payment_method( new PaymentMethodBancontact() );
ideal-issuer
field differ by gateway.
- I don't think the
$supported
parameter makes sense if payment methods are registered this way?
It might be useful to register unsupported payment methods. In the UI we can inform users about unsupported payment methods.
- I'm not sure if we should include an $active parameter here.
Good point, maybe this is a better approach?
// ...
$gateway->can_process_payment( $payment );
// ...
class Gateway {
// ...
public function can_process_payment( Payment $payment ) {
$method = $payment->get_method();
// check if method is supported?
// check if method is active at payment provider?
// check if amount is sufficient?
// check country / currency / etc.
}
}
- A field should be able to somehow have access to the gateway, as for example the issuer options for an ideal-issuer field differ by gateway.
Yes, i agree. A gateway integration could extend the default iDEAL issuer field:
class IDealIssuerField extends CoreIDealIssuerField {
public function __construct( $gateway ) {
$this->gateway = $gateway;
}
public function get_options() {
// Request iDEAL issuer via `$gateway`?
}
}
Thats requires gateway integrations to register their own iDEAL issuer field.
We could also transform the core iDEAL issuers options to the gateway / provider corresponding iDEAL issuer value. Downside of that is that we no longer have a dynamic iDEAL issuers list that is updated automatically.
Or we could implement a callback in the PaymentMethodIDeal
or IDealIsseurField
class to retrieve the options / issuers:
$this->register_payment_method( new PaymentMethodIDeal( $callback = function() use( $gateway ) {
// Request iDEAL issuer via `$gateway`?
} ) );
It might be useful to register unsupported payment methods. In the UI we can inform users about unsupported payment methods.
👍
Good point, maybe this is a better approach?
Yes, $gateway->can_process_payment( $payment );
is a better fit.
A gateway integration could extend the default iDEAL issuer field [...]
That seems the best approach to me. Loosing the dynamic lists is not an option.
$this->register_payment_method( new PaymentMethod( 'ideal', 'iDEAL', $supported = true, $active = true, $fields = array( Fields::get( 'ideal-issueur' ) ) ) );
For some gateways the iDEAL bank / issuer is required to start a payment, other gateways will ask customers to choose the bank / issuer in their environment. Therefore it is probably not useful to reuse the iDEAL issuer field over different gateways.
$ideal_issuer_field = new IDealIsseurField();
$ideal_issuer_field->set_required( true );
$payment_method_ideal = new PaymentMethod( 'ideal', 'iDEAL' );
$payment_method_ideal->set_supported( true );
$payment_method_ideal->add_field( $ideal_issuer_field );
https://www.digiwallet.nl/nl/documentation/paymethods/directdebit#startapi
$iban_field = new IBANField();
$iban_field->set_required( true );
$name_field = new NameField();
$name_field->set_required( true );
$payment_method_direct_debit = new PaymentMethod( 'direct_debit', 'Direct Debit' );
$payment_method_direct_debit->set_supported( true );
$payment_method_direct_debit->add_field( $iban_field );
$payment_method_direct_debit->add_field( $name_field );
In WooCommerce we can change this to something like:
$payment_method = $gateway->get_payment_method( $this->payment_method );
$fields = $payment_method->get_fields();
In the test meta box we can iterate over all the available payment methods.
foreach ( $gateway->get_payment_methods() as $payment_method ) {
foreach ( $payment_method->get_fields() as $field ) {
// render field
}
}
With some JavaScript / AlpineJS magic we can show only the fields for the selected payment method.
For forms plugins like Gravity Forms it's harder to make sure we retrieve all the required input.
Related issue/PR, which would benefit from improved payment method registration:
Currently we have the following fields:
Gender:
PaymentMethods::AFTERPAY_NL
PaymentMethods::FOCUM
PaymentMethods::IN3
PaymentMethods::KLARNA_PAY_LATER
PaymentMethods::SPRAYPAY
Date of birth:
PaymentMethods::AFTERPAY_NL
PaymentMethods::FOCUM
PaymentMethods::IN3
PaymentMethods::KLARNA_PAY_LATER
PaymentMethods::SPRAYPAY
Consumer bank details name:
PaymentMethods::DIRECT_DEBIT
Consumer bank details IBAN:
PaymentMethods::DIRECT_DEBIT
Issuer iDEAL
PaymentMethods::IDEAL
Issuer credit card
PaymentMethods::CREDITCARD
I removed the $gateway->get_issuer_field()
method in https://github.com/pronamic/wp-pay-core/commit/f8a263781d3a4f72bd9d793ed615f0df232352a9. This method is however still in use in Gravity Forms and Formidable Forms:
To-do:
$gateway->get_issuer_field()
usage in Gravity Forms$gateway->get_issuer_field()
usage in Formidable FormsWe should not forget that PaymentMethods::DIRECT_DEBIT_BANCONTACT
, PaymentMethods::DIRECT_DEBIT_IDEAL
and PaymentMethods::DIRECT_DEBIT_SOFORT
may also require fields. For PaymentMethods::DIRECT_DEBIT_IDEAL
we want to display the iDEAL issuers (banks).
PaymentMethods::get_first_payment_method( $payment_method )
in https://github.com/pronamic/wp-pay-core/commit/96df9ba5507e1c28163551b6021e7507fed8c32f.$gateway->get_input_fields()
.$gateway->get_payment_method()
.$gateway->set_payment_method( $payment_method )
.$gateway->get_input_html()
.$gateway->get_issuers()
.$gateway->get_transient_issuers()
.$gateway->payment_method_is_required()
.$gateway->get_payment_method_field_options( $other_first = false )
$gateway->get_supported_payment_methods()
In SelectField
we need better support for <optgroup>
:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/add
Not all supported extensions have support for <optgroup>
.
We need a way to flat <optgroup>
to just a flat list of options.
In https://github.com/pronamic/wp-pay-core/commit/f21d102f70f2dba6c7ed0b77631041017350944b we removed the phone number field from the test meta box. We have to figure out how we handle checkout fields like a phone number. Payment methods like AfterPay.nl often also require a complete shipping and billing address. Perhaps we should extend the test meta box to a full-fledged checkout form such as WooCommerce. For example, for the AfterPay.nl payment method, we may have to indicate that the fields 'shipping address' and 'billing address' are required, but leave the display and handling of these fields to the extensions. Also see:
I think discussed before my holiday with @rvdsteege, but could not find any information about this. We could add a $gateway->get_payment_methods( $query_args )
parameter.
That allows us to 'query' for example only the payment methods with the status active
:
$payment_methods = $gateway->get_payment_methods( [
'status' => 'active',
] );
$payment_methods = $gateway->get_payment_methods( [
'status' => 'active',
'cache_results' => false,
] );
Something similar might also come in handy within the fields:
$fields = $payment_method->get_fields( [
'class' => IdealIssuerField::class,
] );
https://github.com/pronamic/wp-pay-core/commit/93b251b657dd38d5a8e965efa401914644d9c81c
I think discussed before my holiday with @rvdsteege, but could not find any information about this.
Found it in https://github.com/pronamic/wp-pronamic-pay-private/issues/8.
For next week we have still a few things to-do:
Fields
namespace?$gateway->get_input_html()
.$gateway->get_payment_method_field_options( $other_first = false )
.VOID
payment method.Config
classes JSON serializable for cache key.SelectField
options lazy loadable more abstract set_options_callback
), Traversable
→ IteratorAggregate
.Match fields with https://wordpress.github.io/gutenberg/?path=/story/components-selectcontrol--default naming?
We stick to term field
instead of control
, we define the required fields, the term control
is more UI related.
IDealIssuerSelectField
class, just use general SelectField
class?$_POST
handled?Add support for fields processing / handling, how is input via $_POST handled?
For the iDEAL issuer this is currently handled in: Plugin:: complement_payment( Payment $payment )
.
https://github.com/pronamic/wp-pay-core/blob/046ed470ff0966419fda8ae663a9630b95b0c70a/src/Plugin.php#L932-L951
We should no longer use the filter_has_var()
and filter_input()
functions, but using the super global $_POST
is also not handy. Some extensions may store the post data in another variable, see for example: https://github.com/pronamic/wp-pronamic-pay-restrict-content-pro/blob/8ec4a2aae1c446bb2c9fc271f351d219b58c9121/src/Util.php#L60-L67.
In Restrict Content Pro:
$payment->post_data = $gateway->subscription_data['post_data'];
in core:
$payment->post_data = $_POST;
also in core:
Plugin::process_payment_post_data( $payment ) {
$gateway = $payment->get_gateway();
if ( null === $gateway ) {
return;
}
$payment_method = $gateway->get_payment_method( $payment->get_payment_method() );
if ( null === $payment_method ) {
return;
}
foreach ( $payment_method->get_fields() as $field ) {
if ( array_key_exists( $field->get_id(), $payment->post_data ) ) {
// ?
}
}
}
I think we are done, the items from https://github.com/pronamic/wp-pronamic-pay/issues/154#issuecomment-1222428469 are included on following issue:
Some gateways and payment methods require extra input from the customer. For example: iDEAL payment method requires sometimes an iDEAL issuer / bank and AfterPay often requires a birth date and gender. In this core library we have support for input fields. There is however room for improvement so we can write code more according to the DRY principle. Some gateways / payment methods require the same input. In our internal Basecamp project we also have a to-do open to this:
I think we need a global place where can define 'checkout fields'. In this core library we can define the most common used 'checkout fields' like:
Also see:
https://github.com/woocommerce/woocommerce/blob/4.7.0/includes/class-wc-checkout.php#L197-L281
https://github.com/woocommerce/woocommerce/blob/4.7.0/includes/abstracts/abstract-wc-payment-gateway.php#L392-L405
For each gateway / payment method we must be able to indicate what input is required. As soon as an extension does not provide the required data, we can show an intermediate screen in which the missing data is requested. Similar to how, for example, OmniKassa 2.0 does this:
We might need to extend the way we define which payment methods are supported by the gateways in
get_supported_payment_methods()
:That way we can also only show the input fields in the test meta box that are required for the chosen payment method.
This requires some thought.