React Redux 中的条带支付网关问题

问题描述 投票:0回答:2

这个项目运行良好,结账也运行良好,但条纹没有显示任何付款。

也许我在 checkout.js 中遗漏了一些设置我的 Stripe 支付网关的代码...但我找不到。

这是 chekcout.jsx

import { Redirect } from "react-router-dom";
import { connect } from "react-redux";
import { confirmOrder, setPromoCode } from "../store/actions";
import CheckoutCartProduct from "../components/Checkout/CheckoutCartProduct";
import PromoCodeForm from "../components/Checkout/PromoCodeForm";
import PromoCodeValue from "../components/Checkout/PromoCodeValue";
import CheckoutCartTotals from "../components/Checkout/CheckoutCartTotals";
import CustomerInputs from "../components/Checkout/Forms/CustomerInputs";
import DeliveryOptions from "../components/Checkout/Forms/DeliveryOptions";
import PaymentOptions from "../components/Checkout/Forms/Payments/PaymentOptions";
import Alert from "../components/UI/Alert/Alert";
import PropTypes from "prop-types";
import formValidator from "../Utility/formValidation";
import { CardElement, injectStripe } from "react-stripe-elements";
import { currencyToUse } from "../Utility/currency";

class Checkout extends Component {
  state = {
    promoCode: "",
    showAlert: false,
    alertType: "",
    alertMessage: "",
    paymentMethod: "creditCard",
    shippingPrice: 300,
    usedDeliveryOption: 1,
    makeOrder: false,
    correctCardInfo: false,
    customerInfo: {
      firstName: {
        value: "",
        valid: false,
        touched: false,
        errorsMsg: "",
      },
      secondName: {
        value: "",
        valid: false,
        touched: false,
        errorsMsg: "",
      },
      email: {
        value: "",
        valid: false,
        touched: false,
        errorsMsg: "",
      },
    },
  };

  customerInfoChangeHandler = (event, identifier) => {
    // use deep cloning to be able to get the values of nested objects
    const customerInfo = { ...this.state.customerInfo };
    const customerInfoField = { ...customerInfo[identifier] };
    customerInfoField.value = event.target.value;
    const validationResults = formValidator(
      identifier,
      customerInfoField.value
    );
    customerInfoField.valid = validationResults.isValid;
    customerInfoField.errorsMsg = validationResults.errorsMsg;
    customerInfoField.touched = true;
    customerInfo[identifier] = customerInfoField;

    let makeOrder = true;
    for (let identifier in customerInfo) {
      makeOrder = customerInfo[identifier].valid && makeOrder;
    }
    this.setState({ customerInfo: customerInfo, makeOrder: makeOrder });
  };

  promoCodeChangeHandler = (event) => {
    this.setState({ promoCode: event.target.value });
  };

  paymentOptionChangeHandler = (event) => {
    if (event.target.value === "creditCard") {
      this.setState({ correctCardInfo: false });
    } else {
      this.setState({ correctCardInfo: true });
    }
    this.setState({ paymentMethod: event.target.value });
  };

  confirmOrderHandler = (event) => {
    event.preventDefault();
    let order = {};
    order["cart"] = this.props.cartProductsProps;
    order["user"] = {
      firstName: this.state.customerInfo.firstName.value,
      secondName: this.state.customerInfo.secondName.value,
      email: this.state.customerInfo.email.value,
    };
    order["usedPromoCode"] = this.state.promoCode;
    order["currency"] = this.props.usedCurrencyProp;
    order["paymentMethod"] = this.state.paymentMethod;
    order["deliveryOption"] = this.state.usedDeliveryOption;

    // todo

   
    // create stripe token for payments

    
    this.props.confirmOrderProp(order);
  };

  setPromoCode = (event) => {
    event.preventDefault();
    // check promo code in state
    let getPromoCode = this.props.promoCodeProp.filter(
      (codeName) => codeName.code === this.state.promoCode
    );

    if (getPromoCode.length > 0) {
      this.props.setPromoCodeProp(getPromoCode[0]);
      this.setState({
        showAlert: true,
        alertType: "alert-success",
        alertMessage: `The promo code you entered has given you a ${getPromoCode[0].percentage}% discount on the total price.`,
      });
    } else {
      this.setState({
        showAlert: true,
        alertType: "alert alert-danger",
        alertMessage: "The Promo code you entered does not have discounts",
      });
    }
  };

  closeAlertHandler = () => {
    this.setState({
      showAlert: !this.state.showAlert,
      alertType: "",
      alertMessage: "",
    });
  };

  deliveryOptionChangeHandler = (event) => {
    //get used delivery option from the state
    let deliveryOption = this.props.deliveryOptions.find(
      (option) => option.id === parseInt(event.target.value)
    );
    if (deliveryOption) {
      this.setState({
        usedDeliveryOption: parseInt(event.target.value),
        shippingPrice: deliveryOption.cost,
      });
    }
  };

  creditCardHandler = (element) => {
    if (element.complete) {
      this.setState({ correctCardInfo: true });
    }
  };

  render() {
    let productsPrices = [];
    let chosenPaymentMethod = null;
    let currencyKeys = currencyToUse(this.props.usedCurrencyProp);
    let currencyValue = currencyKeys.value;

    const cartProducts = this.props.cartProductsProps.map(
      (cartProduct, index) => {
        // fetch product information from source based on id
        let productFromStore = this.props.productsProps.find(
          (product) => product.id === cartProduct.id
        );
        productsPrices.push({
          price:
            productFromStore.quantity > 0
              ? Math.round(productFromStore.price * currencyValue)
              : 0,
          count: cartProduct.quantity,
        });
        return (
          <CheckoutCartProduct
            key={index}
            checkoutProductName={productFromStore.name}
            checkoutProductCategory={productFromStore.category}
            checkoutProductPrice={Math.round(
              productFromStore.price * currencyValue
            )}
            checkoutProductImage={productFromStore.img}
            checkoutCartCount={cartProduct.quantity}
            checkoutCartSize={cartProduct.size}
            currency={this.props.usedCurrencyProp}
            
          />
        );
      }
    );

    let shippingPrice = this.state.shippingPrice
      ? Math.round(this.state.shippingPrice * currencyValue)
      : 0;
    let productTotals = productsPrices.reduce(
      (acc, el) => acc + el.price * el.count,
      0
    );
    let vatPercentage = this.props.vatProps > 0 ? this.props.vatProps / 100 : 0;
    let vat = productTotals > 0 ? Math.round(productTotals * vatPercentage) : 0;
    let percentageDiscount = this.props.usedPromoCodeProp
      ? this.props.usedPromoCodeProp.percentage / 100
      : 0;
    let discountAmount = productTotals * percentageDiscount;
    let shoppingTotal =
      productTotals > 0
        ? productTotals + vat + shippingPrice - discountAmount
        : 0;

    if (this.state.paymentMethod === "creditCard") {
      chosenPaymentMethod = (
        <div className={"ml-4 p-3 shop-card-field"}>
          <CardElement
            onChange={(element) => this.creditCardHandler(element)}
          />
        </div>
      );
    } else if (this.state.paymentMethod === "onDelivery") {
      chosenPaymentMethod = (
        <div className={"ml-4 p-3"}>
          You will pay when the product is delivered to you.
        </div>
      );
    }

    return (
      <div className="container py-4">
        {this.props.cartTotalProps <= 0 ? <Redirect to="/cart" /> : null}

        {this.state.showAlert ? (
          <Alert
            alertType={this.state.alertType}
            closeAlert={this.closeAlertHandler}
          >
            {this.state.alertMessage}
          </Alert>
        ) : null}

        <div className="row">
          <div className="col-md-4 order-md-2 mb-4">
            <h4 className="d-flex justify-content-between align-items-center mb-3">
              <span className="text-muted">Order Review</span>
              <span className="badge badge-secondary badge-pill">
                {this.props.cartTotalProps}
              </span>
            </h4>

            <ul className="list-group mb-3">
              {/* items in cart */}
              {cartProducts}

              {/* used promo codes */}
              {this.props.usedPromoCodeProp ? (
                <PromoCodeValue
                  currency={this.props.usedCurrencyProp}
                  usedPromoCode={this.props.usedPromoCodeProp}
                  discountAmount={discountAmount}
                />
              ) : null}

              {/* checkout totals */}
              <CheckoutCartTotals
                productTotals={productTotals}
                vat={vat}
                shippingPrice={shippingPrice}
                shoppingTotal={shoppingTotal}
                currency={this.props.usedCurrencyProp}
              />
            </ul>

            {/*promo code form */}
            <PromoCodeForm
              setPromoCode={this.setPromoCode}
              promoCodeChangeHandler={(event) =>
                this.promoCodeChangeHandler(event)
              }
              promoCode={this.state.promoCode}
            />
          </div>
          <div className="col-md-8 order-md-1 ">
            <h4 className="mb-3">Billing Information</h4>
            <form className="shop-form shop-bg-white p-3" noValidate>
              {/* customer details form fields */}
              <CustomerInputs
                customerInfo={this.state.customerInfo}
                inputChanged={(event, identifier) =>
                  this.customerInfoChangeHandler(event, identifier)
                }
              />
              {/* delivery options selection fields */}
              <h4 className="">Delivery Options</h4>
              <DeliveryOptions
                currency={this.props.usedCurrencyProp}
                deliveryOptions={this.props.deliveryOptions}
                usedDeliveryOption={this.state.usedDeliveryOption}
                deliveryOptionChanged={this.deliveryOptionChangeHandler}
              />

              <h4 className="mb-3">Payment Method</h4>
              {/* payment option selection field */}
              <PaymentOptions
                paymentMethod={this.state.paymentMethod}
                paymentOptionChanged={this.paymentOptionChangeHandler}
              />
              {/* payment section */}
              <div>{chosenPaymentMethod}</div>

              <hr className="mb-4" />
              <button
                disabled={!(this.state.makeOrder && this.state.correctCardInfo)}
                className="btn shop-btn-secondary btn-lg btn-block"
                onClick={(event) => this.confirmOrderHandler(event)}
              >
                Confirm Order
              </button>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

Checkout.propTypes = {
  productsProps: PropTypes.array.isRequired,
  cartProductsProps: PropTypes.array.isRequired,
  cartTotalProps: PropTypes.number.isRequired,
  promoCodeProp: PropTypes.array,
  usedPromoCodeProp: PropTypes.object,
  deliveryOptions: PropTypes.array.isRequired,
  usedCurrencyProp: PropTypes.object.isRequired,
  vatProps: PropTypes.number,
};

Checkout.defaultProps = {
  shippingPriceProp: 0,
};

const mapStateToProps = (state) => {
  return {
    productsProps: state.products,
    cartProductsProps: state.cart,
    cartTotalProps: state.cartTotal,
    vatProps: state.vat,
    promoCodeProp: state.promoCode,
    usedPromoCodeProp: state.usedPromoCode,
    deliveryOptions: state.deliveryOptions,
    usedCurrencyProp: state.usedCurrency,
  };
};

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    confirmOrderProp: (order) => dispatch(confirmOrder(order, ownProps)),
    setPromoCodeProp: (promoCode, percentage) =>
      dispatch(setPromoCode(promoCode, percentage)),
  };
};

// inject stripe prop into the component
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(injectStripe(Checkout));

这是index.js

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import store from "./store/store";
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
import "./index.css";
import {  Elements, StripeProvider  } from "react-stripe-elements";
import App from "./App";

const app = (
  <Provider store={store}>
    <BrowserRouter>
      {/* StripeProvider initializes the stripe and passes in the publishable key */}
      <StripeProvider apiKey={process.env.REACT_APP_STRIPE_KEY}>
        <Elements>

          <App />
          
        </Elements>
      </StripeProvider>
    </BrowserRouter>
  </Provider>
);

ReactDOM.render(app, document.getElementById("root"));

我还添加了.env文件和stripe密钥,此代码来自Github我想通过stripe设置支付网关,但我不明白我需要做什么。

react-redux stripe-payments express-checkout redux-store
2个回答
0
投票

您需要从服务器创建一个 PaymentIntent,并将其 client_secret 传递给前端并调用 stripe.confirmCardPayment,以便 Stripe 可以处理此付款。

您可以在此处找到完整的集成指南。


0
投票
Hi Brother,

To successfully complete a Stripe payment, we need to follow some steps. Here are the steps:

 1. We need to implement card elements on the checkout page.
 2. We need to create a payment method as shown below:

const { error: stripeError, paymentMethod } = await stripe.createPaymentMethod({
  type: "card",
  card: elements.getElement(CardExpiryElement, CardNumberElement, CardCvcElement),
});


We need to create a PaymentIntent using the above payment method key. To achieve this, we should pass the payment method key to the backend to create the PaymentIntent.
We need to confirm the PaymentIntent with the client secret key. If third-party validation is required, we need to pass the 3D authentication key; otherwise, the normal payment confirmation method is sufficient.

if (paymentIntent.status === "requires_action") {
  // Let Stripe.js handle the rest of the payment flow.
  const { error: actionError } = await stripe.confirmCardPayment(clientSecret);
  if (actionError) {
    ev.complete('fail');
    setPaymentStatus('Payment actionError error');
    return;
    // The payment failed -- ask your customer for a new payment method.
  } else {
    paymentSuccessShow(true);
    setPaymentStatus('Payment succeeded');
    navigate("/orderstatus");
    ev.complete('success');
    // The payment has succeeded -- show a success message to your customer.
  }
}

These steps ensure a smooth and successful Stripe payment process. If you have any questions or need further clarification, feel free to ask.
© www.soinside.com 2019 - 2024. All rights reserved.