pronamic / wp-pronamic-pay

The Pronamic Pay plugin allows you to easily accept payments with payment methods like credit card, iDEAL, Bancontact and Sofort through a variety of payment providers on your WordPress website.
https://pronamicpay.com
34 stars 14 forks source link

Support for partial refunds Gravity Forms #119

Closed remcotolsma closed 3 years ago

remcotolsma commented 3 years ago

After https://github.com/wp-pay/core/commit/7af53e7218ad65844dcd680549cf62d0d059e0a8 it is possible to keep track of the refunded amount per payment.

Gravity Forms can also keep track of refunds by adding transaction info in a gf_addon_payment_transaction table.

The gf_addon_payment_transaction table has no unique constrains, so addons have to make sure transactions are not added twice. Within the PayPal add-on, I think they assume that the PayPal only calls the IPN URL once.

My colleague @rvdsteege had the idea to also keep track of the 'refunded amount' in the Gravity Forms entry. The Gravity Forms refund_payment function should then only be called if the Gravity Forms entry 'refunded amount' is bigger than the Pronamic Payment 'refunded amount'.

Downside of this approach is that we can't include the payment provider his transactie ID in the refund_payment call. https://github.com/wp-premium/gravityforms/blob/2.4.20/includes/addon/class-gf-payment-addon.php#L1908-L1964

remcotolsma commented 3 years ago

Gravity Forms stores the payment_amount in the wp_gf_entry table. We can also store extra data for entries in the wp_gf_entry_meta table.

We can store the refunded amount in, for example, the meta field refunded_amount. Then we can check for that in the pronamic_payment_status_update_{$slug} action:

$entry_id = $payment->get_source_id();

$entry = \GFAPI::get_entry( $entry_id );

$refunded_amount = $payment->get_refunded_amount()->get_value();

$entry_refunded_amount = \gform_get_meta( $entry_id, 'pronamic_pay_refunded_amount' );

if ( $entry_refunded_amount < $refunded_amount ) {
    $result = $this->addon->refund_payment(
        $entry,
        array(
            // The Gravity Forms payment add-on callback feature uses the action ID to prevent processing an action twice.
            'id'             => '',
            'type'           => 'refund_payment',
            // Unfortunately we don't have a specific transaction ID for this refund at this point.
            'transaction_id' => '',
            'entry_id'       => $entry_id,
            'amount'         => ( $refunded_amount - $entry_refunded_amount ),
        )
    );

    if ( true === $result ) {
        \gform_update_meta( $entry_id, 'pronamic_pay_refunded_amount', $refunded_amount );
    }
}

The gf_addon_payment_transaction table has no unique constrains, so addons have to make sure transactions are not added twice. Within the PayPal add-on, I think they assume that the PayPal only calls the IPN URL once.

This assumption does not seem correct, Gravity Forms can track the callbacks (eg IPN requests) in the gf_addon_payment_callback table. There is a is_duplicate_callback function to make sure callbacks are not processed twice.

https://github.com/wp-premium/gravityforms/blob/a9c8f2de051e016e096069210ecd5fb8f5a19801/includes/addon/class-gf-payment-addon.php#L1630-L1632

I don't think we can use this because we don't work with the Gravity Forms payment callback functionality.

remcotolsma commented 3 years ago

Work in progress: https://youtu.be/E2vHO-ZuHvc, also see:

remcotolsma commented 3 years ago

This is done, it requires some testing, but for now good to go. We have two other Buckaroo issues open: https://github.com/pronamic/wp-pronamic-pay/issues/120 and https://github.com/pronamic/wp-pronamic-pay/issues/140.