SureCart – Purchased Revoked Access Custom Fields

Tech Articles | April 28, 2025 | Automation, Blog, Coding, Plugins, SureCart, Wordpress

SureCart has several action hooks, and I have already extensively written about and published blogs, videos and plugins that utilise the checkout_confirmed action, which is a pretty nice payload to work with and easy, when coupled with this action and the unique price-id identifier custom solutions can be built to do all kind of things based on a surecart purchase and several of my one plugin solutions such as Post Access Manager For SureCart, Ticket Manager Pro For SureCart and Hoster Gateway all use this trigger and Post-ID.

The good thing about checkout_confirmed is that it fires regardless of whether it’s a subscription or one-time sale, which means it’s consistent and well-used. It also includes custom checkout fields, such as those used in Post Access Manager for SureCart, meaning we can get the post_id field and do something with it from the payload.

I have previously asked SureCart support if its possible to get the checkout via API or hook to see a custom field at purchase on purchase revoked and was told it wasn’t feasible at the time having designed a custom solution using a new DB table to do this I asked a few questions about payload and was told today that you can now get the custom fields and a decent support answer, gave me my first real lead that they could be queried giving me the following information.

The Solution:

add_action('surecart/purchase_revoked', function($purchase, $webhook_data){   $purchase_data = \SureCart\Models\Purchase::with( [ 'initial_order', 'order.checkout' ] )
->find( $purchase->id );

 $checkout = $purchase_data->initial_order->checkout ?? null;

 if ($checkout) {                        // Now access any metadata easily.
$checkout->metadata->member_phone ?? null; }

}, 10, 2);
PHP

And a link to this documentation: https://developer.surecart.com/docs/purchase-actions-reference#real-life-example—adding-a-zoom-link-after-purchase-created-in-metadata

This was enough to confirm that the data was there and I could now access it, and with this I was able to take the very light way purchase object given to us on purchase_revoked and query it for more data, i.e

\SureCart\Models\Purchase::with([ 'initial_order', 'order.checkout' ])->find( $purchase->id )
PHP

This returns our nested checkout object, and this checkout object now contains the metadata, including custom metadata from the checkout, and this then allows me to revoke access to a post on the running of purchase_revoke.

What’s good about this is it runs on a refund, or a subscription cancellation, so it is as useful as checkout_confirmed from that point of view and within a few minutes, I had a new function to allow me to revoke access to a post on subscription cancellation and order termination.

A couple of minor pitfalls:

  1. In my support request, the hook was said to be “revoke”, but it’s actually revoked. The documentation is correct. I assume this is a typo, but it’s important to note, else it won’t fire.
  2. It’s also possible that sometimes the webhook_data passed can be missing, and you will get a too few arguments error; the fix for this is to accept webhook_data as null.
// Use the real “purchase_revoked” action, and make the second parameter optional
add_action( 'surecart/purchase_revoked', 'your_revoke_handler', 10, 2 );
function your_revoke_handler( $purchase, $webhook_data = null ) {
    // …
}
PHP

Is the meta not the same on all sites?

Now I was left with one challenge, which is based on how the code works, but wasn’t designed with this in mind. I use a filter to allow people to set a custom field ID that is of their own choosing, which doubles as the parameter key i.e ?post_id

This was easier to fix than I expected, allowing us to do something like the following.

$param_key = apply_filters('rup_sell_ind_posts_param_key','post_id');
$post_id   = $checkout->metadata->{$param_key} ?? null;
PHP

This means it’s always looking for the set param_key, not the default.

So, in the following example, I’d be looking for video_id as the custom param key

add_filter('rup_sell_ind_posts_param_key', fn()=> 'video_id');
PHP

With all of that, I’ve had some real success revoking a subscription purchase and with this version 1.5 of Post Access Manager for SureCart will be able to handle post subscriptions too;

In closing:

I firstly think SureCart Support is amazing, sometimes it’s difficult to accurately document everything, but you get the right person who truly understands what you’re asking, and you get a solid answer, and the truth is that their hooks and API do most stuff you need, you just need to find what works.

SureCart does seem to get some stick for not doing this or that, and it is more difficult than Woo to customise, but the reason it’s more difficult is one of the advantages; the details are stored on their servers, the processing happens there, the updates, the data storage, etc. Which means its lighter and faster but it does mean you don’t have the ability to hook in and do things as much as you would with a locally hosted solutions but if they keep adding hooks, API end points and query items to there documentation and as they build out you will be able to do a lot more with custom solutions too.

Support the Author

buy me a coffee
Really Useful Plugin Logo
Wpvideobank temp
Appoligies for any spelling and grammer issue. As a dyslexic i need to rely on tools for this they like me are not perfect but I do try my best