Skip to content

Commit

Permalink
Release 0.3.1
Browse files Browse the repository at this point in the history
  • Loading branch information
mmroz committed Mar 27, 2023
1 parent 83b58e2 commit 4734412
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 16 deletions.
2 changes: 1 addition & 1 deletion CashAppPayKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'CashAppPayKit'
s.version = '0.3.0'
s.version = '0.3.1'
s.summary = 'PayKit iOS SDK'
s.homepage = 'https://github.com/cashapp/cash-app-pay-ios-sdk'
s.license = 'Apache License, Version 2.0'
Expand Down
2 changes: 1 addition & 1 deletion CashAppPayKitUI.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'CashAppPayKitUI'
s.version = "0.3.0"
s.version = "0.3.1"
s.summary = 'UI components for the PayKit iOS SDK'
s.homepage = 'https://github.com/cashapp/cash-app-pay-ios-sdk'
s.license = 'Apache License, Version 2.0'
Expand Down
78 changes: 73 additions & 5 deletions Demo/PayKitDemo/PayKitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ import UIKit
// swiftlint:disable file_length
class PayKitViewController: UIViewController {

private let sandboxClientID = "CAS-CI_PAYKIT_MOBILE_DEMO"
private let sandboxBrandID = "BRAND_9t4pg7c16v4lukc98bm9jxyse"

private lazy var stackView = makeStackView()

private lazy var endpointLabel = makeLabel(text: environment.title)
private lazy var endpointToggle = makeEndpointToggle()
private lazy var paymentTypeControlLabel = makeLabel(text: "Payment Type")
private lazy var paymentTypeControl = makePaymentTypeControl()

Expand All @@ -39,20 +38,26 @@ class PayKitViewController: UIViewController {
private lazy var authorizeRequestButton = makeAuthorizeRequestButton()
private lazy var statusTextView = makeStatusTextView()

var environment: Environment = .sandbox {
didSet {
updateViewState()
}
}

var pendingRequest: CustomerRequest? {
didSet {
updateViewState()
}
}

private lazy var sdk: CashAppPay = {
let sdk = CashAppPay(clientID: sandboxClientID, endpoint: .sandbox)
let sdk = CashAppPay(clientID: environment.clientID, endpoint: environment.endpoint)
sdk.addObserver(self)
return sdk
}()

private var brandID: String {
sandboxBrandID
environment.brandID
}

override func viewDidLoad() {
Expand All @@ -75,6 +80,10 @@ class PayKitViewController: UIViewController {

stackView.setCustomSpacing(20, after: accountReferenceIDTextField)

stackView.addArrangedSubview(endpointToggle)

stackView.setCustomSpacing(20, after: endpointToggle)

stackView.addArrangedSubview(createRequestButton)
stackView.addArrangedSubview(updateRequestButton)
stackView.addArrangedSubview(authorizeRequestButton)
Expand All @@ -87,6 +96,8 @@ class PayKitViewController: UIViewController {
stackView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor),
stackView.centerYAnchor.constraint(equalTo: view.readableContentGuide.centerYAnchor),

endpointToggle.widthAnchor.constraint(equalTo: stackView.widthAnchor),

paymentTypeControlLabel.widthAnchor.constraint(equalTo: stackView.widthAnchor),
paymentTypeControl.widthAnchor.constraint(equalTo: stackView.widthAnchor),

Expand All @@ -111,6 +122,7 @@ class PayKitViewController: UIViewController {
authorizeRequestButton.isEnabled = (pendingRequest != nil)
amountTextField.isEnabled = (paymentType == .ONE_TIME_PAYMENT)
accountReferenceIDTextField.isEnabled = (paymentType == .ON_FILE_PAYMENT)
endpointLabel.text = environment.title
}

// MARK: - Button Actions
Expand All @@ -128,6 +140,13 @@ class PayKitViewController: UIViewController {
guard let request = pendingRequest else { return }
sdk.authorizeCustomerRequest(request)
}

func endpointToggleChanged() {
self.environment = (environment == .sandbox) ? .staging : .sandbox
sdk.removeObserver(self)
sdk = CashAppPay(clientID: environment.clientID, endpoint: environment.endpoint)
sdk.addObserver(self)
}
}

// MARK: - Computed Properties
Expand Down Expand Up @@ -197,6 +216,15 @@ extension PayKitViewController {
return stackView
}

func makeEndpointToggle() -> UIStackView {
let toggle = UISwitch(frame: .zero, primaryAction: UIAction { [weak self] _ in
self?.endpointToggleChanged()
})
let stack = UIStackView(arrangedSubviews: [toggle, endpointLabel])
stack.spacing = 16
return stack
}

func makeCreateRequestButton() -> UIButton {
var configuration = UIButton.Configuration.filled()
configuration.buttonSize = .large
Expand Down Expand Up @@ -354,3 +382,43 @@ extension PayKitViewController: UITextFieldDelegate {
return string.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
}
}

extension PayKitViewController {
enum Environment {
private static let sandboxClientID = "CAS-CI_PAYKIT_MOBILE_DEMO"
private static let sandboxBrandID = "BRAND_9t4pg7c16v4lukc98bm9jxyse"
private static let stagingClientID = "CASH_CHECKOUT"
private static let stagingBrandID = "BRAND_4wv02dz5v4eg22b3enoffn6rt"

case sandbox
case staging

var title: String {
switch self {
case .staging: return "Staging"
case .sandbox: return "Sandbox"
}
}

var clientID: String {
switch self {
case .sandbox: return Environment.sandboxClientID
case .staging: return Environment.stagingClientID
}
}

var brandID: String {
switch self {
case .sandbox: return Environment.sandboxBrandID
case .staging: return Environment.stagingBrandID
}
}

var endpoint: CashAppPay.Endpoint {
switch self {
case .sandbox: return .sandbox
case .staging: return .staging
}
}
}
}
10 changes: 10 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## PayKit 0.3.1 Release Notes

*PayKit 0.3.1* supports *iOS* and requires *Xcode 9* or later. The minimum supported *Base SDK* is *11.0*.

*PayKit 0.3.1* includes the following new features and enhancements.

- **PayKit Demo**

The *PayKitDemo App* now includes a toggle to test in the staging environment.

## PayKit 0.3.0 Release Notes

*PayKit 0.3.0* supports *iOS* and requires *Xcode 9* or later. The minimum supported *Base SDK* is *11.0*.
Expand Down
7 changes: 4 additions & 3 deletions Sources/PayKit/CashAppPay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import UIKit

public class CashAppPay {

public static let version = "0.3.0"
public static let version = "0.3.1"

public static let RedirectNotification: Notification.Name = Notification.Name("CashAppPayRedirect")

Expand All @@ -34,10 +34,10 @@ public class CashAppPay {
EventStream2.CommonFields.platform.rawValue: "iOS",
EventStream2.CommonFields.sdkVersion.rawValue: CashAppPay.version,
EventStream2.CommonFields.clientUA.rawValue: UserAgent.userAgent,
EventStream2.CommonFields.isSandbox.rawValue: (endpoint == .sandbox),
EventStream2.CommonFields.environment.rawValue: endpoint.analyticsField,
],
store: AnalyticsDataSource(),
client: AnalyticsClient(restService: ResilientRESTService())
client: AnalyticsClient(restService: ResilientRESTService(), endpoint: endpoint.analyticsEndpoint)
)

let stateMachine = StateMachine(networkManager: networkManager, analyticsService: analytics)
Expand All @@ -52,6 +52,7 @@ public class CashAppPay {
public enum Endpoint {
case production
case sandbox
case staging
}

/// The endpoint that the requests are routed to
Expand Down
2 changes: 2 additions & 0 deletions Sources/PayKit/NetworkManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ extension CashAppPay.Endpoint {
return URL(string: "https://api.cash.app/")!
case .sandbox:
return URL(string: "https://sandbox.api.cash.app/")!
case .staging:
return URL(string: "https://api.cashstaging.app/")!
}
}
}
Expand Down
28 changes: 25 additions & 3 deletions Sources/PayKit/Services/Analytics/AnalyticsClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ class AnalyticsClient {

private let restService: RESTService

private let endpointURL = URL(string: "https://api.squareup.com/")!
private let apiPath = "2.0/log/eventstream"
private var baseURL: URL {
URL(string: apiPath, relativeTo: endpointURL)!
URL(string: apiPath, relativeTo: endpoint.baseURL)!
}

private var requestHeaders: [String: String] {
Expand All @@ -37,10 +36,15 @@ class AnalyticsClient {

private let encoder: JSONEncoder = .eventStream2Encoder()

// MARK: - Public Properties

private let endpoint: Endpoint

// MARK: - Lifecycle

init(restService: RESTService) {
init(restService: RESTService, endpoint: Endpoint) {
self.restService = restService
self.endpoint = endpoint
}

// MARK: - Public
Expand Down Expand Up @@ -82,6 +86,24 @@ class AnalyticsClient {
}
}

// MARK: - Endpoint

extension AnalyticsClient {
enum Endpoint {
case production
case staging

var baseURL: URL {
switch self {
case .production:
return URL(string: "https://api.squareup.com/")!
case .staging:
return URL(string: "https://api.squareupstaging.com/")!
}
}
}
}

// MARK: - Request Models

struct EventStream2CollectionParams: Encodable {
Expand Down
2 changes: 1 addition & 1 deletion Sources/PayKit/Services/Analytics/AnalyticsService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,6 @@ extension EventStream2 {
case platform = "platform"
case sdkVersion = "sdk_version"
case clientUA = "client_ua"
case isSandbox = "is_sandbox"
case environment = "environment"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// CashAppPayEndpoint+Analytics.swift
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

extension CashAppPay.Endpoint {
var analyticsEndpoint: AnalyticsClient.Endpoint {
switch self {
case .production, .sandbox:
return .production
case .staging:
return .staging
}
}

var analyticsField: String {
switch self {
case .production:
return "production"
case .sandbox:
return "sandbox"
case .staging:
return "staging"
}
}
}
7 changes: 6 additions & 1 deletion Tests/PayKitTests/AnalyticsClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ class AnalyticsClientTests: XCTestCase {
XCTAssertEqual(try param.event.jsonString(), try event.jsonString())
}

func test_endpoint() {
XCTAssertEqual(AnalyticsClient.Endpoint.staging.baseURL.absoluteString, "https://api.squareupstaging.com/")
XCTAssertEqual(AnalyticsClient.Endpoint.production.baseURL.absoluteString, "https://api.squareup.com/")
}

func test_request_body() {
let expectation = self.expectation(description: "Uploaded")
let mock = MockRestService { request, retry, _ in
Expand All @@ -38,7 +43,7 @@ class AnalyticsClientTests: XCTestCase {
expectation.fulfill()
}

let client = AnalyticsClient(restService: mock)
let client = AnalyticsClient(restService: mock, endpoint: .production)
client.upload(appName: "app", events: [event]) { _ in }

waitForExpectations(timeout: 0.5)
Expand Down
2 changes: 1 addition & 1 deletion Tests/PayKitTests/AnalyticsServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ private class MockAnalyticsClient: AnalyticsClient {

init(uploadStub: @escaping ((String, [AnalyticsEvent], (Result<Void, Error>) -> Void) -> Void) = { _, _, _ in }) {
self.uploadStub = uploadStub
super.init(restService: ResilientRESTService())
super.init(restService: ResilientRESTService(), endpoint: .production)
}

override func upload(
Expand Down
13 changes: 13 additions & 0 deletions Tests/PayKitTests/CashAppPay+EndpointTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,20 @@ import XCTest

class CashAppPay_EndpointTest: XCTestCase {
func test_endpoint_url() {
XCTAssertEqual(CashAppPay.Endpoint.staging.baseURL.absoluteString, "https://api.cashstaging.app/")
XCTAssertEqual(CashAppPay.Endpoint.sandbox.baseURL.absoluteString, "https://sandbox.api.cash.app/")
XCTAssertEqual(CashAppPay.Endpoint.production.baseURL.absoluteString, "https://api.cash.app/")
}

func test_endpoint_analytics_endpoint() {
XCTAssertEqual(CashAppPay.Endpoint.staging.analyticsEndpoint, .staging)
XCTAssertEqual(CashAppPay.Endpoint.production.analyticsEndpoint, .production)
XCTAssertEqual(CashAppPay.Endpoint.sandbox.analyticsEndpoint, .production)
}

func test_analytics_field() {
XCTAssertEqual(CashAppPay.Endpoint.staging.analyticsField, "staging")
XCTAssertEqual(CashAppPay.Endpoint.production.analyticsField, "production")
XCTAssertEqual(CashAppPay.Endpoint.sandbox.analyticsField, "sandbox")
}
}

0 comments on commit 4734412

Please sign in to comment.