AoyTasks Documentation
Welcome to the comprehensive guide for integrating the AoyTasks offerwall. Everything you need to get up and running smoothly is right here.
Getting Started
Before integrating our offerwall, make sure you're registered on aoyco.in, as an account is required to use any of our tools.
Add Your Website
To be able to integrate our offerwall, first you have to add your website. Once you have added your website you will have an API KEY, a SECRET KEY, and a BEARER TOKEN that you will need to integrate our offerwall.
Registration Steps
- 1 Login to your aoyco.in account.
- 2 Navigate to the Publisher -> My Apps page from the sidebar.
- 3 Fill out the "Create New App" form.
- 4 Set your Currency Name (e.g. Points), Exchange Rate (how many units = 1 USD), and Currency Decimals (e.g., 2 for 0.01).
- 5 Set your Postback URL. Whenever a user completes an offer, we will make a call to this URL by sending all the information needed to help you to credit the virtual currency to your users.
- Done! You have added your website. One of our team members will review it, and once it is Approved, you can begin integrating. You can edit your app details later by clicking the "Edit" button.
Integrate Offerwall
This is the easiest and recommended way to show our complete offerwall (PTC & Shortlinks) on your website. Our offerwall is responsive, secure (VPN/Proxy protected), and will adapt to any screen.
iFrame Integration
<iframe scrolling="yes"
frameborder="0"
src="https://aoyco.in/offerwall/[API_KEY]/[USER_ID]"
style="width: 100%; height: 1000px;">
</iframe>
JavaScript (New Tab) Integration
window.open("https://aoyco.in/offerwall/[API_KEY]/[USER_ID]")
Replace [API_KEY] with your website API key and [USER_ID] by the unique identifier code (e.g., 1, 123, or a898d7f...) of the user on your site who is viewing the wall.
Strict Rule: The [USER_ID] parameter only accepts alphanumeric characters (a-z, A-Z, 0-9). Other characters (like _ or =) will be rejected with a 404 error.
Mobile App Integration
If you are looking to integrate the offerwall into your native mobile app, use a WebView to show the offerwall inside your app.
Endpoint URL
https://aoyco.in/offerwall/[API_KEY]/[USER_ID]
Android WebView (Java)
WebView myWebView = new WebView(activityContext);
setContentView(myWebView);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl("https://aoyco.in/offerwall/[API_KEY]/[USER_ID]");
iOS WebView (Swift)
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string:"https://aoyco.in/offerwall/[API_KEY]/[USER_ID]")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}
}
React Native WebView
/* Add react-native-webview to your dependencies */
import { WebView } from 'react-native-webview';
return <WebView source={{ uri: 'https://aoyco.in/offerwall/[API_KEY]/[USER_ID]' }} />;
Direct API Integration Advanced
If you want to take our campaign data directly and adjust its appearance to the appearance of your website, you can use our Direct API feeds. You must include your BEARER TOKEN in the Authorization header for all requests.
Rate Limiting
This API is rate limited. Exceeding this limit may result in a 429 Too Many Requests error. Cache responses where possible.
1 PTC API Integration
Fetch active PTC ads using the following endpoint:
curl -X GET https://aoyco.in/api/v1/ptc/[API_KEY]/[USER_ID]/[USER_IP_ADDRESS] \
-H "Authorization: Bearer [BEARER_TOKEN]"
JSON Response
{
"status": "200",
"message": "success",
"data": [
{
"id": 41,
"image": "",
"title": "Visit this Awesome Site",
"description": "Get rewarded for visiting this site.",
"duration": 10,
"reward": "600.00",
"currency_name": "Coins",
"url": "https://aoyco.in/offer/ptc/go/eyJpdiI...",
"ad_type": "Iframe"
}
]
}
PHP Integration Example
function requestWithCurl($url, $token) {
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer $token",
"User-UA: $userAgent"
]);
$response = curl_exec($ch);
if(curl_errno($ch)) { $response = false; }
curl_close($ch);
return $response;
}
$url = 'https://aoyco.in/api/v1/ptc/[API_KEY]/[USER_ID]/[USER_IP_ADDRESS]';
$token = '[BEARER_TOKEN]';
$response = requestWithCurl($url, $token);
if($response) {
$responseArray = json_decode($response, true);
if(isset($responseArray['status']) && $responseArray['status'] == 200) {
foreach($responseArray['data'] as $ptc) {
echo "Title: " . $ptc['title'] . "\n";
echo "Reward: " . $ptc['reward'] . "\n";
echo "Link: " . $ptc['url'] . "\n";
}
}
} else {
echo "Request Failed";
}
Vie Script Controller Example
public function index()
{
$this->data['page'] = 'Paid To Click';
$this->data['totalReward'] = 0;
// Load Local Ads
$this->data['ptcAds'] = $this->m_ptc->availableAds($this->data['user']['id']);
// Load AoyTasks Ads
$url = 'https://aoyco.in/api/v1/ptc/[API_KEY]/'.$this->data['user']['id'].'/'.$this->input->ip_address();
$token = '[BEARER_TOKEN]'; // Your Bearer Token
$response = $this->requestWithCurl($url, $token);
if($response) {
$responseArray = json_decode($response, true);
if(isset($responseArray['status']) && $responseArray['status'] == 200) {
$this->data['aoytasks_ptc'] = $responseArray['data'];
}
}
$this->render('ptc', $this->data);
}
2 Shortlink API Integration
Fetch active Shortlinks using the following endpoint:
curl -X GET https://aoyco.in/api/v1/sl-api/[API_KEY]/[USER_ID]/[USER_IP_ADDRESS] \
-H "Authorization: Bearer [BEARER_TOKEN]"
JSON Response
{
"status": "200",
"message": "success",
"data": [
{
"id": 1,
"title": "ShortLink Name",
"reward": "600.00",
"currency_name": "Coins",
"available": "2",
"limit": "2",
"url": "https://aoyco.in/offer/link/go/eyJpdiI..."
}
]
}
PHP Integration Example
$url = 'https://aoyco.in/api/v1/sl-api/[API_KEY]/[USER_ID]/[USER_IP_ADDRESS]';
$token = '[BEARER_TOKEN]';
$response = requestWithCurl($url, $token);
if($response) {
$responseArray = json_decode($response, true);
if(isset($responseArray['status']) && $responseArray['status'] == 200) {
foreach($responseArray['data'] as $link) {
echo "Title: " . $link['title'] . "\n";
echo "Available: " . $link['available'] . "\n";
echo "URL: " . $link['url'] . "\n";
}
}
}
Vie Script Controller Example
public function index()
{
$this->data['page'] = 'Shortlinks Wall';
$this->data['availableLinks'] = $this->m_links->availableLinks($this->data['user']['id']);
// Load AoyTasks Shortlinks
$url = 'https://aoyco.in/api/v1/sl-api/[API_KEY]/'.$this->data['user']['id'].'/'.$this->input->ip_address();
$token = '[BEARER_TOKEN]';
$response = $this->requestWithCurl($url, $token);
if($response) {
$responseArray = json_decode($response, true);
if(isset($responseArray['status']) && $responseArray['status'] == 200) {
$this->data['aoytasks_sl'] = $responseArray['data'];
}
}
$this->render('links', $this->data);
}
3 Third-Party Offers API NEW
Fetch third-party offerwalls (CPX, Revlum, TimeWall):
curl -X GET https://aoyco.in/api/v1/offers/[API_KEY]/[USER_ID]/[USER_IP_ADDRESS] \
-H "Authorization: Bearer [BEARER_TOKEN]"
JSON Response
{
"status": "200",
"message": "success",
"data": [
{
"id": 1,
"name": "CPX Research",
"description": "Top paying surveys & daily rewards",
"image": "https://blog.cpx-research.com/...",
"url": "https://offers.cpx-research.com/...",
"badge": "HOT",
"rate_note": "1 USD = 10,000 Coins"
}
]
}
PHP Integration Example
$url = 'https://aoyco.in/api/v1/offers/[API_KEY]/[USER_ID]/[USER_IP_ADDRESS]';
$token = '[BEARER_TOKEN]';
$response = requestWithCurl($url, $token);
if($response) {
$responseArray = json_decode($response, true);
if(isset($responseArray['status']) && $responseArray['status'] == 200) {
foreach($responseArray['data'] as $offer) {
echo "Name: " . $offer['name'] . "\n";
echo "URL: " . $offer['url'] . "\n";
}
}
}
Vie Script Controller Example
public function index()
{
$this->data['page'] = 'Offerwalls';
// Load AoyTasks Third-Party Offers
$url = 'https://aoyco.in/api/v1/offers/[API_KEY]/'.$this->data['user']['id'].'/'.$this->input->ip_address();
$token = '[BEARER_TOKEN]';
$response = $this->requestWithCurl($url, $token);
if($response) {
$responseArray = json_decode($response, true);
if(isset($responseArray['status']) && $responseArray['status'] == 200) {
$this->data['aoytasks_offers'] = $responseArray['data'];
}
}
$this->render('offerwalls', $this->data);
}
Integrate on Faucet Scripts
We have provided some common faucet script integration methods here. With this tutorial, any faucet owner can easily integrate AoyTasks on their script.
Vie Faucet 4.4 Integration
It takes only three steps to integrate AoyTasks offerwall into your VieFaucet script.
Webhook Handler wh.php
Open file application/controllers/wh.php and enter the following code before the last closing bracket (}).
Important: We have updated our integration code to be secure and robust. Please use the exact code below.
public function aoytasks()
{
$secret = "YOUR_APP_SECRET_KEY"; // ⭐️ UPDATE YOUR SECRET KEY
$hold = 0; // UPDATE HOLD DAYS IF YOU USE HOLD
$minHold = 0; // Reward Lower than this amount will not be hold
// 1. Get RAW inputs for Signature Check
$subId_raw = $this->input->get('subId');
$transId_raw = $this->input->get('transId');
$reward_raw = $this->input->get('reward');
$signature = $this->input->get('signature');
$action_raw = $this->input->get('status');
$userIp_raw = $this->input->get('userIp');
// Check for missing data
if ($subId_raw === null || $subId_raw === '') {
echo "ERROR: No Data Received";
return;
}
// 2. Validate Signature (Must match AoyTasks signature format)
$check_signature = md5($subId_raw . $transId_raw . $reward_raw . $secret);
if ($check_signature != $signature) {
echo "ERROR: Signature doesn't match";
return;
}
// you can divide the reward by your currency rate here.
// if ($this->data['settings']['currency_rate'] > 0) {
// $reward_raw = $reward_raw / $this->data['settings']['currency_rate'];
// }
// 3. Sanitize inputs for Database
$userId = $this->db->escape_str($subId_raw);
$transactionId = $this->db->escape_str($transId_raw);
$reward = $this->db->escape_str($reward_raw);
$action = $this->db->escape_str($action_raw);
$userIp = $userIp_raw ? $this->db->escape_str($userIp_raw) : "0.0.0.0";
$trans = $this->m_offerwall->getTransaction($transactionId, 'AoyTasks');
if ($action == 2) {
// Chargeback
$this->m_offerwall->reduceUserBalance($userId, abs($reward));
$this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 1, time());
echo "ok";
} else {
// Credit (Status = 1)
if (!$trans) {
if ($hold == 0 || $reward < $minHold) {
$offerId = $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 2, time());
$this->m_offerwall->updateUserBalance($userId, $reward);
$this->m_core->addNotification($userId, currencyDisplay($reward, $this->data['settings']) . " from AoyTasks Offer #" . $offerId . " was credited to your balance.", 1);
$user = $this->m_core->getUserFromId($userId);
if($user) {
$this->m_core->addExp($user['id'], $this->data['settings']['offerwall_exp_reward']);
if (($user['exp'] + $this->data['settings']['offerwall_exp_reward']) >= ($user['level'] + 1) * 100) {
$this->m_core->levelUp($user['id']);
}
}
} else {
$availableAt = time() + $hold * 86400;
$offerId = $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 0, $availableAt);
$this->m_core->addNotification($userId, "Your AoyTasks Offer #" . $offerId . " is pending approval.", 0);
}
echo "ok";
} else {
echo "DUP";
}
}
}
Controller offerwall.php
Open application/controllers/offerwall.php file, add this code before the last closing bracket (}).
public function aoytasks()
{
$api_key = "YOUR_APP_API_KEY"; // ⭐️ UPDATE YOUR API KEY HERE
$this->data['page'] = 'AoyTasks Offerwall';
$this->data['iframe'] = '<iframe style="width:100%;height:800px;border:0;padding:0;margin:0;" scrolling="yes" frameborder="0" src="https://aoyco.in/offerwall/' . $api_key . '/' . $this->data['user']['id'] . '"></iframe>';
$this->data['wait'] = 0; // UPDATE YOUR HOLD TIME
$this->render('offerwall', $this->data);
}
View & Config
1. Sidebar Menu: Go to application/views/user_template/template.php, and place this code in the sidebar menu.
<li><a href="<?= site_url('offerwall/aoytasks') ?>" key="t-aoytasks">AoyTasks</a></li>
2. Final Step: Open Application/Config/config.php and add 'wh/aoytasks', to the $config['csrf_exclude_uris'] array.
Settings in AoyTasks Panel
Your PostBack URL should be set to: https://yourdomain.com/wh/aoytasks
Vie Faucet 4.3 Integration
The integration for 4.3 is almost identical to 4.4. Follow the steps above, but use this code for Step 1 (wh.php):
public function aoytasks()
{
$secret = "YOUR_APP_SECRET_KEY"; // ⭐️ UPDATE YOUR SECRET KEY
$hold = 0; // UPDATE HOLD DAYS IF YOU USE HOLD
$minHold = 0; // Reward Lower than this amount will not be hold
$subId_raw = $this->input->get('subId');
$transId_raw = $this->input->get('transId');
$reward_raw = $this->input->get('reward');
$signature = $this->input->get('signature');
$action_raw = $this->input->get('status');
$userIp_raw = $this->input->get('userIp');
if ($subId_raw === null || $subId_raw === '') {
echo "ERROR: No Data Received";
return;
}
$check_signature = md5($subId_raw . $transId_raw . $reward_raw . $secret);
if ($check_signature != $signature) {
echo "ERROR: Signature doesn't match";
return;
}
$userId = $this->db->escape_str($subId_raw);
$transactionId = $this->db->escape_str($transId_raw);
$reward = $this->db->escape_str($reward_raw);
$action = $this->db->escape_str($action_raw);
$userIp = $userIp_raw ? $this->db->escape_str($userIp_raw) : "0.0.0.0";
$trans = $this->m_offerwall->getTransaction($transactionId, 'AoyTasks');
if ($action == 2) {
$this->m_offerwall->reduceUserBalance($userId, abs($reward));
$this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 1, time());
echo "ok";
} else {
if (!$trans) {
if ($hold == 0 || $reward < $minHold) {
$offerId = $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 2, time());
$this->m_offerwall->updateUserBalance($userId, $reward);
// Note: Vie 4.3 uses currency() function
$this->m_core->addNotification($userId, currency($reward, $this->data['settings']['currency_rate']) . " from AoyTasks Offer #" . $offerId . " was credited to your balance.", 1);
$user = $this->m_core->get_user_from_id($userId);
if($user) {
$this->m_core->addExp($user['id'], $this->data['settings']['offerwall_exp_reward']);
if (($user['exp'] + $this->data['settings']['offerwall_exp_reward']) >= ($user['level'] + 1) * 100) {
$this->m_core->levelUp($user['id']);
}
}
} else {
$availableAt = time() + $hold * 86400;
$offerId = $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 0, $availableAt);
$this->m_core->addNotification($userId, "Your AoyTasks Offer #" . $offerId . " is pending approval.", 0);
}
echo "ok";
} else {
echo "DUP";
}
}
}
CryptoFaucet / ClaimBits Integration
Integration is very easy in this script. Less than 5 minutes!
Create Gateway File
Open system/gateways/ and create a new file named aoytasks.php. Put the following code in this file:
<?php
define('BASEPATH', true);
require('../init.php');
$secret = "YOUR_APP_SECRET_KEY"; // ⭐️ Enter Your AoyTasks SECRET KEY
// 1. Get RAW inputs
$subId_raw = isset($_REQUEST['subId']) ? $_REQUEST['subId'] : null;
$transId_raw = isset($_REQUEST['transId']) ? $_REQUEST['transId'] : null;
$reward_raw = isset($_REQUEST['reward']) ? $_REQUEST['reward'] : null;
$signature = isset($_REQUEST['signature']) ? $_REQUEST['signature'] : null;
// 2. Validate Signature (Using RAW inputs)
if (md5($subId_raw.$transId_raw.$reward_raw.$secret) != $signature){
echo "ERROR: Signature doesn't match";
return;
}
// 3. Escape inputs for Database
$userId = $db->EscapeString($subId_raw);
$transId = $db->EscapeString($transId_raw);
$reward = $db->EscapeString($reward_raw);
$payout = isset($_REQUEST['payout']) ? $db->EscapeString($_REQUEST['payout']) : null;
$action = isset($_REQUEST['status']) ? $db->EscapeString($_REQUEST['status']) : null;
$userIP = isset($_REQUEST['userIp']) ? $db->EscapeString($_REQUEST['userIp']) : '0.0.0.0';
$country = isset($_REQUEST['country']) ? $db->EscapeString($_REQUEST['country']) : null;
if ($action == 2) {
// Chargeback Logic
echo 'ok';
return;
}
// Credit Logic
if(!empty($userId) && $db->QueryGetNumRows("SELECT * FROM `completed_offers` WHERE `survey_id`='".$transId."' LIMIT 1") == 0)
{
$user = $db->QueryFetchArray("SELECT `id` FROM `users` WHERE `id`='".$userId."'");
if(!empty($user['id'])) {
$tc_points = (0.10 * ($payout * 100)); // Example contest points
$tc_points = ($tc_points < 1 ? 1 : number_format($tc_points, 0));
$db->Query("UPDATE `users` SET `ow_credits`=`ow_credits`+'".$reward."', `tasks_contest`=`tasks_contest`+'".$tc_points."' WHERE `id`='".$user['id']."'");
$db->Query("INSERT INTO `users_offers` (`uid`,`total_offers`,`total_revenue`,`last_offer`) VALUES ('".$user['id']."','1','".$reward."','".time()."') ON DUPLICATE KEY UPDATE `total_offers`=`total_offers`+'1', `total_revenue`=`total_revenue`+'".$reward."', `last_offer`='".time()."'");
$db->Query("INSERT INTO `completed_offers` (`user_id`,`survey_id`,`user_country`,`user_ip`,`revenue`,`reward`,`method`,`timestamp`) VALUES ('".$user['id']."','".$transId."','".$country."','".ip2long($userIP)."','".$payout."','".$reward."','AoyTasks','".time()."')");
}
}
echo 'ok';
?>
Display Offerwall
1. Register View: Open template/default/pages/offers.php, and add the following code after one of the existing offerwalls (e.g., after a break; statement).
case 'aoytasks' :
$title = 'AoyTasks';
$offer_wall = '<iframe src="https://aoyco.in/offerwall/YOUR_APP_API_KEY/'.$data['id'].'" style="width:100%;height:690px;border:0;border-radius:5px;"></iframe>';
break;
2. Insert Link: In the same file (offers.php), scroll down and insert the link to the AoyTasks offerwall:
<a href="<?php echo GenerateURL('offers&x=aoytasks'); ?>" class="btn btn-secondary mb-1<?php echo ($method == 'aoytasks' ? ' active' : ''); ?>">AoyTasks</a>
Settings in AoyTasks Panel
- Currency should be set in
creditson AoyTasks 'My Apps' page. - Your PostBack URL should be:
http://yourdomain.com/system/gateways/aoytasks.php
WAF Script Integration (Legacy)
These steps detail the integration of AoyTasks into older WAF-based scripts.
Update Offerwall Controller
Go to the file app/Http/Controllers/OfferwallController.php and add 'aoytasks' => 'AoyTasks' to the $allowedofferwalls array inside the index function.
public function index(Request $request, $offerwall)
{
$allowedofferwalls = ['bitcotasks' => 'Bitcotasks', 'wannads' => 'Wannads', 'aoytasks' => 'AoyTasks'];
// ... rest of the code ...
}
Add API Routes
Go to the file routes/web.php and add the following code at the bottom of the file.
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
Route::get('/get-aoytasks-ptc', function (Request $request) {
$api = get_setting('aoytasks_api');
$token = get_setting('aoytasks_token');
$userId = Auth::id();
$userIp = $request->ip();
$client = new \GuzzleHttp\Client();
try {
$response = $client->request('GET', "https://aoyco.in/api/v1/ptc/{$api}/{$userId}/{$userIp}", [
'headers' => [
'Authorization' => "Bearer {$token}",
'Accept' => 'application/json',
],
'timeout' => 10,
]);
$body = json_decode($response->getBody(), true);
if (isset($body['status']) && $body['status'] == 200) {
return response()->json(['success' => true, 'data' => $body['data']]);
}
return response()->json(['success' => false, 'message' => $body['message'] ?? 'Failed to load offers.']);
} catch (\Exception $e) {
return response()->json(['success' => false, 'message' => $e->getMessage()]);
}
})->name('offerwall.aoytasks.ptc');
Route::get('/get-aoytasks-shortlink', function (Request $request) {
$api = get_setting('aoytasks_api');
$token = get_setting('aoytasks_token');
$userId = Auth::id();
$userIp = $request->ip();
$client = new \GuzzleHttp\Client();
try {
$response = $client->request('GET', "https://aoyco.in/api/v1/sl-api/{$api}/{$userId}/{$userIp}", [
'headers' => [
'Authorization' => "Bearer {$token}",
'Accept' => 'application/json',
],
'timeout' => 10,
]);
$body = json_decode($response->getBody(), true);
if (isset($body['status']) && $body['status'] == 200) {
return response()->json(['success' => true, 'data' => $body['data']]);
}
return response()->json(['success' => false, 'message' => $body['message'] ?? 'Failed to load offers.']);
} catch (\Exception $e) {
return response()->json(['success' => false, 'message' => $e->getMessage()]);
}
})->name('offerwall.aoytasks.sl');
Route::get('/get-aoytasks-offers', function (Request $request) {
$api = get_setting('aoytasks_api');
$token = get_setting('aoytasks_token');
$userId = Auth::id();
$userIp = $request->ip();
$client = new \GuzzleHttp\Client();
try {
$response = $client->request('GET', "https://aoyco.in/api/v1/offers/{$api}/{$userId}/{$userIp}", [
'headers' => [
'Authorization' => "Bearer {$token}",
'Accept' => 'application/json',
],
'timeout' => 10,
]);
$body = json_decode($response->getBody(), true);
if (isset($body['status']) && $body['status'] == 200) {
return response()->json(['success' => true, 'data' => $body['data']]);
}
return response()->json(['success' => false, 'message' => $body['message'] ?? 'Failed to load offers.']);
} catch (\Exception $e) {
return response()->json(['success' => false, 'message' => $e->getMessage()]);
}
})->name('offerwall.aoytasks.offers');
Upload View Files & Configurations
You need to upload a few files to integrate the AoyTasks UI into your admin panel and user dashboard. Please download the provided files and place them in the correct directories on your server.
Admin View
Upload to: resources/views/admin/settings/aoytasks.blade.php
Access Link: https://example.com/admin/setting/aoytasks
User View
Upload to: resources/views/offerwalls/aoytasks.blade.php
Access Link: https://example.com/offerwall/aoytasks
Database Import
Import this SQL file into your database via phpMyAdmin to create the required tables.
WAF Script V1.1+ Integration
This section guides you through the integration of the AoyTasks offerwall specifically for WAF Script V1.1+. This updated version utilizes the dynamic postback system and standalone view templates, requiring zero external JavaScript dependencies and no postback controller modifications.
Admin Dashboard Configuration
Option A: Fast JSON Import Recommended
Don't want to configure everything manually? Simply download our pre-made JSON config file and import it directly inside your WAF Script dashboard.
Option B: Manual Dashboard Configuration
If you prefer manual configuration, navigate to /admin/postback-list and enter the details below:
Navigate to /admin/postback-list in your Admin Dashboard and create a New Config. Set the Offerwall Name to aoycoin. Carefully fill out the fields as shown below:
General Settings
- Request Method: Select
GET - Whitelisted IPs: Enter
145.79.26.204, 2a02:4780:5c:2200:0:1957:fb47:1 - Rewarded Status Value: Enter
1 - Denied Status Value: Enter
2 - Response Text: Type exactly
ok(lowercase only) - Response Code: Enter
200 - Hash Type: Select
MD5 - Hash Separator / Prefix: Leave this completely empty
CRITICAL: The order in which you add parameters affects the security hash calculation. You MUST click "Add Parameter" and add the first 4 parameters in the exact sequential order shown below to match the AoyTasks format.
| Creation Order | Parameter Name | Checkboxes to Select |
|---|---|---|
| Order 1 | subId | Is UID & Include in Hash |
| Order 2 | transId | Is TXID & Include in Hash |
| Order 3 | reward | Is Reward & Include in Hash |
| Order 4 | secret | Is Secret Key & Include in Hash |
| Order 5 | signature | Is Signature (DO NOT select Include in Hash) |
| Order 6 | status | Is Status |
| Order 7 | userIp | Is IP |
| Order 8 | country | Is Country |
Add API Fetch Routes web.php
Open the routes/web.php file. Add the following API fetch routes inside the authenticated middleware group Route::middleware(['ip.lookup', 'auth'])->group(function () { ... });
Route::get('/get-aoycoin-ptc', [\App\Http\Controllers\OfferwallController::class, 'fetchAoycoPTC'])->middleware('throttle:offerwall');
Route::get('/get-aoycoin-shortlink', [\App\Http\Controllers\OfferwallController::class, 'fetchAoycoSL'])->middleware('throttle:offerwall');
Route::get('/get-aoycoin-offers', [\App\Http\Controllers\OfferwallController::class, 'fetchAoycoOF'])->middleware('throttle:offerwall');
Update the Offerwall Controller OfferwallController.php
Open app/Http/Controllers/OfferwallController.php. Add these three methods inside the class to act as a bridge for the API requests:
public function fetchAoycoPTC(Request $request)
{
return $this->offerwallService->fetchAoycoPTC($request);
}
public function fetchAoycoSL(Request $request)
{
return $this->offerwallService->fetchAoycoSL($request);
}
public function fetchAoycoOF(Request $request)
{
return $this->offerwallService->fetchAoycoOF($request);
}
Update Offerwall Data Fetch Service OfferwallService.php
Open app/Services/Offerwall/OfferwallService.php. First, map the display name inside the index method. Then, append the actual curl fetch logic to the bottom of the class.
1. Map the variable keys inside the index() method:
public function index(Request $request, $offerwall)
{
$supported = [
'bitcotasks',
'cpx',
'monlix',
'notik',
'excentiv',
'timewall',
'offerwallmedia',
'offerwallme',
'aoycoin', // ⭐️ ADD THIS
];
// ...
$pageNames = [
'bitcotasks' => 'Bitcotasks',
'aoycoin' => 'AoyCo.in', // ⭐️ ADD THIS
'cpx' => 'CPX Research',
// ...
];
// ...
}
2. Add the fetching logic to the bottom of the class:
private function fetchAoycoData($endpoint)
{
$userId = Auth::id();
$ipAddress = request()->ip();
$api = get_setting('aoycoin_api');
$url = "https://aoyco.in/api/v1/$endpoint/$api/$userId/$ipAddress";
$token = get_setting('aoycoin_token');
$userAgent = request()->userAgent() ?? 'Mozilla/5.0';
$client = new Client();
try {
$response = $client->request('GET', $url, [
'headers' => [
'Authorization' => "Bearer $token",
'User-UA' => $userAgent,
'Accept' => 'application/json',
],
'timeout' => 15,
]);
$body = json_decode($response->getBody(), true);
if (!isset($body['status']) || $body['status'] != 200) {
return response()->json(['success' => false, 'message' => $body['message'] ?? 'Unknown error']);
}
foreach ($body['data'] ?? [] as $key => $item) {
if (isset($item['reward'])) {
$safeReward = floatval($item['reward']);
$body['data'][$key]['reward'] = addSymbol($safeReward);
}
}
return response()->json(['success' => true, 'data' => $body['data'] ?? []]);
} catch (RequestException $e) {
$msg = $e->getCode() == 28 ? 'Request timeout, please try again.' : 'Request failed: ' . $e->getMessage();
return response()->json(['success' => false, 'message' => $msg]);
}
}
public function fetchAoycoPTC(Request $request)
{
if (!$request->ajax()) return response()->json(['error' => 'Invalid request'], 400);
return $this->fetchAoycoData('ptc');
}
public function fetchAoycoSL(Request $request)
{
if (!$request->ajax()) return response()->json(['error' => 'Invalid request'], 400);
return $this->fetchAoycoData('sl-api');
}
public function fetchAoycoOF(Request $request)
{
if (!$request->ajax()) return response()->json(['error' => 'Invalid request'], 400);
return $this->fetchAoycoData('offers');
}
Create Blade View Templates
Create the following two blade templates to handle the user interface and admin backend configuration.
1. Admin Settings Template resources/views/admin/settings/aoycoin.blade.php
Access Route: /admin/setting/aoycoin
Database Note: Once you set and save your API keys on this page, the system will automatically handle the database configurations for you. You do NOT need to manually create any tables or import SQL files.
<x-admin-layout>
@section('title', $page . ' | ' . get_setting('site_name'))
<div class="mt-4 grid grid-cols-12 gap-4 sm:mt-5 sm:gap-5 lg:mt-6 lg:gap-6">
<div class="col-span-12">
<div class="card px-4 pb-4 sm:px-5">
<div class="space-y-4">
<h2 class="text-2xl font-semibold text-slate-600 dark:text-navy-100 mt-4 mb-4">
{{ $page }}
</h2>
@if(session('success'))
<div class="alert flex items-center overflow-hidden rounded-lg border border-success text-success">
<div class="px-4 py-3 sm:px-5">
<strong>{{ session('success') }}</strong>
</div>
</div>
@endif
@if(session('error'))
<div class="alert flex items-center overflow-hidden rounded-lg border border-error text-error">
<div class="px-4 py-3 sm:px-5">
<strong>{{ session('error') }}</strong>
</div>
</div>
@endif
</div>
<form action="/admin/settings/update?route=aoycoin" method="POST" class="mt-4">
@csrf
<div class="space-y-4">
<div>
<label class="block text-sm font-medium py-3">AoyCoin Status</label>
<div class="flex items-center space-x-3">
<span class="text-sm">Off</span>
<label class="inline-flex items-center space-x-2">
<input type="hidden" name="aoycoin_status" value="off" />
<input
id="aoycoin_status"
name="aoycoin_status"
type="checkbox"
value="on"
@checked(get_setting('aoycoin_status') == 'on')
class="form-switch h-5 w-10 rounded-full bg-slate-300 before:rounded-full before:bg-slate-50 checked:bg-primary checked:before:bg-white dark:bg-navy-900 dark:before:bg-navy-300 dark:checked:bg-accent dark:checked:before:bg-white"
/>
</label>
<span class="text-sm">On</span>
</div>
</div>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div>
<label class="block text-sm font-medium py-3">AoyCoin Api Key:</label>
<input id="aoycoin_api" name="aoycoin_api" type="text" value="{{ get_setting('aoycoin_api') }}" class="form-input peer w-full rounded-lg border border-slate-300 bg-transparent px-3 py-2 pl-4 placeholder:text-slate-400/70 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:hover:border-navy-400 dark:focus:border-accent" />
</div>
<div>
<label class="block text-sm font-medium py-3">AoyCoin Secret Key:</label>
<input id="aoycoin_secret" name="aoycoin_secret" type="text" value="{{ get_setting('aoycoin_secret') }}" class="form-input peer w-full rounded-lg border border-slate-300 bg-transparent px-3 py-2 pl-4 placeholder:text-slate-400/70 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:hover:border-navy-400 dark:focus:border-accent" />
</div>
<div>
<label class="block text-sm font-medium py-3">AoyCoin Bearer Token:</label>
<input id="aoycoin_token" name="aoycoin_token" type="text" value="{{ get_setting('aoycoin_token') }}" class="form-input peer w-full rounded-lg border border-slate-300 bg-transparent px-3 py-2 pl-4 placeholder:text-slate-400/70 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:hover:border-navy-400 dark:focus:border-accent" />
</div>
<div>
<label class="block text-sm font-medium py-3">Pending if Reward is equal or more than ($):</label>
<input id="aoycoin_hold" name="aoycoin_hold" type="number" step="0.000001" value="{{ get_setting('aoycoin_hold') }}" class="form-input peer w-full rounded-lg border border-slate-300 bg-transparent px-3 py-2 pl-4 placeholder:text-slate-400/70 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:hover:border-navy-400 dark:focus:border-accent" />
</div>
</div>
<div>
<label class="block text-sm font-medium py-3">Postback Url:</label>
<pre><code>{{ url('/pb/aoycoin') }}</code></pre>
</div>
<button type="submit" class="btn space-x-2 bg-primary font-medium text-white hover:bg-primary-focus focus:bg-primary-focus active:bg-primary-focus/90 dark:bg-accent dark:hover:bg-accent-focus dark:focus:bg-accent-focus dark:active:bg-accent/90">Save</button>
</div>
</form>
</div>
</div>
</div>
</x-admin-layout>
2. Standalone Frontend User View resources/views/offerwalls/aoycoin.blade.php
<x-app-layout>
@section('title', $page . ' | ' . get_setting('site_name'))
<div class="mt-4 grid grid-cols-12 gap-4 sm:mt-5 sm:gap-5 lg:mt-6 lg:gap-6">
<div class="col-span-12">
<div x-data="{ activeTab: 'ptc' }" class="tabs flex flex-col">
<div class="is-scrollbar-hidden overflow-x-auto rounded-lg bg-slate-200 text-slate-600 dark:bg-navy-800 dark:text-navy-200">
<div class="tabs-list flex px-1.5 py-1 gap-2">
<button @click="activeTab = 'ptc'"
:class="activeTab === 'ptc' ? 'bg-white dark:bg-navy-600 text-primary dark:text-accent shadow' : 'hover:text-slate-800 dark:hover:text-navy-100'"
class="btn rounded-full px-5 py-1.5 text-xs+ font-medium transition-all duration-200"
id="loadPtcAds">
PTC
</button>
<button @click="activeTab = 'shortlink'"
:class="activeTab === 'shortlink' ? 'bg-white dark:bg-navy-600 text-primary dark:text-accent shadow' : 'hover:text-slate-800 dark:hover:text-navy-100'"
class="btn rounded-full px-5 py-1.5 text-xs+ font-medium transition-all duration-200"
id="loadShortlinks">
Shortlink
</button>
<button @click="activeTab = 'offers'"
:class="activeTab === 'offers' ? 'bg-white dark:bg-navy-600 text-primary dark:text-accent shadow' : 'hover:text-slate-800 dark:hover:text-navy-100'"
class="btn rounded-full px-5 py-1.5 text-xs+ font-medium transition-all duration-200"
id="loadOffers">
Offers
</button>
<button onclick="window.open('https://aoyco.in/offerwall/{{ get_setting('aoycoin_api') }}/{{ Auth::user()->id }}')"
class="btn rounded-full px-5 py-1.5 text-xs+ font-medium transition-all duration-200 hover:text-slate-800 dark:hover:text-navy-100">
More Offers
</button>
<button @click="activeTab = 'history'"
:class="activeTab === 'history' ? 'bg-white dark:bg-navy-600 text-primary dark:text-accent shadow' : 'hover:text-slate-800 dark:hover:text-navy-100'"
class="btn rounded-full px-5 py-1.5 text-xs+ font-medium transition-all duration-200">
History
</button>
</div>
</div>
<x-user-page-ad name="offer_top_ad" />
<div x-show="activeTab === 'ptc'" class="pt-4">
<div id="ptc-result"></div>
<div id="ptc-ads-pagination" class="mt-4 flex justify-center"></div>
</div>
<div x-show="activeTab === 'shortlink'" class="pt-4">
<div id="shortlink-result"></div>
<div id="shortlink-ads-pagination" class="mt-4 flex justify-center"></div>
</div>
<div x-show="activeTab === 'offers'" class="pt-4">
<div id="offers-result"></div>
<div id="offers-ads-pagination" class="mt-4 flex justify-center"></div>
</div>
<div x-show="activeTab === 'history'" class="mt-4">
<div class="card border-l-4 border-primary">
<div class="px-4 py-4 sm:px-5">
<h2 class="text-base font-medium tracking-wide text-slate-700 dark:text-navy-100">Offerwall History</h2>
</div>
<div class="overflow-x-auto">
<table class="is-hoverable w-full text-left">
<thead>
<tr>
<th class="whitespace-nowrap rounded-tl-lg bg-slate-200 px-4 py-3 font-semibold uppercase text-slate-800 dark:bg-navy-800 dark:text-navy-100 lg:px-5">Status</th>
<th class="whitespace-nowrap bg-slate-200 px-4 py-3 font-semibold uppercase text-slate-800 dark:bg-navy-800 dark:text-navy-100 lg:px-5">Transaction</th>
<th class="whitespace-nowrap bg-slate-200 px-4 py-3 font-semibold uppercase text-slate-800 dark:bg-navy-800 dark:text-navy-100 lg:px-5">Balance</th>
<th class="whitespace-nowrap bg-slate-200 px-4 py-3 font-semibold uppercase text-slate-800 dark:bg-navy-800 dark:text-navy-100 lg:px-5">Date</th>
</tr>
</thead>
<tbody id="offerwall-history"></tbody>
</table>
</div>
</div>
<div id="pagination" class="mt-4 flex justify-center"></div>
</div>
<x-user-page-ad name="offer_bottom_ad" />
</div>
</div>
</div>
@push('scripts')
<script>
$(document).ready(function() {
const offerwall = 'aoycoin';
const ITEMS_PER_PAGE = 12;
var offerGoalItems = {};
let aoyItems = { ptc: [], shortlink: [], offers: [] };
let aoyLoaded = { ptc: false, shortlink: false, offers: false };
// --- Shared Utilities ---
function buildPageHtml(currentPage, totalPages, btnClass) {
if (totalPages <= 1) return '';
var s = Math.max(1, currentPage - 2);
var e = Math.min(totalPages, s + 4);
var prev = currentPage > 1 ? currentPage - 1 : '';
var next = currentPage < totalPages ? currentPage + 1 : '';
var html = `<ol class="pagination">
<li class="rounded-l-full bg-slate-150 dark:bg-navy-500">
<a href="#" class="${btnClass} flex size-8 items-center justify-center rounded-full text-slate-500 transition-colors hover:bg-slate-300" data-page="${prev}" ${prev ? '' : 'disabled'}>
<svg xmlns="http://www.w3.org/2000/svg" class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7"/></svg>
</a>
</li>`;
if (s > 1) {
html += `<li class="bg-slate-150 dark:bg-navy-500"><a href="#" class="${btnClass} flex h-8 min-w-[2rem] items-center justify-center rounded-full px-3" data-page="1">1</a></li>`;
if (s > 2) html += `<li class="bg-slate-150 dark:bg-navy-500">...</li>`;
}
for (var i = s; i <= e; i++) {
html += `<li class="bg-slate-150 dark:bg-navy-500"><a href="#" class="${btnClass} flex h-8 min-w-[2rem] items-center justify-center rounded-full px-3 ${i === currentPage ? 'bg-primary text-white dark:bg-accent' : 'transition-colors hover:bg-slate-300'}" data-page="${i}">${i}</a></li>`;
}
if (e < totalPages) {
if (e < totalPages - 1) html += `<li class="bg-slate-150 dark:bg-navy-500">...</li>`;
html += `<li class="bg-slate-150 dark:bg-navy-500"><a href="#" class="${btnClass} flex h-8 min-w-[2rem] items-center justify-center rounded-full px-3" data-page="${totalPages}">${totalPages}</a></li>`;
}
html += `<li class="rounded-r-full bg-slate-150 dark:bg-navy-500">
<a href="#" class="${btnClass} flex size-8 items-center justify-center rounded-full text-slate-500 transition-colors hover:bg-slate-300" data-page="${next}" ${next ? '' : 'disabled'}>
<svg xmlns="http://www.w3.org/2000/svg" class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
</a>
</li></ol>`;
return html;
}
function escapeHtml(value) {
return String(value ?? '').replace(/[&<>"']/g, function(char) {
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[char];
});
}
function escapeAttr(value) { return escapeHtml(value).replace(/`/g, '`'); }
function safeUrl(value) { var url = String(value || '').trim(); return !/^(https?:)?\/\//i.test(url) ? '#' : escapeAttr(url); }
function safeRawUrl(value) { var url = String(value || '').trim(); return !/^(https?:)?\/\//i.test(url) ? '#' : url; }
function rewardHtml(value) { return value ? String(value) : 'N/A'; }
function loadingCardHtml() {
var card = '<div class="card border-l-4 border-primary p-4 rounded-xl flex flex-col gap-4">'
+ '<div class="flex items-start justify-between gap-3">'
+ '<div class="flex min-w-0 items-center gap-3">'
+ '<div class="skeleton animate-wave size-12 shrink-0 rounded-lg bg-slate-150 dark:bg-navy-500"></div>'
+ '<div class="min-w-0 flex-1">'
+ '<div class="skeleton animate-wave h-4 w-32 rounded bg-slate-150 dark:bg-navy-500"></div>'
+ '<div class="skeleton animate-wave mt-2 h-3 w-20 rounded bg-slate-150 dark:bg-navy-500"></div>'
+ '</div>'
+ '</div>'
+ '<div class="skeleton animate-wave h-5 w-14 rounded-full bg-slate-150 dark:bg-navy-500"></div>'
+ '</div>'
+ '<div>'
+ '<div class="skeleton animate-wave h-3 w-full rounded bg-slate-150 dark:bg-navy-500"></div>'
+ '<div class="skeleton animate-wave mt-2 h-3 w-10/12 rounded bg-slate-150 dark:bg-navy-500"></div>'
+ '</div>'
+ '<div class="mt-auto flex items-center justify-between gap-3 pt-2">'
+ '<div class="skeleton animate-wave h-4 w-20 rounded bg-slate-150 dark:bg-navy-500"></div>'
+ '<div class="skeleton animate-wave h-9 w-24 rounded-full bg-slate-150 dark:bg-navy-500"></div>'
+ '</div>'
+ '</div>';
return '<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-5 xl:grid-cols-3 lg:gap-6">' + card + card + card + '</div>';
}
function ensureGoalModal() {
if ($('#offer-goal-modal').length) return;
$('body').append(`
<div id="offer-goal-modal" class="fixed inset-0 z-[100] hidden px-4 py-6 sm:px-5">
<div class="absolute inset-0 bg-slate-900/60"></div>
<div class="relative mx-auto flex h-full max-w-2xl items-center justify-center">
<div class="is-scrollbar-hidden max-h-[90vh] w-full overflow-y-auto rounded-lg bg-white px-4 py-5 shadow-xl dark:bg-navy-700 sm:px-5">
<div class="flex items-start justify-between gap-4">
<div class="flex items-start gap-3">
<img id="offer-goal-modal-image" class="hidden size-14 rounded-lg object-cover" alt="">
<div>
<h3 id="offer-goal-modal-title" class="text-lg font-semibold text-slate-700 dark:text-navy-100"></h3>
<p id="offer-goal-modal-reward" class="mt-1 text-sm font-semibold text-primary dark:text-accent"></p>
</div>
</div>
</div>
<p id="offer-goal-modal-description" class="mt-4 text-sm leading-relaxed text-slate-500 dark:text-navy-100"></p>
<div class="mt-4">
<p class="text-sm font-semibold text-slate-700 dark:text-navy-100">Goals</p>
<div id="offer-goal-modal-goals" class="mt-2 divide-y divide-slate-150 rounded-lg border border-slate-150 dark:divide-navy-500 dark:border-navy-500"></div>
</div>
<div class="mt-5 flex justify-end gap-2">
<button type="button" id="offer-goal-modal-cancel" class="btn rounded-full bg-slate-150 px-4 py-2 text-xs+ font-medium text-slate-700 dark:bg-navy-500 dark:text-navy-100">Close</button>
<a id="offer-goal-modal-start" href="#" target="_blank" rel="noopener noreferrer" class="btn rounded-full bg-primary px-4 py-2 text-xs+ font-medium text-white dark:bg-accent">Start Offer</a>
</div>
</div>
</div>
</div>`);
$(document).on('click', '#offer-goal-modal-close, #offer-goal-modal-cancel, #offer-goal-modal > .absolute', function() {
$('#offer-goal-modal').addClass('hidden');
});
}
function openGoalModal(item, btnLabel) {
ensureGoalModal();
$('#offer-goal-modal-title').text(item.title || 'Offer');
$('#offer-goal-modal-reward').html(rewardHtml(item.reward));
$('#offer-goal-modal-description').text(item.description || '');
$('#offer-goal-modal-start').attr('href', safeRawUrl(item.url)).text(btnLabel || 'Start Offer');
if (item.image) { $('#offer-goal-modal-image').attr('src', safeRawUrl(item.image)).removeClass('hidden'); }
else { $('#offer-goal-modal-image').addClass('hidden').attr('src', ''); }
var goalsHtml = (item.goals || []).map(function(goal) {
return `<div class="flex items-start justify-between gap-3 px-4 py-3">
<div><p class="text-sm font-medium text-slate-700 dark:text-navy-100">${escapeHtml(goal.name || 'Goal')}</p></div>
<span class="shrink-0 text-sm font-semibold text-primary dark:text-accent">${rewardHtml(goal.reward)}</span>
</div>`;
}).join('');
$('#offer-goal-modal-goals').html(goalsHtml || '<div class="px-4 py-3 text-sm text-slate-500">No goals listed.</div>');
$('#offer-goal-modal').removeClass('hidden');
}
function buildOfferCard(item, btnLabel) {
var imageHtml = item.image ? `<img src="${safeUrl(item.image)}" class="size-12 rounded-lg object-cover shrink-0" onerror="this.style.display='none'">` : '';
var hasGoals = item.goals && item.goals.length;
var goalKey = hasGoals ? 'aoycoin-' + String(item.id || item.title) + '-' + Math.random().toString(36).slice(2) : '';
if (hasGoals) { offerGoalItems[goalKey] = { item: item, btnLabel: btnLabel }; }
var actionHtml = hasGoals
? `<button type="button" class="btn offer-goal-btn text-xs bg-primary font-medium text-white dark:bg-accent" data-goal-key="${escapeAttr(goalKey)}">${escapeHtml(btnLabel)}</button>`
: `<a href="${safeUrl(item.url)}" target="_blank" rel="noopener noreferrer" class="btn text-xs bg-primary font-medium text-white dark:bg-accent">${escapeHtml(btnLabel)}</a>`;
var durationHtml = item.duration !== undefined ? `<p class="text-xs text-slate-400 dark:text-navy-300">Duration: ${escapeHtml(item.duration)}s</p>` : '';
var limitHtml = item.limit !== undefined ? `<p class="text-xs text-slate-400 dark:text-navy-300">Limit: ${escapeHtml(item.available ?? 0)}/${escapeHtml(item.limit)}</p>` : '';
return `<div class="card border-l-4 border-primary p-4 rounded-xl flex flex-col gap-3">
<div class="flex items-start gap-3">
${imageHtml}
<div class="flex flex-col gap-1 min-w-0">
<h5 class="text-sm font-semibold text-slate-700 line-clamp-2 dark:text-navy-100">${escapeHtml(item.title)}</h5>
${durationHtml}
${limitHtml}
</div>
</div>
${item.description ? `<p class="text-xs text-slate-500 dark:text-navy-300 line-clamp-2">${escapeHtml(item.description)}</p>` : ''}
<div class="flex justify-between items-center mt-auto pt-2">
<span class="text-sm font-semibold text-primary dark:text-accent">${rewardHtml(item.reward)}</span>
${actionHtml}
</div></div>`;
}
function buildThirdPartyOfferCard(item, btnLabel) {
var imageHtml = item.image ? `<img src="${safeUrl(item.image)}" class="size-12 rounded-lg object-cover shrink-0" onerror="this.style.display='none'">` : '';
var displayTitle = item.title || item.name || 'Offer';
var displayRate = item.rate_note || rewardHtml(item.reward);
return `<div class="card border-l-4 border-primary p-4 rounded-xl flex flex-col gap-3">
<div class="flex items-start gap-3">
${imageHtml}
<h5 class="text-sm font-semibold text-slate-700 line-clamp-2 dark:text-navy-100">${escapeHtml(displayTitle)}</h5>
</div>
${item.description ? `<p class="text-xs text-slate-500 dark:text-navy-300 line-clamp-2">${escapeHtml(item.description)}</p>` : ''}
<div class="flex justify-between items-center mt-auto pt-2">
<span class="text-sm font-semibold text-primary dark:text-accent">${escapeHtml(displayRate)}</span>
<a href="${safeUrl(item.url)}" target="_blank" rel="noopener noreferrer" class="btn text-xs bg-primary font-medium text-white dark:bg-accent">${escapeHtml(btnLabel)}</a>
</div></div>`;
}
function fetchItems(url, containerId, onSuccess) {
$(containerId).html(loadingCardHtml());
$.ajax({
url: url, type: "GET", dataType: "json",
success: function(r) { if (r.success) { onSuccess(r.data); } else { $(containerId).html(`<p class="text-error text-center py-4">${escapeHtml(r.message)}</p>`); } },
error: function() { $(containerId).html("<p class='text-error text-center py-4'>Request failed</p>"); }
});
}
function renderPage(items, containerId, paginationId, btnClass, page, cardBuilder) {
var start = (page - 1) * ITEMS_PER_PAGE;
var pageItems = items.slice(start, start + ITEMS_PER_PAGE);
var total = Math.ceil(items.length / ITEMS_PER_PAGE);
if (!pageItems.length) {
$(containerId).html('<p class="text-slate-400 text-center py-6">No items available.</p>');
$(paginationId).html('');
return;
}
var grid = '<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-5 xl:grid-cols-3 lg:gap-6">';
pageItems.forEach(function(item) { grid += cardBuilder(item); });
grid += '</div>';
$(containerId).html(grid);
$(paginationId).html(buildPageHtml(page, total, btnClass));
}
// --- Core Loading Actions ---
function loadAoycoinTasks(type, url, containerId, paginationId, btnClass, label) {
if (aoyLoaded[type]) return;
fetchItems(url, containerId, function(data) {
aoyItems[type] = data; aoyLoaded[type] = true;
renderPage(aoyItems[type], containerId, paginationId, btnClass, 1, function(item) {
return type === 'offers' ? buildThirdPartyOfferCard(item, label) : buildOfferCard(item, label);
});
});
}
function handleAoyPagination(type, containerId, paginationId, btnClass, label, page) {
renderPage(aoyItems[type], containerId, paginationId, btnClass, page, function(item) {
return type === 'offers' ? buildThirdPartyOfferCard(item, label) : buildOfferCard(item, label);
});
}
// --- History Loader ---
function loadOfferwallHistory(page) {
page = page || 1;
$.ajax({
url: "/offerwall-history/" + offerwall, type: "GET", data: { page: page }, dataType: "json",
beforeSend: function() { $("#offerwall-history").html('<tr><td colspan="4" class="text-center py-4"><div class="w-full px-6 py-4"><div class="skeleton animate-wave h-3 w-full rounded bg-slate-150"></div></div></td></tr>'); },
success: function(data) {
var html = "";
if (data.records.length > 0) {
data.records.forEach(function(item) {
html += `<tr class="border-y border-b-slate-200 dark:border-b-navy-500">
<td class="whitespace-nowrap px-4 py-3 sm:px-5"><span class="badge bg-${item.status.color} text-white">${item.status.text}</span></td>
<td class="whitespace-nowrap px-4 py-3 sm:px-5">${escapeHtml(item.transaction)}</td>
<td class="whitespace-nowrap px-4 py-3 sm:px-5">${item.reward}</td>
<td class="whitespace-nowrap px-4 py-3 sm:px-5">${item.date}</td></tr>`;
});
} else { html = '<tr><td colspan="4" class="text-center py-4">No data available</td></tr>'; }
$("#offerwall-history").html(html);
$("#pagination").html(buildPageHtml(data.current_page, data.total_pages, 'pagination-btn'));
}
});
}
// --- Event Listeners ---
$("#loadPtcAds").click(function() { loadAoycoinTasks('ptc', '/get-aoycoin-ptc', '#ptc-result', '#ptc-ads-pagination', 'aoy-ptc-btn', 'Earn'); });
$("#loadShortlinks").click(function() { loadAoycoinTasks('shortlink', '/get-aoycoin-shortlink', '#shortlink-result', '#shortlink-ads-pagination', 'aoy-sl-btn', 'Claim'); });
$("#loadOffers").click(function() { loadAoycoinTasks('offers', '/get-aoycoin-offers', '#offers-result', '#offers-ads-pagination', 'aoy-offer-btn', 'Start'); });
// Initial Load
loadAoycoinTasks('ptc', '/get-aoycoin-ptc', '#ptc-result', '#ptc-ads-pagination', 'aoy-ptc-btn', 'Earn');
loadOfferwallHistory(1);
$(document).on('click', '.offer-goal-btn', function() {
var entry = offerGoalItems[$(this).data('goal-key')];
if (entry) openGoalModal(entry.item, entry.btnLabel);
});
$(document).on("click", ".aoy-ptc-btn", function(e) { e.preventDefault(); var p = $(this).data("page"); if (p) handleAoyPagination('ptc', '#ptc-result', '#ptc-ads-pagination', 'aoy-ptc-btn', 'Earn', parseInt(p)); });
$(document).on("click", ".aoy-sl-btn", function(e) { e.preventDefault(); var p = $(this).data("page"); if (p) handleAoyPagination('shortlink', '#shortlink-result', '#shortlink-ads-pagination', 'aoy-sl-btn', 'Claim', parseInt(p)); });
$(document).on("click", ".aoy-offer-btn", function(e) { e.preventDefault(); var p = $(this).data("page"); if (p) handleAoyPagination('offers', '#offers-result', '#offers-ads-pagination', 'aoy-offer-btn', 'Start', parseInt(p)); });
$(document).on("click", ".pagination-btn", function(e) { e.preventDefault(); var p = $(this).data("page"); if (p) loadOfferwallHistory(parseInt(p)); });
});
</script>
@endpush
</x-app-layout>
Update Front Service (Partner Display) FrontService.php
To display AoyCo.in as an official partner on your website's homepage, open the app/Services/Content/FrontService.php file and add it to the $offerwallProviders collection inside the index method.
$offerwallProviders = collect([
['name' => 'Bitcotasks', 'slug' => 'bitcotasks', 'status' => get_setting('bitcotasks_status') === 'on'],
['name' => 'AoyCo.in', 'slug' => 'aoycoin', 'status' => get_setting('aoycoin_status') === 'on'], // ⭐️ ADD THIS LINE
['name' => 'CPX Research', 'slug' => 'cpx', 'status' => get_setting('cpx_status') === 'on'],
// ...
])->where('status', true)->values();
S2S Postback & Security
Whenever a user completes an offer, we will make a call to the Postback URL that you indicated in your app, attaching all the information that you will need to credit your users. Our server will make an HTTP GET request.
| Parameter | Description | Example |
|---|---|---|
| subId | This is the unique identifier code of the user (your [USER_ID]). |
12345 |
| transId | Unique identification code of the transaction. | 3fe2905e... |
| offer_name | Name of the completed offer. | Register and Earn |
| offer_type | Type of the offer completed (e.g., ptc, shortlink). |
ptc |
| reward | Amount of your virtual currency to be credited. | 100.00 |
| reward_name | The name of your currency set in your app. | Points |
| payout | The offer payout in USD (the amount we pay you). | 0.100000 |
| status | 1 (valid credit) or 2 (chargeback / reversal). |
1 |
| userIp | The user's IP address who completed the action. | 192.168.1.0 |
| country | The user's 2-letter country code (ISO2). | US |
| reward_value | Amount of your virtual currency credited for $1 worth of payout (Exchange Rate). | 1000.00 |
| debug | Check if is a test or a live postback call. | 1 (test) / 0 (live) |
| signature | MD5 hash that can be used to verify the call. | 428aa4... |
Postback Security
You should verify the signature received in the postback to ensure that the call comes from our servers.
<?php
$secret = "YOUR_APP_SECRET_KEY"; // Get your secret key from the "My Apps" page on aoyco.in
// Use RAW parameters for signature check
$subId = isset($_REQUEST['subId']) ? $_REQUEST['subId'] : null;
$transId = isset($_REQUEST['transId']) ? $_REQUEST['transId'] : null;
$reward = isset($_REQUEST['reward']) ? $_REQUEST['reward'] : null;
$signature = isset($_REQUEST['signature']) ? $_REQUEST['signature'] : null;
// Validate Signature
if(md5($subId.$transId.$reward.$secret) != $signature)
{
echo "ERROR: Signature doesn't match";
return;
}
?>
Response Requirement
Our servers will expect your website to respond with ok (lowercase). If your postback script does not return exactly this, the postback will be marked as "Failed".
IPs to Whitelist
We will be sending the postbacks from our server IP. Please make sure it is whitelisted if needed.