При отправке данных из приложения в firebase-функции в PayPal электронное письмо с уведомлением не создается - PullRequest
0 голосов
/ 14 января 2019

У меня есть приложение в 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, она принимается и параметры принимаются.

firebase-function log

Кроме того, когда я захожу в PayPal Sandbox, был также получен API.

API Call

Но, если я пойду в https://developer.paypal.com/developer/notifications/ должно быть уведомление по электронной почте о том, что гонщик заплатил, но не было отправлено письмо с сообщением о выплате водителю - me@me.com

Я пробовал множество разных почтовых запросов, но все, что я пробовал, не сработало. Я попробовал учебники онлайн. Я слишком новичок в этом, чтобы понять, почему это не работает.

...