Integrating MPSDK on Android

For downloading MPSDK and basic setup, refer to Basic Setup.

Do This First

Regardless of the payment method, you need to create and initialize a WirecardClient instance before anything else:

paymentSDK only works with non-rooted devices; if it detects a device that is rooted, it will throw an exception during initialization of the WirecardClient object.

WirecardClient wirecardClient;
String environment = WirecardEnvironment.TEST.getValue();
try {
    wirecardClient = WirecardClientBuilder.newInstance(context, environment)
                    .build();
} catch (WirecardException exception) {
    //device is rooted
}

The example above also handles the "device is rooted" exception situation by using try and catch.

For credit card & PayPal payments, add this line when creating the payment object (e.g. WirecardCardPayment):

wirecardPayment.setProcessingURL("paymentsdkdemo://web.result");

Additional Features

Features which are not bound to a single payment method are listed here:

Checking Transaction Status

You can use the checkPayment method to see the current status of your transaction

checkPayment Format
wirecardClient.checkPayment(wirecardPayment, wirecardResponseListener);

Instead of wirecardPayment use the relevant payment object (e.g. wirecardCardPayment). It should contain the same request ID & MAID as the transaction you are checking.

Credit Card

Fullscreen Form
Do not forget to create and initialize an instance of the WirecardClient object before you go further, as explained at the start of this section.
Simple Transactions
  1. Create and initialize the WirecardCardPayment object, which stores the transaction’s payload & signature:

    WirecardCardPayment wirecardCardPayment = new WirecardCardPayment (signature, requestTimeStamp, requestID,merchantID, transactionType, amount, currency);
  2. Initialize the WirecardResponseListener object, which stores callback methods that let you know the result of the transaction, or any errors, should they occur:

    WirecardResponseListener Initialization
    WirecardResponseListener wirecardResponseListener = new WirecardResponseListener() {
        @Override
        public void onResponse(WirecardPaymentResponse paymentResponse) {
            // handle server response
            if (paymentResponse.getTransactionState().equals(TransactionState.SUCCESS)) {
                // handle successful transaction
            } else {
                // handle unsuccessful transaction
            }
        }
        @Override
        public void onError(WirecardResponseError responseError) {
            // handle error
            switch (responseError.getErrorCode()) {
                case WirecardErrorCode.ERROR_CODE_GENERAL:
                    String detailedMessage = responseError.getErrorMessage();
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_INVALID_PAYMENT_DATA:
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_NETWORK_ISSUE:
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_USER_CANCELED:
                    //...
                    break;
            }
        }
    };
  3. Call the WirecardClient's method makePayment to send the transaction request:

    wirecardClient.makePayment(wirecardCardPayment, wirecardResponseListener, paymentPageStyle);

    You can customize the UI through resources of the paymentPageStyle object. We will revisit the 'how' at the end of this section.

  4. Process the response. If everything went smoothly server-side, the onResponse method will be called. If any errors occurred, onError will be called instead.

Referenced Transactions

If you need to perform referenced transactions (i.e. one’s using token or parentTransactionID), set them in the wirecardCardPayment instance:

wirecardPayment.setParentTransactionID(parentTransactionID);

OR

CardToken cardToken = new CardToken(tokenID, maskedAccountNumber);
wirecardPayment.setCardToken(cardToken);
Customizing the UI

Despite strict rules, we give you as much customization as possible within the limits of the PCI DSS standards.

