Compliance Webhooks Check Failing for Custom PHP App (No Shopify CLI)

Hi everyone,

I’m building a Shopify app without using the Shopify CLI. This app has no UI—it’s just a backend service that connects my POS system with Shopify. When the app is installed on a Shopify store, it receives the Shopify store credentials (API key, access token) and stores them in my system. I then use these credentials to call Shopify APIs for creating/updating products, orders, inventory, etc.

Here’s an example of how I’m creating webhooks programmatically in PHP:

$topics = [
    ['topic' => 'orders/create', 'address' => 'https://staging.cheerspos.com/'.$store_data['store_db_name'].'/login/get_shopify_order'],
    ['topic' => 'fulfillments/create', 'address' => 'https://staging.cheerspos.com/'.$store_data['store_db_name'].'/login/update_shopify_order'],
    ['topic' => 'inventory_levels/update', 'address' => 'https://staging.cheerspos.com/'.$store_data['store_db_name'].'/login/update_item_data'],
    ['topic' => 'products/update', 'address' => 'https://staging.cheerspos.com/'.$store_data['store_db_name'].'/login/sync_update_data'],
    ['topic' => 'app/uninstalled', 'address' => 'https://staging.cheerspos.com/cron/shopify_uninstall'],
];

// 1. Fetch and delete all existing webhooks
$url = "https://{$shop}/admin/api/{$this->API_VERSION}/webhooks.json";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-Shopify-Access-Token: {$access_token}"]);
$response = curl_exec($ch);
curl_close($ch);

The problem is with the compliance webhooks required for GDPR/CCPA:

  • customers/redact

  • shop/redact

  • customers/data_request

Even though I created the endpoints and tried adding a .toml configuration file, my app fails the mandatory compliance webhooks check when submitting for public distribution.

I’m looking for guidance on:

  1. How to properly configure these compliance webhooks programmatically in PHP.

  2. How to implement HMAC verification for these endpoints so Shopify recognizes them.

  3. Any tips for passing the automated compliance check without using the Shopify CLI.

Has anyone successfully implemented compliance webhooks in a headless app like this? Any examples, snippets, or tips would be really helpful!

Thanks in advance!

Hi @Yasir_shoukat

Just to confirm, are you intending to submit this to the app store? If so, I think a bigger problem will be this:

This app has no UI —it’s just a backend service that connects my POS system with Shopify.

If the app has no UI, it won’t pass an app store review, see app store requirements:

Hi @Yasir_shoukat

  1. How to properly configure these compliance webhooks programmatically in PHP.
    [Currently you must need to use Shopify CLI for that due to as of now no any options to set this urls directly using dev dashboard. Please find example screenshot below to add into .toml file.]

  2. How to implement HMAC verification for these endpoints so Shopify recognizes them.
    [Please find example php code below.]

  3. Any tips for passing the automated compliance check without using the Shopify CLI.
    [Currently no]

function verify_webhook($data, $hmac_header, $shared_secret) {
// 1. Calculate the HMAC digest of the RAW request body
// The ‘true’ parameter in hash_hmac returns the raw binary output
$calculated_hmac = hash_hmac(‘sha256’, $data, $shared_secret, true);

// 2. Encode the binary HMAC to base64
$calculated_hmac_base64 = base64_encode($calculated_hmac);

// 3. Securely compare the calculated digest with the header value
return hash_equals($calculated_hmac_base64, $hmac_header);

}

// Example usage in your webhook handler (e.g., in webhook.php)
$shared_secret = ‘YOUR_APP_CLIENT_SECRET’; // Use the same shared secret
$hmac_header = $_SERVER[‘HTTP_X_SHOPIFY_HMAC_SHA256’] ?? ‘’; // Retrieve the header
$data = file_get_contents(‘php://input’); // Get the raw POST body

if (verify_webhook($data, $hmac_header, $shared_secret)) {
// HMAC is valid, process the webhook data (e.g., decode the JSON payload)
$decoded_payload = json_decode($data, true);
// Process the data…
http_response_code(200); // Respond with 200 OK
} else {
// HMAC is invalid, reject the request
http_response_code(401); // Respond with 401 Unauthorized
exit(‘HMAC validation failed.’);
}

Hi Liam,

Thanks for the clarification.

Yes, the app does have a simple UI. When a merchant clicks Open App from the Shopify Admin dashboard, the app loads a page that confirms the connection status (for example, “The app is successfully connected”) and provides basic context about the integration.

The core functionality of the app is backend-focused, as it primarily connects our POS system with Shopify and operates through APIs and webhooks.

Please let me know if this level of UI is sufficient for App Store requirements, or if Shopify expects additional interactive elements or configuration screens.

Thanks for your guidance..