Node.js 单击“使用节点付款”和“快速付款”后,未返回成功消息

Node.js 单击“使用节点付款”和“快速付款”后,未返回成功消息,node.js,reactjs,express,stripe-payments,stripe-api,Node.js,Reactjs,Express,Stripe Payments,Stripe Api,我目前正在使用带条带支付API的ReactJS、node和express。单击“支付”按钮并输入虚拟信用卡凭据后,页面将不处理支付。我已经输入了从仪表板获得的正确的发布密钥和api密钥。我相信这可能与我需要添加到server.js文件(又名节点后端)中的内容有关。我已经阅读了文档,以获得任何线索。也在这里搜索了堆栈溢出。没有一个问题和我想问的一样。请参阅下面的图片和代码。谢谢 这是在按下按钮之前。请注意右侧的控制台。 这是在按下按钮之后。加载微调器将永远显示。还要注意右侧的控制台 //pro

我目前正在使用带条带支付API的ReactJS、node和express。单击“支付”按钮并输入虚拟信用卡凭据后,页面将不处理支付。我已经输入了从仪表板获得的正确的发布密钥和api密钥。我相信这可能与我需要添加到server.js文件(又名节点后端)中的内容有关。我已经阅读了文档,以获得任何线索。也在这里搜索了堆栈溢出。没有一个问题和我想问的一样。请参阅下面的图片和代码。谢谢

这是在按下按钮之前。请注意右侧的控制台。

这是在按下按钮之后。加载微调器将永远显示。还要注意右侧的控制台

