iron-bound-designs / exchange-addon-licensing Goto Github PK
View Code? Open in Web Editor NEWiThemes Exchange Licensing Add-on
License: GNU Affero General Public License v3.0
iThemes Exchange Licensing Add-on
License: GNU Affero General Public License v3.0
This issue describes the /version/
API action. An outline of the API is specified in issue #8.
The version action is used to retrieve information about the latest version of the software, and a url to the download location.
URL: https://www.youstore.com/itelic-api/version/
Verb: GET
If the request is successful, i.e. a valid, active license key, the following response will be returned.
Code: 200 OK
{
"success": true,
"body": {
"version": "1.2.1",
"package": "https://www.yourstore.com/itelic-api/secure-download-link",
"expires": "2015-11-21T16:05:30"
}
}
success
– Boolean field representing if the response is successful, For handling error conditions, see Error.body
– Object containing the response body.
version
– String representing the current version of the software productpackage
– Encoded download URL.expires
– ISO 8601 representation of when the download URL expires. Default value is 24 hours after request.This will cover all possible errors, besides an authentication error resulting from not passing any license key. The message string MAY be changed in the future. The error code MUST NOT be changed.
Code: 402 Payment Required
Returned when the license key being used is Expired.
{
"success": false,
"error": {
"code": 02,
"message": "Your license key has expired."
}
}
A simple drop-in class will be provided for use in WordPress themes to provide automatic updates. Updates will be made available in the typical WordPress fashion.
A simple drop-in class will be provided for use in WordPress plugins to provide automatic updates. Updates will be made available in the typical WordPress fashion. We will also autofill the various fields in the plugin modal: i.e., name, description, banner images, tested up to, etc... The updater class will make use of the API described in #8.
This issue describes the /download/
API action. An outline of the API is specified in issue #8.
The download action is used to force the download of the latest version of the software.
URL: https://www.yourstore.com/itelic-api/download/
Verb: GET
If the request is successful, i.e. an active API key, the latest version of the software will be downloaded. Most commonly the software will be in zip
format.
Code: 200 OK
This will cover all possible errors, besides an authentication error resulting from not passing any license key. The message string MAY be changed in the future. The error code MUST NOT be changed.
Code: 402 Payment Required
Returned when the license key being used is Expired.
{
"success": false,
"error": {
"code": 02,
"message": "Your license key has expired."
}
}
Allow for license keys to be pulled from a list per-product. List should be stored in post meta for the product.
The settings form for this key type should display a disabled
textfield with a fixed height and width as well as a button. When the button is pressed a WordPress Thickbox should popup that allows for a list of license keys to be copy and pasted into a textfield, and an upload button for uploading keys from a list. When finished, user presses Done – closing the Thickbox and displaying the keys in the disabled
textfield.
In the Licenses
admin page, there will be an additional tab called Reports
. This will displaying various charts and tables sectioned off in groups by the type of data the charts are representing.
An additional Account sub-page should be registered call Licenses. This will display a list of all of the customer's licenses, their status, the product, a link to see the initiating transaction, and a link to see the active install locations. On this page, they should be able to remotely deactivate any of those install locations. Additionally, they should be able to activate a license location. This would probably only make sense if the product is something installed on Websites, allowing for an easy UX.
Licenses can be renewed in a variety of manners.
Super Widget. When in the Super Widget for a product, an additional option will be added to Buy Now and Add to Cart called Renew. The system will then look up the originating transaction. This will prompt the user for their license key. If the transaction was a Guest Checkout payment, then the user will be prompted for the email address they initially used. Otherwise the user will be prompted to login. The product will then be added to the cart.
Checkout. On the checkout screen, a button will be presented allowing users to renew their license by entering their license key. If the user is logged in, they'll be able to mark their order as a renewal without having to enter a license key.
Account Purchases Page. A button will be added to the account/purchases page for each licensed purchase allowing users to renew their license key. This will redirect the user into the Super Widget with the renewal option already selected, and, naturally, the license key pre-filled.
We should add Help tabs to all of the admin screens. We'll need a way to filter based on the current tab, and current view.
An arbitrary number of renewal notifications can be created. These can be fired n days before and n days after a license key expires. There should be a distinction made between renewal notifications for automatic renewing keys and manual renewing keys.
The following substitutions should be made available.
The renewal reminders should be automatically sent out via a daily cron job.
Licensing will ship with a basic API for interacting with license keys. Initially, the plugin will have to register its own endpoints, because the WP REST API is not yet released. When the WP API is released into WP Core, Licensing will register its endpoints through the WP API, while retaining back-compat with the old endpoints. As such, the handling of global state, super globals, URLs, etc... should be abstracted away as much as possible from the core API to facilitate an easier transition process.
This Issue will describe the overall API. Specifics on endpoints and actions will be covered in their own issues.
The API will be consumed using JSON. The API will be accessible at site_url()/itelic-api/{$action}/
.
The following are the currently supported API actions.
/activate/
POST
. Activate an API key for a certain location./deactivate
POST
. Deactivate an API key for a certain location./info/
GET
. Retrieve information about a key: status, expiry date, location, etc.../version/
GET
. Retrieve the latest version for the product the API key grants access to. Includes download URL./download/
GET
. Force download of latest version./product/
GET
. Retrieve information about the product. Tested up to, Version, Banners, etc...All requests require a license key passed via the BasicAuth username field. The password field is left blank. If an API key is not present, 401 Not Authorized
header will be returned. For actions that require an active key, but the key passed is expired, a 403 Forbidden
header will be returned.
All requests SHOULD be made over HTTPS. But the API will not reject HTTP requests.
Another filter action should be implemented to filter the releases table by the expiry date. You should be able to filter by month, six months prior to and twelve months after the current month.
Allow for editing the changelog with tinyMCE, instead of just a plain text area.
Currently, when trying to make the substitution, tinyMCE freezes, unless the page was initially loaded with tinyMCE in the "text" mode.
We need an automated way to archive releases. There are a couple of options.
Lastly this could be either a UI configuration or a filter.
Admin page showing information about a particular license key.
A table of all activations of a particular license, including not only active activations, but deactivated and expired activations as well.
An active activation can be deactivated, and any deactivated activation can be reactivated. Additionally, an activation record can optionally be completely removed from the DB.
License keys can be activated for an installation location. This will be done using a regular text input for capturing the installation location, and an "Activate" button for triggering the remote activation.
In the Licensing admin page, see #17, on the Licenses view, a paginated list table should be displayed representing all of the licenses created on the site.
The list table will have the following columns. Nested list items represent row actions.
An additional admin page should be registered under the Exchange menu called Licensing. Similar to how it is handled in Classes, there will be a tab interface on the top of the page.
Admins can toggle between the Licenses view and the Reports view. In brief, the Licenses view contains information about all of the license keys created on the site and the Reports view graphs renewals over time.
One section in the reports tab (#40) is called Products. The following information will be displayed.
By default licenses last forever. If the Recurring Payments add-on is activated, then the license key's active period will be restricted to the options set out in RP.
If auto-renewal is disabled, then after the purchase period is finished, the license should no longer be valid.
If auto-renewal is enabled, then the license will be valid, for as long as the recurring payment persists.
Customer's need to have a way to easily upgrade from one license type to another license type.
This would probably be done in a similar manner to how we handle renewals. We will add an additional button to the Super Widget prompting people to upgrade their license if they have an existing license for this product.
The upgrade price would be the new price, minus the existing price.
To add a new license key by hand, the Manual Purchases add-on must be active. The user will do this through the manual purchases flow.
If a user selects a digital download with licensing enabled, the following fields will appear.
Once the key has been generated, the user will be redirected to the license single view.
In the activations list we should display the currently installed version for that activation.
Each release has its own type.
Major releases are from 1.5 to 1.6. In the admin, these releases will be marked as major, and will recommend backing up before updating.
Minor releases are from 1.5.1 to 1.5.2. These do not have any special demarkations.
Security releases fix a security bug. In the admin these are marked as such, and recommend immediate upgrading.
Pre-release releases are alpha or beta releases. These releases won't appear by default. Instead when a user activates a license key, they need to sign up for pre-releases. An activation can be PATCH
ed to enable or disable pre-releases.
Restricted releases are limited to only certain license keys. These license keys can be specified when creating a release, or while editing a release.
The user interface for restricted releases is a bit complex. Releases are restricted by license keys. The restricted releases also require an incrementing version number see issue #33.
The UI for this is a bit tricky. Ideally, a user can search for a license key directly, by customer, or by activation location ( website ). Each of these search options will return results formatted in a list, with each result displaying the license key, license status, and customer. If the user searches by activation location, the user will need visual confirmation of some kind.
When the result is selected, it will be appended to the list of whitelisted license keys. This will be saved via ajax.
When a customer goes to create a release, we display the current version number next to the text input. There is currently nothing preventing the user from creating a release with a version number less than the current one. We should validate the version number in javascript as the version number is inputted.
Users can draft releases. This makes it possible for a user to draft a release, r1, with version 1.1. Then create another release, r2, with version 1.2. If the user then activates r2, we need to prevent the user from releasing r1 because its version number is now outdated. To accomplish this, we should display a warning message on top of the outdated release and prevent the user from toggling the status to Active.
Releases and upgrades will be stored in separate tables.
Releases
ID
. Unique, auto-generated, primary key.product
. ID of the corresponding product.download
. ID of the corresponding Exchange download post.version
. Varchar storing the version number.status
. Varchar of the status.type
. Varchar of the Release type.changelog
. Text of what changed just in this version.start_date
. Date and time of when the releases was started.Updates
ID
. Unique, auto-generated, primary key.activation
. ID of the activation record.release
. ID of the corresponding release.date
. Time of the upgrade.Store owners can optionally setup a license renewal discount that will be automatically applied at checkout – see #3. The renewal discount can be overwritten on a per-product basis. This should be treated as a separate product feature, that is only displayed if licensing is enabled for the current product by checking the enable checkbox. The product feature should always be registered, and rendered. However, the product feature should be initially hidden from view. When the enable checkbox is checked, the product feature should automatically be displayed.
The discount has a variety of options.
How should renewal records be stored? Renewals will be charged as a child transaction. So that will take care of the detailed information about renewals.
The main requirement is that we need someway to report on the rate of renewals. i.e. in the month of September, 150 licenses expired, and 100 were renewed. This is complicated by the fact a license often could not be renewed at the same time as the license expires.
The child transaction does have a post date, and references the parent transaction which would have generated the original transaction. The question is if that'd be efficient. We'd have to do something along the following to get all of the renewals.
SELECT * FROM wp_posts WHERE post_parent IN ( SELECT transaction_id FROM wp_itelic_keys )
Users can create a new release from the Releases tab in the licensing admin area. The following are the steps the user will go through. Each step should only reveal itself as necessary.
At this point the view will transition to a clear screen, with a button prompting them to "Notify Your Customers" or "Continue to Release".
If they select Notify:
wp_editor
instance. Template tags will be made available.License keys should be displayed in the following places on the front-end.
This issue describes the /activate/
API action. An outline of the API is specified in issue #8.
The activate action is used to activate a license key for a particular location.
URL: https://www.yourstore.com/itelic-api/activate/
{
"location": "http://www.install-location.com"
}
location
– Location of this install. For plugins and themes, this would be the URL of the website it was installed on. Otherwise any unique identifier can be used. Ideally, this should be human readable, but could be appended with a unique hash. Max length: 255 chars.If the request is successful, i.e. an active API key, the following response will be returned.
Code: 201 Created
{
"success": true,
"body": {
"id": 143,
"activation": "2015-05-22T13:45:56",
"deactivation": "",
"location": "http://www.install-location.com",
"status": "active"
}
}
success
– Boolean field representing if the response is successful. For handling error conditions, see Error.body
– Object containing the response body.
id
– Unique ID representing this install location.activation
– ISO 8601 representation of the time of activation.deactivation
– ISO 8601 representing the time of deactivation.location
– Location of this install.status
– The status of the activation. One of active
, deactivated
, expired
. This will be active
for a fresh activation.This will cover all possible errors, besides an authentication error resulting from not passing any license key. The message string MAY be changed in the future. The error code MUST NOT be changed.
Code: 403 Forbidden
Returned when the maximum number of activations has been reached before this request.
{
"success": false,
"error": {
"code": 01,
"message": "The maximum number of activations of this license key has been reached.."
}
}
Code: 402 Payment Required
Returned when the license key being used is Expired.
{
"success": false,
"error": {
"code": 02,
"message": "Your license key has expired."
}
}
On the single key view we should display a list of renewals for that key.
This would display the date that the renewal took place, and a link to the renewing transaction.
The changelog should be editable with Markdown. The API should support retrieving it as Markdown, HTML, or Plain Text.
Delete, Extend, and Send Renewal Notice bulk actions must be implemented.
Consider adding extend.
Ideally, it'd be nice for releases to be automated via services like GitHub. For example, whenever a new release is made on GitHub, a release could be drafted by pulling the version number, changelog and new download file.
Each release has its own view/edit page in the admin. This is accessed via the releases list page.
On the top of the page the following information will be displayed.
The percentage of licenses upgraded will update automatically via the Heartbeat API. A cool looking and useful graph would be nice. Perhaps a graph of upgrades over time.
Optionally, the user can click a button to reveal all of the upgrade records. This will be a table paginated with AJAX.
Finally, a user can write an email to be sent to all of the users who have not yet upgraded to the latest version.
We should add support for variants.
We would be registering a new variant type, similar to colors. The user would be able to control the name of the variant, and how many activations the variant would be good for. So a user could setup an option for selling a license with a max activation count of 1, or 5, or unlimited.
One section in the reports tab (#40) is called Licensing. The following information will be displayed.
One section in the reports tab (#40) is called Renewals. The following information will be displayed.
The releases list table should support filtering by the following:
This issue describes the /info/
API action. An outline of the API is specified in issue #8.
The info action is used to retrieve information about a license key.
URL: https://www.yourstore.com/itelic-api/meta/
Verb: GET
As long as a license key is used for authentication, this request will always be successful.
Code: 200 OK
{
"success": true,
"body": {
"transaction": 423,
"product": 231,
"customer": 32,
"status": "active",
"max": 5,
"activations": {
"count": 2,
"count_active": 1,
"list": [
{
"id": 143,
"activation": "2015-05-22T13:45:56",
"deactivation": "2015-05-29T01:31:45",
"location": "http://www.install-location.com",
"status": "deactivated"
},
{
"id": 147,
"activation": "2015-05-22T13:45:56",
"deactivation": "",
"location": "http://www.other-install-location.com",
"status": "active"
}
]
}
}
}
success
– Boolean field representing if the request was successful.body
– Object contain the response body.
transaction
– Originating transaction ID.product
– Product this key is licensed to.customer
– Customer ID this key belongs to.status
– Status of this license key. One of active
or expired
.max
– Maximum number of concurrent activations.activations
– Object containing information about this key's activation history.
count
– Number of total activations.count_active
– Number of active activations.count_deactivated
– Number of deactivate activations.list
– Array listing the activation history of this key.
id
– Unique id identifying this activation.activation
– ISO 8601 representation of the time of activation.deactivation
– ISO 8601 representation of the time of deactivation. MAY be empty.location
– Location of this activation. SHOULD be unique.status
– Status of this activation. One of active
, deactivated
, expired
.This issue describes the /deactivate/
API action. An outline of the API is specified in issue #8.
The deactivate action is used to deactivate a license key for a particular location. The location can be specified using the activation id
returned by a successful activation OR the unique location
value passed when activating, see #9.
URL: https://www.yourstore.com/itelic-api/deactivate/
{
"location_id": 143
}
location_id
– Activation id returned from #9.If the request is successful, i.e. a valid identifier, the following response will be returned.
Code: 200 OK
{
"success": true,
"body": {
"id": 143,
"activation": "2015-05-22T13:45:56",
"deactivation": "2015-05-29T01:31:45",
"location": "http://www.install-location.com",
"status": "deactivated"
}
}
success
– Boolean field representing if the response is successful. For handling error conditions, see Error.body
– Object containing the response body.
id
– Unique ID representing this install location.activation
– ISO 8601 representation of the time of activation.deactivation
– ISO 8601 representing the time of deactivation.location
– Location of this install.status
– The status of the activation. One of active
, deactivated
, expired
. This will be deactivated
for a fresh deactivation.This will cover all possible errors, besides an authentication error resulting from not passing any license. The message string MAY be changed in the future. The error code MUST NOT be changed.
Code: 404 Not Found
Returned when the activation could not be found. Either because of an invalid activation id or install location.
{
"success": false,
"error": {
"code": 03,
"message": "Activation record could not be found."
}
}
One section in the reports tab (#40) is called Upgrades. The following information will be displayed.
This is a tracking ticket for the overarching goal of "Releases." Instead of developers changing the update file, updating the version, and updating the changelog to initiate a new release, developers will use a custom release interface. This will provide more power and customization, while making the process more intuitive.
Releases will be a new tab in the licensing admin page. The index page will list all of the releases in a WP_List_Table
. The releases can be filtered down by product and/or status. Additionally, an Add New button will be on the top of the screen. From here a user can create a new release.
A release has three choices for a status:
There are also multiple types of releases:
The licenses list table should support filtering by the following:
The list table should allow for passing a customer
parameter in the $_GET
variable.
Releases need a way to be archived. Archiving a release reduces the amount of data we have to store.
A release can only be archived if it isn't the latest release. Releases can be automatically archived after a certain amount of time.
When an archived is released, we aggregate all of the data in the itelic_updates
table for that release, and delete all of those rows.
Although bulk products are not yet a think in Exchange, we should plan to be able to support bulk products in the future. There are two mechanisms in which this could work.
An additional tab in the customer data area should be added called Licensing.
This will display a list of the users license keys. Both expired and active. Each license key should link to the single license view.
This issue describes the /product/
API action. An outline of the API is specified in issue #8.
The product action is used to retrieve information about the licensed product.
URL: https://www.yoursite.com/itelic-api/product/
Verb: GET
If the request is successful, i.e. an active API key, the following response will be returned.
Code: 200 OK
{
"success": true,
"body": {
"name": "Your Licensed Product",
"description": "This is the description of the licensed product.",
"version": "1.5.4",
"tested": "4.1",
"author": "TimothyBlynJacobs",
"last_updated": "2015-02-15",
"banner_low": "https://www.yourstore.com/product/banner-low.png",
"banner_high": "https://www.yourstore.com/product/banner-high.png",
"package_url": "https://www.yourstore.com/itelic-api/secure-download-link",
"description_url": "https://www.yourstore.com/product/",
"changelog": "This is the changelog of your product"
}
}
This will cover all possible errors, besides an authentication error resulting from not passing any license key. The message string MAY be changed in the future. The error code MUST NOT be changed.
Code: 402 Payment Required
Returned when the license key being used is Expired.
{
"success": false,
"error": {
"code": 02,
"message": "Your license key has expired."
}
}
Another filter action should be implemented to filter the keys table by the expiry date. You should be able to filter by month, six months prior to and twelve months after the current month.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.