Skip to content

Commit

Permalink
Vault with Purchase PayPalWeb (#221)
Browse files Browse the repository at this point in the history
* vault with purchase create order PayPal

* remove unnecessary decoding of links field

* remove customerID entry for PP vault with purchase

* add initializer with default nil for customer

* change Customer to Codable for reuse for Vault customer decoding

* Add comments that required experienceContext for PayPal vault option in order create not used in SDK

* Jax, Sammy PR feedback
  • Loading branch information
KunJeongPark authored Nov 30, 2023
1 parent 29307de commit ae1adc3
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 18 deletions.
54 changes: 47 additions & 7 deletions Demo/Demo/Models/CreateOrderParams.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ struct CreateOrderParams: Encodable {
let applicationContext: ApplicationContext?
let intent: String
var purchaseUnits: [PurchaseUnit]?
var paymentSource: VaultCardPaymentSource?
var paymentSource: VaultPaymentSource?
}

struct ApplicationContext: Codable {
Expand All @@ -17,6 +17,39 @@ struct ApplicationContext: Codable {
}
}

enum VaultPaymentSource: Encodable {
case card(VaultCardPaymentSource)
case paypal(VaultPayPalPaymentSource)

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .card(let cardSource):
try container.encode(cardSource)
case .paypal(let paypalSource):
try container.encode(paypalSource)
}
}
}

struct VaultPayPalPaymentSource: Encodable {

let paypal: VaultPayPal
}

struct VaultPayPal: Encodable {

let attributes: Attributes
let experienceContext: ExperienceContext
}

struct ExperienceContext: Encodable {

// these fields are not encoded for our SDK but are required for create order with PayPal vault option
let returnURL: String
let cancelURL: String
}

