You are viewing an old version of this page. View the current version.
Compare with Current
View Page History
« Previous
Version 13
本文書は開発者向けドキュメントです。
ユーザーがBuzzvilプロダクトを通じてリワードポイントの付与を受けるには、Buzzvilとパブリッシャー間でポイントシステムの連携が必要です(S2S接続)。本ドキュメントにはポイント付与を実現するためのサーバー連携に関する技術情報を記載しています。
自社ポイントシステムと連携方法の選択
自社ポイントシステムを持っているかどうかによって連携方法が異なります。
自社でポイントシステムを持っている場合
下記の手順で連携を行います。
Buzzvilからのポイント付与リクエストを受け取れるサーバーエンドポイントを構築(該当のエンドポイントのURLのを"postback url"とする)
本ガイドに従ってServer-To-Sever連携を行う
Buzzvil担当者にpostback urlを伝える
自社でポイントシステムを持っていない場合
アプリ内にBuzzvilのポイントシステム(BuzzStore) を連携します。詳しくはBuzzvil担当者までお問い合わせください。
Index
イントロダクション
このAPIはBuzzScreen SDK, BuzzAd SDKを通じてユーザーがリワードポイントの付与を受ける場合において、パブリッシャーにこの事実を伝達し、ポイント付与リクエストを送信するためのものです。
| 項目 | 内容 |
---|
1 | 送信方向 | Buzzvil → パブリッシャー |
2 | HTTP Request method | POST - application/x-www-form-urlencoded |
3 | HTTP Request URL | パブリッシャー側で定義 |
4 | HTTP Request Parameters | 下記の表を参照 |
5 | HTTP Response Code | パブリッシャー側から受けた応答コードによって該当のPostbackリクエストの成功可否を決定 |
HTTP Request Parameters(リクエストパラメータ)
ポイント付与Postbackはポイントを付与する状況によって下記の2タイプに分けられて転送されます。各タイプ別のフィールド値は下記の表を参照してください。
フィールド | 対応 | 説明 |
---|
user_id
必須 | String (max 255) | パブリッシャー側で定義したユーザー識別子 |
transaction_id
必須 | String (max 32) | ポイント重複付与を防ぐためのid |
point
必須 | Integer | ユーザーに付与されるポイントの合計 |
unit_id
必須 | Long | 広告枠を区分するID値 |
title
必須 | String (max 255) | ポイントが付与された方式に設定された名前 広告 (参加した広告のキャンペーン名) その他はすべて空の値になる
|
action_type
必須 | String (max 32) | ポイントの付与を受けるためにユーザーが行ったアクション |
event_at
必須 | Long (timestamp) | ポイント付与時点 (UNIX Timestamp 秒単位)
通常はAPI呼び出し時点と同一ですが、再試行の場合は異なることがあります。
|
extra
必須 | String (max 1024) | パラメータを追加した場合、json serializeされた文字列を表示 |
data
オプション | String | HTTP request parameterを暗号化して転送する場合に使用するパラメータ |
リクエストパラメータの検証 オプション
1. HTTP Request Parameterの暗号化と復号
Postbackの際、Buzzvilサーバーからパブリッシャーのサーバーにパラメータを送信します。このパラメータの暗号化を希望する場合は下記の手順で行います。なお、この設定は任意
であり、必須ではありません。
提供可能な暗号化方式は暗号化の標準であるAES(Advanded Encryption Standard)です。提供されるブロック暗号化はAES-256
で、ブロック暗号化モード(Block Cipher)はCBC(Cipher Block Chaning) Modeと PKCS7を使用します。
暗号化の手順
手順
暗号化キーの発行
Buzzvil担当者との事前協議
Buzzvil担当者に暗号化キー(AES key, IV 値)の発行を依頼する
Buzzvil serverにて下記順序でパラメータを暗号化
JSON serialized parameters with UTF-8 encoding
AES(CBC mode, PKCS7 padding) encryption
base64 encoding
HTTP POST requestにdata
パラメータを追加した状態で暗号化されたデータを送信
受信側(パブリッシャー)は HTTP POST requestにてdata
パラメータを取得し、下記順序で復号する
base64 decoding
AES decoding
JSON load
暗号化と復号化の例
{
"event_at": 1442984268,
"user_id": "testuserid76301",
"action_type": "u",
"extra": "{}",
"is_media": 0,
"base_point": 2,
"point": 2,
"campaign_name": "test campaign",
"campaign_id": 3467,
"transaction_id": 429482977
}
暗号化の結果
復号するには
base64 decoding)
\xb2\x07\xc78.Y\xeb\xabK\x9aZ$\x99\x01\x1a]\x8d\xfd\xbb\xee\xb8\x80\xc5\xa1.|P\x01\x9fb\xbd\x8b\x13\xbc]b\xb25_i\x1cv\x04\xd8N\x00<\x0fG\xa2\x81\xe7\x9f\xfb\x17\xb8\x97\x06nE)O&\x1ea\xe7\x95\x1d\xf0J\x89\x95\x02W#\xb7\x1e\xfb*[\xa8b\x85\xe2\xfe4B\xbd\xa1K\x18\x8a;\xbd\xc2\xb5\x19Q\xf1K\x9e{\xbb\xf5\xd3\xa3\x9d\xff\x037Of\x99?iy/\x15\x9b\xd6>\x04\xbe\x19h\xf5Mi^\xd2`I\xd3\x13\xa0~f\xfc/\x03\x1f\x8b\x8a\xef}\xac\x93\xa6\x1d\xdbe\xea\xf2.\xeaa\xa2\xb0s2\x82!\x7f\xe9\x10/(\xdf#*.YZ\x02\x87\xa5\x08\t\xe4A\x834\xd2\xf5)`u@:3S\xd5\x94+\x10r\x1d3)W\x93%\x91\x05\x12\x7f8\xef\xc4\x1b\xa4A!\x80p\xe1^L\xdd\xa3\xcbW\x82L
AES decryption) Key, IV: 12341234asdfasdf
{"event_at": 1442984268, "user_id": "testuserid76301", "action_type": "u", "extra": "{}", "is_media": 0, "base_point": 2, "point": 2, "campaign_name": "test campaign", "campaign_id": 3467, "transaction_id": 429482977}
UTF-8 decoding
{"event_at": 1442984268, "user_id": "testuserid76301", "action_type": "u", "extra": "{}", "is_media": 0, "base_point": 2, "point": 2, "campaign_name": "test campaign", "campaign_id": 3467, "transaction_id": 429482977}
(memo) 上の例では日本語文字が含まれていないためUTF-8 decoding を行わなくても同じ結果が得られます
開発言語別のコード例は下記のとおりです。
Java 1.8+
import java.lang.RuntimeException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.*;
import javax.crypto.spec.SecretKeySpec;
public class Main {
public static void main(String[] args) {
String aesKey = "BuzzvilAESKeyTest123456789101112";
String aesIV = "0000000000000000";
// Check to make sure encryption is compatible with Buzzvil
String toBuzzvilMessage = "{\"success\": 1, \"reason\": \"중복 적립 요청\"}";
String encrypted = encrypt(toBuzzvilMessage, aesKey, aesIV);
System.out.println("----encrypted----\n"+encrypted);
System.out.println("buzzvil encryption compatible? YES");
// Check to make sure values coming from Buzzvil is decryptable
String fromBuzzvilEncrypted = "IGCdundUBkXf3s7VXl0pqIKDSC/KGc2j8n1DBLKLZAHqkYlG+aWW+G5hGLvoNeUjlI42FtJLpwGUYbFlhy0QXLQv1Z+P7iUOyJrhujmFWX1FdJ5ZBefA5aceGiOlN119NPAX3JOuUAf45HkWG52NcdaHOzWu8rTnghSeLPo9QK0t6l/2gSFvGtOfZolnAHNZAeGEmcqAkhPmUoFtRAW+Zh6TNQY68FrSUI/XYc87Ky0ndaug1Kf7Ogbf8zLK+tJ4LdTCn9A+wcWxEpdkX45f1r/8jTIUK/s1PqBirXFuruq5/XhkhFmdq/I0qBAJ0uxBnk+29GaEQVMtYTzB+eJWTgrQzKhN6Nww2XEPEOl27yH+K0F+sj8QpZ0jkPETadP0gpwKMKv3zlA6xyndIYWrpw==";
String fromBuzzvilDecrypted = "{\"point\": 1, \"user_id\": \"buzzvil_test\", \"transaction_id\": \"100004_100000000\", \"event_at\": 1588936508, \"campaign_name\": \"버즈빌 테스트 campaign_name\", \"extra\": \"{}\", \"action_type\": \"l\", \"base_point\": 1, \"campaign_id\": 202010160022, \"is_media\": 1, \"unit_id\": 452613281179508, \"revenue_type\": \"cpm\"}";
String decrypted = decrypt(fromBuzzvilEncrypted, aesKey, aesIV);
System.out.println("----decrypted-----\n"+decrypted);
System.out.println("buzzvil decryption compatible? "+fromBuzzvilDecrypted.equals(decrypted));
}
static String encrypt(String message, String key, String iv) {
try {
// 1. encode in utf-8
byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
// 2. encrypt message through AES CBC with PKCS7
byte[] encrypted = aes(messageBytes, key, iv, Cipher.ENCRYPT_MODE);
// 3. encode in base64
return Base64.getEncoder().encodeToString(encrypted);
} catch (Exception e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
}
static String decrypt(String message, String key, String iv) {
try {
// 1. decode base64 message
byte[] base64DecodedBytes = Base64.getDecoder().decode(message);
// 2. decrypt message through AES CBC with PKCS7
byte[] decrypted = aes(base64DecodedBytes, key, iv, Cipher.DECRYPT_MODE);
// 3. decode in utf-8
return new String(decrypted, StandardCharsets.UTF_8);
} catch (Exception e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
}
static byte[] aes(byte[] messageBytes, String key, String iv, int cipherMode) {
try {
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
byte[] ivBytes = iv.getBytes(StandardCharsets.UTF_8);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(cipherMode, keySpec, ivSpec);
return cipher.doFinal(messageBytes);
} catch (Exception e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
}
}
PHP 7.0+
<?php
function encrypt($str, $mode, $key, $iv) {
$encrypted = openssl_encrypt($str, $mode, $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($encrypted);
}
function decrypt($str, $mode, $key, $iv) {
$text = base64_decode($str);
return openssl_decrypt($text, $mode, $key, OPENSSL_RAW_DATA, $iv);
}
$mode = "AES-256-CBC";
$key = "BuzzvilAESKeyTest123456789101112";
$iv = "0000000000000000";
$plaintext = '{"success": 1, "reason": "중복 적립 요청"}';
$encrypted = encrypt($plaintext, $mode, $key, $iv);
print ("ENCRYPTED: ".$encrypted."\n");
// +VEmHrt+jwI6Dg2zImdGtI+iIQEqV8v5btpS1a3cdEQBzIc72V9aKju5m6+ELTBixbITMBoHIYjj8jJbsKbIgg==
$fromBuzzvil = "IGCdundUBkXf3s7VXl0pqIKDSC/KGc2j8n1DBLKLZAHqkYlG+aWW+G5hGLvoNeUjlI42FtJLpwGUYbFlhy0QXLQv1Z+P7iUOyJrhujmFWX1FdJ5ZBefA5aceGiOlN119NPAX3JOuUAf45HkWG52NcdaHOzWu8rTnghSeLPo9QK0t6l/2gSFvGtOfZolnAHNZAeGEmcqAkhPmUoFtRAW+Zh6TNQY68FrSUI/XYc87Ky0ndaug1Kf7Ogbf8zLK+tJ4LdTCn9A+wcWxEpdkX45f1r/8jTIUK/s1PqBirXFuruq5/XhkhFmdq/I0qBAJ0uxBnk+29GaEQVMtYTzB+eJWTgrQzKhN6Nww2XEPEOl27yH+K0F+sj8QpZ0jkPETadP0gpwKMKv3zlA6xyndIYWrpw==";
$decrypted = decrypt($fromBuzzvil, $mode, $key, $iv);
print("DECRYPTED: ".$decrypted);
/*
{"point": 1, "user_id": "buzzvil_test", "transaction_id": "100004_100000000", "event_at": 1588936508, "campaign_name": "버즈빌 테스트 campaign_name", "extra": "{}", "action_type": "l", "base_point": 1, "campaign_id": 202010160022, "is_media": 1, "unit_id": 452613281179508, "revenue_type": "cpm"}
*/
?>
Python 2.7+ &
Python 2.7+
# -*- coding:utf-8 -*-
import base64
# https://pypi.python.org/pypi/pycryptodome/3.9.9
from Crypto.Cipher import AES
# https://pypi.python.org/pypi/pkcs7/0.1.2
from pkcs7 import PKCS7Encoder
def encrypt(message, key, iv):
message_plaintext_padded = PKCS7Encoder().encode(message)
cipher = AES.new(key, AES.MODE_CBC, iv)
message_encrypted_raw = cipher.encrypt(message_plaintext_padded)
return base64.b64encode(message_encrypted_raw)
def decrypt(message, key, iv):
message_decoded = base64.b64decode(message)
cipher = AES.new(key, AES.MODE_CBC, iv)
messaged_decrypted_padded = cipher.decrypt(message_decoded)
message_plaintext_decoded = PKCS7Encoder().decode(messaged_decrypted_padded)
return message_plaintext_decoded
iv = '0000000000000000'
key = 'BuzzvilAESKeyTest123456789101112'
plaintext = '{"success": 1, "reason": "중복 적립 요청"}'
encrypted = encrypt(plaintext, key, iv)
print "ENCRYPTED: {}".format(encrypted)
# +VEmHrt+jwI6Dg2zImdGtI+iIQEqV8v5btpS1a3cdEQBzIc72V9aKju5m6+ELTBixbITMBoHIYjj8jJbsKbIgg==
from_buzzvil = "IGCdundUBkXf3s7VXl0pqIKDSC/KGc2j8n1DBLKLZAHqkYlG+aWW+G5hGLvoNeUjlI42FtJLpwGUYbFlhy0QXLQv1Z+P7iUOyJrhujmFWX1FdJ5ZBefA5aceGiOlN119NPAX3JOuUAf45HkWG52NcdaHOzWu8rTnghSeLPo9QK0t6l/2gSFvGtOfZolnAHNZAeGEmcqAkhPmUoFtRAW+Zh6TNQY68FrSUI/XYc87Ky0ndaug1Kf7Ogbf8zLK+tJ4LdTCn9A+wcWxEpdkX45f1r/8jTIUK/s1PqBirXFuruq5/XhkhFmdq/I0qBAJ0uxBnk+29GaEQVMtYTzB+eJWTgrQzKhN6Nww2XEPEOl27yH+K0F+sj8QpZ0jkPETadP0gpwKMKv3zlA6xyndIYWrpw=="
decrypted = decrypt(from_buzzvil, key, iv)
print "DECRYPTED: {}".format(decrypted)
#{"point": 1, "user_id": "buzzvil_test", "transaction_id": "100004_100000000", "event_at": 1588936508, "campaign_name": "버즈빌 테스트 campaign_name", "extra": "{}", "action_type": "l", "base_point": 1, "campaign_id": 202010160022, "is_media": 1, "unit_id": 452613281179508, "revenue_type": "cpm"}
Python 3.6+
# -*- coding:utf-8 -*-
import base64
# https://pypi.python.org/pypi/pycryptodome/3.9.9
from Crypto.Cipher import AES
from binascii import unhexlify
BLOCK_SIZE = 16
def encrypt(message, key, iv):
message_plaintext_padded = pad(message).encode('utf-8')
cipher = AES.new(key, AES.MODE_CBC, iv)
message_encrypted_raw = cipher.encrypt(message_plaintext_padded)
return base64.b64encode(message_encrypted_raw)
def decrypt(message, key, iv):
message_decoded = base64.b64decode(message)
cipher = AES.new(key, AES.MODE_CBC, iv)
messaged_decrypted_padded = unpad(cipher.decrypt(message_decoded))
return messaged_decrypted_padded.decode('utf-8')
def pad(s):
return s + (BLOCK_SIZE - len(s.encode('utf-8')) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s.encode('utf-8')) % BLOCK_SIZE)
def unpad(s):
return s[:-ord(s[len(s)-1:])]
iv = '0000000000000000'.encode('utf-8')
key = 'BuzzvilAESKeyTest123456789101112'.encode('utf-8')
plaintext = '{"success": 1, "reason": "중복 적립 요청"}'
encrypted = encrypt(plaintext, key, iv)
print ("ENCRYPTED: {}".format(encrypted))
# +VEmHrt+jwI6Dg2zImdGtI+iIQEqV8v5btpS1a3cdEQBzIc72V9aKju5m6+ELTBixbITMBoHIYjj8jJbsKbIgg==
from_buzzvil = "IGCdundUBkXf3s7VXl0pqIKDSC/KGc2j8n1DBLKLZAHqkYlG+aWW+G5hGLvoNeUjlI42FtJLpwGUYbFlhy0QXLQv1Z+P7iUOyJrhujmFWX1FdJ5ZBefA5aceGiOlN119NPAX3JOuUAf45HkWG52NcdaHOzWu8rTnghSeLPo9QK0t6l/2gSFvGtOfZolnAHNZAeGEmcqAkhPmUoFtRAW+Zh6TNQY68FrSUI/XYc87Ky0ndaug1Kf7Ogbf8zLK+tJ4LdTCn9A+wcWxEpdkX45f1r/8jTIUK/s1PqBirXFuruq5/XhkhFmdq/I0qBAJ0uxBnk+29GaEQVMtYTzB+eJWTgrQzKhN6Nww2XEPEOl27yH+K0F+sj8QpZ0jkPETadP0gpwKMKv3zlA6xyndIYWrpw=="
decrypted = decrypt(from_buzzvil, key, iv)
print ("DECRYPTED: {}".format(decrypted))
#{"point": 1, "user_id": "buzzvil_test", "transaction_id": "100004_100000000", "event_at": 1588936508, "campaign_name": "버즈빌 테스트 campaign_name", "extra": "{}", "action_type": "l", "base_point": 1, "campaign_id": 202010160022, "is_media": 1, "unit_id": 452613281179508, "revenue_type": "cpm"}