Youmi ios offers order callback protocol tw

来自有米广告开发者WIKI
跳转至: 导航搜索

有米 IOS 積分牆積分訂單伺服器回調協議

說明

  • 此文檔只適合 iOS 平台,Android 平台開發者請看這裡:有米 Android 積分牆積分訂單伺服器回調協議
  • 介面統一使用的編碼為:UTF-8
  • 適合於開發者使用自己的伺服器來託管積分的情況。
  • 當我們收到廣告主反饋的積分時,我們會實時反饋給開發者伺服器。
  • 需要開發者提供一個介面來接收數據(web 端提供設置頁面),介面接收數據的方式:GET。


流程

  1. 開發者在有米的開發者後台設置自己應用的積分反饋地址,例如:https://app.youmi.net/apps/setting
  2. 當有米的伺服器接收到一個有效的效果記錄時,就會按開發者提供的反饋地址,加上相關的參數(具體參數見下面的表格),一起反饋給開發者的伺服器(GET 的方式)。


參數

參數全稱 參數名 長度限制(字節數) 說明
Order ID order 字符串(16字節) 訂單ID:該值是唯一的,如果開發者接收到相同的訂單號,那說明該訂單已經存在。
App ID app 字符串(16字節) 開發者應用ID
Ad Name ad 廣告名(50字節) 廣告名,如果是應用類型的廣告則是應用名
Ad Identify adid 廣告編號(整型) 廣告的編號ID
User ID user 字符串 用戶ID:開發者可以設置自己的用戶ID,或者將該字段作為回調預留字段使用
Device ID device 字符串 設備ID:iOS是MAC地址,iOS 7 沒有MAC地址則傳Advertising Identifier (IDFA) "https://developer.apple.com/library/ios/documentation/AdSupport/Reference/ASIdentifierManager_Ref/ASIdentifierManager.html#// apple_ref/occ/instp/ASIdentifierManager/advertisingIdentifier“
Channel chn 整型 渠道號,對於IOS來說該值為0
Price price 浮點型 開發者獲得的收入
Points points 整型 用戶可以賺取的積分
Order Create Time time 整形 有米創建訂單的時間
Sig sig 字符串(8字節) 保留字段(無意義)
Sign sign 字符串(36字節) 簽名

注:

  • 本協議的所有參數均採用 UTF-8。
  • $dev_server_secret:開發者伺服器端密鑰,由有米單獨提供給開發者。請登錄後進入“https://app.youmi.net/apps/setting” 找到積分廣告回調方式設置-伺服器回調設置那裡,進行伺服器地址設置,設置成功後就會分配一個密鑰給您的應用。
  • 部分字段可能包含有特殊字符,在接收到請求時請自行使用 urldecode。


簽名算法

將【參數】列表中除“sign”外的所有參數作為 key 求 MD5 值。
假設參與參數簽名計算的請求參數分別是“k1”、“k2”、“k3”,它們的值分別是“v1”、“v2”、“v3”,則參數簽名計算方法如下:

  • 將請求的非 binary 類型的參數格式化為“key=value”格式,即“k1=v1”、“k2=v2”、“k3=v3”;
  • 將格式化好的參數鍵值對以字典序升序排列後,拼接在一起,即“k1=v1k2=v2k3=v3”;
  • 在拼接好的字符串末尾追加上 $dev_server_secret;
  • 上述字符串的 MD5 值即為簽名的值。

注意:

  • 計算簽名時的請求參數中不要包含 sign(簽名)參數,因為 sign 參數的值此時還不知道,有待計算。
  • 簽名過程中的各個參數並未經過 urlencode 處理
即:sign = md5("ad={$ad}adid={$adid}app={$app}chn={$chn}device={$device}order={$order}points={$points}price ={$price}sig={$sig}time={$time}user={$user}{$dev_server_secret}");

示例:

原URL:http://api.kaifazhe.com/youmi.php?order=YM121201PWxw0DGr0f&app=2f3ca4oge6894826&ad=%E7%BE%8E%E4%B8%BD%E8%AF%B4&adid=476&user=ef2&chn=0&points=140&price= 0.93&time=1354851585&device=98fee7g64057&sig=b68184af
$dev_server_secret:1234567890

經計算後

sign=ca8ac4661e283eb8fe119ccabbcd2352
最終URL:http://api.kaifazhe.com/youmi.php?order=YM121201PWxw0DGr0f&app=2f3ca4oge6894826&ad=%E7%BE%8E%E4%B8%BD%E8%AF%B4&adid=476&user=ef2&chn=0&points=140&price= 0.93&time=1354851585&device=98fee7g64057&sig=b68184af&sign=ca8ac4661e283eb8fe119ccabbcd2352

PHP實現:

<?php
  $url = 'http://api.kaifazhe.com/youmi.php?order=YM121201PWxw0DGr0f&app=2f3ca4oge6894826&ad=%E7%BE%8E%E4%B8%BD%E8%AF%B4&adid=476&user=ef2&chn=0&points=140&price =0.93&time=1354851585&device=98fee7g64057&sig=b68184af';
  $dev_server_secret = '1234567890';
  $url .= '&sign=' . getUrlSignature($url, $dev_server_secret);
  echo $url, "\n";
 
  function getUrlSignature($url, $secret){
    $params = array();
    $url_parse = parse_url($url);
    if (isset($url_parse['query'])){
      $query_arr = explode('&', $url_parse['query']);
      if (!empty($query_arr)){
        foreach($query_arr as $p){
          if (strpos($p, '=') !== false){
            list($k, $v) = explode('=', $p);
            $params[$k] = urldecode($v);
          }
        }
      }
    }
    return getSignature($params, $secret);
  }
 
  function getSignature($params, $secret){
    $str = '';
    ksort($params);
    foreach ($params as $k => $v) {
      $str .= "{$k}={$v}";
    }
    $str .= $secret;
    return md5($str);
  }


