【问题标题】:How to pass data through firebase-functions to Paypal?如何通过firebase-functions将数据传递给Paypal?
【发布时间】:2019-05-28 13:10:06
【问题描述】:

我在同一个 Firebase 项目上的 Android 和 iOS 上都有一个应用。该应用程序的最后一部分是将数据从我的应用程序发送到 firebase-function,然后发送到 PayPal。它适用于Android,但不适用于iOS。请看下面的代码。

我什至与 PayPal 谈过,但他们认为这是 iOS 代码。我在 GitHub、PayPal、Stack Overflow 等有帖子,但看不到任何解决方案。

基本上,当我按下按钮 - GET PAYOUT 时,将执行 payoutRequest() 方法。它应该将“uid”和“电子邮件”发送到函数,然后发送到 PayPal。

PayPal SDK 包含在函数中。

它不会将数据发送到 PayPal,但它在函数中被识别(https 函数不是可调用函数)

Android 代码工作

public static final MediaType MEDIA_TYPE = MediaType.parse("application/json"); ProgressDialog progress;

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();
    }
});
}

Firebase 函数:index.js

'use strict';
const functions = require('firebase-functions');
const paypal = require('paypal-rest-sdk');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

paypal.configure({
    mode: 'sandbox',
    client_id: functions.config().paypal.client_id,
    client_secret: functions.config().paypal.client_secret
})

exports.newRequest = functions.database.ref('/history/{pushId}').onCreate((snapshot, context) => {
    var requestSnapshot = snapshot.val();
    var price  = snapshot.child('price').val();
    var pushId = context.params.pushId;

    return snapshot.ref.parent.child(pushId).child('price').set(price);
 });


function getPayoutsPending(uid) {
    return admin.database().ref('Users/Drivers/' + uid + '/history').once('value').then((snap) => {
        if(snap === null){
            throw new Error("profile doesn't exist");
        }
        var array = [];
        if(snap.hasChildren()){
            snap.forEach(element => {
                if (element.val() === true) {
                    array.push(element.key);
                }
            });
        }
        return array;
    }).catch((error) => {
        return console.error(error);
    });
}

function getPayoutsAmount(array) {
    return admin.database().ref('history').once('value').then((snap) => {
        var value = 0.0;
        if(snap.hasChildren()){
            snap.forEach(element => {
                if(array.indexOf(element.key) > -1) {
                        if(element.child('price').val() !== null){
                            value += element.child('price').val();
                        }
                }
            });
            return value;
        }
        return value;
    }).catch((error) => {
        return console.error(error);
    });
}

function updatePaymentsPending(uid, paymentId) {
    return admin.database().ref('Users/Drivers/' + uid + '/history').once('value').then((snap) => {
        if(snap === null){
            throw new Error("profile doesn't exist");
        }

        if(snap.hasChildren()){
            snap.forEach(element => {
                if(element.val() === true) {
                    admin.database().ref('Users/Drivers/' + uid + '/history/' + element.key).set( {
                        timestamp: admin.database.ServerValue.TIMESTAMP,
                        paymentId: paymentId
                    });
                    admin.database().ref('history/' + element.key + '/driverPaidOut').set(true);
                }
            });
        }
        return null;
    }).catch((error) => {
        return console.error(error);
    });
}

exports.payout = functions.https.onRequest((request, response) => {
    return getPayoutsPending(request.body.uid)
        .then(array => getPayoutsAmount(array))
        .then(value => {
            var valueTrunc = parseFloat(Math.round((value * 0.75) * 100) / 100).toFixed(2);
            const sender_batch_id = Math.random().toString(36).substring(9);
            const sync_mode = 'false';
            const payReq = JSON.stringify({
                sender_batch_header: {
                    sender_batch_id: sender_batch_id,
                    email_subject: "You have a payment"
                },
                items: [
                    {
                        recipient_type: "EMAIL",
                        amount: {
                            value: valueTrunc,
                            currency: "CAD"
                        },
                        receiver: request.body.email,
                        note: "Thank you.",
                        sender_item_id: "Payment"
                    }
                ]
            });

            return paypal.payout.create(payReq, sync_mode, (error, payout) => {
                if (error) {
                    console.warn(error.response);
                    response.status('500').end();
                    throw error;
                }
                console.info("uid: " + request.body.uid + " email: " + request.body.email) // testing
                console.info("payout created");
                console.info(payout);
                return updatePaymentsPending(request.body.uid, sender_batch_id)
            });
        }).then(() => {
            response.status('200').end();
            return null;
        }).catch(error => {
            console.error(error);
        });
});

