激活日志打点
<p>[TOC]</p>
<h3>1、开发环境配置</h3>
<h4>引入 SDK 资源,其中 LewanSDK 部分代码可以混淆</h4>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=d42fa1f1a9d618d50a2aadb1d8e27aa2&amp;file=file.png" alt="" /></p>
<h4>在 Xcode 中,选择你的工程设置项,选中“TARGETS”一栏,在“info”标签栏的“URL type“添加“URL scheme”,输入应用对应的包名作为scheme头;</h4>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=dbf882cd7472a746646c86f85ee3d64a&amp;file=file.png" alt="" /></p>
<h4>iOS隐私合规声明文件,可直接复制合并到自己项目或者使用压缩包内文件</h4>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;dict&gt;
&lt;key&gt;NSPrivacyCollectedDataTypes&lt;/key&gt;
&lt;array/&gt;
&lt;key&gt;NSPrivacyAccessedAPITypes&lt;/key&gt;
&lt;array&gt;
&lt;dict&gt;
&lt;key&gt;NSPrivacyAccessedAPIType&lt;/key&gt;
&lt;string&gt;NSPrivacyAccessedAPICategoryDiskSpace&lt;/string&gt;
&lt;key&gt;NSPrivacyAccessedAPITypeReasons&lt;/key&gt;
&lt;array&gt;
&lt;string&gt;E174.1&lt;/string&gt;
&lt;/array&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;NSPrivacyAccessedAPIType&lt;/key&gt;
&lt;string&gt;NSPrivacyAccessedAPICategoryFileTimestamp&lt;/string&gt;
&lt;key&gt;NSPrivacyAccessedAPITypeReasons&lt;/key&gt;
&lt;array&gt;
&lt;string&gt;DDA9.1&lt;/string&gt;
&lt;/array&gt;
&lt;/dict&gt;
&lt;dict&gt;
&lt;key&gt;NSPrivacyAccessedAPIType&lt;/key&gt;
&lt;string&gt;NSPrivacyAccessedAPICategoryUserDefaults&lt;/string&gt;
&lt;key&gt;NSPrivacyAccessedAPITypeReasons&lt;/key&gt;
&lt;array&gt;
&lt;string&gt;CA92.1&lt;/string&gt;
&lt;/array&gt;
&lt;/dict&gt;
&lt;/array&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</code></pre>
<h3>2、客户端启动上报接口( 生命周期)</h3>
<pre><code>#import &quot;LewanSDK.h&quot;
如使用AppDelegate</code></pre>
<pre><code class="language-objectivec">- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[LewanSDK getInstance] application:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary&lt;UIApplicationOpenURLOptionsKey,id&gt; *)options{
[[LewanSDK getInstance] application:app openURL:url options:options];
return YES;
}</code></pre>
<pre><code>如使用SceneDelegate</code></pre>
<pre><code class="language-objectivec">- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
[[LewanSDK getInstance] scene:scene willConnectToSession:session options:connectionOptions];
}
- (void)scene:(UIScene *)scene openURLContexts:(NSSet&lt;UIOpenURLContext *&gt; *)URLContexts{
[[LewanSDK getInstance] scene:scene openURLContexts:URLContexts];
}</code></pre>
<h3>3、客户端上报激活代码demo</h3>
<pre><code class="language-objectivec"> NSString *secretKey = @&quot;Lewan@2023&quot;;
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:[[[UIDevice currentDevice] identifierForVendor] UUIDString] forKey:@&quot;tmp_uid&quot;];
[dict setValue:@&quot;ios&quot; forKey:@&quot;platform&quot;];
[dict setValue:[[NSBundle mainBundle] bundleIdentifier] forKey:@&quot;package&quot;];
NSString *click_id = [[LewanSDK getInstance] getClickId] ?: @&quot;&quot;;
[dict setValue:click_id forKey:@&quot;click_id&quot;];
//排序
NSArray *sortedKeys = [[dict allKeys] sortedArrayUsingSelector:@selector(compare:)];
NSMutableString *builder = [NSMutableString string];
for (NSString *key in sortedKeys) {
NSString *value = [NSString stringWithFormat:@&quot;%@&quot;, dict[key]];
[builder appendString:[NSString stringWithFormat:@&quot;%@=%@&amp;&quot;, key, value]];
}
[builder deleteCharactersInRange:NSMakeRange(builder.length - 1, 1)];
[builder appendString:secretKey];
//签名
const char *cStr = [builder UTF8String];
unsigned char result[16];
CC_MD5( cStr, strlen(cStr), result );
NSString *md5Sing = [NSString stringWithFormat:
@&quot;%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X&quot;,
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]];
NSString *sign = [md5Sing lowercaseString];
//sign 加回字典
[dict setValue:sign forKey:@&quot;sign&quot;];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@&quot;%@&quot;,jsonString);
//转 json 请求
NSURL *url = [NSURL URLWithString:@&quot;https://graph.whmwan.com/v3/LogHandle/activeLog&quot;];
NSData *postData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
[request setHTTPMethod:@&quot;POST&quot;];
[request setHTTPBody:postData];
[request setValue:@&quot;application/json&quot; forHTTPHeaderField:@&quot;Content-Type&quot;];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@&quot;Error: %@&quot;, error);
} else {
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@&quot;Response: %@&quot;, responseString);
}
}];
[task resume]; </code></pre>
<h3>1、【壳包激活日志上报】接口功能说明</h3>
<pre><code>在用户打开app触发激活行为时上报(首次激活)</code></pre>
<h5>请求URL</h5>
<ul>
<li><a href="https://graph.llewan.com/v3/LogHandle/activeLog">https://graph.llewan.com/v3/LogHandle/activeLog</a> //几何王国/天命主公</li>
<li><a href="https://graph.whmwan.com/v3/LogHandle/activeLog">https://graph.whmwan.com/v3/LogHandle/activeLog</a> //一切高手</li>
</ul>
<h5>请求方式</h5>
<ul>
<li>POST </li>
<li>Content-Type:application/json</li>
</ul>
<h5>请求参数</h5>
<table>
<thead>
<tr>
<th style="text-align: left;">参数名</th>
<th style="text-align: left;">必选</th>
<th style="text-align: left;">类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">tmp_uid</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>设备标识&用户临时标识:ios设备传idfv,安卓设备传androidId</td>
</tr>
<tr>
<td style="text-align: left;">platform</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">Enums</td>
<td>设备操作系统:[ios,android]</td>
</tr>
<tr>
<td style="text-align: left;">package</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>包名</td>
</tr>
<tr>
<td style="text-align: left;">click_id</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>巨量 click_id</td>
</tr>
<tr>
<td style="text-align: left;">sign</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>签名,签名方式见下说明</td>
</tr>
</tbody>
</table>
<h5>返回示例</h5>
<pre><code>// 成功
{
&quot;code&quot;: 1,
&quot;msg&quot;: &quot;success&quot;,
&quot;d&quot;: []
}
// 异常
{&quot;code&quot;: -1, &quot;msg&quot;: &quot;check sign fail&quot;} // 签名错误
</code></pre>
<h5>响应参数说明</h5>
<table>
<thead>
<tr>
<th style="text-align: left;">参数名</th>
<th style="text-align: left;">必选</th>
<th style="text-align: left;">类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">code </td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">integer</td>
<td>响应状态码,1成功,-1异常</td>
</tr>
<tr>
<td style="text-align: left;">msg</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>请求结果说明</td>
</tr>
<tr>
<td style="text-align: left;">d</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">array</td>
<td>响应数据主体,code不为1时响应空数组</td>
</tr>
</tbody>
</table>
<h5>签名方式说明</h5>
<ul>
<li><strong>参与签名字段说明</strong>
请求参数除sign外都需要参与签名</li>
<li><strong>签名规则</strong>
1、签名串规则:所有参与签名的参数,按参数名(key)字典序升序排序,以key=value格式,并用【&】连接组成签名串,最后连接签名秘钥
2、对签名串进行MD5加密得到签名(32位小写字符串),PHP示例如下:</li>
</ul>
<pre><code>&lt;?php
function getSign($params, $secret)
{
//剔除sign字段
if (isset($params[&#039;sign&#039;])) unset($params[&#039;sign&#039;]);
//对数组按key升序排序
ksort($params);
//拼接签名串
$formatStr = &#039;&#039;;
foreach ($params as $key =&gt; $v) {
$formatStr .= $key . &#039;=&#039; . $v . &#039;&amp;&#039;;
}
return md5(substr($formatStr, 0, -1) . $secret);
}
$secret = &#039;abc&#039;; //服务端签名秘钥
$params = [
&#039;game&#039; =&gt; &#039;aaa-weixin&#039;,
&#039;role_id&#039; =&gt; &#039;1520001&#039;,
&#039;server_id&#039; =&gt; &#039;10001&#039;,
&#039;user_name&#039; =&gt; &#039;昵称&#039;,
...
]; //请求参数
$sign = getSign($params, $secret); //签名
</code></pre>