【问题标题】:Best practice for storing Stripe payments in database?将 Stripe 付款存储在数据库中的最佳实践?
【发布时间】:2018-08-13 19:59:21
【问题描述】:

我想知道是否存在某种“约定”或其他将 Stripe 支付数据存储在数据库中的最佳实践。网上信息真的很缺乏,因为我是自己做的,所以我想从其他人那里得到一些反馈。

我的网站的基本设置是有一家商店,里面有几种产品。还有一个订阅选项,每月接收这些产品。

所以我设置了两条发布路线。一种用于购买产品,一种用于订阅。这些使用 Stripe API。对于订单,我使用 stripe.charge,对于订阅,我从 stripe.customer 创建一个客户并为他们订阅一个计划。

对于stripe.charges,我将返回的对象保存到数据库中。这包含所有的收费数据。如果charge succeeded,则以charge.succeeded 发送一个webhook。我不存储这些数据。也许我应该只在此处存储费用 ID,而不是整个费用对象。我将其存储如下:

订购路线

module.exports = async (req, res) => {
try {
    const charge = await stripe.charges.create({
        amount: req.session.cart.totalPrice,
        currency: 'usd',
        source: req.body.id
    });

    const order = await new Order({
        user: req.user,
        cart: req.session.cart,
        stripeCharge: charge
    }).save();

    req.session.cart = new Cart({});    
    res.sendStatus(200);

} catch (e) {
    console.log(e);
}
};

订阅会稍微复杂一些,因为创建的客户对象不包含任何费用 ID。所以我将客户 ID 保存到该用户模型中。如果订阅处理得很好,Stripe 会触发 6 个 webhook。我存储customer.subscription.createdcustomer.createdcharge.succeededinvoice.created。我像这样存储客户对象:

订阅路线

module.exports = async (req, res) => {
try {
    if(!req.user.hasSubscription) {
        const customer = await stripe.customers.create({
            email: req.body.email,
            source: req.body.id,
            plan: 'pro'
        });

        await new Subscription({
            user: req.user,
            customerId: customer.id
        }).save();

        req.user.hasSubscription = true;
        await req.user.save();
        res.send(req.user);
    }

} catch (e) {
    console.log(e);
}
};

如您所见,我在 Mongoose User 模型 hasSubscription 上设置了一个布尔值。如果这是真的,则不会创建客户,因此不会设置订阅。如果它是假的,我从创建的客户对象中保存客户 ID。然后在 webhook 路由中,我将上面的 4 个事件保存给正确的用户,并通过客户 ID 进行匹配。我认为我可以在这里节省更少的数据,可能会记录任何订阅和任何取消。我将 webhook 事件保存如下:

WEBHOOKS 路线

module.exports = async (req, res) => {
try {
    const data = {};        

    if (req.body.type === 'customer.subscription.created') {
        await Subscription.findOneAndUpdate({ customerId: 
        req.body.data.object.customer }, {
            $set: {
                'stripe_data.customer_subscription_created': 
                 req.body.data.object
            }
        }, {
            new: true
        });
        res.sendStatus(200);            
    };

 …//OTHER STRIPE EVENTS SIMILAR TO ABOVE…

 }

为了安全起见,我存储的数据比我可能需要的更多,我在某处读到建议存储足够的数据有利于遵守法律。但由于 Stripe 将所有内容都存储在仪表板中,我可以理解您的观点,即收费 ID 之类的简单识别信息就足够了。

我仍处于测试模式,但我认为 Stripe 只发回卡的最后 4 位数字,到期年份如下:

exp_year: 2042 last4: '4242'

关于将机密信息保存到数据库:我没有看到任何更敏感的信息被泄露。卡片本身由 Stripe 创建的 id 引用。

【问题讨论】:

  • 你能解释一下你所说的“支付数据”是什么意思吗?你的意思是——产品/库存管理或订单历史或卡片详细信息?我对此有点迷茫。 --- 我认为您可能最好依靠 webhook 事件来获取此信息并异步更新本地数据存储区,不管您的答案如何。
  • 一般来说,您可以存储 API 的返回的任何数据。重要的是,您不能让用户的支付信息(卡号、银行号码等)接触您的数据库,而只能使用他们的令牌/ID。至于您为自己使用而存储的内容,除了不存储您并不真正需要的数据之外,实际上并没有“最佳实践”。即使您在某些时候“需要”它,您是否需要存储它还是可以获取它?在大多数情况下,您只需存储费用 ID 或等效项即可。
  • 为缺乏清晰道歉 - 我已经在上面编辑了我的 OP。

标签: stripe-payments stripe.js


【解决方案1】:

Stripes security docs 中,它提到了Out-of-scope card data that can be safely storedJake T. 的评论确实是答案——从 API 返回的所有内容都可以存储。

卡类型、到期日期和最后四位数字不受 PCI 合规性约束

【讨论】:

    猜你喜欢
    • 2020-03-06
    • 2011-03-13
    • 2018-04-21
    • 1970-01-01
    • 2011-03-23
    • 2011-03-31
    • 2018-07-27
    • 1970-01-01
    • 2012-04-28
    相关资源
    最近更新 更多