s2s redeem callbacks - Unity-Technologies/unity-ads GitHub Wiki
/*
Title: Server-to-server redeem callbacks
Sort: 10
*/
Server-to-server callbacks are sent to your server when a user has watched an ad. You can use these callbacks to reward players with virtual goods and to e.g. detect and prevent cheating.
Note: By default the server-to-server redeem callbacks are not available. If you want to enable them for your game, please contact our support. Provide your game ID(s) and their respective callback URL(s) in the message. Then we'll send you a secret hash used to sign and validate the callbacks.
After your player has completed the video view, the Unity Ads server will send a signed callback to the URL you've specified. This is done before the actual end of the video, so that the awarding cycle can be completed before user comes back to the game. Show the reward notification after the ad view is finished. This is to avoid any distraction for the user until the video has actually ended.
Depending on the traffic, it can take some time for the callbacks to arrive. To ensure a smooth gameplay experience, reward the players immediately and use the S2S callbacks for sanity checks against cheating.
To use S2S callbacks, you need to set server ID (sid) before showing an ad.
Unity example:
using UnityEngine;
using System.Collections;
using UnityEngine.Advertisements;
public class UnityAdsManager : MonoBehaviour
{
public string gameId;
public string placement = "rewardedVideo"
// Call this function when Advertisement.IsReady == true.
public void ShowAd() {
ShowOptions options = new ShowOptions();
// setting the server ID
options.gamerSid = "your-side-id";
Advertisement.Show(placementID, options);
}
}
In the native Unity Ads SDKs, this is done with PlayerMetaData
API class.
Android example:
if(UnityAds.isReady()) {
PlayerMetaData playerMetaData = new PlayerMetaData(context);
playerMetaData.setServerId("example");
playerMetaData.commit();
UnityAds.show(activity);
}
iOS example:
if([UnityAds isReady]) {
id playerMetaData = [[UADSPlayerMetaData alloc] init];
[playerMetaData setServerId:@"example"];
[playerMetaData commit];
[UnityAds show:self];
}
The callback will come from the IP addresses/networks listed in https://static.applifier.com/public_ips.json. The list will be updated on the first of each month. Publisher can safely ignore or block callbacks from everywhere else.
The request is a HTTP/1.1 GET
request to an URL of the following format:
[CALLBACK_URL][SEPARATOR1]sid=[SID][SEPARATOR]oid=[OID][SEPARATOR]hmac=[SIGNATURE]
where the parameters and the contents can be explained as follows.
Parameter | Content |
---|---|
CALLBACK_URL | The base URL of the callback URL, for example: https://developer.example.com/award.php?productid=1234 . To configure this, contact [email protected]
|
SEPARATOR1 |
& or ? : If ? does not exist in the URL yet, ? is used, otherwise & is used. |
SID | the User ID or any custom data you want to send to your endpoint. Above examples illustrate setting the Server ID on different platforms. For example 1234567890
|
SEPARATOR | & |
OID | The unique Offer ID generated by Unity Ads servers, for example 0987654321
|
SEPARATOR | & |
SIGNATURE | a HDMAC-MD5 hash of a parameter string, as described below, for example 106ed4300f91145aff6378a355fced73
|
The Callback URL request will have a signature attached to the URL parameters. The signature is a HDMAC-MD5 hash of a parameter string created by concatenating the all the URL parameters in key=value form except the hmac in alphabetical order separated by commas.
For example, a callback URL with SID and OID of https://developer.example.com/award.php?productid=1234&sid=1234567890&oid=0987654321
will have a parameter string βoid=0987654321,productid=1234,sid=1234567890
β which hashed with the secret hash key βxyzKEY
β (you'll get the secret hash from one of our support engineers when they enable the callbacks for you) gives a hash of β106ed4300f91145aff6378a355fced73
β. As the result, the award callback will be fired to a URL:
https://developer.example.com/award.php?productid=1234&sid=1234567890&oid=0987654321&hmac=106ed4300f91145aff6378a355fced73
Note: All the parameters included in the callback url must be included in the signature calculation in alphabetical order. Otherwise the signatures will not match.
If the request passes all the checks and user was awarded the item, the URL must reply with a HTTP/1.1 200 OK and include character β1
β³ in the body of the HTTP request:
HTTP/1.1 200 OK
Date: Wed, 22 Feb 2012 23:59:59 GMT
Content-Length: 8
1
If thereβs an error, the server should return an HTTP error in the 400- or the 500-range with a human readable error (for example, when the OID has already been used, or signature does not match, or any other error when user does not end up having the promised item):
HTTP/1.1 400 ERROR
Date: Wed, 22 Feb 2012 23:59:59 GMT
Content-Length: 12
Duplicate order
The following example shows how to verify the signature using node.js
+ express:
// NODE.js S2S callback endpoint sample implementation
// Unity Ads
var express = require('express');
var crypto = require('crypto')
var app = express();
app.listen(process.env.PORT || 3412);
function getHMAC(parameters, secret) {
var sortedParameterString = sortParams(parameters);
return crypto.createHmac('md5', secret).update(sortedParameterString).digest('hex');
}
function sortParams(parameters) {
var params = parameters || {};
return Object.keys(params)
.filter(key => key !== 'hmac')
.sort()
.map(key => params[key] === null ? `${key}=` : `${key}=${params[key]}`)
.join(',');
}
app.get('/', function (req, res) {
var sid = req.query.sid;
var oid = req.query.oid;
var hmac = req.query.hmac;
// Save the secret as an environment variable. If none is set, default to xyzKEY
var secret = process.env.UNITYADSSECRET || 'xyzKEY';
var newHmac = getHMAC(req.query, secret);
if (hmac === newHmac) {
// Signatures match
// Check for duplicate oid here (player already received reward) and return 403 if it exists
// If there's no duplicate - give virtual goods to player. Return 500 if it fails.
// Save the oid for duplicate checking. Return 500 if it fails.
// Callback passed, return 200 and include '1' in the message body
res.status(200).send('1');
} else {
// no match
res.sendStatus(403);
}
});
The following example shows how to verify the signature in PHP:
<?php
function generate_hash($params, $secret) {
ksort($params); // All parameters are always checked in alphabetical order
$s = '';
foreach ($params as $key => $value) {
$s .= "$key=$value,";
}
$s = substr($s, 0, -1);
$hash = hash_hmac('md5', $s, $secret);
return $hash;
}
$hash = $_GET['hmac'];
unset($_GET['hmac']);
$signature = generate_hash($_GET, 'xyzKEY'); // insert here the secret hash key you received from Unity Ads support
error_log("req hmac".$hash);
error_log("sig hmac".$signature);
// check signature
if($hash != $signature) { header('HTTP/1.1 403 Forbidden'); echo "Signature did not match"; exit; }
// check duplicate orders
if(check_duplicate_orders($_GET['oid']) { header('HTTP/1.1 403 Forbidden'); echo "Duplicate order"; exit; }
// if not then give the player the item and check that it succeeds.
if(!give_item_to_player($_GET['sid'], $_GET['product']) { header('HTTP/1.1 500 Internal Server Error'); echo "Failed to give item to the player"; exit; }
// save the order ID for duplicate checking
if(save_order_number($_GET['oid']) { header('HTTP/1.1 500 Internal Server Error'); echo "Order ID saving failed, user granted item"; exit; }
// everything OK, return "1"
header('HTTP/1.1 200 OK');
echo "1";
?>