0
votes

I'm trying to get Stripe Express Connect to work with my Cloud Firebase Functions.

So far I've been able to set up my Android App to open up a browser and begin the signup process with some prefilled forms however once my client gets sent to the completed screen(using test mode) with the special URL, I cant retrieve the information from within that URL following the tutorial given. I get stuck at Step 4.

These are the sources I've been looking at for the past week but can't seem to put it together

1) https://firebase.google.com/docs/functions/http-events#using_existing_express_apps

2) Parameters in Firebase Cloud Functions HTTPS

3) Stripe Connect Firebase Functions

Currently, I have a webhook set up in Stripe and I get back responses whenever I manually execute my cloud function however with the success response returned, I cannot get my state or authorization code values.

-----------------update--------------------

here is the code I use to send them to the URL(the connect form that is filled out)

val openURL = Intent(Intent.ACTION_VIEW)
                    openURL.data = Uri.parse(
                            "https://connect.stripe.com/express/oauth/authorize?" +
                                    "redirect_uri=http://YourNeighborsBookshelf.com&" +
                                    "client_id=ca_32D88BD1XXXXXXXXXXXXXXXXXXXXXXXXXX&" +
                                    "state=" + mAuth.currentUser!!.uid +

                                    "&stripe_user[email]=" + userEmail +
                                    "&stripe_user[phone_number]=" + userPhoneNumberStripped +
                                    "#/")

                    startActivity(openURL)

----------end of update---------------

Here is the URL I'm trying to get the code and state values from

https://connect.stripe.com/connect/default/oauth/test?code=ac_XXXXXXXXXXXXXXXXX&state=YYYYYYYYYYYYYYY

This is the error I get in the Stripe Functions :

Test webhook error: 500
Response
Error: could not handle the request

This is the error I get in the firebase functions log:

Error: Invalid JSON received from the Stripe API
    at IncomingMessage.res.once (/srv/node_modules/stripe/lib/StripeResource.js:182:13)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:111:20)
    at IncomingMessage.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1064:12)
    at _combinedTickCallback (internal/process/next_tick.js:139:11)
    at process._tickDomainCallback (internal/process/next_tick.js:219:9)

Here is my code although im not too sure how to call this when the URL goes to the success/redirect URL:

exports.stripeCreateOathResponseToken = functions.https.onRequest((req, res) => {
    // res.send("code: " + req.query.code); // doesnt work here
    // res.send("state: " + req.query.state);  // doesnt work here


    return stripe.oauth.token({
        grant_type: 'authorization_code',
        // code: req.query.code, // doesnt work for some reason
        code: "<code given in url hardcoded>",  // first shows as "authorization code does not belong to you" then shows "code has expired" after trying again a few minutes later
        state: req.query.state,  // not sure if this is working

    // }).then(function (res) {
    }).then(function (response) {
        // asynchronously called

        // return res.send("code: " + res.query.code)
        return response.stripe_user_id;
        // return response.stripe_user_id; // this doesnt work
        // return request.query.code; // this doesnt work
    });

});

I've also tried this one which gives me a 200 success code but returns the values as undefined

exports.stripeCreateOathResponseToken = functions.https.onRequest(cores((req, res) => {

    const authCode = req.query.code;
    const stateCode = req.query.state;


    return res.send("code: " + req.query.code + " state: " + req.query.state);
    // return res.send("code: " + req.body.code + " state: " + req.body.state); // <-- doesnt work

    return res.send("\nauthCode: " + authCode + "\nstateCode: " + stateCode)
}));

Any and all help/direction is appreciated.

----------------------------update 02/27/2020-----------------------------

I think I've made some progress on the issue. I've gotten my webhook to fire correctly, see this post. I also now get the full request.rawbody response that I can see in both my stripe webhook dashboard and also the firebase cloud functions log.

One of the issues along the way was whenever I called response.send(), I would get an error saying response.send() is not a function although a lot of other sources showed response.send() being used. If anyone could shed more light on the matter, that would be helpful.

It seems like I have one last issue to get around hopefully. see below for the error.

code

const admin = require('firebase-admin');
// const database = admin.database();
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
const Chatkit = require('@pusher/chatkit-server');
const stripeToken = require('stripe')(functions.config().stripe.token);
const stripeWebhooks = require('stripe')(functions.config().keys.webhooks);
const express = require('express');
const cors = require('cors');
const endpointSecret = functions.config().keys.signing; //<-- is this correct?
const request = require('request-promise');
const app = express();

// Automatically allow cross-origin requests
app.use(cors({ origin: true }));


exports.stripeCreateOathResponseToken = functions.https.onRequest(cors((request, res) => {
    // Get the signature from the request header
    let sig = request.headers["stripe-signature"];

    let rawbody = request.rawBody;

    console.log("rawbody: " + rawbody);
    console.log("request.body: " + request.body);
    console.log("request.query.code: " + request.query.code);
    console.log("request.query.body: " + request.query.body);
    console.log("request.query.state: " + request.query.state);

    return stripeWebhooks.webhooks.constructEvent(request.rawBody, sig, endpointSecret);
}));

when running the above code, I now get this error:


Error: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing
    at Object.verifyHeader (/srv/node_modules/stripe/lib/Webhooks.js:117:13)
    at Object.constructEvent (/srv/node_modules/stripe/lib/Webhooks.js:12:20)
    at exports.stripeCreateOathResponseToken.functions.https.onRequest.cors (/srv/index.js:383:36)
    at corsMiddleware (/srv/node_modules/cors/lib/index.js:204:7)
    at cloudFunction (/srv/node_modules/firebase-functions/lib/providers/https.js:49:9)
    at /worker/worker.js:783:7
    at /worker/worker.js:766:11
    at _combinedTickCallback (internal/process/next_tick.js:132:7)
    at process._tickDomainCallback (internal/process/next_tick.js:219:9)
When you say 'sent to the completed screen', where are you sending them? You need to send them to some server-side code will process your exports.stripeCreateOathResponseToken function; is that what you're doing?floatingLomas
How do you pass to your Cloud Function the authorization code that you receive n Step 3 (of the Stripe workflow)?? This is not clear.Renaud Tarnec
@floatingLomas, I am sending them to the success/redirect URL. https://connect.stripe.com/connect/default/oauth/test?code=ac_XXXXXXXXXXXXXXXXX&state=YYYYYYYYYYYYYYY which is the test mode success page for when the user has succesfully signed up for Stripe Connect through their Express system. You can try the URL in your web browser and it will come up. In LIVEMODE, it would be my actual website's page.Cflux
@RenaudTarnec, I've updated my question's code with the information you've requested. For step 3, I have my android app open up a web browser through an intent with the necessary stripe information. I couldnt get a webview to work because it wouldnt load the [form], I created an SO question about it but still havent been able to figure it out. (stackoverflow.com/questions/60200609/…)Cflux
@Cflux That's the URL that they use to connect, it isn't meant as a redirect URL. You should put the URL of your Firebase app as the redirect URL.floatingLomas