Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 7 Next »

사용자에게 보상을 지급하기 위해서 포스트백(Postback) 연동이 필요합니다. 포스트백 요청은 보안을 위해 서버 간 통신(Server-to-server) 형태로 진행됩니다.

매체사의 상황에 따른 연동 방법

 매체사의 포인트 시스템이 있을 경우

아래의 절차에 따라 진행합니다.

  1. 버즈빌의 포인트 적립 요청을 받을 수 있는 서버 endpoint 구축 (해당 endpoint 의 URL을 postback url로 지칭)

  2. 본 가이드에 따라 Server-To-Sever 연동

  3. 버즈빌 BD 매니저에게 postback url 전달

매체사 앱을 미국 혹은 다국가에서 운영하는 경우, 반드시 BD 매니저와 사전 논의 부탁드립니다.

 매체사의 포인트 시스템이 없을 경우

매체사 앱에 버즈빌의 포인트 시스템 (BuzzStore) 을 연동합니다. 해당 문서의 연동 가이드에 따라 진행해주세요.

 Index


Introduction

버즈빌을 통해 유저가 포인트를 지급받은 경우, 매체사에게 이 사실을 전달하여 적립 요청을 보내기 위한 API입니다.

항목

내용

1

요청 방향

버즈빌 → 매체사

2

HTTP Request method

POST - application/x-www-form-urlencoded

3

HTTP Request URL

매체사 서버의 endpoint

4

HTTP Request Parameters

아래 Http Request Parameters 테이블을 참고합니다.

5

HTTP Response Code

버즈빌 서버는 매체사 서버로 부터 전달받은 응답 코드(Response Code)를 바탕으로 성공 여부를 판단합니다.

  • 200 (ok): 성공 처리

    • 매체 서버에서 요청을 제대로 처리한 경우의 응답 코드

  • 200 이외의 응답 코드: 최대 5회까지 해당 Postback 요청을 재시도

    • Exponential하게 1분, 10분, 1시간, 3시간, 24시간의 간격을 두고 수행

body에 오류 내용을 담더라도 응답 코드가 200인 경우 재시도하지 않으므로 주의해 주세요.

HTTP Request Parameters

기능에 따라서 두 종류의 포스트백이 존재합니다. 각 타입에 관한 포스트백 파라미터 정보는 아래의 표를 참고하세요.

String 타입의 파라미터 필드 값이 한국어일 경우에는 유니코드로 인코딩되어 전달됩니다.

파라미터 필드(Field)

타입
(Type)

설명

user_id

REQUIRED

String 
(max 255)

매체사에서 정의한 유저의 식별값

transaction_id

REQUIRED

String 
(max 32)

보상에 발급되는 ID, 이는 포인트 중복 지급을 방지하기 위해 사용

  • 최대 32자까지 전달될 수 있으므로, 연동 시 확인이 필요합니다.

같은 transaction_id로 요청이 온 경우에는 반드시 포인트 중복 적립이 되지 않도록 처리해주어야 합니다.

point

REQUIRED

Integer

사용자에게 지급해야하는 포인트

unit_id

REQUIRED

Long

광고가 노출된 지면의 ID 값

현재 주로 사용하는 값은 15자리의 숫자입니다.

title

REQUIRED

String
(max 255)

포인트가 지급된 방식에 설정된 이름

  • 광고 (참여한 광고의 이름)

    • e.g 출시 임박! 해당 CPS 상품을 먼저 만나보세요! 😁 #Buzzvil #환상적

  • 그 외는 모두 빈값

    • ex. 만보기/뽀또

최대 한글 255자까지 전달될 수 있으므로 연동 시 DB별 String 사이즈를 참조해 주세요.

action_type

REQUIRED

String
(max 32)

포인트를 지급 받기 위해 사용자가 취한 액션 타입

  • opened: Feed 지면 진입 (지면을 방문하기만 해도 기본 리워드 적립)

  • u: 잠금 해제

  • l: 랜딩

  • a: 액션 (해당 광고의 요구 액션을 완료했을 때)

  • won: Potto에서 당첨번호에 당첨되었을 시 포인트 적립을 요청

  • walked: 만보기에서 목표 걸음수를 달성하고 포인트 적립을 요청

  • spinned : 룰렛 미션 참여 시 지급되는 포인트

