【问题标题】:How to get this iOS Http Post Request to work?如何让这个 iOS Http Post Request 工作?
【发布时间】:2021-01-03 20:58:50
【问题描述】:

我正在使用 Firebase Cloud Functions 和 Paypal 在我的应用中为司机设置付款流程。要发布的url是Firebase中实际云功能的url:

https://us-central1-ryyde-sj.cloudfunctions.net/payout

尝试发送 HTTP Post 请求时,它似乎不起作用。请参阅下面的 payoutRequest()Response 代码:

payoutRequest()

let email = txtPayoutEmail.text!
    let uid = self.uid!
    
    // Prepare URL:
    let url = URL(string: "https://us-central1-ryyde-sj.cloudfunctions.net/payout")
    guard let requestUrl = url else { fatalError() }
    
    // Prepare URL Request Object:
    var request = URLRequest(url: requestUrl)
    request.httpMethod = "POST"
    
    // Set HTTP Request Headers
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue("Your Token", forHTTPHeaderField: "Authorization")
    request.setValue("no-cache", forHTTPHeaderField: "cache-control")

    print("request = \(request)")
    
    // HTTP Request Parameters which will be sent in HTTP Request Body:
    let postString = "uid=\(uid)&email=\(email)"
    print("postString = \(postString)")
     
    // Set HTTP Request Body
    request.httpBody = postString.data(using: String.Encoding.utf8)
    
    // Perform HTTP Request
    let task = URLSession.shared.dataTask(with: request) { (data, response, error ) in
        
        print("data: \(String(describing: data))")
        print("response: \(String(describing: response))")
        print("error: \(String(describing: error))")
        
        if let response = response as? HTTPURLResponse {
            // Read all HTTP Response Headers
            print("All headers: \(response.allHeaderFields)")
            // Read a specific HTTP Response Header by name
            if #available(iOS 13.0, *) {
                print("Specific header: \(response.value(forHTTPHeaderField: "Content-Type") ?? " header not found")")
            } else {
                // Fallback on earlier versions
            }
        }
        
        // Check for Errors
        if let error = error {
            print("Error took place \(error)")
            return
        }
        
        // Convert HTTP Response Data to a String
        if let data = data, let dataString = String(data: data, encoding: .utf8) {
            print("Response data string: \(dataString)")
        }
    }
    
    task.resume()

回应

request = https://us-central1-ryyde-sj.cloudfunctions.net/payout
postString = uid=kv8JRVBwAfS1tgD04lNeM9esVzI2&email=myiosapp@me.com
data: Optional(138 bytes)
response: Optional(<NSHTTPURLResponse: 0x6000037d1c20> { URL: https://us-central1-ryyde-sj.cloudfunctions.net/payout } { Status Code: 400, Headers {
"Content-Length" =     (
    138
);
"Content-Type" =     (
    "text/html; charset=utf-8"
);
Date =     (
    "Thu, 17 Sep 2020 01:00:50 GMT"
);
Server =     (
    "Google Frontend"
);
"alt-svc" =     (
    "h3-Q050=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""
);
"content-security-policy" =     (
    "default-src 'none'"
);
"function-execution-id" =     (
    cmrwbktlroxl
);
"x-cloud-trace-context" =     (
    "a85aaacd578e60690581aa64ead13b23;o=1"
);
"x-content-type-options" =     (
    nosniff
);
"x-powered-by" =     (
    Express
);
} })
error: nil
All headers: [AnyHashable("content-security-policy"): default-src 'none', 
AnyHashable("Date"): Thu, 17 Sep 2020 01:00:50 GMT, AnyHashable("alt-svc"): h3-Q050=":443"; 
ma=2592000,h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3- 
T050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; 
ma=2592000; v="46,43", AnyHashable("Content-Type"): text/html; charset=utf-8, 
AnyHashable("Content-Length"): 138, AnyHashable("x-cloud-trace-context"): 
a85aaacd578e60690581aa64ead13b23;o=1, AnyHashable("Server"): Google Frontend, 
AnyHashable("x-powered-by"): Express, AnyHashable("x-content-type-options"): nosniff, 
AnyHashable("function-execution-id"): cmrwbktlroxl]
Specific header: text/html; charset=utf-8
Response data string: <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Bad Request</pre>
</body>
</html>

