{"id":23765824,"url":"https://github.com/solidusio-contrib/solidus_digital","last_synced_at":"2025-09-05T09:33:08.909Z","repository":{"id":46148273,"uuid":"100708416","full_name":"solidusio-contrib/solidus_digital","owner":"solidusio-contrib","description":"Adds support for digital products to your Solidus store.","archived":false,"fork":false,"pushed_at":"2025-01-08T09:52:35.000Z","size":446,"stargazers_count":18,"open_issues_count":1,"forks_count":15,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-06T03:21:44.858Z","etag":null,"topics":["digital-products","drm","ecommerce","extension","solidus"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/solidusio-contrib.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-18T12:08:41.000Z","updated_at":"2025-01-11T08:50:35.000Z","dependencies_parsed_at":"2025-01-09T00:30:44.374Z","dependency_job_id":null,"html_url":"https://github.com/solidusio-contrib/solidus_digital","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/solidusio-contrib/solidus_digital","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio-contrib%2Fsolidus_digital","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio-contrib%2Fsolidus_digital/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio-contrib%2Fsolidus_digital/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio-contrib%2Fsolidus_digital/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/solidusio-contrib","download_url":"https://codeload.github.com/solidusio-contrib/solidus_digital/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidusio-contrib%2Fsolidus_digital/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273739172,"owners_count":25159289,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["digital-products","drm","ecommerce","extension","solidus"],"created_at":"2024-12-31T23:18:10.109Z","updated_at":"2025-09-05T09:33:08.892Z","avatar_url":"https://github.com/solidusio-contrib.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# solidus_digital\n\n[![CircleCI](https://circleci.com/gh/solidusio-contrib/solidus_digital.svg?style=svg)](https://circleci.com/gh/solidusio-contrib/solidus_digital)\n\nThis is a [Solidus](http://solidus.io/) extension to enable downloadable products (ebooks, MP3s, videos, etc).\n\nThis documentation is not complete and possibly out of date in some cases.\nThere are features that have been implemented that are not documented here, please look at the source for complete documentation.\n\n### Digital products\nThe idea is simple.\nYou attach a file to a Product (or a Variant of this Product) and when people buy it, they will receive a link via email where they can download it once.\nThere are a few assumptions that solidus_digital (currently) makes and it's important to be aware of them.\n\n* The table structure of spree_core is not touched.\n  Spree digital lives parallel to spree_core and does change the existing database, except adding two new tables.\n* The download links will be sent via email in the order confirmation (or \"resend\" from the admin section).\n  The links do *not* appear in the order \"overview\" that the customer sees.\n  Adding download buttons to `OrdersController#show` is easy, [check out this gist](https://gist.github.com/3187793#file_add_solidus_digital_buttons_to_invoice.rb).\n* Once the order is checked-out, the download links will immediately be sent (i.e. in the order confirmation).\n  You'll have to modify the system to support 'delayed' payments (like a billable account).\n* You should create a ShippingMethod based on the Digital Delivery calculator type.\n  The default cost for digital delivery is 0, but you can define a flat rate (creating a per-item digital delivery fee would be possible as well).\n  Checkout the [source code](https://github.com/halo/solidus_digital/blob/master/app/models/spree/calculator/digital_delivery.rb) for the Digital Delivery calculator for more information.\n* One may buy several items of the same digital product in one cart.\n  The customer will simply receive several links by doing so.\n  This allows customer's to legally purchase multiple copies of the same product and maybe give one away to a friend.\n* You can set how many times (clicks) the users downloads will work.\n  You can also set how long the users links will work (expiration).\n  For more information, [check out the preferences object](https://github.com/halo/solidus_digital/blob/master/lib/spree/solidus_digital_configuration.rb)\n* The file `views/order_mailer/confirm_email.text.erb` needs to be customized by you.\n  If you are looking for HTML emails, [this branch of spree-html-email](http://github.com/iloveitaly/spree-html-email) supports solidus_digital.\n* A purchased product can be downloaded even if you disable the product immediately.\n  You would have to remove the attached file in your admin section to prevent people from downloading purchased products.\n* File are uploaded to `RAILS_ROOT/private`.\n  Make sure it's symlinked in case you're using Capistrano.\n  If you want to change the upload path, [check out this gist](https://gist.github.com/3187793#file_solidus_digital_path_change_decorator.rb).\n* You must add a `views/spree/digitals/unauthorized.html.erb` file to customize an error message to the user if they exceed the download / days limit\n* We use send_file to send the files on download.\n  See below for instructions on how to push file downloading off to nginx.\n\n## Issues\n\nCurrent version of `solidus_digital` is not compatable with `solidus` version 2.3.0.\n\n## Quickstart\n\nAdd this line to the `Gemfile` in your Spree project:\n\n```ruby\ngem 'solidus_digital', github: 'solidusio-contrib/solidus_digital'\n```\n\nThe following terminal commands will copy the migration files to the corresponding directory in your Rails application and apply the migrations to your database.\n\n```shell\nbundle exec rails g solidus_digital:install\nbundle exec rake db:migrate\n```\n\nThen set any preferences in the web interface.\n\n### Shipping Configuration\n\nYou should create a ShippingMethod based on the Digital Delivery calculator type.\nIt will be detected by `solidus_digital`.\nOtherwise your customer will be forced to choose something like \"UPS\" even if they purchase only downloadable products.\n\n### Links access configuration\n\nConfiguration class `Spree::DigitalConfiguration`.\nDefault configuration:\n\n```ruby\nclass SpreeDigitalConfiguration \u003c Preferences::Configuration\n  # number of times a customer can download a digital file\n  # nil - infinite number of clicks\n  preference :authorized_clicks, :integer, default: 3\n\n  # number of days after initial purchase the customer can download a file\n  preference :authorized_days, :integer, default: 2\n\n  # should digitals be kept around after the associated product is destroyed\n  preference :keep_digitals, :boolean, default: false\n\n  # number of seconds before an s3 link expires\n  preference :s3_expiration_seconds, :integer, default: 10\n\n  # number of digital links generated per line item\n  # accepts: 'quantity' or Integer numbers\n  # quantity - 'line_item.quantity' digital links will be generated\n  # Integer 'number' - 'number' digital links will be generated\n  preference :digital_links_count, :string, default: 'quantity'\nend\n\n```\n\nExample:\n```ruby\nRails.application.config.after_initialize do\n  Spree::DigitalConfiguration[:authorized_clicks] = nil # infinite access for user\nend\n```\n\n### DRM\n\nIf you want to create attachment with [DRM](https://en.wikipedia.org/wiki/Digital_rights_management) for your digital product, e.g.: _watermark_ or _digital signature_,\nyou'll need to implement a class which will transform original attachement from `Spree::Digital` class, to modified attachment. This attachment will be stored as `Spree::DrmRecord` which is assigned to `Spree::Digital` class. And check \"DRM\" checkbox while creating Digital for product.\n\nFor example:\n```ruby\nclass SampleDrmMaker\n  def initialize(drm_record)\n    @drm_record = drm_record\n  end\n\n  def create!\n    # DRM file attachment specific code\n    @drm_record.attachment = drm_attachemnt\n  end\nend\n```\n\nThen insert it into `DrmClass`:\n```ruby\n\nSpree::DrmRecord.class_eval do\n  private\n  def prepare_drm_mark\n    SampleDrmMaker.new(self).create!\n  end\nend\n```\n\n`prepare_drm_mark` method will call **after_create** for `Spree::DrmRecord`. We'd suggest to run your drm maker class in parallel with [Delayed::Job](https://github.com/collectiveidea/delayed_job) or [Sidekiq](https://github.com/mperham/sidekiq).\n\nEvery time user confirms order on checkout process, new `Spree::DrmRecord` will be created for every `LineItem` which has digital product with enabled `DRM` flag.\n\n\n### Improving File Downloading: `send_file` + nginx\n\nWithout customization, all file downloading will route through the rails stack.\nThis means that if you have two workers, and two customers are downloading files, your server is maxed out and will be unresponsive until the downloads have finished.\n\nLuckily there is an easy way around this:\npass off file downloading to nginx (or apache, etc).\nTake a look at [this article](http://blog.kiskolabs.com/post/637725747/nginx-rails-send-file) for a good explanation.\n\n```ruby\n# in your app's source\n# config/environments/production.rb\n\n# Specifies the header that your server uses for sending files\n# config.action_dispatch.x_sendfile_header = \"X-Sendfile\" # for apache\nconfig.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx\n```\n\n```nginx\n# on your server\n# e.g. /etc/nginx/sites-available/spree-secure\nupstream unicorn_spree_secure {\n  server unix:/data/spree/shared/sockets/unicorn.sock fail_timeout=0;\n}\nserver {\n  listen 443;\n  ...\n\n  location / {\n    proxy_set_header X_FORWARDED_PROTO https;\n    ...\n    proxy_set_header X-Sendfile-Type  X-Accel-Redirect;\n    proxy_set_header X-Accel-Mapping  /data/spree/shared/uploaded-files/digitals/=/digitals/;\n    ...\n  }\n\n  location /digitals/ {\n    internal;\n    root /data/spree/shared/uploaded-files/;\n  }\n  ...\n}\n```\n\nReferences:\n\n* [Gist of example config](https://gist.github.com/416004)\n* [Change paperclip's upload / download path](https://gist.github.com/3187793#file_solidus_digital_path_change_decorator.rb)\n* [\"X-Accel-Mapping header missing\" in nginx error log](http://stackoverflow.com/questions/6237016/message-x-accel-mapping-header-missing-in-nginx-error-log)\n* [Another good, but older, explanation](http://kovyrin.net/2006/11/01/nginx-x-accel-redirect-php-rails/)\n\n### Development\n\n#### Table Diagram\n\n\u003cimg src=\"https://camo.githubusercontent.com/5fc9017154dc2ea3463e59cb76f7860597f2d3ff/68747470733a2f2f63646e2e7261776769742e636f6d2f68616c6f2f73707265655f6469676974616c2f6d61737465722f646f632f7461626c65732e706e67\"\u003e\n\n#### Testing\n\n```shell\nrake test_app\nrake rspec\n```\n\n### Contributors\n\nSee https://github.com/solidusio-contrib/solidus_digital/graphs/contributors\n\n### License\n\nMIT © 2011-2015 halo, see [LICENSE](https://github.com/solidusio-contrib/solidus_digital/blob/master/LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolidusio-contrib%2Fsolidus_digital","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolidusio-contrib%2Fsolidus_digital","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolidusio-contrib%2Fsolidus_digital/lists"}