我正在尝试设置一个教程内容页面,用户可以通过条纹结帐付款,一旦完成,他们就可以查看页面上的内容。
我正在使用 firebase 的 firestore 和 firebase run stripe payment 扩展进行付款,就结帐而言一切都工作正常,一旦完成,它就会在付款集合中为我提供新文档,其中包含金额、状态和所有内容。
问题是我有多种不同价格的不同产品,所以我无法使用状态字段来查询是否应该显示内容。我还尝试使用返回的金额字段来过滤付款,但我很快了解到,如果客户以外币付款,则金额会发生变化,因此也不起作用。
下面是我的查询过滤代码,其中失败的金额字段被用作我当前拥有的查询。
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>
我还想澄清一下,我使用的是 vue 作为显示页面。我还将包括价格选择页面,以便您可以看到下面的所有内容。
<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>
我最初尝试寻找解决方案的路径是条带文档中的条带结帐履行https://docs.stripe.com/checkout/fulfillment 不幸的是,我无法在 Firebase 文档中找到有关条带实现的任何信息,并且无法拼凑出它如何与 Firebase 扩展一起使用。
我真正需要做的就是在结帐会话成功完成时返回的文档中添加一个额外的字段,这样我可以使用包含 ProductId 的新字段或与状态字段类似的内容进行查询,然后如果正确则显示内容。因此,为了澄清这一点,需要在返回的条带文档中完成,因为除了手动阅读 firestore 文档之外,我无法判断结帐会话完成后是否已支付该特定产品。
这可以吗?如果可以,怎么做? 如果没有,还有其他方法可以实现我想要做的事情吗?
我建议尝试这样的事情:
const docRef = await addDoc(collectionRef, {
mode: "payment",
price: this.selectedPrice,
success_url: window.location.href,
cancel_url: window.location.href,
metadata: {
field: "value" // Should add field to checkout session document
},
payment_intent_data: {
metadata: {
field: "value" // Should add field to payments document
}
}
});
值得注意的是,这是 Stripe 知识,而不是 Firebase 知识。由于您使用的是 Firebase 库,我并不是 100% 肯定这会起作用,但是您在
addDoc
函数中设置的参数似乎与 Stripe 的 checkout 会话创建是一对一匹配的call,这表明这应该可行。