You can customize the following
  • styling of the input fields

  • background color of the form & buttons

  • labels, hints, and their colors

  • icons for the supported card providers

  1. To begin customizing, initialize PaymentPageStyle:

    PaymentPageStyle style = new PaymentPageStyle();
  2. Then, provide your customized resources:

    PaymentPageStyle style = new PaymentPageStyle();
               style.backgroundResourceId = R.color.yellow;
               style.inputTextColor = context.getResources().getColor(R.color.red);
               style.inputFieldColor = context.getResources().getColor(R.color.red);
               style.inputHintTextColor = context.getResources().getColor(R.color.red_transparent);
               style.payButtonBackgroundResourceId = R.color.blue;
               style.toolbarResourceId = R.color.red;
               style.inputLabelTextColor = context.getResources().getColor(R.color.blue);
               style.scanButtonTextColor = context.getResources().getColor(R.color.red);
               style.toolbarTextColor = context.getResources().getColor(R.color.yellow);
               style.payButtonTextColor = context.getResources().getColor(R.color.yellow);
    
               //!!!
               Set<CardBrand> supportedCardBrands = new HashSet<>();
               supportedCardBrands.add(CardBrand.MASTERCARD);
               supportedCardBrands.add(CardBrand.AMEX);
               style.supportedCardBrands = supportedCardBrands;
    
               ...
If you do not configure Set<CardBrand> supportedCardBrands at this point, all of the possible card brands will be considered supported by default.
Embedded Form
Do not forget to create and initialize an instance of the WirecardClient object before you go further, as explained at the start of this section.

Since you’re using an embedded component instead of rendering the whole page, there are some changes in the approach.

You need to initialize the WirecardCardFormFragment component first:

  1. In the XML layout, create a container where you will place the WirecardCardFormFragment :

    <FrameLayout
       android:id="@+id/container"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
     </FrameLayout>
  2. Create a new instance of this fragment:

    WirecardCardFormFragment wirecardCardFormFragment = new WirecardCardFormFragment.Builder(wirecardExtendedCardPayment).build();
  3. Add wirecardCardFormFragment into the container created in first step:

    getSupportFragmentManager()
        .beginTransaction()
        .add(R.id.container, wirecardCardFormFragment)
        .commit();

Now you should be able to see the card component in your layout.

Customizing The Form Fragment

To style the fragment, create WirecardCardFormFragment using WirecardCardFormFragment.Builder:

WirecardCardFormFragment wirecardCardFormFragment = new WirecardCardFormFragment.Builder(wirecardExtendedCardPayment)
.setLocale("de")
.setTextSize(12)
.setHintColorID(hintColorID)
.setTextColorID(textColorID)
.setRequestFocus(true)
.build();

To set supported card brands, use WirecardCardFormFragment.Builder method setSupportedCardBrands(Set<CardBrand> supportedCardBrands):

Set<CardBrand> supportedCardBrands = new HashSet<>();
supportedCardBrands.add(CardBrand.MASTERCARD);
supportedCardBrands.add(CardBrand.AMEX);

builder.setSupportedCardBrands(supportedCardBrands);
If you do not set the supported card brands, all of them are shown as supported by default.
Initializing the Payment Object

After setting the fragment into the layout, the steps are similar to the normal process.

The way you enable the payment object is almost identical to the full screen form approach; however, instead of WirecardCardPayment, use WirecardExtendedCardPayment:

WirecardExtendedCardPayment wirecardExtendedCardPayment = new WirecardExtendedCardPayment(signature, requestTimeStamp, requestID, merchantID, transactionType, amount, currency);

Optionally, if a last name is required for successful transaction, add it to WirecardExtendedCardPayment:

CustomerData accountHolder = new CustomerData();
accountHolder.setLastName(lastName);
wirecardExtendedCardPayment.setAccountHolder(accountHolder);
Initializing the Input State Listener

As the name suggests, Input State Listener notifies you of any state changes in your card input fields (e.g. you can use this for showing text message or alerts for certain cases).

To use it, follow these steps:

  1. Create a WirecardInputFormsStateChangedListener instance:

    WirecardInputFormsStateChangedListener wirecardInputFormsStateChangedListener = new WirecardInputFormsStateChangedListener() {
        @Override
            public void onStateChanged(int code) {
                switch(code){
                    case WirecardInputFormsStateChangedListener.CARD_NUMBER_FORM_FOCUS_GAINED:
                        ...
                        break;
                    case WirecardInputFormsStateChangedListener.EXPIRATION_MONTH_FORM_FOCUS_GAINED:
                        ...
                        break;
                    ...
                }
            }
    };
  2. Create a WirecardInputFormsStateManager instance. This manages communication between the input fields and the listener:

    WirecardInputFormsStateManager wirecardInputFormsStateManager = new WirecardInputFormsStateManager(context, wirecardInputFormsStateChangedListener);