struct VaultCardPaymentSource: Encodable {

let card: VaultCard
Expand All @@ -30,20 +63,27 @@ struct VaultCard: Encodable {
struct Attributes: Encodable {

let vault: Vault
let customer: CardVaultCustomer?
let customer: Customer?

init(vault: Vault, customer: Customer? = nil) {
self.vault = vault
self.customer = customer
}
}

struct Vault: Encodable {

let storeInVault: String
}

struct CardVaultCustomer: Encodable {
let usageType: String?
let customerType: String?

let id: String
init(storeInVault: String, usageType: String? = nil, customerType: String? = nil) {
self.storeInVault = storeInVault
self.usageType = usageType
self.customerType = customerType
}
}


struct PurchaseUnit: Encodable {

var shipping: Shipping?
Expand Down
5 changes: 3 additions & 2 deletions Demo/Demo/Models/Order.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ struct Order: Codable, Equatable {
let id: String
let status: String
var paymentSource: PaymentSource?

struct PaymentSource: Codable, Equatable {

let card: Card?
Expand All @@ -25,7 +25,8 @@ struct Order: Codable, Equatable {

struct PayPal: Codable, Equatable {

let emailAddress: String
let emailAddress: String?
let attributes: Attributes?
}

struct Attributes: Codable, Equatable {
Expand Down
4 changes: 2 additions & 2 deletions Demo/Demo/Models/PaymentTokenResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ struct PaymentTokenResponse: Decodable, Equatable {
let paymentSource: PaymentSource
}

struct Customer: Decodable, Equatable {
struct Customer: Codable, Equatable {

let id: String
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ struct CreateOrderPayPalWebView: View {
@ObservedObject var paypalWebViewModel: PayPalWebViewModel

@State private var selectedIntent: Intent = .authorize
@State var shouldVaultSelected = false

let selectedMerchantIntegration: MerchantIntegration

Expand All @@ -22,6 +23,10 @@ struct CreateOrderPayPalWebView: View {
Text("CAPTURE").tag(Intent.capture)
}
.pickerStyle(SegmentedPickerStyle())
HStack {
Toggle("Should Vault with Purchase", isOn: $shouldVaultSelected)
Spacer()
}
ZStack {
Button("Create an Order") {
Task {
Expand All @@ -30,7 +35,9 @@ struct CreateOrderPayPalWebView: View {
try await paypalWebViewModel.createOrder(
amount: "10.00",
selectedMerchantIntegration: DemoSettings.merchantIntegration,
intent: selectedIntent.rawValue)
intent: selectedIntent.rawValue,
shouldVault: shouldVaultSelected
)
} catch {
print("Error in getting setup token. \(error.localizedDescription)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ struct PayPalWebOrderCompletionResultView: View {
LeadingText("Email", weight: .bold)
LeadingText("\(email)")
}
if let vaultID = orderResponse.paymentSource?.paypal?.attributes?.vault.id {
LeadingText("Vault ID / Payment Token", weight: .bold)
LeadingText("\(vaultID)")
}
if let customerID = orderResponse.paymentSource?.paypal?.attributes?.vault.customer.id {
LeadingText("Customer ID", weight: .bold)
LeadingText("\(customerID)")
}
Text("")
.id("bottomView")
}
Expand Down
13 changes: 9 additions & 4 deletions Demo/Demo/ViewModels/CardPaymentViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,20 @@ class CardPaymentViewModel: ObservableObject, CardDelegate {
let amountRequest = Amount(currencyCode: "USD", value: amount)
// TODO: might need to pass in payee as payee object or as auth header

var vaultPaymentSource: VaultCardPaymentSource?
var vaultCardPaymentSource: VaultCardPaymentSource?
if shouldVault {
var customer: CardVaultCustomer?
var customer: Customer?
if let customerID {
customer = CardVaultCustomer(id: customerID)
customer = Customer(id: customerID)
}
let attributes = Attributes(vault: Vault(storeInVault: "ON_SUCCESS"), customer: customer)
let card = VaultCard(attributes: attributes)
vaultPaymentSource = VaultCardPaymentSource(card: card)
vaultCardPaymentSource = VaultCardPaymentSource(card: card)
}

var vaultPaymentSource: VaultPaymentSource?
if let vaultCardPaymentSource {
vaultPaymentSource = .card(vaultCardPaymentSource)
}

let orderRequestParams = CreateOrderParams(
Expand Down
24 changes: 22 additions & 2 deletions Demo/Demo/ViewModels/PayPalWebViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,35 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate {

let configManager = CoreConfigManager(domain: "PayPalWeb Payments")

func createOrder(amount: String, selectedMerchantIntegration: MerchantIntegration, intent: String) async throws {
func createOrder(
amount: String,
selectedMerchantIntegration: MerchantIntegration,
intent: String,
shouldVault: Bool
) async throws {
// might need to pass in payee as payee object or as auth header

let amountRequest = Amount(currencyCode: "USD", value: amount)
// TODO: might need to pass in payee as payee object or as auth header

var vaultPayPalPaymentSource: VaultPayPalPaymentSource?
if shouldVault {
let attributes = Attributes(vault: Vault(storeInVault: "ON_SUCCESS", usageType: "MERCHANT", customerType: "CONSUMER"))
// The returnURL is not used in our mobile SDK, but a required field for create order with PayPal payment source. DTPPCPSDK-1492 to track this issue
let paypal = VaultPayPal(attributes: attributes, experienceContext: ExperienceContext(returnURL: "https://example.com/returnUrl", cancelURL: "https://example.com/cancelUrl"))
vaultPayPalPaymentSource = VaultPayPalPaymentSource(paypal: paypal)
}

var vaultPaymentSource: VaultPaymentSource?
if let vaultPayPalPaymentSource {
vaultPaymentSource = .paypal(vaultPayPalPaymentSource)
}

let orderRequestParams = CreateOrderParams(
applicationContext: nil,
intent: intent,
purchaseUnits: [PurchaseUnit(amount: amountRequest)]
purchaseUnits: [PurchaseUnit(amount: amountRequest)],
paymentSource: vaultPaymentSource
)

do {
Expand Down

0 comments on commit ae1adc3

Please sign in to comment.