猿问

使用 Swift 在 MySQL 数据库中存储设备令牌

我一直在取得进展,但在如何使用服务器端的 PHP 和我的 iOS 应用程序上的 Swift 代码将我的用户的设备令牌放入 MySQL 数据库方面停留了几天。它成功注册了推送通知,但不会发送到我的服务器。代码片段如下。此外,我还想发送设备的 IP 以匹配我应用的当前用户。任何帮助表示赞赏!


斯威夫特代码:


func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    // 1. Convert device token to string

    let tokenParts = deviceToken.map { data -> String in

        return String(format: "%02.2hhx", data)

    }

    let token = tokenParts.joined()

    // 2. Print device token to use for PNs payloads

    print("Successfully registered for notifications!")

    print("Device Token: \(token)")

    URLRequest(url: URL(string:"https://MY_URL.com/registerPushApple.php?key=MY_KEY&token=\(token)")!)


}

PHP代码:


//Put in database

date_default_timezone_set('America/New_York');

$date = date("Y-m-d");

$device_ip = $_GET['device_ip'];

$device_token = $_GET['token'];

$key = $_GET['key'];


if($key == "MY_KEY") {


    // Insert Info into Database

    $mysqli->query("INSERT INTO device_info (date, device_ip, device_token) VALUES ('$date', '$device_ip', '$device_token')");



} else {


    die();


}


// close connection 

$mysqli->close();


MM们
浏览 130回答 1
1回答

撒科打诨

几点观察:您的 Swift 代码没有将请求发送到服务器。您可能会执行以下操作:var request = URLRequest(url: URL(string:"https://MY_URL.com/registerPushApple.php")!)request.httpBody = "key=MY_KEY&token=\(token)".data(using: .utf8)request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")request.httpMethod = "POST"let task = URLSession.shared.dataTask(with: request) { data, response, error in&nbsp; &nbsp; guard let data = data, error == nil else {&nbsp; &nbsp; &nbsp; &nbsp; print(error ?? "Unknown error")&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // OK, if you got here, the server successfully responded, but you now&nbsp; &nbsp; // need to parse it with `JSONDecoder` and make sure there weren’t any&nbsp;&nbsp; &nbsp; // SQL errors reported. But I’m just going to print the response JSON for now:&nbsp; &nbsp; print(String(data: data, encoding: .utf8))}task.resume()笔记:这是一个POST请求;我们在httpBody请求中发送我们的数据,而不是 URL;和我们正在执行请求resume。&nbsp;我还建议对请求正文进行百分比编码,以防您的任何值包含任何保留字符。或者使用像Alamofire这样的库,它可以让你摆脱构建格式良好的请求的麻烦。您的 PHP 代码不会检查是否INSERT成功,如果没有,则以足够的信息进行响应,以便您诊断正在发生的事情。例如:<?phpheader('Content-type: application/json');// You didn’t send IP in your request, so you won’t find it in `$_GET` or `$_POST`// Perhaps https://stackoverflow.com/a/2031935/1271826function get_ip_address(){&nbsp; &nbsp; foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){&nbsp; &nbsp; &nbsp; &nbsp; if (array_key_exists($key, $_SERVER) === true){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (explode(',', $_SERVER[$key]) as $ip){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ip = trim($ip); // just to be safe&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return $ip;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}$mysqli = new mysqli('localhost', 'user', 'pwd', 'db');// check connection&nbsp;if ($mysqli->connect_errno) {&nbsp; &nbsp; echo json_encode(array('success' => false, 'message' => $mysqli->connect_error, 'sqlerrno' => $mysqli->connect_errno));&nbsp; &nbsp; exit();}$mysqli->set_charset('utf8');// perform the insert$device_ip = get_ip_address();$device_token = $_POST['token'];$key = $_POST['key'];$sql = 'INSERT INTO device_info (date, device_ip, device_token, key) VALUES (NOW(), ?, ?, ?)';if ($stmt = $mysqli->prepare($sql)) {&nbsp; &nbsp; $stmt->bind_param('sss', $device_ip, $device_token, $key);&nbsp; &nbsp; if (!$stmt->execute())&nbsp; &nbsp; &nbsp; &nbsp; $response = array('success' => false, 'message' => $mysqli->error, 'sqlerrno' => $mysqli->errno, 'sqlstate' => $mysqli->sqlstate);&nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; $response = array('success' => true);&nbsp; &nbsp; $stmt->close();} else {&nbsp; &nbsp; $response = array('success' => false, 'message' => $mysqli->error, 'sqlerrno' => $mysqli->errno, 'sqlstate' => $mysqli->sqlstate);}$mysqli->close();echo json_encode($response);?>笔记:您希望将您的值绑定到?SQL 中以防止 SQL 注入攻击(或使用real_escape_string);和您想检查插入是否成功并返回有意义的 JSON 响应,无论成功与否。现在,我只是把它删掉了,所以请原谅任何印刷错误。但希望这能给你基本的想法。显然,您不应该只打印返回的 JSON,而是对其进行解析JSONDecoder并查看结果是否有错误。同样,您的 PHP 可能应该对请求中的参数进行一些优雅的检查,如果没有,则返回漂亮的 JSON 错误响应。但希望这能让你朝着正确的方向前进。你说:我还想发送设备的 IP 以匹配我应用的当前用户。不,您不希望设备在请求中添加其 IP 号码,因为设备只会知道其本地 IP 号码(例如,如果在 wifi 上,它通常是 192.168.0.x 之类的东西,许多用户可能有各自的 LAN 上相同的本地 IP 号)。显然,就服务器而言,这通常是没有意义的。您应该让 PHP 从它收到的请求中提取 IP 号,如上所示。最重要的是,无论如何,我认为IP号码不是验证用户的好方法。如果您走进一家咖啡馆并使用他们的 wifi:IP 号码已更改。您打开 VPN:IP 号码再次更改。您失去 Internet 连接并重新连接:IP 号码可能再次更改。最重要的是,IP 编号(即使您让服务器获取它而不是要求设备找出它)可能会发生变化,并且不是验证用户的好方法。不要误会我的意思:我不认为捕获 IP 号码一定是一个坏主意。但仅供参考。如果您想验证用户,通常还有其他更好的方法可以做到这一点。
随时随地看视频慕课网APP
我要回答