Изучив другие варианты, я узнал, что единственный способ решить проблему для моего варианта использования приема платежей по картам в моем веб-приложении Flutter — это использовать пакеты Flutter_stripe и flutter_stripe_web.
Я реализовал оба варианта, чтобы узнать, что Stripe.PaymentSheet НЕ поддерживается в Интернете. :( Благодаря поддержке Stripe я узнал, что вместо PaymentSheet мне следует использовать Stripe.PaymentElement, в то время как остальная часть кода остается прежней, то есть PaymentIntent, внутренняя функция и т. д.
Я попробовал следующий документ (хотя это немного неясно в контексте Flutter/dart), но я просто не могу заполнить недостающие блоки.
Не могли бы вы, ребята, взглянуть и сообщить мне, что я делаю неправильно или какой может быть правильный способ реализации PaymentElement вместо Sheets?
Заранее спасибо.
Мой файл платежа
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:http/http.dart' as http;
class StripePayments {
Future<void> initPaymentSheet(context,
{required String email, required int amount}) async {
try {
// 1. create payment intent on the server
final response = await http.post(
Uri.parse(
'https://mycloudFunctionUrl/stripePaymentIntentRequest'),
body: {
'email': email,
'amount': amount.toString(),
});
if (response.statusCode != 200) {
throw Exception('Failed to create payment intent: ${response.body}');
}
final jsonResponse = jsonDecode(response.body);
log('Payment intent response: $jsonResponse');
// 2. Verify the keys and data
if (jsonResponse['paymentIntent'] == null ||
jsonResponse['customer'] == null ||
jsonResponse['ephemeralKey'] == null) {
throw Exception('Invalid response from server: $jsonResponse');
}
// 3. initialize the payment sheet
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: jsonResponse['paymentIntent'],
merchantDisplayName: 'Cruise-App',
customerId: jsonResponse['customer'],
customerEphemeralKeySecret: jsonResponse['ephemeralKey'],
style: ThemeMode.light,
),
);
// 4. Present the payment sheet
await Stripe.instance.presentPaymentSheet();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Payment completed!')),
);
} catch (e) {
if (e is StripeException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error from Stripe: ${e.error.localizedMessage}'),
),
);
} else if (e is StripeConfigException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Stripe configuration error: ${e.message}'),
),
);
} else {
print(e.toString());
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')),
);
}
}
}
}
Вот как выглядит моя серверная/облачная функция
const functions = require("firebase-functions");
const cors = require("cors")({ origin: true });
const stripe = require("stripe")("sk_test_my_secret_key");
exports.stripePaymentIntentRequest = functions.region("europe-west3").https.onRequest((req, res) => {
cors(req, res, async () => {
try {
let customerId;
// Gets the customer whose email id matches the one sent by the client
const customerList = await stripe.customers.list({
email: req.body.email,
limit: 1
});
// Checks if the customer exists, if not creates a new customer
if (customerList.data.length !== 0) {
customerId = customerList.data[0].id;
} else {
const customer = await stripe.customers.create({
email: req.body.email
});
customerId = customer.id; // Changed customer.data.id to customer.id
}
// Creates a temporary secret key linked with the customer
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customerId },
{ apiVersion: '2020-08-27' }
);
// Creates a new payment intent with amount passed in from the client
const paymentIntent = await stripe.paymentIntents.create({
amount: parseInt(req.body.amount),
currency: 'nok',
customer: customerId,
});
res.status(200).send({
paymentIntent: paymentIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: customerId,
success: true,
});
} catch (error) {
res.status(404).send({ success: false, error: error.message });
}
});
});
Это документация, на которую меня направила команда Stripe, но их служба поддержки говорит в Discord: «Мы не знаем ни дротика, ни флаттера. Не знаю, как это делают люди, которые уже это сделали».
Пожалуйста, предложите! Еще раз спасибо
В моем общем коде вы можете увидеть шаг 3 — инициализация платежного листа и шаг 4 — представление платежного листа. Я хочу, чтобы эти функции были реализованы в чем-то, что Stripe называет PaymentElement, чего я не могу найти в методах библиотеки. Так что не уверен, что делать дальше
вы можете напрямую использовать виджет PaymentElement. У меня мало знаний по этому поводу, но это может помочь вам начать работу.
var paymentIntentResult = await createPaymentIntent('100','JYP');
var paymentIntentSecret = paymentIntentResult['client_secret'];
PaymentElement(
autofocus: true,
enablePostalCode: true,
onCardChanged: (_) {},
clientSecret: paymentIntentSecret ?? '',
)
createPaymentIntent(String amount, String currency) async {
try {
//Request body
Map<String, dynamic> body = {
'amount': calculateAmount(amount),
'currency': currency,
};
//Make post request to Stripe
var response = await http.post(
Uri.parse('https://api.stripe.com/v1/payment_intents'),
headers: {
'Authorization':
'Bearer [your_key]',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: body,
);
return json.decode(response.body);
} catch (err) {
throw Exception(err.toString());
}
и используйте это, чтобы вызвать
OutlinedButton(
onPressed: () async {
try {
await WebStripe.instance
.confirmPaymentElement(ConfirmPaymentElementOptions(
redirect: PaymentConfirmationRedirect.ifRequired,
confirmParams: ConfirmPaymentParams(return_url: ''),
));
} on Exception catch (e) {
print(e.toString());
}
},
child: Text('Go'));
это не полный ответ для моего случая, но в большинстве случаев это действительно указывало правильный путь. Спасибо.
Можете ли вы предоставить более подробную информацию о том, что не работает? Вы поделились кодом, но не знаете, что вас заблокировало.