Overview
An important part of being successful as a digital product seller is taking precautions to protect your product and keep it from being improperly downloaded. In this guide, we have several steps you can take to keep your product secure.
The following subjects are covered in this article:
General Guidance
Here are several suggestions to protect your digital product from piracy:
If your digital product is a one-time digital product, see the Digital Product Upload article for information about having ClickBank deliver your product to customers.
Add the following HTML code in the <HEAD> element of your Thank You Page should prevent a search engine robot from indexing that page or following links on that page:
<META name="robots" content="noindex, nofollow"/>
Give your Thank You Page URL an obscure file name (it should not be something like thankyou.htm, which is too easy to guess).
If you are concerned about security and you have experience with CGI programming, you can generate a script that will verify the customer’s successful completion of the purchase process before allowing him or her access to the Thank You Page. Follow the instructions below for implementing the ClickBank Link Security Script.
Using a Link Security Setup
When the customer completes a purchase, several values are passed along to your thank you page in the query string if you have specified a secret key in your account settings. These are the ClickBank receipt number (cbreceipt), the epoch time of the order (time), the ClickBank item number (item), and the ClickBank proof of purchase (cbpop) value.
During the purchase we encrypt the receipt, time, and item using the secret key you specify in your account. We will then pass the result back to you as a query string parameter called cbpop. Use the validation script to confirm the cbpop value is correct.
Unlike prior versions of this script there is no need for a “seed” value.
The C#, VB.NET, and Ruby examples below are only a method for checking for a valid cbpop value and leave the capturing of the request parameters up to your individual implementations.
Code Samples
PHP Source:
function cbValid() {
$key = 'YOUR_SECRET_KEY';
$rcpt = $_REQUEST['cbreceipt'];
$time = $_REQUEST['time'];
$item = $_REQUEST['item'];
$cbpop = $_REQUEST['cbpop'];
$xxpop = hash('sha256', "$key|$rcpt|$time|$item");
$xxpop = strtoupper(substr($xxpop, 0, 8));
return ($cbpop === $xxpop);
}
Perl Source:
use Digest::SHA qw(sha256_hex);
use CGI;
sub cbValid {
my $q = CGI->new;
my $key = 'YOUR_SECRET_KEY';
my $rcpt = $q->param('cbreceipt') || '';
my $time = $q->param('time') || '';
my $item = $q->param('item') || '';
my $cbpop = $q->param('cbpop') || '';
my $xxpop = uc(substr(sha256_hex("$key|$rcpt|$time|$item"), 0, 8));
return ($cbpop eq $xxpop);
}
C# Source:
using System;
using System.Security.Cryptography;
using System.Text;
public class CBValidator {
public static bool cbValid(string cbreceipt, string time, string item, string cbpop) {
string secret_key = "YOUR_SECRET_KEY";
string data = $"{secret_key}|{cbreceipt}|{time}|{item}";
using (SHA256 sha256 = SHA256.Create()) {
byte[] hashedData = sha256.ComputeHash(Encoding.UTF8.GetBytes(data));
string xxpop = BitConverter.ToString(hashedData).Replace("-", "").ToUpper().Substring(0, 8);
return cbpop.Equals(xxpop);
}
}
}
VB.NET Source:
Imports System.Security.Cryptography
Imports System.Text
Public Class CBValidator
Public Shared Function cbValid(receipt As String, time As String, item As String, cbpop As String) As Boolean
Dim key As String = "YOUR_SECRET_KEY"
Dim data As String = key & "|" & receipt & "|" & time & "|" & item
Dim sha As SHA256 = SHA256.Create()
Dim result() As Byte = sha.ComputeHash(Encoding.UTF8.GetBytes(data))
Dim xxpop As String = BitConverter.ToString(result).Replace("-", "").ToUpper().Substring(0, 8)
Return cbpop.Equals(xxpop)
End Function
End Class
Ruby Source:
require 'digest'
def cbValid(receipt, time, item, cbpop)
key = "YOUR_SECRET_KEY"
popCheck = "#{key}|#{receipt}|#{time}|#{item}"
xxpop = Digest::SHA256.hexdigest(popCheck).upcase[0,8]
cbpop == xxpop
end
Python Source:
import hashlib
def valid_cb_pop(receipt, time, item, cbpop):
secret_key = 'YOUR_SECRET_KEY'
data = f"{secret_key}|{receipt}|{time}|{item}".encode('utf-8')
xxpop = hashlib.sha256(data).hexdigest()[:8].upper()
return cbpop == xxpop
Java Source:
import org.apache.commons.codec.digest.DigestUtils;
public class CBPopValidator {
public static boolean validCbPop(String receipt, String time, String item, String cbpop) {
final String secretKey = "YOUR_SECRET_KEY";
String hashedData = DigestUtils.sha256Hex(String.format("%s|%s|%s|%s", secretKey, receipt, time, item));
return hashedData.substring(0, 8).equalsIgnoreCase(cbpop);
}
}