Introduction

Introduction

The Paze® API offers Merchants an easy, simple, and convenient way for their consumers to provide them with checkout information. A customers Paze wallet contains their credit and debit card information from participating Issuers as well as address information that can be used for shipping.

This document provides an introduction to integrating Paze checkout within a native mobile application.

Prerequisites

To use the Paze API, Merchants must establish a relationship with an approved Paze Distributor who will sponsor and onboard the Merchant. Upon onboarding, Merchants will be assigned entity identifiers (such as API keys and profile IDs) and exchange required cryptographic material.

Onboard Instructions

This section requires that you have a merchant account. Reach out to our merchant integrations team to learn more about building with Paze via [email protected]. Download and populate the merchant setup form in preparation for your kickoff call with our implementation team.

  • Paze API uses JWKS: JSON Web Key Set for secure authentication and communication.
  • Generate the JSON Web Key Set then provide Paze with your public JWK. Paze will then generate an oAuth ID which will be used to create client assertion - then submitted as a token for 30 minutes of access to the Paze endpoints.
  • Submit your public JSON web key via email to [email protected].
  • In addition you will need a Paze test wallet that allows developers to run integration and API tests without the need to have an actual credit card in their Paze wallet. To complete the test wallet set up, be sure to provide a full name, email address, and a US mobile number to the Paze implementation team.

Common Definitions

Field Status

The field status column of the following tables uses letters to signify required, optional, or conditional characteristics of the parameter:

  • R - Required: The request requires a value for this parameter.
  • O - Optional: The request does not require a value for this parameter, but inclusion of the parameter in the request may change script behavior. See the Definition / Description column formore information.
  • C - Conditional: The request requires a value for this parameter in specific circumstances. See the Definition / Description column for more information.

API Errors

API errors are reported using a standard error response structure. Logically, all errors are categorized into standard errors and business errors. Standard errors can be returned by any API and should be handled in a common way. Business errors are returned by only some APIs and are described in the errors section for each API.

Standard Error Response Structure

Unless noted elsewhere, the standard response structure (shown below) will be returned in case of an error. Use the reason field to drive your error handling logic. Errors are also provided with a human- readable description in the message field. This field should be used only to understand the problem. In rare cases, depending on the type of error, this error structure might not be returned and you should rely on the HTTP status code semantics.

FieldTypeMax SizeDescriptionField Status

clientContext

String

64

Merchant-defined transaction identifier, reflected in response.

O

ewSID

String

36

Globally unique identifier generated by the Service Operator. Returned 
in the response 
message in response to the initial request. This identifier ties all

information about the session together and should be easily accessible 
by Merchant staff submitting support requests to the Service Operator.Character set: a-f, 0-9, -

R

timestampISO8601

String

24

Timestamp of message in ISO 8601 extended combined format. Format: 
{YYYY}-{MM|-{DD}T{HH}:{MM}:{SS}ZExample: 2015-12-31T17:18Z


Time stamp when response is sent by the Service Operator.

R

error

Object

Container for the error details.

R

error.reason

String

64

Reason for the error.


Use this field to drive our error handling business logic.

R

error.message

String

1024

Free form text message describing the error condition.


Do not show this message to the end user.


Do not use this field to drive error handling logic. Use the reason field instead.


The server can change this message at any point in time.

R

error.details

Array

Array of fields, which failed validation. Populated if there are field level error details.

error.details[].reason

String

128

Error reason

C

error.details[].source

String

128

The value of this field is using XPATH expression to point to the field that failed validation.

C

error.details[].message

String

256

The specific error for this field.

//Example:

400 Bad Request 
Server: pazeserver
Date: Mon, 06 Jul 2020 13: 44: 07 GMT
Timestamp: 1594043046
Content - Type: application/json 
Content - Length: 1633

{
 "clientContext": "clientContextString",
  "ewSID": "string",
  "timestampISO08601": "2021-08-23T21:59:57Z",
  "error": {
        "reason": "INVALID\_ARGUMENT",
        "message": "Missing or invalid value specified in request.",
        "details": [
            {
              "reason": "INVALID\_VALUE",
              "source": "expirationMonth",
              "message": "Should be a numeric value"
            }
        ]
    }

}

Standard Errors

Standard errors can be returned by any API and should be handled consistently in a unified way. These errors may not be documented as part of each individual API description.

HTTP StatusCodeReasonDescription

400

INVALID_ARGUMENT

The value provided for one or more request parameters is considered invalid.
For example:

  • Missing required field.

  • The value exceeds the length specified for this field.

  • Field formatting does not match the expected format. The details.location field of the error response may provide a list of fields which failed data validation constraints.

400

INVALID_REQUEST

The API server could not understand the request.This sometimes occurs when a data field is not in the appropriate/particular format.


For example:

  • Base64URL decoding failed.

  • The field is not in a particular format. The message field may provide additional clarification of what part/field of the request is considered incorrect.Refer to the API specification for the structure, format and constraints of the API request.

401

AUTH_ERROR

Unauthorized, see error object for details, e.g., API credentials do not match, or authorization token validation failure

403

FORBIDDEN

Forbidden, see error object for details, e.g., invalid client identity (origin)

422

As provided by the TSP

The error occurred at the TSP (Token Service Provider) while processing the provisioning request. The error structure will provide the details as provided by the TSP.

429

TOO_MANY_REQUESTS

The requestor is exceeding the concurrent request limit.

500

SERVICE_ERROR

Internal server error, see error object for details


Mobile Client UX Integration

This section describes how to launch the UI/UX from a mobile application and return to the mobile application.

Once the mobile app receives thePazecheckout URL from the /checkout/session/create API call, and the consumer taps the Paze button (or related action), the mobile app needs to open the Paze checkout URL in the specific WebView control for the given mobile operating system. The WebViews will maintain state between multiple invocations and across the main browser as well asother apps, providing the best experience to a returning consumer.

Operating SystemWebView Control to Use
iOSASWebAuthenticationSession
AndriodCustom Chrome Tab

When the consumer exits the Paze UX, the Paze API  redirect the WebView to the callbackURLScheme that the Merchant has provided in the /checkout/session/create API call.

It is expected that this URL is provided in a native mobile format that will cause control to return to the native mobile app.

On redirect to this schema, the Paze API will append query string parameters of status and a hash(#) param response.

  1. "status" parameter with one of the following values:
    • success - the consumer successfully completed the Paze checkout steps, and the Merchant can utilize the other Paze APIs to get data to display or to get the secure payload
    • canceled – the consumer cancelled out of the Paze UX before the last step
    • failed – there was some error encountered during the Paze UX flow
  2. “response” parameter, includes a Base64URL encoded string with a JWS containing the minimal 'maskedCard' structure in the claim section. Once decoded the JWKS is the code for review/complete call.

The minimal “maskedCard” structure:

FieldTypeMax SizeDefinition / DescriptionField Status

maskedCard.panLastFour

String

4

Last 4 digits of the card.

R

maskedCard.paymentCardDescr iptor

String

32

A free-form string (max of 32 characters) used for card/program recognition. Example ‘Travel Rewards', ‘Cashback Rewards' etc.

R

maskedCard.paymentCardNetwork

Enum

Valid values:

  • VISA

  • MASTERCARD

  • DISCOVER

R

maskedCard.paymentCardType

Enum

Valid values:

  • CREDIT

  • DEBIT

R

maskedCard.paymentCardBrand

Enum

Brand of payment instrument. 
Valid values:

  • VISA
    - MASTERCARD

  • DISCOVER

R

maskedCard.digitalCardData

Object

Digital Card Art.

R

maskedCard.digitalCardData. artUri

String

1024

URI that hosts the Card Art image to be used for presentation purposes.

R

maskedCard.digitalCardData.artHeight

Integer

Height of art card image, in pixels.

R

maskedCard.digitalCardData.artWidth

Integer

Width of art card image, in pixels.

R

maskedCard.changeCardUrl

String

10K

URL to change card

R

“response” parameter example:

{

    "maskedCard": { 
        "panLastFour": "<String>",
        "paymentCardDescriptor": "<String>",
        "paymentCardNetwork": "<String>",
        "paymentCardType": "<String>",
        "paymentCardBrand": "<String>",
        "digitalCardData": {

            "artUri": "<URL>",

            "artHeight": < Integer > ,
            "artWidth": < Integer >

        },

        "changeCardUrl": "<URL>"

    },

    "authorization": {
        "intentId":   "<String>"

    }

}

For example, if the provided callbackURLScheme was “pazeCheckoutResponse”, then on redirect after successful completion of thePazecheckout flow, the redirect URL will look like this:

“pazeCheckoutResponse://?status=success#response = Rm9ybWF0OmJhc2U2NFVSTEVuY29kZShKVM6aGVhZGVyLmNsYWltLnNpZ25hdHVyZQ==”

Implementation Examples

iOS

This section will describe the iOS specific setup and code to launch the Paze checkout experience in a webview. The webview that must be used for iOS is the ASWebAuthenticationSession.

  1. Import the AuthenticationServices framework in the project file.
    • import AuthenticationServices
  2. Configure the URL Scheme
    • Open your Xcode project.
    • Go to the project settings, select your target, and open the "Info" tab.
    • Add a new URL Type by clicking on the plus button.
    • Set the callback URL scheme (e.g., com.domain.appid).
  3. ASWebAuthenticationSession takes two parameters:
    • url
    • callbackURLScheme

Implementation

class PazeViewController: UIViewController, ASWebAuthenticationPresentationContextProviding {
    // startPaze should be called when user hit PAZE checkout button 
    func startPaze() {
        /* pazeURL will be returned in /checkout/session/create response.this is the same, callbackURLScheme which is passed in createCheckoutSession, generally it is app’s bundle identifier( like – com.domain.appName ) */
        let callbackPazeScheme = "com.domain.appid"
        let sessionPaze = ASWebAuthenticationSession.init(url: pazeURL, callbackURLScheme: callbackPazeScheme) {
            callbackURL,
            error in guard
            let successCallbackURL = callbackURL,
                error == nil
            else {
                // Handle error; checkout with Paze has not be successful.
                return
            }
            let queryItems = URLComponents(string: successCallbackURL.absoluteString) ? .queryItems
                // Extract 'status' and 'response' from queryItems and proceed accordingly
        }
        session.presentationContextProvider = self
        session.start()
    }
    func presentationAnchor(
        for session: ASWebAuthenticationSession) - > ASPresentationAnchor {
        return self.view.window!
    }
}

Android

This section will describe the Android specific setup and code to launch thePazeexperience in a webview. The webview that must be used for Android is the Custom Chrome Tab (CCT).

  1. Add Dependencies in build.gradl file.
    implementation androidx.browser:browser:<version>
  2. Configure the Custom URL Scheme
    • Open your AndroidManifest.xml.
    • Add an intent filter to handle the callback URL scheme (e.g., 'com.domain.app_name').

AndroidManifest.xml

 <activity android:name=.PazeCallbackActivity”>
 <intent-filter>
 		<action android:name=”android.intent.action.VIEW” />
 		<category android:name=”android.intent.category.DEFAULT” />
 		<category android:name=”android.intent.category.BROWSABLE” />
 		<data android:scheme="<com.domain.app_name>"; android:host=”callback” />
 </intent-filter>
</activity>

Implementation

Launch the WebView

 import android.content.Intent;
 import android.net.Uri;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.browser.customtabs.CustomTabsIntent;
 public class PazeActivity extends AppCompatActivity {

     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_paze);
         startPaze();
     }

     private void startPaze() {
         // pazeURL will be returned in createCheckoutSession response
         Uri uri = Uri.parse(pazeUrl);
         CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
         CustomTabsIntent customTabsIntent = builder.build();
         customTabsIntent.intent.setData(uri);
         customTabsIntent.launchUrl(this, uri);
     }

 }

Handle the Callback

public class PazeCallbackActivity extends AppCompatActivity {

    /* This is the same callbackURLScheme which is passed in   
    createCheckoutSession; generally it is app’s applicationId (like – 
    com.domain.appName )*/
    private static final String CALLBACK_SCHEME_PAZE = "com.domain.app_name";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Uri uri = getIntent().getData();
        if (uri != null && uri.getScheme().equals(CALLBACK_SCHEME_PAZE)) {
            // Process 'status' and 'response' parameters and proceed accordingly
        }
        finish();
    }

}

API Backward Compatibility Considerations

The following changes are considered backward-compatible:

  • Adding a new API resource or method.
  • Adding a new optional request parameter to an existing API method.
  • Adding a new value to a pre-defined list of values. The value can be added either in the request or the response
  • Relaxing some of the constraints on an existing request parameter. For example, making it optional.
  • Adding a new response parameter to the API response.
  • Changing the format of opaque string identifiers. 

In simple terms, these rules mean:

  • Ignore any unknown fields received as part of API responses.
  • Code to deal with unknown values received as part of API responses in a graceful manner.
  • Do not make any assumptions except length about opaque string identifiers.
  • The Service Operator may add new optional parameters to existing APIs and relax constraints on existing request parameters at any time.

We consider “additive” changes or changes to field values already flagged as having the potential to change, non-breaking.

“Reductive” changes; removing fields, end points, payload entries or changes to fields that were not noted as having a potential to change are all considered breaking changes.