Rev 156 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<!DOCTYPE html>
<html lang="en">
<head>
<title>eBay Listing Promotion</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script src="js/XMLWriter.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data-2012-2022.min.js"></script>
<link rel="stylesheet" href="css/style.css">
<script src="js/muna-tools.js"></script>
</head>
<body onload="return initConfig();">
<div>
<div>
<div class="container-fluid bg-secondary">
<div class="clearfix">
<img class="img-fluid float-right" src="images/MUNA%20-%20Logo%20100x100.png" alt="MUNA Trading Logo" />
<h1 id="connected">eBay Listing Promotion
<input id="login" type="button" class="btn bg-success mb-2 w3-hide" onclick="eBayLogin();" value="Login" /></h1>
</div>
</div>
<div class="border col">
<div>
<form id="searchForm" class="container-fluid bg-light" onsubmit="return getListingsForPromote();">
<input id="promoteButton" type="button" class="btn btn-danger" onclick="getListingsForPromote();" value="Promote" />
</form>
</div>
<div class="modal" id="progressBarDiv">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 id="progressBarHeader"></h4>
</div>
<div class="modal-body">
<div class="progress">
<div id="progressBar" class="progress-bar" style="width:0%">0%</div>
</div>
</div>
</div>
</div>
</div>
<div id="results" class="border bg-info w3-hide"></div>
<div id="logging"></div>
</div>
</div>
<footer class="container-fluid text-center border border-bottom-0 border-left-0 border-right-0">
<div w3-include-html="php/footer.php"></div>
</footer>
</div>
<script>
// Config
var configCampaignId = '10477406018';
var accessToken = '';
var refreshToken = '';
var pagesToProcess = 0;
var maxPagesToProcess = 0;
var pagesProcessed = 0;
var html = [];
// Initialize Configuration Variables
function initConfig() {
eBayAuthToken = readCookie();
if (eBayAuthToken.length > 0) {
connected();
}
if (eBayAuthTokenFlag === false) {
var x = document.getElementById("login");
if (x.className.indexOf("w3-show") == -1) {
x.className += " w3-show";
}
}
getOAuthToken();
}
function requireNewLogin() {
// dummy
}
function connected() {
var x;
eBayAuthTokenFlag = true;
document.getElementById("connected").innerHTML += " (Connected)";
x = document.getElementById("promoteButton");
x.className = x.className.replace(" btn-danger", " btn-dark");
x = document.getElementById("login");
x.className = x.className.replace(" w3-show", "");
x = document.getElementById("results");
x.innerHTML = "";
x.className = x.className.replace(" w3-show", "");
x.className = x.className.replace("process-errors", "");
}
function getListingsForPromote() {
var x;
if (eBayAuthTokenFlag === false) {
return;
}
// if (accessToken.length < 1) {
// getOAuthToken();
// } else if (refreshToken.length > 0) {
// refreshApplicationToken(refreshToken);
// }
if (accessToken.length < 1) {
return;
}
document.getElementById("logging").innerHTML = '';
x = document.getElementById("results");
if (x.className.indexOf("w3-show") == -1) {
x.className += " w3-show";
}
x.innerHTML = '<p><strong>Retrieving Listings...</strong></p>';
x.className = x.className.replace("process-errors", "");
pagesToProcess = 1;
maxPagesToProcess = 0;
pagesProcessed = 0;
initProgressBar("Retrieving Listings...");
eBaySearch(1);
function checkpagesToProcess() {
if (pagesToProcess > 0) {
window.setTimeout(checkpagesToProcess, 300); // wait 100 milliseconds
} else {
endProgressBar();
processCurrentAds();
}
}
checkpagesToProcess();
}
function processCurrentAds() {
adsToRead = 1;
getCurrentAds(1);
function checkAdsToRead() {
if (adsToRead > 0) {
window.setTimeout(checkAdsToRead, 100); // wait 100 milliseconds
} else {
updateAds();
}
}
checkAdsToRead();
}
function updateAds() {
var i = 1;
var pt = document.getElementById("promoteTable");
var x;
var updateList = [];
var addList = [];
var entry;
var maxAds = 500;
adsToUpdate = 0;
for (i = 1; i < pt.rows.length; i++) {
if (pt.rows[i].cells[1].innerHTML != pt.rows[i].cells[3].innerHTML) {
entry = '{"bidPercentage":"' + pt.rows[i].cells[1].innerHTML + '","listingId" : "' + pt.rows[i].cells[0].innerHTML + '"}';
if (pt.rows[i].cells[2].innerHTML.length > 0) {
if (updateList.indexOf(entry) == -1) {
updateList.push(entry);
}
} else {
if (addList.indexOf(entry) == -1) {
addList.push(entry);
}
}
}
}
for (i = 0; (i * maxAds) < updateList.length; i++) {
++adsToUpdate;
updateAd(1, updateList.slice(i * maxAds, (i + 1) * maxAds));
}
for (i = 0; (i * maxAds) < addList.length; i++) {
++adsToUpdate;
updateAd(0, addList.slice(i * maxAds, (i + 1) * maxAds));
}
function checkAdsToUpdate() {
if (adsToUpdate > 0) {
window.setTimeout(checkAdsToUpdate, 100); // wait 100 milliseconds
} else {
x = document.getElementById("results");
x.innerHTML += '<p><strong>Report Finished!</strong></p>';
if (!x.className.includes("process-errors")) {
setTimeout(function() {
x.className = x.className.replace(" w3-show", "");
}, 3000);
}
}
}
checkAdsToUpdate();
}
function getCurrentAds(pageNumber) {
var i;
var response;
var limit = 500;
url = configeBayAdCampaign;
url += configCampaignId;
url += '/ad?';
url += 'offset=';
url += (pageNumber - 1) * limit;
url += '&limit=';
url += limit;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {
response = JSON.parse(this.responseText);
for (i = 0; i < response.ads.length; i++) {
itemId = response.ads[i].listingId;
if (document.getElementById('AdId' + itemId) !== null) {
document.getElementById('AdId' + itemId).innerHTML = response.ads[i].adId;
document.getElementById('CurrentRate' + itemId).innerHTML = response.ads[i].bidPercentage;
}
}
if (Number(response.total) > (pageNumber * limit)) {
++adsToRead;
document.getElementById("results").innerHTML += '<p><strong>Retrieving Ads (' + pageNumber + '/' + Number((response.total / limit) + 1).toFixed(0) + ')</strong></p>';
getCurrentAds(pageNumber + 1);
}
}
--adsToRead;
}
};
xhttp.open("GET", configProxyUrl, true);
xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
xhttp.setRequestHeader('X-Authorization', 'Bearer ' + accessToken);
xhttp.send();
}
function updateAd(flag, list) {
var xhttp;
var json;
var i, j;
var obj;
var errors;
if (list.length === 0) {
return;
}
json = '{"requests":[' + list.join(',') + ']}';
if (flag) {
url = configeBayAdCampaign;
url += configCampaignId;
url += '/bulk_update_ads_bid_by_listing_id';
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4) {
obj = JSON.parse(this.responseText);
if (this.status == 200 || this.status == 207) {
for (i = 0; i < obj.responses.length; i++) {
if (Number(obj.responses[i].statusCode) == 200) {
document.getElementById('AdId' + obj.responses[i].listingId).innerHTML = obj.responses[i].adId;
document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML = 'Updated';
document.getElementById('UpdateStatus' + obj.responses[i].listingId).style.color = 'green';
} else {
document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML = 'Update Failed (';
errors = getJsonArray(obj.responses[i].errors);
if (errors[0] !== undefined) {
document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML += errors[0].message;
} else if (obj.responses[i].statusCode !== undefined) {
document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML += " " + obj.responses[i].statusCode;
}
document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML += ')';
document.getElementById('UpdateStatus' + obj.responses[i].listingId).style.color = 'red';
}
}
} else {
var x = document.getElementById("results");
x.className += " process-errors";
x.innerHTML += '<p class="text-danger">Bulk Update Ads: <strong>' + this.status + '</strong></p>';
}
--adsToRead;
}
};
xhttp.open("POST", configProxyUrl, true);
xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
xhttp.setRequestHeader('X-Authorization', 'Bearer ' + accessToken);
xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhttp.send(json);
} else {
url = configeBayAdCampaign;
url += configCampaignId;
url += '/bulk_create_ads_by_listing_id';
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4) {
obj = JSON.parse(this.responseText);
if (this.status == 200 || this.status == 207) {
for (i = 0; i < obj.responses.length; i++) {
if (Number(obj.responses[i].statusCode) == 201) {
document.getElementById('AdId' + obj.responses[i].listingId).innerHTML = obj.responses[i].adId;
document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML = 'Added';
document.getElementById('UpdateStatus' + obj.responses[i].listingId).style.color = 'green';
} else {
errors = getJsonArray(obj.responses[i].errors);
document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML = 'Add Failed (' + getJsonValue(errors[0].message) + ')';
document.getElementById('UpdateStatus' + obj.responses[i].listingId).style.color = 'red';
}
}
} else {
var x = document.getElementById("results");
x.className += " process-errors";
x.innerHTML += '<p class="text-danger">Bulk Create Ads: <strong>' + this.status + '</strong></p>';
}
--adsToRead;
}
};
xhttp.open("POST", configProxyUrl, true);
xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
xhttp.setRequestHeader('X-Authorization', 'Bearer ' + accessToken);
xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhttp.send(json);
}
--adsToUpdate;
}
// Build an HTML table to display search results
function eBaySearch(pageNo) {
var i;
var xml;
if (eBayAuthTokenFlag === false) {
return;
}
var xw = new XMLWriter('UTF-8', '1.0');
var xhr = new XMLHttpRequest();
if (!createAddXMLSearch(xw, xhr, 'GetSellerList', pageNo)) {
return;
}
xml = xw.flush();
xw.close();
xhr.onload = function() {
var jsonObj = XMLparse(xhr.responseXML, false);
var obj = jsonObj.GetSellerListResponse;
var returnCode = obj.Ack;
var str;
var x = document.getElementById("results");
if (returnCode == 'Success') {
createTable(obj.ItemArray, pageNo, Number(obj.PaginationResult.TotalNumberOfPages));
if (Number(obj.PaginationResult.TotalNumberOfPages) > pageNo) {
maxPagesToProcess = Number(obj.PaginationResult.TotalNumberOfPages);
++pagesToProcess;
eBaySearch(pageNo + 1);
}
updateProgressBar(maxPagesToProcess, pagesProcessed);
} else {
x.className += " process-errors";
str = '<p class="text-danger"><strong>' + returnCode + ':</strong></p>';
var errors = getJsonArray(obj.Errors);
str += "<p>";
for (i = 0; i < errors.length; i++) {
str += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
}
str += "</p>";
x.innerHTML += str;
}
--pagesToProcess;
++pagesProcessed;
document.getElementById("logging").innerHTML = html.join('');
updateProgressBar(maxPagesToProcess, pagesProcessed);
};
xhr.send(xml);
}
function createAddXMLSearch(xw, xhr, callname, pageNo) {
var startDate = moment(moment().subtract(31, "days").format('YYYY-MM-DD') + " 00:00:00", "YYYY-MM-DD HH:mm:ss").tz("UTC").toISOString();
var todayDate = moment(moment().format('YYYY-MM-DD') + " 23:59:59", "YYYY-MM-DD HH:mm:ss").tz("UTC").toISOString();
var endDate = moment(moment().add(31, "days").format('YYYY-MM-DD') + " 00:00:00", "YYYY-MM-DD HH:mm:ss").tz("UTC").toISOString();
xw.writeStartDocument();
xw.writeStartElement(callname + "Request");
xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
xw.writeStartElement('RequesterCredentials');
xw.writeElementString('eBayAuthToken', eBayAuthToken);
xw.writeEndElement(); /* RequesterCredentials */
xw.writeElementString('DetailLevel', 'ItemReturnDescription');
xw.writeElementString('StartTimeFrom', startDate);
xw.writeElementString('StartTimeTo', todayDate);
xw.writeElementString('EndTimeFrom', todayDate);
xw.writeElementString('EndTimeTo', endDate);
xw.writeElementString('OutputSelector', 'ItemArray.Item.ItemID');
xw.writeElementString('OutputSelector', 'ItemArray.Item.ListingType');
xw.writeElementString('OutputSelector', 'PaginationResult');
xw.writeElementString('OutputSelector', 'ItemArray.Item.SellingStatus.ConvertedCurrentPrice');
xw.writeStartElement('Pagination');
xw.writeElementString('EntriesPerPage', '200');
xw.writeElementString('PageNumber', '' + pageNo);
xw.writeEndElement(); /* Pagination*/
xw.writeElementString('ErrorLanguage', 'en_US');
xw.writeElementString('Version', configeBayTradingVersion);
xw.writeElementString('WarningLevel', configWarningLevel);
xw.writeEndElement(); /* xmlrequest */
xw.writeEndDocument();
xhr.open('POST', configProxyUrl, true);
xhr.setRequestHeader('Content-Type', 'text/xml');
xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
xhr.setRequestHeader('X-EBAY-API-COMPATIBILITY-LEVEL', configeBayTradingVersion);
xhr.setRequestHeader('X-EBAY-API-CALL-NAME', callname);
xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
xhr.setRequestHeader('X-Proxy-URL', configServiceEndpoint);
return true;
}
function createTable(obj, pageNumber, totalPages) {
var currentPrice;
var adRate;
if (pageNumber == 1) {
document.getElementById("logging").innerHTML = '';
html = [];
html.push('<div class="border table-responsive">');
html.push('<h3>Listing Promotions</h3>');
html.push('<table id="promoteTable" class="table table-hover table-striped table-bordered small">');
html.push('<thead class="thead-dark">');
html.push('<tr>');
html.push(tableHeader('Item ID'));
html.push(tableHeader('New Ad Rate'));
html.push(tableHeader('Ad Id'));
html.push(tableHeader('Current Ad Rate'));
html.push(tableHeader('Create/Update Status'));
html.push('</tr>');
html.push('</thead>');
html.push('<tbody>');
}
for (var entry = 0; entry < obj.Item.length; entry++) {
var item = obj.Item[entry];
if (item.ListingType == 'Chinese') {
continue;
}
currentPrice = Number(item.SellingStatus.ConvertedCurrentPrice.text).toFixed(2);
// minimum ad rate is 1.00%
/*
if (currentPrice > 99.99) {
adRate = 2.0;
} else if (currentPrice > 49.99) {
adRate = 2.7;
} else if (currentPrice > 29.99) {
adRate = 3.0;
} else if (currentPrice > 19.99) {
adRate = 3.2;
} else if (currentPrice > 14.99) {
adRate = 3.5;
} else if (currentPrice > 9.99) {
adRate = 3.7;
} else if (currentPrice > 4.99) {
adRate = 4.0;
} else if (currentPrice > 3.99) {
adRate = 4.2;
} else {
continue;
}
*/
adRate = 3.0;
html.push('<tr>');
html.push(tableCell(item.ItemID));
html.push(tableCell(Number(adRate).toFixed(1)));
html.push(tableCellLabel('AdId' + item.ItemID));
html.push(tableCellLabel('CurrentRate' + item.ItemID));
html.push(tableCellLabel('UpdateStatus' + item.ItemID));
html.push('</tr>');
}
if (pageNumber == totalPages) {
html.push('</tbody>');
html.push('</table>');
html.push('</div>');
}
}
function getOAuthToken() {
var code = "";
var win = window.open(configeBayLoginUrl, "eBay OAUTH", "");
var pollTimer = window.setInterval(function() {
if (win.closed !== false) {
window.clearInterval(pollTimer);
getApplicationToken(code);
} else {
if (code === null || code.length === 0) {
try {
code = getUrlParameter(win, 'code');
} catch(err) {
// empty
}
}
}
}, 200);
}
function getApplicationToken(code) {
var param;
param = 'grant_type=authorization_code';
param += '&code=' + code;
param += '&redirect_uri=' + configRuName;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {
response = JSON.parse(this.responseText);
accessToken = getJsonValue(response.access_token);
refreshToken = getJsonValue(response.refresh_token);
}
}
};
xhttp.open("POST", configProxyUrl, true);
xhttp.setRequestHeader("X-Proxy-Url", configOauthTokenUrl);
xhttp.setRequestHeader('X-Authorization', 'Basic XxXAuthorization');
xhttp.setRequestHeader('X-DECODE-PARAMS', '1');
xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhttp.send(param);
}
function refreshApplicationToken(code) {
var param;
param = 'grant_type=refresh_token';
param += '&refresh_token=' + code;
param += '&scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope%2Fsell.marketing';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {
response = JSON.parse(this.responseText);
accessToken = getJsonValue(response.access_token);
refreshToken = getJsonValue(response.refresh_token);
}
}
};
xhttp.open("POST", configProxyUrl, true);
xhttp.setRequestHeader("X-Proxy-Url", configOauthTokenUrl);
xhttp.setRequestHeader('X-Authorization', 'Basic XxXAuthorization');
xhttp.setRequestHeader('X-DECODE-PARAMS', '1');
xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhttp.send(param);
}
</script>
<script>includeHTML();</script>
</body>
</html>