Как отправить параметры проверки сеанса Stripe в режиме подписки
Я совсем новичок в интеграции stripe, и из-за страны, в которой я нахожусь, я не могу получить доступ к странице сеанса оформления заказа из-за требований активации учетной записи. Поэтому я не могу увидеть все детали, отображаемые на странице оформления заказа, и не могу отладить ее. (Я нахожусь в тестовом режиме)
Я совсем запутался в том, как я могу отправить идентификатор цены выбранного мной продукта.
Я создал два продукта в своей панели управления и отображаю их на фронтенде с помощью кнопки оплаты, которая вызывает конечную точку checkout-session
.
это мой вид checkoutSession
class CreateCheckoutSession(APIView):
def post(self, request):
if request.method == 'POST':
try:
if request.user.is_authenticated:
print(request.user)
print(request.user.id)
checkout_session = stripe.checkout.Session.create(
client_reference_id=request.user.id,
payment_method_types=['card'],
line_items=[
{
'price': "",
'quantity': 1,
},
],
mode='subscription',
success_url=os.environ['DOMAIN_URL']+'/dashboard',
cancel_url=os.environ['DOMAIN_URL'],
)
return Response({'sessionId': checkout_session.id})
else:
return Response({'message': 'You need to register first.'}, status=403)
except InvalidRequestError as e:
error_message = str(e)
return Response({'error': error_message}, status=400)
else:
return Response({'error': 'Method not allowed'}, status=405)
Я думаю, что мне нужно отправить только идентификатор цены или идентификатор продукта (какой из них я должен отправить?) подписки, которую я хочу купить. Я не уверен, как я могу это сделать. Не мог бы кто-нибудь помочь мне здесь? Мой фронтенд - NEXTJS, а бэкенд - django с DRF
const handleSubscription = async () => {
try {
const response = await AxiosInstance.post("/checkout-session", {
});
const sessionId = response.data.sessionId;
const stripe = await loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
);
const { error } = await stripe.redirectToCheckout({
sessionId: sessionId,
});
if (error) {
console.error("Error:", error);
}
При вызове product api он выдает мне два массива, по одному на каждый товар. Мне нужна ваша помощь, чтобы понять, какие параметры я должен отправить товару, на который я подписываюсь? и как я могу их отправить?
Я пробовал реализовать код stripe, используя элементы stripe, а теперь переключился на код stripe low, поскольку он лучше всего подходит для моего текущего случая использования. Я не могу проверить, успешно ли проходит мой платеж, поскольку я не могу совершить платеж из своей страны до активации аккаунта из-за политики stripe.
В представлении CreateCheckoutSession
необходимо передать правильный price
идентификатор плана подписки, который вы хотите приобрести. Вот как можно изменить код, чтобы добиться этого:
class CreateCheckoutSession(APIView):
def post(self, request):
if request.method == 'POST':
try:
# Retrieve the selected price ID from the request data
price_id = request.data.get('price_id')
if request.user.is_authenticated:
print(request.user)
print(request.user.id)
checkout_session = stripe.checkout.Session.create(
client_reference_id=request.user.id,
payment_method_types=['card'],
line_items=[
{
'price': price_id, # Pass the selected price ID here
'quantity': 1,
},
],
mode='subscription',
success_url=os.environ['DOMAIN_URL']+'/dashboard',
cancel_url=os.environ['DOMAIN_URL'],
)
return Response({'sessionId': checkout_session.id})
else:
return Response({'message': 'You need to register first.'}, status=403)
except InvalidRequestError as e:
error_message = str(e)
return Response({'error': error_message}, status=400)
else:
return Response({'error': 'Method not allowed'}, status=405)
В коде вашего фронтенда при вызове конечной точки /checkout-session
обязательно включайте price_id
в данные запроса. Вот как это можно сделать:
const handleSubscription = async (priceId) => { // Pass the price ID as an argument
try {
const response = await AxiosInstance.post("/checkout-session", {
price_id: priceId, // Include the selected price ID in the request data
});
const sessionId = response.data.sessionId;
const stripe = await loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
);
const { error } = await stripe.redirectToCheckout({
sessionId: sessionId,
});
if (error) {
console.error("Error:", error);
}
} catch (error) {
console.error("Error:", error);
}
}
Убедитесь, что priceId
правильно передается из фронтенда при вызове handleSubscription
. Это позволит вам передать правильный план подписки в Stripe Checkout и продолжить оплату. Дайте мне знать, если вам нужна дополнительная помощь!
Я не могу совершить платеж из своей страны до активации аккаунта из-за политики stripe.
Почему вы не используете тестовые API-ключи? Вы можете проводить тестовые платежи и сеансы оформления заказа без активированной учетной записи Stripe.
Что касается форматирования массива line_items
, то у вас есть два варианта:
Используйте существующий идентификатор цены
. У вас уже есть код для этого, просто создайте продукт на вашем аккаунте Stripe, который будет иметь дочерний идентификатор цены (он может иметь несколько, например, продукт "Курс Python" может иметь объект цены "месячный план", который выставляет счета ежемесячно, и объект цены "годовой план").line_items=[ {'price':price_id, 'quantity':1}, {'price':price_id_2, 'quantity':2} ]
Обратите внимание, что в Checkout вы можете иметь одноразовые цены и повторяющиеся цены. При использовании mode='subscription'
необходимо иметь хотя бы одну повторяющуюся цену.
Создайте специальную цену в коде сессии оформления заказа
. Этот способ, по общему признанию, не так хорошо документирован, но это чрезвычайно мощный способ работы с ценами без необходимости создавать их в вашем аккаунте Stripe (или через API) заранее.line_items=[ # Ad hoc recurring price { 'price_data':{ 'unit_amount':amount, 'currency':'usd', 'recurring':{'interval':'month','interval_count':1}, 'product':prod_id }, 'quantity':1}, # Ad hoc one-time price { 'price_data':{ 'unit_amount':amount, 'currency':'usd', 'product_dada':{'name':'Product name'} }, 'quantity':2}, ]
Обратите внимание, как я использую product
для первой цены и product_data
для второй (вы должны использовать то или другое для любой цены). price_data
позволяет создать продукт в строке с сессией, точно так же, как price_data
делает это для цен.
---EDIT---.
Согласно вашим комментариям ниже, я не думаю, что это ответ на ваш вопрос. Ваша проблема заключается в том, как передать выбор клиента в бэкенд для нескольких цен без if
из case switch
утверждений.
Если бы у меня было такое требование, я бы использовал lookup_keys
:
- Давайте рассмотрим два выпадающих меню на лицевой стороне, одно для выбора продукта, а другое - для интервала.
- Когда клиент отправляет форму, вы можете объединить оба значения, чтобы они выглядели как 'prodA-month' или 'prodB-year'.
- На вашем аккаунте Stripe цены задаются с помощью ключей lookup_keys, подобных этим.
https://docs.stripe.com/api/prices/update#update_price-lookup_key - Затем вы можете просто передать эту конкатенированную строку в бэкэнд и искать свою цену с помощью списка цен и этого ключа lookup_key
. https://docs.stripe.com/api/prices/list#list_prices-lookup_keys
Вы также можете просто преобразовать строку в ID цены на вашем бэкенде с помощью других методов, таких как ваш собственный словарь, но это будет способ сделать это, используя инфраструктуру Stripe.
Вы можете просто отправить ID цены товара, который пользователь выбирает на фронтенде, в бэкенд при вызове представления CreateCheckoutSession.
const handleSubscription = async (priceId) => {
try {
const response = await AxiosInstance.post("/checkout-session", {
priceId: priceId
});
const sessionId = response.data.sessionId;
const stripe = await loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
);
const { error } = await stripe.redirectToCheckout({
sessionId: sessionId,
});
if (error) {
console.error("Error:", error);
}
} catch (error) {
console.error("Error:", error);
}
};
В бэкенде, в представлении CreateCheckoutSession, вы можете получить идентификатор цены товара и использовать его при создании платежной сессии со Stripe.
class CreateCheckoutSession(APIView):
def post(self, request):
if request.method == 'POST':
try:
price_id = request.data.get('priceId')
if request.user.is_authenticated:
print(request.user)
print(request.user.id)
checkout_session = stripe.checkout.Session.create(
client_reference_id=request.user.id,
payment_method_types=['card'],
line_items=[
{
'price': price_id, #### here
'quantity': 1,
},
],
mode='subscription',
success_url=os.environ['DOMAIN_URL']+'/dashboard',
cancel_url=os.environ['DOMAIN_URL'],
)
return Response({'sessionId': checkout_session.id})
else:
return Response({'message': 'You need to register first.'}, status=403)
except InvalidRequestError as e:
error_message = str(e)
return Response({'error': error_message}, status=400)
else:
return Response({'error': 'Method not allowed'}, status=405)
Я думаю, что для вас будет лучше, если ваши продукты будут находиться в базе данных. Обычно у вас есть определенное количество товаров, и в базе данных вы храните идентификатор товара и идентификаторы цен, которые вам нужны, а также название и цену (в поле базы данных). Таким образом, их будет легко получить с помощью ORM. Однако, если вы предпочитаете делать это таким образом,