서버 간 보상 지급 콜백 구현

Read time 8 minutes

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

자세히 알아보기

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

S2S redeem callback process

구현

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