Last Updated: June 08, 2019
· stevenmaguire

Build a ShareASale Proxy with Slim PHP Framework

Recently, I launched a new (and extremely dumb) website, FootballCropTop.com, that makes use of the ShareASale Product Search API. If you've ever worked with ShareASale before you are likely familiar with some of the roadblocks thrown up by the enforcement of their security policies. I want to share one approach I took to solve for these roadblocks as part of a larger effort to explain how I built and maintain an automated affiliate website with an ecommerce experience for pennies per month.

In order to access the Product Search API offered by ShareASale you will need to configure some basic security and access controls in your account. One such control is an IP whitelist feature. This requires you to explicitly define all (up to five) of the IP addresses that will be allowed to access the API using your access credentials. This means you will need to have a static IP address somewhere out in the wild.

For my personal projects I do some light hosting on Digital Ocean and each of my Droplets are issued a static IP, something that I am already paying for (~$5/month). For this project I decided to build a small proxy app in PHP using the Slim Framework and deploy it to one of my existing Droploets.

My proxy app is a "hello world" installation of Slim, following the installation guide. It depends on only one additional library, league/csv by The League of Extraordinary Packages.

In addition to the static IP whitelisting requirement, ShareASale also requires that each request be signed with an encrypted token which must be done on each request. I'd like to use other tools (like Postman locally or AWS Lambdas in the cloud) to access the ShareASale data through the static IP address associated with the Droplet hosting this small proxy app.

I came up with a basic design that would allow me to set my secret credential information via headers and forward a request through the proxy. In turn the proxy will sign and authenticate the request, fetch the results, cleanup and format a nice response (ShareASale is not the best in this area), and finally send it back to the requesting client. Here is the code from my Slim project that does this work:


use GuzzleHttp\Client;
use League\Csv\Reader;
use Slim\Http\Request;
use Slim\Http\Response;

// Routes

$app->group('/shareasale', function () {
    $this->get('/{action}', function ($request, $response, $args) {

        // Extract our ShareASale query params from inbound request
        try {
            // 'keyword' => 'crop top',
            // 'merchantId' => 1234,
            parse_str($request->getUri()->getQuery(), $query);
        } catch (\Exception $e) {
            $query = [];

        // Extract our ShareASale action from the route
        $action = $args['action'];
        $serviceUrl = 'https://api.shareasale.com/x.cfm';

        // Extract our ShareASale auth parts from inbound headers
        $versionHeaders = $request->getHeader('x-shareasale-version');
        $version = array_shift($versionHeaders);

        $affiliateIdHeaders = $request->getHeader('x-shareasale-affiliateid');
        $affiliateId = array_shift($affiliateIdHeaders);

        $tokenHeaders = $request->getHeader('x-shareasale-token');
        $token = array_shift($tokenHeaders);

        $secretKeyHeaders = $request->getHeader('x-shareasale-secretkey');
        $secretKey = array_shift($secretKeyHeaders);

        // Create our ShareASale authentication from auth parts
        $timestamp = gmdate(DATE_RFC1123);
        $signature = $token.':'.$timestamp.':'.$action.':'.$secretKey;
        $signatureHash = hash("sha256", $signature);

        // Prepare our ShareASale request
        $headers = [
            'x-ShareASale-Date' => $timestamp,
            'x-ShareASale-Authentication' => $signatureHash,

        $options = array_merge($query, [
            'action' => $action,
            'affiliateId' => $affiliateId,
            'version' => $version,
            'token' => $token,
            'format' => 'csv'

        // Get our ShareASale response from our request
        $client = new Client();
        $res = $client->request('GET', 'https://api.shareasale.com/x.cfm', [
            'headers' => $headers,
            'query' => $options

        $status = $res->getStatusCode();
        $json = [];

        // Handle and format our ShareASale response
        try {
            $csv = Reader::createFromString($res->getBody())->jsonSerialize();

            $csvHeaders = array_shift($csv);

            $csvHeaders = array_map(function ($property) {
                $property = preg_replace('/([a-z])([A-Z])/',"$1_$2", $property);
                $property = strtolower($property);
                $property = preg_replace('/ /', '_', $property);

                return $property;
            }, $csvHeaders);

            array_walk($csv, function ($csvRow) use ($csvHeaders, &$json) {
                array_push($json, array_combine($csvHeaders, $csvRow));
        } catch (\Exception $e) {
            $status = $e->getCode();
            $json['status'] = $status;
            $json['message'] = (string) $res->getBody();
            $json['error'] = $e->getMessage();

        // Return our reformatted ShareASale response
        return $response->withStatus($status)->withJson($json);

With this little piece of infrastructure in place I am free to begin consuming the product feed data from basically anywhere.

You can read more about this project in the full technical walkthrough.

8 Responses
Add your response



over 1 year ago ·

So why choose us when looking for professional assistance on writing successful medical school essays ? The answer is obvious. We are the team that conceals no information from our customers. You are always welcome to browse our reviews section to discover how satisfied our customers are. We are very proud of our good name and reputation and we are happy to see every single positive response and evaluation of our best practices. From the number of positive responses on our website you may see that we excel ourselves to meet the highest standards you require and we are extremely good at that.

The fact that you are on http://medicalschoolexamprofessor.com right now means you have found a company of professional essay writers you can trust. A reputable team of highly educated and vastly experienced essayists, we will make sure that the piece of writing you purchase from us is the best one you can imagine. The writers from our agency have the necessary education to give you a very good argumentative essay on health care or an original research paper on health care because health care issues are among the most prioritized directions of our business.

4 months ago ·

The News Geeks is a platform that is accessible differing kinds of news, articles story, history, diversion news, Bollywood and Hollywood news it means that the entire world of stories squares measures on the news market, here our news and facts belong to the good of characters together with absolute data, if you need to browse any classical, historical or the other sorts news go one in all the news treasure The News geeks website. It has each class news categories like Entertainment, Science & Technology, Featured, Lifestyle, World, Trending, World

4 months ago ·

Thanks for the post. You can check out our exclusive WPX Hosting Coupons page for latest deals on WPX Hosting. For more info, take a look here: https://itsmyurls.com/edwardseugen


about 2 months ago ·

Great post man thanks for sharing the code. I'll try it and see the results.

14 days ago ·