use client::Client;
use error::{Error, ErrorCode};
use params::{Identifiable, List, Metadata, RangeQuery, Timestamp};
use resources::{Address, Currency, PaymentSource, PaymentSourceParams, Refund};
use serde_qs as qs;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChargeOutcome {
#[serde(rename = "type")]
pub outcome_type: OutcomeType,
pub network_status: NetworkStatus,
#[serde(default)]
pub reason: Option<OutcomeReason>,
#[serde(default)]
pub risk_level: Option<RiskLevel>,
#[serde(default)]
pub seller_message: Option<String>,
#[serde(default)]
pub rule: Option<String>,
}
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy, Eq)]
#[serde(rename_all = "snake_case")]
pub enum OutcomeType {
Authorized,
ManualReview,
IssuerDeclined,
Blocked,
Invalid,
#[serde(other)]
Other,
}
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Eq)]
#[serde(rename_all = "snake_case")]
pub enum NetworkStatus {
ApprovedByNetwork,
DeclinedByNetwork,
NotSentToNetwork,
ReversedAfterApproval,
#[serde(other)]
Other,
}
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Eq)]
#[serde(rename_all = "snake_case")]
pub enum RiskLevel {
Normal,
Elevated,
Highest,
NotAssessed,
#[serde(other)]
Unknown
}
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Eq)]
#[serde(rename_all = "snake_case")]
pub enum OutcomeReason {
ApprovedWithId,
CallIssuer,
CardNotSupported,
CardVelocityExceeded,
CurrencyNotSupported,
DoNotHonor,
DoNotTryAgain,
DuplicateTransaction,
ExpiredCard,
Fraudulent,
GenericDecline,
IncorrectNumber,
IncorrectCvc,
IncorrectPin,
IncorrectZip,
InsufficientFunds,
InvalidAccount,
InvalidAmount,
InvalidCvc,
InvalidExpiryYear,
InvalidNumber,
InvalidPin,
IssuerNotAvailable,
LostCard,
MerchantBlacklist,
NewAccountInformationAvailable,
NoActionTaken,
NotPermitted,
PickupCard,
PinTryExceeded,
ProcessingError,
ReenterTransaction,
RestrictedCard,
RevocationOfAllAuthorizations,
RevocationOfAuthorization,
SecurityViolation,
ServiceNotAllowed,
StolenCard,
StopPaymentOrder,
TestmodeDecline,
TransactionNotAllowed,
TryAgainLater,
WithdrawalCountLimitExceeded,
#[serde(other)]
Other,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct FraudDetails {
pub user_report: Option<String>,
#[serde(skip_serializing)]
pub stripe_report: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ShippingDetails {
pub name: String,
pub address: Address,
#[serde(skip_serializing_if = "Option::is_none")]
pub carrier: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub phone: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tracking_number: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct CaptureParams<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub amount: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub application_fee: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub receipt_email: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub statement_descriptor: Option<&'a str>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DestinationParams<'a> {
pub account: &'a str,
pub amount: u64,
}
#[derive(Clone, Debug, Default, Serialize)]
pub struct ChargeParams<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub amount: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub currency: Option<Currency>,
#[serde(skip_serializing_if = "Option::is_none")]
pub application_fee: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub capture: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub destination: Option<DestinationParams<'a>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fraud_details: Option<FraudDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
pub transfer_group: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub on_behalf_of: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub receipt_email: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shipping: Option<ShippingDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
pub customer: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<PaymentSourceParams<'a>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub statement_descriptor: Option<&'a str>,
}
#[derive(Copy, Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum SourceFilterType {
All,
AlipayAccount,
BankAccount,
BitcoinReceiver,
Card,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SourceFilter {
pub object: SourceFilterType,
}
impl SourceFilter {
pub fn all() -> SourceFilter {
SourceFilter {
object: SourceFilterType::All,
}
}
pub fn alipay() -> SourceFilter {
SourceFilter {
object: SourceFilterType::AlipayAccount,
}
}
pub fn bank() -> SourceFilter {
SourceFilter {
object: SourceFilterType::BankAccount,
}
}
pub fn bitcoin() -> SourceFilter {
SourceFilter {
object: SourceFilterType::BitcoinReceiver,
}
}
pub fn card() -> SourceFilter {
SourceFilter {
object: SourceFilterType::Card,
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct ChargeListParams<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub created: Option<RangeQuery<Timestamp>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub customer: Option<&'a str>,
#[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 source: Option<SourceFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub starting_after: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub transfer_group: Option<&'a str>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Charge {
pub id: String,
pub amount: u64,
pub amount_refunded: u64,
pub application: Option<String>,
pub application_fee: Option<String>,
pub balance_transaction: Option<String>,
pub captured: bool,
pub created: Timestamp,
pub currency: Currency,
pub customer: Option<String>,
pub description: Option<String>,
pub destination: Option<String>,
pub dispute: Option<String>,
pub failure_code: Option<ErrorCode>,
pub failure_message: Option<String>,
pub fraud_details: FraudDetails,
pub invoice: Option<String>,
pub livemode: bool,
pub metadata: Metadata,
pub on_behalf_of: Option<String>,
pub order: Option<String>,
pub outcome: Option<ChargeOutcome>,
pub paid: bool,
pub payment_intent: Option<String>,
pub receipt_email: Option<String>,
pub receipt_number: Option<String>,
pub refunded: bool,
pub refunds: List<Refund>,
pub review: Option<String>,
pub shipping: Option<ShippingDetails>,
pub source: PaymentSource,
pub source_transfer: Option<String>,
pub statement_descriptor: Option<String>,
pub status: ChargeStatus,
pub transfer_group: Option<String>,
}
impl Identifiable for Charge {
fn id(&self) -> &str {
&self.id
}
}
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Eq)]
pub enum ChargeStatus {
#[serde(rename = "succeeded")]
Succeeded,
#[serde(rename = "pending")]
Pending,
#[serde(rename = "failed")]
Failed,
}
impl Charge {
pub fn create(client: &Client, params: ChargeParams) -> Result<Charge, Error> {
client.post("/charges", params)
}
pub fn retrieve(client: &Client, charge_id: &str) -> Result<Charge, Error> {
client.get(&format!("/charges/{}", charge_id))
}
pub fn update(client: &Client, charge_id: &str, params: ChargeParams) -> Result<Charge, Error> {
client.post(&format!("/charges/{}", charge_id), params)
}
pub fn capture(
client: &Client,
charge_id: &str,
params: CaptureParams,
) -> Result<Charge, Error> {
client.post(&format!("/charges/{}/capture", charge_id), params)
}
pub fn list(client: &Client, params: ChargeListParams) -> Result<Vec<Charge>, Error> {
client.get(&format!("/charges?{}", qs::to_string(¶ms)?))
}
}