From 5af1a995b78c4b943546d6c59c1958c8229bbf36 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:21:25 -0400 Subject: [PATCH 01/26] Added Coupon model. --- Sources/Models/Coupons/Coupon.swift | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 Sources/Models/Coupons/Coupon.swift diff --git a/Sources/Models/Coupons/Coupon.swift b/Sources/Models/Coupons/Coupon.swift new file mode 100644 index 0000000..da471a9 --- /dev/null +++ b/Sources/Models/Coupons/Coupon.swift @@ -0,0 +1,92 @@ +// +// Coupon.swift +// Stripe +// +// Created by Andrew Edwards on 5/28/17. +// +// + +import Foundation +import Vapor +import Helpers + +/** + Coupon Model + https://stripe.com/docs/api/curl#coupon_object + */ +public final class Coupon: StripeModelProtocol +{ + public var id: String? + public var amountOff: Int? + public var currency: StripeCurrency? + public var duration: StripeDuration = .never + public var durationInMonths: Int? + public var maxRedemptions: Int? + public var percentOff: Int? + public var redeemBy: Date? + public private(set) var object: String? + public private(set) var created: Date? + public private(set) var timesRedeemed: Int? + public private(set) var isValid: Bool? + public private(set) var isLive: Bool? + + /** + Only metadata is mutable/updatable. + https://stripe.com/docs/api/curl#update_coupon + */ + public var metadata: Node? + + + required public init(duration: StripeDuration) + { + self.duration = duration + } + + public init(node: Node) throws + { + self.id = try node.get("id") + self.amountOff = try node.get("amount_off") + self.created = try node.get("created") + + if let currency = node["currency"]?.string + { + self.currency = StripeCurrency(rawValue: currency) + } + + if let duration = node["duration"]?.string + { + self.duration = StripeDuration(rawValue: duration) ?? StripeDuration.never + } + self.object = try node.get("object") + self.durationInMonths = try node.get("duration_in_months") + self.isLive = try node.get("livemode") + self.maxRedemptions = try node.get("max_redemptions") + self.metadata = try node.get("metadata") + self.percentOff = try node.get("percent_off") + self.redeemBy = try node.get("redeem_by") + self.timesRedeemed = try node.get("times_redeemed") + self.isValid = try node.get("valid") + } + + public func makeNode(in context: Context?) throws -> Node + { + let object: [String: Any?] = [ + "id": self.id, + "object": self.object, + "amount_off": self.amountOff, + "created": self.created, + "currency": self.currency, + "duration": self.duration, + "duration_in_months": self.durationInMonths, + "livemode": self.isLive, + "max_redemptions": self.maxRedemptions, + "metadata": self.metadata, + "percent_off": self.percentOff, + "redeem_by": self.redeemBy, + "times_redeemed": self.timesRedeemed, + "valid": self.isValid + ] + + return try Node(node: object) + } +} From 7bd050aedd9bc4e6d3ef1b48770ac8aa45e316ed Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:23:49 -0400 Subject: [PATCH 02/26] Added coupon lists --- Sources/Models/CouponList.swift | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Sources/Models/CouponList.swift diff --git a/Sources/Models/CouponList.swift b/Sources/Models/CouponList.swift new file mode 100644 index 0000000..f732a3e --- /dev/null +++ b/Sources/Models/CouponList.swift @@ -0,0 +1,38 @@ +// +// CouponList.swift +// Stripe +// +// Created by Andrew Edwards on 5/28/17. +// +// + +import Foundation +import Vapor +import Helpers + +public final class CouponList: StripeModelProtocol +{ + public let object: String + public let url: String + public let hasMore: Bool + public let items: [Coupon]? + + public init(node: Node) throws + { + self.object = try node.get("object") + self.url = try node.get("url") + self.hasMore = try node.get("has_more") + self.items = try node.get("data") + } + + public func makeNode(in context: Context?) throws -> Node + { + let object: [String : Any?] = [ + "object": self.object, + "url": self.url, + "has_more": self.hasMore, + "data": self.items + ] + return try Node(node: object) + } +} From 8015097f104cff8ee2cd0750cecc167b4bb956b0 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:25:28 -0400 Subject: [PATCH 03/26] Removed force unwrapped. We never want a server crash. --- Sources/Models/Balance/BalanceTransactionItem.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Models/Balance/BalanceTransactionItem.swift b/Sources/Models/Balance/BalanceTransactionItem.swift index 7f443ba..1eb7669 100644 --- a/Sources/Models/Balance/BalanceTransactionItem.swift +++ b/Sources/Models/Balance/BalanceTransactionItem.swift @@ -34,8 +34,8 @@ public final class BalanceTransactionItem: StripeModelProtocol { self.fees = try node.get("fee_details") self.net = try node.get("net") self.source = try node.get("source") - self.status = try StripeStatus(rawValue: node.get("status"))! - self.type = try ActionType(rawValue: node.get("type"))! + self.status = try StripeStatus(rawValue: node.get("status")) ?? StripeStatus.failed + self.type = try ActionType(rawValue: node.get("type")) ?? ActionType.none } public func makeNode(in context: Context?) throws -> Node { From 41c6f6d906cfa362a28c8f9ca9b48896313177ea Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:26:19 -0400 Subject: [PATCH 04/26] Made transactionId optional - can only appear if a charge has been captured. --- Sources/Models/Charges/Charge.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Models/Charges/Charge.swift b/Sources/Models/Charges/Charge.swift index 3897e79..de1d17f 100644 --- a/Sources/Models/Charges/Charge.swift +++ b/Sources/Models/Charges/Charge.swift @@ -22,7 +22,7 @@ public final class Charge: StripeModelProtocol { public let amountRefunded: Int public let application: String? public let applicationFee: Int? - public let balanceTransactionId: String + public let balanceTransactionId: String? public let isCaptured: Bool public let created: Date public let customerId: String? From 52737ce433ff7440e005e9d79bed169ffdc055e6 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:26:47 -0400 Subject: [PATCH 05/26] Added url property. --- Sources/Models/Customer/CustomerList.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/Models/Customer/CustomerList.swift b/Sources/Models/Customer/CustomerList.swift index a2a0f97..159b7a0 100644 --- a/Sources/Models/Customer/CustomerList.swift +++ b/Sources/Models/Customer/CustomerList.swift @@ -13,11 +13,13 @@ import Helpers public final class CustomerList: StripeModelProtocol { public let object: String + public let url: String public let hasMore: Bool public let items: [Customer]? public init(node: Node) throws { self.object = try node.get("object") + self.url = try node.get("url") self.hasMore = try node.get("has_more") self.items = try node.get("data") } @@ -25,10 +27,10 @@ public final class CustomerList: StripeModelProtocol { public func makeNode(in context: Context?) throws -> Node { let object: [String : Any?] = [ "object": self.object, + "url": self.url, "has_more": self.hasMore, "data": self.items ] return try Node(node: object) } - } From c1f347e2879be2a36134165537e0df01db7d421d Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:27:18 -0400 Subject: [PATCH 06/26] Extra asterisks --- Sources/Models/Tokens/Token.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Models/Tokens/Token.swift b/Sources/Models/Tokens/Token.swift index b97f84a..e6e3fcd 100644 --- a/Sources/Models/Tokens/Token.swift +++ b/Sources/Models/Tokens/Token.swift @@ -8,7 +8,7 @@ import Vapor -/* +/** Token Model https://stripe.com/docs/api/curl#token_object */ From 7d65db23353d9daa074d96bff620baea610d1c75 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:27:47 -0400 Subject: [PATCH 07/26] Added none case for failure reasons. --- Sources/Helpers/ActionType.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/Helpers/ActionType.swift b/Sources/Helpers/ActionType.swift index f32d6a3..4546fcc 100644 --- a/Sources/Helpers/ActionType.swift +++ b/Sources/Helpers/ActionType.swift @@ -21,4 +21,6 @@ public enum ActionType: String { case ideal = "ideal" case sofort = "sofort" case bancontact = "bancontact" + + case none = "none" } From 066aaab67fae58930c565a4d9ba3a99a099fe183 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:28:11 -0400 Subject: [PATCH 08/26] Created Stripe duration. --- Sources/Helpers/StripeDuration.swift | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Sources/Helpers/StripeDuration.swift diff --git a/Sources/Helpers/StripeDuration.swift b/Sources/Helpers/StripeDuration.swift new file mode 100644 index 0000000..7391561 --- /dev/null +++ b/Sources/Helpers/StripeDuration.swift @@ -0,0 +1,19 @@ +// +// StripeDuration.swift +// Stripe +// +// Created by Andrew Edwards on 5/28/17. +// +// + +public enum StripeDuration: String +{ + case forever = "forever" + case once = "once" + case repeating = "repeating" + case never = "never" + + var description: String { + return self.rawValue.uppercased() + } +} From ab72d34432bef0c60876b7b1884e9dff4315c8f8 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:28:38 -0400 Subject: [PATCH 09/26] Added coupon routes --- Sources/API/StripeClient.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/API/StripeClient.swift b/Sources/API/StripeClient.swift index cf7f57a..2b51552 100644 --- a/Sources/API/StripeClient.swift +++ b/Sources/API/StripeClient.swift @@ -17,6 +17,7 @@ public class StripeClient { public private(set) var customer: CustomerRoutes! public private(set) var tokens: TokenRoutes! public private(set) var refunds: RefundRoutes! + public private(set) var coupons: CouponRoutes! public init(apiKey: String) throws { self.apiKey = apiKey @@ -28,6 +29,7 @@ public class StripeClient { self.customer = CustomerRoutes(client: self) self.tokens = TokenRoutes(client: self) self.refunds = RefundRoutes(client: self) + self.coupons = CouponRoutes(client: self) } } From 9624e991494552d82d848cb2b2874d2097fc5aba Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:29:02 -0400 Subject: [PATCH 10/26] Clean up --- Sources/API/StripeRequest.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/API/StripeRequest.swift b/Sources/API/StripeRequest.swift index a195095..675f33a 100644 --- a/Sources/API/StripeRequest.swift +++ b/Sources/API/StripeRequest.swift @@ -85,5 +85,4 @@ public class StripeRequest { guard let value = self.response.json else { throw StripeError.serializationError } return value } - } From a74ea8868cab31371aabddef918cae4314650631 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:29:46 -0400 Subject: [PATCH 11/26] Renamed Filter to StripeFilter to avoid confusion with Vapor's Filter --- Sources/API/Filter/StripeFilter.swift | 169 ++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 Sources/API/Filter/StripeFilter.swift diff --git a/Sources/API/Filter/StripeFilter.swift b/Sources/API/Filter/StripeFilter.swift new file mode 100644 index 0000000..9660362 --- /dev/null +++ b/Sources/API/Filter/StripeFilter.swift @@ -0,0 +1,169 @@ +// +// StripeFilter.swift +// Stripe +// +// Created by Anthony Castelli on 4/16/17. +// +// + +import Foundation +import Vapor +import Helpers +import Node +import HTTP + +public final class StripeFilter { + + public init() { } + + /** + Can either be a UNIX timestamp, or a dictionary with these key/values + + - gt: Return values where the created field is after this timestamp. + - gte: Return values where the created field is after or equal to this timestamp. + - lt: Return values where the created field is before this timestamp. + - lte: Return values where the created field is before or equal to this timestamp. + + Example: + created = Node(node: ["UNIX_TIMESTAMP": "gte"]) + or + created = Node(node: UNIX_TIMESTAMP) + */ + public var created: Node? + + /** + Can either be a UNIX timestamp, or a dictionary with these key/values + + - gt: Return values where the created field is after this timestamp. + - gte: Return values where the created field is after or equal to this timestamp. + - lt: Return values where the created field is before this timestamp. + - lte: Return values where the created field is before or equal to this timestamp. + + Example: + availableOn = Node(node: ["UNIX_TIMESTAMP": "gte"]) + or + availableOn = Node(node: UNIX_TIMESTAMP) + */ + public var availableOn: Node? + + /** + A currency + */ + public var currency: StripeCurrency? + + /** + Only return charges for the customer specified by this customer ID. + */ + public var customerId: Node? + + /** + A cursor for use in pagination. `ending_before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, starting with `obj_bar`, your + subsequent call can include `ending_before=obj_bar` in order to fetch the previous page of the list. + + Example: endingBefore = "obj_bar" + */ + public var endingBefore: Node? + + /** + A limit on the number of objects to be returned. Limit can range between 1 and 100 items. + This field MUST be a possitive Integer or String. Default is 10 + */ + public var limit: Node? + + /** + A filter on the list based on the source of the charge. + */ + public var source: SourceType? + + /** + A cursor for use in pagination. `starting_after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with `obj_foo`, your + subsequent call can include `starting_after=obj_foo` in order to fetch the next page of the list. + + Example: startingAfter = "obj_foo" + */ + public var startingAfter: Node? + + /** + Only return charges for this transfer group. + */ + public var transferGroup: Node? + + /** + For automatic Stripe payouts only, only returns transactions that were payed out on the specified payout ID. + */ + public var payout: Node? + + /** + Only returns transactions of the given type. One of BalanceType + */ + public var balanceType: BalanceType? + + + internal func createBody() throws -> Node { + var node = Node([:]) + if let value = self.created { + if let value = value.object { + for (key, value) in value { + node["created[\(key)]"] = value + } + } else { + node["created"] = value + } + } + + if let value = self.created { + if let value = value.object { + for (key, value) in value { + node["available_on[\(key)]"] = value + } + } else { + node["available_on"] = value + } + } + + if let value = self.currency + { + node["currency"] = value.rawValue.makeNode(in: nil) + } + + if let value = self.customerId { + node["customer"] = value + } + + if let value = self.endingBefore { + node["ending_before"] = value + } + + if let value = self.limit { + node["limit"] = value + } + + if let value = self.source { + node["source"] = value.rawType.makeNode(in: nil) + } + + if let value = self.startingAfter { + node["starting_after"] = value + } + + if let value = self.transferGroup { + node["transfer_group"] = value + } + + if let value = self.payout { + node["payout"] = value + } + + if let value = self.balanceType { + node["type"] = value.rawValue.makeNode(in: nil) + } + + return node + } + + internal func createQuery() throws -> [String : NodeRepresentable]? { + return try self.createBody().object + } +} From 5b1d6b15e26f4b7f3e1f6a60e39015231f3ff301 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:30:29 -0400 Subject: [PATCH 12/26] Updated API version and added coupon routes --- Sources/API/Helpers/Endpoints.swift | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Sources/API/Helpers/Endpoints.swift b/Sources/API/Helpers/Endpoints.swift index c0fce5c..f1c9e53 100644 --- a/Sources/API/Helpers/Endpoints.swift +++ b/Sources/API/Helpers/Endpoints.swift @@ -14,7 +14,7 @@ internal let APIVersion = "v1/" internal let DefaultHeaders = [ HeaderKey.contentType: "application/x-www-form-urlencoded", - StripeHeader.Version: "2017-04-06" + StripeHeader.Version: "2017-05-25" ] internal struct StripeHeader { @@ -76,6 +76,14 @@ internal enum API { case refunds case refund(String) + /** + COUPONS + A coupon contains information about a percent-off or amount-off discount you might want to + apply to a customer. Coupons may be applied to invoices or orders. + */ + case coupons + case coupon(String) + var endpoint: String { switch self { case .balance: return APIBase + APIVersion + "balance" @@ -95,6 +103,9 @@ internal enum API { case .refunds: return APIBase + APIVersion + "refunds" case .refund(let id): return APIBase + APIVersion + "refunds/\(id)" + + case .coupons: return APIBase + APIVersion + "coupons" + case .coupon(let id): return APIBase + APIVersion + "coupons/\(id)" } } From 804fe8913647ff006fd52d9cc96cab23f0a88912 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:31:48 -0400 Subject: [PATCH 13/26] Updated to StripeFilter and fixed ass typo --- Sources/API/Routes/BalanceRoutes.swift | 4 ++-- Sources/API/Routes/ChargeRoutes.swift | 4 ++-- Sources/API/Routes/CustomerRoutes.swift | 4 ++-- Sources/API/Routes/RefundRoutes.swift | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/API/Routes/BalanceRoutes.swift b/Sources/API/Routes/BalanceRoutes.swift index d0b0b3d..b793d88 100644 --- a/Sources/API/Routes/BalanceRoutes.swift +++ b/Sources/API/Routes/BalanceRoutes.swift @@ -43,11 +43,11 @@ public final class BalanceRoutes { Returns a list of transactions that have contributed to the Stripe account balance (e.g., charges, transfers, and so forth). The transactions are returned in sorted order, with the most recent transactions appearing first. - - parameter filter: A Filter item to ass query parameters when fetching results + - parameter filter: A Filter item to pass query parameters when fetching results - returns: A StripeRequest<> item which you can then use to convert to the corresponding node */ - public func history(forFilter filter: Filter?=nil) throws -> StripeRequest { + public func history(forFilter filter: StripeFilter?=nil) throws -> StripeRequest { var query = [String : NodeRepresentable]() if let data = try filter?.createQuery() { query = data diff --git a/Sources/API/Routes/ChargeRoutes.swift b/Sources/API/Routes/ChargeRoutes.swift index a198eee..1c4f70a 100644 --- a/Sources/API/Routes/ChargeRoutes.swift +++ b/Sources/API/Routes/ChargeRoutes.swift @@ -216,11 +216,11 @@ public final class ChargeRoutes { Returns a list of charges you’ve previously created. The charges are returned in sorted order, with the most recent charges appearing first. - - parameter filter: A Filter item to ass query parameters when fetching results + - parameter filter: A Filter item to pass query parameters when fetching results - returns: A StripeRequest<> item which you can then use to convert to the corresponding node */ - public func listAll(filter: Filter?=nil) throws -> StripeRequest { + public func listAll(filter: StripeFilter?=nil) throws -> StripeRequest { var query = [String : NodeRepresentable]() if let data = try filter?.createQuery() { query = data diff --git a/Sources/API/Routes/CustomerRoutes.swift b/Sources/API/Routes/CustomerRoutes.swift index 3b7485d..450a5b6 100644 --- a/Sources/API/Routes/CustomerRoutes.swift +++ b/Sources/API/Routes/CustomerRoutes.swift @@ -255,11 +255,11 @@ public final class CustomerRoutes { Returns a list of your customers. The customers are returned sorted by creation date, with the most recent customers appearing first. - - parameter filter: A Filter item to ass query parameters when fetching results + - parameter filter: A Filter item to pass query parameters when fetching results - returns: A StripeRequest<> item which you can then use to convert to the corresponding node */ - public func listAll(filter: Filter?=nil) throws -> StripeRequest { + public func listAll(filter: StripeFilter?=nil) throws -> StripeRequest { var query = [String : NodeRepresentable]() if let data = try filter?.createQuery() { query = data diff --git a/Sources/API/Routes/RefundRoutes.swift b/Sources/API/Routes/RefundRoutes.swift index 41df57b..a31f196 100644 --- a/Sources/API/Routes/RefundRoutes.swift +++ b/Sources/API/Routes/RefundRoutes.swift @@ -133,11 +133,11 @@ public final class RefundRoutes { recent refunds appearing first. For convenience, the 10 most recent refunds are always available by default on the charge object. - - parameter filter: A Filter item to ass query parameters when fetching results + - parameter filter: A Filter item to pass query parameters when fetching results - returns: A StripeRequest<> item which you can then use to convert to the corresponding node */ - public func listAll(by charge: String? = nil, filter: Filter?=nil) throws -> StripeRequest { + public func listAll(by charge: String? = nil, filter: StripeFilter?=nil) throws -> StripeRequest { var query = [String : NodeRepresentable]() if let data = try filter?.createQuery() { query = data From a470b7d4abc70191281403dac2d2f733f2b6e4c9 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:32:08 -0400 Subject: [PATCH 14/26] Added coupon routes --- Sources/API/Routes/CouponRoutes.swift | 230 ++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 Sources/API/Routes/CouponRoutes.swift diff --git a/Sources/API/Routes/CouponRoutes.swift b/Sources/API/Routes/CouponRoutes.swift new file mode 100644 index 0000000..9190a8c --- /dev/null +++ b/Sources/API/Routes/CouponRoutes.swift @@ -0,0 +1,230 @@ +// +// CouponRoutes.swift +// Stripe +// +// Created by Andrew Edwards on 5/28/17. +// +// + +import Foundation +import Node +import HTTP +import Models +import Helpers +import Errors + +public final class CouponRoutes +{ + let client: StripeClient + + init(client: StripeClient) + { + self.client = client + } + + /** + Create a coupon + Creates a new coupon object. + + - parameter id: Unique string of your choice that will be used to identify this coupon when applying it to a customer. + This is often a specific code you’ll give to your customer to use when signing up (e.g. FALL25OFF). If + you don’t want to specify a particular code, you can leave the ID blank and Stripe will generate a + random code for you. + + - parameter duration: Specifies how long the discount will be in effect. + + - parameter amountOff: Amount to subtract from an invoice total (required if percent_off is not passed). + + - parameter currency: The currency in which the charge will be under. (required if amount_off passed). + + - parameter durationInMonths: Required only if duration is `repeating`, in which case it must be a positive + integer that specifies the number of months the discount will be in effect. + + - parameter maxRedemptions: A positive integer specifying the number of times the coupon can be redeemed before it’s + no longer valid. + + - parameter percentOff: A positive integer between 1 and 100 that represents the discount the coupon will apply + (required if amount_off is not passed). + + - parameter redeemBy: Unix timestamp specifying the last time at which the coupon can be redeemed. + + - parameter metaData: A set of key/value pairs that you can attach to a coupon object. + + - returns: A StripeRequest<> item which you can then use to convert to the corresponding node. + */ + + public func create(id: String?, duration: StripeDuration, amountOff: Int?, currency: StripeCurrency?, durationInMonths: Int?, maxRedemptions: Int?, percentOff: Int?, redeemBy: Date?, metadata: [String: String]?) throws -> StripeRequest + { + var body = Node([:]) + + body["duration"] = Node(duration.rawValue) + + if let amountOff = amountOff + { + body["amount_off"] = Node(amountOff) + } + + if let currency = currency + { + body["currency"] = Node(currency.rawValue) + } + + if let durationInMonths = durationInMonths + { + body["duration_in_months"] = Node(durationInMonths) + } + + if let maxRedemptions = maxRedemptions + { + body["max_redemptions"] = Node(maxRedemptions) + } + + if let percentOff = percentOff + { + body["percent_off"] = Node(percentOff) + } + + if let redeemBy = redeemBy + { + body["redeem_by"] = Node(Int(redeemBy.timeIntervalSince1970)) + } + + if let metadata = metadata + { + for (key, value) in metadata { + body["metadata[\(key)]"] = try Node(node: value) + } + } + + return try StripeRequest(client: self.client, method: .post, route: .coupons, query: [:], body: Body.data(body.formURLEncoded()), headers: nil) + } + + /** + Create a coupon + Creates a new coupon object. + + - parameter coupon: A coupon object created with appropriate values set. Any unset parameters (nil) + will unset the value on stripe. + + - returns: A StripeRequest<> item which you can then use to convert to the corresponding node. + */ + + public func create(coupon: Coupon) throws -> StripeRequest + { + var body = Node([:]) + + body["duration"] = Node(coupon.duration.rawValue) + + if let amountOff = coupon.amountOff + { + body["amount_off"] = Node(amountOff) + } + + if let currency = coupon.currency + { + body["currency"] = Node(currency.rawValue) + } + + if let durationInMonths = coupon.durationInMonths + { + body["duration_in_months"] = Node(durationInMonths) + } + + if let maxRedemptions = coupon.maxRedemptions + { + body["max_redemptions"] = Node(maxRedemptions) + } + + if let percentOff = coupon.percentOff + { + body["percent_off"] = Node(percentOff) + } + + if let redeemBy = coupon.redeemBy + { + body["redeem_by"] = Node(redeemBy.timeIntervalSince1970) + } + + if let metadata = coupon.metadata?.object + { + for (key, value) in metadata { + body["metadata[\(key)]"] = value + } + } + + return try StripeRequest(client: self.client, method: .post, route: .coupons, query: [:], body: Body.data(body.formURLEncoded()), headers: nil) + } + + /** + Retrieve a coupon + Retrieves the coupon with the given ID. + + - parameter couponId: The ID of the desired coupon. + + - returns: A StripeRequest<> item which you can then use to convert to the corresponding node + */ + + public func retrieve(coupon couponId: String) throws -> StripeRequest + { + return try StripeRequest(client: self.client, method: .get, route: .coupon(couponId), query: [:], body: nil, headers: nil) + } + + /** + Update a coupon + Updates the metadata of a coupon. Other coupon details (currency, duration, amount_off) are, by design, not editable. + + - parameter couponId: The identifier of the coupon to be updated. + + - parameter metaData: A set of key/value pairs that you can attach to a coupon object. It can be useful for storing additional + information about the coupon in a structured format. + + - returns: A StripeRequest<> item which you can then use to convert to the corresponding node + */ + + public func update(metadata: [String:String], forCouponId couponId: String) throws -> StripeRequest + { + var body = Node([:]) + + for (key, value) in metadata + { + body["metadata[\(key)]"] = try Node(node: "\(String(describing: value))") + } + + return try StripeRequest(client: self.client, method: .post, route: .coupon(couponId), query: [:], body: Body.data(body.formURLEncoded()), headers: nil) + } + + /** + Delete a coupon + Deletes the coupon with the given ID. + + - parameter couponId: The identifier of the coupon to be deleted. + + - returns: A StripeRequest<> item which you can then use to convert to the corresponding node + */ + + public func delete(coupon couponId: String) throws -> StripeRequest + { + return try StripeRequest(client: self.client, method: .delete, route: .coupon(couponId), query: [:], body: nil, headers: nil) + } + + /** + List all coupons + Returns a list of your coupons. The coupons are returned sorted by creation date, with the + most recent coupons appearing first. + + - parameter filter: A Filter item to pass query parameters when fetching results. + + - returns: A StripeRequest<> item which you can then use to convert to the corresponding node + */ + + public func listAll(filter: StripeFilter?=nil) throws -> StripeRequest + { + var query = [String : NodeRepresentable]() + + if let data = try filter?.createQuery() + { + query = data + } + return try StripeRequest(client: self.client, method: .get, route: .coupons, query: query, body: nil, headers: nil) + } +} From 1a2aa0cb036ce58f8efc320dfeca6f8de906555e Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:33:13 -0400 Subject: [PATCH 15/26] Updated test cases. --- Tests/StripeTests/BalanceTests.swift | 41 ++++++++++-- Tests/StripeTests/ChargeTests.swift | 95 +++++++++++++++++++++------ Tests/StripeTests/CustomerTests.swift | 64 ++++++++++++------ Tests/StripeTests/RefundTests.swift | 57 ++++++++++++---- 4 files changed, 199 insertions(+), 58 deletions(-) diff --git a/Tests/StripeTests/BalanceTests.swift b/Tests/StripeTests/BalanceTests.swift index 809bbe4..98837e4 100644 --- a/Tests/StripeTests/BalanceTests.swift +++ b/Tests/StripeTests/BalanceTests.swift @@ -21,15 +21,43 @@ class BalanceTests: XCTestCase { ("testFilterBalanceHistory", testFilterBalanceHistory), ] + var drop: Droplet? + var transactionId: String = "" + + override func setUp() + { + do + { + drop = try self.makeDroplet() + + let paymentToken = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", + expirationMonth: 10, + expirationYear: 2018, + cvc: 123, + name: "Test Card") + .serializedResponse().id ?? "" + + transactionId = try drop?.stripe?.charge.create(amount: 10_00, + in: .usd, + for: .source(paymentToken), + description: "Vapor Stripe: Test Description") + .serializedResponse() + .balanceTransactionId ?? "" + } + catch + { + fatalError("Setup failed: \(error.localizedDescription)") + } + } + func testBalance() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.balance.retrieveBalance().serializedResponse() + let object = try drop?.stripe?.balance.retrieveBalance().serializedResponse() XCTAssertNotNil(object) } - func testBalanceTransactionItem() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.balance.retrieveBalance(forTransaction: TestTransactionID).serializedResponse() + func testBalanceTransactionItem() throws + { + let object = try drop?.stripe?.balance.retrieveBalance(forTransaction: transactionId).serializedResponse() XCTAssertNotNil(object) } @@ -41,10 +69,9 @@ class BalanceTests: XCTestCase { func testFilterBalanceHistory() throws { let drop = try self.makeDroplet() - let filter = Filter() + let filter = StripeFilter() filter.limit = 1 let object = try drop.stripe?.balance.history(forFilter: filter).serializedResponse() XCTAssertEqual(object?.items.count, 1) } - } diff --git a/Tests/StripeTests/ChargeTests.swift b/Tests/StripeTests/ChargeTests.swift index f526081..9f88b0e 100644 --- a/Tests/StripeTests/ChargeTests.swift +++ b/Tests/StripeTests/ChargeTests.swift @@ -24,34 +24,73 @@ class ChargeTests: XCTestCase { ("testChargeCapture", testChargeCapture) ] - func testCharge() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.charge.create(amount: 10_000, in: .usd, for: .source(TestChargeSourceTokenID), description: "Vapor Stripe: Test Description").serializedResponse() + var drop: Droplet? + var chargeId: String = "" + + override func setUp() + { + do + { + drop = try self.makeDroplet() + + let tokenId = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", + expirationMonth: 10, + expirationYear: 2018, + cvc: 123, + name: "Test Card") + .serializedResponse().id ?? "" + + chargeId = try drop?.stripe?.charge.create(amount: 10_00, + in: .usd, + for: .source(tokenId), + description: "Vapor Stripe: Test Description") + .serializedResponse().id ?? "" + } + catch + { + fatalError("Setup failed: \(error.localizedDescription)") + } + } + + func testCharge() throws + { + let paymentToken = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", + expirationMonth: 10, + expirationYear: 2018, + cvc: 123, + name: "Test Card") + .serializedResponse() + + let object = try drop?.stripe?.charge.create(amount: 10_00, + in: .usd, + for: .source(paymentToken?.id ?? ""), + description: "Vapor Stripe: Test Description") + .serializedResponse() XCTAssertNotNil(object) } - func testRetrieveCharge() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.charge.retrieve(charge: TestChargeID).serializedResponse() + func testRetrieveCharge() throws + { + let object = try drop?.stripe?.charge.retrieve(charge: chargeId).serializedResponse() XCTAssertNotNil(object) } - func testListAllCharges() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.charge.listAll().serializedResponse() + func testListAllCharges() throws + { + let object = try drop?.stripe?.charge.listAll().serializedResponse() XCTAssertNotNil(object) } - func testFilterAllCharges() throws { - let drop = try self.makeDroplet() - let filter = Filter() + func testFilterAllCharges() throws + { + let filter = StripeFilter() filter.limit = 1 - let object = try drop.stripe?.charge.listAll(filter: filter).serializedResponse() + let object = try drop?.stripe?.charge.listAll(filter: filter).serializedResponse() XCTAssertEqual(object?.items.count, 1) } - func testChargeUpdate() throws { - let drop = try self.makeDroplet() + func testChargeUpdate() throws + { let shippingAddress = ShippingAddress() shippingAddress.addressLine1 = "123 Test St" shippingAddress.addressLine2 = "456 Apt" @@ -68,13 +107,31 @@ class ChargeTests: XCTestCase { shippingLabel.address = shippingAddress let metadata = ["test": "metadata"] - let object = try drop.stripe?.charge.update(charge: TestChargeID, metadata: metadata, receiptEmail: "test-email@test.com", shippingLabel: shippingLabel).serializedResponse() + let object = try drop?.stripe?.charge.update(charge: chargeId, + metadata: metadata, + receiptEmail: "test-email@test.com", + shippingLabel: shippingLabel) + .serializedResponse() XCTAssertNotNil(object) } - func testChargeCapture() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.charge.capture(charge: TestChargeID).serializedResponse() + func testChargeCapture() throws + { + let paymentToken = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", + expirationMonth: 10, + expirationYear: 2018, + cvc: 123, + name: "Test Card") + .serializedResponse().id ?? "" + + let uncapturedCharge = try drop?.stripe?.charge.create(amount: 10_00, + in: .usd, + for: .source(paymentToken), + description: "Vapor Stripe: test Description", + capture: false) + .serializedResponse().id ?? "" + + let object = try drop?.stripe?.charge.capture(charge: uncapturedCharge).serializedResponse() XCTAssertNotNil(object) } } diff --git a/Tests/StripeTests/CustomerTests.swift b/Tests/StripeTests/CustomerTests.swift index f2545f1..5b0ceb2 100644 --- a/Tests/StripeTests/CustomerTests.swift +++ b/Tests/StripeTests/CustomerTests.swift @@ -24,48 +24,70 @@ class CustomerTests: XCTestCase { ("testFilterCustomers", testFilterCustomers) ] - func testCreateCustomer() throws { - let drop = try self.makeDroplet() + var drop: Droplet? + var customerId: String = "" + + override func setUp() + { + do + { + drop = try self.makeDroplet() + + let customer = Customer() + + customer.email = "test@stripetest.com" + + customer.description = "This is a test customer" + + customerId = try drop?.stripe?.customer.create(customer: customer).serializedResponse().id ?? "" + } + catch + { + fatalError("Setup failed: \(error.localizedDescription)") + } + } + + func testCreateCustomer() throws + { let customer = Customer() customer.email = "test@stripetest.com" customer.description = "This is a test customer" - let object = try drop.stripe?.customer.create(customer: customer).serializedResponse() + let object = try drop?.stripe?.customer.create(customer: customer).serializedResponse() XCTAssertNotNil(object) } - func testRetrieveCustomer() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.customer.retrieve(customer: TestCustomerID).serializedResponse() + func testRetrieveCustomer() throws + { + let object = try drop?.stripe?.customer.retrieve(customer: customerId).serializedResponse() XCTAssertNotNil(object) } - func testUpdateCustomer() throws { - let drop = try self.makeDroplet() + func testUpdateCustomer() throws + { let customer = Customer() - customer.email = "test@stripetest.com" + customer.email = "tester@stripetest.com" customer.description = "This is a test customer updated" - let object = try drop.stripe?.customer.update(customer: customer, forCustomerId: TestCustomerID).serializedResponse() + let object = try drop?.stripe?.customer.update(customer: customer, forCustomerId: customerId).serializedResponse() XCTAssertNotNil(object) } - func testDeleteCustomer() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.customer.delete(customer: TestCustomerID).serializedResponse() + func testDeleteCustomer() throws + { + let object = try drop?.stripe?.customer.delete(customer: customerId).serializedResponse() XCTAssertEqual(object?.deleted, true) } - func testRetrieveAllCustomers() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.customer.listAll().serializedResponse() + func testRetrieveAllCustomers() throws + { + let object = try drop?.stripe?.customer.listAll().serializedResponse() XCTAssertGreaterThanOrEqual(object!.items!.count, 1) } - func testFilterCustomers() throws { - let drop = try self.makeDroplet() - let filter = Filter() + func testFilterCustomers() throws + { + let filter = StripeFilter() filter.limit = 1 - let object = try drop.stripe?.customer.listAll(filter: filter).serializedResponse() + let object = try drop?.stripe?.customer.listAll(filter: filter).serializedResponse() XCTAssertEqual(object?.items?.count, 1) } - } diff --git a/Tests/StripeTests/RefundTests.swift b/Tests/StripeTests/RefundTests.swift index 76fff6e..6a9b15d 100644 --- a/Tests/StripeTests/RefundTests.swift +++ b/Tests/StripeTests/RefundTests.swift @@ -21,28 +21,63 @@ class RefundTests: XCTestCase { ("testListingAllRefunds", testListingAllRefunds) ] + var drop: Droplet? + var refundId: String = "" + + override func setUp() + { + do + { + drop = try self.makeDroplet() + + let tokenId = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", + expirationMonth: 10, + expirationYear: 2018, + cvc: 123, + name: "Test Card").serializedResponse().id ?? "" + + let chargeId = try drop?.stripe?.charge.create(amount: 10_00, + in: .usd, + for: .source(tokenId), + description: "Vapor Stripe: Test Description").serializedResponse().id ?? "" + + refundId = try drop?.stripe?.refunds.refund(charge: chargeId).serializedResponse().id ?? "" + } + catch + { + fatalError("Setup failed: \(error.localizedDescription)") + } + } + func testRefunding() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.refunds.refund(charge: TestChargeID).serializedResponse() + + let paymentToken = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", + expirationMonth: 10, + expirationYear: 2018, + cvc: 123, + name: "Test Card").serializedResponse().id ?? "" + + let charge = try drop?.stripe?.charge.create(amount: 10_00, + in: .usd, + for: .source(paymentToken), + description: "Vapor Stripe: Test Description").serializedResponse().id ?? "" + + let object = try drop?.stripe?.refunds.refund(charge: charge).serializedResponse() XCTAssertNotNil(object) } func testUpdatingRefund() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.refunds.update(refund: TestRefundID, metadata: ["test": "Test Updating a charge"]).serializedResponse() + let object = try drop?.stripe?.refunds.update(refund: refundId, metadata: ["test": "Test Updating a charge"]).serializedResponse() XCTAssertNotNil(object) } func testRetrievingRefund() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.refunds.retrieve(refund: TestRefundID).serializedResponse() + let object = try drop?.stripe?.refunds.retrieve(refund: refundId).serializedResponse() XCTAssertNotNil(object) } func testListingAllRefunds() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.refunds.listAll().serializedResponse() - XCTAssertGreaterThanOrEqual(object!.items!.count, 2) - } - + let object = try drop?.stripe?.refunds.listAll().serializedResponse() + XCTAssertGreaterThanOrEqual(object!.items!.count, 1) + } } From 88874c07a8122b336b9d7c4782ea59f10e1af16f Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:35:15 -0400 Subject: [PATCH 16/26] Removed tokens and id's. Tests now create and use tokens and id's dynamically. --- Tests/StripeTests/Test+Droplet.swift | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/Tests/StripeTests/Test+Droplet.swift b/Tests/StripeTests/Test+Droplet.swift index 2779845..e048a1b 100644 --- a/Tests/StripeTests/Test+Droplet.swift +++ b/Tests/StripeTests/Test+Droplet.swift @@ -11,29 +11,11 @@ import XCTest import Vapor import Stripe -// Used for fetching a specific Transaction in the history -let TestTransactionID = "txn_1A9KJiJm6xi4tXu1EkbD0ZEC" - -// Used for creating charges -let TestChargeSourceTokenID = "tok_1A9M61Jm6xi4tXu1sSQMnsxp" - -// Used for fetching a specific charge -let TestChargeID = "ch_1A9M5oJm6xi4tXu1iWO7wxMy" - -// Used for fetching a specific customer -let TestCustomerID = "cus_AVqRAm2Gv8EMyd" - -// Used for token testing -let TestTokenID = "tok_1AIiMpJm6xi4tXu1hoimk73q" - -// Used for refund testing -let TestRefundID = "re_1AJ4FFJm6xi4tXu1YFFB9N7P" - extension XCTestCase { func makeDroplet() throws -> Droplet { let config = Config([ "stripe": [ - "apiKey": "sk_test_Pb8SpX80t1XhJengpQ3oE67H" // Add your own API Key for tests + "apiKey": "" // Add your own API Key for tests ], ]) try config.addProvider(Stripe.Provider.self) From 9949aeffca9c0796460c1614ce07f0664200296e Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:35:42 -0400 Subject: [PATCH 17/26] Updated tests --- Tests/StripeTests/TokenTests.swift | 46 ++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/Tests/StripeTests/TokenTests.swift b/Tests/StripeTests/TokenTests.swift index bb10602..51ef88d 100644 --- a/Tests/StripeTests/TokenTests.swift +++ b/Tests/StripeTests/TokenTests.swift @@ -20,22 +20,50 @@ class TokenTests: XCTestCase { ("testBankAccountCreation", testBankAccountCreation), ] - func testTokenCreation() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", expirationMonth: 10, expirationYear: 2018, cvc: 123, name: "Test Card").serializedResponse() + var drop: Droplet? + var tokenId: String = "" + + override func setUp() + { + do + { + drop = try self.makeDroplet() + + tokenId = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", + expirationMonth: 10, + expirationYear: 2018, + cvc: 123, + name: "Test Card").serializedResponse().id ?? "" + } + catch + { + fatalError("Setup failed: \(error.localizedDescription)") + } + } + + func testTokenCreation() throws + { + let object = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", + expirationMonth: 10, + expirationYear: 2018, + cvc: 123, + name: "Test Card").serializedResponse() XCTAssertNotNil(object?.card) } - func testTokenRetrieval() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.tokens.retrieve(TestTokenID).serializedResponse() + func testTokenRetrieval() throws + { + let object = try drop?.stripe?.tokens.retrieve(tokenId).serializedResponse() XCTAssertNotNil(object) } func testBankAccountCreation() throws { - let drop = try self.makeDroplet() - let object = try drop.stripe?.tokens.createBank(country: "US", currency: .usd, accountNumber: "000123456789", routingNumber: "110000000", accountHolderName: "Test Person", accountHolderType: "Individual").serializedResponse() + let object = try drop?.stripe?.tokens.createBank(country: "US", + currency: .usd, + accountNumber: "000123456789", + routingNumber: "110000000", + accountHolderName: "Test Person", + accountHolderType: "Individual").serializedResponse() XCTAssertNotNil(object?.bankAccount) } - } From c1fac8f4aec59d297670ed117fde001330c6a844 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 10:44:23 -0400 Subject: [PATCH 18/26] Added coupon tests. --- Tests/StripeTests/CouponTests.swift | 127 ++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 Tests/StripeTests/CouponTests.swift diff --git a/Tests/StripeTests/CouponTests.swift b/Tests/StripeTests/CouponTests.swift new file mode 100644 index 0000000..b95b71a --- /dev/null +++ b/Tests/StripeTests/CouponTests.swift @@ -0,0 +1,127 @@ +// +// CouponTests.swift +// Stripe +// +// Created by Andrew Edwards on 5/28/17. +// +// + +import XCTest + +@testable import Stripe +@testable import Vapor +@testable import Helpers +@testable import API + +class CouponTests: XCTestCase +{ + static var allTests = [ + ("testCreateCoupon", testCreateCoupon), + ("testRetrieveCoupon",testRetrieveCoupon), + ("testUpdateCoupon",testUpdateCoupon), + ("testDeleteCoupon",testDeleteCoupon), + ("testListAllCoupons",testListAllCoupons), + ("testFilterCoupons",testFilterCoupons) + ] + + var drop: Droplet? + var couponId: String = "" + + override func setUp() + { + do + { + drop = try self.makeDroplet() + + couponId = try drop?.stripe?.coupons.create(id: nil, + duration: .once, + amountOff: 5, + currency: .usd, + durationInMonths: nil, + maxRedemptions: 5, + percentOff: nil, + redeemBy: Date().addingTimeInterval(3000), + metadata: ["meta":"data"]).serializedResponse().id ?? "" + } + catch + { + fatalError("Setup failed: \(error.localizedDescription)") + } + } + + func testCreateCoupon() throws + { + let coupon = try drop?.stripe?.coupons.create(id: nil, + duration: .once, + amountOff: 5, + currency: .usd, + durationInMonths: nil, + maxRedemptions: 5, + percentOff: nil, + redeemBy: Date().addingTimeInterval(3000), + metadata: ["meta":"data"]).serializedResponse() + XCTAssertNotNil(coupon) + } + + func testRetrieveCoupon() throws + { + let coupon = try drop?.stripe?.coupons.retrieve(coupon: couponId).serializedResponse() + + XCTAssertNotNil(coupon) + } + + func testUpdateCoupon() throws + { + let metadata = ["hello":"world"] + let updatedCoupon = try drop?.stripe?.coupons.update(metadata: metadata, forCouponId: couponId).serializedResponse() + + XCTAssertNotNil(updatedCoupon) + + XCTAssert(updatedCoupon?.metadata?["hello"] == "world") + } + + func testDeleteCoupon() throws + { + let deletedCoupon = try drop?.stripe?.coupons.delete(coupon: couponId).serializedResponse() + + XCTAssertNotNil(deletedCoupon) + + XCTAssertTrue(deletedCoupon?.deleted ?? false) + } + + func testListAllCoupons() throws + { + let coupons = try drop?.stripe?.coupons.listAll().serializedResponse() + + XCTAssertNotNil(coupons) + + if let couponItems = coupons?.items + { + XCTAssertGreaterThanOrEqual(couponItems.count, 1) + } + else + { + XCTFail("Coupons are not present") + } + } + + func testFilterCoupons() throws + { + let filter = StripeFilter() + + filter.limit = 1 + + let coupons = try drop?.stripe?.coupons.listAll(filter: filter).serializedResponse() + + XCTAssertNotNil(coupons) + + if let couponItems = coupons?.items + { + XCTAssertEqual(couponItems.count, 1) + } + else + { + XCTFail("Coupons are not present") + } + } +} From ae208ba9554356ef7fdb9dca08cde2ecc9829cf6 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 11:07:51 -0400 Subject: [PATCH 19/26] Renamed to StripeFilter --- Sources/API/Filter/Filter.swift | 134 -------------------------------- 1 file changed, 134 deletions(-) delete mode 100644 Sources/API/Filter/Filter.swift diff --git a/Sources/API/Filter/Filter.swift b/Sources/API/Filter/Filter.swift deleted file mode 100644 index b503375..0000000 --- a/Sources/API/Filter/Filter.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// Filter.swift -// Stripe -// -// Created by Anthony Castelli on 4/16/17. -// -// - -import Foundation -import Vapor -import Helpers -import Node -import HTTP - -public final class Filter { - - public init() { } - - /** - Can either be a UNIX timestamp, or a dictionary with these key/values - - - gt: Return values where the created field is after this timestamp. - - gte: Return values where the created field is after or equal to this timestamp. - - lt: Return values where the created field is before this timestamp. - - lte: Return values where the created field is before or equal to this timestamp. - - Example: - created = Node(node: ["UNIX_TIMESTAMP": "gte"]) - or - created = Node(node: UNIX_TIMESTAMP) - */ - public var created: Node? - - /** - Only return charges for the customer specified by this customer ID. - */ - public var customerId: Node? - - /** - A cursor for use in pagination. `ending_before` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, starting with `obj_bar`, your - subsequent call can include `ending_before=obj_bar` in order to fetch the previous page of the list. - - Example: endingBefore = "obj_bar" - */ - public var endingBefore: Node? - - /** - A limit on the number of objects to be returned. Limit can range between 1 and 100 items. - This field MUST be a possitive Integer or String. Default is 10 - */ - public var limit: Node? - - /** - A filter on the list based on the source of the charge. - */ - public var source: SourceType? - - /** - A cursor for use in pagination. `starting_after` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with `obj_foo`, your - subsequent call can include `starting_after=obj_foo` in order to fetch the next page of the list. - - Example: startingAfter = "obj_foo" - */ - public var startingAfter: Node? - - /** - Only return charges for this transfer group. - */ - public var transferGroup: Node? - - /** - For automatic Stripe payouts only, only returns transactions that were payed out on the specified payout ID. - */ - public var payout: Node? - - /** - Only returns transactions of the given type. One of BalanceType - */ - public var balanceType: BalanceType? - - - internal func createBody() throws -> Node { - var node = Node([:]) - if let value = self.created { - if let value = value.object { - for (key, value) in value { - node["created[\(key)]"] = value - } - } else { - node["created"] = value - } - } - - if let value = self.customerId { - node["customer"] = value - } - - if let value = self.endingBefore { - node["ending_before"] = value - } - - if let value = self.limit { - node["limit"] = value - } - - if let value = self.source { - node["source"] = value.rawType.makeNode(in: nil) - } - - if let value = self.startingAfter { - node["starting_after"] = value - } - - if let value = self.transferGroup { - node["transfer_group"] = value - } - - if let value = self.payout { - node["payout"] = value - } - - if let value = self.balanceType { - node["type"] = value.rawValue.makeNode(in: nil) - } - - return node - } - - internal func createQuery() throws -> [String : NodeRepresentable]? { - return try self.createBody().object - } -} From e6b4ba4d74e5af1c21e3e06431f52a6e83554fda Mon Sep 17 00:00:00 2001 From: Andrew Edwards Date: Mon, 29 May 2017 11:10:55 -0400 Subject: [PATCH 20/26] Update README.md Coupon implementation --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 8e6149f..73a586e 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,12 @@ The object is returned response model, or model array. * [x] Deleting * [x] Fetching by Customer ID * [x] Listing All Customers (With filters) +* [x] Coupons + * [x] Creating + * [x] Updating + * [x] Deleting + * [x] Fetching by Coupon ID + * [x] Listing All Coupons (With filters) * [ ] Disputes * [x] Refunds * [x] Creating a Refund From ab4cb0ac73994eb9485d660f5ee8c937ec679776 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 11:48:24 -0400 Subject: [PATCH 21/26] Automatic test generation with sourcery. Reduces maintenance. --- Sourcery/LinuxMain.stencil | 17 ++++++ Tests/LinuxMain.swift | 83 ++++++++++++++++++++++++--- Tests/StripeTests/BalanceTests.swift | 9 +-- Tests/StripeTests/ChargeTests.swift | 9 --- Tests/StripeTests/CouponTests.swift | 11 +--- Tests/StripeTests/CustomerTests.swift | 11 +--- Tests/StripeTests/ProviderTests.swift | 4 -- Tests/StripeTests/RefundTests.swift | 9 +-- Tests/StripeTests/TokenTests.swift | 6 -- 9 files changed, 97 insertions(+), 62 deletions(-) create mode 100644 Sourcery/LinuxMain.stencil diff --git a/Sourcery/LinuxMain.stencil b/Sourcery/LinuxMain.stencil new file mode 100644 index 0000000..5b3f946 --- /dev/null +++ b/Sourcery/LinuxMain.stencil @@ -0,0 +1,17 @@ +// sourcery:file:Tests/LinuxMain.swift +import XCTest +{{ argument.testimports }} + +{% for type in types.classes|based:"XCTestCase" %} +{% if not type.annotations.disableTests %}extension {{ type.name }} { +static var allTests = [ +{% for method in type.methods %}{% if method.parameters.count == 0 and method.shortName|hasPrefix:"test" %} ("{{ method.shortName }}", {{ method.shortName }}), +{% endif %}{% endfor %}] +} + +{% endif %}{% endfor %} + +XCTMain([ +{% for type in types.classes|based:"XCTestCase" %}{% if not type.annotations.disableTests %} testCase({{ type.name }}.allTests), +{% endif %}{% endfor %}]) +// sourcery:end diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 6186ec2..0e4ec6a 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1,12 +1,81 @@ +// Generated using Sourcery 0.6.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT + import XCTest @testable import StripeTests +extension BalanceTests { +static var allTests = [ + ("testBalance", testBalance), + ("testBalanceTransactionItem", testBalanceTransactionItem), + ("testBalanceHistory", testBalanceHistory), + ("testFilterBalanceHistory", testFilterBalanceHistory), +] +} + +extension ChargeTests { +static var allTests = [ + ("testCharge", testCharge), + ("testRetrieveCharge", testRetrieveCharge), + ("testListAllCharges", testListAllCharges), + ("testFilterAllCharges", testFilterAllCharges), + ("testChargeUpdate", testChargeUpdate), + ("testChargeCapture", testChargeCapture), +] +} + +extension CouponTests { +static var allTests = [ + ("testCreateCoupon", testCreateCoupon), + ("testRetrieveCoupon", testRetrieveCoupon), + ("testUpdateCoupon", testUpdateCoupon), + ("testDeleteCoupon", testDeleteCoupon), + ("testListAllCoupons", testListAllCoupons), + ("testFilterCoupons", testFilterCoupons), +] +} + +extension CustomerTests { +static var allTests = [ + ("testCreateCustomer", testCreateCustomer), + ("testRetrieveCustomer", testRetrieveCustomer), + ("testUpdateCustomer", testUpdateCustomer), + ("testDeleteCustomer", testDeleteCustomer), + ("testRetrieveAllCustomers", testRetrieveAllCustomers), + ("testFilterCustomers", testFilterCustomers), +] +} + +extension ProviderTests { +static var allTests = [ + ("testProvider", testProvider), +] +} + +extension RefundTests { +static var allTests = [ + ("testRefunding", testRefunding), + ("testUpdatingRefund", testUpdatingRefund), + ("testRetrievingRefund", testRetrievingRefund), + ("testListingAllRefunds", testListingAllRefunds), +] +} + +extension TokenTests { +static var allTests = [ + ("testTokenCreation", testTokenCreation), + ("testTokenRetrieval", testTokenRetrieval), + ("testBankAccountCreation", testBankAccountCreation), +] +} + + XCTMain([ - testCase(ProviderTests.allTests), - - testCase(BalanceTests.allTests), - testCase(ChargeTests.allTests), - testCase(CustomerTests.allTests), - testCase(TokenTests.allTests), - testCase(RefundTests.allTests), + testCase(BalanceTests.allTests), + testCase(ChargeTests.allTests), + testCase(CouponTests.allTests), + testCase(CustomerTests.allTests), + testCase(ProviderTests.allTests), + testCase(RefundTests.allTests), + testCase(TokenTests.allTests), ]) diff --git a/Tests/StripeTests/BalanceTests.swift b/Tests/StripeTests/BalanceTests.swift index 98837e4..33d25c8 100644 --- a/Tests/StripeTests/BalanceTests.swift +++ b/Tests/StripeTests/BalanceTests.swift @@ -13,14 +13,7 @@ import XCTest @testable import API class BalanceTests: XCTestCase { - - static var allTests = [ - ("testBalance", testBalance), - ("testBalanceTransactionItem", testBalanceTransactionItem), - ("testBalanceHistory", testBalanceHistory), - ("testFilterBalanceHistory", testFilterBalanceHistory), - ] - + var drop: Droplet? var transactionId: String = "" diff --git a/Tests/StripeTests/ChargeTests.swift b/Tests/StripeTests/ChargeTests.swift index 9f88b0e..24c8aa7 100644 --- a/Tests/StripeTests/ChargeTests.swift +++ b/Tests/StripeTests/ChargeTests.swift @@ -14,15 +14,6 @@ import XCTest @testable import API class ChargeTests: XCTestCase { - - static var allTests = [ - ("testCharge", testCharge), - ("testRetrieveCharge", testRetrieveCharge), - ("testListAllCharges", testListAllCharges), - ("testFilterAllCharges", testFilterAllCharges), - ("testChargeUpdate", testChargeUpdate), - ("testChargeCapture", testChargeCapture) - ] var drop: Droplet? var chargeId: String = "" diff --git a/Tests/StripeTests/CouponTests.swift b/Tests/StripeTests/CouponTests.swift index b95b71a..b95da2a 100644 --- a/Tests/StripeTests/CouponTests.swift +++ b/Tests/StripeTests/CouponTests.swift @@ -14,16 +14,7 @@ import XCTest @testable import API class CouponTests: XCTestCase -{ - static var allTests = [ - ("testCreateCoupon", testCreateCoupon), - ("testRetrieveCoupon",testRetrieveCoupon), - ("testUpdateCoupon",testUpdateCoupon), - ("testDeleteCoupon",testDeleteCoupon), - ("testListAllCoupons",testListAllCoupons), - ("testFilterCoupons",testFilterCoupons) - ] - +{ var drop: Droplet? var couponId: String = "" diff --git a/Tests/StripeTests/CustomerTests.swift b/Tests/StripeTests/CustomerTests.swift index 5b0ceb2..8f2759f 100644 --- a/Tests/StripeTests/CustomerTests.swift +++ b/Tests/StripeTests/CustomerTests.swift @@ -14,16 +14,7 @@ import XCTest @testable import API class CustomerTests: XCTestCase { - - static var allTests = [ - ("testCreateCustomer ", testCreateCustomer), - ("testRetrieveCustomer", testRetrieveCustomer), - ("testUpdateCustomer", testUpdateCustomer), - ("testDeleteCustomer", testDeleteCustomer), - ("testRetrieveAllCustomers", testRetrieveAllCustomers), - ("testFilterCustomers", testFilterCustomers) - ] - + var drop: Droplet? var customerId: String = "" diff --git a/Tests/StripeTests/ProviderTests.swift b/Tests/StripeTests/ProviderTests.swift index 10cf04f..9132b5c 100644 --- a/Tests/StripeTests/ProviderTests.swift +++ b/Tests/StripeTests/ProviderTests.swift @@ -4,10 +4,6 @@ import XCTest class ProviderTests: XCTestCase { - static var allTests = [ - ("testProvider", testProvider), - ] - func testProvider() throws { let config = Config([ "stripe": [ diff --git a/Tests/StripeTests/RefundTests.swift b/Tests/StripeTests/RefundTests.swift index 6a9b15d..052c075 100644 --- a/Tests/StripeTests/RefundTests.swift +++ b/Tests/StripeTests/RefundTests.swift @@ -13,14 +13,7 @@ import XCTest @testable import API class RefundTests: XCTestCase { - - static var allTests = [ - ("testRefunding", testRefunding), - ("testUpdatingRefund", testUpdatingRefund), - ("testRetrievingRefund", testRetrievingRefund), - ("testListingAllRefunds", testListingAllRefunds) - ] - + var drop: Droplet? var refundId: String = "" diff --git a/Tests/StripeTests/TokenTests.swift b/Tests/StripeTests/TokenTests.swift index 51ef88d..ef0ce21 100644 --- a/Tests/StripeTests/TokenTests.swift +++ b/Tests/StripeTests/TokenTests.swift @@ -14,12 +14,6 @@ import XCTest class TokenTests: XCTestCase { - static var allTests = [ - ("testTokenCreation", testTokenCreation), - ("testTokenRetrieval", testTokenRetrieval), - ("testBankAccountCreation", testBankAccountCreation), - ] - var drop: Droplet? var tokenId: String = "" From eb14a962a755170f6f76179c56f41f16b56eb6b1 Mon Sep 17 00:00:00 2001 From: Andrew Edwards Date: Mon, 29 May 2017 11:59:01 -0400 Subject: [PATCH 22/26] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 73a586e..169a27b 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,12 @@ let object = try drop.stripe?.balance.history().serializedResponse() ~~~~ The object is returned response model, or model array. +## Testing + +To avoid having to remmeber to add tests to `LinuxMain.swift` you can use [Sourcery][sourcery] to add your tets cases there for you. Just install the sourcery binary with Homebrew `brew install sourcery`, navigate to your project flder, and from the command line run the following: +~~~~bash +sourcery --sources Tests/ --templates Sourcery/LinuxMain.stencil --args testimports='@testable import StripeTests' +~~~~ ## Whats Implemented * [x] Balance Fetching * [x] History @@ -74,3 +80,4 @@ The object is returned response model, or model array. [stripe_home]: http://stripe.com "Stripe" [stripe_api]: https://stripe.com/docs/api "Stripe API Endpoints" +[sourcery]: https://github.com/krzysztofzablocki/Sourcery "Sourcery" From a4dc72f3c44862eecbf513c8bd9b38db7701d647 Mon Sep 17 00:00:00 2001 From: Andrew Edwards Date: Mon, 29 May 2017 11:59:27 -0400 Subject: [PATCH 23/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 169a27b..76457d8 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ The object is returned response model, or model array. ## Testing -To avoid having to remmeber to add tests to `LinuxMain.swift` you can use [Sourcery][sourcery] to add your tets cases there for you. Just install the sourcery binary with Homebrew `brew install sourcery`, navigate to your project flder, and from the command line run the following: +To avoid having to remmeber to add tests to `LinuxMain.swift` you can use [Sourcery][sourcery] to add your tets cases there for you. Just install the sourcery binary with Homebrew `brew install sourcery`, navigate to your project folder, and from the command line run the following: ~~~~bash sourcery --sources Tests/ --templates Sourcery/LinuxMain.stencil --args testimports='@testable import StripeTests' ~~~~ From 126cc973d32e27d3b26bad848b7e4401359fb400 Mon Sep 17 00:00:00 2001 From: Andrew Edwards Date: Mon, 29 May 2017 12:02:38 -0400 Subject: [PATCH 24/26] Update README.md --- README.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 76457d8..49ad4d5 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,33 @@ The object is returned response model, or model array. ## Testing -To avoid having to remmeber to add tests to `LinuxMain.swift` you can use [Sourcery][sourcery] to add your tets cases there for you. Just install the sourcery binary with Homebrew `brew install sourcery`, navigate to your project folder, and from the command line run the following: +To avoid having to remember to add tests to `LinuxMain.swift` you can use [Sourcery][sourcery] to add your tets cases there for you. Just install the sourcery binary with Homebrew `brew install sourcery`, navigate to your project folder, and from the command line run the following: ~~~~bash sourcery --sources Tests/ --templates Sourcery/LinuxMain.stencil --args testimports='@testable import StripeTests' ~~~~ +It will generate the following with your tests added: + +~~~~swift +import XCTest +@testable import StripeTests +extension BalanceTests { +static var allTests = [ + ("testBalance", testBalance), + . + . + . +] +} +. +. +XCTMain([ + testCase(BalanceTests.allTests), + . + . + . +]) +~~~~ + ## Whats Implemented * [x] Balance Fetching * [x] History From 64a2170125ebdefabeb12578a310b34dfd903812 Mon Sep 17 00:00:00 2001 From: Andrew Edwards Date: Mon, 29 May 2017 12:03:06 -0400 Subject: [PATCH 25/26] Update README.md --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 49ad4d5..e4abedb 100644 --- a/README.md +++ b/README.md @@ -50,18 +50,14 @@ import XCTest extension BalanceTests { static var allTests = [ ("testBalance", testBalance), - . - . - . + ... ] } . . XCTMain([ testCase(BalanceTests.allTests), - . - . - . + ... ]) ~~~~ From 4658d1c4e76a417bffa999b37dd08764ee032990 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 29 May 2017 12:49:52 -0400 Subject: [PATCH 26/26] Update braces placement --- Sources/API/Routes/CouponRoutes.swift | 66 +++++++++------------------ Sources/Helpers/StripeDuration.swift | 3 +- Sources/Models/CouponList.swift | 9 ++-- Sources/Models/Coupons/Coupon.swift | 12 ++--- Tests/StripeTests/BalanceTests.swift | 6 +-- Tests/StripeTests/ChargeTests.swift | 22 +++------ Tests/StripeTests/CouponTests.swift | 21 +++------ Tests/StripeTests/CustomerTests.swift | 21 +++------ Tests/StripeTests/RefundTests.swift | 3 +- Tests/StripeTests/TokenTests.swift | 6 +-- 10 files changed, 56 insertions(+), 113 deletions(-) diff --git a/Sources/API/Routes/CouponRoutes.swift b/Sources/API/Routes/CouponRoutes.swift index 9190a8c..4493d6a 100644 --- a/Sources/API/Routes/CouponRoutes.swift +++ b/Sources/API/Routes/CouponRoutes.swift @@ -13,12 +13,10 @@ import Models import Helpers import Errors -public final class CouponRoutes -{ +public final class CouponRoutes { let client: StripeClient - init(client: StripeClient) - { + init(client: StripeClient) { self.client = client } @@ -53,44 +51,36 @@ public final class CouponRoutes - returns: A StripeRequest<> item which you can then use to convert to the corresponding node. */ - public func create(id: String?, duration: StripeDuration, amountOff: Int?, currency: StripeCurrency?, durationInMonths: Int?, maxRedemptions: Int?, percentOff: Int?, redeemBy: Date?, metadata: [String: String]?) throws -> StripeRequest - { + public func create(id: String?, duration: StripeDuration, amountOff: Int?, currency: StripeCurrency?, durationInMonths: Int?, maxRedemptions: Int?, percentOff: Int?, redeemBy: Date?, metadata: [String: String]?) throws -> StripeRequest { var body = Node([:]) body["duration"] = Node(duration.rawValue) - if let amountOff = amountOff - { + if let amountOff = amountOff { body["amount_off"] = Node(amountOff) } - if let currency = currency - { + if let currency = currency { body["currency"] = Node(currency.rawValue) } - if let durationInMonths = durationInMonths - { + if let durationInMonths = durationInMonths { body["duration_in_months"] = Node(durationInMonths) } - if let maxRedemptions = maxRedemptions - { + if let maxRedemptions = maxRedemptions { body["max_redemptions"] = Node(maxRedemptions) } - if let percentOff = percentOff - { + if let percentOff = percentOff { body["percent_off"] = Node(percentOff) } - if let redeemBy = redeemBy - { + if let redeemBy = redeemBy { body["redeem_by"] = Node(Int(redeemBy.timeIntervalSince1970)) } - if let metadata = metadata - { + if let metadata = metadata { for (key, value) in metadata { body["metadata[\(key)]"] = try Node(node: value) } @@ -109,44 +99,36 @@ public final class CouponRoutes - returns: A StripeRequest<> item which you can then use to convert to the corresponding node. */ - public func create(coupon: Coupon) throws -> StripeRequest - { + public func create(coupon: Coupon) throws -> StripeRequest { var body = Node([:]) body["duration"] = Node(coupon.duration.rawValue) - if let amountOff = coupon.amountOff - { + if let amountOff = coupon.amountOff { body["amount_off"] = Node(amountOff) } - if let currency = coupon.currency - { + if let currency = coupon.currency { body["currency"] = Node(currency.rawValue) } - if let durationInMonths = coupon.durationInMonths - { + if let durationInMonths = coupon.durationInMonths { body["duration_in_months"] = Node(durationInMonths) } - if let maxRedemptions = coupon.maxRedemptions - { + if let maxRedemptions = coupon.maxRedemptions { body["max_redemptions"] = Node(maxRedemptions) } - if let percentOff = coupon.percentOff - { + if let percentOff = coupon.percentOff { body["percent_off"] = Node(percentOff) } - if let redeemBy = coupon.redeemBy - { + if let redeemBy = coupon.redeemBy { body["redeem_by"] = Node(redeemBy.timeIntervalSince1970) } - if let metadata = coupon.metadata?.object - { + if let metadata = coupon.metadata?.object { for (key, value) in metadata { body["metadata[\(key)]"] = value } @@ -164,8 +146,7 @@ public final class CouponRoutes - returns: A StripeRequest<> item which you can then use to convert to the corresponding node */ - public func retrieve(coupon couponId: String) throws -> StripeRequest - { + public func retrieve(coupon couponId: String) throws -> StripeRequest { return try StripeRequest(client: self.client, method: .get, route: .coupon(couponId), query: [:], body: nil, headers: nil) } @@ -181,8 +162,7 @@ public final class CouponRoutes - returns: A StripeRequest<> item which you can then use to convert to the corresponding node */ - public func update(metadata: [String:String], forCouponId couponId: String) throws -> StripeRequest - { + public func update(metadata: [String:String], forCouponId couponId: String) throws -> StripeRequest { var body = Node([:]) for (key, value) in metadata @@ -202,8 +182,7 @@ public final class CouponRoutes - returns: A StripeRequest<> item which you can then use to convert to the corresponding node */ - public func delete(coupon couponId: String) throws -> StripeRequest - { + public func delete(coupon couponId: String) throws -> StripeRequest { return try StripeRequest(client: self.client, method: .delete, route: .coupon(couponId), query: [:], body: nil, headers: nil) } @@ -217,8 +196,7 @@ public final class CouponRoutes - returns: A StripeRequest<> item which you can then use to convert to the corresponding node */ - public func listAll(filter: StripeFilter?=nil) throws -> StripeRequest - { + public func listAll(filter: StripeFilter?=nil) throws -> StripeRequest { var query = [String : NodeRepresentable]() if let data = try filter?.createQuery() diff --git a/Sources/Helpers/StripeDuration.swift b/Sources/Helpers/StripeDuration.swift index 7391561..5a604c2 100644 --- a/Sources/Helpers/StripeDuration.swift +++ b/Sources/Helpers/StripeDuration.swift @@ -6,8 +6,7 @@ // // -public enum StripeDuration: String -{ +public enum StripeDuration: String { case forever = "forever" case once = "once" case repeating = "repeating" diff --git a/Sources/Models/CouponList.swift b/Sources/Models/CouponList.swift index f732a3e..4ac021a 100644 --- a/Sources/Models/CouponList.swift +++ b/Sources/Models/CouponList.swift @@ -10,23 +10,20 @@ import Foundation import Vapor import Helpers -public final class CouponList: StripeModelProtocol -{ +public final class CouponList: StripeModelProtocol { public let object: String public let url: String public let hasMore: Bool public let items: [Coupon]? - public init(node: Node) throws - { + public init(node: Node) throws { self.object = try node.get("object") self.url = try node.get("url") self.hasMore = try node.get("has_more") self.items = try node.get("data") } - public func makeNode(in context: Context?) throws -> Node - { + public func makeNode(in context: Context?) throws -> Node { let object: [String : Any?] = [ "object": self.object, "url": self.url, diff --git a/Sources/Models/Coupons/Coupon.swift b/Sources/Models/Coupons/Coupon.swift index da471a9..4d931af 100644 --- a/Sources/Models/Coupons/Coupon.swift +++ b/Sources/Models/Coupons/Coupon.swift @@ -14,8 +14,7 @@ import Helpers Coupon Model https://stripe.com/docs/api/curl#coupon_object */ -public final class Coupon: StripeModelProtocol -{ +public final class Coupon: StripeModelProtocol { public var id: String? public var amountOff: Int? public var currency: StripeCurrency? @@ -37,13 +36,11 @@ public final class Coupon: StripeModelProtocol public var metadata: Node? - required public init(duration: StripeDuration) - { + required public init(duration: StripeDuration) { self.duration = duration } - public init(node: Node) throws - { + public init(node: Node) throws { self.id = try node.get("id") self.amountOff = try node.get("amount_off") self.created = try node.get("created") @@ -68,8 +65,7 @@ public final class Coupon: StripeModelProtocol self.isValid = try node.get("valid") } - public func makeNode(in context: Context?) throws -> Node - { + public func makeNode(in context: Context?) throws -> Node { let object: [String: Any?] = [ "id": self.id, "object": self.object, diff --git a/Tests/StripeTests/BalanceTests.swift b/Tests/StripeTests/BalanceTests.swift index 33d25c8..6c15088 100644 --- a/Tests/StripeTests/BalanceTests.swift +++ b/Tests/StripeTests/BalanceTests.swift @@ -17,8 +17,7 @@ class BalanceTests: XCTestCase { var drop: Droplet? var transactionId: String = "" - override func setUp() - { + override func setUp() { do { drop = try self.makeDroplet() @@ -48,8 +47,7 @@ class BalanceTests: XCTestCase { XCTAssertNotNil(object) } - func testBalanceTransactionItem() throws - { + func testBalanceTransactionItem() throws { let object = try drop?.stripe?.balance.retrieveBalance(forTransaction: transactionId).serializedResponse() XCTAssertNotNil(object) } diff --git a/Tests/StripeTests/ChargeTests.swift b/Tests/StripeTests/ChargeTests.swift index 24c8aa7..192cdb7 100644 --- a/Tests/StripeTests/ChargeTests.swift +++ b/Tests/StripeTests/ChargeTests.swift @@ -18,8 +18,7 @@ class ChargeTests: XCTestCase { var drop: Droplet? var chargeId: String = "" - override func setUp() - { + override func setUp() { do { drop = try self.makeDroplet() @@ -43,8 +42,7 @@ class ChargeTests: XCTestCase { } } - func testCharge() throws - { + func testCharge() throws { let paymentToken = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", expirationMonth: 10, expirationYear: 2018, @@ -60,28 +58,24 @@ class ChargeTests: XCTestCase { XCTAssertNotNil(object) } - func testRetrieveCharge() throws - { + func testRetrieveCharge() throws { let object = try drop?.stripe?.charge.retrieve(charge: chargeId).serializedResponse() XCTAssertNotNil(object) } - func testListAllCharges() throws - { + func testListAllCharges() throws { let object = try drop?.stripe?.charge.listAll().serializedResponse() XCTAssertNotNil(object) } - func testFilterAllCharges() throws - { + func testFilterAllCharges() throws { let filter = StripeFilter() filter.limit = 1 let object = try drop?.stripe?.charge.listAll(filter: filter).serializedResponse() XCTAssertEqual(object?.items.count, 1) } - func testChargeUpdate() throws - { + func testChargeUpdate() throws { let shippingAddress = ShippingAddress() shippingAddress.addressLine1 = "123 Test St" shippingAddress.addressLine2 = "456 Apt" @@ -106,8 +100,7 @@ class ChargeTests: XCTestCase { XCTAssertNotNil(object) } - func testChargeCapture() throws - { + func testChargeCapture() throws { let paymentToken = try drop?.stripe?.tokens.createCard(withCardNumber: "4242 4242 4242 4242", expirationMonth: 10, expirationYear: 2018, @@ -126,4 +119,3 @@ class ChargeTests: XCTestCase { XCTAssertNotNil(object) } } - diff --git a/Tests/StripeTests/CouponTests.swift b/Tests/StripeTests/CouponTests.swift index b95da2a..b7dc0b6 100644 --- a/Tests/StripeTests/CouponTests.swift +++ b/Tests/StripeTests/CouponTests.swift @@ -18,8 +18,7 @@ class CouponTests: XCTestCase var drop: Droplet? var couponId: String = "" - override func setUp() - { + override func setUp() { do { drop = try self.makeDroplet() @@ -40,8 +39,7 @@ class CouponTests: XCTestCase } } - func testCreateCoupon() throws - { + func testCreateCoupon() throws { let coupon = try drop?.stripe?.coupons.create(id: nil, duration: .once, amountOff: 5, @@ -54,15 +52,13 @@ class CouponTests: XCTestCase XCTAssertNotNil(coupon) } - func testRetrieveCoupon() throws - { + func testRetrieveCoupon() throws { let coupon = try drop?.stripe?.coupons.retrieve(coupon: couponId).serializedResponse() XCTAssertNotNil(coupon) } - func testUpdateCoupon() throws - { + func testUpdateCoupon() throws { let metadata = ["hello":"world"] let updatedCoupon = try drop?.stripe?.coupons.update(metadata: metadata, forCouponId: couponId).serializedResponse() @@ -71,8 +67,7 @@ class CouponTests: XCTestCase XCTAssert(updatedCoupon?.metadata?["hello"] == "world") } - func testDeleteCoupon() throws - { + func testDeleteCoupon() throws { let deletedCoupon = try drop?.stripe?.coupons.delete(coupon: couponId).serializedResponse() XCTAssertNotNil(deletedCoupon) @@ -80,8 +75,7 @@ class CouponTests: XCTestCase XCTAssertTrue(deletedCoupon?.deleted ?? false) } - func testListAllCoupons() throws - { + func testListAllCoupons() throws { let coupons = try drop?.stripe?.coupons.listAll().serializedResponse() XCTAssertNotNil(coupons) @@ -96,8 +90,7 @@ class CouponTests: XCTestCase } } - func testFilterCoupons() throws - { + func testFilterCoupons() throws { let filter = StripeFilter() filter.limit = 1 diff --git a/Tests/StripeTests/CustomerTests.swift b/Tests/StripeTests/CustomerTests.swift index 8f2759f..29d03a5 100644 --- a/Tests/StripeTests/CustomerTests.swift +++ b/Tests/StripeTests/CustomerTests.swift @@ -18,8 +18,7 @@ class CustomerTests: XCTestCase { var drop: Droplet? var customerId: String = "" - override func setUp() - { + override func setUp() { do { drop = try self.makeDroplet() @@ -38,8 +37,7 @@ class CustomerTests: XCTestCase { } } - func testCreateCustomer() throws - { + func testCreateCustomer() throws { let customer = Customer() customer.email = "test@stripetest.com" customer.description = "This is a test customer" @@ -47,14 +45,12 @@ class CustomerTests: XCTestCase { XCTAssertNotNil(object) } - func testRetrieveCustomer() throws - { + func testRetrieveCustomer() throws { let object = try drop?.stripe?.customer.retrieve(customer: customerId).serializedResponse() XCTAssertNotNil(object) } - func testUpdateCustomer() throws - { + func testUpdateCustomer() throws { let customer = Customer() customer.email = "tester@stripetest.com" customer.description = "This is a test customer updated" @@ -62,20 +58,17 @@ class CustomerTests: XCTestCase { XCTAssertNotNil(object) } - func testDeleteCustomer() throws - { + func testDeleteCustomer() throws { let object = try drop?.stripe?.customer.delete(customer: customerId).serializedResponse() XCTAssertEqual(object?.deleted, true) } - func testRetrieveAllCustomers() throws - { + func testRetrieveAllCustomers() throws { let object = try drop?.stripe?.customer.listAll().serializedResponse() XCTAssertGreaterThanOrEqual(object!.items!.count, 1) } - func testFilterCustomers() throws - { + func testFilterCustomers() throws { let filter = StripeFilter() filter.limit = 1 let object = try drop?.stripe?.customer.listAll(filter: filter).serializedResponse() diff --git a/Tests/StripeTests/RefundTests.swift b/Tests/StripeTests/RefundTests.swift index 052c075..38f8d1a 100644 --- a/Tests/StripeTests/RefundTests.swift +++ b/Tests/StripeTests/RefundTests.swift @@ -17,8 +17,7 @@ class RefundTests: XCTestCase { var drop: Droplet? var refundId: String = "" - override func setUp() - { + override func setUp() { do { drop = try self.makeDroplet() diff --git a/Tests/StripeTests/TokenTests.swift b/Tests/StripeTests/TokenTests.swift index ef0ce21..aeca7dc 100644 --- a/Tests/StripeTests/TokenTests.swift +++ b/Tests/StripeTests/TokenTests.swift @@ -17,8 +17,7 @@ class TokenTests: XCTestCase { var drop: Droplet? var tokenId: String = "" - override func setUp() - { + override func setUp() { do { drop = try self.makeDroplet() @@ -45,8 +44,7 @@ class TokenTests: XCTestCase { XCTAssertNotNil(object?.card) } - func testTokenRetrieval() throws - { + func testTokenRetrieval() throws { let object = try drop?.stripe?.tokens.retrieve(tokenId).serializedResponse() XCTAssertNotNil(object) }