如果请求成功,它将显示在以下链接的 PayPal 沙盒的 PayPal 通知中,但不是。

PayPal developer notifications link

我在 PayPal HTTP 请求方面没有太多经验。

我已经做了与我在这里尝试做的相同的事情,但在 Android 中它运行良好,所以我知道这应该可以工作,除了发布请求(我尝试使用在线示例来匹配我为 Android 应用程序所拥有的)

编辑

更新的 payoutRequest():

** ** 中的代码是新代码

let email = txtPayoutEmail.text!
    let uid = self.uid!

    // Prepare URL:
    let url = URL(string: "https://us-central1-ryyde-sj.cloudfunctions.net/payout")
    guard let requestUrl = url else { fatalError() }

    // Prepare URL Request Object:
    var request = URLRequest(url: requestUrl)
    request.httpMethod = "POST"

    // Set HTTP Request Headers
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue("Your Token", forHTTPHeaderField: "Authorization")
    request.setValue("no-cache", forHTTPHeaderField: "cache-control")

    print("request = \(request)")

    // HTTP Request Parameters which will be sent in HTTP Request Body:
    **let body = ["uid": uid, "email": email]** 
    print("body = \(body)")

    // Set HTTP Request Body
    **request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: [])**

    // Perform HTTP Request
    let task = URLSession.shared.dataTask(with: request) { (data, response, error ) in

        print("data: \(String(describing: data))")
        print("response: \(String(describing: response))")
        print("error: \(String(describing: error))")

        if let response = response as? HTTPURLResponse {
            // Read all HTTP Response Headers
            print("All headers: \(response.allHeaderFields)")
            // Read a specific HTTP Response Header by name
            if #available(iOS 13.0, *) {
                print("Specific header: \(response.value(forHTTPHeaderField: "Content-Type") ?? " header not found")")
            } else {
                // Fallback on earlier versions
            }
        }

        // Check for Errors
        if let error = error {
            print("Error took place \(error)")
            return
        }

        // Convert HTTP Response Data to a String
        if let data = data, let dataString = String(data: data, encoding: .utf8) {
            print("Response data string: \(dataString)")
        }
    }

    task.resume()

回应:

