Search code examples
typescriptrestionic-frameworkbraintreebraintree-sandbox

Runtime Error: Class extends value [object Object] is not a constructor or null


I want to replicate a braintree demo app using ionic 3.

I have imported braintree with... import * as braintree from 'braintree';

but I am not able to connect to braintree.

The message reads... "Runtime Error: Class extends value [object Object] is not a constructor or null"

This is the code in my ts file

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, ViewController } from 'ionic-angular';

import * as braintree from 'braintree';

@IonicPage()
@Component({
  selector: 'page-apply',
  templateUrl: 'apply.html',
})

export class ApplyPage {

  gateway: any;

  constructor(public navCtrl: NavController, public navParams: NavParams, public viewCtrl: ViewController) {
    this.gateway = braintree.connect({
      environment:  braintree.Environment.Sandbox,
      merchantId:   'personalMerchantId',
      publicKey:    'personalPublicKey',
      privateKey:   'personalPrivateKey'
    });
  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad ApplyPage');
  }


}

This is the code within the index.js file of the module

'use strict';

module.exports = require('./lib/braintree');

And this code sits in the braintree.js file of which index.js points to

'use strict';

let version = require('../package.json').version;
let Config = require('./braintree/config').Config;
let Environment = require('./braintree/environment').Environment;
let BraintreeGateway = require('./braintree/braintree_gateway').BraintreeGateway;
let errorTypes = require('./braintree/error_types').errorTypes;

let Transaction = require('./braintree/transaction').Transaction;

let CreditCard = require('./braintree/credit_card').CreditCard;
let PayPalAccount = require('./braintree/paypal_account').PayPalAccount;
let AndroidPayCard = require('./braintree/android_pay_card').AndroidPayCard;
let ApplePayCard = require('./braintree/apple_pay_card').ApplePayCard;
let VenmoAccount = require('./braintree/venmo_account').VenmoAccount;
let CoinbaseAccount = require('./braintree/coinbase_account').CoinbaseAccount;
let AmexExpressCheckoutCard = require('./braintree/amex_express_checkout_card').AmexExpressCheckoutCard;
let VisaCheckoutCard = require('./braintree/visa_checkout_card').VisaCheckoutCard;
let MasterpassCard = require('./braintree/masterpass_card').MasterpassCard;

let CreditCardVerification = require('./braintree/credit_card_verification').CreditCardVerification;
let Subscription = require('./braintree/subscription').Subscription;
let MerchantAccount = require('./braintree/merchant_account').MerchantAccount;
let PaymentInstrumentTypes = require('./braintree/payment_instrument_types').PaymentInstrumentTypes;
let WebhookNotification = require('./braintree/webhook_notification').WebhookNotification;
let TestingGateway = require('./braintree/testing_gateway').TestingGateway;
let ValidationErrorCodes = require('./braintree/validation_error_codes').ValidationErrorCodes;

let CreditCardDefaults = require('./braintree/test/credit_card_defaults').CreditCardDefaults;
let CreditCardNumbers = require('./braintree/test/credit_card_numbers').CreditCardNumbers;
let MerchantAccountTest = require('./braintree/test/merchant_account').MerchantAccountTest;
let Nonces = require('./braintree/test/nonces').Nonces;
let TransactionAmounts = require('./braintree/test/transaction_amounts').TransactionAmounts;

let connect = config => new BraintreeGateway(new Config(config)); // eslint-disable-line func-style
let Test = {
  CreditCardDefaults: CreditCardDefaults,
  CreditCardNumbers: CreditCardNumbers,
  MerchantAccountTest: MerchantAccountTest,
  Nonces: Nonces,
  TransactionAmounts: TransactionAmounts
};

module.exports = {
  connect: connect,
  version: version,
  Environment: Environment,
  errorTypes: errorTypes,

  Transaction: Transaction,

  CreditCard: CreditCard,
  PayPalAccount: PayPalAccount,
  AndroidPayCard: AndroidPayCard,
  ApplePayCard: ApplePayCard,
  VenmoAccount: VenmoAccount,
  CoinbaseAccount: CoinbaseAccount,
  AmexExpressCheckoutCard: AmexExpressCheckoutCard,
  VisaCheckoutCard: VisaCheckoutCard,
  MasterpassCard: MasterpassCard,

  CreditCardVerification: CreditCardVerification,
  Subscription: Subscription,
  MerchantAccount: MerchantAccount,
  PaymentInstrumentTypes: PaymentInstrumentTypes,
  WebhookNotification: WebhookNotification,
  TestingGateway: TestingGateway,
  ValidationErrorCodes: ValidationErrorCodes,

  Test: Test
};

And this is the code that sits in the index.js file of the working ExpressJs Demo

var express = require('express');
var router = express.Router();
var braintree = require('braintree');

var gateway = braintree.connect({
    environment:  braintree.Environment.Sandbox,
    merchantId:   'personalMerchantID',
    publicKey:    'personalPublicKey',
    privateKey:   'personal_PrivateKey'
});

router.get('/', function(req, res) {
  gateway.clientToken.generate({}, function(err, response) {
    var token = response.clientToken;

    res.render('index', {token : token});
  });
});

router.post('/add', function(req, res) {

  var merchant_id = req.body.merchant_id;
  var bank_account = req.body.bank_account;
  var bank_routing = req.body.bank_routing;

  var merchantAccountParams = {
    individual: {
      firstName: "Jane",
      lastName: "Doe",
      email: "[email protected]",
      phone: "5553334444",
      dateOfBirth: "1981-11-19",
      ssn: "456-45-4567",
      address: {
        streetAddress: "111 Main St",
        locality: "Chicago",
        region: "IL",
        postalCode: "60622"
      }
    },
    funding: {
      destination: braintree.MerchantAccount.FundingDestination.Bank,
      accountNumber: bank_account,
      routingNumber: bank_routing
    },
    tosAccepted: true,
    masterMerchantAccountId: "_my_personal_master_merchant_account_ID",
    id: merchant_id
  };

  gateway.merchantAccount.create(merchantAccountParams, function (err, result) {
    res.render('addResult', {result: result});
  });

});

router.get('/find', function(req, res) {
  var merchant_id = req.query.merchant_id;

  gateway.merchantAccount.find(merchant_id, function(err, result) {
    res.render('findResult', {result: result, merchant_id: merchant_id});
  });

});

router.post('/process', function(req, res) {
  var nonce = req.body.payment_method_nonce;
  var total = req.body.total;
  var service = req.body.service;
  var merchant_id = req.body.merchant_id;

  gateway.transaction.sale({
    amount: total,
    merchantAccountId: merchant_id,
    paymentMethodNonce: nonce,
    serviceFeeAmount: service
  }, function (err, result) {
    res.render('processResult', {result: result});
  });
});

module.exports = router;

Again the above code was produced by braintree. I am sure for demo purposes only.


Solution

  • You should not do this.

    By including the Braintree node server library in the mobile client, you are exposing your private key to anyone who is using the app. This is highly insecure.

    Instead, you should have a server where you can accept a nonce generated by your app to process transactions. The Braintree Cordova Plugin that @Sampath posted looks like a reasonable way to generate a nonce in your app.