如何在Stripe checkout完成后为Firestore支付文档添加产品标识字段
付费教程页面:如何通过Firebase+Stripe扩展标记用户购买的特定产品?
问题背景
我正在搭建一个付费教程页面,用户通过Stripe Checkout完成支付后即可查看对应页面内容。目前使用Firebase Firestore及Firebase Run Stripe Payments扩展处理支付流程,Checkout完成后payments集合会自动生成包含金额、状态等信息的文档。
但由于平台存在多款不同定价的产品,且外币支付时金额会出现变动,无法通过status或amount_received字段准确判断用户是否购买了某一特定产品。
当前查询过滤代码(内容展示组件)
<script> import PriceSelection1 from "./DildoRiding/PriceSelection1.vue"; import SubscribedAccountSignup1 from "./DildoRiding/SubscribedAccountSighnup1.vue"; import { firebaseAuth } from "../../Firebase/firebase"; import { ref } from 'vue' import { getFirestore, collection, query, where, getDocs, } from "firebase/firestore"; export default { components: { PriceSelection1, SubscribedAccountSignup1 }, data() { return { isLoading: false, Purchased2: null, }; }, mounted() { this.fetchSubscription(); }, methods: { async fetchSubscription() { this.isLoading = true; const db = getFirestore(); const subsRef = collection( db, "Subscribed", firebaseAuth.currentUser.uid, "payments" ); const subsQuery = query( subsRef, where("amount_received", "==", 5000 ) ); this.subscription = await getDocs(subsQuery) .then((sub) => sub.docs.length > 0 ? sub.docs[0].data() : null); this.isLoading = false; }, }, setup(){ const Activate = ref(false) return { Activate } } } </script> <template> <div v-if="isLoading">Loading account information...</div> <PriceSelection1 v-else-if="!subscription" /> <SubscribedAccountSignup1 v-else :subscription="subscription"/> <br> <div v-if="subscription" class="inline-block"> <p class="text-2xl text-red-700 font-serif inline">Cookie Recipes Purchased</p><br><br> <video width="320" height="240" controls> <source src="https://vid2"> Your browser does not support the video tag. </video> <video width="320" height="240" controls> <source src="https://vid1"> Your browser does not support the video tag. </video> <br><br> </div> </template>
价格选择页面代码
<script> import { getFirestore, getDocs, where, query, collection, addDoc, onSnapshot, } from "firebase/firestore"; import { projectFirestore } from '../../../Firebase/Config' import { firebaseAuth } from "../../../Firebase/firebase"; export default { data() { return { products: [], selectedPrice: null, isLoading: false, }; }, mounted() { this.fetchProducts(); }, methods: { async fetchProducts() { const db = getFirestore(); const productsRef = collection(db, "products"); const productsQuery = query(productsRef, where("name", "==", "Cookie Recipes")); const productsQuerySnap = await getDocs(productsQuery); productsQuerySnap.forEach(async (doc) => { const pricesRef = collection(db, "products", doc.id, "prices"); const pricesQuerySnap = await getDocs(pricesRef); this.products.push({ id: doc.id, ...doc.data(), prices: pricesQuerySnap.docs.map((price) => { return { id: price.id, ...price.data(), }; }), }); }); }, async createSub() { this.isLoading = true; const db = getFirestore(); const collectionRef = collection( db, "Subscribed", firebaseAuth.currentUser.uid, "checkout_sessions" ); const docRef = await addDoc(collectionRef, { mode: "payment", price: this.selectedPrice, success_url: window.location.href, cancel_url: window.location.href, }); onSnapshot(docRef, (snap) => { const { error, url } = snap.data(); if (error) { console.error(`An error occured: ${error.message}`); this.isLoading = false; } if (url) { window.location.assign(url); } }); }, }, }; </script> <template> <div class="row"> <div class="col"> <br><br> <h2 class="text-5xl text-red-700 font-serif">Cookie recipes</h2> <br> <hr /> <br><br> <div v-for="(product, index) in products" :key="index + '-product'"> <h3 class="text-3xl text-red-700 font-serif">{{ product.name }}</h3> <br> <div v-for="(price, priceIndex) in product.prices" :key="priceIndex + '-price'"> <div class="form-check"> <input type="radio" v-model="selectedPrice" :value="price.id" :id="price.id" :label="price.unit_amount" /> <label :for="price.id" class="cursor-pointer bg-neutral-800 hover:bg-neutral-900 active:bg-neutral-800 hover:scale-105 text-red-700 text-xl w-80 p-4 rounded-xl hover:text-neutral-400 shadow inline-block mx-10 transition ease-in-out duration-300 drop-shadow-2xl"> {{ price.interval_count }} {{ price.interval }} {{ price.id.price}} ${{ price.unit_amount/100 }} </label><br><br> </div> </div> </div> <button class="bg-neutral-800 hover:bg-neutral-900 active:bg-neutral-800 text-red-700 hover:text-neutral-400 hover:scale-105 text-xl w-64 p-4 rounded-xl shadow cursor-pointer focus:cursor-wait inline-block m-10 transition ease-in-out duration-300 drop-shadow-2xl" target="_blank" @click="createSub" :disabled="!selectedPrice || isLoading" > {{ isLoading ? "Loading..." : "Purchase Content" }} </button> </div> </div> </template>
需求与疑问
我需要在Checkout会话成功完成后,给Firestore的支付文档添加类似productId的额外字段,这样就能结合status字段查询用户是否购买了特定产品,进而展示对应内容。
补充说明:
checkout_sessions文档在跳转至Checkout页面时就已生成,没有支付成功状态字段;payment_intent_data仅存在于checkout_sessions文档,和payments集合的文档无关。
另外,我考虑过将支付文档的ID设为产品ID,通过查询status: succeeded来判断用户是否购买该产品,请问这个方案可行吗?
内容的提问来源于stack exchange,提问作者Epimetheus14
相关产品推荐
相关产品推荐

