Validating a receipt

A receipt is proof that an app buyer has purchased your app. A receipt encodes an affirmation by a payment processor that a particular user has completed a transaction to acquire a particular digital product. The receipt is sent to the user's machine after the user has paid for an app on the Mozilla Marketplace. The receipt is placed on the user's machine using the second argument to the mozApps.install() method.

If you have a paid app, you should check that a user has a valid receipt. If you do not check, someone can buy the app, get an immediate refund, and then have the app for free.

When to validate a receipt

You have to decide when the app will validate the receipt. A usual time to validate is when the user starts the app. If it's a long-running app, you might want to validate on a regular schedule. Netflix, for example, checks the receipt every 20 minutes.

Note that if the user is offline, the app will not be able to validate the receipt. What the app does in this situation is up to you. To avoid some user annoyance you might want to be lax on enforcing the receipt checking (let's say the user is temporarily in a tunnel), and just keep trying until the user is online again.

How to validate a receipt

The simplest way to validate a receipt is to use the Mozilla Marketplace validation service. If your app is HTML-only, where the server doesn't do anything but serve static files, you can use the following JavaScript library:

Include this script in your app and use the verify() function. See the GitHub page for more information. The service will analyze the receipt and respond with one of the following values: "ok", "pending", "refunded", "expired" or "invalid". Have the app act accordingly.

More information on validation

You might also need to handle the validation in a more manual way, so here is more information on that.

The receipt used by an Open Web app is a portable, verifiable proof of purchase token. It is a digitally-signed JSON data structure called a JSON Web Token (JWT). This format is universally readable by clients and servers. There are JWT libraries available for many programming languages.

Without using a JWT library, you can find the URL for the validation service in the verify field in the receipt, and then send the receipt to the validation service. Each app has a different URL to the Mozilla Marketplace validation service.

The code sample below will show the verify URL in the receipt. The code is set up to be used in the Firefox web console developer tool.

var req = window.navigator.mozApps.mgmt.getAll();
req.onsuccess = function() {
  // Get the first receipt of the first app and decode it

To get the verify URL, this sample does the following things:

  • Saves the return from mozApps.mgmt.getAll() in a variable. getAll() returns an array of App objects.
  • Goes into the first App object, and splits up the JWT to get the part that contains the receipt.
  • Decodes the Base64-encoded receipt using the JavaScript atob() function.

The following is a pretty-printed example of the result of the code above. It is a full receipt, minus the JWT parts.

  "product": {
    "url": "",
    "storedata": "id=111111"
  "iss": "",
  "verify": "", // The verify URL
  "detail": "",
  "reissue": "",
  "user": {
    "type": "directed-identifier",
    "value": "1234-abcd99ef-a123-456b-bbbb-cccc11112222"
  "exp": 1353028900,
  "iat": 1337304100,
  "typ": "purchase-receipt",
  "nbf": 1337304100

Once you get the verify URL, use the POST method to send the full JWT in the body of a message. The validation service response is described above. This snippet would get the full JWT in the sample above:


Note that the cryptographic aspects of a JWT are not dealt with in the code above.

Combating app piracy

Even if you validate receipts for your paid app, it can be pirated if someone passes around the receipt. The receipt validation methods given above do not prevent this.

If you want a better defense against piracy, you might want to set up a proxy server that will be an intermediary between the app and the Mozilla Marketplace. The proxy server can check the receipts, IP addresses and other things. The server might do something like notice if the same receipt was coming from different IP addresses and take some kind of action. This setup is probably more appropriate with big complicated apps that use server processing.

This Python code is an in-progress project that could give you some ideas for a proxy server. Here is more information on verifying receipts yourself.

Receipt fields

A receipt contains the following fields:

This must be the string "purchase-receipt".
JSON object identifying the product that the receipt covers and any store-specific data. It has the following fields:
  • url - URL representing the root of a domain, without a trailing slash (for example, ""). This is conventionally defined to represent "a web application". URLs rooted further inside the site are conventionally defined to represent "in-application purchases", and can use whatever path scheme is convenient to the developer and issuer of the receipt.
  • storedata - A string that uniquely identifies this app for the verifier of the receipt.
JSON object containing a user ID for the user who made the purchase.  It has the following fields:
  • type - A string with the value "directed-identifier".
  • value - A string that is a unique ID for the user. A given user will show up as a different user ID for each app he purchases.
Domain for the store that issued the receipt.
"Not-before" timestamp indicating when the purchase was completed. The timestamp is the number of seconds from 1970-01-01T00:00:00Z in UTC, RFC 3339.
"Issued-at" timestamp indicating when the receipt was issued. Same timestamp format as nbf. You can use this value to determine the age of the receipt.
(optional) Expiry timestamp indicating when the receipt will expire. Same timestamp format as nbf.
(optional) URL that contains additional human- or machine-readable detail about the purchase. If a transaction log or refund capability is provided for the purchase, it is expected that this page will contain those functions.
(optional) URL that can be used by an authenticated application to verify a receipt. Note that the Mozilla Marketplace always provides this field for an app. If you are going to create your own app marketplace, you might not use this field.
(optional) URL that can be used to re-issue a new receipt.

Tags (1)

Edit tags

Attachments (0)


Attach file