0

In my WooCommerce shop I need to sell digital files (JPEG images) that are dynamically served by a PHP script. (This is because the images come from a huge remote catalogue with 10,000s of images, which we must retrieve on demand through their API. It's not practical to keep local copies of all the JPEGs.)

I have written a PHP script that serves a JPEG image via the API, given its catalogue identifier, something like this: https://example.com/fetch_image.php?id=12345

The PHP script looks like this (simplified):

$ch = curl_init();
...
$result = curl_exec($ch); # fetch the desired JPEG image data
...
header('Content-Type: image/jpeg');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="test.jpg"');
header('Content-Description: File Transfer');
echo $result;

If I visit this script in my browser, I get the test.jpg image successfully.

So I tried setting this script's full URL as the download URL for the WooCommerce product. It was rejected:

The downloadable file fetch_image.php?id=12345 cannot be used as it does not have an allowed file type. Allowed types include: jpg|jpeg|jpe, gif, png, bmp, tiff|tif, [...etc.]

OK, fine, I don't want to "allow php as a file type" (sounds like a security headache). So let's try another approach: I set up an .htaccess redirect so that I can access my script with a jpg URL:

RewriteRule ^REDIRECT_shop_download.jpg https://example.com/fetch_image.php [L,R=301]

Now I can use this URL, which WooCommerce will accept:

https://example.com/REDIRECT_shop_download.jpg?id=12345

Again, this works fine when manually visited in the browser. However, when I use this as the WooCommerce product download URL, and I purchase the product, and click my download link, I get an error page that says File not found. This error still occurs even if I remove the header calls from my PHP script (so it serves the file without returning it as test.jpg).

I have no idea how to diagnose this. What's wrong, and how can I make it work with the valid download URL that I have provided?

8
  • What URLs were called when you clicked on the link, looking in the network tab of your browser, and in the accesslog of your server? Commented Jul 1 at 13:15
  • I have changed the domain, e-mail address, and "key" (in case it is insecure to share) but the URL in both client and server looks a lot like this: example.com/… Commented Jul 1 at 13:22
  • What I meant is: do you see your browser calling the redirected URL (.php), as well as the server seing a request to that .php, or does the network only attempt to access the .jpg URL and then stops with the error page? Commented Jul 1 at 13:29
  • What do you have the "File Download Method" set to in your WC product options? If you have set it to "Force download", try "Redirect only", and see if that changes anything. woocommerce.com/document/digital-downloadable-product-handling/… Commented Jul 1 at 13:53
  • The setting is "Force downloads". If I choose "Redirect only", it works, but (i) there is a warning that "this method is deprecated" and (ii) customers would be able to share download links, which is undesirable. Commented Jul 1 at 13:57

2 Answers 2

0

to add a external download in woocommerce for some products (or for all), you can try that :

add_filter("woocommerce_product_get_downloads", function ($downloads, $product) {
    
    // if this product is a remote download
    if (TRUE) {
        
        // this file name appears in the customer area
        $file_name = "name of the file";
        
        
        $download_object = new WC_Product_Download();
        $download_key = "ext";
        
        $download_object->set_id($download_key);
        $download_object->set_name($file_name);
        $download_object->set_enabled(TRUE);
        
        $downloads[$download_key] = $download_object;
        
    }
    
    
    return $downloads;
    
}, 10, 2);


add_action("woocommerce_download_product", function ($user_email, $order_key, $product_id, $user_id, $download_id, $order_id) {
    
    // if this is a remote download
    if (TRUE) {
        
        // here, download of the file with curl
        
        // if you want lighten your http server, the optimal system should be
        // to use a temporary download token.
        // your server ask the token to the remote server and then, here is
        // a simple redirection to the remote server.
        
        exit();
    }
    
    
}, 10, 6);
Sign up to request clarification or add additional context in comments.

Comments

0

I have found a workaround, which is to store the file-generating PHP script on a different domain and server (along with the JPG htaccess trick I described above).

My original problem only seems to occur when the script is on the same domain, which causes it to fetch the file directly/locally instead of fetching it like a normal URL.

To me this workaround is preferable to writing code for WordPress 'hooks' etc. which are more complicated to understand, and are liable to change and require rewriting the code over time to maintain compatibility.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.