0

I'm working on a project where I need to pass a stripe key as JSON in Angular.

I added the key to Heroku in Config vars and have been trying to pass that value through the Node.js backend to Angular with the process.env.STRIPE_KEY method that was stated in the Heroku tutorial. I am completely lost and am unsure if I am going at this the correct way.

Here is my node server file.

//server.js
const express = require('express');
const app = express();
const bodyParser = require("body-parser");
const router = express.Router();


app.use(express.static(__dirname + '/dist'));
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({extended: true}));

app.listen(3000, function(){});

router.all('*',function(req,res,next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
  res.header("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS");
  next();

});



router.post('/stripetestkey', function(req, res) {
  res.json({
    'STRIPE_TEST_API_KEY': process.env.STRIPE_KEY
  });
});


module.exports = router;

Here is the Service provider (in app modules and injected properly)getting the key from the server

//service.ts

import {Injectable} from "@angular/core";
import {Http, Headers} from "@angular/http";
import 'rxjs/add/operator/map';
import {Observable} from "rxjs";

@Injectable()
export class KeyService {
  constructor(private http: Http) {}

  private getError(error: Response): Observable<any>{
    console.log(error);
    return Observable.throw(error.json() || 'Server Issue');
  }

  getKey(): Observable<any> {
    let headers = new Headers();
    headers.append('Content-type', 'application/json');
    return this.http.get('http://localhost:3000/stripetestkey',{ headers: headers })
      .map(res => res.json())
      .catch(this.getError);
  }


}

And here is the code I have for opening Stripe checkout with the proper key

 openCheckout() {
    this.keyService.getKey().subscribe(data => this.stripeTestKey = data.STRIPE_TEST_API_KEY);
    let handler = (<any>window).StripeCheckout.configure({
      key: this.stripeTestKey,
      locale: 'auto',
      token: function (token: any) {

      }
    });
    handler.open({
      name: 'XXXXXX',
      description: 'Donation',
      amount: (this.donation * 100)
    });
  }

I've been getting HTML back instead of JSON and am just unsure if I'm even going at this correctly. I've also tried passing JSON instead of process.env.STRIPE_KEY. Can anyone let me know what I need to do to pass a heroku config var through node.js to my angular app?

Thanks!

P.S. here is the error I am receiving ..

Failed to load resource: the server responded with a status of 404 (Not Found)
main.bundle.js:32 Response
vendor.bundle.js:1443 ERROR SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at Response.Body.json 

UPDATE ** I changed res.send to res.json in server.js and here is the updated error I am getting.

keys.service.ts:11 Response {_body: "<!DOCTYPE html>↵<html lang="en">↵<head>↵<meta char…body>↵<pre>Cannot GET /stripetestkey</pre>↵</body>↵</html>↵", status: 404, ok: false, statusText: "Not Found", headers: Headers…}


core.es5.js:1084 ERROR SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at Response.Body.json (http.es5.js:796)

UPDATE #2 ******* I've changed router.post to router.get in server.js. I'm still getting the same error stated above. I tried passing the key directly as an object

router.get('/stripetestkey', function(req, res) {
  res.json({
    'STRIPE_TEST_API_KEY': 'pk_test_XXXXXXXXXXXXXXXXXX'
  });
});

and Stripe returned this error for me.

StripeCheckout.configure: Type mismatch for option 'key':
Looking for type 'string', but instead we found 'object'.
You can learn about the available configuration options in the Checkout docs:

Checking out the docs now.

**** Still Struggling here

enter image description here

****UPDATE (so many) Changed http://localhost:3000/stripetestkey to https://localhost:3000/keys (also changed server side to /keys for correct routing (easier to follow).

OPTIONS https://localhost:3000/keys net::ERR_CONNECTION_CLOSED
scheduleTask @ zone.js:1990
webpackJsonp.585.ZoneDelegate.scheduleTask @ zone.js:384
onScheduleTask @ zone.js:274
webpackJsonp.585.ZoneDelegate.scheduleTask @ zone.js:378
webpackJsonp.585.Zone.scheduleTask @ zone.js:209
webpackJsonp.585.Zone.scheduleMacroTask @ zone.js:232
(anonymous) @ zone.js:2014
send @ VM1198:3
(anonymous) @ http.es5.js:1254
Observable._trySubscribe @ Observable.js:57
Observable.subscribe @ Observable.js:45
MapOperator.call @ map.js:54
Observable.subscribe @ Observable.js:42
CatchOperator.call @ catch.js:79
Observable.subscribe @ Observable.js:42
webpackJsonp.237.NavbarComponent.openCheckout @ navbar.component.ts:74
(anonymous) @ NavbarComponent.html:40
handleEvent @ core.es5.js:11798
callWithDebugContext @ core.es5.js:13006
debugHandleEvent @ core.es5.js:12594
dispatchEvent @ core.es5.js:8773
(anonymous) @ core.es5.js:9363
(anonymous) @ platform-browser.es5.js:2683
webpackJsonp.585.ZoneDelegate.invokeTask @ zone.js:398
onInvokeTask @ core.es5.js:4116
webpackJsonp.585.ZoneDelegate.invokeTask @ zone.js:397
webpackJsonp.585.Zone.runTask @ zone.js:165
ZoneTask.invoke @ zone.js:460
keys.service.ts:11 

1 Answer 1

1

Use res.json() instead of res.send()

router.post('/stripetestkey', function(req, res) {
  res.json({
    'KeyCode': process.env.STRIPE_KEY
  });
});

Link to express documention on res.json(): https://expressjs.com/en/api.html#res.json

EDIT per the 404 error you are getting:

Make sure you are requesting the same resource with the same verb (GET, POST, etc.) as your router is defining. In your case, you are defining a POST request in ExpressJS, but your client is trying to GET the request which doesn't exist per your router (this.http.get() in your .ts file)

Your new route will be:

router.get('/stripetestkey', function(req, res) {
  res.json({
    'KeyCode': process.env.STRIPE_KEY
  });
});

UPDATE to help illustrate how to ensure this.stripeTestKey is set before handler.open()

Because this.keyService.getKey().subscribe() is async, handler.open() is getting called before you set the this.stripTestKey. You can do something similar to the following to fix it in your .subscribe() callback:

openCheckout() {
  this.keyService.getKey().subscribe(data => {
    this.stripeTestKey = data.STRIPE_TEST_API_KEY

    let handler = (<any>window).StripeCheckout.configure({
      key: this.stripeTestKey,
      locale: 'auto',
      token: function (token: any) {

      }
    });
    handler.open({
      name: 'XXXXXX',
      description: 'Donation',
      amount: (this.donation * 100)
    });
  });
}
Sign up to request clarification or add additional context in comments.

17 Comments

I changed res.send to res.json but still got an error. See above for edits in error.
Sorry didn't notice that you were trying to GET from the client but you're Express router is defining a POST request. Can you use router.get() instead of router.post() -- router.get('/stripetestkey', function(req, res) { res.json({ 'KeyCode': process.env.STRIPE_KEY }); });
I changed as you stated. I'm still getting the same error. I tried passing the key directly in the object in a dev environment and got the error given by Stripe above. I may be missing something else, I'm just unsure of what that is.
If you're returning JSON, and then parsing the JSON, you need to get the appropriate key for that JSON. So if your server is returning the JSON object {"KeyCode", "value"}, the following needs to get KeyCode from the returned object: So the following this.keyService.getKey().subscribe(data => this.stripeTestKey = data); turns into this.keyService.getKey().subscribe(data => this.stripeTestKey = data.KeyCode);
Also, the errors above ({_body: "<!DOCTYPE html>↵<html lang="en">↵<head>↵<meta char…body>↵<pre>Cannot GET /key</pre>↵</body>↵</html>↵", status: 404...) indicates you're trying to request the /key route which isn't the route you are sending the KeyCode in. It's /stripetestkey that your setting up in your router, so the client needs to request that route.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.