developer

Workflow to create a checkout against API v3 with PHP and Guzzle

Preparation

Install Guzzle

First of all you need to install Guzzle. Please follow the steps here You can also use HTTP-Client or plain cURL if you want to reduce footprint of your implementation.

Create API-Token

We will use our all new RESTfull API. To authorize against this API, one have to create an API-Access-Token. You will need settings section in plenigo-Backend and at least the right to write Settings, to create a new Access-Token.

Examples for external User-Management

At the moment we only provide examples for external customer management.

Initialize Guzzle

$client = new GuzzleHttp\Client(['base_uri' => 'https://api.plenigo.com/api/v3.0/']);

POST the Customer

We tried to keep the examples as simple as possible. You can pimp the guzzle client as much as you want .

$client = new GuzzleHttp\Client(['base_uri' => 'https://api.plenigo.com/api/v3.0/']);
$user = [
    'customerId' => "4711", // User-ID in external system
    'email' => "{$emailAdress}", // E-Mail address of your customer
    'language' => 'de',
  ];

$response = $client->request('POST', 'customers', [
    // here you will need to work with the Api-Access token from plenigo backend
    'headers' => ['X-plenigo-token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw'],
    // the payload, we'll send
    'json' => $user
]);

$customer = json_decode($response->getBody()->getContents());

This will return the created user or the already existing user. It will not recreate it.

Create Checkout-Code

After having a customer we need to create a checkout token:

// @see https://stackoverflow.com/a/55790/2336470
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

$payload = [
    "debugMode" => true, // enable debugging in checkout (please turn it off in prod environment)
    "customerIpAddress" => $ip,
    "customerId" => $customer->customerId,
    "items" => [
        [
            "plenigoOfferId" => "O_6E487EBURRY35FOD0J",
            "quantity" => 1,
        ],
    ],
]);

$response = json_decode($client->request('POST', '/checkout/preparePurchase', [
      'headers' => ['X-plenigo-token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw'],
      'json' => $payload
])->getBody()->getContents());

Create the Checkout

In your HTML-Code you will need to add the plenigo Javascript.

<!-- plenigo Javascript SDK will inject the Checkout into this div -->
<div id="plenigoCheckout"></div>

<script>
    // if your're working against the staging system, you have to extend the endpoint
    var plenigo = plenigo || {};
    plenigo.configuration = plenigo.configuration || {};
    plenigo.baseCheckoutURI = "https://checkout.plenigo-stage.com";
</script>

<script src="https://static.plenigo.com/static_resources/javascript/{YourCompanyId}/plenigo_sdk.min.js"
        type="text/javascript" data-disable-metered="true" data-oauth2-access-code="oauth2Test"></script>

<script>

  new plenigo.Checkout("<?php echo $response->purchaseId;  ?>", {elementId: "plenigoCheckout"}).start();

  // this will be triggered, if Checkout is finished successfully
  document.addEventListener("plenigo.PurchaseSuccess", function (e) {
    // debugging Code:
    console.info("Event is: ", e);
    console.info("Custom data is: ", e.detail);
    location.href = location.pathname + "?" + e.orderId;
    // please take care by using orderId in your scripts. It can be -1, if customer tries to buy a product multiple times
  });

  // if you enabled WebAnalytics, then you will recieve some additional information during the checkout 
  document.addEventListener("plenigo.WebAnalyticsLoad", function (e) {
    // debugging Code:
    console.group("ANALYTICS");
    console.info("Event is: ", e);
    console.info("Custom data is: ", e.detail);
    console.groupEnd();
  });

</script>

Since plenigo checkout will prevent customers from buying same product multiple times, orderId will be -1, if product is already bought.

Purchase a single product and overwrite it with custom data

Some may have hundreds of identical products. Lets say, you are publishing one ePaper a day. And you want to be able to sell each of them. Then you should not create a new product every day - just reuse an old one. Create one product in the plenigo backend for all of your pdf-files, and sell it this way:

// @see https://stackoverflow.com/a/55790/2336470
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

$payload = [
    "debugMode" => true, // enable debugging in checkout (please turn it off in prod environment)
    "customerIpAddress" => $ip,
    "customerId" => $customer->customerId,
    "items" => [
        [
            "plenigoOfferId" => "O_6E487EBURRY35FOD0J", // offerId of your all pdf product
            "quantity" => 1,
            "title" => "my daily ePaper issue: 2020-04-04",
            "products" => [
               [
                   "plenigoProductId" => "P_GZUZGJHGJHGGJ", // productID of the underlying product
                   "productId" => "ePaper-2020-04-04", // unique ID to make you able to differentiate between singular issues
                   "price" => 5, // you can overwrite price (only if you want to)
                   "title" => "my daily ePaper issue: 2020-04-04", // we will provide multi product offers
                   "accessRightUniqueId" => "ePaper-2020-04-04", // to be able to give access to one specific issue, you need to set specific access right
               ]
           ]

        ],
    ],
]);

$response = json_decode($client->request('POST', '/checkout/preparePurchase', [
      'headers' => ['X-plenigo-token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw'],
      'json' => $payload
])->getBody()->getContents());

Check Access

If you are selling products, you want to give your customers access to your digital goods. With plenigo you simply use the method hasAccess

