Skip to content

Commit

Permalink
Merge pull request #6 from vapor-community/Disputes
Browse files Browse the repository at this point in the history
Support for Disputes
  • Loading branch information
anthonycastelli authored Jul 18, 2017
2 parents 7fb5896 + ebd6406 commit 8f674b7
Show file tree
Hide file tree
Showing 16 changed files with 908 additions and 32 deletions.
11 changes: 11 additions & 0 deletions Sources/API/Helpers/Endpoints.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ internal enum API {
case accountsReject(String)
case accountsLoginLink(String)

/**
DISPUTES
A dispute occurs when a customer questions your charge with their bank or credit card company.
*/
case dispute
case disputes(String)
case closeDispute(String)


var endpoint: String {
Expand Down Expand Up @@ -166,6 +173,10 @@ internal enum API {
case .accounts(let id): return APIBase + APIVersion + "accounts/\(id)"
case .accountsReject(let id): return APIBase + APIVersion + "accounts/\(id)/reject"
case .accountsLoginLink(let id): return APIBase + APIVersion + "accounts/\(id)/login_links"

case .dispute: return APIBase + APIVersion + "disputes"
case .disputes(let id): return APIBase + APIVersion + "disputes/\(id)"
case .closeDispute(let id): return APIBase + APIVersion + "disputes/\(id)/close"
}
}
}
81 changes: 80 additions & 1 deletion Sources/API/Routes/CustomerRoutes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public final class CustomerRoutes {
- returns: A StripeRequest<> item which you can then use to convert to the corresponding node
*/

public func addNewSource(forCustomer customerId: String, inConnectAccount account: String?, source: String) throws -> StripeRequest<Card> {
public func addNewSource(forCustomer customerId: String, inConnectAccount account: String?, source: String) throws -> StripeRequest<Source> {
let body = try Node(node: ["source": source])

var headers: [HeaderKey: String]?
Expand All @@ -160,6 +160,85 @@ public final class CustomerRoutes {
return try StripeRequest(client: self.client, method: .post, route: .customerSources(customerId), query: [:], body: Body.data(body.formURLEncoded()), headers: headers)
}

/**
Adds a new bank account source for the customer.

- parameter customerId: The customer object to add the source to
- parameter account: A connect account to add the customer to
- parameter source: The bank account token or source token or a dictionary with bank account details.

- returns: A StripeRequest<> item which you can then use to convert to the corresponding node
*/

public func addNewBankAccountSource(forCustomer customerId: String, inConnectAccount account: String?, source: Node, metadata: Node? = nil) throws -> StripeRequest<BankAccount> {

var body = Node([:])

if let sourceString = source.string {
body["source"] = Node(sourceString)
}

if let bankDetails = source.object {
for (key,value) in bankDetails {
body["source[\(key)]"] = value
}
}

if let metadata = metadata?.object {
for (key, value) in metadata {
body["metadata[\(key)]"] = value
}
}

var headers: [HeaderKey: String]?

// Check if we have an account to set it to
if let account = account {
headers = [StripeHeader.Account : account]
}

return try StripeRequest(client: self.client, method: .post, route: .customerSources(customerId), query: [:], body: Body.data(body.formURLEncoded()), headers: headers)
}

/**
Adds a new card source for the customer.

- parameter customerId: The customer object to add the source to
- parameter account: A connect account to add the customer to
- parameter source: The card token or source token or a dictionary with card details.

- returns: A StripeRequest<> item which you can then use to convert to the corresponding node
*/

public func addNewCardSource(forCustomer customerId: String, inConnectAccount account: String?, source: Node, metadata: Node? = nil) throws -> StripeRequest<Card> {
var body = Node([:])

if let sourceString = source.string {
body["source"] = Node(sourceString)
}

if let cardDetails = source.object {
for (key,value) in cardDetails {
body["source[\(key)]"] = value
}
}

if let metadata = metadata?.object {
for (key, value) in metadata {
body["metadata[\(key)]"] = value
}
}

var headers: [HeaderKey: String]?

// Check if we have an account to set it to
if let account = account {
headers = [StripeHeader.Account : account]
}

return try StripeRequest(client: self.client, method: .post, route: .customerSources(customerId), query: [:], body: Body.data(body.formURLEncoded()), headers: headers)
}

/**
Retrieve a customer
Retrieves the details of an existing customer. You need only supply the unique customer identifier
Expand Down
60 changes: 60 additions & 0 deletions Sources/API/Routes/DisputeRoutes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// DisputeRoutes.swift
// Stripe
//
// Created by Andrew Edwards on 7/12/17.
//
//

import Foundation
import Node
import Models
import Helpers
import HTTP
import Errors

public final class DisputeRoutes {
let client: StripeClient

init(client: StripeClient) {
self.client = client
}

public func retrieve( dispute disputeId: String) throws -> StripeRequest<Dispute> {
return try StripeRequest(client: self.client, method: .get, route: .disputes(disputeId), query: [:], body: nil, headers: nil)
}

public func update(dispute disputeId: String, evidence: Node?, submit: Bool?, metadata: Node? = nil) throws -> StripeRequest<Dispute> {
var body = Node([:])

if let evidence = evidence?.object {
for (key, value) in evidence {
body["evidence[\(key)]"] = value
}
}

if let submit = submit {
body["submit"] = Node(submit)
}

if let metadata = metadata?.object {
for (key, value) in metadata {
body["metadata[\(key)]"] = value
}
}

return try StripeRequest(client: self.client, method: .post, route: .disputes(disputeId), query: [:], body: Body.data(body.formURLEncoded()), headers: nil)
}

public func close(dispute disputeId: String) throws -> StripeRequest<Dispute> {
return try StripeRequest(client: self.client, method: .post, route: .closeDispute(disputeId), query: [:], body: nil, headers: nil)
}

public func listAll(filter: StripeFilter?) throws -> StripeRequest<DisputeList> {
var query = [String : NodeRepresentable]()
if let data = try filter?.createQuery() {
query = data
}
return try StripeRequest(client: self.client, method: .get, route: .dispute, query: query, body: nil, headers: nil)
}
}
18 changes: 9 additions & 9 deletions Sources/API/Routes/SourceRoutes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public final class SourceRoutes {
- returns: A StripeRequest<> item which you can then use to convert to the corresponding node
*/

public func createNewSource(sourceType: SourceType, source: [String:Node]?, amount: Int?, currency: StripeCurrency?, flow: String?, owner: Owner?, redirectReturnUrl: String?, token: String?, usage: String?, metadata: Node? = nil) throws -> StripeRequest<Source> {
public func createNewSource(sourceType: SourceType, source: Node, amount: Int?, currency: StripeCurrency?, flow: String?, owner: Owner?, redirectReturnUrl: String?, token: String?, usage: String?, metadata: Node? = nil) throws -> StripeRequest<Source> {

var body = Node([:])

Expand All @@ -59,50 +59,50 @@ public final class SourceRoutes {
switch sourceType{

case .card:
if let source = source {
if let source = source.object {
for (key,val) in source {
body["card[\(key)]"] = val
}
}
case .bitcoin:
if let source = source {
if let source = source.object {
for (key,val) in source {
body["bitcoin[\(key)]"] = val
}
}
case .threeDSecure:
if let source = source {
if let source = source.object {
for (key,val) in source {
body["three_d_secure[\(key)]"] = val
}
}

case .bancontact:
if let source = source {
if let source = source.object {
for (key,val) in source {
body["bancontact[\(key)]"] = val
}
}
case .giropay:
if let source = source {
if let source = source.object {
for (key,val) in source {
body["giropay[\(key)]"] = val
}
}
case .ideal:
if let source = source {
if let source = source.object {
for (key,val) in source {
body["ideal[\(key)]"] = val
}
}
case .sepaDebit:
if let source = source {
if let source = source.object {
for (key,val) in source {
body["sepa_debit[\(key)]"] = val
}
}
case .sofort:
if let source = source {
if let source = source.object {
for (key,val) in source {
body["sofort[\(key)]"] = val
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/API/StripeClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class StripeClient {
public private(set) var subscriptionItems: SubscriptionItemRoutes!
public private(set) var subscriptions: SubscriptionRoutes!
public private(set) var account: AccountRoutes!
public private(set) var disputes: DisputeRoutes!

public init(apiKey: String) throws {
self.apiKey = apiKey
Expand All @@ -40,5 +41,6 @@ public class StripeClient {
self.subscriptionItems = SubscriptionItemRoutes(client: self)
self.subscriptions = SubscriptionRoutes(client: self)
self.account = AccountRoutes(client: self)
self.disputes = DisputeRoutes(client: self)
}
}
36 changes: 36 additions & 0 deletions Sources/Helpers/DisputeReason.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// DisputeReason.swift
// Stripe
//
// Created by Andrew Edwards on 7/11/17.
//
//

import Foundation

public enum DisputeReason: String {
case duplicate = "duplicate"
case fraudulent = "fraudulent"
case subscriptionCanceled = "subscription_canceled"
case productUnacceptable = "product_unacceptable"
case productNotReceived = "product_not_received"
case unrecognized = "unrecognized"
case creditNotProcessed = "credit_not_processed"
case general = "general"
case incorrectAccountDetails = "incorrect_account_details"
case insufficientFunds = "insufficient_funds"
case bankCannotProcess = "bank_cannot_process"
case debitNotAuthorized = "debit_not_authorized"
case customerInitiated = "customer_initiated"
}

public enum DisputeStatus: String {
case warningNeedsResponse = "warning_needs_response"
case warningUnderReview = "warning_under_review"
case warningClosed = "warning_closed"
case needsResponse = "needs_response"
case underReview = "under_review"
case chargeRefunded = "charge_refunded"
case won = "won"
case lost = "lost"
}
1 change: 0 additions & 1 deletion Sources/Helpers/SourceType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
//

import Foundation
import Errors

public enum SourceType: String
{
Expand Down
1 change: 1 addition & 0 deletions Sources/Models/Balance/BalanceTransactionItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public final class BalanceTransactionItem: StripeModelProtocol {
public private(set) var availableOn: Date?
public private(set) var created: Date?
public private(set) var description: String?
// AETODO add fee
public private(set) var fees: [Fee]?
public private(set) var net: Int?
public private(set) var source: String?
Expand Down
Loading

0 comments on commit 8f674b7

Please sign in to comment.