서버 간 보상 지급 콜백 구현

플레이어에게 보상을 지급할 때 S2S(서버 간) 콜백을 사용하여 부정 행위를 감지 및 방지할 수 있습니다.

자세히 알아보기

플레이어가 동영상 광고를 끝까지 보면 Unity Ads 서버는 서명된 콜백을 지정한 URL로 전송합니다. 플레이어가 게임으로 복귀하기 전에 게임에서 보상 주기를 완료할 수 있도록 이 과정은 동영상이 실제 종료되기 전에 이루어집니다.

: 트래픽에 따라, 콜백이 도착하기까지 약간의 시간이 걸릴 수 있습니다. 원활한 게임플레이를 보장하려면 플레이어에게 즉각적으로 보상을 제공한 후 S2S 콜백으로 온전성 검사를 수행하여 부정 행위를 방지해야 합니다. 동영상이 끝날 때까지 플레이어를 방해하지 않도록 광고 시청이 끝난 후에 보상 알림을 표시합니다.

구현

S2S 콜백을 사용하려면 광고를 표시하기 전에 서버 ID(sid)를 설정해야 합니다. 기본값으로, S2S 보상 지급 콜백은 이용할 수 없는 상태로 설정됩니다. 게임에서 이를 활성화하려는 경우 메시지에 게임 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);
    }
}

Android 예제

Java 코드에 콜백을 구현하려면 PlayerMetaData.setServerId 값을 서버 ID로 설정합니다.

PlayerMetaData playerMetaData = new PlayerMetaData(context);
        playerMetaData.setServerId("example");
        playerMetaData.commit();
 
        UnityAds.show(activity);

iOS 예제

Objective-C 코드에 콜백을 구현하려면 playerMetaData.setServerId 값을 서버 ID로 설정합니다.

id playerMetaData = [[UADSPlayerMetaData alloc] init];
        [playerMetaData setServerId:@"example"];
        [playerMetaData commit];
 
        [UnityAds show:self
          placementId: placementId
   	      showDelegate: showDelegate];

콜백 정보

콜백 출처

콜백은 여기에 기재된 IP 주소/네트워크에서 발생합니다. 이 목록은 매월 초에 업데이트될 것입니다. 퍼블리셔는 여기에 기재되지 않은 출처로부터 발생하는 모든 콜백을 안전하게 차단하거나 무시할 수 있습니다.

콜백 URL 포맷

다음 포맷의 URL에 대한 HTTP/1.1 GET 요청입니다.

[CALLBACK_URL][SEPARATOR1]sid=[SID][SEPARATOR]oid=[OID][SEPARATOR]hmac=[SIGNATURE]

쿼리 파라미터에 대한 자세한 내용은 다음 표를 참고하십시오.

파라미터

콘텐츠

CALLBACK_URL

콜백의 기본 URL이며 예를 들면 다음과 같습니다.

https://developer.example.com/award.php?productid=1234.

이를 구성하려면 지원 부서에 문의하십시오.

SEPARATOR1

?가 아직 URL에 없으면 ?를 사용합니다. 이외에는 &가 사용됩니다.

SID

사용자 ID 또는 엔드포인트에 전송할 모든 커스텀 데이터입니다.

SEPARATOR&
OID

Unity Ads 서버에서 생성된 고유의 Offer ID입니다.

SEPARATOR&
SIGNATURE

파라미터 문자열의 HDMAC-MD5 해시입니다.

예를 들면 다음과 같습니다. 106ed4300f91145aff6378a355fced73

콜백 URL 예제

https://developer.example.com/award.php?productid=1234&sid=1234567890&oid=0987654321&hmac=106ed4300f91145aff6378a355fced73

콜백 URL 서명

콜백 URL 요청에는 URL 파라미터에 서명(Signature)이 첨부됩니다. 서명은 HMAC를 제외하고 모든 URL 파라미터를 쉼표 구분한 알파벳순 키-값 형식으로 연결하여 만들어진 파라미터 문자열의 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에 포함된 모든 파라미터는 서명 계산에 알파벳순으로 포함되어야 합니다. 그렇지 않으면 서명이 일치하지 않습니다.

콜백 응답

요청이 모든 점검 사항을 통과하고 사용자에게 아이템 보상이 주어지면, URL은 HTTP 요청의 본문에 문자 1을 넣어서 HTTP/1.1 200 OK 응답으로 회신해야 합니다. 예를 들면 다음과 같습니다.

콜백 응답 예제

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";
?>