If you have some software or an add-on, and you want to find a way of giving a free trial that expires, one way is to create a token code that has all that built in. Here’s a way to do it using Apps Script.

The coupon code

A generated code looks like this

prefix-part1-part2

where

  • prefix is a plain code you can use to identify which kind of coupon this is.
  • part1-part2 is generated cryptogram that is used to decide whether the code is valid and what its expiration date is

Encryption

To decode a coupon code, you need to know the private key and algorithm key with which it was created. Both are needed to sign and hash the coupon code

Using

The cCoupon library is available here

1X-tyDMF_iILp3cQ4MMCY0GQwrOPHl8ocKtWhqVuw1u5PG5wMytL6mjOP

or you can get the source from github.  If using from the library, then you can define Coupon as

Examples

Let’ say you want to generate a coupon for some promotion, lets call it xmas. You’ll want to give it an expiry date that you can check later when the coupon is redeemed, but you also want to ensure that the coupon is a genuine one that you created using your private key and algorithm.

A coupon code could look like this, and is generated as per the examples below

Private key

This is any string (I’ve the minimum length at 6 characters, but longer is better), and you’d probably store this securely away in your Apps Script PropertiesStore.

Expiring at a specific time

Here you specify a specific time as a timestamp. This is later decoded from the coupon code and is used to decide whether the coupon has expired

– this generates

Expiring in some days

This allows you ask for a code that expires some number of days from now.

– this generates

Expiring in some months

This allows you ask for a code that expires some number of months from now.

– this generates

Number of days valid from redemption

Sometimes you want the code to have an expiry date for redemption, but to have a trial period starting at the date of redemption. Each of the examples above can take an extra parameter that is the number of days the coupon lasts for from the day of redemption. In this case the code contains not only the expiration date (when it has to be used by), but also the number of days it’s valid for from redemption.

This example generates a coupon that’s valid for a year, and has a 28 day trial period from the date of redemption –

Of course you’d need some caution with that one, because since the expiration is valid for a year, there’s nothing to stop it being used multiple times within that period – there’s no way to know if a token has already been used unless you record somewhere – in the property store or somewhere else – that a token has been redeemed.

Creating a coupon code specific to a user

Let’s say you want to create a coupon code that’s specific to a particular user.  All you need to do here is to add some user id to your private key. When you app checks the validity of the token, it will only be reported as valid if you decode it with the same user id appended to your private key –

You could of course use this same technique to keep the same prefix and private key but apply it to different apps.

For example:

Would create an entirely different code from;

even though both codes would start with

Decoding

To decode a coupon, you need to know the private key it was created with. Let’s take a look at all the keys we generated earlier.

gives this

 property  description
 expiry  a timestamp for when the coupon code expires
 valid  where the code is valid
 prefix  the prefix
 coupon  the coupon code
 expired  whether the thing has expired now
 extraDays  the number of extra days. This would be the value for a coupon that has some days available from the redemption date
 extendedExpiry  If there are extraDays and the token was redeemed now, this is when it would expire

The others follow the same pattern. Let’s look at what you get when you have extra days built in to the token, as in the example

If the coupon were to be redeemed now, then the expiry date is in the extendedExpiry property timestamp.

Specific use code
If we have included some kind of user specific info in the encryption, as in the example

then , we need to also include that in the decoding process, as in this example

which produces this

Expired code

Let’s say a code is valid, but has expired – I’ll deliberately create and decode one that expires yesterday like this.
var couponCode = Coupon.generateDays(privateKey, -1 ,’xmas’);
var decode = Coupon.decode (privateKey , couponCode);

then the code is valid, but expired as below

Invalid code

Using a completely invalid code will of course result in an invalid decode.

Using the wrong private key will also be invalid

As will using a code generated with the wrong specific user info

By the way, none of the codes shown here will be valid for you, as I used a different private key than this to generate them.

Algorithm key and signature size

This is built in to the library. If you make your own copy of the code, you can change the algorithm key to something else. You’ll find them at the top of the Coupon namespace. Both the algorithm key and your private key are needed to create and decode coupon codes. The signature size can also be changed. This controls size of the key, and should be at least 3, and you can increase it for stronger encryption but longer code sizes. If you change any of these, then any previously generated keys will no longer be decodable and will report as invalid, just as will happen if you use a different private key.

Specific codes for Anonymous users

If you need to generate codes for specific anonymous users, you can use the library in Anonymous user registration with the Apps Script PropertiesService to generate an maintain anonymous ids, and then apply those ids as part of the encoding and decoding.

How to use

The cCoupon library is available here

1X-tyDMF_iILp3cQ4MMCY0GQwrOPHl8ocKtWhqVuw1u5PG5wMytL6mjOP

or you can get the source from github

For more like this see Google Apps Scripts Snippets
Why not join our forum, follow the blog or follow me on Twitter to ensure you get updates when they are available.