How to (programatically) take an action based on PayPal results using PayPal Standard Addon [RESOLVED]


I have a plugin which needs to automatically set a checkbox value when a payment is made via PayPal Standard Addon. For example, upon successful payment (only), the field would show as checked:

[x] User has paid.

I see several hooks and after reading I’m thinking I need to use gform_post_payment_action because it lets me capture the status of the payment.

Problem is I’m testing via PayPal Sandbox and I cannot figure out HOW to capture any data.

I tried this … (in functions.php)

add_action( 'gform_post_payment_action', function ( $entry, $action ) {
	var_dump( $action );
}, 10, 2 );

…which failed miserably as the payment completed and showed me nothing (ajax?).

Also, PayPal is not returning to my page. I have to manually click “Return to Merchant”. What am I missing?

please advise.

Hi @SleeperTech

PayPal Standard communicates payment status changes to your site using IPN requests. To take custom actions based on the information reported by PayPal you will want to use the following hook gform_paypal_post_ipn - Gravity Forms Documentation
The $_POST variable gives you access to all the information received including the payment status.

​​​​I would recommend you to enable logging on the Forms > Settings page and then on the Forms > Settings > Logging page ensure that Gravity Forms Core and any add-ons are enabled and set to log all messages.

Then you can add custom logging statements to ensure your custom function is running when expected and dump information from key parts of your code to the log (that is way better than using var_dump() ), check instructions here: Custom Logging Statements - Gravity Forms Documentation

Regarding to the Auto Return feature, that’s controled by the PayPal site not by the add-on, you should find an Auto Return setting in your PayPal account. I’m sure PayPal support can help you further with this if you’re unable to find the setting.

1 Like

What a great answer! Thank you, good Sir …and thanks for pointing me to the right hook!

+1 for the intro to GF Logging & Debugging. I will be on that today!


Greetings @sacom

So based on the reading I’ve turned on logging and i can generate logs. However, I have been completely unsuccessful at writing anything to the log. Tried the code below (in functions.php), checked the logs for Gravity Forms Core and for Gravity Forms PayPal Standard Add-On and nothing was written to the logs.

The test code:

