braintree / braintree_node

Braintree Node.js library
https://developer.paypal.com/braintree/docs/start/overview
MIT License
334 stars 104 forks source link

Unable to create test Payment method or Customer #132

Closed rapidmon17 closed 6 years ago

rapidmon17 commented 6 years ago

Hi, I am currently in Sandbox mode. I am able to obtain the paymentNonce from the DropIn. However, when I tried to create a paymentMethod, it appeared to work. But there was no vault showing up on the Braintree sandbox dashboard when I did a search for vaults created today. Here is the code used in creating a paymentMethod.


Meteor.methods({
    'braintreeAPI.createPaymentMethod'(nonce){
        gateway.paymentMethod.create({
            paymentMethodNonce: nonce,
            options: {
                verifyCard: true
            }
        }, function (err, result) { 
            if(err){
                console.log(`Error ${err}`);
            } else {
                console.log(`Result ${result.paymentMethodToken}`);
            }
        });
    }
});

So I decided that maybe I needed to create a customer first. And that didn't work. I got an Authorization Error.

authorizationError: Authorization Error

Here is my code below.

Meteor.methods({
    'braintreeAPI.createPaymentMethod'(nonce){
        gateway.customer.create({
            id:this.userId,
            paymentMethodNonce: nonce,
            options: {
                verifyCard: true
            }
        }, function (err, result) { 
            if(err){
                console.log(`Error ${err}`);
            } else {
                console.log(`Result ${result.paymentMethodToken}`);
            }
        });
    }
});

Below is my client code.

import React from 'react';
import axios from 'axios';

import {Link} from 'react-router-dom';
import { Meteor } from 'meteor/meteor';
import PrivateHeader from '../ui/LinkComponents/PrivateHeader';
import DropIn from "braintree-web-drop-in-react";

export default class Payment extends React.Component {
instance;

    state = {
        clientToken: null
    };

    componentDidMount() {
        axios.get('/setupBraintree')
        .then(res => {
            const clientToken = res.data;
            //console.log(`Client side value for token ${clientToken}`);
            this.setState({clientToken})
        })
    }

    async add() {
        // Send the nonce to  server
        const { nonce } = await this.instance.requestPaymentMethod();        
        Meteor.call('braintreeAPI.createPaymentMethod', nonce, (err, res) => {
            if(!err){
                console.log(res);
            } else {
                console.log(err);
            }
         });

    }

    render() {
        if (!this.state.clientToken) {
            return (
                <div>
                    <PrivateHeader title="Payment setup"/>
                    <h1>Loading...</h1>
                </div>
            );
        } else {
            return (
                <div>
                    <PrivateHeader title="Payment setup"/>
                    <DropIn
                        options={{ authorization: this.state.clientToken }}
                        onInstance={instance => (this.instance = instance)}
                    />
                    <button className="button" onClick={this.add.bind(this)}>Add Payment source</button>
                </div>
            );
        }
    }
}

Am I missing something? I am in sandbox mode, I could really use a clue. And I have admin authorization on my Braintree sandbox account.

quinnjn commented 6 years ago

Your client side code sounds correct by the fact that you're getting a nonce back 👍 I'm assuming you're using the same gateway object to create a Client Token so I'm ruling out the thought that your server side credentials might be incorrect.

Your first snippet would fail because you're missing customerId which is a required param for creating a payment method: https://developers.braintreepayments.com/reference/request/payment-method/create/node

Your second snippet would fail because your options param needs to be nested under creditCard: https://developers.braintreepayments.com/reference/request/customer/create/node#card-verification

You are getting authorizationError probably because of that missing customerId param. You're probably also seeing that for the gateway.paymentMethod.create call as well.

quinnjn commented 6 years ago

The authorization error is misleading. We are tracking the issue in #129.

rapidmon17 commented 6 years ago

Thank you! Turns out my request structure was a bit off. I corrected it and it worked.

Meteor.methods({
    'braintreeAPI.createPaymentMethod'(nonce){
        console.log(`UserID on server side ${this.userId}`);
        gateway.customer.create({
            Id:this.userId,
            paymentMethodNonce: nonce,
            creditCard: {
                options: {
                  verifyCard: true
                }
            }
        }, function (err, result) { 
            if(err){
                console.log(`Error ${err}`);
            } else {
                var paymentToken = result.customer.paymentMethods[0].token;
                addPaymentToken(this.userId, paymentToken);
                console.log(`Results ${result.customer.paymentMethods[0].token}`);
            }
        });
    }
});

I am glad you guys are adding more context to Authorization Error.