Skip to content

Server to server redeem callbacks

pineglobal edited this page Dec 5, 2018 · 3 revisions

서버 간 보상 지급 콜백

사용자가 광고를 시청하면 서버에 서버 간 보상 지급 콜백이 전송됩니다. 이 콜백을 이용하여 플레이어에게 가상 재화를 보상으로 지급할 수 있으며, 치팅을 감지 및 방지하는 등의 기능으로도 활용 가능합니다.

참고: 기본값으로, 서버 간 보상 지급 콜백은 이용할 수 없는 상태로 설정됩니다. 게임에 서버 간 보상 지급 콜백을 활성화하려면 유니티 지원 팀에 문의해 주세요. 메시지에 게임 ID와 해당 콜백 URL을 넣어서 보내주시기 바랍니다. 그러면 유니티에서 콜백 서명 및 검증에 사용되는 비밀 해시를 보내드립니다.

플레이어가 동영상 시청을 완료하면 Unity Ads 서버는 서명된 콜백을 지정 URL로 전송합니다. 사용자가 게임으로 복귀하기 전에 보상 주기를 완료해야 하기 때문에, 이 과정은 동영상이 실제 종료되기 전에 이루어집니다. 광고 시청이 완료된 후에 보상 알림을 표시하십시오. 이는 동영상이 실제로 종료될 때까지 사용자에게 혼란을 주지 않기 위해서입니다.

트래픽에 따라, 콜백이 도착하기까지 약간의 시간이 걸릴 수 있습니다. 원활한 게임플레이를 보장하려면 플레이어에게 즉각적으로 보상을 제공하고 서버 간 콜백으로 온전성 검사를 수행하여 치팅을 방지해야 합니다.

서버 간 콜백을 사용하려면 광고를 표시하기 전에 서버 ID(sid)를 설정해야 합니다.

Unity 예제:

using UnityEngine;
using System.Collections;
using UnityEngine.Monetization;

public class UnityAdsManager : MonoBehaviour {
    public string gameId;
    public string placementId = "rewardedVideo"
    public bool testing = false;

    public void Awake (){
        Monetization.Initialize (gameId, testing);
    }

    // Call this method when a placement is ready
    public void ShowAd () {
        ShowAdPlacementContent ad = Monetization.GetPlacementContent (placementId) as ShowAdPlacementContent;
        ad.gamerSid = "example";
        ad.Show ();
    }
}

네이티브 Unity Ads SDK에서는 이 과정이 PlayerMetaData API 클래스를 이용해 수행됩니다.

Android 예제:

    if(UnityAds.isReady()) {
        PlayerMetaData playerMetaData = new PlayerMetaData(context);
        playerMetaData.setServerId("example");
        playerMetaData.commit();

        UnityAds.show(activity);
    }

iOS 예제:

    if([UnityAds isReady]) {
        id playerMetaData = [[UADSPlayerMetaData alloc] init];
        [playerMetaData setServerId:@"example"];
        [playerMetaData commit];

        [UnityAds show:self];
    }

콜백 출처

콜백은 https://static.applifier.com/public_ips.json에 기재된 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. 이를 구성하려면 unityads-support@unity3d.com에 문의하세요.
SEPARATOR1 & or ?: 아직 URL에 ?가 존재하지 않으면, ?가 사용되고 그렇지 않은 경우 &가 사용됩니다.
SID 사용자 ID 또는 엔드포인트에 전송할 모든 커스텀 데이터입니다. 위 예제들은 다양한 플랫폼에서의 서버 ID 설정을 설명한 것입니다. 예: 1234567890
SEPARATOR &
OID Unity Ads 서버에서 생성된 고유 상품 ID입니다. 예: 0987654321
SEPARATOR &
SIGNATURE 아래 설명대로 파라미터 문자열의 HDMAC-MD5 해시입니다. 예: 106ed4300f91145aff6378a355fced73

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

콜백 URL 서명

콜백 URL 요청에는 URL 파라미터에 서명이 첨부됩니다. 서명은 hmac를 제외하고 모든 URL 파라미터를 쉼표 구분한 알파벳순 key=value 형식으로 연결하여 만들어진 파라미터 문자열의 HDMAC-MD5 해시입니다.

예를 들어, https://developer.example.com/award.php?productid=1234&sid=1234567890&oid=0987654321의 SID 및 OID가 있는 콜백 URL은 비밀 해시 키 'xyzKEY'(유니티 지원 팀의 엔지니어가 콜백을 활성화할 때 비밀 해시를 받을 수 있습니다)로 해시된 파라미터 문자열 'oid=0987654321,productid=1234,sid=1234567890'을 가지며 ‘106ed4300f91145aff6378a355fced73‘의 해시를 제공합니다. 결과적으로 보상 콜백이 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 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
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";
?>
Clone this wiki locally