文档

支持

实现服务器到服务器兑换回调

Set up server-to-server callbacks to securely validate rewarded ad completions to help prevent fraud and ensure accurate reward distribution.
阅读时间5 分钟

奖励玩家时可使用服务器到服务器 (S2S) 回调来检测和防止作弊。

工作原理

当玩家完整观看视频广告时,Unity 广告服务器会向您指定的 URL 发送已签名的回调。这个过程发生在视频实际结束之前,因此可以在玩家返回游戏之前完成奖励循环。
S2S redeem callback process

实现

要使用 S2S 回调,您需要在展示广告之前设置服务器 ID (sid)。默认情况下,S2S 兑换回调不可用。如果您需要为项目启用这些回调,请联系支持团队,并在消息中提供您的 Game ID(游戏 ID)及其各自的回调 URL。Unity 将向您发送用于签名和验证回调的密钥哈希值。
要在 C# 代码中实现回调,请将
ShowOptions.gamerSid
值设置为您的服务器 ID,然后通过
Show
方法传递 options 对象。
using UnityEngine;
using System.Collections;
using UnityEngine.Advertisements;

public class UnityAdsManager : MonoBehaviour
{
    public string gameId;
    public string placement = "rewardedVideo"

    public void ShowAd() {

        ShowOptions options = new ShowOptions();

        // setting the server ID
        options.gamerSid = "your-side-id";

        Advertisement.Show(placementID, options);
    }
}

回调信息

回调来源

回调将来自于此处列出的 IP 地址/网络。该列表将在每个月的第一天更新。发行商可以放心忽略或阻止来自任何其他地方的回调。

回调 URL 格式

该请求是对以下格式的 URL 的 HTTP/1.1
GET
请求:
[CALLBACK_URL][SEPARATOR1]sid=[SID][SEPARATOR]oid=[OID][SEPARATOR]hmac=[SIGNATURE]
有关 query 参数的信息,请参阅下表:

参数

内容

CALLBACK_URL
回调 URL 的基 URL,例如:
https://developer.example.com/award.php?productid=1234
。 要配置此参数,请联系支持团队
SEPARATOR1
如果 URL 中不存在
?
,请使用
?
。否则,使用
&
SID
用户 ID 或要发送到终端的任何自定义数据。
SEPARATOR
&
OID
Unity Ads 服务器生成的唯一 Offer ID(优惠 ID)。
SEPARATOR
&
SIGNATURE
参数字符串的 HDMAC-MD5 哈希值 例如:
106ed4300f91145aff6378a355fced73
回调 URL 示例
https://developer.example.com/award.php?productid=1234&sid=1234567890&oid=0987654321&hmac=106ed4300f91145aff6378a355fced73

回调 URL 的签名

回调 URL 请求会将一个签名附加到 URL 参数。该签名是通过以键值形式连接所有 URL 参数(HMAC 除外,按字母顺序排列并以逗号分隔)创建的参数字符串的 HDMAC-MD5 哈希值。 例如,一个包含 SID 和 OID 的回调 URL
https://developer.example.com/award.php?productid=1234&sid=1234567890&oid=0987654321
将具有以下参数字符串:
oid=0987654321,productid=1234,sid=1234567890
此字符串与您即将从支持团队收到的密钥进行哈希处理后,返回一个由奖励回调触发为 URL 的哈希值。例如:
https://developer.example.com/award.php?productid=1234&sid=1234567890&oid=0987654321&hmac=106ed4300f91145aff6378a355fced73

回调响应

如果该请求通过了所有检查并且用户获得了奖励物品,则 URL 必须以
HTTP/1.1 200 OK
响应作为应答并在 HTTP 请求的正文中包含字符
1
。例如:
回调响应示例
HTTP/1.1 200 OK
Date: Wed, 22 Feb 2012 23:59:59 GMT
Content-Length: 8

1
如果出现错误(例如,OID 已被使用,或签名不匹配,或者当用户未能获得承诺物品时的任何其他错误),服务器应返回
400
500
范围内的 HTTP 错误,并显示人类可读的错误。例如:
回调错误响应示例
HTTP/1.1 400 ERROR
Date: Wed, 22 Feb 2012 23:59:59 GMT
Content-Length: 12

Duplicate order

node.js 中的回调示例

以下示例演示了如何使用 node.js + express 来验证签名: node.js 中的回调示例
// 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)
  }
})

PHP 中的回调示例

以下示例演示了如何在 PHP 中验证签名: 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";
?>

实现服务器到服务器兑换回调 • Unity Grow • Unity Docs