(Newbie) Need details info for connecting payment to license delievery

Ok, so I’m completely new to all this so please be patient.

My current set up.
Cryptlex: Products/licenses (subscription) all set up, tested and working.
Website: Setup a WYSIWYG website with cPanel
Product: Subscription based software
Paypal: I think I have the payment all set up.

I need help setting up a listener, listening for the successful paypal transactions. This would generate a license and email the user with a link to the download and their license key.

I know there are lots of documentation about webhooks but I can’t figure it out. Basically I need some handholding doing this: https://docs.cryptlex.com/web-integration/using-web-api

I feel like I’m so close, just don’t understand how to connect things.


I got Zapier connected and it seems to be doing this for me.
However…it feels like this is just a couple of webpage/scripts I need to put on my server and it would do the same thing without a monthly fee.

Am I wrong? It’d be nice not to have to pay $20/m for this service at this point.

Getting closer.
I have my own paypal listener on my site and the IPN simulator from paypal likes it. (successful handshake)

In the listener, once verified, I try to generate a license and create a user. This isn’t happening and I don’t know why.
Any ideas?

Ok, So I have the paypal IPN listener working.
–tested with paypal’s IPN simulator

I have a separate generate-license.php file on my server.
–using curl to pass POST data

Both work independently but when I put the generate-license code in the paypal listener code, it doesn’t create a new user/license. Any ideas?


The generate-license.php file needs to be updated to parse the data format sent by PayPal.

Yeah, I’ve done that. I’ve sent the POST data (from paypal’s example) to the URL and it creates licenses perfectly. But when I add the code to the IPN listener, nothing happens.
No doubt, user error.

Let’s get detailed…cause I’m stumped.
Server File structure:
/home/name/public_html/generate-license.php see below
/home/name/public_html/paypalIPN.php source: https://github.com/paypal/ipn-code-samples/blob/master/php/PaypalIPN.php



// pass this secret as query param in the url e.g. https://yourserver.com/generate-license.php?cryptlex_secret=SOME_RANDOM_STRING

// access token must have following permissions (scope): license:write, user:read, user:write
$PERSONAL_ACCESS_TOKEN = "Yes, I have my PAT here";

// utility functions
function IsNullOrEmptyString($str){
    return (!isset($str) || trim($str) === '');

function ForbiddenRequest() {
    $message['error'] = 'You are not authorized to perform this action!';
    echo json_encode($message);

function BadRequest($error) {
    $message['error'] = $error;
    echo json_encode($message);

function VerifySecret($secret) {
    if($secret == $GLOBALS['CRYPTLEX_SECRET']) {
        return true;
    return false;

function parsePayPalPostData() {
    $postBody['company'] = $_POST['payer_email'];
    if(IsNullOrEmptyString($postBody['email'])) {
        $postBody['company'] = "";

    $postBody['quantity'] = $_POST['quantity'];
    if(IsNullOrEmptyString($postBody['quantity'])) {
        $postBody['quantity'] = NULL;

    $postBody['email'] = $_POST['payer_email'];
    if(IsNullOrEmptyString($postBody['email'])) {
        BadRequest('email is missing!');
        return NULL;

    $postBody['last_name'] = $_POST['last_name'];
    if(IsNullOrEmptyString($_POST['last_name'])) {
        BadRequest('last name is missing!');
        return NULL;
    $postBody['first_name'] = $_POST['first_name'];
    if(IsNullOrEmptyString($_POST['first_name'])) {
        BadRequest('first name is missing!');
        return NULL;

    $postBody['order_id'] = $_POST['txn_id'];
    if(IsNullOrEmptyString($postBody['order_id'])) {
        BadRequest('reference is missing!');
        return NULL;
    return $postBody;

try {

    if(VerifySecret($_GET['cryptlex_secret']) == false) {
        return ForbiddenRequest();


    $product_id = "this is my product id";

    $postBody = parsePayPalPostData();

    if($postBody == NULL) {
        echo "no data \n";

    $email = $postBody['email'];
    $first_name = $postBody['first_name'];
    $last_name = $postBody['last_name'];
    $quantity = $postBody['quantity'];

    // required for renewing the license subscription
    $order_id = $postBody['order_id'];

    // creating user is optional
    $user_exists = false;
    $user = CryptlexApi::GetUser($email);
    if($user == NULL) {
        $user_body["email"] = $email;
        $user_body["firstName"] = $first_name;
        $user_body["lastName"] = $last_name;
        $user_body["company"] = $last_name;
        // generate a random 8 character password
        $user_body["password"] = substr(md5(uniqid()), 0, 8);
        $user_body["role"] = "user";
        $user = CryptlexApi::CreateUser($user_body);
    } else {
        $user_exists = true;

    echo "Quantity = $quantity \n";
    // creating license
    if($quantity != NULL) {
        $license_body["allowedActivations"] = (int)$quantity;
    $license_body["productId"] = $product_id;
    $license_body["userId"] = $user->id;
    $metadata["key"] = "order_id";
    $metadata["value"] = $order_id;
    $metadata["visible"] = false;
    $license_body["metadata"] = array($metadata);

    $license = CryptlexApi::CreateLicense($license_body);

    echo $license->key;

    } catch(Exception $e) {
    echo 'message: ' .$e->getMessage();

Ok, So if I do the following in the terminal, I will successfully create a user/license

curl -d "payer_email=emailaddress%40gmail.com&quantity=1&last_name=smith&first_name=bob&txn_id=ordernumber" -X POST https://mywebsite.com/generate-license.php?cryptlex_secret=SOME_RANDOM_STRING

So, I take that code and put it in paypalIPN.php and renamed to enerate-license-IPN_combined.php

In the paypalIPN.php file, I inserted the above code here:

// Check if PayPal verifies the IPN data, and if so, return true.
       if ($res == self::VALID) {
            ######## I put all of my code above right here #########
            return true;
        } else {
            return false;

The IPN code seems to work since the Paypal IPN simulator says it does. Nothing happens on the database side though.

I’ve removed checks and even went as far as putting this code before the IPN but it’s not working. Please help.

I guess this is the issue. You are assigning payer_email to the company. And then using wrong property to get the email.

$email = $postBody[‘email’];

One of many issues. I ended up getting lots of help here: https://stackoverflow.com/questions/66713607/paypal-ipn-not-executing-license-creation-code/66717454#66717454

What really ‘fixed’ the issue was creating a way to debug through log files and discovering the error log.

Things are working now. Need to add some additional features now.

Thank you for the help.

For those reading, Zapier is far-far easier but I went from knowing nothing about this to a functioning system in a few days with only self-taught coding skills. So now I don’t have to pay a monthly fee to Zapier.