common: add paddle billing api client
This commit is contained in:
committed by
Abdullah Atta
parent
ed6e3c56f2
commit
3beb716b83
@@ -37,19 +37,21 @@ namespace Streetwriters.Common.Extensions
|
||||
request.Content = content;
|
||||
}
|
||||
|
||||
foreach (var header in headers)
|
||||
if (headers != null)
|
||||
{
|
||||
if (header.Key == "Content-Type" || header.Key == "Content-Length")
|
||||
foreach (var header in headers)
|
||||
{
|
||||
if (request.Content != null)
|
||||
request.Content.Headers.TryAddWithoutValidation(header.Key, header.Value.AsEnumerable());
|
||||
continue;
|
||||
if (header.Key == "Content-Type" || header.Key == "Content-Length")
|
||||
{
|
||||
request.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.AsEnumerable());
|
||||
continue;
|
||||
}
|
||||
request.Headers.TryAddWithoutValidation(header.Key, header.Value.AsEnumerable());
|
||||
}
|
||||
request.Headers.TryAddWithoutValidation(header.Key, header.Value.AsEnumerable());
|
||||
}
|
||||
|
||||
var response = await httpClient.SendAsync(request);
|
||||
if (response.Content.Headers.ContentLength > 0)
|
||||
if (response.Content.Headers.ContentLength > 0 && response.Content.Headers.ContentType.ToString().Contains("application/json"))
|
||||
{
|
||||
var res = await response.Content.ReadFromJsonAsync<T>();
|
||||
res.Success = response.IsSuccessStatusCode;
|
||||
@@ -58,7 +60,7 @@ namespace Streetwriters.Common.Extensions
|
||||
}
|
||||
else
|
||||
{
|
||||
return new T { Success = response.IsSuccessStatusCode, StatusCode = (int)response.StatusCode };
|
||||
return new T { Success = response.IsSuccessStatusCode, StatusCode = (int)response.StatusCode, Content = response.Content };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,14 @@ You should have received a copy of the Affero GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Streetwriters.Common.Interfaces
|
||||
{
|
||||
public interface IResponse
|
||||
{
|
||||
bool Success { get; set; }
|
||||
int StatusCode { get; set; }
|
||||
HttpContent Content { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,223 @@
|
||||
/*
|
||||
This file is part of the Notesnook Sync Server project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the Affero GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
Affero GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the Affero GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
using Streetwriters.Common.Interfaces;
|
||||
|
||||
namespace Streetwriters.Common.Models
|
||||
{
|
||||
public class SubscriptionResponse : Response
|
||||
{
|
||||
[JsonPropertyName("subscription")]
|
||||
public ISubscription Subscription { get; set; }
|
||||
}
|
||||
}
|
||||
namespace Streetwriters.Common.Models
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Globalization;
|
||||
|
||||
public partial class GetSubscriptionResponse
|
||||
{
|
||||
[JsonPropertyName("data")]
|
||||
public Data Data { get; set; }
|
||||
|
||||
[JsonPropertyName("meta")]
|
||||
public Meta Meta { get; set; }
|
||||
}
|
||||
|
||||
public partial class Data
|
||||
{
|
||||
// [JsonPropertyName("id")]
|
||||
// public string Id { get; set; }
|
||||
|
||||
// [JsonPropertyName("status")]
|
||||
// public string Status { get; set; }
|
||||
|
||||
[JsonPropertyName("customer_id")]
|
||||
public string CustomerId { get; set; }
|
||||
|
||||
// [JsonPropertyName("address_id")]
|
||||
// public string AddressId { get; set; }
|
||||
|
||||
// [JsonPropertyName("business_id")]
|
||||
// public object BusinessId { get; set; }
|
||||
|
||||
// [JsonPropertyName("currency_code")]
|
||||
// public string CurrencyCode { get; set; }
|
||||
|
||||
// [JsonPropertyName("created_at")]
|
||||
// public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("updated_at")]
|
||||
// public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("started_at")]
|
||||
// public DateTimeOffset StartedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("first_billed_at")]
|
||||
public DateTimeOffset? FirstBilledAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("next_billed_at")]
|
||||
// public DateTimeOffset NextBilledAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("paused_at")]
|
||||
// public object PausedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("canceled_at")]
|
||||
// public object CanceledAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("collection_mode")]
|
||||
// public string CollectionMode { get; set; }
|
||||
|
||||
// [JsonPropertyName("billing_details")]
|
||||
// public object BillingDetails { get; set; }
|
||||
|
||||
// [JsonPropertyName("current_billing_period")]
|
||||
// public CurrentBillingPeriod CurrentBillingPeriod { get; set; }
|
||||
|
||||
[JsonPropertyName("billing_cycle")]
|
||||
public BillingCycle BillingCycle { get; set; }
|
||||
|
||||
// [JsonPropertyName("scheduled_change")]
|
||||
// public object ScheduledChange { get; set; }
|
||||
|
||||
// [JsonPropertyName("items")]
|
||||
// public Item[] Items { get; set; }
|
||||
|
||||
// [JsonPropertyName("custom_data")]
|
||||
// public object CustomData { get; set; }
|
||||
|
||||
[JsonPropertyName("management_urls")]
|
||||
public ManagementUrls ManagementUrls { get; set; }
|
||||
|
||||
// [JsonPropertyName("discount")]
|
||||
// public object Discount { get; set; }
|
||||
|
||||
// [JsonPropertyName("import_meta")]
|
||||
// public object ImportMeta { get; set; }
|
||||
}
|
||||
|
||||
public partial class BillingCycle
|
||||
{
|
||||
[JsonPropertyName("frequency")]
|
||||
public long Frequency { get; set; }
|
||||
|
||||
[JsonPropertyName("interval")]
|
||||
public string Interval { get; set; }
|
||||
}
|
||||
|
||||
// public partial class CurrentBillingPeriod
|
||||
// {
|
||||
// [JsonPropertyName("starts_at")]
|
||||
// public DateTimeOffset StartsAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("ends_at")]
|
||||
// public DateTimeOffset EndsAt { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class Item
|
||||
// {
|
||||
// [JsonPropertyName("status")]
|
||||
// public string Status { get; set; }
|
||||
|
||||
// [JsonPropertyName("quantity")]
|
||||
// public long Quantity { get; set; }
|
||||
|
||||
// [JsonPropertyName("recurring")]
|
||||
// public bool Recurring { get; set; }
|
||||
|
||||
// [JsonPropertyName("created_at")]
|
||||
// public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("updated_at")]
|
||||
// public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("previously_billed_at")]
|
||||
// public DateTimeOffset PreviouslyBilledAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("next_billed_at")]
|
||||
// public DateTimeOffset NextBilledAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("trial_dates")]
|
||||
// public object TrialDates { get; set; }
|
||||
|
||||
// [JsonPropertyName("price")]
|
||||
// public Price Price { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class Price
|
||||
// {
|
||||
// [JsonPropertyName("id")]
|
||||
// public string Id { get; set; }
|
||||
|
||||
// [JsonPropertyName("product_id")]
|
||||
// public string ProductId { get; set; }
|
||||
|
||||
// [JsonPropertyName("type")]
|
||||
// public string Type { get; set; }
|
||||
|
||||
// [JsonPropertyName("description")]
|
||||
// public string Description { get; set; }
|
||||
|
||||
// [JsonPropertyName("name")]
|
||||
// public string Name { get; set; }
|
||||
|
||||
// [JsonPropertyName("tax_mode")]
|
||||
// public string TaxMode { get; set; }
|
||||
|
||||
// [JsonPropertyName("billing_cycle")]
|
||||
// public BillingCycle BillingCycle { get; set; }
|
||||
|
||||
// [JsonPropertyName("trial_period")]
|
||||
// public object TrialPeriod { get; set; }
|
||||
|
||||
// [JsonPropertyName("unit_price")]
|
||||
// public UnitPrice UnitPrice { get; set; }
|
||||
|
||||
// [JsonPropertyName("unit_price_overrides")]
|
||||
// public object[] UnitPriceOverrides { get; set; }
|
||||
|
||||
// [JsonPropertyName("custom_data")]
|
||||
// public object CustomData { get; set; }
|
||||
|
||||
// [JsonPropertyName("status")]
|
||||
// public string Status { get; set; }
|
||||
|
||||
// [JsonPropertyName("quantity")]
|
||||
// public Quantity Quantity { get; set; }
|
||||
|
||||
// [JsonPropertyName("import_meta")]
|
||||
// public object ImportMeta { get; set; }
|
||||
|
||||
// [JsonPropertyName("created_at")]
|
||||
// public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("updated_at")]
|
||||
// public DateTimeOffset UpdatedAt { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class Quantity
|
||||
// {
|
||||
// [JsonPropertyName("minimum")]
|
||||
// public long Minimum { get; set; }
|
||||
|
||||
// [JsonPropertyName("maximum")]
|
||||
// public long Maximum { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class UnitPrice
|
||||
// {
|
||||
// [JsonPropertyName("amount")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Amount { get; set; }
|
||||
|
||||
// [JsonPropertyName("currency_code")]
|
||||
// public string CurrencyCode { get; set; }
|
||||
// }
|
||||
|
||||
public partial class ManagementUrls
|
||||
{
|
||||
[JsonPropertyName("update_payment_method")]
|
||||
public Uri UpdatePaymentMethod { get; set; }
|
||||
|
||||
[JsonPropertyName("cancel")]
|
||||
public Uri Cancel { get; set; }
|
||||
}
|
||||
|
||||
public partial class Meta
|
||||
{
|
||||
[JsonPropertyName("request_id")]
|
||||
public string RequestId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
25
Streetwriters.Common/Models/GetTransactionInvoiceResponse.cs
Normal file
25
Streetwriters.Common/Models/GetTransactionInvoiceResponse.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace Streetwriters.Common.Models
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Globalization;
|
||||
|
||||
public partial class GetTransactionInvoiceResponse
|
||||
{
|
||||
[JsonPropertyName("data")]
|
||||
public Invoice Invoice { get; set; }
|
||||
|
||||
[JsonPropertyName("meta")]
|
||||
public Meta Meta { get; set; }
|
||||
}
|
||||
|
||||
public partial class Invoice
|
||||
{
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
||||
18
Streetwriters.Common/Models/GetTransactionResponse.cs
Normal file
18
Streetwriters.Common/Models/GetTransactionResponse.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace Streetwriters.Common.Models
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Globalization;
|
||||
|
||||
public partial class GetTransactionResponse
|
||||
{
|
||||
[JsonPropertyName("data")]
|
||||
public TransactionV2 Transaction { get; set; }
|
||||
|
||||
[JsonPropertyName("meta")]
|
||||
public Meta Meta { get; set; }
|
||||
}
|
||||
}
|
||||
520
Streetwriters.Common/Models/ListTransactionsResponseV2.cs
Normal file
520
Streetwriters.Common/Models/ListTransactionsResponseV2.cs
Normal file
@@ -0,0 +1,520 @@
|
||||
namespace Streetwriters.Common.Models
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Globalization;
|
||||
|
||||
public partial class ListTransactionsResponseV2
|
||||
{
|
||||
[JsonPropertyName("data")]
|
||||
public TransactionV2[] Transactions { get; set; }
|
||||
|
||||
[JsonPropertyName("meta")]
|
||||
public Meta Meta { get; set; }
|
||||
}
|
||||
|
||||
public partial class TransactionV2
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonPropertyName("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
[JsonPropertyName("customer_id")]
|
||||
public string CustomerId { get; set; }
|
||||
|
||||
// [JsonPropertyName("address_id")]
|
||||
// public string AddressId { get; set; }
|
||||
|
||||
// [JsonPropertyName("business_id")]
|
||||
// public object BusinessId { get; set; }
|
||||
|
||||
[JsonPropertyName("custom_data")]
|
||||
public Dictionary<string, string> CustomData { get; set; }
|
||||
|
||||
[JsonPropertyName("origin")]
|
||||
public string Origin { get; set; }
|
||||
|
||||
// [JsonPropertyName("collection_mode")]
|
||||
// public string CollectionMode { get; set; }
|
||||
|
||||
// [JsonPropertyName("subscription_id")]
|
||||
// public string SubscriptionId { get; set; }
|
||||
|
||||
// [JsonPropertyName("invoice_id")]
|
||||
// public string InvoiceId { get; set; }
|
||||
|
||||
// [JsonPropertyName("invoice_number")]
|
||||
// public string InvoiceNumber { get; set; }
|
||||
|
||||
[JsonPropertyName("billing_details")]
|
||||
public BillingDetails BillingDetails { get; set; }
|
||||
|
||||
[JsonPropertyName("billing_period")]
|
||||
public BillingPeriod BillingPeriod { get; set; }
|
||||
|
||||
// [JsonPropertyName("currency_code")]
|
||||
// public string CurrencyCode { get; set; }
|
||||
|
||||
// [JsonPropertyName("discount_id")]
|
||||
// public string DiscountId { get; set; }
|
||||
|
||||
[JsonPropertyName("created_at")]
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("updated_at")]
|
||||
// public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("billed_at")]
|
||||
public DateTimeOffset? BilledAt { get; set; }
|
||||
|
||||
[JsonPropertyName("items")]
|
||||
public Item[] Items { get; set; }
|
||||
|
||||
[JsonPropertyName("details")]
|
||||
public Details Details { get; set; }
|
||||
|
||||
// [JsonPropertyName("payments")]
|
||||
// public Payment[] Payments { get; set; }
|
||||
|
||||
// [JsonPropertyName("checkout")]
|
||||
// public Checkout Checkout { get; set; }
|
||||
}
|
||||
|
||||
public partial class BillingDetails
|
||||
{
|
||||
// [JsonPropertyName("enable_checkout")]
|
||||
// public bool EnableCheckout { get; set; }
|
||||
|
||||
[JsonPropertyName("payment_terms")]
|
||||
public PaymentTerms PaymentTerms { get; set; }
|
||||
|
||||
// [JsonPropertyName("purchase_order_number")]
|
||||
// public string PurchaseOrderNumber { get; set; }
|
||||
|
||||
// [JsonPropertyName("additional_information")]
|
||||
// public object AdditionalInformation { get; set; }
|
||||
}
|
||||
|
||||
public partial class PaymentTerms
|
||||
{
|
||||
[JsonPropertyName("interval")]
|
||||
public string Interval { get; set; }
|
||||
|
||||
[JsonPropertyName("frequency")]
|
||||
public long Frequency { get; set; }
|
||||
}
|
||||
|
||||
public partial class BillingPeriod
|
||||
{
|
||||
[JsonPropertyName("starts_at")]
|
||||
public DateTimeOffset StartsAt { get; set; }
|
||||
|
||||
[JsonPropertyName("ends_at")]
|
||||
public DateTimeOffset EndsAt { get; set; }
|
||||
}
|
||||
|
||||
// public partial class Checkout
|
||||
// {
|
||||
// [JsonPropertyName("url")]
|
||||
// public Uri Url { get; set; }
|
||||
// }
|
||||
|
||||
public partial class Details
|
||||
{
|
||||
// [JsonPropertyName("tax_rates_used")]
|
||||
// public TaxRatesUsed[] TaxRatesUsed { get; set; }
|
||||
|
||||
[JsonPropertyName("totals")]
|
||||
public Totals Totals { get; set; }
|
||||
|
||||
// [JsonPropertyName("adjusted_totals")]
|
||||
// public AdjustedTotals AdjustedTotals { get; set; }
|
||||
|
||||
// [JsonPropertyName("payout_totals")]
|
||||
// public Dictionary<string, string> PayoutTotals { get; set; }
|
||||
|
||||
// [JsonPropertyName("adjusted_payout_totals")]
|
||||
// public AdjustedTotals AdjustedPayoutTotals { get; set; }
|
||||
|
||||
[JsonPropertyName("line_items")]
|
||||
public LineItem[] LineItems { get; set; }
|
||||
}
|
||||
|
||||
public partial class Totals
|
||||
{
|
||||
[JsonPropertyName("subtotal")]
|
||||
public long Subtotal { get; set; }
|
||||
|
||||
[JsonPropertyName("tax")]
|
||||
public long Tax { get; set; }
|
||||
|
||||
[JsonPropertyName("discount")]
|
||||
public long Discount { get; set; }
|
||||
|
||||
[JsonPropertyName("total")]
|
||||
public long Total { get; set; }
|
||||
|
||||
[JsonPropertyName("grand_total")]
|
||||
public long GrandTotal { get; set; }
|
||||
|
||||
// [JsonPropertyName("fee")]
|
||||
// public object Fee { get; set; }
|
||||
|
||||
// [JsonPropertyName("credit")]
|
||||
// public long Credit { get; set; }
|
||||
|
||||
// [JsonPropertyName("credit_to_balance")]
|
||||
// public long CreditToBalance { get; set; }
|
||||
|
||||
[JsonPropertyName("balance")]
|
||||
public long Balance { get; set; }
|
||||
|
||||
// [JsonPropertyName("earnings")]
|
||||
// public object Earnings { get; set; }
|
||||
|
||||
[JsonPropertyName("currency_code")]
|
||||
public string CurrencyCode { get; set; }
|
||||
}
|
||||
// public partial class AdjustedTotals
|
||||
// {
|
||||
// [JsonPropertyName("subtotal")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Subtotal { get; set; }
|
||||
|
||||
// [JsonPropertyName("tax")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Tax { get; set; }
|
||||
|
||||
// [JsonPropertyName("total")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Total { get; set; }
|
||||
|
||||
// [JsonPropertyName("fee")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Fee { get; set; }
|
||||
|
||||
// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
// [JsonPropertyName("chargeback_fee")]
|
||||
// public ChargebackFee ChargebackFee { get; set; }
|
||||
|
||||
// [JsonPropertyName("earnings")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Earnings { get; set; }
|
||||
|
||||
// [JsonPropertyName("currency_code")]
|
||||
// public string CurrencyCode { get; set; }
|
||||
|
||||
// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
// [JsonPropertyName("grand_total")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long? GrandTotal { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class ChargebackFee
|
||||
// {
|
||||
// [JsonPropertyName("amount")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Amount { get; set; }
|
||||
|
||||
// [JsonPropertyName("original")]
|
||||
// public object Original { get; set; }
|
||||
// }
|
||||
|
||||
public partial class LineItem
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonPropertyName("price_id")]
|
||||
public string PriceId { get; set; }
|
||||
|
||||
// [JsonPropertyName("quantity")]
|
||||
// public long Quantity { get; set; }
|
||||
|
||||
// [JsonPropertyName("totals")]
|
||||
// public Totals Totals { get; set; }
|
||||
|
||||
// [JsonPropertyName("product")]
|
||||
// public Product Product { get; set; }
|
||||
|
||||
// [JsonPropertyName("tax_rate")]
|
||||
// public string TaxRate { get; set; }
|
||||
|
||||
// [JsonPropertyName("unit_totals")]
|
||||
// public Totals UnitTotals { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("proration")]
|
||||
public Proration Proration { get; set; }
|
||||
}
|
||||
|
||||
// public partial class Product
|
||||
// {
|
||||
// [JsonPropertyName("id")]
|
||||
// public string Id { get; set; }
|
||||
|
||||
// [JsonPropertyName("name")]
|
||||
// public string Name { get; set; }
|
||||
|
||||
// [JsonPropertyName("description")]
|
||||
// public string Description { get; set; }
|
||||
|
||||
// [JsonPropertyName("type")]
|
||||
// public TypeEnum Type { get; set; }
|
||||
|
||||
// [JsonPropertyName("tax_category")]
|
||||
// public TypeEnum TaxCategory { get; set; }
|
||||
|
||||
// [JsonPropertyName("image_url")]
|
||||
// public Uri ImageUrl { get; set; }
|
||||
|
||||
// [JsonPropertyName("custom_data")]
|
||||
// public CustomData CustomData { get; set; }
|
||||
|
||||
// [JsonPropertyName("status")]
|
||||
// public Status Status { get; set; }
|
||||
|
||||
// [JsonPropertyName("created_at")]
|
||||
// public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("updated_at")]
|
||||
// public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("import_meta")]
|
||||
// public object ImportMeta { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class CustomData
|
||||
// {
|
||||
// [JsonPropertyName("features")]
|
||||
// public Features Features { get; set; }
|
||||
|
||||
// [JsonPropertyName("suggested_addons")]
|
||||
// public string[] SuggestedAddons { get; set; }
|
||||
|
||||
// [JsonPropertyName("upgrade_description")]
|
||||
// public string UpgradeDescription { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class Features
|
||||
// {
|
||||
// [JsonPropertyName("aircraft_performance")]
|
||||
// public bool AircraftPerformance { get; set; }
|
||||
|
||||
// [JsonPropertyName("compliance_monitoring")]
|
||||
// public bool ComplianceMonitoring { get; set; }
|
||||
|
||||
// [JsonPropertyName("flight_log_management")]
|
||||
// public bool FlightLogManagement { get; set; }
|
||||
|
||||
// [JsonPropertyName("payment_by_invoice")]
|
||||
// public bool PaymentByInvoice { get; set; }
|
||||
|
||||
// [JsonPropertyName("route_planning")]
|
||||
// public bool RoutePlanning { get; set; }
|
||||
|
||||
// [JsonPropertyName("sso")]
|
||||
// public bool Sso { get; set; }
|
||||
// }
|
||||
|
||||
public partial class Proration
|
||||
{
|
||||
[JsonPropertyName("billing_period")]
|
||||
public BillingPeriod BillingPeriod { get; set; }
|
||||
}
|
||||
|
||||
// public partial class Totals
|
||||
// {
|
||||
// [JsonPropertyName("subtotal")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Subtotal { get; set; }
|
||||
|
||||
// [JsonPropertyName("discount")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Discount { get; set; }
|
||||
|
||||
// [JsonPropertyName("tax")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Tax { get; set; }
|
||||
|
||||
// [JsonPropertyName("total")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Total { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class TaxRatesUsed
|
||||
// {
|
||||
// [JsonPropertyName("tax_rate")]
|
||||
// public string TaxRate { get; set; }
|
||||
|
||||
// [JsonPropertyName("totals")]
|
||||
// public Totals Totals { get; set; }
|
||||
// }
|
||||
|
||||
public partial class Item
|
||||
{
|
||||
[JsonPropertyName("price")]
|
||||
public Price Price { get; set; }
|
||||
|
||||
[JsonPropertyName("quantity")]
|
||||
public long Quantity { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("proration")]
|
||||
public Proration Proration { get; set; }
|
||||
}
|
||||
|
||||
public partial class Price
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
// [JsonPropertyName("description")]
|
||||
// public string Description { get; set; }
|
||||
|
||||
// [JsonPropertyName("type")]
|
||||
// public TypeEnum Type { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
// [JsonPropertyName("product_id")]
|
||||
// public string ProductId { get; set; }
|
||||
|
||||
// [JsonPropertyName("billing_cycle")]
|
||||
// public PaymentTerms BillingCycle { get; set; }
|
||||
|
||||
// [JsonPropertyName("trial_period")]
|
||||
// public object TrialPeriod { get; set; }
|
||||
|
||||
// [JsonPropertyName("tax_mode")]
|
||||
// public TaxMode TaxMode { get; set; }
|
||||
|
||||
// [JsonPropertyName("unit_price")]
|
||||
// public UnitPrice UnitPrice { get; set; }
|
||||
|
||||
// [JsonPropertyName("unit_price_overrides")]
|
||||
// public object[] UnitPriceOverrides { get; set; }
|
||||
|
||||
// [JsonPropertyName("custom_data")]
|
||||
// public object CustomData { get; set; }
|
||||
|
||||
// [JsonPropertyName("quantity")]
|
||||
// public Quantity Quantity { get; set; }
|
||||
|
||||
// [JsonPropertyName("status")]
|
||||
// public Status Status { get; set; }
|
||||
|
||||
// [JsonPropertyName("created_at")]
|
||||
// public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("updated_at")]
|
||||
// public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("import_meta")]
|
||||
// public object ImportMeta { get; set; }
|
||||
}
|
||||
|
||||
// public partial class Quantity
|
||||
// {
|
||||
// [JsonPropertyName("minimum")]
|
||||
// public long Minimum { get; set; }
|
||||
|
||||
// [JsonPropertyName("maximum")]
|
||||
// public long Maximum { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class UnitPrice
|
||||
// {
|
||||
// [JsonPropertyName("amount")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Amount { get; set; }
|
||||
|
||||
// [JsonPropertyName("currency_code")]
|
||||
// public CurrencyCode CurrencyCode { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class Payment
|
||||
// {
|
||||
// [JsonPropertyName("payment_attempt_id")]
|
||||
// public Guid PaymentAttemptId { get; set; }
|
||||
|
||||
// [JsonPropertyName("stored_payment_method_id")]
|
||||
// public Guid StoredPaymentMethodId { get; set; }
|
||||
|
||||
// [JsonPropertyName("payment_method_id")]
|
||||
// public string PaymentMethodId { get; set; }
|
||||
|
||||
// [JsonPropertyName("amount")]
|
||||
// [JsonConverter(typeof(ParseStringConverter))]
|
||||
// public long Amount { get; set; }
|
||||
|
||||
// [JsonPropertyName("status")]
|
||||
// public string Status { get; set; }
|
||||
|
||||
// [JsonPropertyName("error_code")]
|
||||
// public string ErrorCode { get; set; }
|
||||
|
||||
// [JsonPropertyName("method_details")]
|
||||
// public MethodDetails MethodDetails { get; set; }
|
||||
|
||||
// [JsonPropertyName("created_at")]
|
||||
// public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
// [JsonPropertyName("captured_at")]
|
||||
// public DateTimeOffset? CapturedAt { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class MethodDetails
|
||||
// {
|
||||
// [JsonPropertyName("type")]
|
||||
// public string Type { get; set; }
|
||||
|
||||
// [JsonPropertyName("card")]
|
||||
// public Card Card { get; set; }
|
||||
// }
|
||||
|
||||
// public partial class Card
|
||||
// {
|
||||
// [JsonPropertyName("type")]
|
||||
// public string Type { get; set; }
|
||||
|
||||
// [JsonPropertyName("last4")]
|
||||
// public string Last4 { get; set; }
|
||||
|
||||
// [JsonPropertyName("expiry_month")]
|
||||
// public long ExpiryMonth { get; set; }
|
||||
|
||||
// [JsonPropertyName("expiry_year")]
|
||||
// public long ExpiryYear { get; set; }
|
||||
|
||||
// [JsonPropertyName("cardholder_name")]
|
||||
// public string CardholderName { get; set; }
|
||||
// }
|
||||
|
||||
public partial class Meta
|
||||
{
|
||||
[JsonPropertyName("pagination")]
|
||||
public Pagination Pagination { get; set; }
|
||||
}
|
||||
|
||||
public partial class Pagination
|
||||
{
|
||||
[JsonPropertyName("per_page")]
|
||||
public long PerPage { get; set; }
|
||||
|
||||
[JsonPropertyName("next")]
|
||||
public Uri Next { get; set; }
|
||||
|
||||
[JsonPropertyName("has_more")]
|
||||
public bool HasMore { get; set; }
|
||||
|
||||
[JsonPropertyName("estimated_total")]
|
||||
public long EstimatedTotal { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ You should have received a copy of the Affero GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Net.Http;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
using Streetwriters.Common.Interfaces;
|
||||
@@ -28,5 +29,7 @@ namespace Streetwriters.Common.Models
|
||||
[JsonIgnore]
|
||||
public bool Success { get; set; }
|
||||
public int StatusCode { get; set; }
|
||||
[JsonIgnore]
|
||||
public HttpContent Content { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
60
Streetwriters.Common/Models/SubscriptionPreviewResponse.cs
Normal file
60
Streetwriters.Common/Models/SubscriptionPreviewResponse.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace Streetwriters.Common.Models
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Globalization;
|
||||
|
||||
public partial class SubscriptionPreviewResponse
|
||||
{
|
||||
[JsonPropertyName("data")]
|
||||
public SubscriptionPreviewData Data { get; set; }
|
||||
|
||||
[JsonPropertyName("meta")]
|
||||
public Meta Meta { get; set; }
|
||||
}
|
||||
|
||||
public partial class SubscriptionPreviewData
|
||||
{
|
||||
[JsonPropertyName("currency_code")]
|
||||
public string CurrencyCode { get; set; }
|
||||
|
||||
[JsonPropertyName("billing_cycle")]
|
||||
public BillingCycle BillingCycle { get; set; }
|
||||
|
||||
[JsonPropertyName("update_summary")]
|
||||
public UpdateSummary UpdateSummary { get; set; }
|
||||
|
||||
[JsonPropertyName("immediate_transaction")]
|
||||
public TransactionV2 ImmediateTransaction { get; set; }
|
||||
|
||||
[JsonPropertyName("next_transaction")]
|
||||
public TransactionV2 NextTransaction { get; set; }
|
||||
|
||||
[JsonPropertyName("recurring_transaction_details")]
|
||||
public Details RecurringTransactionDetails { get; set; }
|
||||
}
|
||||
|
||||
public partial class UpdateSummary
|
||||
{
|
||||
[JsonPropertyName("charge")]
|
||||
public UpdateSummaryItem Charge { get; set; }
|
||||
|
||||
[JsonPropertyName("credit")]
|
||||
public UpdateSummaryItem Credit { get; set; }
|
||||
|
||||
[JsonPropertyName("result")]
|
||||
public UpdateSummaryItem Result { get; set; }
|
||||
}
|
||||
|
||||
public partial class UpdateSummaryItem
|
||||
{
|
||||
[JsonPropertyName("amount")]
|
||||
public long Amount { get; set; }
|
||||
|
||||
[JsonPropertyName("action")]
|
||||
public string? Action { get; set; }
|
||||
}
|
||||
}
|
||||
129
Streetwriters.Common/Services/PaddleBillingService.cs
Normal file
129
Streetwriters.Common/Services/PaddleBillingService.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Streetwriters.Common.Models;
|
||||
|
||||
namespace Streetwriters.Common.Services
|
||||
{
|
||||
public class PaddleBillingService
|
||||
{
|
||||
#if DEBUG
|
||||
private const string PADDLE_BASE_URI = "https://sandbox-api.paddle.com";
|
||||
#else
|
||||
private const string PADDLE_BASE_URI = "https://api.paddle.com";
|
||||
#endif
|
||||
private readonly HttpClient httpClient = new();
|
||||
public PaddleBillingService(string paddleApiKey)
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", paddleApiKey);
|
||||
}
|
||||
|
||||
public async Task<GetSubscriptionResponse?> GetSubscriptionAsync(string subscriptionId)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/subscriptions/{subscriptionId}";
|
||||
var response = await httpClient.GetAsync(url);
|
||||
return await response.Content.ReadFromJsonAsync<GetSubscriptionResponse>();
|
||||
}
|
||||
|
||||
public async Task<GetTransactionResponse?> GetTransactionAsync(string transactionId)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/transactions/{transactionId}";
|
||||
var response = await httpClient.GetAsync(url);
|
||||
return await response.Content.ReadFromJsonAsync<GetTransactionResponse>();
|
||||
}
|
||||
|
||||
public async Task<GetTransactionInvoiceResponse?> GetTransactionInvoiceAsync(string transactionId)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/transactions/{transactionId}/invoice";
|
||||
var response = await httpClient.GetAsync(url);
|
||||
return await response.Content.ReadFromJsonAsync<GetTransactionInvoiceResponse>();
|
||||
}
|
||||
|
||||
public async Task<ListTransactionsResponseV2?> ListTransactionsAsync(string? subscriptionId = null, string? customerId = null, string[]? status = null, string[]? origin = null)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/transactions";
|
||||
var parameters = new Dictionary<string, string?>()
|
||||
{
|
||||
{ "subscription_id", subscriptionId },
|
||||
{ "customer_id", customerId },
|
||||
{ "status", string.Join(',', status ?? ["billed","completed"]) },
|
||||
{ "order_by", "billed_at[DESC]" }
|
||||
};
|
||||
if (origin is not null) parameters.Add("origin", string.Join(',', origin));
|
||||
var response = await httpClient.GetAsync(QueryHelpers.AddQueryString(url, parameters));
|
||||
|
||||
return await response.Content.ReadFromJsonAsync<ListTransactionsResponseV2>();
|
||||
}
|
||||
|
||||
public async Task<bool> RefundTransactionAsync(string transactionId, string transactionItemId, string reason = "")
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/adjustments";
|
||||
var response = await httpClient.PostAsync(url, JsonContent.Create(new Dictionary<string, object>
|
||||
{
|
||||
{ "action", "refund" },
|
||||
{
|
||||
"items",
|
||||
new object[]
|
||||
{
|
||||
new Dictionary<string, string> {
|
||||
{"item_id", transactionItemId},
|
||||
{"type", "full"}
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "reason", reason },
|
||||
{ "transaction_id", transactionId }
|
||||
}));
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
public async Task<SubscriptionPreviewResponse?> PreviewSubscriptionChangeAsync(string subscriptionId, string newProductId)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/subscriptions/{subscriptionId}/preview";
|
||||
var response = await httpClient.PatchAsync(url, JsonContent.Create(new
|
||||
{
|
||||
proration_billing_mode = "prorated_immediately",
|
||||
items = new[] { new { price_id = newProductId, quantity = 1 } }
|
||||
}));
|
||||
return await response.Content.ReadFromJsonAsync<SubscriptionPreviewResponse>();
|
||||
}
|
||||
|
||||
public async Task<bool> ChangeSubscriptionAsync(string subscriptionId, string newProductId)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/subscriptions/{subscriptionId}";
|
||||
var response = await httpClient.PatchAsync(url, JsonContent.Create(new
|
||||
{
|
||||
proration_billing_mode = "prorated_immediately",
|
||||
items = new[] { new { price_id = newProductId, quantity = 1 } }
|
||||
}));
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
public async Task<bool> CancelSubscriptionAsync(string subscriptionId)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/subscriptions/{subscriptionId}/cancel";
|
||||
var response = await httpClient.PostAsync(url, JsonContent.Create(new { effective_from = "immediately" }));
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
public async Task<bool> PauseSubscriptionAsync(string subscriptionId)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/subscriptions/{subscriptionId}/pause";
|
||||
var response = await httpClient.PostAsync(url, JsonContent.Create(new { }));
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
public async Task<bool> ResumeSubscriptionAsync(string subscriptionId)
|
||||
{
|
||||
var url = $"{PADDLE_BASE_URI}/subscriptions/{subscriptionId}";
|
||||
var response = await httpClient.PatchAsync(url, JsonContent.Create(new Dictionary<string, string?>
|
||||
{
|
||||
{"scheduled_change", null}
|
||||
}));
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user