You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native支付成功后cartItems无法插入MySQL数据库求助

React Native支付成功后无法将购物车数据提交到PHP后端

问题现象

支付成功后,前端通过POST请求携带cartItems数据,但PHP端接收不到有效数据:$_POST输出为空数组,提示cartItems未定义,var_dump显示该变量为null,导致foreach循环无法执行,最终购物车数据未能插入MySQL数据库。

PHP端错误输出

Array ( )
Warning: Undefined array key "cartItems" in C:\xampp\htdocs\api\insertOrders.php on line 14

Warning: Undefined variable $_cartItems in C:\xampp\htdocs\api\insertOrders.php on line 16
NULL
Warning: foreach() argument must be of type array|object, null given in C:\xampp\htdocs\api\insertOrders.php on line 23
Cart items inserted successfully!

相关代码

React Native前端支付页面代码

import {
  StyleSheet,
  Text,
  View,
  Image,
  TouchableOpacity,
  TextInput,
  Alert,
} from "react-native";
import React, { useRef, useState } from "react";
import { cartTotalPriceSelector } from "../redux/selectors";
import { useDispatch, useSelector } from "react-redux";
import { color } from "react-native-reanimated";
import colors from "../config/colors";

import { clear } from "../redux/features/cart/cartSlice";

import { Paystack, paystackProps } from "react-native-paystack-webview";

const PaymentScreen = () => {
  const paystackWebViewRef = useRef(paystackProps.PayStackRef);
  const totalPrice = useSelector(cartTotalPriceSelector);
  const userId = useSelector((state) => state.user.userId);
  const email = useSelector((state) => state.email.email);
  const cart = useSelector((state) => state.cart);
  const cartItems = cart.map((cartItem) => {
    return {
      userId: userId,
      bookId: cartItem.bookId,
      name: cartItem.name,
      quantity: cartItem.quantity,
      price: cartItem.price,
    };
  });

  console.log("myItem",{ cartItems });

  const insertOrders = () => {
    const url = "http://192.168.11.102:80/api/insertOrders.php";

    const requestOptions = {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ cartItems }),
    };

    console.log("Before fetch request");

    fetch(url, requestOptions)
      .then((response) => {
        console.log("Response received");
        return response.json();
      })
      .then((result) => {
        console.log("Result:", result);
      })
      .catch((error) => {
        console.error("Error:", error);
      });
  };

  return (
    <View style={styles.container}>
      <Paystack
        paystackKey="*****************************************"
        billingEmail={email}
        amount={totalPrice}
        onCancel={(e) => {}}
        onSuccess={(res) => {
          Alert.alert("Payment successful");
          console.log("myItem",{ cartItems });
          insertOrders();
        }}
        ref={paystackWebViewRef}
      />
      <Image style={styles.image} source={require("../assets/payment.jpg")} />

      <View style={styles.totalContainer}>
        <Text style={styles.totalText}>₦{totalPrice}</Text>
        <TouchableOpacity
          style={styles.checkoutButton}
          onPress={() => paystackWebViewRef.current.startTransaction()}>
          <Text style={styles.checkoutButtonText}>Pay Now</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

export default PaymentScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
  },
  checkoutButton: {
    backgroundColor: colors.orange,
    paddingHorizontal: 20,
    paddingVertical: 10,
    borderRadius: 20,
    elevation: 3,
  },
  checkoutButtonText: {
    fontSize: 16,
    fontWeight: "bold",
    color: "#FFFFFF",
  },
  image: {
    width: 200,
    height: 200,
    resizeMode: "cover",
    marginRight: 10,
    borderRadius: 11,
  },
  totalContainer: {
    margin: 10,
    borderColor: colors.lightOrange,
    borderWidth: 3,
    borderRadius: 10,
    padding: 20,
    justifyContent: "center",
    alignItems: "center",
  },
  totalText: {
    fontSize: 18,
    fontWeight: "bold",
  },
  emailInput: {
    height: 40,
    width: "100%",
    borderColor: colors.lightOrange,
    borderWidth: 2,
    borderRadius: 5,
    paddingHorizontal: 10,
    marginTop: 10,
  },
  errorText: {
    color: "red",
    marginTop: 5,
  },
});

前端控制台输出

myItem {"cartItems": [{"bookId": 18, "name": "The diary of a nigerian christian girl", "price": "2000.00", "quantity": 5, "userId": 31}, {"bookId": 21, "name": "A Time to Love", "price": "1500.00", "quantity": 3, "userId": 31}]}

PHP后端代码(insertOrders.php)

<?php
include 'connection.php';

// Prepare the SQL statement for inserting into orderProducts table
$insertOrderProductsStmt = $mysqli->prepare("INSERT INTO orders (userId, bookId, name, quantity, price) VALUES (?, ?, ?, ?,?)");

