owned this note
owned this note
Published
Linked with GitHub
# Hello Orders API!!
# Prerequisites
- Create PayPal Developer account at: https://developer.paypal.com
- Create a test application at: https://developer.paypal.com/developer/applications/
---
# Setup
We need an access token in order to use Orders API:
```
POST v1/oauth2/token
```
### Info needed to be collected from merchants:
- Client ID at minimum
- Client secret (if not provided, the token we get with `v1/oauth2/token` will have limited scopes)
**Note:** Requirement for full-scoped/low-scoped access token for each endpoints is documented below in [General order actions](https://hackmd.io/oo00FrwyQEe3aT4NI8WcuA?both#General-order-actions)
---
# General order actions
## 1. Create order
```
POST v2/checkout/orders
```
**Note:**
- If we create an order with `payment_method`, we need to provide `PayPal-Request-Id` in the request's header.
- When creating an order, order's `status` will be `CREATED`. In order to approve an order (change `status` to `APPROVED`), we can:
- Either let the buyer go thru order's review page (web) at `approve` link in create order response (Note: haven't been able to test this, clicking Continue/PayNow redirects back to review page, and order's `status` is still `CREATED` => need to ask/retest)
- Or call `confirm-payment-source` endpoint to approve the payment method for an order.
- Or, for PayPal flow, go thru PayPalCheckout SDK.
- If we create a general order (no payment method), `status` will be `CREATED`. But if we create an order with a `card` payment method, the order will be captured immediately, and `status` will be `COMPLETED` in create order response.
- Can be done with low-scoped access token.
## 2. Get order's info
```
GET v2/checkout/orders/<order_id>
```
**Note:**
- Need full-scoped access token.
## 3. Validate a payment method for an oder
```
POST v2/checkout/orders/<order_id>/validate-payment-method
```
**Note:**
- If the payment source is valid, calling this endpoint will attach the `payment_source` to the order.
- Can be done with low-scoped access token.
## 4. Confirm/approve an order with a payment method
```
POST v2/checkout/orders/<order_id>/confirm-payment-source
```
**Note:**
- If the payment source is valid, calling this endpoint will attach the `payment_source` to the order and approve the order (`status` -> `APPROVED`).
- Need full-scoped access token.
## 5. Authorize an order
```
POST v2/checkout/orders/<order_id>/authorize
```
**Note:**
- An order needs to be created with `intent: AUTHORIZE`
- An order needs to have a payment source attached before authorizing
- Merchants need to capture an authorized order later on.
- Need full-scoped access token.
## 6. Capture an order
```
POST v2/checkout/orders/<order_id>/capture
```
**Note:**
- An order needs to be created with `intent: CAPTURE`
- An order needs to have a payment source attached before capturing
- Need full-scoped access token.
---
# Payment methods
## 1. PayPal
### Prerequisites
- Create PayPal buyer test accounts at: https://developer.paypal.com/developer/accounts/
### Flow
1. Create order: `v2/checkout/orders` with no `payment_source`
2. Approve order: Kick buyer to review page and let them approve the order by routing buyer to the approve link in create order response / OR using PayPalCheckout SDK
3. Authorize or capture: `v2/checkout/orders/<order_id>/authorize` or `v2/checkout/orders/<order_id>/capture`
## 2. Unbranded card
### Prerequisites
- In order to process unbranded card, onboard your PayPal developer account for advanced card payment processing (process is immediate for sandbox) at: https://developer.paypal.com/docs/business/checkout/advanced-card-payments/#1-enable-your-account
- Create a sandbox application with type **Platform** at: https://developer.paypal.com/developer/applications/create
### Flow
#### Option 1: Create and authorize/capture card order immediately
1. Create order: `v2/checkout/orders` with `payment_source` being `card`.
2. If there's no special property in create order request's body that requires buyer's approval/action (eg. 3DS?, anything else? need to look into this more!!!), the order will be created and captured immediately (`status: COMPLETED`)
#### Option 2: Create + validate/confirm + authorize/capture
1. Create order: `v2/checkout/orders` with no `payment_source`
2. Attach card payment source to order by:
- 2a. Validate card: `validate-payment-method` with `payment_source` being `card` after buyer enters card info
- 2b. OR Confirm/approve order: `confirm-payment-source` with buyer's card info
3. Authorize or capture: `v2/checkout/orders/<order_id>/authorize` or `v2/checkout/orders/<order_id>/capture`
#### Option 3: Create + authorize/capture
1. Create order: `v2/checkout/orders` with no `payment_source`
2. Authorize or capture: `v2/checkout/orders/<order_id>/authorize` or `v2/checkout/orders/<order_id>/capture` with `payment_source` being `card`.
## 3. (iOS only) Apple Pay
### Prerequisites (TBD):
We need to have a merchant onboarding process for Apple Pay similar to [Braintree ApplePay setup](https://developer.paypal.com/braintree/docs/guides/apple-pay/configuration), in which step 3 + 4 + 5 haven't been built from PayPal side.
But the process underneath should look like this for each merchant:
1. We (our keymaker team) need to create a new ECC P256 keypair with name `applepay_payment_processing_<merchant_identifier>_15156_ecc_keypair` and provide merchant with a certificate signing request (CSR) - similar to step 3 in Braintree process.
2. Merchant use this CSR to create their Apple payment processing certificate in Apple site - step 4.
3. Merchant then upload this certificate to us, then keymaker team will grant the key to `cryptoserv` - step 5.
**Note:**
- `<merchant_identifier>` above can be anything that makes sense (merchant's Apple merchant id, or PayPal clientId, etc.). As long as our SDK pass correct field `partner: <merchant_identifier>` in the apple pay token JSON (more info below) that we send to Orders API, `cryptoserv` will find certificate based on this `partner` field and be able to decrypt apple payment token correctly.
### Flow (WIP):
1. Integrate with Apple Pay in our SDK. Reference: https://developer.apple.com/documentation/passkit/apple_pay
2. Inside `PKPaymentAuthorizationViewControllerDelegate`'s function `paymentAuthorizationViewController(_: didAuthorizePayment:, handler:)`, we should be able to get Apple `payment: PKPayment` after buyer approve payment in Apple Paysheet. The `payment.token` contains encrypted buyer's payment method.
3. Convert `payment.token.paymentData` to `base64EncodedString`:
```
let paymentDataDictionary: [AnyHashable: Any]? = try? JSONSerialization.jsonObject(with: payment.token.paymentData, options: .mutableContainers) as! [AnyHashable: Any]
let appleTokenDictionary: [AnyHashable: Any] = [
"partner": <merchant_identifier> // This can be clientId. We need this since cryptoserv will fetch certificate based on this partner field in order to decrypt correctly
"paymentData": paymentDataDictionary
]
let appleTokenEncoded = appleTokenDictionary.base64EncodedString()
```
5. The rest should follow similarly to the 3 unbranded card's flows above using this `payment_source`:
```
"payment_source" {
"apple_pay": {
"token": appleTokenEncoded
}
}
```
**Note:**
- `token` is the only required field for `payment_source` being `apple_pay`, but other optional fields can all be constructed from other properties found in the `PKPayment` we receive in step 2 (if provided by buyer or required by merchant):
```
"id": payment.token.transactionIdentifier
"name": payment.billingContact.name.givenName + payment.billingContact.name.familyName
"email_address": payment.billingContact.emailAddress
"phone_number": {
"national_number": payment.billingContact.phoneNumber.stringValue
}
"shipping": {
"name": {
"given_name": payment.shippingContact.givenName
"surname": payment.shippingContact.familyName
},
"email_address": payment.shippingContact.emailAddress,
"phone_number": {
"national_number": payment.shippingContact.phoneNumber.stringValue
},
"address": {
"address_line_1": payment.shippingContact.postalAddress.street
"admin_area_2": payment.shippingContact.postalAddress.city
"admin_area_1": payment.shippingContact.postalAddress.state
"postal_code": payment.shippingContact.postalAddress.postalCode
"country_code": payment.shippingContact.postalAddress.countryCode
}
}
"card": {
"name": payment.billingContact.name.givenName + payment.billingContact.name.familyName
"brand": payment.token.paymentMethod.network.rawValue.uppercased()
"type": payment.token.paymentMethod.type // this is an Int enum, we need string value and make it uppercase
"billing_address": // similar to "shipping.address" above but use payment.billingContact.postalAddress
}
```
*Note:* Apple Pay is WIP, will need to test and update Postman collection once merchant onboarding is sorted out.
---
# Postman collection
https://www.getpostman.com/collections/82f6b22651ca629aff26
# API Reference
https://ppaas/api/3719176155270030#apiReference