추후 다양한 타입이 추가될 수 있습니다.

event_at

REQUIRED

Long (timestamp)

포인트 지급 시점 (UNIX Timestamp 초단위)

대부분 API 호출시점과 동일하지만 API 호출이 재시도인 경우 다를 수 있습니다.

extra

REQUIRED

String
(max 1024)

파라미터를 추가해야할 경우, 해당 파라미터(JSON serialize 된 문자열 값)을 활용

  • 매체사가 지정한 캠페인 데이터 (대시보드에서 캠페인을 생성할 때 지정할 수 있습니다)

    • e.g {"sub_type": "A", "source":"external"}

data

OPTIONAL

String

HTTP request parameter를 암호화 해서 전송하는 경우 사용되는 파라미터

자세한 내용은 아래 HTTP Request Parameter Encryption/Decryption을 참조하세요.

c

OPTIONAL

String

HTTP request parameter에 Checksum을 전송하는 경우 사용되는 파라미터

자세한 내용은 아래 Add Checksum Parameter를 참조하세요.

HTTP Request Parameter 포스트백 예제

다음은 HTTP Request Parameter의 포스트백 예제입니다.

{
  "user_id": "12345",
  "point": 1,
  "transaction_id": "126905422_10000001",
  "event_at": 1641452397,
  "unit_id": 5539189976900000,
  "action_type": "l",
  "title": "\uad11\uace0\u0020\ud2b9\uac00",
  "extra": "{}"
}

요청 파라미터 검증 OPTIONAL

버즈빌 서버에서 전달되는 포인트 적립 요청(포스트백)을 암호화 할 수 있습니다. 이 과정은 필수 적용 항목은 아니고, 필요한 경우, 아래의 두 가지 방법을 제공합니다.

1. HTTP Request Parameter Encryption/Decryption

버즈빌 서버에서 매체사로 보내는 HTTP Request parameter를 암호화 하고 싶은 경우 사용합니다. 제공하는 암호화 방식은 고급 암호화 표준, AES(Advanded Encryption Standard)입니다. 제공되는 블록 암호화는 AES-256 이고, 사용하는 블록 암호화 모드(Block Cipher)는 CBC(Cipher Block Chaning) Mode와 PKCS7을 사용합니다.

 진행 과정

준비물

  • 버즈빌 매니저 통해 AES-256 암호화에 필요한 아래 값들 발급:

    • AES Key (길이 32)

    • AES IV (길이 16)

진행 절차

  1. 버즈빌 서버에서 HTTP Request parameter를 암호화

    1. JSON serialized parameters(string)에 해당 string을 UTF-8 인코딩 적용

    2. 해당 string에 PKCS7 패딩 적용 및 AES 암호화 진행

    3. 암호화된 값을 base64 encoding을 진행

  2. 암호화 된 데이터를 HTTP POST request에 파라미터 data라는 이름으로 추가하여 전송

    1. e.g

      {
        "data": "cg087LiIp30jCWpc3MVLfxPL4F05OFGGCkQwwpS6pRVMZhkumzfTFxc8iBoZ8unI15uk0cmY+CbSeOaLHsd7PaxsbyKISiJ31WJJ1OwfaYttoMwFysKNfL7pSz2HB9ULWZicG8MSPxCPKr9RDqgOXpuEoVm9YR3I4yNE5M0LNltpCTdXRBjTrOcjp+RtEZ1VENtHqTICK18nDqO+91BUt3AJsf4VmzogJ8UpA0izEbY="
      }
  3. 수신 측 (매체사) 에서는 HTTP POST request에서 data 파라미터를 가져와 아래와 같은 순서로 복호화

    1. 암호화된 값을 base64 decoding 진행

    2. 해당 decoding된 string을 복호화 진행 이후 PKCS7 패딩 제거

    3. 해당 string을 UTF-8 디코딩

 

예제

  • 예제에서는 AES key, IV 값으로 모두 buzzvil123456789를 사용