request = https://us-central1-ryyde-sj.cloudfunctions.net/payout
body = ["uid": "kv8JRVBwAfS1tgD04lNeM9esVzI2", "email": "driver@ryyde.com"]
data: Optional(0 bytes)
response: Optional(<NSHTTPURLResponse: 0x600001f0d6a0> { URL: https://us-central1-ryyde-sj.cloudfunctions.net/payout } { Status Code: 200, Headers {
    "Content-Length" =     (
        0
    );
    "Content-Type" =     (
        "text/html"
    );
    Date =     (
        "Thu, 17 Sep 2020 04:41:29 GMT"
    );
    Server =     (
        "Google Frontend"
    );
    "alt-svc" =     (
        "h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""
    );
    "function-execution-id" =     (
        cmrwtq89fdsr
    );
    "x-cloud-trace-context" =     (
        "f3fe884ca8499e7a10c7081ce222876e;o=1"
    );
    "x-powered-by" =     (
        Express
    );
} })
error: nil
All headers: [AnyHashable("Content-Length"): 0, AnyHashable("x-cloud-trace-context"): f3fe884ca8499e7a10c7081ce222876e;o=1, AnyHashable("Server"): Google Frontend, AnyHashable("x-powered-by"): Express, AnyHashable("function-execution-id"): cmrwtq89fdsr, AnyHashable("alt-svc"): h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43", AnyHashable("Date"): Thu, 17 Sep 2020 04:41:29 GMT, AnyHashable("Content-Type"): text/html]
Specific header: text/html
Response data string: 

编辑 2

当我运行我的代码时,我会检查 firebase/functions 中的函数日志(从下往上读取 - 函数活动似乎没问题)

编辑 3 - Charles 会议结果

URL https://us-central1-ryyde-sj.cloudfunctions.net 状态发送 请求正文... 备注 事务在会话被清除之前开始, 在会话清除之前传输的正文内容尚未被 捕获响应代码 200 连接已建立协议 HTTP/1.1 TLS TLSv1.2 (TLS_AES_128_GCM_SHA256) 协议 TLSv1.2 会话 已恢复 是 密码套件 TLS_AES_128_GCM_SHA256 ALPN - 客户端 证书 - 服务器证书 - 扩展方法 CONNECT 保留 Alive No Content-Type 客户端地址 127.0.0.1:57209 远程 地址 us-central1-ryyde-sj.cloudfunctions.net/216.239.36.54:443 标签 - 连接 WebSockets - 时间大小请求 1.77 KB (1,817 字节)响应 1.35 KB(1,379 字节)

编辑 4 - Android 代码

private void payoutRequest() {

    progress = new ProgressDialog(this);
    progress.setTitle("Processing your payout ...");
    progress.setMessage("Please Wait .....");
    progress.setCancelable(false);
    progress.show();

    // HTTP Request ....
    final OkHttpClient client = new OkHttpClient();

    // in json - we need variables for the hardcoded uid and Email
    JSONObject postData = new JSONObject();

    try {
        postData.put("uid", FirebaseAuth.getInstance().getCurrentUser().getUid());
        postData.put("email", mPayoutEmail.getText().toString());

    } catch (JSONException e) {
        e.printStackTrace();
    }

    // Request body ...
    RequestBody body = RequestBody.create(MEDIA_TYPE, postData.toString());

    // Build Request ...
    final Request request = new Request.Builder()
            .url("https://us-central1-ryyde-sj.cloudfunctions.net/payout")
            .post(body)
            .addHeader("Content-Type", "application/json")
            .addHeader("cache-control", "no-cache")
            .addHeader("Authorization", "Your Token")
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            // something went wrong right off the bat
            progress.dismiss();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            // response successful ....
            // refers to response.status('200') or ('500')
            int responseCode = response.code();
            if (response.isSuccessful()) {
                switch(responseCode) {
                    case 200:
                        Snackbar.make(findViewById(R.id.layout),
                                "Payout Successful!", Snackbar.LENGTH_LONG)
                                .show();
                        break;

                    case 500:
                        Snackbar.make(findViewById(R.id.layout),
                                "Error: no payout available", Snackbar
                                        .LENGTH_LONG).show();
                        break;

                    default:
                        Snackbar.make(findViewById(R.id.layout),
                                "Error: couldn't complete the transaction",
                                Snackbar.LENGTH_LONG).show();
                        break;
                }

            } else {
                Snackbar.make(findViewById(R.id.layout),
                        "Error: couldn't complete the transaction",
                        Snackbar.LENGTH_LONG).show();
            }

            progress.dismiss();
        }
    });
}

【问题讨论】:

  • 我建议使用Charles Proxy 之类的东西来查看您的工作 Android 请求和非工作 iOS 请求之间的区别。
  • 这是我没有遇到过的。它究竟是做什么的?它是否需要我的 android 代码并使其与 ios 代码兼容?
  • 哈哈,不,很遗憾没有。它是一种工具,可让您查看和检查所有网络请求和响应。您可以捕获您的 Android 请求和 iOS 请求,查看它们的原始标头和帖子正文等,这将使您可以比较它们以了解您在 iOS 端的问题所在。我强烈建议您学习如何使用它——它对于调试 http 请求问题非常有用,并且被 iOS 和 Android 开发人员广泛使用。
  • 我在 Charles Proxy 中运行了一个请求,并在 EDIT 3 中附加了结果。

标签: android ios paypal google-cloud-functions httprequest


【解决方案1】:

试试这个:

    let body = ["uid": uid,
                "email": email]
     
    request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: [])

【讨论】:

  • 我尝试了上述方法,仍然无法正常工作,请参阅上面的 EDIT 新代码和结果
  • 添加 EDIT 2 以在运行 payoutRequest 时显示函数活动 ...
  • @LizG 为什么它不起作用?您期望哪个响应状态代码?您的响应状态代码是 400,现在是 200。也许您缺少此功能范围之外的某些内容。
  • 我不认为它正在获取数据。我要放弃这个了
  • @halfer 这不是答案。我正在为我尝试在 iOS 中工作的请求发布 Android 代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
  • 2015-01-01
  • 1970-01-01
  • 2017-04-22
  • 2013-04-15
相关资源
最近更新 更多