//provate.js
从“React”导入React;
导入“/Donate.css”;
从“@stripe/stripe js”导入{loadStripe};
从“@stripe/react stripe js”导入{Elements}”;
从“/CheckoutForm”导入CheckoutForm;
//确保在组件渲染外部调用'loadStripe',以避免
//在每个渲染上重新创建“条带”对象。
常量条带=加载条带(
“主键*****************************”
);
条带。然后((数据)=>{
控制台日志(数据);
});
常数=()=>{
返回(
现在捐赠
);
};
出口违约金;
//检查口
从“React”导入React,{useState,useffect};
从“@stripe/react stripe js”导入{CardElement,useStripe,useElements};
导入“/CheckoutForm.css”;
导出默认函数CheckoutForm(){
const[successed,setSucceeded]=使用状态(false);
const[error,setError]=useState(null);
const[processing,setProcessing]=useState(“”);
const[disabled,setDisabled]=使用状态(true);
const[clientSecret,setClientSecret]=useState(“”);
常量stripe=useStripe();
常量元素=useElements();
useffect(()=>{
//页面加载后立即创建PaymentIntent
窗口
.fetch(“/捐赠”{
方法:“张贴”,
标题:{
“内容类型”:“应用程序/json”,
接受:“应用程序/json”,
},
body:JSON.stringify({items:[{id:'xl tshirt}]}),
})
。然后((res)=>{
返回res.json();
})
。然后((数据)=>{
setClientSecret(data.clientSecret);
});
}, []);
常数cardStyle={
风格:{
基数:{
颜色:“32325d”,
fontFamily:“Arial,无衬线”,
字体平滑:“抗锯齿”,
字体大小:“16px”,
“::占位符”:{
颜色:“32325d”,
},
},
无效:{
颜色:“fa755a”,
iconColor:#fa755a“,
},
},
};
const handleChange=async(事件)=>{
//侦听CardElement中的更改
//并在客户键入卡片详细信息时显示任何错误
setDisabled(event.empty);
setError(event.error?event.error.message:);
};
const handleSubmit=异步(ev)=>{
ev.preventDefault();
设置处理(真);
const payload=wait stripe.confirmCardPayment(clientSecret{
付款方式:{
卡片:elements.getElement(CardElement),
},
});
if(有效负载错误){
setError(`Payment failed${payload.error.message}`);
设置处理(假);
}否则{
设置错误(空);
设置处理(假);
设置成功(真);
}
console.log(clientSecret);
};
返回(
{处理?:“支付”}
{/*显示处理付款时发生的任何错误*/}
{错误&&(
{错误}
)}
{/*完成后显示成功消息*/}

付款成功,请在您的帐户中查看结果 {" "} 刷新页面以再次付款。

); } //server.js const express=要求(“express”); 常量app=express(); const{resolve}=require(“路径”); //这是您真正的测试机密API密钥。 常量条带=需要(“条带”)( “SKU测试**************************************” ); 应用程序使用(快速静态(“.”); 使用(express.json()); 常量calculateOrderAmount=(项)=>{ //用订单金额的计算替换此常量 //计算服务器上的订单总数以防止 //人们不能直接在客户机上操纵金额 返回1400; }; app.post(“/create payment intent”),异步(请求、回复)=>{ const{items}=req.body; //使用订单金额和货币创建PaymentIntent const paymentIntent=wait stripe.paymentIntents.create({ 金额:1099, 货币:“美元”, //通过包含此参数验证您在本指南中的集成 元数据:{集成检查:“接受付款”}, }); res.send({ clientSecret:paymentIntent.client\u secret, }); }); app.listen(4242,()=>console.log(“节点服务器在端口4242上侦听”);
您需要使用
客户端密码查看服务器呼叫/网络响应。控制台错误表示您向
confirmCardPayment
提供了无效的密码,显然是一个空字符串

您指定:。

您的应用程序似乎没有按预期通过
setClientSecret
设置状态,您最终得到的是
useState(“”)中的初始空字符串值

在调用
confirmCardPayment
之前,检查您的
client\u secret
值,然后后退一步查找该值的删除位置

    // Donate.js
    import React from "react";
    import "./Donate.css";
    import { loadStripe } from "@stripe/stripe-js";
    import { Elements } from "@stripe/react-stripe-js";
    import CheckoutForm from "./CheckoutForm";
    
    // Make sure to call `loadStripe` outside of a component’s render to avoid
    // recreating the `Stripe` object on every render.
    const stripe = loadStripe(
      "pk*****************************"
    );
    
    stripe.then((data) => {
      console.log(data);
    });
    
    const Donate = () => {
      return (
        <div className="donate">
          <h1 className="donate__sectionHeader">Donate Now</h1>
          <Elements stripe={stripe}>
            <CheckoutForm />
          </Elements>
        </div>
      );
    };
    
    export default Donate;

//CheckoutForm
import React, { useState, useEffect } from "react";
import { CardElement, useStripe, useElements } from "@stripe/react-stripe-js";
import "./CheckoutForm.css";

export default function CheckoutForm() {
  const [succeeded, setSucceeded] = useState(false);
  const [error, setError] = useState(null);
  const [processing, setProcessing] = useState("");
  const [disabled, setDisabled] = useState(true);
  const [clientSecret, setClientSecret] = useState("");
  const stripe = useStripe();
  const elements = useElements();
  useEffect(() => {
    // Create PaymentIntent as soon as the page loads

    window
      .fetch("/donate", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
        },
        body: JSON.stringify({ items: [{ id: "xl-tshirt" }] }),
      })
      .then((res) => {
        return res.json();
      })
      .then((data) => {
        setClientSecret(data.clientSecret);
      });
  }, []);
  const cardStyle = {
    style: {
      base: {
        color: "#32325d",
        fontFamily: "Arial, sans-serif",
        fontSmoothing: "antialiased",
        fontSize: "16px",
        "::placeholder": {
          color: "#32325d",
        },
      },
      invalid: {
        color: "#fa755a",
        iconColor: "#fa755a",
      },
    },
  };
  const handleChange = async (event) => {
    // Listen for changes in the CardElement
    // and display any errors as the customer types their card details
    setDisabled(event.empty);
    setError(event.error ? event.error.message : "");
  };
  const handleSubmit = async (ev) => {
    ev.preventDefault();
    setProcessing(true);
    const payload = await stripe.confirmCardPayment(clientSecret, {
      payment_method: {
        card: elements.getElement(CardElement),
      },
    });
    if (payload.error) {
      setError(`Payment failed ${payload.error.message}`);
      setProcessing(false);
    } else {
      setError(null);
      setProcessing(false);
      setSucceeded(true);
    }

    console.log(clientSecret);
  };
  return (
    <form id="payment-form" onSubmit={handleSubmit}>
      <CardElement
        id="card-element"
        options={{ hidePostalCode: true, cardStyle }}
        onChange={handleChange}
      />
      <button disabled={processing || disabled || succeeded} id="submit">
        <span id="button-text">
          {processing ? <div className="spinner" id="spinner"></div> : "Pay"}
        </span>
      </button>
      {/* Show any error that happens when processing the payment */}
      {error && (
        <div className="card-error" role="alert">
          {error}
        </div>
      )}
      {/* Show a success message upon completion */}
      <p className={succeeded ? "result-message" : "result-message hidden"}>
        Payment succeeded, see the result in your
        <a href={`https://dashboard.stripe.com/test/payments`}>
          {" "}
          Stripe dashboard.
        </a>{" "}
        Refresh the page to pay again.
      </p>
    </form>
  );
}


//server.js
const express = require("express");
const app = express();
const { resolve } = require("path");
// This is your real test secret API key.
const stripe = require("stripe")(
  "sk_test_**********************************"
);
app.use(express.static("."));
app.use(express.json());

const calculateOrderAmount = (items) => {
  // Replace this constant with a calculation of the order's amount
  // Calculate the order total on the server to prevent
  // people from directly manipulating the amount on the client
  return 1400;
};

app.post("/create-payment-intent", async (req, res) => {
  const { items } = req.body;

  // Create a PaymentIntent with the order amount and currency
  const paymentIntent = await stripe.paymentIntents.create({
    amount: 1099,
    currency: "usd",
    // Verify your integration in this guide by including this parameter
    metadata: { integration_check: "accept_a_payment" },
  });
  res.send({
    clientSecret: paymentIntent.client_secret,
  });
});

app.listen(4242, () => console.log("Node server listening on port 4242!"));