try {

    $response = json_decode($client->request('GET', "accessRights/{$customer->customerId}/hasAccess?accessRightUniqueIds=ePaper-2020-04-04", [
        'headers' => ['X-plenigo-token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw']
    ])->getBody()->getContents()));

   $access = $response->accessGranted; // here we get the access status

} catch(\GuzzleHttp\Exception\ClientException $e) {
    // with external user managment we can't guarantee for an existing plenigo user. in these case you have to catch a GuzzleHttp\Exception\ClientException - this user should not get any access
    $access = false;
}

Guzzle loves to throw Exceptions. In case of a missing user plenigo will return a 404 StatusCode - guzzle will turn this into a GuzzleHttp\Exception\ClientException.

Work with Sessions, use plenigo SSO

If plenigo is used as a SSO you have to deal with sessions. You can use the session, to start a Checkout, to check users access rights or start selfservice process.

Create a transfer token

To open plenigo selfservice you need to have a transfer token:

    
    // @see https://api.plenigo-stage.com/#operation/createTransferToken
    // $session should be the plenigo session token
    $payload = ['customerSession' => $session];
    try {        
        $response = json_decode($client->request('POST', '/sessions/transferToken', [
          'headers' => [
            'X-plenigo-token' =>                        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw'],
      'json' => $payload
])->getBody()->getContents());

    $transferToken = $response->transferToken;
    
   } catch (\GuzzleHttp\Exception\ClientException $exception) {
        // handle errors
    }

use token to start selfservice

<div id="plenigoCheckout"></div>
    <script src="https://static.plenigo-stage.com/static_resources/javascript/<?php echo $companyId; ?>/plenigo_sdk.min.js"
            type="text/javascript" data-disable-metered="true" data-lang="de" data-disable-redirect="true"></script>

    <script>
        new plenigo.Snippets("<?php echo $transferToken; ?>", {elementId: "plenigoCheckout"}).start();
    </script>

Start a checkout with plenigo session

// @see https://stackoverflow.com/a/55790/2336470
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

$payload = [
    "debugMode" => true, // enable debugging in checkout (please turn it off in prod environment)
    "customerIpAddress" => $ip,
// $session is you plenigo session token
// @see https://api.plenigo-stage.com/#operation/preparePurchase
    "customerSession" => $session,
    "items" => [
        [
            "plenigoOfferId" => "O_6E487EBURRY35FOD0J",
            "quantity" => 1,
        ],
    ],
]);

$response = json_decode($client->request('POST', '/checkout/preparePurchase', [
      'headers' => ['X-plenigo-token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw'],
      'json' => $payload
])->getBody()->getContents());

Check access with plenigo session

// https://customer-api.plenigo-test.com/#operation/checkAccessOfCustomer
$response = json_decode($client->request('GET', 'https://customer-api.plenigo-stage.com/api/v1.0/accessRights/hasAccess', [
      'headers' => ['X-plenigo-customer-session' => $session],
])->getBody()->getContents());

if ($response->accessGranted) {
// show content
}

plenigo voucher process

Vouchers enable you to sell products you don’t want to show on your website. Vouchers are always connected to a plenigo product. So voucher process is thought like a normal checkout: it generates an order.

Validate a voucher code

You can split voucher process into the validation and redemption part. Validating a voucher code will return status of the code and the plenigo offer it will be redeemed into:

// @see https://api.plenigo-stage.com/#operation/validateVoucherCode

$response = json_decode($client->request('GET', "/vouchers/{$voucherCode}/validate", [
      'headers' => ['X-plenigo-token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw'],
      'json' => null
])->getBody()->getContents());

Redeem into a free offer

If plenigo offer is a free product, you can redeem a voucher simply by calling https://api.plenigo-stage.com/#operation/voucherPurchase.

// @see https://stackoverflow.com/a/55790/2336470
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

// @see https://api.plenigo-stage.com/#operation/voucherPurchase

$payload = [
    'customerId' => '123',
    'customerIpAddress' => $ip,
    'voucherCode' => "1234-5678-1234"
];

$response = json_decode($client->request('POST', "/checkout/buyWithVoucher", [
      'headers' => ['X-plenigo-token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw'],
      'json' => $payload
])->getBody()->getContents());

Redeem into a not free offer

If offer is not free or you are not sure, you can use the checkout process to redeem the voucher code. Checkout process will run with a free offer too.

// @see https://stackoverflow.com/a/55790/2336470
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

// @see https://api.plenigo-stage.com/#operation/preparePurchase

$payload = [
    "debugMode" => true, // enable debugging in checkout (please turn it off in prod environment)
    "customerIpAddress" => $ip,
    "customerId" => $customer->customerId,
    "voucherCode" => "1234-5678-1234"
]);

$response = json_decode($client->request('POST', '/checkout/preparePurchase', [
      'headers' => ['X-plenigo-token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGVzZSI6ImFyZSIsInBsZW5pZ28iOiJ0ZXN0IiwiZGF0YSI6ImRvIiwibm90IjoiY29uc3VtZSJ9.xnFAQQbHEFLisgeU2YqWsIfpCgEbmh_Hy59Ja0Ztxyw'],
      'json' => $payload
])->getBody()->getContents());

This will generate a purchaseToken. In the next step you have to start the checkout.