# Mobile Integration Story (Server Side Order Creation)
These stories outline the mobile integration experience and what the customer journey will look like. These stories assume that the order will be created on the merchant server. An [example code snippet](##Snippet-E) is provided to showcase the client side order creation integration.
- [How it Works](##How-it-Works)
- [Initial Setup](##Setup)
- [Card Integration](##Card-Integration)
- [PayPal Integration](##PayPal-Integration)
- [Venmo Integration](##Venmo-Integration)
- [Button Integrations](##Button-Integrations)
- [Vault with Purchase](##Vault-with-Purchase)
## How it Works

New integration flow: ***In review***

## Setup
#### Add the Payments SDK to your app (All Modules)
##### Swift Package Manager
In Xcode, add the [package dependency](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app) and enter https://github.com/paypal/iOS-SDK as the repository URL. Tick the checkboxes for the specific PayPal libraries you wish to include.
In your app's source code files, use the following import syntax to include PayPal's Card, Venmo and PayPal libraries:
```swift
import Card // Card module (includes 3DS)
import PayPal // PayPal module
import Venmo // Venmo module
```
##### CocoaPods
Include the PayPal pod in your `Podfile`.
```ruby
pod 'PayPal'
```
In your app's source code files, use the following import syntax to include PayPal's Card, Venmo and PayPal libraries:
```swift
import Card // Card module
import PayPal // PayPal module
import Venmo // Venmo module
```
## Card Integration
#### Merchant/Client Journey (with 3DS challenge)
1. Customer: Checking out in the merchant's app
1. Merchant: Call `SDK Eligibility` method to determine if credit card processing is available [[See Code]](###Snippet-A)
1. Merchant: Renders card input UI
1. Customer: types in card PAN, expiry date, billing address, CVV etc. and taps submit
1. Merchant: Call `SDK approveOrder` on `SDK Card` module using the data input by the customer [[See Code]](###Snippet-B)
1. `SDK sets the payment source using the data passed in`
1. `API response indicates that a 3DS challenge is required`
1. An `In App Browser` is displayed in the merchant app by the SDK
1. Customer: Authenticates the challenge and the `In App Browser` is dismissed and the control is returned to the merchant app
1. Merchant: Receives order in APPROVED state via SDK
#### Merchant/Client Journey (no 3DS challenge)
1. Customer: Checking out in the merchant's app
1. Merchant: Call `SDK Eligibility` method to determine if credit card processing is available [[See Code]](###Snippet-A)
1. Merchant: Renders card input UI
1. Customer: types in card PAN, expiry date, billing address, CVV etc. and taps submit
1. Merchant: Call `SDK approveOrder` on `SDK Card` module using the data input by the customer [[See Code]](###Snippet-B)
1. `SDK sets the payment source using the data passed in`
1. `API response indicates NO 3DS challenge is required`
1. Merchant: Receives order in APPROVED state via SDK
## PayPal Integration
#### Merchant/Client Journey
1. Customer: Checking out in the merchant's app
1. Merchant: Call `SDK Eligibility` method to determine if PayPal processing is available [[See Code]](###Snippet-A)
1. Merchant: Renders PayPal button
1. Customer: Taps PayPal button
1. Merchant: Call `SDK approveOrder` on `SDK PayPal` module passing in all relevant params [[See Code]](###Snippet-C)
1. `SDK sets the payment source using the data passed in`
1. `API response contains URL for approval`
1. An `In App Browser` is displayed in the merchant app by the SDK showing the approval URL
1. Customer: Authenticates the PayPal payment and the `In App Browser` is dismissed and the control is returned to the merchant app
1. Merchant: Receives order in APPROVED state via SDK
## Venmo Integration
#### Merchant/Client Journey
1. Customer: Checking out in the merchant's app
1. Merchant: Call `SDK Eligibility` method to determine if Venmo processing is available and that the Venmo app is installed [[See Code]](###Snippet-A)
1. Merchant: Renders Venmo button
1. Customer: Taps Venmo button
1. Merchant: Call `SDK approveOrder` on `SDK Venmo` module passing in all relevant params [[See Code]](###Snippet-D)
1. `SDK sets the payment source using the data passed in`
1. `API response contains order information`
1. The SDK composes the Universal Link URL with all required params that will open the Venmo app and `invokes the app switch`
1. Customer: Is switched to the Venmo app for authorization/approval
1. Customer: Approves in the Venmo app and is returned to the merchant app
1. `SDK does a GET on the Order`
1. Merchant: Receives order in APPROVED state via SDK
# Code Snippets
### Snippet A
Check eligibility for current and future payment methods:
```swift=
// Setup config
let config = CoreConfig(clientID: "<CLIENT_ID>", environment: .sandbox)
let apiClient = APIClient(config: config)
// Merchant calls eligibility API
apiClient.checkEligibility { result in
switch result {
case .success(let result):
// `result.eligibility.acdc`
// `result.eligibility.venmo`
// `result.eligibility.paypal`
// `result.eligibility.applepay`
// `result.eligibility.googlepay`
// `result.eligibility.sepa`
// `result.eligibility.ach`
case .failure(let error):
// handle the error by accessing `result.localizedDescription`
}
}
```
### Snippet B
Card integration.
```swift=
class MyViewController: ASWebAuthenticationPresentationContextProviding, CardDelegate {
...
func checkoutWithCard() {
let config = CoreConfig(clientID: "<CLIENT_ID>", environment: .sandbox)
let apiClient = APIClient(config: config)
let cardClient = CardClient(apiClient: apiClient)
// This data comes from the merchant UI
let card = Card(
number: "4111111111111111",
expirationMonth: "01",
expirationYear: "25",
securityCode: "123",
cardholderName: "Jane Smith",
billingAddress: Address(
addressLine1: "123 Main St.",
addressLine2: "Apt. 1A",
locality: "city",
region: "IL",
postalCode: "12345",
countryCode: "US"
)
)
let cardRequest = CardRequest(card: card)
cardClient.delegate = self
cardClient.approveOrder(cardRequest: cardRequest, orderId: "<ORDER_ID_FROM_SERVER>")
}
func cardClient(_ cardClient: CardClient, didFinishWithResult result: CardResult) {
// Order was APPROVED: `result.order.id`
}
func cardClient(_ cardClient: CardClient, didFinishWithError error: CoreSDKError) {
// handle the error by accessing `error.localizedDescription`
}
func cardClientDidCancel(_ cardClient: CardClient) {
// the user canceled
}
func cardClientWillPresentChallenge(_ cardClient: CardClient) {
// In App Browser is about to be shown
}
func cardClientChallengeDismissed(_ cardClient: CardClient) {
// In App Browser dismissed
}
// Required OS method to display In App Browser
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
UIApplication
.shared
.connectedScenes
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
.first { $0.isKeyWindow }
?? ASPresentationAnchor()
}
}
```
### Snippet C
PayPal integration.
```swift=
class MyViewController: ASWebAuthenticationPresentationContextProviding, PayPalWebCheckoutDelegate {
...
func checkoutWithPayPal() {
let config = CoreConfig(clientID: "<CLIENT_ID>", environment: .sandbox)
let apiClient = APIClient(config: config)
let payPalClient = PayPalWebCheckoutClient(apiClient: apiClient)
let payPalRequest = PayPalWebCheckoutRequest()
payPalClient.delegate = self
payPalClient.approveOrder(payPalRequest: payPalRequest, orderId: "<ORDER_ID_FROM_SERVER>")
}
func payPal(_ payPalClient: PayPalWebCheckoutClient, didFinishWithResult result: PayPalWebCheckoutResult) {
// Order was APPROVED: `result.order.id`
}
func payPal(_ payPalClient: PayPalWebCheckoutClient, didFinishWithError error: CoreSDKError) {
// handle the error by accessing `error.localizedDescription`
}
func payPalDidCancel(_ payPalClient: PayPalWebCheckoutClient) {
// the user canceled
}
func payPalClientWillPresentAuthentication(_ payPalClient: PayPalWebCheckoutClient) {
// In App Browser is about to be shown
}
func payPalClientAuthenticationDismissed(_ payPalClient: PayPalWebCheckoutClient) {
// In App Browser dismissed
}
// Required OS method to display In App Browser
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
UIApplication
.shared
.connectedScenes
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
.first { $0.isKeyWindow }
?? ASPresentationAnchor()
}
}
```
### Snippet D
Venmo integration.
```swift=
class MyViewController: ASWebAuthenticationPresentationContextProviding, VenmoDelegate {
...
func checkoutWithVenmo() {
let config = CoreConfig(clientID: "<CLIENT_ID>", environment: .sandbox)
let apiClient = APIClient(config: config)
let venmoClient = VenmoClient(apiClient: apiClient)
let venmoRequest = VenmoRequest()
venmoRequest.requireBillingAddress = true
venmoClient.delegate = self
venmoClient.approveOrder(venmoRequest: venmoRequest, orderId: "<ORDER_ID_FROM_SERVER>")
}
func venmoClient(_ venmoClient: VenmoClient, didFinishWithResult result: VenmoResult) {
// Order was APPROVED: `result.order.id`
}
func venmoClient(_ venmoClient: VenmoClient, didFinishWithError error: CoreSDKError) {
// handle the error by accessing `error.localizedDescription`
}
func venmoClientDidCancel(_ venmoClient: VenmoClient) {
// the user canceled
}
func venmoClientWillAppSwitch(_ venmoClient: VenmoClient) {
// Customer is about to be app switched to the Venmo app
}
func venmoClientAppSwitchReturned(_ venmoClient: VenmoClient) {
// Customer returned from app switch
}
}
```
### Snippet E
Example Venmo integration setup when order is created on the client rather than the server.
***NOTE: This integration pattern for client side order creation applies to all current and future payment methods: Venmo, Card, PayPal...***
```swift=
func checkoutWithVenmo() {
let config = CoreConfig(clientID: "<CLIENT_ID>", environment: .sandbox)
let apiClient = APIClient(config: config)
let venmoClient = VenmoClient(apiClient: apiClient)
let venmoRequest = VenmoRequest()
venmoRequest.requireBillingAddress = true
let orderRequest = OrderRequest()
var purchaseUnit = PurchaseUnit()
orderRequest.intent = .capture
orderRequest.purchaseUnits = [purchaseUnit]
orderRequest.amount = "20.99"
venmoClient.delegate = self
venmoClient.createAndApproveOrder(venmoRequest: venmoRequest, orderRequest: orderRequest)
}
```
## Button Integrations
Each payment module will include an optional and customizable button.
```swift=
// PayPalButton will be a UI button in the PayPal module
lazy var payPalButton: PayPalButton = {
let payPalButton = PayPalButton(...)
payPalButton.addTarget(self, action: #selector(paypalButtonTapped), for: .touchUpInside)
return payPalButton
}()
@objc func paypalButtonTapped() {
// Merchant starts the PayPal flow here...
}
```
## Vault with Purchase
By using the Orders V2 API, the Native SDK can provide the merchant with vaulting capabilities during a purchase for Cards and PayPal Wallet
### Vault with Purchase Flow
The flow for each of the payment methods is similar. The OrdersAPI v2 allows PayPal Wallet, Cards and Venmo to vault any of these payment methods with a purchase. Look at the changes in the payment_source section of this Create Order request for each payment method:
#### Cards
Request Sequence:
***payment_source.card.attributes.vault***
`"confirm_payment_token":"ON_ORDER_COMPLETION"`: Defines that the payer's payment-source should be vaulted only when at least one payment (authorization/capture) using that payment-source is successful.
```json=
curl -v -k -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders/' \
-H 'PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a' \
-H 'Authorization: Bearer 6V7rbVwmlM1gFZKW_8QtzWXqpcwQ6T5vhEGYNJDAAdn3paCgRpdeMdVYmWzgbKSsECednupJ3Zx5Xd-g' \
-H 'Content-Type: application/json' \
-d '{
"intent": "AUTHORIZE",
"purchase_units": [
{
"reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
"amount": {
"currency_code": "USD",
"value": "100.00"
}
}
],
"payment_source": {
"card": {
"number": "4111111111111111",
"expiry": "2020-02",
"name": "John Doe",
"billing_address": {
"address_line_1": "2211 N First Street",
"address_line_2": "17.3.160",
"admin_area_1": "CA",
"admin_area_2": "San Jose",
"postal_code": "95131",
"country_code": "US"
},
"attributes": {
"customer": {
"id": "wxj1234"
},
"vault": {
"confirm_payment_token": "ON_ORDER_COMPLETION"
}
}
}
}
}'
```
#### PayPal
Request Sequence:
***payment_source.card.attributes.vault***
`"confirm_payment_token":"ON_ORDER_COMPLETION"`: Defines that the payer's payment-source should be vaulted only when at least one payment (authorization/capture) using that payment-source is successful.
```json=
curl -v -k -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders/id/authorize' \
-H 'PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a' \
-H 'Authorization: Bearer 6V7rbVwmlM1gFZKW_8QtzWXqpcwQ6T5vhEGYNJDAAdn3paCgRpdeMdVYmWzgbKSsECednupJ3Zx5Xd-g' \
-H 'Content-Type: application/json' \
-d '{
"intent": "AUTHORIZE",
"purchase_units": [
{
"reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
"amount": {
"currency_code": "USD",
"value": "100.00"
}
}
],
"payment_source": {
"paypal": {
"attributes": {
"customer": {
"id": "wxj1234"
},
"vault": {
"confirm_payment_token": "ON_ORDER_COMPLETION",
"usage_type": "PLATFORM"
}
}
}
}
}'
```
#### Venmo
Request Sequence:
***payment_source.card.attributes.vault***
`"confirm_payment_token":"ON_ORDER_COMPLETION"`: Defines that the payer's payment-source should be vaulted only when at least one payment (authorization/capture) using that payment-source is successful.
`"usage_type":"MERCHANT"`: TBC: *Defines that the merchant performing the vaulting*
```javascript=
curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer Access-Token" \
-d '{
"intent": "CAPTURE",
"purchase_units": [
{
"amount": {
"currency_code": "USD",
"value": "100.00"
}
}
],
"payment_source": {
"venmo": {
"email_address": "customer@example.com",
"experience_context": {
"shipping_preference": "SET_PROVIDED_ADDRESS",
"brand_name":"EXAMPLE INC"
},
"attributes": {
"customer": {
"id": "wxj1234"
},
//The vault parameter is added to allow vaulting with a purchase
"vault": {
"store_in_vault": "ON_ORDER_COMPLETION",
"usage_type": "MERCHANT"
}
}
}
}
}'
```
## Retrieve a Vaulted Payment Method
Now that a payment method has been vaulted via the Orders API, a merchant can retrieve a customer's vaulted payment method(s) by using the Vault API.
Retrieving vaulted payment methods via the customer ID returns all the payment methods that the specified `customerID` have vaulted in the past. This allows the merchant-developer to retrieve them and be able provide the buyer with a better experience at checkout.
### Vault Retrieval Request
```json=
curl -v -k -X GET 'https://msmaster.qa.paypal.com:18582/v3/vault/payment-tokens?customer_id=customer_4029352050' \
-H 'Authorization: Bearer FULL_scoped_access_token' \
-H 'Content-Type: application/json'
```
### Vault Retrieval Response
```json=
//Response
HTTP status code: 200
HTTP Headers:
"Content-Type": "application/json"
Response payload:
{
"customer_id": "customer_4029352050",
"payment_tokens": [
{
"id": "8kk845",
"status": "CREATED",
"source": {
"card": {
"brand": "VISA",
"last_digits": "1111",
"verification_status": "NOT_VERIFIED"
}
},
"links": [
{
"rel": "self",
"href": "https://api-m.paypal.com/v2/vault/payment-tokens/8kk845",
"method": "GET"
},
{
"rel": "delete",
"href": "https://api-m.paypal.com/v2/vault/payment-tokens/8kk845",
"method": "DELETE"
}
]
},
{
"id": "6km842",
"status": "CREATED",
"source": {
"card": {
"brand": "VISA",
"last_digits": "1234",
"verification_status": "NOT_VERIFIED"
}
},
"links": [
{
"rel": "self",
"href": "https://api-m.paypal.com/v2/vault/payment-tokens/6km842",
"method": "GET"
},
{
"rel": "delete",
"href": "https://api-m.paypal.com/v2/vault/payment-tokens/6km842",
"method": "DELETE"
}
]
}
],
"links": [
{
"rel": "self",
"href": "https://api-m.paypal.com/v2/vault/payment-tokens?customer_id=customer_4029352050&page=1&page_size=5&total_required=false",
"method": "GET"
},
{
"rel": "first",
"href": "https://api-m.paypal.com/v2/vault/payment-tokens?customer_id=customer_4029352050&page=1&page_size=5&total_required=false",
"method": "GET"
},
{
"rel": "last",
"href": "https://api-m.paypal.com/v2/vault/payment-tokens?customer_id=customer_4029352050&page=1&page_size=5&total_required=false",
"method": "GET"
}
]
}
```
## Future Integration Offerings
From the building blocks of the various payment modules, larger orchestrations can be offered:
* Smart Payment Button UI
* Card Forms
* Payment Sheets
## Appendix