function CreateBitPayInvoice($loginState) { $paid = GetIsPaid($loginState); if (!$paid['accept']) { DebugMessage("User " . $loginState['id'] . " attempted to create BitPay invoice when we would not accept payments."); return []; } $priceAmount = preg_match('/\\d+\\.\\d+/', SUBSCRIPTION_PAID_PRICE, $res) ? $res[0] : false; $priceCurrency = preg_match('/\\b[A-Z]{3}\\b/', SUBSCRIPTION_PAID_PRICE, $res) ? $res[0] : false; if (!$priceAmount || !$priceCurrency) { DebugMessage("Could not find price ({$priceAmount}) or currency ({$priceCurrency}) from " . SUBSCRIPTION_PAID_PRICE . " when creating BitPay invoice."); return []; } $LANG = GetLang($loginState['locale']); $toPost = ['price' => $priceAmount, 'currency' => $priceCurrency, 'posData' => $paid['accept']['custom'], 'fullNotifications' => true, 'notificationURL' => SUBSCRIPTION_BITPAY_IPN_URL, 'notificationEmail' => SUBSCRIPTION_ERRORS_EMAIL_ADDRESS, 'redirectURL' => 'https://' . strtolower($_SERVER["HTTP_HOST"]) . '/#subscription', 'itemDesc' => $LANG['paidSubscription'] . ' - ' . round(SUBSCRIPTION_PAID_ADDS_SECONDS / 86400) . ' ' . $LANG['timeDays']]; $headers = ['Content-Type: application/json; charset=utf-8', 'Authorization: Basic ' . base64_encode(SUBSCRIPTION_BITPAY_KEY . ':')]; $jsonString = \Newsstand\HTTP::Post(SUBSCRIPTION_BITPAY_INVOICE_URL, json_encode($toPost), $headers); if (!$jsonString) { DebugMessage("No response from BitPay having sent:\n" . json_encode($toPost) . "\n" . print_r($headers, true)); return []; } $json = json_decode($jsonString, true); if (json_last_error() != JSON_ERROR_NONE) { DebugMessage("Invalid response from BitPay:\n{$jsonString}\nHaving sent:\n" . json_encode($toPost) . "\n" . print_r($headers, true)); return []; } if (!UpdateBitPayTransaction($json, true)) { return []; } return ['url' => $json['url']]; }
$tr .= "--{$boundary}--\r\n\r\n"; return [$tr, $boundary]; } $latestVersion = GetLatestGameVersionID(); if (!$latestVersion) { exit(1); } $metaData = ['changelog' => sprintf('Automatic data update for %s', date('l, F j, Y')), 'gameVersions' => [$latestVersion], 'releaseType' => 'release']; $postFields = []; $postFields[] = ['data' => file_get_contents($zipPath), 'headers' => ['Content-Disposition' => 'form-data; name="file"; filename="TheUndermineJournal.zip"', 'Content-Type' => 'application/zip', 'Content-Transfer-Encoding' => 'binary']]; $postFields[] = ['data' => json_encode($metaData), 'headers' => ['Content-Disposition' => 'form-data; name="metadata"', 'Content-Type' => 'application/json;charset=UTF-8']]; list($toPost, $boundary) = mimeset($postFields); unset($postFields); fwrite(STDERR, sprintf("Starting upload of %d bytes..\n", strlen($toPost))); $responseHeaders = []; $result = HTTP::Post(sprintf('https://wow.curseforge.com/api/projects/%d/upload-file', CURSEFORGE_PROJECT_ID), $toPost, [sprintf('Content-Type: multipart/form-data; boundary=%s', $boundary), sprintf('X-Api-Token: %s', CURSEFORGE_API_TOKEN)], $responseHeaders); $json = []; if ($result) { $json = json_decode($result, true); if (json_last_error() != JSON_ERROR_NONE) { $json = []; } } if (isset($json['id'])) { fwrite(STDERR, sprintf("Uploaded as file ID %d\n", $json['id'])); } else { fwrite(STDERR, "Error received from server.\n"); if (isset($responseHeaders['responseCode'])) { fwrite(STDERR, sprintf("Received response code %d\n", $responseHeaders['responseCode'])); } fwrite(STDERR, $result);
function UploadTweetMedia($data) { global $twitterCredentials; if ($twitterCredentials === false) { return false; } $boundary = ''; $mimedata['media'] = "content-disposition: form-data; name=\"media\"\r\nContent-Type: image/png\r\nContent-Transfer-Encoding: binary\r\n\r\n" . $data; while ($boundary == '') { for ($x = 0; $x < 16; $x++) { $boundary .= chr(rand(ord('a'), ord('z'))); } foreach ($mimedata as $d) { if (strpos($d, $boundary) !== false) { $boundary = ''; } } } $mime = ''; foreach ($mimedata as $d) { $mime .= "--{$boundary}\r\n{$d}\r\n"; } $mime .= "--{$boundary}--\r\n"; $oauth = new OAuth($twitterCredentials['consumerKey'], $twitterCredentials['consumerSecret']); $oauth->setToken($twitterCredentials[TWITTER_ACCOUNT]['accessToken'], $twitterCredentials[TWITTER_ACCOUNT]['accessTokenSecret']); $url = 'https://upload.twitter.com/1.1/media/upload.json'; $requestHeader = $oauth->getRequestHeader('POST', $url); $inHeaders = ["Authorization: {$requestHeader}", 'Content-Type: multipart/form-data; boundary=' . $boundary]; $outHeaders = []; $ret = \Newsstand\HTTP::Post($url, $mime, $inHeaders, $outHeaders); if ($ret) { $json = json_decode($ret, true); if (json_last_error() == JSON_ERROR_NONE) { if (isset($json['media_id_string'])) { return $json['media_id_string']; } else { DebugMessage('Parsed JSON response from post to twitter, no media id', E_USER_WARNING); DebugMessage(print_r($json, true), E_USER_WARNING); return false; } } else { DebugMessage('Non-JSON response from post to twitter', E_USER_WARNING); DebugMessage($ret, E_USER_WARNING); return false; } } else { DebugMessage('No/bad response from post to twitter', E_USER_WARNING); DebugMessage(print_r($outHeaders, true), E_USER_WARNING); return false; } }
function SendAndroidNotifications($regions) { global $db; global $timeZones, $timeLeftCodes, $regionNames; $sent = []; $AndroidEndpoint = 'https://android.googleapis.com/gcm/send'; foreach ($regions as $region) { $properRegion = strtoupper($region); if ($properRegion == 'US') { $properRegion = 'NA'; } $sql = 'select * from tblWowToken w where region = ? order by `when` desc limit 2'; $stmt = $db->prepare($sql); $stmt->bind_param('s', $region); $stmt->execute(); $result = $stmt->get_result(); $bothTokenData = DBMapArray($result, null); $tokenData = array_shift($bothTokenData); $prevTokenData = count($bothTokenData) ? array_shift($bothTokenData) : []; $stmt->close(); if (!$prevTokenData) { continue; } if ($tokenData['marketgold'] == $prevTokenData['marketgold']) { continue; } if ($tokenData['result'] != 1 || $tokenData['result'] != $prevTokenData['result']) { continue; } $d = new DateTime('now', timezone_open($timeZones[$region])); $d->setTimestamp(strtotime($tokenData['when'])); $formatted = ['BUY' => number_format($tokenData['marketgold']), 'TIMETOSELL' => isset($timeLeftCodes[$tokenData['timeleft']]) ? $timeLeftCodes[$tokenData['timeleft']] : $tokenData['timeleft'], 'UPDATED' => $d->format('M j g:ia T')]; $direction = $tokenData['marketgold'] > $prevTokenData['marketgold'] ? 'over' : 'under'; $sql = <<<EOF select s.endpoint, s.id, e.region, e.value from tblWowTokenSubs s join tblWowTokenEvents e on e.subid = s.id where s.lastfail is null and e.direction = '{$direction}' and e.region = '{$properRegion}' and s.endpoint like '{$AndroidEndpoint}%' EOF; if ($direction == 'over') { $sql .= ' and e.value >= ' . $prevTokenData['marketgold'] . ' and e.value < ' . $tokenData['marketgold']; } else { $sql .= ' and e.value <= ' . $prevTokenData['marketgold'] . ' and e.value > ' . $tokenData['marketgold']; } $stmt = $db->prepare($sql); $stmt->execute(); $result = $stmt->get_result(); $rows = DBMapArray($result, ['id']); $stmt->close(); if (count($rows) == 0) { continue; } //sells in " . $formatted['TIMETOSELL'] . ' $message = $regionNames[$properRegion] . ' price %s: now ' . $formatted['BUY'] . "g, as of " . $formatted['UPDATED'] . '.'; $chunks = array_chunk($rows, 50, true); foreach ($chunks as $chunk) { $lookup = []; $toSend = []; $failed = []; $successful = []; foreach ($chunk as $id => $row) { $registrationId = substr($row['endpoint'], strlen($AndroidEndpoint) + 1); $msg = sprintf($message, $direction . ' ' . number_format($row['value'], 0) . 'g'); $key = md5($row['endpoint']); if (!isset($sent[$key])) { $lookup[] = $id; $toSend[] = $registrationId; $sent[$key] = $msg; } else { $sent[$key] .= " \n" . $msg; } MCSet('tokennotify-' . $key, $sent[$key], 8 * 60 * 60); } if (!count($toSend)) { continue; } $toSend = json_encode(['registration_ids' => $toSend, 'time_to_live' => 4 * 60 * 60]); $headers = ['Authorization: key=' . ANDROID_GCM_KEY, 'Content-Type: application/json']; $outHeaders = []; $ret = \Newsstand\HTTP::Post($AndroidEndpoint, $toSend, $headers, $outHeaders); $ret = json_decode($ret, true); if (json_last_error() != JSON_ERROR_NONE || !isset($ret['results'])) { if (count($lookup) == 1 && isset($outHeaders['responseCode']) && $outHeaders['responseCode'] == '404') { // only sent one, which failed, so mark it as failed $successful = []; $failed = $lookup; } else { // can only assume all went through DebugMessage("Bad response from {$AndroidEndpoint}\n" . print_r($headers, true) . $toSend . "\n" . print_r($outHeaders, true) . "\n{$ret}"); $successful = $lookup; $failed = []; } } else { for ($x = 0; $x < count($ret['results']); $x++) { if (isset($ret['results'][$x]['error'])) { $failed[] = $lookup[$x]; } else { $successful[] = $lookup[$x]; } } } $stmt = $db->prepare('update tblWowTokenEvents set lasttrigger=now() where subid in (' . implode(',', $lookup) . ') and region=\'' . $properRegion . '\' and direction=\'' . $direction . '\''); $stmt->execute(); $stmt->close(); if (count($successful)) { $stmt = $db->prepare('update tblWowTokenSubs set lastpush=now() where id in (' . implode(',', $successful) . ')'); $stmt->execute(); $stmt->close(); } if (count($failed)) { $stmt = $db->prepare('update tblWowTokenSubs set lastpush=now(), lastfail=now() where id in (' . implode(',', $failed) . ')'); $stmt->execute(); $stmt->close(); } DebugMessage('Sent ' . count($lookup) . ' messages to ' . $AndroidEndpoint . ' - ' . count($successful) . ' successful, ' . count($failed) . ' failed.'); } } }
function ValidatePaypalNotification($rawPost, $useSandbox = false) { $url = sprintf('https://www%s.paypal.com/cgi-bin/webscr', $useSandbox ? '.sandbox' : ''); LogPaypalMessage("Validating {$rawPost}"); $result = \Newsstand\HTTP::Post($url, 'cmd=_notify-validate&' . $rawPost); if (trim($result) == 'VERIFIED') { return true; } return $result; }