WirecardInputFormsStateManager provides two methods:

  • startReceivingEvents()

  • stopReceivingEvents()

The manager wraps the BroadcastReceiver, so you can treat these two methods like BroadcastReceiver’s registerReceiver()/unregisterReceiver().

Regardless, call startReceivingEvents() in the onResume() method, and stopReceivingEvents() in the onPause() method:

@Override
public void onResume() {
    super.onResume();
    wirecardInputFormsStateManager.startReceivingEvents();
}
@Override
public void onPause() {
    super.onPause();
    wirecardInputFormsStateManager.stopReceivingEvents();
}

Here is a list of constants for fired events included in WirecardInputFormsStateChangedListener:

Constant Event Description

CARD_NUMBER_FORM_FOCUS_GAINED

card number input form gained focus

EXPIRATION_MONTH_FORM_FOCUS_GAINED

exp. month input form gained focus

EXPIRATION_YEAR_FORM_FOCUS_GAINED

exp. year input form gained focus

SECURITY_CODE_FORM_FOCUS_GAINED

security code (CVC/CID) input form gained focus

CARD_NUMBER_FORM_FOCUS_LOST

card number input form focus lost

EXPIRATION_MONTH_FORM_FOCUS_LOST

exp. month input form focus lost

EXPIRATION_YEAR_FORM_FOCUS_LOST

exp. year input form focus lost

SECURITY_CODE_FORM_FOCUS_LOST

security code (CVC/CID) input form focus lost

CARD_BRAND_UNSUPPORTED

card number wasn’t recognized after typing 3 numbers

CARD_NUMBER_INVALID

card number has reached max length but card validity check wasn’t successful

CARD_NUMBER_INCOMPLETE

card number is not complete, user typing his number

CARD_NUMBER_VALID

card passes validity check

EXPIRATION_MONTH_INCOMPLETE

expiration month is not complete yet. For example, user types one number, and jumps to expiration year field.

EXPIRATION_MONTH_VALID

expiration month is valid. Note that we don’t have event for invalid state, because user is able to enter only valid month.

EXPIRATION_YEAR_INCOMPLETE

called when expiration year is not complete yet.

EXPIRATION_YEAR_VALID

expiration year is valid. Note that we don’t have event for invalid state, because user is able to enter only valid year.

SECURITY_CODE_INCOMPLETE

security code is not complete yet

SECURITY_CODE_VALID

security code is complete

CARD_VALID

all inputs(card number, expiration month, expiration year and security code) are valid. When you get this event, you can proceed to next step

Executing Credit Card Transactions

Before you execute the transaction, you need to get the data from the input fields to the handler:

wirecardExtendedCardPayment = wirecardCardFormFragment.getWirecardExtendedCardPayment();

Now that WirecardExtendedCardPayment has the payment data, you can call WirecardClient's makePayment() method and execute the transaction.

It is possible to clear all input fields (e.g. for situations where the app goes to background).

wirecardCardFormFragment.clearAllFields();

You can also get the card brand of the currently entered card number:

wirecardCardFormFragment.getCardBrand();

Favorite Payment Use Case Example

You might want to offer users who have already made a purchase with you a streamlined way to pay, where they only enter the security code (CVC/CID) instead of all the data (which is now saved as the card token). You still need to follow all of the steps from the Embedded Form section, but with some differences:

  1. Add a card token (as is, or instead of cardholder’s last name) to WirecardExtendedCardPayment:

    wirecardExtendedCardPayment.setCardToken(new CardToken(token, maskedCardNumber));
  2. Create the WirecardCardFormFragment using WirecardCardFormFragment.Builder like this:

    wirecardCardFormFragment = new WirecardCardFormFragment.Builder(wirecardExtendedCardPayment)
            .setCardBrand(cardBrand) //for example CardBrand.VISA
            .setExpirationDate(expirationDate) // for example "1219"
            .build();
  3. Same as in the previous example, you need to get the updated WirecardExtendedCardPayment, now containing the security code from the input field:

    wirecardExtendedCardPayment = wirecardCardFormFragment.getWirecardExtendedCardPayment();
  4. Call WirecardClient's makePayment() method to execute the transaction:

    wirecardClient.makePayment(WirecardExtendedCardPayment, wirecardResponseListener, paymentPageStyle);

PayPal

Do not forget to create and initialize an instance of the WirecardClient object before you go further, as explained at the start of this section.
Simple Transactions
  1. Create and initialize WirecardPayPalPayment:

    WirecardPayPalPayment wirecardPayment = new WirecardPayPalPayment(signature, requestTimeStamp, requestID, merchantID, transactionType, amount, currency);
  2. Initialize the WirecardResponseListener object, which stores callback methods that let you know the result of the transaction, or any errors, should they occur:

    WirecardResponseListener Initialization
    WirecardResponseListener wirecardResponseListener = new WirecardResponseListener() {
        @Override
        public void onResponse(WirecardPaymentResponse paymentResponse) {
            // handle server response
            if (paymentResponse.getTransactionState().equals(TransactionState.SUCCESS)) {
                // handle successful transaction
            } else {
                // handle unsuccessful transaction
            }
        }
        @Override
        public void onError(WirecardResponseError responseError) {
            // handle error
            switch (responseError.getErrorCode()) {
                case WirecardErrorCode.ERROR_CODE_GENERAL:
                    String detailedMessage = responseError.getErrorMessage();
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_INVALID_PAYMENT_DATA:
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_NETWORK_ISSUE:
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_USER_CANCELED:
                    //...
                    break;
            }
        }
    };
  3. Call WirecardClient's method makePayment to execute the transaction:

    wirecardClient.makePayment(wirecardPayPalPayment, wirecardResponseListener, paymentPageStyle);
  4. Process the response. If everything went smoothly server-side, wirecardResponseListener's onResponse method is called. If any errors occurred, onError will be called instead.

Recurring Transactions

If you require recurring transactions, set the Periodic object into the wirecardPayPalPayment instance:

Periodic periodic = new Periodic(periodicType, sequenceType);
wirecardPayPalPayment.setPeriodic(periodic);

SEPA Direct Debit

Do not forget to create and initialize an instance of the WirecardClient object before you go further, as explained at the start of this section.
Simple Transactions
  1. Create and initialize WirecardSepaPayment:

    WirecardSepaPayment payment = new WirecardSepaPayment (signature, requestTimeStamp, requestID, merchantID, transactionType, amount, currency, creditorId, mandateId, mandateSignedDate, merchantName, dueDate);
  2. Initialize the WirecardResponseListener object, which stores callback methods that let you know the result of the transaction, or any errors, should they occur:

    WirecardResponseListener Initialization
    WirecardResponseListener wirecardResponseListener = new WirecardResponseListener() {
        @Override
        public void onResponse(WirecardPaymentResponse paymentResponse) {
            // handle server response
            if (paymentResponse.getTransactionState().equals(TransactionState.SUCCESS)) {
                // handle successful transaction
            } else {
                // handle unsuccessful transaction
            }
        }
        @Override
        public void onError(WirecardResponseError responseError) {
            // handle error
            switch (responseError.getErrorCode()) {
                case WirecardErrorCode.ERROR_CODE_GENERAL:
                    String detailedMessage = responseError.getErrorMessage();
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_INVALID_PAYMENT_DATA:
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_NETWORK_ISSUE:
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_USER_CANCELED:
                    //...
                    break;
            }
        }
    };
  3. Call WirecardClient's method makePayment to execute the transaction:

    wirecardClient.makePayment(wirecardSepaPayment, wirecardResponseListener, paymentPageStyle);
  4. Process the response. If everything went smoothly server-side, wirecardResponseListener's onResponse method is called. If any errors occurred, onError is called instead.

