use crate::config::{Client, Response};
use crate::ids::{BankAccountId, PaymentSourceId};
use crate::params::{Identifiable, List, Metadata, RangeQuery, Timestamp};
use crate::resources::{
Address, BankAccount, BankAccountVerifyParams, Currency, Deleted, Discount, PaymentSource,
PaymentSourceParams, Source, Subscription,
};
use serde_derive::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CustomerShippingDetails {
pub address: Address,
pub name: String,
pub phone: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "object", rename_all = "snake_case")]
pub enum DetachedSource {
Source(Source),
BankAccount(Deleted),
Card(Deleted),
}
#[derive(Clone, Debug, Default, Serialize)]
pub struct CustomerParams<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub account_balance: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub business_vat_id: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_source: Option<PaymentSourceId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub coupon: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shipping: Option<CustomerShippingDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<PaymentSourceParams<'a>>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct CustomerListParams<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub created: Option<RangeQuery<Timestamp>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ending_before: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub starting_after: Option<&'a str>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Customer {
pub id: String,
pub account_balance: i64,
pub business_vat_id: Option<String>,
pub created: u64,
pub currency: Option<Currency>,
pub default_source: Option<PaymentSourceId>,
pub delinquent: bool,
pub desc: Option<String>,
pub discount: Option<Discount>,
pub email: Option<String>,
pub livemode: bool,
pub metadata: Metadata,
pub shipping: Option<CustomerShippingDetails>,
pub sources: List<PaymentSource>,
pub subscriptions: List<Subscription>,
}
impl Customer {
pub fn create(client: &Client, params: CustomerParams<'_>) -> Response<Customer> {
client.post_form("/customers", params)
}
pub fn retrieve(client: &Client, customer_id: &str) -> Response<Customer> {
client.get(&format!("/customers/{}", customer_id))
}
pub fn update(
client: &Client,
customer_id: &str,
params: CustomerParams<'_>,
) -> Response<Customer> {
client.post_form(&format!("/customers/{}", customer_id), params)
}
pub fn delete(client: &Client, customer_id: &str) -> Response<Deleted> {
client.delete(&format!("/customers/{}", customer_id))
}
pub fn list(client: &Client, params: CustomerListParams<'_>) -> Response<List<Customer>> {
client.get_query("/customers", ¶ms)
}
pub fn attach_source(
client: &Client,
customer_id: &str,
source: PaymentSourceParams<'_>,
) -> Response<PaymentSource> {
#[derive(Serialize)]
struct AttachSource<'a> {
source: PaymentSourceParams<'a>,
}
let params = AttachSource { source };
client.post_form(&format!("/customers/{}/sources", customer_id), params)
}
pub fn detach_source(
client: &Client,
customer_id: &str,
source_id: &PaymentSourceId,
) -> Response<DetachedSource> {
client.delete(&format!("/customers/{}/sources/{}", customer_id, source_id))
}
pub fn retrieve_source(
client: &Client,
customer_id: &str,
source_id: &PaymentSourceId,
) -> Response<PaymentSource> {
client.get(&format!("/customers/{}/sources/{}", customer_id, source_id))
}
pub fn verify_bank_account(
client: &Client,
customer_id: &str,
bank_account_id: &BankAccountId,
params: BankAccountVerifyParams<'_>,
) -> Response<BankAccount> {
client.post_form(
&format!("/customers/{}/sources/{}/verify", customer_id, bank_account_id),
params,
)
}
}
impl Identifiable for Customer {
fn id(&self) -> &str {
&self.id
}
}