# Intercepting payments using payment hooks

# Overview

Poynt payment fragement provides a set of hooks to intercept payments there by allowing developers to provide value added services such as loyalty, discounts and many others. This document describes how a developer can register and make use of payment hooks.

SamplePaymentHooks app has a sample implementation payment hooks usage.

Payment hooks allows developers to build applications that hook into the payment flow without having the need for opening the application manually. This allows for a better user experience and few interactions per transaction. For example if you would like to provide loyalty rewards for every customer then you could just add points based on the amount and identify the customer using the unique card hash provided after the card is swiped.

Note

Minimum OS version required to use payment hooks

Device OS Version
Poynt 5 1.19.7-56-101
Smart terminal v1 1.19.7-57-105
Smart terminal v2 1.19.7-54-98

# Integration Steps

Minimum SDK version required

implementation 'co.poynt.api:android-api-model:1.2.140'
implementation 'co.poynt.android.sdk:poynt-sdk:1.2.44'
1
2
  1. Create a service that implements IPoyntPaymentHooks
public class SamplePaymentHooksService extends Service {
    public SamplePaymentHooksService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private final IPoyntPaymentHooks.Stub mBinder = new IPoyntPaymentHooks.Stub() {
        @Override
        public void onEvent(@PaymentHookEvent.Type String eventType, Payment payment, @Nullable Transaction transaction, @Nullable Bundle bundle, IPoyntPaymentHooksListener listener) throws RemoteException {

        	/**
        	 * put you code here
        	 * or use default behavior
             * IMP NOTE: IF YOU RECEIVE AN EVENT THAT YOU DO NOT RECOGNIZE, YOU MUST
             * CALL ONCONTINUE() CALLBACK. THIS IS IMPORTANT FOR BACKWARD/FORWARD
             * COMPATIBILITY
        	 */
          listener.onContinue();
        }
    };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Note

Always call listener.onContinue() by default if there is no action needed, not doing this can break the ability to transact

  1. Specify configuration in payment_hooks_capability.xml and add it to your Android.manifest file

Payment hooks capability file

<?xml version="1.0" encoding="utf-8"?>
<capability>
  <!-- Your App ID same as your package name-->
  <appid>com.poynt.samples.paymenthooks</appid>

	<!-- DO NOT CHANGE-->
  <type>PAYMENT_HOOKS</type>

  <!-- descriptive name of this capability -->
  <provider>Sample Hooks</provider>
</capability>
1
2
3
4
5
6
7
8
9
10
11

Android manifest file

........
<service
  android:name=".SamplePaymentHooksService"
  android:enabled="true"
  android:exported="true">
  <intent-filter>
      <action android:name="co.poynt.os.services.v1.IPoyntPaymentHooks" />
  </intent-filter>
  <meta-data
      android:name="co.poynt.os.service.capability"
      android:resource="@xml/payment_hooks_capability" />
</service>
1
2
3
4
5
6
7
8
9
10
11
12

# Payment Hooks Listener

Payment hooks listener provides multiple ways to pass back information or to resume flow.

interface IPoyntPaymentHooksListener{

    /**
     * Call this listener when you want to send updated payment object
     * @param payment
     */
    void updatePayment(Payment payment);

    /**
     * Call this listener when you want to use default flow
     */
    void onContinue();

    /**
     * Call this listener when you want to start an activity
     * @param intent
     */
    void onLaunchActivity(Intent intent);

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# Payment hook events and extras

Payment hook events are triggered for sales, refunds, voids and authorizations. Event types currently supported are

public class PaymentHookEvent {
    @Retention(RetentionPolicy.SOURCE)
    @StringDef({
            PAYMENT_STARTED,
            PAYMENT_CANCELED,
            PAYMENT_RESTARTED,
            PAYMENT_METHOD_SELECTED,
            PAYMENT_AUTHORIZED,
            PAYMENT_FAILED,
            PAYMENT_VOIDED,
            PAYMENT_REFUNDED})
    public @interface Type {
    }

    /**
     * Event will be called just after opening payment fragment.
     */
    public static final String PAYMENT_STARTED = "PAYMENT_STARTED";

    /**
     * Event will be called when transaction is canceled after tap on "Cancel" button
     */
    public static final String PAYMENT_CANCELED = "PAYMENT_CANCELED";

    /**
     * Event will be called when transaction is restarted after tap on "Retry" button
     */
    public static final String PAYMENT_RESTARTED = "PAYMENT_RESTARTED";

    /**
     * Event will be called when payment method has been selected:
     * CASH
     * CARD
     * MANUAL_ENTRY
     */
    public static final String PAYMENT_METHOD_SELECTED = "PAYMENT_METHOD_SELECTED";

    /**
     * Event will be called after online authorization.
     * CARD and MANUAL_ENTRY only
     */
    public static final String PAYMENT_AUTHORIZED = "PAYMENT_AUTHORIZED";

    /**
     * Event will be called when transaction has failed (example: offline decline)
     */
    public static final String PAYMENT_FAILED = "PAYMENT_FAILED";

    /**
     * Event will be called when transaction is voided
     */
    public static final String PAYMENT_VOIDED = "PAYMENT_VOIDED";

    /**
     * Event will be called when transaction is refunded
     */
    public static final String PAYMENT_REFUNDED = "PAYMENT_REFUNDED";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

Hook events are accompanied by a bundle with additional data based on the hook type. Available extras included in bundle

Note

Not all extras are available with all hoooks

public static final class HooksExtras {
        public static final String PAYMENT_TYPE = "PAYMENT_TYPE";
        public static final String PAYMENT = "payment";
        public static final String TRANSACTION = "transaction";
}

public static final class CardExtras {
        public static final String SERVICE_CODE = "SERVICE_CODE";
        public static final String CARDHOLDER_NAME = "CARDHOLDER_NAME";
        public static final String APP_EXPIRATION_DATE = "APP_EXPIRATION_DATE";
        public static final String PAN_LAST_4 = "PAN_LAST_4";
        public static final String CARD_BIN_RANGE = "CARD_BIN_RANGE";
        public static final String ACQUIRER_ID = "ACQUIRER_ID";
        public static final String AID_TERMINAL = "AID_TERMINAL";
        public static final String APPLICATION_LABEL = "APPLICATION_LABEL";
        public static final String PAN_SEQUENCE_NUMBER = "PAN_SEQUENCE_NUMBER";
        public static final String ISSUER_COUNTRY_CODE = "ISSUER_COUNTRY_CODE";
        public static final String ENCRYPTED_PAN = "ENCRYPTED_PAN";
        public static final String ENCRYPTED_TRACK = "ENCRYPTED_TRACK";
        public static final String ISSUER_CODE_TABLE_INDEX = "ISSUER_CODE_TABLE_INDEX";
        public static final String APP_PREFERRED_NAME = "APP_PREFERRED_NAME";
        public static final String KEY_IDENTIFIER = "KEY_IDENTIFIER";
        public static final String APPLICATION_CURRENCY_CODE = "APPLICATION_CURRENCY_CODE";
        public static final String PAN_HASH = "PAN_HASH";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# FAQ

Last Update: 8/27/2020, 9:42:06 AM