wp-pronamic-pay
wp-pronamic-pay copied to clipboard
Empty payment amount `!=` payment status success
Currently we give all payments with an empty (€ 0
) amount the status success and return early so the payment is not started at the gateway: https://github.com/pronamic/wp-pay-core/blob/develop/src/Plugin.php#L1025-L1045.
This seems less convenient because subscriptions may include a free first period (trial), but with some payment methods / gateways a minimum payment is required to obtain a mandate.
This is the case for a recurring direct debit payment where a mandate is obtained via a first iDEAL payment. Certain gateways must have the chance to throw an exception in that case.


It would be great if the Mollie gateway could throw an exception in case of an € 0
payment for the 'Direct Debit mandate via iDEAL payment method' (DIRECT_DEBIT_IDEAL
).
https://help.mollie.com/hc/nl/articles/214072489-Hoe-verkrijg-ik-een-mandaat-van-mijn-klant-customer-voor-Recurring-
I also noted a $maybe_tokenize
variable introduced in https://github.com/pronamic/wp-pay-core/commit/8d90f0dba9f3c6ac0d95bf28ffe6598168b54dca that may also be related to this.
Internal HelpScout ticket: https://secure.helpscout.net/conversation/1604745461/22551?folderId=1425710
I agree we need to improve on this. We'll be able to set payment method constraints (like minimum amount) with the updated Payment Methods API, which will resolve this issue.
- https://github.com/pronamic/wp-pronamic-pay/issues/154
Further investigation shows that subscriptions for MemberPress memberships with an invalid initial amount for DIRECT_DEBIT_IDEAL
are already impossible to start and result in a gateway error "The amount is lower than the minimum". The status of the first payment gets updated to Failed.

In the past, if the first payment failed, the subscription status was updated to Cancelled to prevent unintended reactivation of subscription (if a mandate would become available at a later time, for example if a new subscription had been started successfully by the same user). It seems this has been removed some time ago:
- https://github.com/pronamic/wp-pay-core/commit/b26ec8237bb0df23c5ea3153c0e1ca382d2667d4
Therefore, recurring payments are still created for these failed subscriptions and the recurring payments result in the "No suitable mandates found for customer" error. For a failed first payment, the subscription should be canceled or put on hold to prevent further payments for the invalid subscription. The error about the required minimum amount should already be sufficient to prevent creating invalid subscriptions, as we can assume this error will be noticed by users during setup testing.
Thoughts, @remcotolsma?
I think we should no longer create follow-up payments for subscriptions that have the subscr_failed
status:
https://github.com/pronamic/wp-pay-core/blob/develop/src/Subscriptions/SubscriptionsModule.php#L1091-L1093
In the case of a failed direct debit payment, Mollie almost always advises you to contact the customer:
MS03 is used for other reasons. MS03 can sometimes be the result of reasons that already have another reason code, such as insufficient funds. We recommend you to contact the consumer when you see code MS03.
https://help.mollie.com/hc/en-us/articles/115000309865-Why-did-my-direct-debit-payment-fail-
It therefore does not seem desirable to me to initiate follow-up payments if something went wrong earlier.
A problem can also arise when starting the follow-up payment with the payment provider:
https://docs.mollie.com/overview/handling-errors
You do not want the follow-up payments to be stopped completely with for example the following errors:
Status Code | Description |
---|---|
401 |
Unauthorized – Your request was not executed due to failed authentication. Check your API key. |
429 |
Too Many Requests – Your request has hit a rate limit. Please wait for a bit and retry. |
500 |
Internal Server Error – An internal server error occurred while processing your request. Our developers are notified automatically, but if you have any information on how you triggered the problem, please contact us. |
502 |
Bad Gateway – The service is temporarily unavailable, either due to calamity or (planned) maintenance. Please retry the request at a later time. |
503 |
Service Unavailable – The service is temporarily unavailable, either due to calamity or (planned) maintenance. Please retry the request at a later time. |
504 |
Gateway Timeout – Your request is causing an unusually long process time. |
The follow-up payments that could not be started could be put in a queue.
We could change https://github.com/wp-pay-gateways/mollie/blob/c17db2ffa9f9c14cf0b1ff6871c35f10bd1fa232/src/Gateway.php#L455-L456 to something like this:
try {
$result = $this->client->create_payment( $request );
} catch { Exception $e ) {
if ( ! $payment->is_interactive() ) {
// Increase number attempts and add payment to retry queue.
return;
}
throw $e;
}
Don't know if is_interactive
is the right term, maybe is_recurring
or needs_no_interaction
.
But for now i think the easiest thing to do is take out subscr_failed
. status and implement a retry queue later.
Asynchronous payment flows are complex to manage because they depend on customer interactions that happen outside of your application.
https://stripe.com/docs/payments/intents#intent-statuses
I checked how Gravity Forms handles an empty amount (0
) by default:
https://github.com/wp-premium/gravityforms/blob/2.4.20/includes/addon/class-gf-payment-addon.php#L663-L700
By default a payment amount is valid when the amount is greater than zero. Currently we bypass this check and also start a payment for an empty amount (0
). For a creditcard subscription payment via Mollie this is desired.
It is possible to initiate a payment via conditional logic only if the amount is greater than 0. However, for this you need to add a hidden number field with a calculation that can be used within the conditional logic.


We could advice users to setup their forms this way if they don't want to trigger the payment feed for payments of € 0
.
But this change will likely result in some support tickets.