0

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)
Cflux
  • 1,423
  • 3
  • 19
  • 39
  • 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 Feb 24 '20 at 07:26
  • 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 Feb 24 '20 at 10:02
  • @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 Feb 24 '20 at 13:36
  • @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. (https://stackoverflow.com/questions/60200609/android-stripe-connect-webview-create-account-form-not-loading) – Cflux Feb 24 '20 at 13:43
  • @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 Feb 25 '20 at 04:49
  • @floatingLomas, good eye, thank you for catching that one. I've updated my redirect url. however, I still get the `Test webhook error: 500` `Error: Invalid JSON received from the Stripe API`. After looking at the 1st comment, To answer your question, I have a Webhook set up on stripe to fire whenever a new user is created which is sent to my firebase cloud functions URL(which i may or may not have set up correctly) for now I'm just trying to get a 200 response and the auth code from Stripe URL when sending a test event to a webhook endpoint or actually creating a new user to test. – Cflux Feb 25 '20 at 14:19
  • @Cflux What happens when you log the request body? What are you receiving? Are you passing the raw request body (not parsed JSON) to `stripe.webhooks.constructEvent()`? – floatingLomas Feb 26 '20 at 04:28
  • @floatingLomas, I've updated my code in the question. See bottom of question beginning at "update 02/27/2020" it seems like i'm almost there – Cflux Feb 29 '20 at 17:34
  • I was getting `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 ` error because I didnt reset the webhook endpoint signing key when i created the new webook. I'm able to get the `request.rawbody` returned but I'm still getting the `request.body.code` returning `undefined` and then it times out. – Cflux Feb 29 '20 at 17:46
  • `req.rawBody` should be correct (https://cloud.google.com/functions/docs/writing/http#handling_content_types) and you should make sure your signing key is actually coming through properly; if you're using the raw body and the correct signing key for that webhook endpoint, it should work. – floatingLomas Mar 02 '20 at 01:20

0 Answers0