---
title: SureCart - Purchased Revoked Access Custom Fields
date: 2025-04-28T12:59:04Z
modified: 2025-04-28T13:06:46Z
permalink: "https://techarticles.co.uk/surecart-purchased-revoked-access-custom-fields/"
type: post
status: publish
excerpt: ""
wpid: 4817
categories:
  - Automation
  - Blog
  - Coding
  - Plugins
  - SureCart
  - Wordpress
timestamp: 2025-04-28T13:06:46Z
tags:
  - Automation
  - Blog
  - Coding
  - Plugins
  - SureCart
  - Wordpress
---

[SureCart](https://ta0.uk/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](https://reallyusefulplugins.com/plugins/post-access-manager-for-surecart/), [Ticket Manager Pro For SureCart](https://reallyusefulplugins.com/plugins/post-access-manager-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:

```
<span class="line"><span style="color: #B392F0">add_action</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">'surecart/purchase_revoked'</span><span style="color: #E1E4E8">, </span><span style="color: #F97583">function</span><span style="color: #E1E4E8">($purchase, $webhook_data){   $purchase_data </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">\SureCart\Models\Purchase</span><span style="color: #F97583">::</span><span style="color: #B392F0">with</span><span style="color: #E1E4E8">( [ </span><span style="color: #9ECBFF">'initial_order'</span><span style="color: #E1E4E8">, </span><span style="color: #9ECBFF">'order.checkout'</span><span style="color: #E1E4E8"> ] )</span></span>
<span class="line"><span style="color: #F97583">-></span><span style="color: #B392F0">find</span><span style="color: #E1E4E8">( $purchase</span><span style="color: #F97583">-></span><span style="color: #E1E4E8">id );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8"> $checkout </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $purchase_data</span><span style="color: #F97583">-></span><span style="color: #E1E4E8">initial_order</span><span style="color: #F97583">-></span><span style="color: #E1E4E8">checkout </span><span style="color: #F97583">??</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">null</span><span style="color: #E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8"> </span><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($checkout) {                        </span><span style="color: #6A737D">// Now access any metadata easily.</span></span>
<span class="line"><span style="color: #E1E4E8">$checkout</span><span style="color: #F97583">-></span><span style="color: #E1E4E8">metadata</span><span style="color: #F97583">-></span><span style="color: #E1E4E8">member_phone </span><span style="color: #F97583">??</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">null</span><span style="color: #E1E4E8">; }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">}, </span><span style="color: #79B8FF">10</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">2</span><span style="color: #E1E4E8">);</span></span>
```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 ](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

```
<span class="line"><span style="color: #79B8FF">\SureCart\Models\Purchase</span><span style="color: #F97583">::</span><span style="color: #B392F0">with</span><span style="color: #E1E4E8">([ </span><span style="color: #9ECBFF">'initial_order'</span><span style="color: #E1E4E8">, </span><span style="color: #9ECBFF">'order.checkout'</span><span style="color: #E1E4E8"> ])</span><span style="color: #F97583">-></span><span style="color: #B392F0">find</span><span style="color: #E1E4E8">( $purchase</span><span style="color: #F97583">-></span><span style="color: #E1E4E8">id )</span></span>
```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.

```
<span class="line"><span style="color: #6A737D">// Use the real “purchase_revoked” action, and make the second parameter optional</span></span>
<span class="line"><span style="color: #B392F0">add_action</span><span style="color: #E1E4E8">( </span><span style="color: #9ECBFF">'surecart/purchase_revoked'</span><span style="color: #E1E4E8">, </span><span style="color: #9ECBFF">'your_revoke_handler'</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">10</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">2</span><span style="color: #E1E4E8"> );</span></span>
<span class="line"><span style="color: #F97583">function</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">your_revoke_handler</span><span style="color: #E1E4E8">( $purchase, $webhook_data </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">null</span><span style="color: #E1E4E8"> ) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #6A737D">// …</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
```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.

```
<span class="line"><span style="color: #E1E4E8">$param_key </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">apply_filters</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">'rup_sell_ind_posts_param_key'</span><span style="color: #E1E4E8">,</span><span style="color: #9ECBFF">'post_id'</span><span style="color: #E1E4E8">);</span></span>
<span class="line"><span style="color: #E1E4E8">$post_id   </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $checkout</span><span style="color: #F97583">-></span><span style="color: #E1E4E8">metadata</span><span style="color: #F97583">-></span><span style="color: #E1E4E8">{$param_key} </span><span style="color: #F97583">??</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">null</span><span style="color: #E1E4E8">;</span></span>
```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

```
<span class="line"><span style="color: #B392F0">add_filter</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">'rup_sell_ind_posts_param_key'</span><span style="color: #E1E4E8">, </span><span style="color: #F97583">fn</span><span style="color: #E1E4E8">()=> </span><span style="color: #9ECBFF">'video_id'</span><span style="color: #E1E4E8">);</span></span>
```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.