IOS 代码:payoutRequest()

var params: Parameters = ["uid": FIRAuth.auth()?.currentUser!.uid as Any, "email": txtPayoutEmail.text!]

    let url = URL(string: "https://us-central1-ryyde-sj.cloudfunctions.net/payout")

    let headers: HTTPHeaders = [
        "Content-Type": "application/json",
        "Authorization": "Your Token",
        "cache-control": "no-cache"
    ]

    let request = NSMutableURLRequest(url: url!)
    let session = URLSession.shared
    request.httpMethod = "POST"
    params = params as! Dictionary<String, String>
    request.httpBody = try! JSONSerialization.data(withJSONObject: params, options: [])
    request.allHTTPHeaderFields = headers

    let task = session.dataTask(with: request as URLRequest) { data, response, error in
        guard data != nil, error == nil else {
            print("no data found: \(String(describing: error))")
            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
            print("status code: \(httpStatus.statusCode)")
            print("response: \(String(describing: response))")
        }

        let jsonData = try? JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
        let parsedObject = try! JSONSerialization.jsonObject(with: jsonData!, options: .allowFragments)
        print(parsedObject)
    }

    task.resume()

会发生什么

当方法(payoutRequest())被执行时,Firebase Function中的日志显示'uid'和'email'参数被保留:

在控制台第3行可以看到,uid和email参数被保留了。

接下来发生的事情是将数据(参数)发送到 Paypal,并发送通知到电子邮件地址,说明已收到付款,如下所示:

但没有这样的通知。

如果我检查沙盒的 API 调用,我会看到:

然后 4 小时到一天后,我在日志中收到此错误,基本上,它被退回,因为 PayPal 没有保留发送的数据:

【问题讨论】:

  • 这和your last question本质上是不是一样的问题?
  • 是的,仍然没有解决。我在 apple.stackexchange 上开了一个帖子,认为他们可以提供帮助。
  • 我不认为他们在那里接受编程问题。事实上,如果您在网络上的多个地方交叉发布问题,请在每个地方都包含指向所有其他地方的链接。这将允许读者检查您的任何重复项是否已被回答,以防止他们在您已经在其他地方找到答案时浪费时间。
  • 好的,谢谢你告诉我。还在学习哈哈
  • 您使用的是哪个 Firebase 付款计划?火花、火焰还是烈焰? firebase.google.com/pricing

标签: ios paypal google-cloud-functions


【解决方案1】:

您在 iOS 代码中遇到的一个问题是 params 的值应该是 [String: String] 类型(这是 POST 数据所需的类型)。

我特指这一行:

var params: Parameters = ["uid": FIRAuth.auth()?.currentUser!.uid as Any, "email": txtPayoutEmail.text!]

尝试将 uid 转换为 String:

var params: Parameters = ["uid": FIRAuth.auth()?.currentUser!.uid as String, "email": txtPayoutEmail.text!]

【讨论】:

  • 好的,我按照你的建议做了,但最终结果没有区别。另外,如果我打印出数据 --> 0 个字节
  • 很奇怪。您可以尝试使用JSONEncoder().encode() 编码params 吗?
  • 这就是我所做的: do { let jsonEncoder = JSONEncoder() let jsonData = try jsonEncoder.encode(params) let jsonString = String(data: jsonData, encoding: .utf8) print("jsonString : (jsonString ?? "")") } catch { print("Unexpected error: (error)") } 结果 :: jsonString: {"uid":"o2a30PjFufSBYtSIUR5UWFpwPcr1","email":"me@me.com" }
  • 它是否解决了问题,不幸的是没有。我放在正确的位置了吗?我把上面的代码放在代码“let task = session....”的上方
猜你喜欢
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 2012-11-07
  • 2023-01-18
  • 2016-05-30
  • 1970-01-01
相关资源
最近更新 更多