add_action( 'gform_paypal_post_ipn', 'blackopz_gf_log_test', 10, 4 );
function blackopz_gf_log_test( $entry, $feed, $transaction_id, $amount ) {
	GFCommon::log_debug( __METHOD__ . '(): BlackOpz_Entry => ' . print_r( $entry, true ) );
	GFCommon::log_debug( __METHOD__ . '(): BlackOpz_Feed => ' . print_r( $feed, true ) );

Not showing up. What am I missing.

Please Advise.


Preston, gform_paypal_post_ipn will run only if your site receives an IPN request from PayPal. Is your PayPal log showing any IPN request being received since you added the snippet?

Well, it’s still working as expected. Transactions are completing, etc. It’s setup using an IPN so nothing has changed. Plus, I am seeing logs, I just cannot add anything to it.

  1. I added this to my Beaver Builder (child) theme’s function.php file:

    add_action( ‘gform_paypal_post_ipn’, ‘test_log_after_submission’, 10, 2 );
    function test_log_after_submission( $entry, $form ) {
    GFCommon::log_debug( "(): is this thing on? " );

  2. Then I completed a PayPal transaction.

  3. Then I opened the Gravity Forms Core log and did a search for “is this thing on?” and found nothing. Also did a search for IPN and found nothing (in core log).

  4. Then I checked the Gravity Forms PayPal Standard Add-On log and searched for “is this thing on?” and found nothing. But I did find a boatload of references to IPN. See snippet:

    2021-03-02 19:36:40.338723 - DEBUG → GFPayPal::callback(): Form 46 is properly configured.
    2021-03-02 19:36:40.338778 - DEBUG → GFPayPal::can_process_ipn(): Checking that IPN can be processed.
    2021-03-02 19:36:40.338813 - DEBUG → GFPayPal::callback(): Processing IPN…
    2021-03-02 19:36:40.338839 - DEBUG → GFPayPal::process_ipn(): Payment status: Completed - Transaction Type: cart - Transaction ID: 20784037NL848493T - Parent Transaction: - Subscriber ID: - Amount: 400.00 - Pending reason: - Reason:
    2021-03-02 19:36:40.339127 - DEBUG → GFPayPal::callback(): IPN processing complete.
    2021-03-02 19:36:40.339160 - DEBUG → GFPaymentAddOn::maybe_process_callback(): Result from gateway callback => Array
    [id] => 20784037NL848493T_Completed
    [type] => complete_payment
    [transaction_id] => 20784037NL848493T
    [amount] => 400.00
    [entry_id] => 242
    [payment_date] => 21-03-03 00:36:40
    [payment_method] => PayPal
    [ready_to_fulfill] => 1

    2021-03-02 19:36:40.339184 - DEBUG → GFPaymentAddOn::process_callback_action(): Processing callback action.
    2021-03-02 19:36:40.341953 - DEBUG → GFPaymentAddOn::complete_payment(): Processing request.
    2021-03-02 19:36:40.361305 - DEBUG → GFPaymentAddOn::maybe_process_callback(): Result of callback action => 1
    2021-03-02 19:36:40.363459 - DEBUG → GFPayPal::fulfill_order(): Executing functions hooked to gform_paypal_fulfillment.

So yeah, I would say IPN is on and working. But still no custom messages showing.

Your PayPal log should contain a line like this:

Executing functions hooked to gform_paypal_post_ipn

I’m not seeing it above. Make sure that you’re running latest version of the add-on.

The following would add Testing my function… to the PayPal log:

add_action( 'gform_paypal_post_ipn', 'test_ipn_received', 10, 4 );
function test_ipn_received( $ipn_post, $entry, $feed, $cancel ) {
  gf_paypal()->log_debug( __METHOD__ . '(): Testing my function...' );

It’s working for me on a default WordPress installation without caching or other third-party plugins or custom code.

So now this is making zero sense to me.

  1. I have IPN setup correctly.

  2. I completed a transaction via PayPal.

  3. The form entry shows the transaction with the following details:

    Status: Paid
    Date: 2021/03/03 at 12:10 pm
    Transaction Id: 83V20347G5367820V
    Amount: $450.00

  4. Then I checked the logs (both core and PayPal Standard) and (using a search) I did not see the string gform_paypal_post_ipn.

  5. Now, I am seeing all kinds of references to IPN this and IPN that.

For example…

2021-03-02 19:36:40.335932 - DEBUG --> GFPayPal::callback(): IPN message successfully verified by PayPal 
2021-03-02 19:36:40.335988 - DEBUG --> GFPayPal::get_entry(): IPN message has a valid custom field: 242|c8e534f6a348c3041eab30dce9d28e77 
  1. But again, not the string gform_paypal_post_ipn.

So if the lack of the string gform_paypal_post_ipn indicates that IPN is not working, then how can there possibly be a completed transaction (both in PayPal Sandbox and in the GF Entry)?

Also, although I cannot test sandbox on localhost, I disabled the PayPal feed and tested the following (see code) just to see if I could use any hook to write anything to the log.

add_action( 'gform_after_submission', 'blackopz_gf_log_test', 10, 4 );
function blackopz_gf_log_test( $entry, $feed, $transaction_id, $amount ) {
	GFCommon::log_debug( '(): BlackOpz ' );
	GFCommon::log_debug( __METHOD__ . '(): BlackOpz Entry => ' . print_r( $entry, true ) );

It Works! …on localhost!

So I tried the exact same code on SiteGround (GrowBig) server and …FAIL!


  1. So PayPal or not, I cant seem to write anything to the site while on SiteGround. To be clear, logs are generated on SiteGround, but custom logging -PayPal or Not- continuously FAILS to write to the log.
  2. While I cannot test PayPal on LocalHost, I can confirm that custom logging does at least work …locally.


So if the lack of the string gform_paypal_post_ipn indicates that IPN is not working

That’s not correct, all the IPN stuff that you see on the log and the fact that you’re seeing the entry payment details being updated indicate the IPN handling is working.

The only issue here is that something on the SiteGround hosted site preventing your custom code from running. As pointed previously, I can’t replicate the issue you’re experiencing on a default WordPress installation, you have also confirmed the same basic logging code that is working on your localhost copy is not working on the SiteGround site, so the issue is tied to something on that site setup or the host.

I would recommend you to start by excluding your form page from cache to ensure you always work with fresh resources: SuperCacher Controls in SG Optimizer Tutorial (scroll down to Exclude URLs).

You can also try using a custom functions plugin instead of adding the code to your theme functions.php file. Here’s a helper plugin to do that: Pluginception – WordPress plugin |

If none of the above helps, I would recommend you to perform a full conflict test: Testing for a Theme/Plugin Conflict using the Health Check & Troubleshooting Plugin - Gravity Forms Documentation

1 Like

I figured as much. Esp. since i’m seeing transactions. But that begs the question: so why no gform_paypal_post_ipn in the logs? …just curious.

Agreed. Local tests bear that out.

Will do. …more news as it happens.

Interesting plugin. …and by the great Otto, no less :slight_smile:. But I already have starter plugin code. But does it matter that the tests are in functions.php? True, for best practices, I normally like to keep my functions.php file pretty clean. But now I’m curious as to why you are recommending a plugin? More for best practices (I assume), than for performance/functionality, correct? …or no?

Well, since its pretty much working locally, I will leave this as you have stated: last resort.

Next Up

I’m gonna give the caching options a shot (thanks again for going the extra mile in providing the links :wink:). If tweaking the cache fails, I’m off to SiteGround Support. I will report back.

Thanks again for your help!


Final Update:

The “something” in fact did turn out to be cache related. SiteGround is …well… “aggressive” with their caching (and their speedy sites show it). Also, they recently moved from Static Cache to NGINX Direct Delivery . Don’t know what role that may have played.

Their solution was to (temporarily) completely disable dynamic caching for the site. Then re-enable once testing is done. A bit draconian, maybe …but it worked. When time permits, I’m going to test whether I can be a bit more “strategic” using the SG Optimizer (I did exclude the form page, but it had no effect).

But for now, I’m back in business!

Thanks to all who helped!


1 Like