Many parts of Polymart require JavaScript to function correctly.
Click here to enable JavaScript.

Placeholders

Back to Wiki Home
For all resources (both paid and free), you can take advantage of placeholders. You can verify that these placeholders are authentic by using the /v1/verifyPurchase API Action.

For paid resources, every placeholder will have a value. For free resources, only some placeholders are replaced.

We recommend that you also use Polymart's automatic obfuscator to combat piracy. The obfuscator will automatically encrypt all of the placeholders in your .jar file, among other things, making it much harder to pirate your plugin.

%%__SIGNATURE__%% is an advanced placeholder that can not be spoofed, and can be used to get information about the resource download and the identity of the user who downloaded. It impossible to generate a valid signature without downloading the resource from Polymart. You can get more information about it in the advanced placeholders section below. If you're looking for something that's a little easier to use, you should check out the %%__VERIFY_TOKEN__%% placeholder.

Remember that anyone can modify a file once it's downloaded, so there's no way to completely stop someone who's truly determined and has the right skill sets — but, we can make their lives so hard that they don't even try.


Here's yet another thing that other marketplaces can't do: Every placeholder on this page will get replaced with it's respective value, no matter where it is. It can be in a .jar file, inside of a compressed .zip upload, or even inside of a .jar file that's inside of a .zip file that's inside of another .zip file that's inside of a .jar file. Cool, huh?


%%__USER__%%
Replaced with the user's ID. The user's profile at https://polymart.org/user/%%__USER__%%.
This will always have a value for paid resources. For free resources, this will be "-1" if the user isn't logged in.


%%__USERNAME__%%
Replaced with the user's username on Polymart. Keep in mind that users can change their usernames, so if you need to uniquely identify a user, you should use %%__USER__%% instead.
This will always have a value for paid resources. For free resources, this will be "-1" if the user isn't logged in.


%%__RESOURCE__%%
Replaced with your resource's ID on Polymart. The resource is at https://polymart.org/resource/%%__RESOURCE__%%
This will always be replace in all resources


%%__NONCE__%%
Replaced with a unique identifier for the download
This will only be replaced in paid resources


%%__RESOURCE_VERSION__%%
Replaced with the version of your resource that was downloaded from Polymart. This is the version on Polymart, and will only match what you have in the plugin.yml if you give the two the same value. If you want your plugin.yml to always have the same version number as what you upload to Polymart, set the "version" in the plugin.yml to "%%__RESOURCE_VERSION__%%"
This will always be replaced in all resources


%%__VERIFY_TOKEN__%%
Replaced with a token that can be used to verify the download using the /v1/verifyPurchase API action. If you want to make use of the API action, you'll also need to include all of the placeholders on this page.
This will only be replaced in paid resources


%%__POLYMART__%%
Replaced with a "1". So, if your resource was downloaded from polymart, this will be replaced with "1". If it was downloaded from somewhere else, it will stay as "%%__POLYMART__%%".
This will always be replaced in all resources


%%__AGENT__%%
Replaced with an ID for the agent that downloaded this resource. If the resource was downloaded directly from Polymart, this will be a string of one or more 0's. If it was downloaded using a token from the Developer API, this will be the ID of that token.
This will only be replaced in paid resources


%%__TIMESTAMP__%%
Replaced with the time at which the resource was downloaded (seconds in epoch time)
This will always be replaced in all resources


If there's any placeholders that you think would be useful, but aren't currently supported, shoot us a message and we'll add them as soon as possible


Custom Placeholders
You can add custom placeholders to your resource, and even make them different for each version, if you want! You can also use this for anti-piracy by doing operations on information about the downloading user. For more information, please Contact Us


Advanced Placeholders
If you plan to use placeholders for automatic piracy prevention, you must first test your system and ensure that it doesn't generate false positives. These only work for paid resources.


%%__RSA_PUBLIC_KEY__%%
Replaced with the websafe contents of the 2048-bit RSA public key for your resource. The contents of RSA keys are normally base64-encoded, but remember that Polymart turns the base64 into websafe base64. Websafe base64-encoding replaces all "+" with "-", replaces all "/" with "_", and removes all "=" from the original base64 string. Use this public key to decrypt %%__SIGNATURE__%%. The key is encoded according to the X.509 standard.

For example, it might look something like this:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4fcZHVjpsBVjTGxlf2miXfGiCH71eMbEAlhCof-QZOC5CZV1EV03f9ufQIJN6bTOY3TxppB65KImQYHPY1q05hCeM9odkjDVKBZri-HGRcLdXCce_nU-55H1szTESza8JmtCaGn70Y_NOqhCBcr5xjufoCjHzHNnTOwmoNI2dIVD2PAEl7MwL2jqvj0NoMs53NVvW2MA5hLLNUuxpemojOj2HaL8btid0av1Z2MVJsRhB524UVW75xiUQ8InzWO0M4Cn9bsNhOIcKw4BUpBnpRrqM5n9iKr6uk7tLjJNP_6zAT5d3hotPzGSHru2b2Fd-Y_mJ2JuS2dSr6FSR9pU8wIDAQAB

%%__SIGNATURE__%%
Replaced with a web-safe base64-encoded string. It encodes an encrypted JSON string, which is encrypted using your resource's RSA private key (which only Polymart knows). The encrypted JSON string contains information about the resource download.

The string can be decrypted using the RSA public key in %%__RSA_PUBLIC_KEY__%%, and is padded using OpenSSL PKCS1.

The JSON string that is encrypted will contain the following information:
{
  "ver": "%%__INJECT_VER__%%",
  "resource_ver": "%%__RESOURCE_VERSION__%%",
  "user": "%%__USER__%%",
  "resource": "%%__RESOURCE__%%",
  "nonce": "%%__NONCE__%%",
  "agent": "%%__AGENT__%%",
  "timestamp": "%%__TIMESTAMP__%%"
}
This is then encrypted using your resource's private key. Then, the encrypted string is encoded as websafe base64. The result might look something like this:

LLK7UqXjRHXotXIhMQSGaDQj2K2i7jDJs6Ief1CR5dHjg03D2e3HcT14rL61Dxq3B2F68y436sbd2HzhYCsP5tNQWaVJxt5YOaXpu1lI75hAiglA_joHBKC5xZc4J9TJrraiyGdQdFMBnNd_2pU9AhL86XxMEiUbtF9SR8IyEdVE2mLP7Fkehgg4P9PRt5mjppMBBggcDM_psmwdXdqK5131OPPbzjkjv4LBUoihAkUsUP35CSXLk0ruymZNcYzDvvzsLeVx2pBlzID6DuGnTcWjfXT1SnaMyBGj3DAzd324-DYGKfp2Dy0BCWwKb0O7VqVYtutOsU381gsy4Cd9OA

You can then decrypt this using your resource's public key, %%__RSA_PUBLIC_KEY__%%, to retrieve the above JSON.

If you want to test your system, decrypt the above websafe base64-encoded example with the example public key given above in %%__RSA_PUBLIC_KEY__%%. Remember that OpenSSL PKCS1 padding is used! You should get this:
{
  "ver": "1",
  "resource_ver": "1.0.4",
  "user": "1",
  "resource": "4",
  "nonce": "7318",
  "agent": "0",
  "timestamp": "1595627584"
}