首页 > 解决方案 > 将数据从应用程序发送到 firebase-functions 到 PayPal 时,未创建通知电子邮件

问题描述

我在firebase中有一个应用程序,我试图将参数发送到firebase-functions中的函数,该函数发送到PayPal,但它不起作用。

func payoutRequest() {

    print("payoutRequest")

    let driver_uid = self.uid!
    let email = txtPayoutEmail.text!
    let url = "https://us-central1-ryyde-sj.cloudfunctions.net/payout"

    let paypal_token = "mytoken"

    let params : Parameters = [
        "uid": driver_uid,
        "email": email
    ]

    let headers : HTTPHeaders = [
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Authorization": "\(paypal_token)",
        "cache-control": "no-cache"
    ]

    Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in


        print("Request: \(String(describing: response.request))")   // original url request
        print("Response: \(String(describing: response.response))") // http url response
        print("Result: \(response.result)") // response serialization result


        switch response.result {
        case .success(let value):
            print(value)

            if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
                print("Data: \(utf8Text)") 
            }

        case .failure(let error):
            print("Error while querying database: \(String(describing: error))")
            return
        }
    }
}

*以上代码的结果

payoutRequest
Request: Optional(https://us-central1-ryyde-sj.cloudfunctions.net/payout)
Response: Optional(<NSHTTPURLResponse: 0x6000010109a0> { URL: https://us-central1-ryyde-sj.cloudfunctions.net/payout } { Status Code: 200, Headers {
    "Content-Length" =     (
        0
    );
    "Content-Type" =     (
        "text/html"
    );
    Date =     (
        "Sun, 13 Jan 2019 23:37:26 GMT"
    );
    Server =     (
        "Google Frontend"
    );
    "alt-svc" =     (
        "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
    );
    "function-execution-id" =     (
        1fcniah306ur
    );
    "x-cloud-trace-context" =     (
        "b4cb4d1470906270abb0b04efa99ea37;o=1"
    );
    "x-powered-by" =     (
        Express
    );
} })
Result: FAILURE
Error while querying database: responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)

firebase 功能 - 支出:

'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 payout!"
                },
                items: [
                    {
                        recipient_type: "EMAIL",
                        amount: {
                            value: valueTrunc,
                            currency: "CAD"
                        },
                        note: "Thank you.",
                        sender_item_id: "Payout",
                        receiver: request.body.email
                    }
                ]
            });

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

编辑#1

根据我研究过的其他请求,我稍微更改了 payoutRequest()。它带有一个。200 状态码,但仍未在 PayPal 上收到付款通知:

func payoutRequest() {

    print("payoutRequest")

    //Progress View
    self.progress.progress = value
    self.perform(#selector(updateProgressView), with: nil, afterDelay: 1.0)

    let email = txtPayoutEmail.text!

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

    let params : [String: Any] = [
        "uid": self.uid!,
        "email": email
    ]

    let headers : HTTPHeaders = [
        "Content-Type": "application/json",
        "Authorization": "my token",
        "Cache-Control": "no-cache"
    ]

    let myData = try? JSONSerialization.data(withJSONObject: params, options: [])
    print("data: \(String(describing: myData))")

   Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers)
        .validate(statusCode: 200..<300)
        .validate(contentType: ["application/json"])
        .responseData(completionHandler: { (response) in

        //print("Request: \(String(describing: response.request))")   // original url request
        //print("Response: \(String(describing: response.response))") // http url response
        print("Result: \(response.result)")                         // response serialization result

        switch response.result {
        case .success:
            print("Validation Successful")
            let parsedObject = try! JSONSerialization.jsonObject(with: myData!, options: .allowFragments)
            print("parsed: \(parsedObject)")

        case .failure(let error):
            print(error)
        }
    })
}

我从印刷品中得到的回应是:

payoutRequest
data: Optional(58 bytes)
Result: SUCCESS
Validation Successful
parsed: {
    email = "me@me.com";
    uid = o2a30PjFufSBYtSIUR5UWFpwPcr1;
}

正如您从 firebase-function 中看到的那样,它被接受并收到了参数。

firebase 功能日志

另外,当我进入 PayPal Sandbox 时,也收到了 api。

API 调用

但是,如果我进入https://developer.paypal.com/developer/notifications/ ,应该会收到一封通知电子邮件,说明乘客已付款,但没有电子邮件说明已向司机发送付款 - me@me.com

我尝试了许多不同的帖子请求,但无论我尝试过什么都没有奏效。我试过网上教程。我对此太陌生,无法理解为什么它不起作用。

标签: iosswifthttp-postalamofire

解决方案


推荐阅读