自社管理 仮想通貨は、ユーザーの仮想通貨の増減の処理をパブリッシャーの用意する自社サーバーで行うものです。この方法の場合、ユーザーの仮想通貨管理をより柔軟に行えますが、全ユーザーの仮想通貨管理と運用のバックエンド作業をアプリ開発者自身が行う必要があります。getCurrencyBalance、 awardCurrency、および spendCurrency は Tapjoy管理仮想通貨でしか使用できません。Tapjoyは自社管理仮想通貨に関してはクライアントサイド(アプリ側)への通知の仕組みは提供していません。Tapjoyから自社のサーバにコールバックが行われた際のアプリおよびユーザーへ通知を行う仕組みはパブリッシャ自身が面倒を見る必要があります。また、自社管理仮想通貨を使用するためにはコールバック用のサーバを用意する必要があります。
注: Tapjoyはユーザーへのリワードを可能な限り素早く付与しますが、ユーザーがすぐにリワードされる事は保証できません。ユーザーへリワードを行う時間に関わる要素が多く割るため、ユーザーへのリワードが行われる時間を決定する事は困難です。ベスト・プラクティスとしては、動画広告が閉じた後に仮想通貨残高をチェックするのに加え、定期的、および起動・レジューム・レベル完了・アプリ内ストアの表示前等のアプリイベントで残高を確認する事をお勧めします。また、ユーザーにオファーの完了までに時間がかかる場合がある旨を知らせておく事もお勧めします。
注: 自社管理通貨の場合でも、仮想通貨はプラットフォーム固有となります。
ユーザーが広告のアクションを完了して仮想通貨を獲得すると、TapjoyサーバーがHTTP(S) GETリクエストを送信します。 パラメーターのフォーマットは次のようになります:
<callback_url>?snuid=<user_id>¤cy=<currency>&mac_address=<mac_address>
//Example
http://www.sampledoman.com/payments/offers/tapjoy?&snuid=42&currency=50&mac_address=00-16-41-34-2C-A6
デフォルトのリクエストパラメータにはsnuid (setUserIDで指定したユーザーID)、currency(ユーザーのアカウントに追加する仮想通貨量)、および取得可能な場合ユーザーのWiFiのmac アドレスが含まれます。
Tapjoyサーバーは、アプリ開発者のサーバーから200または403レスポンスを受け取ります。
アプリ開発者のサーバーが200をレスポンスする場合:
アプリ開発者のサーバーが403をレスポンスする場合:
Tapjoyサーバーが200もしくは403以外のレスポンスコードを受け取った場合、Tapjoyは再送を試みます。(注: 200以外のレスポンスを返す場合には、ユーザーにリワードを付与しないようにして下さい。Tapjoyはコールバックを再送する場合があり、リワードが複数回行われてしまう場合があるからです)。再送は2分毎に4日間行います。また、サーバーからのレスポンスが5秒を超える場合にも失敗として取り扱います。
注: コールバックのレスポンスのbodyの内容はUTF-8である必要があります。UTF-8以外のエンコーディングの場合、レスポンスコードが200であっても再送する場合があります。
ダッシュボードの[マネタイズ]-[仮想通貨]-[Secret Key]-[作成/編集]から仮想通貨のSecret Keyを取得できます。 このキーは アプリのSDK Keyとは違うものです。この仮想通貨 Secret Key を使用してコールバックを署名します。
仮想通貨にSecret Keyが指定されている場合、Tapjoyからのコールバックに以下のパラメータを追加します:
verifierはID、snuid、仮想通貨および秘密鍵をコロンで区切った文字列のMD5ハッシュ値です。 Rubyでは、次のコードで計算できます:
Digest::MD5.hexdigest("#{id}:#{snuid}:#{currency}:#{secret_key}")
アプリ開発者のサーバーは、ベリファイアを再計算して一致しないリクエストを却下します。verifierが一致しない場合にはサーバーは403レスポンスを返すようにして下さい。
各アプリケーションは異なるSecret Keyを指定するようにして下さい。アプリケーション間で共通のSecret Keyを使用した場合、あるアプリケーションのユーザーに対するリワードが別のアプリケーションでのリワードに再利用される可能性があります。また、idパラメータが仮想通貨のIDではなくリワードに対するユニーク値だと言う事も留意して下さい。
上記のコールバックに、より多くの情報とセキュリティを追加して改善しました。この改良版のコールバックを使用したい場合は、アカウントマネージャーまたはサポートチームに連絡して、このバージョンを有効にするための支援を受けてください。
ユーザーがオファーを完了して通貨を獲得したとき、指定されたURLにPOSTリクエストを行います。パラメータの形式は以下のようになります。
{
"id": "reward.id",
“rev”: 100,
“cp”: ”your_custom_string”
"currency": {
"id": "currency_id",
"reward": "xxx",
"currency_sale": "",
},
"offer": {
"name": "Some offer",
“type”: “”,
“icon_url”: “offer_icon_url,
},
“placement”: {
“content_type”: “offerwall”,
“name”: “placement_name”
},
"user": {
"id": "pub_user_id"
},
“timestamp”: “123491324”
}
パラメータ | タイプ | 説明 |
---|---|---|
id | string | このリクエストの仮想通貨付与イベントに割り振られたユニークID |
rev | integer | 獲得した収益(USDセント単位) |
cp | string | setCustomParameterメソッドでSDKから渡されたカスタムパラメータ |
currency.id | string | この通貨のID |
currency.reward | integer | ユーザーに付与される通貨の量 |
currency.currency_sale | float | カレンシーセールの乗数(該当する場合) |
offer.name | string | 広告主のオファー名 |
offer.type | 現時点ではサポートされていません | |
offer.icon_url | string | オファーのアイコンURL |
placement.name | string | このコンバージョンに使用したプレイスメント名 |
placement.content_type | string | 使用されたプレイスメントの種類 |
user.id | string | setUserIDメソッドを通じてSDKから渡されたユーザーID |
timestamp | timestamp | このトランザクションのタイムスタンプ |
JSON本文はSHA256ハッシュアルゴリズムを使用してハッシュ化されます。verifierはPOST通貨コールバックリクエストの本文と、共有シークレットキー(TapjoyダッシュボードでコールバックURLと共に表示されています)から生成されます。 このverifierはPOST通貨コールバックリクエストのヘッダーに送信されます。
HMAC_SHA-256(<Request-Body>,<Secret-Key>)
verifierのシグネチャを含むTapjoyヘッダの例:
X-Tapjoy-Signature => 7205ccfdfa1fe28cd05a1b56a9508d898cc938aa555a6c18848097fe4ee0975b
自社管理仮想通貨を使用する場合、User ID を指定する事は非常に重要です。この値はコールバックURLで snuid
パラメータの値として設定されます。User ID の指定にはコンテンツをリクエストする前の、SDK初期化時のconnect flagを使用する事をおすすめします。
正しく設定されなかった場合、ユーザーはリワードを得られないでしょうし、レベニューが発生しない場合もあります。User IDの値はユーザーを特定できる一意のID (通常は数値) である必要があります。
セキュリティ上、およびGDPR準拠の観点から、setUerIDのパラメータの値にユーザー名、氏名、メールアドレス等の認識・識別可能な情報を使うべきではありません。 セキュリティおよび不正検知の観点から、ユーザーIDはユーザーのアプリプラットフォーム上での利用期間全般において同じ値が使われるようにするべきです。(例えば、レベルやスコア等の変化する値を付加する事は行わないで下さい)
User ID は最大190文字までです。
以下のコードサンプルは connect flagを使う方法、および必要がある場合(connectの後に)setUserID
APIを直接呼び出す例です。APIを直接呼び出す場合にはUser IDが設定されたかを確認するためにコールバックを利用してください。可能な限り、connect flag を使う方法を強くおすすめします。
// connect flag でUser IDを指定する(推奨)
NSDictionary *connectFlags = @{TJC_OPTION_USER_ID : @"<USER_ID_HERE>"};
[Tapjoy connect:@"SDK_KEY_GOES_HERE" options:connectFlags];
// User IDを直接指定する
[Tapjoy setUserIDWithCompletion:@"<USER_ID_HERE>" completion:^(BOOL success, NSError *error) {
}];
// connect flag でUser IDを指定する(推奨)
Hashtable<String, Object> connectFlags = new Hashtable<String, Object>();
connectFlags.put(TapjoyConnectFlag.USER_ID, "<USER_ID_HERE>"); // Important for self-managed currency
Tapjoy.connect(getApplicationContext(), "SDK_KEY_GOES_HERE", connectFlags, new TJConnectListener() {...});
// User IDを直接指定する
Tapjoy.setUserID("<USER_ID_HERE>", new TJSetUserIDListener() {
@Override
public void onSetUserIDSuccess() {
}
@Override
public void onSetUserIDFailure(String error) {
}
});
// connect flag でUser IDを指定する(推奨)
Dictionary<string,string> connectFlags = new Dictionary<string,string>();
connectFlags.Add("TJC_OPTION_USER_ID", "<USER_ID_HERE>");
#if UNITY_ANDROID
Tapjoy.Connect("your_android_sdk_key", connectFlags);
#elif UNITY_IOS
Tapjoy.Connect("your_ios_sdk_key", connectFlags);
#endif
// Callbacks for SetUserID
TJPlacement.OnSetUserIDSuccess += HandleOnSetUserIDSuccess;
TJPlacement.OnSetUserIDFailure += HandleOnSetUserIDFailure;
// SUser IDを直接指定する
Tapjoy.SetUserID("<USER_ID_HERE>")
// connect flag を使用する方法(推奨)
try {
let flags: object = { TJC_OPTION_USER_ID: '<userId>' };
await Tapjoy.connect('<sdk_key>', flags);
} catch (error) {
console.log(error);
}
// User IDを直接指定する
try {
await Tapjoy.setUserId('<userId>');
} catch (error) {
console.log(error);
}
詳細な例はクイックスタートのページ(iOS、 Android、 Unity) および React Native もご参照ください。
トラブルシュート: コールバックURLのsnuidの値がsetUserIDでセットしたユーザIDと異なる場合は、setUserIDをTapjoy広告をリクエストする前に呼び出すようにしてください。端末にひもづいたUser IDが見つからない場合、TapjoyはTapjoy内部で使用している端末のユニークIDをコールバックのsnuidパラメータに指定して送ります。こうした事態を避けるためにアプリ起動毎にTapjoyコネクトコールが呼び出され、成功の直後にsetUserIDが確実に呼び出されるような実装をお勧めします。
User IDを設定していなかった場合、Tapjoy システムは使用可能な代替デバイスIDを使用します。多くの場合これは広告IDとなりますが、SDKのバージョンやデバイス種別・バージョン、OSバージョン、Google Play Servicesのバージョン等により実際に使用されるIDは異なります。Tapjoy内部で使用されるudidやmac_addressから構成される場合もあります。
プレイスメントをリクエストするたびに、Tapjoyへユーザーの現在の残高を送信できます。これはプレイスメントのコンテンツをリクエストする前に行う必要があります。
TJPlacement *placement = [TJPlacement placementWithName:@"placementName" delegate:nil];
[placement setBalance:100 forCurrencyId:@"1234" withCompletion:^(NSError * _Nullable error) {
if (error != nil) {
//Failure
NSString *message = error.localizedDescription;
} else {
//Success
}
}];
TJPlacement placement = Tapjoy.getPlacement("placement", this);
placement.setCurrencyBalance("1234", 100, new TJSetCurrencyBalanceListener() {
@Override
public void onSetCurrencyBalanceSuccess() {
}
@Override
public void onSetCurrencyBalanceFailure(int code, String error) {
}
});
TJPlacement placement = TJPlacement.CreatePlacement("placementName");
placement.SetCurrencyBalance("[CURRENCY_ID]", 100);
// Optional callbacks
void OnEnable()
{
TJPlacement.OnSetCurrencyBalanceSuccess += HandleSetCurrencyBalanceSuccess;
TJPlacement.OnSetCurrencyBalanceFailure += HandleSetCurrencyBalanceFailure;
}
void OnDisable()
{
TJPlacement.OnSetCurrencyBalanceSuccess -= HandleSetCurrencyBalanceSuccess;
TJPlacement.OnSetCurrencyBalanceFailure -= HandleSetCurrencyBalanceFailure;
}
public void HandleSetCurrencyBalanceSuccess(TJPlacement placement)
{
}
public void HandleSetCurrencyBalanceFailure(TJPlacement placement, int code, string error)
{
}
let placement = new TJPlacement('placementName');
try {
await placement?.setCurrencyBalance('1234', 100);
} catch (e: any) {
let code = e.code;
let message = e.message;
}
残高を設定する場合、必要な仮想通貨の量もプレイスメントに設定できます。
TJPlacement* placement = [TJPlacement placementWithName:@"placementName" delegate:nil];
placement setRequiredAmount:100 forCurrencyId:@"1234" withCompletion:^(NSError * _Nullable error) {
if (error != nil) {
//Failure
NSString *message = error.localizedDescription;
} else {
//Success
}
}
TJPlacement placement = Tapjoy.getPlacement("placement", this);
placement.setCurrencyAmountRequired("1234", 100, new TJSetCurrencyAmountRequiredListener() {
@Override
public void onSetCurrencyAmountRequiredSuccess() {
}
@Override
public void onSetCurrencyAmountRequiredFailure(int code, String error) {
}
});
TJPlacement placement = TJPlacement.CreatePlacement("placementName");
placement.SetRequiredAmount("[CURRENCY_ID]", 200);
// Optional callbacks
void OnEnable()
{
TJPlacement.OnSetCurrencyAmountRequiredSuccess += HandleSetRequiredAmountSuccess;
TJPlacement.OnSetCurrencyAmountRequiredFailure += HandleSetRequiredAmountFailure;}
void OnDisable()
{
TJPlacement.OnSetCurrencyAmountRequiredSuccess -= HandleSetRequiredAmountSuccess;
TJPlacement.OnSetCurrencyAmountRequiredFailure -= HandleSetRequiredAmountFailure;
}
public void HandleSetCurrencyBalanceSuccess(TJPlacement placement)
{
}
public void HandleSetCurrencyBalanceFailure(TJPlacement placement, int code, string error)
{
}
public void HandleSetRequiredAmountSuccess(TJPlacement placement)
{
}
public void HandleSetRequiredAmountFailure(TJPlacement placement, int code, string error)
{
}
let placement = new TJPlacement('placementName');
try {
await offerwallPlacement?.setRequiredAmount(100, '100');
} catch (e: any) {
let code = e.code;
let message = e.message;
}
リワードコールバックの送信IPアドレスをサーバで制限する必要がある場合は、英語版の "Reward Callback IP Whitelisting"に記載されているIPアドレスをご参照下さい。
まだアプリをローンチしていない場合、TapjoyダッシュボードからTapjoy管理の仮想通貨を自社管理の仮想通貨へ仮想通貨の編集画面で行えます。callback URLフィールドに正しい形式の自社サーバのURL(もしくは "NO_CALLBACK")を指定して下さい。異常な形式の場合、設定が保存されません。
流通している既存アプリでTapjoy管理の仮想通貨を使用している場合、切り替えはより複雑になります。 以下の状況を考える必要があります:
ユーザーの仮想通貨残高を移行するには、以下の手順をおすすめします:
仮想通貨の自社管理を検討している方は Parse や UrbanAirship を利用したソリューションも検討ください。