Why doesn't PayPal retain the data sent from p

2019-03-05 16:24发布

问题:

I have posted similar questions but until now, I am almost positive, the issue has something to do with iOS and PayPal.

I have an app with both Android and iOS on the same firebase project. The Android app works perfectly but when I try putting the equivalent code for the http request of the Android code in iOS, it is not getting to PayPal.

The http post request is sent to the firebase-function which then sends to PayPal, but the iOS code is being received by the function but not retained long enough to get to PayPal ... see below:

Android code

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

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

iOS code : Not reaching PayPal

struct Payout: Codable {
    var uid: String
    var email: String
}

func payoutRequest() {

        print("payoutRequest")

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

        //let 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 token = "A21AAG_Cxp8qmbIuKF8Ey6vKSrff6BIyt3lS0BYkOdZV7LanUP3AJ9E4O7VczLmd8q8wrsr3rCmdUQrSh4437lfnQFnd0W65g"

        let headers: HTTPHeaders = [
            "Content-Type": "application/json",
            "Authorization": "Bearer \(token)",
            "Accept": "application/json"
        ]

        var payout = Payout(uid: uid!, email: txtPayoutEmail.text!)
        payout.uid = (FIRAuth.auth()?.currentUser?.uid)!
        payout.email = txtPayoutEmail.text!

        guard let uploadData = try? JSONEncoder().encode(payout) else { return }

        var request = URLRequest(url: url!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
        request.httpMethod = "POST"
        request.allHTTPHeaderFields = headers
        request.httpBody = uploadData as Data

        let task = URLSession.shared.uploadTask(with: request, from: uploadData) { (data, response, error) in

            if let error = error {
                print("error: \(error)")
                return
            }

            guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                    print("server error")
                    return
            }

            let parsedObject = try! JSONSerialization.jsonObject(with: uploadData, options: .allowFragments)
            print(parsedObject)
        }

        task.resume()
    }

index.js file located in firebase function:

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

How it works vs how it's supposed to work:

In the controller (iOS) the person enters their PayPal email in a textview and then selects GET PAYOUT - payoutRequest() is then executed.

As you can see from log below, it receives both the uid and email, payout is created:

Firebase-Functions log:

The next step would be to go to developer.paypal.com, log into dashboard and check notifications for the drivers PayPal email address, stating that a payment has been received.

As the image shows below, the Android app shows this notification:

but the notification for the iOS app does not show anything like it wasn't received.

And, if I go into the API calls for Sandbox, it shows that an api call was made successfully:

Then, the next day, I get this in firebase-functions (it says 8pm but didn't get this til next day) - basically saying that the email received is null: