# Northstar Native SDK Client Spec ## BT SDK Card Client - initized with an API client - Two top level functions ```objectivec= - (void)tokenizeCard:(BTCard *)card completion:(void (^)(BTCardNonce *tokenizedCard, NSError *error))completion ``` - params: card object and completion - flow: - merchant uses SDK to create a nonce of the input card - merchant passes nonce to their server, which creates and executes the transcation ```objectivec= - (void)tokenizeCard:(BTCardRequest *)request options:(NSDictionary *)options completion:(void (^)(BTCardNonce * _Nullable, NSError * _Nullable))completionBlock ``` - params: card request and completion - internally invoked by the other `tokenizeCard` function ## Northstar implementation ### Example integration ```kotlin= // Create a CardClient instance val cardClient = CardClient(config) // Create an OrderRequest and Card val orderRequest = OrderRequest( purchaseUnitList = listOf( PurchaseUnit( amount = Amount( currencyCode = CurrencyCode.USD, value = "10.00" ) ) ) ) val card = Card(number = "4032036247327321", expiry = "2024-11") // Execute order cardClient.executeOrder(orderRequest, card) { result -> when(result) { is Success -> { // Transaction was executed } is Failure -> { // Error executing transaction } } } ``` ### 1. Create CardClient ```swift= CardClient(_ config:) { // Use dependency injection to satisfy dependencies // instead of exposing them publicly through the constructor // This is something we can add later on iOS if we want to first // getthings working before exploring DI solutions self.apiClient = Resolver.resolve() } ``` The config object passed in here should live in Core and contain all the shared parameters that a merchant would need to give the SDK in order to perform its operations. Some values that should live in this config: - ClientID - Environment - Access token? - others? ### 2a. Execute transaction passing in an OrderRequest - To consume card transaction with no card validation and an order request object: - https://developer.paypal.com/docs/api/orders/v2/#orders_create - Order is created, and immediately executed. The intent is required to be `CAPTURE`, and the status of the order after creation will be `COMPLETED` - API Doc Reference: https://hackmd.io/oo00FrwyQEe3aT4NI8WcuA?view#Option-1-Create-and-authorizecapture-card-order-immediately ```swift= client.executeOrder(order: OrderRequest, card: Card) { result in // POST to /v2/checkout/orders/ // request body contains: { "purchase_units": [ <Purchase_Unit Definition> https://developer.paypal.com/docs/api/orders/v2/#definition-purchase_unit_request ], "payment_source":{ "card":{ "number":"4032036247327321", "expiry":"2024-12" } } } // response <https://developer.paypal.com/docs/api/orders/v2/#orders-create-response>: - Order Response object - Order ID - Intent (always CAPTURE) - purchase_units - status (always COMPLETED) - Other response params found here: https://ppaas/api/3719176155270030?tab=apiReference&operation_id=post-_v2_checkout_orders // vend result to merchant through completion handler switch result { case .success(let orderResponse): orderResponse.orderID orderResponse.intent orderResponse.purchaseUnits orderResponse.status orderResponse. ? case .failure(let error): // transaction failed - human readable error information } } ``` ### 2b. Execute transaction passing in an OrderID - Executes a transaction given an order ID and a Card object - API Doc Reference: https://hackmd.io/oo00FrwyQEe3aT4NI8WcuA?view#Option-3-Create--authorizecapture ```swift= client.executeOrder(orderID: String, card: Card) { result in // POST to either: `v2/checkout/orders/<order_id>/authorize` `v2/checkout/orders/<order_id>/capture` // request: { "payment_source":{ "card":{ "number":"4032036247327321", "expiry":"2024-12" } } } // response: - Order Response object - Order ID - Intent (always CAPTURE) - purchase_units - status (always COMPLETED) - Other response params found here: https://ppaas/api/3719176155270030?tab=apiReference&operation_id=post-_v2_checkout_orders // vend result to the merchant switch result { case .success(let orderResponse): orderResponse.orderID orderResponse.intent orderResponse.purchaseUnits orderResponse.status orderResponse. ? case .failure(let error): // transaction failed - human readable error information } } ``` ## Issues and Questions **Token Source** - The desire is for a merchant to be able to pass us a token generated from any source (`v1/payments`, `v2/orders`, others?) - per Mark - EC Tokens generated from the v1 API are not compatible with the v2 order actions: - `v2/checkout/orders/<order_id>/authorize` - `v2/checkout/orders/<order_id>/capture` - In order to satisfy #1 natively, we would need some ability to determine the token source AND properly handle / type the responses from the different potential token sources (ie `INTENT` values are different between `v1` and `v2` APIs) - **Possible solution:** Since this is a problem that will need to be solved by all three platforms (JS, Android, iOS), does it make sense to put this logic and response formatting behind a GraphQL layer that is universally targeted instead of targeting the orders API directly? **Authorization Intent** - Using the v2 API, does an `intent` value of `authorize` make sense for unbranded card transactions? **Merchant usecase for card validation** - Currently, the validation endpoint is marked `INTERNAL`. Is there a reason we would want this exposed? Without this endpoint, there wouldn't be a way for a merchant to do card validation using the orders API - [/v2/checkout/orders/{OrderID}/validate-payment-method](https://ppaas/api/3719176155270030?tab=apiReference&operation_id=post-_v2_checkout_orders_id_validate_payment_method) ------ ### **Possible implementation of card validation (if it becomes externally available)** - To consume card transaction with card validation: - Post to: [/v2/checkout/orders/{OrderID}/validate-payment-method](https://ppaas/api/3719176155270030?tab=apiReference&operation_id=post-_v2_checkout_orders_id_validate_payment_method) - Order can be created client side or server side - Documentation: https://hackmd.io/oo00FrwyQEe3aT4NI8WcuA?view#Option-2-Create--validate--approve--authorizecapture Do we need to provide the ability for the merchant to validate the card data before order execution? ```swift clientConfig.validate(orderID: orderID, card: Card) { result in // validates card data against above API response: response object would match the above order object } ``` Create transaction and capture separately - /v2/checkout/orders/:orderId/validate-payment-method - Order created, then captured or authorized separately - Documentation: https://hackmd.io/oo00FrwyQEe3aT4NI8WcuA?view#Option-3-Create--authorizecapture - **Questions**: If a user authorizes a card transaction and wants to capture the same transaction at a future point in time, would the merchant need to pass the card object in again, or would they pass in some part of the authorization response? What is the format of the capture / authorization response, and what should be vended to the user?