| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "stripe/stripe_api_client.h"
- #include "stripe/stripe_error.h"
- #include "stripe/stripe_token.h"
- #include "stripe/stripe_form_encoder.h"
- #include <QtCore/QJsonObject>
- #include <QtCore/QJsonDocument>
- #include <QtNetwork/QNetworkRequest>
- #include <QtNetwork/QNetworkReply>
- #include <crl/crl_on_main.h>
- namespace Stripe {
- namespace {
- [[nodiscard]] QString APIURLBase() {
- return "api.stripe.com/v1";
- }
- [[nodiscard]] QString TokenEndpoint() {
- return "tokens";
- }
- [[nodiscard]] QString StripeAPIVersion() {
- return "2015-10-12";
- }
- [[nodiscard]] QString SDKVersion() {
- return "9.1.0";
- }
- [[nodiscard]] QString StripeUserAgentDetails() {
- const auto details = QJsonObject{
- { "lang", "objective-c" },
- { "bindings_version", SDKVersion() },
- };
- return QString::fromUtf8(
- QJsonDocument(details).toJson(QJsonDocument::Compact));
- }
- } // namespace
- APIClient::APIClient(PaymentConfiguration configuration)
- : _apiUrl("https://" + APIURLBase())
- , _configuration(configuration) {
- _additionalHttpHeaders = {
- { "X-Stripe-User-Agent", StripeUserAgentDetails() },
- { "Stripe-Version", StripeAPIVersion() },
- { "Authorization", "Bearer " + _configuration.publishableKey },
- };
- }
- APIClient::~APIClient() {
- const auto destroy = std::move(_old);
- }
- void APIClient::createTokenWithCard(
- CardParams card,
- TokenCompletionCallback completion) {
- createTokenWithData(
- FormEncoder::formEncodedDataForObject(MakeEncodable(card)),
- std::move(completion));
- }
- void APIClient::createTokenWithData(
- QByteArray data,
- TokenCompletionCallback completion) {
- const auto url = QUrl(_apiUrl + '/' + TokenEndpoint());
- auto request = QNetworkRequest(url);
- for (const auto &[name, value] : _additionalHttpHeaders) {
- request.setRawHeader(name.toUtf8(), value.toUtf8());
- }
- destroyReplyDelayed(std::move(_reply));
- _reply.reset(_manager.post(request, data));
- const auto finish = [=](Token token, Error error) {
- crl::on_main([
- completion,
- token = std::move(token),
- error = std::move(error)
- ] {
- completion(std::move(token), std::move(error));
- });
- };
- const auto finishWithError = [=](Error error) {
- finish(Token::Empty(), std::move(error));
- };
- const auto finishWithToken = [=](Token token) {
- finish(std::move(token), Error::None());
- };
- QObject::connect(_reply.get(), &QNetworkReply::finished, [=] {
- const auto replyError = int(_reply->error());
- const auto replyErrorString = _reply->errorString();
- const auto bytes = _reply->readAll();
- destroyReplyDelayed(std::move(_reply));
- auto parseError = QJsonParseError();
- const auto document = QJsonDocument::fromJson(bytes, &parseError);
- if (!bytes.isEmpty()) {
- if (parseError.error != QJsonParseError::NoError) {
- const auto code = int(parseError.error);
- finishWithError({
- Error::Code::JsonParse,
- QString("InvalidJson%1").arg(code),
- parseError.errorString(),
- });
- return;
- } else if (!document.isObject()) {
- finishWithError({
- Error::Code::JsonFormat,
- "InvalidJsonRoot",
- "Not an object in JSON reply.",
- });
- return;
- }
- const auto object = document.object();
- if (auto error = Error::DecodedObjectFromResponse(object)) {
- finishWithError(std::move(error));
- return;
- }
- }
- if (replyError != QNetworkReply::NoError) {
- finishWithError({
- Error::Code::Network,
- QString("RequestError%1").arg(replyError),
- replyErrorString,
- });
- return;
- }
- auto token = Token::DecodedObjectFromAPIResponse(document.object());
- if (!token) {
- finishWithError({
- Error::Code::JsonFormat,
- "InvalidTokenJson",
- "Could not parse token.",
- });
- }
- finishWithToken(std::move(token));
- });
- }
- void APIClient::destroyReplyDelayed(std::unique_ptr<QNetworkReply> reply) {
- if (!reply) {
- return;
- }
- const auto raw = reply.get();
- _old.push_back(std::move(reply));
- QObject::disconnect(raw, &QNetworkReply::finished, nullptr, nullptr);
- raw->deleteLater();
- QObject::connect(raw, &QObject::destroyed, [=] {
- for (auto i = begin(_old); i != end(_old); ++i) {
- if (i->get() == raw) {
- i->release();
- _old.erase(i);
- break;
- }
- }
- });
- }
- } // namespace Stripe
|