Aimee Casden
Aimee Casden

Reputation: 21

Is there a way to put a paypal script tag inside a button using reactjs?

I am working on implementing smart buttons for a PayPal widget and I was wondering how to go about doing this. My idea right now is to make a button and see if I can fit a script tag inside it that would lead me to make a payment. This is my code so far:

This is from the index.js file

<button>Donate Here Plz</button>

this is the reactjs file that was already written before I hopped on the project.

import ReactDOM from "react-dom";
import scriptLoader from "react-async-script-loader";

class PaypalButton extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      showButton: false,
      price: 1.0,
      priceError: true
    };

    window.React = React;
    window.ReactDOM = ReactDOM;
  }

  componentDidMount() {
    const { isScriptLoaded, isScriptLoadSucceed } = this.props;

    if (isScriptLoaded && isScriptLoadSucceed) {
      this.setState({ showButton: true });
    }
  }

  handleInputChange = e => {
    const re = /^\d*\.?\d{0,2}$/;

    if (e.target.value === "" || re.test(e.target.value)) {
      this.setState({ price: e.target.value });
    }
    if (this.state.price >= 1) {
      this.state.priceError = false;
    } else {
      this.state.priceError = true;
    }
    console.log(this.state.priceError);
  };

  componentWillReceiveProps(nextProps) {
    const { isScriptLoaded, isScriptLoadSucceed } = nextProps;

    const isLoadedButWasntLoadedBefore =
      !this.state.showButton && !this.props.isScriptLoaded && isScriptLoaded;

    if (isLoadedButWasntLoadedBefore) {
      if (isScriptLoadSucceed) {
        this.setState({ showButton: true });
      }
    }
  }

  render() {
    const paypal = window.PAYPAL;
    const {
      currency,
      env,
      commit,
      client,
      onSuccess,
      onError,
      onCancel
    } = this.props;

    const { showButton, price } = this.state;

    const payment = () =>
      paypal.rest.payment.create(env, client, {
        transactions: [
          {
            amount: {
              total: price,
              currency
            }
          }
        ]
      });

    const onAuthorize = (data, actions) =>
      actions.payment.execute().then(() => {
        const payment = {
          paid: true,
          cancelled: false,
          payerID: data.payerID,
          paymentID: data.paymentID,
          paymentToken: data.paymentToken,
          returnUrl: data.returnUrl
        };

        onSuccess(payment);
      });

    const style = {
      layout: "vertical", // horizontal | vertical
      size: "medium", // medium | large | responsive
      shape: "rect", // pill | rect
      color: "gold" // gold | blue | silver | white | black
    };

    return (
      <React.Fragment>
        <form>
          <h3 style={{ justifySelf: "center" }}>Donate Amount</h3>
          <input
            name="donate"
            type="text"
            placeholder="Minimum $1.00"
            value={this.state.price}
            onChange={this.handleInputChange}
            className="donationInput"
          />
        </form>

        <br />
        {showButton && (
          <paypal.Button.react
            style={style}
            env={env}
            client={client}
            commit={commit}
            payment={payment}
            onAuthorize={onAuthorize}
            onCancel={onCancel}
            onError={onError}
          />
        )}
      </React.Fragment>
    );
  }
}

export default scriptLoader("https://www.paypalobjects.com/api/checkout.js")(
  PaypalButton
);```

No error messages show up, but the button does not lead to anything.

Upvotes: 0

Views: 2922

Answers (1)

Steve K
Steve K

Reputation: 9055

It looks to me like you are trying to use the depreciated version of the checkout api. There is a new version V2 you can view here Paypal Checkout Buttons.

If you want there is an npm package for the new V2 buttons that can be viewed here NPM react-paypal-button-v2.

That said you can do something like the following which is taken from the npm packages github found here react-paypal-button-v2 github but without the typescript and in functional component form:

import React, { useState, useEffect} from 'react';
import ReactDOM from 'react-dom';

const PaypalButton = props => {
  const [sdkReady, setSdkReady] = useState(false);

  const addPaypalSdk = () => {
    const clientID =
      'Your-Paypal-Client-ID';
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = `https://www.paypal.com/sdk/js?client-id=${clientID}`;
    script.async = true;
    script.onload = () => {
      setSdkReady(true);
    };
    script.onerror = () => {
      throw new Error('Paypal SDK could not be loaded.');
    };

    document.body.appendChild(script);
  };

  useEffect(() => {
    if (window !== undefined && window.paypal === undefined) {
      addPaypalSdk();
    } else if (
      window !== undefined &&
      window.paypal !== undefined &&
      props.onButtonReady
    ) {
      props.onButtonReady();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);


  //amount goes in the value field we will use props of the button for this   
  const createOrder = (data, actions) => {
    return actions.order.create({
      purchase_units: [
        {
          amount: {
            currency_code: 'USD',
            value: props.amount,
          }
        }
      ]
    });
  };

  const onApprove = (data, actions) => {
    return actions.order
      .capture()
      .then(details => {
        if (props.onSuccess) {
          return props.onSuccess(data);
        }
      })
      .catch(err => {
        console.log(err)
      });
  };

  if (!sdkReady && window.paypal === undefined) {
    return (
      <div>Loading...</div>
    );
  }

  const Button = window.paypal.Buttons.driver('react', {
    React,
    ReactDOM
  });

  //you can set your style to whatever read the documentation for different styles I have put some examples in the style tag
  return (
    <Button
      {...props}
      createOrder={
        amount && !createOrder
          ? (data, actions) => createOrder(data, actions)
          : (data, actions) => createOrder(data, actions)
      }
      onApprove={
        onSuccess
          ? (data, actions) => onApprove(data, actions)
          : (data, actions) => onApprove(data, actions)
      }
      style={{
        layout: 'vertical',
        color: 'blue',
        shape: 'rect',
        label: 'paypal'
      }}
    />
  );
};

export default PaypalButton;

Then you can use this in your component like so:

const onSuccess = payment => {
  console.log(payment)
}

const onCancel = data => {
  console.log(data)
};

const onError = err => {
  console.log(err);
};

<PaypalButton
  amount="1.00"
  onError={onError}
  onSuccess={onSuccess}
  onCancel={onCancel}
/>

Note this is not tested I just pulled it from the npm packages github and removed the typescript for a little easier reading but it should give you an idea of what to do and how to add your donation logic to the button. I would highly suggest reading through paypals documentation. It is painful to go through but necessary. If you don't feel like messing with creating your own button you can just add the npm package and be on your way pretty easy.

Upvotes: 3

Related Questions