Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gekidoslair/b9ca1c010ece7bef35a65d861753e672 to your computer and use it in GitHub Desktop.
Save gekidoslair/b9ca1c010ece7bef35a65d861753e672 to your computer and use it in GitHub Desktop.
PHP script that uses Unity Publisher API for PHP (https://github.com/LostPolygon/Unity-Publisher-API-PHP) to retrieve new asset sales, put them into a MySQL database, and notify about the sales via e-mail.
Data is inserted into `sales` table, which can be created from sales_table.sql file. Just set up the credentials and put this script on cron with whatever interval you want. Delete the email notification part if you don't need it.
Requires PHP 5.4, php_json extension, and remote socket access.
Also, I know it's ugly, but it does the job and served me well for over a year.
{
"assetstore": {
"login": "somemail@example.com",
"password": "123456"
},
"mysql": {
"domain": "localhost",
"user": "root",
"password": "654321",
"db": "as_stats"
},
"receiver_mail": "somemail@example.com"
}
CREATE TABLE IF NOT EXISTS `sales` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` datetime NOT NULL,
`name` varchar(64) NOT NULL,
`price` float NOT NULL,
`quantity` smallint(5) unsigned NOT NULL,
`refunds` smallint(5) unsigned NOT NULL,
`chargebacks` smallint(5) unsigned NOT NULL,
`payout_cut` float NOT NULL,
`shorturl` varchar(24) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8 ;
<?php
chdir(__DIR__);
error_reporting(E_STRICT | E_ALL);
require_once 'AssetStorePublisherClient.class.php';
date_default_timezone_set('America/Los_Angeles');
// This is the minimum amount of net revenue per launch to trigger an email
$minNetToSendMail = 0;
$credentials = json_decode(file_get_contents('credentials.json'), true);
function loginAndRetrieve($action) {
global $credentials;
$actionResult = null;
$store = new AssetStore\Client();
$loginToken = @file_get_contents("loginToken.txt");
if ($loginToken == null) {
echo "No cached login token, retrieving\r\n";
$tfaResumeDataJsonFile = 'tfaResumeData.json';
$tfaResumeData = null;
if (file_exists($tfaResumeDataJsonFile)) {
$tfaResumeDataJson = file_get_contents($tfaResumeDataJsonFile);
$tfaResumeData = json_decode($tfaResumeDataJson, true);
}
$tfaCodeFile = 'tfaCode.txt';
$tfaCode = null;
if (file_exists($tfaCodeFile)) {
$tfaCode = trim(file_get_contents($tfaCodeFile));
}
if ($tfaResumeData != null && $tfaCode == null) {
die("No TFA code yet in tfaCode.txt, exiting");
}
$loginToken = $store->Login($credentials['assetstore']['login'], $credentials['assetstore']['password'], $tfaResumeData, $tfaCode);
if ($loginToken === AssetStore\Client::TFA_CODE_REQUESTED) {
file_put_contents($tfaResumeDataJsonFile, json_encode($store->getTfaResumeData(), JSON_PRETTY_PRINT));
die("TFA requested, exiting");
} else {
if (file_exists($tfaResumeDataJsonFile)) {
unlink($tfaResumeDataJsonFile);
}
if (file_exists($tfaCodeFile)) {
unlink($tfaCodeFile);
}
file_put_contents("loginToken.txt", $loginToken);
$actionResult = $action($store);
}
} else {
echo "Using cached login token\r\n";
$store->LoginWithToken($loginToken);
try {
$actionResult = $action($store);
} catch (AssetStore\AssetStoreException $e) {
// Get new token on 401 Unauthorized
if ($e->getCode() == 401) {
echo "Cached login token is invalid, retrieving new one\r\n";
$store = new AssetStore\Client();
$loginToken = $store->Login($credentials['assetstore']['login'], $credentials['assetstore']['password']);
file_put_contents("loginToken.txt", $loginToken);
$actionResult = $action($store);
} else {
throw $e;
}
}
}
return $actionResult;
}
function getCurrentSales($year, $month) {
$sales = loginAndRetrieve(function($store) use ($year, $month) {
return $store->FetchSales($year, $month);
});
return $sales->ToArray();
}
function diffSales($prevSales, $curSales) {
$data = Array();
foreach ($curSales as $key => $curSale) {
$prevSale = array_filter($prevSales, function($element) use ($curSale) {
return $element['packageName'] == $curSale['packageName'] &&
$element['price'] == $curSale['price'];
});
@$prevSale = reset($prevSale);
$diffItem = Array(
'packageName' => $curSale['packageName'],
'price' => $curSale['price'],
'quantity' => (int)$curSale['quantity'] - (int)$prevSale['quantity'],
'refunds' => (int)$curSale['refunds'] - (int)$prevSale['refunds'],
'chargebacks' => (int)$curSale['chargebacks'] - (int)$prevSale['chargebacks'],
'shortUrl' => $curSale['shortUrl'],
);
if (!($diffItem['quantity'] == 0 &&
$diffItem['refunds'] == 0 &&
$diffItem['chargebacks'] == 0)) {
$data[] = $diffItem;
}
}
return $data;
}
function saveStats($sales, $year, $month) {
$sales['year'] = $year ;
$sales['month'] = $month;
file_put_contents('prevStats.json', json_encode($sales, JSON_PRETTY_PRINT));
}
// MAIN start
$curYear = date('Y');
$curMonth = date('m');
if (!file_exists('prevStats.json')) {
$sales = getCurrentSales($curYear , $curMonth);
saveStats($sales, $curYear, $curMonth);
}
$prevSales = json_decode(file_get_contents('prevStats.json'), true);
if ($prevSales['year'] != $curYear || $prevSales['month'] != $curMonth)
$prevSales = Array('packageSales' => Array());
$sales = getCurrentSales($curYear , $curMonth);
$diff = diffSales($prevSales['packageSales'], $sales['packageSales']);
saveStats($sales, $curYear, $curMonth);
$mysqli = new mysqli($credentials['mysql']['domain'],
$credentials['mysql']['user'],
$credentials['mysql']['password'],
$credentials['mysql']['db']);
if (mysqli_connect_errno()) {
printf("Connection error: %s\n", mysqli_connect_error());
exit();
}
foreach ($diff as $value) {
$stmt = $mysqli->prepare("INSERT INTO `sales` (`date`, `name`, `price`, `quantity`, `refunds`, `chargebacks`, `payout_cut`, `shorturl`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$date = date ("Y-m-d H:i:s", time());
$name = $value['packageName'];
$price = $value['price'];
$quantity = (int)$value['quantity'];
$refunds = (int)$value['refunds'];
$chargebacks = (int)$value['chargebacks'];
$shortUrl = $value['shortUrl'];
$payout_cut = 0.7;
$stmt->bind_param("ssdiiids", $date, $name, $price, $quantity, $refunds, $chargebacks, $payout_cut, $shortUrl);
if (!$stmt->execute()) {
echo "Unable to execute query: (" . $stmt->errno . ") " . $stmt->error;
}
}
$netRevenueDiff = round($sales["revenueNet"] - $prevSales["revenueNet"], 2);
if (sizeof($diff) > 0 && $netRevenueDiff >= $minNetToSendMail) {
// CONSTRUCT MAIL
$mail_content = '';
foreach ($diff as $value) {
$mail_content .= "• <a href=\"{$value['shortUrl']}\">{$value['packageName']}</a>. ";
if ($value['quantity'] != 0)
$mail_content .= "Purchases: {$value['quantity']} ";
if ($value['refunds'] != 0)
$mail_content .= "Refunds: {$value['refunds']} ";
if ($value['chargebacks'] != 0)
$mail_content .= "Chargebacks: {$value['chargebacks']} ";
$mail_content .= "\r\n<br>";
}
$mail_content .= "\r\n<br>Net: \${$sales['revenueNet']}";
if ($prevSales['year'] == $curYear && $prevSales['month'] == $curMonth) {
$mail_content .= ", ";
if ($netRevenueDiff > 0) {
$mail_content .= "+";
}
$mail_content .= '$' + $netRevenueDiff;
}
$mail_title = "Asset Store purchase!";
$header .= "Content-type: text/html; charset=\"utf-8\"";
mail($credentials["receiver_mail"], $mail_title, $mail_content, $header);
}
if (sizeof($diff) > 0)
file_put_contents("update.log", date ("Y-m-d H:i:s", time()) . ', ' . sizeof($diff) . " added\r\n", FILE_APPEND);
echo "Stats updated, inserted ". sizeof($diff) . " values\r\n";
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment