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

Strapi+Stripe实操:支付成功后如何更新商品Sold字段为True?

问题描述
  • 我是Strapi和Stripe初学者,正在搭建电商练习网站,需求是支付成功后将商品的sold布尔字段设为true(商品为独款,需隐藏已售出商品)。
  • 控制台无报错,但bash提示:
    Updating sold status for product ID: 正确的商品ID
    Error updating sold boolean: Error: Model product not found
    
  • 确认product模型确实存在,尝试过strapi.models.product但问题依旧。

订单控制器代码如下:

"use strict";
const stripe = require("stripe")(process.env.STRIPE_KEY);

const { createCoreController } = require("@strapi/strapi").factories;

module.exports = createCoreController("api::order.order", ({ strapi }) => ({
  async create(ctx) {
    const { products } = ctx.request.body; 
    try {
      const lineItems = await Promise.all(
        products.map(async (product) => {
          const item = await strapi
            .service("api::product.product")
            .findOne(product.id);

          return {
            price_data: {
              currency: "usd",
              product_data: {
                name: item.title,
              },
              unit_amount: Math.round(item.price * 100),
            },
            quantity: 1,
          };
        })
      );

      const session = await stripe.checkout.sessions.create({
        shipping_address_collection: { allowed_countries: ["US"] },
        payment_method_types: ["card"],
        mode: "payment",
        success_url: process.env.CLIENT_URL + "?success=true",
        cancel_url: process.env.CLIENT_URL + "?success=false",
        line_items: lineItems,
      });

      // Update the sold boolean to true for the purchased items
      const updateSoldStatus = async (productId) => {
        try {
          await strapi
            .query("product")
            .update({ id: productId }, { sold: true });
        } catch (error) {
          console.error("Error updating sold boolean:", error);
        }
      };

      // Update the sold status for each purchased product
      for (const product of products) {
        console.log(`Updating sold status for product ID: ${product.id}`);
        await updateSoldStatus(product.id);
      }

      await strapi
        .service("api::order.order")
        .create({ data: { products, stripeId: session.id } });

      return { stripeSession: session };
    } catch (error) {
      ctx.response.status = 500;
      return { error };
    }
  },
}));
解决方案

1. 修复模型查询错误

Strapi v4中,strapi.query()需要传入完整的模型UID(即api::product.product),而非简写的product,这是你找不到模型的直接原因。同时,v4的query.update()语法也有变化,需要调整为update({ where: ... }, { data: ... })格式。

修改updateSoldStatus函数:

const updateSoldStatus = async (productId) => {
  try {
    await strapi
      .query("api::product.product") // 使用完整模型UID
      .update({ where: { id: productId } }, { data: { sold: true } });
  } catch (error) {
    console.error("Error updating sold boolean:", error);
  }
};

2. 修正核心逻辑错误(关键)

你当前的代码会在创建订单时立即更新商品状态,但用户可能取消支付或支付失败,导致商品被错误标记为已售出。正确做法是通过Stripe Webhook监听checkout.session.completed事件,仅在确认支付成功后更新商品状态。

步骤1:创建Stripe Webhook控制器

在Strapi中新建api::webhook.webhook控制器:

"use strict";
const stripe = require("stripe")(process.env.STRIPE_KEY);

module.exports = {
  async stripeWebhook(ctx) {
    const sig = ctx.request.headers["stripe-signature"];
    let event;

    try {
      event = stripe.webhooks.constructEvent(
        ctx.request.body,
        sig,
        process.env.STRIPE_WEBHOOK_SECRET
      );
    } catch (err) {
      ctx.response.status = 400;
      return { error: `Webhook Error: ${err.message}` };
    }

    // 处理支付成功事件
    if (event.type === "checkout.session.completed") {
      const session = event.data.object;
      // 从元数据中取出商品ID数组
      const productIds = JSON.parse(session.metadata.productIds);
      
      // 更新每个商品的sold状态
      for (const productId of productIds) {
        await strapi.query("api::product.product").update(
          { where: { id: productId } },
          { data: { sold: true } }
        );
      }

      // 可选:更新订单状态为已支付
      await strapi.query("api::order.order").update(
        { where: { stripeId: session.id } },
        { data: { status: "paid" } }
      );
    }

    ctx.response.status = 200;
    return { received: true };
  },
};

步骤2:修改订单控制器,添加元数据

创建Stripe Session时,将商品ID存入元数据,方便Webhook获取:

const session = await stripe.checkout.sessions.create({
  shipping_address_collection: { allowed_countries: ["US"] },
  payment_method_types: ["card"],
  mode: "payment",
  success_url: process.env.CLIENT_URL + "?success=true",
  cancel_url: process.env.CLIENT_URL + "?success=false",
  line_items: lineItems,
  metadata: {
    productIds: JSON.stringify(products.map(p => p.id)) // 存入商品ID数组
  },
});

同时删除原订单控制器中创建订单时更新sold状态的代码块。

步骤3:配置Stripe后台Webhook

在Stripe后台添加Webhook端点,URL填写你的Strapi地址+/api/webhooks/stripe-webhook,选择checkout.session.completed事件,将签名密钥存入环境变量STRIPE_WEBHOOK_SECRET。

3. 可选:使用Service更新商品

除了strapi.query(),也可以用Strapi Service更新商品,更符合最佳实践:

await strapi.service("api::product.product").update(productId, {
  data: { sold: true }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 17:36:00