common: add paddle v1 api client

This commit is contained in:
Abdullah Atta
2025-09-27 11:49:39 +05:00
committed by Abdullah Atta
parent 9e6a25ec1d
commit cc459f9fea
5 changed files with 373 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
using System;
using System.Text.Json.Serialization;
namespace Streetwriters.Common.Models
{
public partial class ListPaymentsResponse
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("response")]
public Payment[] Payments { get; set; }
}
public partial class Payment
{
[JsonPropertyName("id")]
public long Id { get; set; }
[JsonPropertyName("subscription_id")]
public long SubscriptionId { get; set; }
[JsonPropertyName("amount")]
public double Amount { get; set; }
[JsonPropertyName("currency")]
public string Currency { get; set; }
[JsonPropertyName("payout_date")]
public string PayoutDate { get; set; }
[JsonPropertyName("is_paid")]
public short IsPaid { get; set; }
[JsonPropertyName("is_one_off_charge")]
public bool IsOneOffCharge { get; set; }
[JsonPropertyName("receipt_url")]
public string ReceiptUrl { get; set; }
}
}

View File

@@ -0,0 +1,77 @@
namespace Streetwriters.Common.Models
{
using System;
using System.Text.Json.Serialization;
public partial class ListTransactionsResponse
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("response")]
public Transaction[] Transactions { get; set; }
}
public partial class Transaction
{
[JsonPropertyName("order_id")]
public string OrderId { get; set; }
[JsonPropertyName("checkout_id")]
public string CheckoutId { get; set; }
[JsonPropertyName("amount")]
public string Amount { get; set; }
[JsonPropertyName("currency")]
public string Currency { get; set; }
[JsonPropertyName("status")]
public string Status { get; set; }
[JsonPropertyName("created_at")]
public string CreatedAt { get; set; }
[JsonPropertyName("passthrough")]
public object Passthrough { get; set; }
[JsonPropertyName("product_id")]
public long ProductId { get; set; }
[JsonPropertyName("is_subscription")]
public bool IsSubscription { get; set; }
[JsonPropertyName("is_one_off")]
public bool IsOneOff { get; set; }
[JsonPropertyName("subscription")]
public PaddleSubscription Subscription { get; set; }
[JsonPropertyName("user")]
public PaddleTransactionUser User { get; set; }
[JsonPropertyName("receipt_url")]
public string ReceiptUrl { get; set; }
}
public partial class PaddleSubscription
{
[JsonPropertyName("subscription_id")]
public long SubscriptionId { get; set; }
[JsonPropertyName("status")]
public string Status { get; set; }
}
public partial class PaddleTransactionUser
{
[JsonPropertyName("user_id")]
public long UserId { get; set; }
[JsonPropertyName("email")]
public string Email { get; set; }
[JsonPropertyName("marketing_consent")]
public bool MarketingConsent { get; set; }
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Text.Json.Serialization;
namespace Streetwriters.Common.Models
{
public partial class ListUsersResponse
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("response")]
public PaddleUser[] Users { get; set; }
}
public class PaddleUser
{
[JsonPropertyName("subscription_id")]
public long SubscriptionId { get; set; }
[JsonPropertyName("plan_id")]
public long PlanId { get; set; }
[JsonPropertyName("user_id")]
public long UserId { get; set; }
[JsonPropertyName("user_email")]
public string UserEmail { get; set; }
[JsonPropertyName("marketing_consent")]
public bool MarketingConsent { get; set; }
[JsonPropertyName("update_url")]
public string UpdateUrl { get; set; }
[JsonPropertyName("cancel_url")]
public string CancelUrl { get; set; }
[JsonPropertyName("state")]
public string State { get; set; }
[JsonPropertyName("signup_date")]
public string SignupDate { get; set; }
[JsonPropertyName("quantity")]
public long Quantity { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Text.Json.Serialization;
namespace Streetwriters.Common.Models
{
public partial class RefundPaymentResponse
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("response")]
public Refund Refund { get; set; }
}
public partial class Refund
{
[JsonPropertyName("refund_request_id")]
public long RefundRequestId { get; set; }
}
}

View File