{
  "unit_id":"12345",
  "transaction_id":"10000000_1",
  "user_id":"buzzvil",
  "point": 1,
  "action_type":"won",
  "event_at": 1599622182,
  "title":"title",
  "extra": "{}"
}
  • 암호화 결과

    • JSON (UTF-8encoding) → AES encryption → base64 encoding 순서로 진행

      cg087LiIp30jCWpc3MVLfxPL4F05OFGGCkQwwpS6pRVMZhkumzfTFxc8iBoZ8unI15uk0cmY+CbSeOaLHsd7PaxsbyKISiJ31WJJ1OwfaYttoMwFysKNfL7pSz2HB9ULWZicG8MSPxCPKr9RDqgOXpuEoVm9YR3I4yNE5M0LNltpCTdXRBjTrOcjp+RtEZ1VENtHqTICK18nDqO+91BUt3AJsf4VmzogJ8UpA0izEbY=

 

  • 위의 암호화된 문장을 복호화시, 다음과 같습니다.

    • base64 decoding

      r\r<\xec\xb8\x88\xa7}#\tj\\\xdc\xc5K\x7f\x13\xcb\xe0]98Q\x86\nD0\xc2\x94\xba\xa5\x15Lf\x19.\x9b7\xd3\x17\x17<\x88\x1a\x19\xf2\xe9\xc8\xd7\x9b\xa4\xd1\xc9\x98\xf8&\xd2x\xe6\x8b\x1e\xc7{=\xaclo"\x88J"w\xd5bI\xd4\xec\x1fi\x8bm\xa0\xcc\x05\xca\xc2\x8d|\xbe\xe9K=\x87\x07\xd5\x0bY\x98\x9c\x1b\xc3\x12?\x10\x8f*\xbfQ\x0e\xa8\x0e^\x9b\x84\xa1Y\xbda\x1d\xc8\xe3#D\xe4\xcd\x0b6[i\t7WD\x18\xd3\xac\xe7#\xa7\xe4m\x11\x9dU\x10\xdbG\xa92\x02+_\'\x0e\xa3\xbe\xf7PT\xb7p\t\xb1\xfe\x15\x9b: \'\xc5)\x03H\xb3\x11\xb6

       

    • AES decryption) Key, IV: buzzvil123456789

      {"unit_id": "12345", "transaction_id": "10000000_1", "user_id": "buzzvil", "point": 1, "action_type": "won", "event_at": 1599622182, "title": "title", "extra": "{}"}

       

    • UTF-8 decoding

      {"unit_id": "12345", "transaction_id": "10000000_1", "user_id": "buzzvil", "point": 1, "action_type": "won", "event_at": 1599622182, "title": "title", "extra": "{}"}

      (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 3.6+

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"}

2. Add Checksum Parameter

포스트백 데이터 검증을 위해 Request Parameters 에 Checksum parameter를 추가하고자 하는 경우 사용합니다. 제공하는 데이터 검증 방식은 HMAC 인증이고, SHA-256 알고리즘을 사용합니다.

 진행 과정

준비물

  • 버즈빌 매니저 통해 HMAC 인증에 필요한 아래 값들 발급:

    • HMAC KEY (최대 길이 64)

진행 절차

  1. 전달받은 포스트백 파라미터 중 transaction_id, user_id, point, event_at 값으로 아래 형식대로 String을 생성 (이하 "msg")

    1. 주의사항 : msg 값은 인코딩되어야 하며, 각 파라미터 string 과 colon 사이에는 띄어쓰기가 없습니다.

      msg=u'{0}:{1}:{2}:{3}'.format(
      							params['transaction_id'],
                          		params['user_id'],
                                  params['point'],
                          		params['event_at'],
                      		).encode('utf-8')

       

  2. HMAC SHA-256 알고리즘을 사용하여 msg 값을 암호화

    • key: 1번에서 발급받은 hmac_key

    • data: 2번에서 생성한 msg

  3. 전달받은 포스트백 파라미터 중 c 필드의 값과 비교, 일치 여부를 확인

    • 결과값 길이: 64자

예제

  • hmac_key = 12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh

    {
        "transaction_id": 429482977,
        "user_id": "testuserid76301",
        "point": 2,
        "event_at": 1849274,
        "c": "43ad5b2639e3363d81879e0ac441a14a369993a0cc6a1f21921f8344cb2612eb"
    }

     

  • msg = 429482977:testuserid76301:2:1849274

  • No labels