Recurring Transactions

If you require recurring transactions, set the Periodic object into the wirecardSepaPayment instance:

Periodic periodic = new Periodic(periodicType, sequenceType);
wirecardSepaPayment.setPeriodic(periodic);

Pay by Bank app (PBBA)

Do not forget to create and initialize an instance of the WirecardClient object before you go further, as explained at the start of this section.
Simple Transactions
  1. Add a dependency for the Zapp merchant library. For more details on dependencies see Basic Setup and Integration:

    compile 'com.zapp.library:merchant:1.1.0'
  2. Create and initialize WirecardPBBAPayment:

    WirecardPBBAPayment wirecardPayment = new WirecardPBBAPayment(signature, timestamp, requestID, merchantID, transactionType, amount, currency, zappTransactionType, zappDeliveryType, returnValue);
    Important notes
    • The only supported transaction type is debit.

    • The only supported currency is GBP.

    • IP address is mandatory for this payment method.

    • zappTransactionType is one of following options: BILLPT, PAYMT, INVOICE, DONATIONS .

    • zappDeliveryType is one of following options: COLLST, DELTAD, DIGDEL, SERVICE, F2F, NONE.

    • ReturnValue is the URL scheme used in the bank application to redirect the consumer back to your application.

    • If a user cancels the ZAPP popup with the payment code BRN by pressing the X button at the top right, ERROR_CODE_USER_CANCELED is returned to let the merchant know that the user cancelled the transaction. Users cannot cancel a transaction if the CFI app is installed.

  3. Initialize the WirecardResponseListener object, which stores callback methods that let you know the result of the transaction, or any errors, should they occur:

    WirecardResponseListener Initialization
    WirecardResponseListener wirecardResponseListener = new WirecardResponseListener() {
        @Override
        public void onResponse(WirecardPaymentResponse paymentResponse) {
            // handle server response
            if (paymentResponse.getTransactionState().equals(TransactionState.SUCCESS)) {
                // handle successful transaction
            } else {
                // handle unsuccessful transaction
            }
        }
        @Override
        public void onError(WirecardResponseError responseError) {
            // handle error
            switch (responseError.getErrorCode()) {
                case WirecardErrorCode.ERROR_CODE_GENERAL:
                    String detailedMessage = responseError.getErrorMessage();
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_INVALID_PAYMENT_DATA:
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_NETWORK_ISSUE:
                    //...
                    break;
                case WirecardErrorCode.ERROR_CODE_USER_CANCELED:
                    //...
                    break;
            }
        }
    };
  4. Update AndroidManifest.xml with a starting activity for the custom URL scheme:

    <activity android:name=".MainActivity"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter android:autoVerify="true">
            <data android:scheme="paymentsdkdemo" android:host="open.pbba" />
    
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
        </intent-filter>
    </activity>

    To avoid app instability, add also android:configChanges="orientation|screenSize" to the activity record in your AndroidManifest file:

    Example Usage
            <activity
                android:name=".ui.activity.PaymentActivity"
                android:label="Payment"
                android:configChanges="orientation|screenSize" />
  5. You need to use PBBAButton for executing transactions (see ZAPP guidelines for more details):

    <com.zapp.library.merchant.ui.view.PBBAButton
        android:id="@+id/pbba"
        android:layout_width="@dimen/pbba_button_width"
        android:layout_height="@dimen/pbba_button_height" />
  6. Call WirecardClient's method makePayment to execute the transaction:

    wirecardClient.makePayment(wirecardSepaPayment, wirecardResponseListener, paymentPageStyle);
  7. Next, either the PBBA dialog is shown or the banking application is opened.

  8. Consumer makes the payment in the banking application and is redirected back to your application. The application returns success or timeout depending on the response.

  9. Process the response. If everything went smoothly server-side, wirecardResponseListener's onResponse method is called. If any errors occurred, onError is called instead.

Custom URL: