Building a digital product sales module in Sylius – Introduction: Modern eCommerce is no longer limited solely to physical products. eBooks, games, event tickets, software, and video courses – these are just a few of the numerous digital products that are gaining popularity. Why? They are easy to distribute, don’t require delivery costs, and can be provided to the customer immediately after purchase. 

That’s why more and more online stores are looking for ways to integrate the sale of digital products with their existing system. If you’re using Sylius as your primary eCommerce management tool, you might be wondering how to add a digital product sales module to it. In this post, we will guide you through the main concepts and considerations to take into account when implementing such a module.

Digital Products – What Are They? Digital products are goods that are delivered and consumed in electronic form. They encompass a variety of categories, such as:

  • eBooks: eBooks that can be read on computers, smartphones, tablets, or eBook readers. 
  • Software: Apps or computer games available for download. 
  • Video Courses: Training that users can browse and watch online. 
  • Graphics and Design: Templates, stock photos, fonts, etc. 
  • Music and Sounds: Audio files, music tracks, sound effects, etc.
  • Virtual: Here, we’re talking about products that don’t have a physical counterpart but have value to the buyer. These can be, for example, tickets to events, virtual goods in games, and activation codes for various services or games.

Quick Jump

File Storage Location 

When it comes to digital products, one of the key aspects is the location for storing downloadable files. There are several options to consider:

  • Local Disk: We can store files directly on our server. This is a straightforward solution but may not be scalable if we have many large files or numerous customers downloading them simultaneously. 
  • Cloud storage: Cloud services, like Amazon S3, offer a flexible environment for file storage. They adapt to increasing data volumes, ensuring security and efficiency at lower IT costs. To provide controlled access to files, one can use pre-signed URLs or CDN services (which, combined with Amazon S3, can deliver even better performance and help reduce costs, for example, for S3). Pre-signed URLs are links with a limited lifespan; once they expire, access is blocked, protecting against unauthorized sharing. 
  • External Services: Beyond downloadable files, digital products can also take the form of online services. Examples include event tickets, software activation codes, games, or access to specialized databases. Such “products” often don’t require physical downloading but are delivered in the form of codes or links.

Sales and Delivery Workflow for Digital Products in Sylius

Understanding the digital product purchase process from the user’s perspective is essential for creating a coherent and intuitive experience for customers. Additionally, this will allow for a more precise preparation of technical implementation stages.

Product addition by Admin

Once we have an integrated file storage system (in our case, Amazon S3), the process starts when the store administrator decides to add a new digital product:

  • Product addition: The administrator creates a new product in the Sylius panel, providing its name, description, price, etc.
  • File selection: Using an autocomplete feature, the admin searches their cloud resources (e.g., Amazon S3). Upon selecting the appropriate file, the system automatically saves the link to it in the database.
  • Digital product type determination: At this point, the admin uses a dropdown list (select field type) to choose the file’s source (e.g., Amazon S3, local server, external source). Thanks to integration with a compiler pass, Sylius knows how to handle each of these sources.

Product purchase by a customer

  • Product selection: The customer browses the available products in the store and decides to purchase a digital product.
  • Purchase finalization: After making the payment, the Sylius system uses a state machine to go through the order stages. Once the transaction is confirmed and the order is paid for, the order status changes to “fulfilled.” At this point, using transitions, the system automatically creates an association between the purchased digital product and the customer’s account.
  • Notification of file access: Upon successful payment, the customer receives a purchase confirmation along with information that the digital product is available for download in a new menu on their user panel.

File download by the Customer

  • User panel access: The customer logs into their account in the store.
  • Review of purchased products: After logging in, the customer has access to a new menu, where they find a list of purchased digital products.
  • Downloading: After clicking the “Download” button, the customer is redirected to an action that generates a temporary download link (pre-signed URL from Amazon S3) and initiates the download process.

Considering the above workflow, it is important that the store’s backend correctly handles the file access logic, verifies user permissions, and integrates with external file storage services.

Implementation

Expanding the store with the ability to sell digital products requires introducing several crucial changes in the code, and all the steps are based on solutions provided by Sylius. Remember to visit the official Sylius documentation for more detailed information.

Extend ProductVariant Entity for Digital Products

If we want to store links to our digital product, we need to extend the existing `ProductVariant` entity. In our case, these will be links to files on Amazon S3.

Modifying the `ProductVariant` Entity

We start by extending the `Sylius\Component\Core\Model\ProductVariant` entity, adding a filePath and a digitalType field. These changes will allow us to store information about the file location and the type of digital product.

More about extending models in Sylius can be found in the official documentation.

Register the Modified Entity in Sylius resource

For Sylius to recognize the new entity structure, you need to register it in `config/packages/_sylius.yaml` under the `sylius_resource` key.

Details on the configuration can be found in the Sylius Resource documentation.

Extend the `ProductVariantType` Form

To include the new fields in the admin panel, you need to extend the base form `Sylius\Bundle\ProductBundle\Form\Type\ProductVariantType` to include the new `filePath` and `digitalType` fields. The `filePath` field must be integrated with `Sylius\Bundle\ResourceBundle\Form\Type\ResourceAutocompleteChoiceType` to display a list of links directly from Amazon S3. 

Remember to configure this field so that it corresponds with your S3 bucket.

Extend the Customer Entity with Purchased Digital Products

To provide customers with a complete overview of purchased digital products, it’s essential that our data model can handle this functionality. We will apply an association between the `Customer` and `ProductVariant` entities by adding a new entity `CustomerDigitalProduct` with fields `Customer` and `ProductVariant`.

Then, you need to extend the `Sylius\Component\Core\Model\Customer` entity, adding the `purchasedDigitalProducts` association referring to `CustomerDigitalProduct`.

Detailed information about mapping associations in Sylius can be found in the documentation.

Defining the new entity `CustomerDigitalProductLink`

This entity will store the pre-signed links generated from Amazon S3, which are valid for a limited time. For this purpose, add the following fields to the entity:

  • `expiresAt` – information about when the link will expire.
  • `productVariant` – reference to the variant.
  • `link` – will store the direct link to the file.
  • `customerDigitalProduct` – reference to the file and the customer.

Customer Dashboard – a new tab with a list of digital products

Configuration of the data grid for the list of digital files purchased by the customer

Add a definition for our grid. In it, we point to the `CustomerDigitalProduct` entity and specify what data should be passed to the view: link to the product, link expiration date, and product name.

For more information on grid configuration, refer to the Sylius documentation.

We need to configure our new route responsible for displaying the list of all digital products purchased by the customer. For this, you can utilize the built-in functionalities of the `ResourceBundle.` In the route configuration, you should use the previously created grid definition and the `Sylius\Bundle\ResourceBundle\Controller\ResourceController` along with its `indexAction` method, which fits perfectly here. 

I encourage you to develop functionalities using the `ResourceBundle`, which is consistent with Sylius and offers many possibilities, such as automatic pagination, the ability to easily configure filters, and adding custom actions to our grid. See the benefits of using ResourceBundle and how to configure the route in SyliusResourceBundle.

Add a “download file” action to the data grid

It’s essential to add an action in the twig template used in the `CustomerDigitalProduct` data grid that initiates the file download. Clicking the button starts the product download or generates a new Pre-signed link (depending on the selected strategy in `ProductVariant.digitalType`, the appropriate service responsible for obtaining the file link is launched).

Integration with the customer panel

We add a new tab in the customer panel, which directs to the above-mentioned data grid `CustomerDigitalProduct` through the ‘indexAction’ from ResourceController of the `CustomerDigitalProduct` entity.

File download action in Sylius

When a customer decides to download a digital product, we must ensure that they have the appropriate permissions and that access to the file is secure. Here are the steps we can take:

Access verification

Before redirecting the customer to the file, we need to verify if they have the right to download this product. We can do this by checking if the digital product is associated with the customer’s account in the `CustomerDigitalProduct` entity.

Generating a link to download the digital product (pre-signed)

If the pre-signed link for a particular product is still valid, we can use it. If not:

Use the Amazon S3 SDK to generate a new pre-signed link. These links are valid for a limited time (e.g., for an hour), which further enhances security.

Update the `CustomerDigitalProduct` entity, adding information about the newly generated link and its expiration date.

Redirect to the link

Once the generated pre-signed link is ready, we directly redirect the customer to this link, allowing them to download the product.

Error handling

In case of problems (e.g., lack of permissions or communication errors with Amazon S3), the user should be informed with an appropriate message.

Additional security mechanisms

Download attempts limit: We can introduce a mechanism that limits the number of attempts to generate a pre-signed link in a specific time frame. This protects against potential attacks and excessive server load.

Logging download attempts: Good security practices include recording information about file download attempts (who, when, which product).

Implementing the above mechanism ensures that only authorized customers have access to purchased digital products and the download process is safe and efficient.

More information about generating pre-signed links in Amazon S3 can be found in the AWS SDK documentation.

Automatic assignment of products after purchase

Automation of the process of assigning digital products to a customer after making a purchase.

Integration with state machine

As you may already know, Sylius uses a state machine to manage states that react to transitions (see what a state machine is in Sylius).

To assign a digital product to a customer after paying for the order, configure the state machine for the `Order` entity so that after changing the order status to fulfilled, it triggers an action from the service responsible for adding the Customer association to `ProductVariant`. Examples:

winzou_state_machine:
    sylius_order:
        callbacks:
            after:
                app_assign_digital_product:
                    on: ["fulfill"]
                    do: ["@app.assigner.digital_product_assigner", "assignToCustomer"]
                    args: ["object"]

Using Compiler Pass to load appropriate services for digital products

If different types of digital products rely on different handling logics, the `digitalType` value is key to determining the appropriate service. Using Compiler Pass, we can dynamically map and load dedicated services depending on the set `digitalType`. For example, for the download process, different types of products may require different mechanisms, such as generating a specific “presigned” link or different ways of tracking file download attempts.

Create your compiler pass implementation; if you don’t know how to do it, you can base it on existing ones in Sylius (link to the example) and check the Symfony documentation.

Service definitions

In service configuration (e.g., `services.xml`), define services for different types of digital products and add a tag with a `type` attribute for each service implementation. In this case, it will be the value from the `digitalType` field of the `ProductVariant` entity.

```
<service id="app.handler.digital_product.amazon_s3" class=”App\Handler\DigitalProduct\AmazonS3Handler">
    <tag name="app.digital_product_handler" type="amazon_s3"/>
</service>

<service id="app.handler.digital_product.google_drive" class="App\Handler\DigitalProduct\GoogleDriveHandler">
    <tag name="app.digital_product_handler" type="google_drive"/>
</service>

<service id="app.handler.digital_product.native_storage" class="App\Handler\DigitalProduct\NativeStorageHandler">
    <tag name="app.digital_product_handler" type="native_storage"/>
</service>

<service id="app.handler.digital_product.brand_game_codes" class="App\Handler\DigitalProduct\BrandGameCodesHandler">
    <tag name="app.digital_product_handler" type="brand_game_codes"/>
</service>

```

Want to know more about Sylius?

sylius-logo

Summary

Introducing digital products to your store’s offer can provide significant added value for your business. Of course, the presented guide serves as the foundation for the digital product sales module in Sylius – as your business evolves and depending on its specificity, you may want to adjust some of these concepts.

As for further improvements, consider using a Content Delivery Network (CDN) for distributing your digital products. Using a `CDN` not only speeds up access to your products worldwide but also offloads your main servers, which can be critical during traffic spikes.

I hope this article has provided you with the necessary tools and knowledge to implement the sale of digital products in Sylius. Good luck in your future endeavors and the continuous development of your online store!

Contact us – If you have questions or are looking for a Sylius development company.