At this point, I am more or less aware of how the whole flow of my project is gonna work, after having a fruitful discussion with Dr Shawn. Let me first summarize the flow from the perspective of the customer:
- Customers can subscribe to a license, in accordance to their prefered category, i.e Hobbyists, Professionals, Organizations, etc.
- Upon purchasing the license successfully, they will be given a download link to whereby the certificate would be automatically installed in their browser. A copy of that certificate would be emailed to them, as soon as the certificate is successfully installed.
- Customers would continue receiving new valid certificates at a period following the subscription they pay for (e.g: certificate valid for 1 month for a monthly subscription), as long as they continue to renew their subscription by paying before or at the due date.
- They can cancel, upgrade or downgrade their subscription at any time. More on this later.
Now let’s go into a little more detail of how each points above could be implemented.
Creating New Subscriptions
Fortunately, WooCommerce has webhooks for subscription Created, Updated, Deleted and Switched. When the customer has completed the Checkout page, the Subscription Created and Subscription Updated webhooks would be triggered and the request is send to 4k’s backend. However, in this case, the server would only process the Created webhook, by extracting the subscription ID and saving it to a database, marking it as a CREATED event. The purpose of having a database is to keep track of new and renewing subscriptions, but will only be temporary until the end of the flow, where the certificate installation would take place. Note, that other crucial data does not need to be stored in the database, as they are already available in the JSON payload. At this point, the customer has not paid yet. The status of the subscription now is ON-HOLD or PENDING.
When payment has been successfully made, the Subscription Updated webhook is triggered, but with the subscription status now ACTIVE. As a result, a new certificate would be created, but it will be issued by an intermediary CA, depending on the subscription product they buy. We decided that each subscription product will have an attribute in which the value contains the fingerprint of the parent certificate or the intermediary CA, so we can identify which intermediary CA is the issuer. If the product is an Organization product, then a new intermediary CA certificate would be created. The DN attributtes of the new certificate would contain all the info regarding the customer, such as name, country, state, etc. For the SAN attributes, like domain name or IP address, which is necessary for organizations like schools or companies, they would be specified as attributes for the product. For Individual certificates, the email SAN attribute would be obtained from their billing info in the webhook’s JSON payload. The fingerprint of the certificate would be saved to the database along with its corresponding subscription. We will see its use later on.
The certificate would be temporarily stored in a special directory in the server, which brings us to the next section.
Now, we would send a email to notify the customer that their payment has been processed and they’re now in an active subscription. In the email, there would also be a download link to the certificate, which would make a request to a REST API in the backend. From there, the server would first request for any valid certificate. You would see why this is done later. However, since the customer has no valid certificate, the server installs the newly created certificate into the browser. After that, the link is refreshed, which prompts the server to ask for a valid certificate again. This is to verify the installation. If the valid certificate is presented, then the installation was a success, otherwise, try again. When installed successfully and the valid certificate is presented to the server, it would show a success page of some sort and then at the same time email a copy of the certificate to the same customer. In the backend, the database entry for this subscription would be removed as I mentioned before that the database is only needed for tracking purposes, not persistent storage.
The customer is expected to renew their subscriptions at a specified time interval. As mentioned in my previous post, either manual or automatic renewal could take place. If its manual renewal, then a reminder email is sent to the customer to pay up by the DUE DATE. On the other hand, if its automatic renewal, then the payment is processed automatically by the DUE DATE. For both renewal process, by the time the recurrent payment is due, the subscription would be in ON-HOLD status, until the payment has been made. The Subscription Updated webhook would be triggered as a result, and again we temporarily save the subscription ID to the database but mark it as a RENEWAL event. When the payment has been finally made, the Subscription Updated is triggered again and the subscription status is ACTIVE again, thus it goes through the same flow as creating a new subscription before.
Notice that what I described above happens when DUE DATE for the renewal payment is reached. It is also possible for customers to pay for the renewal before the DUE DATE, hence the same renewal process would be followed through. But if that happens, it means that their current certificate that they are having is still valid as its validity period is until the next payment date. Which is why the server prompts for a valid certificate first when the download link is clicked. For this case, the currently still valid certificate would be given to the server, and it could check that the certificate was a previously purchased certificate that is still in its validity period by comparing its fingerprint with the fingerprint of the new certificate that was saved into the database and the event of the subscription is a RENEWAL event as well, which can be looked up using the subscription ID.
To handle that, the server should revoke the existing certificate and proceed to install the new certificate like before.
Certificates need to be revoked when the customer cancels their subscription, downgrade or upgrade their subscription or renew their subscription at an earlier date. The revocation is done through a Certificate Revocation List (CRL). At the moment, I do not know much about CRL, but I know that later on in the project, I would need to use it eventually. I’ll save that for a blog post later on. The downgrading and upgrading of a subscription would trigger the Subscription Switched webhook. What determines a downgrade or an upgrade of a subscription? Basically, if the customer switches to a subscription which is more expensive on a daily basis, then its an upgrade, else its a downgrade if the new subscription is cheaper on a daily basis. You can find more info about this from this WooCommerce doc. Note that the switching is only possible between variations of a Variable Subscription or Simple Subscriptions in a Grouped Product, as outlined in the doc. The time frame for the subscription would change, hence the current valid certificate the customer has is to be revoked and a new certificate that has the new time frame would be given instead.
Wow, that’s a lot to be said. I hope you are still with me at this point of the blog. Now that we have established some basic flow for the application, its time to start implementing and putting my gears to work. Of course, I expect that some changes may need to happen mid-way implementation, things don’t always go as planned. But we will see about it in the weeks to come.