@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Streetwriters.Common.Models;
namespace Streetwriters.Common.Services
{
public class PaddleService(string vendorId, string vendorAuthCode)
{
#if (DEBUG || STAGING)
const string PADDLE_BASE_URI = "https://sandbox-vendors.paddle.com/api";
#else
const string PADDLE_BASE_URI = "https://vendors.paddle.com/api";
#endif
HttpClient httpClient = new HttpClient();
public async Task<ListUsersResponse> ListUsersAsync(
string subscriptionId,
int results
)
{
var url = $"{PADDLE_BASE_URI}/2.0/subscription/users";
var httpClient = new HttpClient();
var response = await httpClient.PostAsync(
url,
new FormUrlEncodedContent(
new Dictionary<string, string>
{
{ "vendor_id", vendorId },
{ "vendor_auth_code", vendorAuthCode },
{ "subscription_id", subscriptionId },
{ "results_per_page", results.ToString() },
}
)
);
return await response.Content.ReadFromJsonAsync<ListUsersResponse>();
}
public async Task<ListPaymentsResponse> ListPaymentsAsync(
string subscriptionId,
long planId
)
{
var url = $"{PADDLE_BASE_URI}/2.0/subscription/payments";
var httpClient = new HttpClient();
var response = await httpClient.PostAsync(
url,
new FormUrlEncodedContent(
new Dictionary<string, string>
{
{ "vendor_id", vendorId },
{ "vendor_auth_code", vendorAuthCode },
{ "subscription_id", subscriptionId },
{ "is_paid", "1" },
{ "plan", planId.ToString() },
{ "is_one_off_charge", "0" },
}
)
);
return await response.Content.ReadFromJsonAsync<ListPaymentsResponse>();
}
public async Task<ListTransactionsResponse> ListTransactionsAsync(
string subscriptionId
)
{
var url = $"{PADDLE_BASE_URI}/2.0/subscription/{subscriptionId}/transactions";
var httpClient = new HttpClient();
var response = await httpClient.PostAsync(
url,
new FormUrlEncodedContent(
new Dictionary<string, string>
{
{ "vendor_id", vendorId },
{ "vendor_auth_code", vendorAuthCode },
}
)
);
return await response.Content.ReadFromJsonAsync<ListTransactionsResponse>();
}
public async Task<PaddleTransactionUser> FindUserFromOrderAsync(string orderId)
{
var url = $"{PADDLE_BASE_URI}/2.0/order/{orderId}/transactions";
var httpClient = new HttpClient();
var response = await httpClient.PostAsync(
url,
new FormUrlEncodedContent(
new Dictionary<string, string>
{
{ "vendor_id", vendorId },
{ "vendor_auth_code", vendorAuthCode },
}
)
);
var transactions = await response.Content.ReadFromJsonAsync<ListTransactionsResponse>();
if (transactions.Transactions.Length == 0) return null;
return transactions.Transactions[0].User;
}
public async Task<bool> RefundPaymentAsync(string paymentId, string reason = "")
{
var url = $"{PADDLE_BASE_URI}/2.0/payment/refund";
var httpClient = new HttpClient();
var response = await httpClient.PostAsync(
url,
new FormUrlEncodedContent(
new Dictionary<string, string>
{
{ "vendor_id", vendorId },
{ "vendor_auth_code", vendorAuthCode },
{ "order_id", paymentId },
{ "reason", reason },
}
)
);
var refundResponse = await response.Content.ReadFromJsonAsync<RefundPaymentResponse>();
return refundResponse.Success;
}
public async Task<bool> CancelSubscriptionAsync(string subscriptionId)
{
var url = $"{PADDLE_BASE_URI}/2.0/subscription/users_cancel";
var httpClient = new HttpClient();
var response = await httpClient.PostAsync(
url,
new FormUrlEncodedContent(
new Dictionary<string, string>
{
{ "vendor_id", vendorId },
{ "vendor_auth_code", vendorAuthCode },
{ "subscription_id", subscriptionId },
}
)
);
return response.IsSuccessStatusCode;
}
public async Task<bool> PauseSubscriptionAsync(string subscriptionId)
{
var url = $"{PADDLE_BASE_URI}/2.0/subscription/users/update";
var httpClient = new HttpClient();
var response = await httpClient.PostAsync(
url,
new FormUrlEncodedContent(
new Dictionary<string, string>
{
{ "vendor_id", vendorId },
{ "vendor_auth_code", vendorAuthCode },
{ "subscription_id", subscriptionId },
{ "pause", "true" },
}
)
);
return response.IsSuccessStatusCode;
}
public async Task<bool> ResumeSubscriptionAsync(string subscriptionId)
{
var url = $"{PADDLE_BASE_URI}/2.0/subscription/users/update";
var httpClient = new HttpClient();
var response = await httpClient.PostAsync(
url,
new FormUrlEncodedContent(
new Dictionary<string, string>
{
{ "vendor_id", vendorId },
{ "vendor_auth_code", vendorAuthCode },
{ "subscription_id", subscriptionId },
{ "pause", "false" },
}
)
);
return response.IsSuccessStatusCode;
}
}
}