java實現:

  public class YoumiSign {
    public static void main(String[] args) {
      //test
      HashMap<String, String> ps = new HashMap<String, String>();
      ps.put("order", "abcdef0123456789");
      ps.put("app","abcdef0123456789");
      ps.put("ad","大俠傳");
      ps.put("adid",Integer.toString(1000));
      ps.put("user","abcdefg");
      ps.put("device","ifa");
      ps.put("chn","0");
      ps.put("price",Double.toString(1.0));
      ps.put("points",Integer.toString(100));
      ps.put("time",Long.toString(10000000));
      ps.put("sig","hjd8f33rsjdfas");
      try{
        String sign=getSignature(ps,"xxxxx");
        System.out.println(sign);
      }catch (Throwable e){
        //TODO Handle Throwable
      }
    }
 
    /**
     * 簽名生成算法
     *
     * @param HashMap<String,String> params 請求參數集,所有參數必須已轉換為字符串類型
     * @param String dev_server_secret 開發者在有米後台設置的密鑰
     * @return 簽名
     * @throws IOException
     */
    public static String getSignature(HashMap<String, String> params, String dev_server_secret) throws IOException {
      // 先將參數以其參數名的字典序升序進行排序
      Map<String, String> sortedParams = new TreeMap<String, String>(params);
 
      Set<Map.Entry<String, String>> entrys = sortedParams.entrySet();
      // 遍歷排序後的字典,將所有參數按"key=value"格式拼接在一起
      StringBuilder basestring = new StringBuilder();
      for (Map.Entry<String, String> param : entrys) {
        basestring.append(param.getKey()).append("=").append(param.getValue());
      }
      basestring.append(dev_server_secret);
      System.out.println(basestring.toString());
      // 使用MD5對待簽名串求籤
      byte[] bytes = null;
      try {
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        bytes = md5.digest(basestring.toString().getBytes("UTF-8"));
      } catch (GeneralSecurityException ex) {
        throw new IOException(ex);
      }
      // 將MD5輸出的二進制結果轉換為小寫的十六進制
      StringBuilder sign = new StringBuilder();
      for (int i = 0; i < bytes.length; i++) {
        String hex = Integer.toHexString(bytes[i] & 0xFF);
        if (hex.length() == 1) {
          sign.append("0");
        }
        sign.append(hex);
      }
      return sign.toString();
    }
}


簽名參數的校驗

說明:這裡的校驗是指開發者在嵌入廣告的初期,開發者如果發現校驗不通過,才需要使用該介面進行校驗,當然也可以直接諮詢我們的客服。正常校驗邏輯由開發者自己實現。 

假設開發者最終收到我們的反饋請求為: http://api.kaifazhe.com/youmi.php?order=YM130402cygr_UTb42&app=30996ced018a2a5e&ad=KC%E7%BD%91%E7%BB%9C%E7%94%B5%E8%AF%9D&user=1141058&device=50ead626ae6e&chn= 0&points=7&time=1364890524&sig=15b3dfe0&price=0.749&adid=853&sign=7118194d2da288e6b02878dd9ac07213

這時如果計算得到的簽名和接收到的不同,這時可以請求這樣的一個鏈接來測試: http://ios.wall.youmi.net/v2/check_fb_sig?order=YM130402cygr_UTb42&app=30996ced018a2a5e&ad=KC%E7%BD%91%E7%BB%9C%E7%94%B5%E8%AF%9D&user=1141058&device= 50ead626ae6e&chn=0&points=7&time=1364890524&sig=15b3dfe0&price=0.749&adid=853&sign=7118194d2da288e6b02878dd9ac07213

就是把http://api.kaifazhe.com/youmi.php 替換成http://ios.wall.youmi.net/v2/check_fb_sig 即可。
該測試鏈接會輸出相應的結果。


傳回值

  1. 有米會根據開發者伺服器傳回的 http 狀態碼(http_code)來判斷該進行什麼樣的操作,正常情況收到的 http 狀態碼應該是200或者403。
  2. 如果是200,表示開發者正常接收到信息並且正常處理了。
  3. 如果是403,表示開發者拒絕了該次請求,此時中間層伺服器不會再重複請求開發者伺服器。
  4. 如果超時、或收到的不是200或者403,中間層的伺服器就會放在下一次循環請求開發者伺服器。
  5. 下一次循環請求開發者伺服器會有一定的延遲,延遲分別為:5s, 10s, 60s, 300s, 600s, 3600s(距離上一次發送)。即最差環境下,有米最多將發送7次請求,若7次請求全部失敗,則該鏈接將被丟棄。
  6. 因為網絡等問題,開發者伺服器可能會接收到訂單號完全相同的多條記錄,這時開發者伺服器需要把重複的丟失,並以 http 狀態碼(http_code)403輸出。也就是說:開發者伺服器需要對接收到的信息進行去重