React Native Stripe 集成:卡在 IP/成功/

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

我目前正在致力于将 Stripe 支付集成到我的 React Native 应用程序中。我已经设置了付款流程,用户单击按钮后将被重定向到浏览器中的结帐屏幕。在结帐屏幕上完成付款后,用户将被重定向回我的服务器上的 URL (http://myip:4242/success?session_id={CHECKOUT_SESSION_ID})。然而,我并没有被重定向回 React Native 应用程序,而是停留在浏览器中显示 http://myip:4242/success?session_id= 的屏幕上。

采取的步骤:

Configured Stripe payment flow with React Native and Express server.
Implemented checkout session creation and redirection to Stripe checkout screen.
Configured intent-filter in the Android manifest to handle the redirect back to the React Native app.
Verified the settings in the Stripe Dashboard to ensure correct redirection URLs.
Checked and adjusted the handleOpenURL function in the React Native app to handle redirection.

预期结果:

成功付款后,我希望用户被重定向回 React Native 应用程序,并将会话 ID 参数附加到 URL,以便我可以在应用程序中处理成功事件。

任何有关如何排查和解决此问题的见解或建议将不胜感激!

 const express = require("express");
 const bodyParser = require("body-parser");
 const stripe = require("stripe")(
 "sk_test_numbers"
 );
 const dotenv = require("dotenv");
 dotenv.config();
 const app = express();
 app.use(bodyParser.json());

 const PORT = process.env.PORT || 4242;
 app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

 let paymentDetails = {};

  app.post("/checkout", async (req, res) => {
  try {
  const priceId = "price_1OrLl7HEI2MJxjfpUnFQoLwk"; // Your price ID
  const quantity = req.body.quantity || 1;
  const session = await stripe.checkout.sessions.create({
  mode: "payment",
  success_url:
    "http://myip/success?session_id={CHECKOUT_SESSION_ID}",

  cancel_url: "http://myip/cancel",
  line_items: [
    {
      price: priceId,
      quantity: quantity,
    },
  ],
  payment_method_types: ["card"],
});

    console.log("Checkout session created successfully:", session.id); message
   res.json({ url: session.url });
   }      
     catch (error) {
     console.error(error);
     res.status(500).json({ error: "Failed to create checkout session" });
 }
 });
    app.get('/event', async (req, res) => {
    try {
     const events = await stripe.events.list({
      limit: 1,
      });

      res.json(events);
    } 
 catch (error) {
  console.error(error);
  res.status(500).json({ error: 'Failed to retrieve events' });
    }
  });
  app.get("/success", async (req, res) => {
 const sessionId = req.query.session_id;
  const session = await stripe.checkout.sessions.retrieve(sessionId);
  res.send(`Payment successful! Session ID: ${session.id}`);
  });

  const endpointSecret =
   "secret";

   app.post(
  "/webhook",
      express.raw({ type: "application/json" }),
     (request, response) => {
     const sig = request.headers["stripe-signature"];

    let event;

    try {
     event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
     }   catch (err) {
      response.status(400).send(`Webhook Error: ${err.message}`);
      return;
      }
      switch (event.type) {
  case "payment_intent.succeeded":
    const paymentIntentSucceeded = event.data.object;
    console.log(paymentIntentSucceeded);
    paymentDetails = {
      amount: paymentIntentSucceeded.amount,
      currency: paymentIntentSucceeded.currency,
      status: paymentIntentSucceeded.status,
    
    };

  
    response.status(200).send();

    break;

  default:
    console.log(`Unhandled event type ${event.type}`);
     }
   }
   );
    app.get("/payment-details", (req, res) => {
      res.json(paymentDetails);
     });

并对本机代码做出反应

     React.useEffect(() => {
    const removeLinkingListener = Linking.addEventListener('url', handleOpenURL);
   
    return () => {
       removeLinkingListener.remove();
    };
   }, []);
   const handleOpenURL = (event) => {
    // Example URL: myapp://checkout-success?session_id=cs_test_123
    const { url } = event;
    if (url.startsWith('myip:4242/checkout-success')) {
       // Extract session ID or other relevant data from the URL
       // Then, handle the success in your app
       console.log('Payment was successful');
    } else if (url.startsWith('http://myip:4242/checkout-cancel')) {
       // Handle the cancellation
       console.log('Payment was canceled');
    }
   };
        <Button
     buttonColor="#2C2C2C"
      textColor="#FFFFFF"
       mode="contained"
      style={{ marginTop: 10, width: '100%', height: 50, borderRadius: 10,       justifyContent: 'center', alignItems: 'center' }}
    labelStyle={{ fontSize: 16 }}
    onPress={async () => {
     try {
     const response = await fetch('http://myip/checkout', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
     },
      body: JSON.stringify({
      quantity: 1,
      }),
     });

     const { url } = await response.json();
     if (url) {
    Linking.openURL(url);
    }
   } catch (error) {
  console.error(error);
   }
  }}
    >
    PAGAR
     </Button>

Android 清单

  <intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="myip" android:port="4242" android:pathPrefix="/checkout-success" />
<data android:scheme="http" android:host="myip" android:port="4242" android:pathPrefix="/checkout-cancel" />

我也尝试过:

React.useEffect(() => {
const handleDeepLink = async (event) => {
  const { url } = event;
  if (url.startsWith("http://192.myip:4242/checkout-success")) {
    const sessionId = url.split("session_id=")[1]; // Extract session ID from URL
    console.log("Payment was successful");
    const response = await fetch(
      `http://192.myip:4242/checkout-session?sessionId=${sessionId}`
    );
    const session = await response.json();
    console.log("Checkout Session:", session);
    navigator.navigate("PaymentSuccess");
  } else if (url.startsWith("http://192.myip:4242/checkout-cancel")) {
    console.log("Payment was canceled");
    // navigator.navigate('PaymentCanceled');
  }
};

const subscription = Linking.addEventListener("url", handleDeepLink);

return () => {
  subscription.remove();
 };
  }, []);
android react-native expo stripe-payments
1个回答
0
投票

您需要配置自定义 URL 方案或通用链接才能从 Web 视图返回到您的应用程序。请参阅:[1]

但是,我不相信 Checkout Session

success_url
支持传入自定义应用程序 URL。

我能想到的解决方法是;

  1. 创建一个通用链接,让您可以将用户重定向回您的应用程序
  2. 创建结账会话时将通用链接设置为
    success_url
  3. 配置您的 React Native 应用程序来处理通用链接

[1] https://reactnative.dev/docs/linking

© www.soinside.com 2019 - 2024. All rights reserved.