Northstar Native SDK Client Spec

BT SDK Card Client

  • initized with an API client
  • Two top level functions
- (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
- (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

// 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

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

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

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

Possible implementation of card validation (if it becomes externally available)

 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?