// $jsonPayload = file_get_contents('php://input');
// $data = json_decode($jsonPayload, true);

// Get the cart items from the request
print_r($_POST);
// if(isset($_POST['cartItems'])){

    $cartItems = $_POST['cartItems'];
   echo $cartItems;
  var_dump($_cartItems);
  
  // Start the transaction
  $mysqli->begin_transaction();
  
  try {
      // Iterate over each cart item and execute the insert statement
      foreach ($cartItems as $cartItem) {
          $userId = $cartItem['userId'];
          $bookId = $cartItem['bookId'];
          $name = $cartItem['name'];
          $quantity = $cartItem['quantity'];
          $price = $cartItem['quantity'] * $cartItem['price'];
  
          // Bind the parameters and execute the statement
          $insertOrderProductsStmt->bind_param("iisii", $userId, $bookId, $name, $quantity, $price);
          $insertOrderProductsStmt->execute();
      }
  
      // Commit the transaction
      $mysqli->commit();
  
      // Close the prepared statement
      $insertOrderProductsStmt->close();
  
      // Send a success response
      echo "Cart items inserted successfully!";
  } catch (Exception $e) {
      // Rollback the transaction if an error occurred
      $mysqli->rollback();
  
      // Close the prepared statement
      $insertOrderProductsStmt->close();
  
      // Send an error response
      echo "Error: " . $e->getMessage();
  }
  
  // Close the database mysqliection
  $mysqli->close();
// }
// else{
//     echo "an error occured";
// }

?>

解决方案

核心问题

前端发送的是JSON格式请求体,但PHP默认仅解析application/x-www-form-urlencoded格式数据到$_POST,因此无法通过$_POST['cartItems']获取数据。同时原代码存在变量名笔误($_cartItems应为$cartItems)。

修复步骤

  1. 修改PHP代码,读取JSON请求体
    取消注释原本被注释的JSON解析代码,替换$_POST读取逻辑,并修复变量笔误:
<?php
include 'connection.php';

// Prepare the SQL statement for inserting into orderProducts table
$insertOrderProductsStmt = $mysqli->prepare("INSERT INTO orders (userId, bookId, name, quantity, price) VALUES (?, ?, ?, ?,?)");

// 读取JSON请求体并解析
$jsonPayload = file_get_contents('php://input');
$data = json_decode($jsonPayload, true);

// 检查数据是否存在
if(!isset($data['cartItems']) || empty($data['cartItems'])){
    echo json_encode(["status" => "error", "message" => "cartItems数据不存在"]);
    $mysqli->close();
    exit;
}

$cartItems = $data['cartItems'];

// Start the transaction
$mysqli->begin_transaction();

try {
    // Iterate over each cart item and execute the insert statement
    foreach ($cartItems as $cartItem) {
        $userId = $cartItem['userId'];
        $bookId = $cartItem['bookId'];
        $name = $cartItem['name'];
        $quantity = $cartItem['quantity'];
        // 将字符串类型的price转为数值计算
        $price = $cartItem['quantity'] * (float)$cartItem['price'];

        // Bind the parameters and execute the statement
        $insertOrderProductsStmt->bind_param("iisii", $userId, $bookId, $name, $quantity, $price);
        $insertOrderProductsStmt->execute();
    }

    // Commit the transaction
    $mysqli->commit();

    // Close the prepared statement
    $insertOrderProductsStmt->close();

    // 返回JSON格式响应,适配前端解析
    echo json_encode(["status" => "success", "message" => "Cart items inserted successfully!"]);
} catch (Exception $e) {
    // Rollback the transaction if an error occurred
    $mysqli->rollback();

    // Close the prepared statement
    $insertOrderProductsStmt->close();

    // 返回JSON格式错误响应
    echo json_encode(["status" => "error", "message" => $e->getMessage()]);
}

// Close the database connection
$mysqli->close();
?>
  1. 前端优化(可选)
    适配后端返回的JSON格式响应,处理成功/失败场景:
fetch(url, requestOptions)
  .then((response) => {
    console.log("Response received");
    if(!response.ok){
        throw new Error('网络请求失败');
    }
    return response.json();
  })
  .then((result) => {
    console.log("Result:", result);
    if(result.status === "success"){
        Alert.alert("提交成功", result.message);
        // 可在此处清空购物车
        // dispatch(clear());
    } else {
        Alert.alert("提交失败", result.message);
    }
  })
  .catch((error) => {
    console.error("Error:", error);
    Alert.alert("提交失败", error.message);
  });

额外注意点

  • 前端传递的price是字符串类型,PHP计算时需转为数值类型,避免计算错误。
  • 后端统一返回JSON格式响应,确保前端response.json()解析时不会报错。

内容的提问来源于stack exchange,提问作者Esther Iyege

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:22:00