Android payment service apps

8 Steps to Google Pay on Android

Within our Android Apps we can use the Google Pay API to plugin a convenient way for our users to checkout in our app, without the need for them to enter any of their payment information (after an initial setup). This brings the user a collection of advantages such as:

  • A centralised place to complete all their payments within your apps, just like they are able to do on the web or in stores
  • A streamlined process when completing the checkout stage of a purchase from within your app
  • A feeling of safety whilst paying due to the secure storage of payment information fro Google pay

The Google Pay API for android allows developers to easily integrate a payment method that provides this streamlined, secure and familiar experience for our users.

We all want to make things simpler and better or users, so in this article I want to show you can get Google Pay integrated into your Android Application with 8 individual steps.

Configure payment methods

Before we go ahead and start configuring the class used to handle payments within our app, we need to declare some fundamental data used in the requests that we are going to perform.

We begin by defining a list of accepted cards, this collection can currently include Amex, Discover, Mastercard, JCB and Visa cards.

Next we need to define the accepted authentication methods that can be used for the transaction. The given choice can include the following options:

  • PAN_ONLY — Associated with cards that are stored alongside the Google Account of the current user. The data returned includes a corresponding account number alongside the expiration month and year.
  • CRYPTOGRAM_3DS — Associated with cards that are stored as Android device tokens. The data returned includes a 3DS cryptogram generated on the given device.

Now that we have the above details defined, we can go ahead and prepare this data for use with the Google Pay API. These need to go under the following properties:

  • allowedAuthMethods — Takes the accepted authentication methods that can be used when making payment requests
  • allowedCardNetworks — Takes the declared accepted cards that can be used to make payments

As well as the above we can also optionally declare:

  • allowPrepaidCards — States whether or not pre-paid cards can be used when making payment requests
  • billingAddressRequired — States whether or not a billing address is required to complete the transaction
  • billingAddressParameters — Takes data in the format of the BillingAddressParameters class

Finally, we put all of this together by declaring the accepted payment type as a CARD and pass over the payment parameters that we declared above:

Configure wallet options

Before we instantiate our payment client to handle our payment requests, we need to create an instance of the options used by this client — this is in the form of the WalletOptions class.

Using the builder we can configure two properties to be using by our payment client:

  • environment —The environment to be used when making transactions. This will be set to either ENVIRONMENT_PRODUCTION or ENVIRONMENT_TEST.
  • theme — The theme to be used for the payments widget. This will be set to either THEME_LIGHT or THEME_DARK.

Initialise the Payments Client

Now that we have configured the options for our payments client, we can go ahead an instantiate a new instance of our client ready for use.

Here we pass in our current context and the WalletOptions instance that we built during the last step. At this point we now have a payments client reference within our application that can be triggered when the uses requests to make a payment.

Declare a Google Play Button

Using the assets provided over on the brand guidelines for Google Pay, you need to begin by adding a button to your application that uses one of the provided assets. This provides a way for the user to recognise the Google Pay payment method. Selecting this button will trigger the payment flow that we will look at over the next few sections.

Читайте также:  Андроид хаг мой том

Check if payments is ready for use

Now that we have a payments client, we want to check if the user is able to make payments using the Google Pay API — we may encounter errors when trying to access the API otherwise. So here we want to make sure that the button for Google Pay is not visible until the Google Pay API is ready for use.

We begin by building the request that is to be sent for our isReadyToPay call. Here we pass:

  • apiVersion — The major API version to be used (integer)
  • apiVersionMinor — The minor API version to be used (integer)
  • allowedPaymentMethods — A collection of PaymentMethod instances that declare the supported payment methods of the client.

We can also optionally provide a existingPaymentMethodRequired (boolean) property — setting this property to true will cause isReadyToPay() to return true if the user is ready to pay with at least one of the specified payment methods.

Now that we have these properties built, we can go ahead and pass them to our isReadyToPay() call:

Setup Gateway Configuration

Next we need to setup the relevant gateway details — this gateway is what will receive the encrypted users information to process a given transaction.

  • gateway — Identify for a Google-supported gateway
  • gatewayMerchantId — Unique ID that links the merchant to the given gateway

You’ll notice below that we then bundle this all together (marked with the PAYMENT_GATEWAY identifier) as the tokenizationSpecification argument for use by the Google Pay API.

Prepare transaction information

At this point we need to defined the transaction data that will be presented by the Google Pay widget. We begin with the TransactionInfo, this contains details such as:

  • currencyCode — The currency to be used for the transaction
  • totalPriceStatus — The status of the total price. This will be either NOT_CURRENTLY_KNOWN, ESTIMATED (the price may change based on shipping or tax calculations) or FINAL (the price will never change from the one currently displayed to the user)
  • totalPrice — The total price of the transaction
  • checkoutOption — Decides the behaviour used and text to be shown within the checkout button of the google pay sheet. This can be either DEFAULT (standard behaviour, the user will need to confirm transaction details) or COMPLETE_IMMEDIATE_PURCHASE (when the totalPriceStatus is final, the user will complete the purchase with no further action).

We then need to build the payment request using our transaction information that we just prepared. For this we build a PaymentDataRequest instance and populate the required data:

  • apiVersion — The major API version to be used (integer)
  • apiVersionMinor — The minor API version to be used (integer)
  • merchantInfo — Information regarding the merchant in the form of a MerchantInfo class
  • allowedPaymentMethods — A collection of PaymentMethod instances that declare the supported payment methods of the client.
  • transactionInfo — Information about the transaction in the form of a TransactionInfo class
  • emailRequired — States whether an email address is required to complete the transaction
  • shippingAddressRequired — States whether a shipping address is required to complete the transaction
  • shippingAddressParameters — Information about the shipping address in the form of a ShippingAddressParameters class

Listen for Payments callback

Now that the payment request has been made we need to listen for the result. The result of this request is returned to the calling source via the onActivityResult method with the resultCode that was initially passed in with the request.

Once we have the data back from the request we can make use of the PaymentData class from the Google Pay API to parse the result of the intent — giving us back an instance of this PaymentData class that contains billing information for the transaction.

Here this data is then converted into a JSON format so that it can be passed onto our payment processor. At this point we have carried out all of the required steps and our transaction is ready to be completed.

Conclusion

Hopefully from this quick post you can see just how little steps are required to integrate Google Pay into your Android application. Doing so allows us to implement a streamlined experience that is secure and gives a sense of familiarity to our users. Why not get started with Google Pay in your own Android applications today?

Читайте также:  Какие смартфоны будут без андроида

Источник

Как принимать платежи в мобильном приложении: токенизация, NFC, оптическое сканирование и другие плюшки в одном SDK

Кейс 1. Привязываем карту клиента к бэкенду для регулярных списаний или платежей в 1 клик.

Тут важно понимать, что если ваш бэкенд не сертифицирован по PCI DSS, то номер карты и ее срок действия вы не можете хранить в своей базе данных. Поэтому, прежде чем привязать идентификатор карты к аккаунту клиента, необходимо сначала карту токенизировать. Для этого вам необходимо осуществить через мобильное приложение первый платеж с участием клиента, и желательно с 3D-Secure, заблокировав на карте небольшую сумму, например 1 единицу валюты. 3D-secure в данном случае необходим в первую очередь, чтобы обезопасить себя, как торговую точку, от финансовых претензий (чарджбеков) по будущим рекурентным списаниям, а во вторую очередь — чтобы улучшить конверсию, так как например по картам Сбербанка в России и Приватбанка в Украине в большинстве случаев транзакция без 3D-Secure не пройдет.
Итак, чтобы получить токен карты, необходимо передать параметры requiredRecToken и verification (более подробно как создать мобильное приложение смотрите в статье, ссылку на которую я указал в начале, а также в коде демо-приложения на github):

Параметр requiredRecToken требует возвратить токен карты при успешной авторизации карты, а verification — что средства с карты списывать не нужно, а достаточно их заблокировать, а потом вернуть (платежный шлюз возвращает их автоматически).
В ответ платежный шлюз вернет параметры recToken — токен карты, recTokenLifeTime — срок действия токена (по сути срок действия карты) и maskedCard — маскированный номер карты, который необходимо привязать в бекенде к токену для дальнейшего отображения клиенту при выборе способа оплаты.
Теперь, имея токен карты вы можете в любой момент по требованию клиента или при наступлении срока оплаты, вызвать метод списания по токену через server-to-server API и списать необходимую сумму.
Подводные камни:
По нашей статистике у довольно значимой части картодержателей не получается оплатить через 3DSecure на мобильном устройстве по ряду причин, от него и шлюза не зависящих:
— может не приходить SMS, или пользователь переключаясь между SMS-приложением и вашим, потерял форму с вводом пароля 3D-Secure, так как она открывается в WebView или системном браузере
— полезла верстка 3D-Secure страницы банка на смартфоне или планшете (банки очень редко адаптируют такие страницы)
— веб-сервер банка отключил поддержку небезопасного протокола TSL 1.0, что делает 3D-Secure недоступным для Android версии Пример демо-приложения для использования NFC

Источник

In-app purchasing или внутренние платежи в приложениях для Android

О чем это вообще?

С версией приложения Android Market 2.3.0 для разработчиков приложений для платформы Android открылась возможность предоставлять пользователям платежи внутри самих приложений. Теперь можно продавать уровни и артефакты, видео, музыку, плагины и прочее, пользуясь лишь встроенными средствами платформы. Давайте увидим, как это можно сделать.

Что нам понадобится?

Как обычно, любимая IDE, Android SDK и пример приложения.
Так же будет полезным представлять себе, что такое Service, BroadcastReceiver и, конечно, Activity.

Так же нам понадобится разрешение в файле манифеста —

, без него ничего не заработает.

Как это в принципе работает?

Работает все через сервис в приложении Android Market. Он умеет посылать запросы на получение деталей определенной вещи, которую хочет купить пользователь, на покупку, получать ответы о успехе или неудачи покупки, и прочее. Вся информация о вещах, которые вы продаете, должна быть заведена через Консоль Разработчика для конкретного приложения. Как только мы получили сигнал об успешной покупке, мы можем начать грузить с нашего сервера контент.

Как все это устроено?

На сервере в маркете хранится информация о вещах, которые можно купить. С сервером взаимодействует клиентское приложение маркета. С ним взаимодействует наше приложение.

Наше приложение будет состоять как минимум из:

  1. BillingService. Это сервис, который связан с приложением маркета, и отправляет ему всю информацию об операциях и получает на них ответы, в случае, если они синхронные.
  2. BillingReceiver. Получает асинхронные ответы от приложения маркета.
  3. PurchaseObserver. Сущность, которая будет оповещать UI об изменениях состояния покупок.

Какие сообщения мы отсылаем маркету?

Вначале нам нужно соединить наш BillingService с приложением маркета для того, чтобы вызывать метод sendBillingRequest сервиса MarketBillingService. Интерфейс сервиса описан в файле IMarketBillingService.aidl, его можно скачать отсюда, а положить надо в com.android.vending.billing пакет вашего приложения. IDE должна сразу же сгенерить IMarketBillingService.java файл, который нам понадобиться для вызова вышеупомянутого метода.

Сам метод принимает параметр Bundle, в котором и хранится вся информация. Самой важной является параметр с ключом «BILLING_REQUEST». Он определяет тип запроса. Они бывают:

• CHECK_BILLING_SUPPORTED – проверка доступности in-app billing.
• REQUEST_PURCHASE – запрос покупки.
• GET_PURCHASE_INFORMATION – получение информации об изменении состояния покупки.
• CONFIRM_NOTIFICATIONS – подтверждение факта получение уведомления от приложения маркета.
• RESTORE_TRANSACTIONS – восстановление транзакций по уже купленным вещам.

Читайте также:  Onna no ko android

Какие получаем ответы?

Метод синхронно возвращает ответ, который тоже представляет из себя Bundle. В нем лежит:

• RESPONSE_CODE — код ответа
• PURCHASE_INTENT — PendingIntent , для того, чтобы запустить активти покупки.
• REQUEST_ID – идентификатор посланного запроса

В случае асинхронных ответов(получаемых через BillingReceiver), в них лежит следующее:

• com.android.vending.billing.RESPONSE_CODE
Код ответа. Маркет подтверждает успех или неудачу посылки запроса.

• com.android.vending.billing.IN_APP_NOTIFY
Оповещение о том, что статус покупки изменился. После этого сообщения нужно отправлять запрос с типом GET_PURCHASE_INFORMATION , чтобы получить инфу.

• com.android.vending.billing.PURCHASE_STATE_CHANGED
А тут приходит детальная информация о покупке. Она включает в себя nonce, список заказов, с указанием идентификаторов продуктов, их состояний и проч.

Последовательность при покупке будет такая:

1. Посылаем REQUEST_PURCHASE
2. Получаем синхронный ответ
3. Запускаем Activity покупки(также встроенную в приложение маркета)
4. Получаем асинхронное сообщение IN_APP_NOTIFY
5. Посылаем GET_PURCHASE_INFORMATION
6. Получаем синхронный ответ
7. Получаем асинхронный ответ PURCHASE_STATE_CHANGED
8. Отправляем CONFIRM_NOTIFICATIONS
9. Получаем синхронный ответ

А может, посмотрим лучше на код?

Итак, основные моменты в коде:

1. Коннект к маркету.

В onCreate() в BillingService пишем:

try <
boolean bindResult = getApplicationContext().bindService(
new Intent( «com.android.vending.billing.MarketBillingService.BIND» ),
this ,
Context.BIND_AUTO_CREATE);
if (bindResult) <
Log.i(TAG, «Service bind successful.» );
> else <
Log.e(TAG, «Could not bind to the MarketBillingService.» );
>
> catch (SecurityException e) <
Log.e(TAG, «Security exception: » + e);
>

//И чуть ниже:
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) <
Log.i(TAG, «MarketBillingService connected.» );
marketService = IMarketBillingService.Stub.asInterface(iBinder);
runPendingRequests();
>

* This source code was highlighted with Source Code Highlighter .

2. Отправка запросов.

В примере приложения создана иерархия классов для запросов и это правильно. Самая главная вещь в них – это отложенная отправка. Дело в том, что bindService происходит асинхронно, а значит ссылку на MarketBillingService мы получаем гораздо позже, чем кончается onCreate(), и даже позже, чем пытаемся в первый раз выполнить запросы. Поэтому делаем так:

/**
* Run the request, starting the connection if necessary.
*
* @return this request if the request was not executed in order to queue it.
*/
public final AbstractRequest runRequest() <
if (runIfConnected()) <
return null ;
>
return this ;
>

/**
* Try running the request directly if the service is already connected.
*
* @return true if the request ran successfully; false if the service
* is not connected or there was an error when trying to use it
*/
public boolean runIfConnected() <
if (service.isConnected()) <
try <
requestId = run();
if (requestId >= 0) <
service.addRequest(requestId, this );
>
return true ;
> catch (MyException e) <
onException(e);
>
>
return false ;
>

* This source code was highlighted with Source Code Highlighter .

Возвращение запроса нужно, чтобы запомнить его в списке ожидающих отправки запросов в сервисе. Потом, когда мы получим ссылку на MarketBillingService в onServiceConnected(), мы все запросы попробуем отправить еще раз.

3. Оповещение UI

В BillingService будем хранить ссылку на некую сущность, которая хранит в себе Handler от нашего UI. Тогда по получении ответов можно будет делать следующее:

private void notifyGui( int messageId, PurchasedItem item) <
if (observer != null ) <
observer.notifyGui(messageId, item);
> else <
// пошлем здесь оповещение в NotificationBar
>
>

* This source code was highlighted with Source Code Highlighter .

Важно: не забывать обнулять observer сервиса из своей Activity при выходе из нее и восстанавливать эту ссылку. Делается это так:

@Override
protected void onUserLeaveHint() <
if (billingService != null ) <
unbindService( this );
billingService.resetEventDispatcher();
billingService = null ;
>
super.onUserLeaveHint();
>

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) <
//Connected to BillingService
if (componentName.getShortClassName().equals(serviceClassName)) <
billingService = ((BillingService.LocalBinder) iBinder).getService();
billingService.setObserver( new PurchaseObserver());
try <
billingService.checkBillingAvailability();
> catch (MyException e) <
Log.e(TAG, «Billing unavailable» , e);
Toast.makeText( this , «Billing unavailable» , Toast.LENGTH_LONG).show();
>
>
>

* This source code was highlighted with Source Code Highlighter .

4. Запуск Activity покупки.

Загляните в PurchaseObserver класс примера. Там есть метод public void startBuyPageActivity(PendingIntent pendingIntent, Intent intent). PendingIntent – это то, что мы получили ответом от маркета. А Intent – просто new Intent().
Что же этот метод делает?
На самом деле в этот класс передается инстанс вашей Activity. Дальше от нее через reflection происходит попытка получить метод startInstentSender. Этот метод появился только в Android 2.0. Если он есть, то метод вызывается, и Activity запускается в стеке Activity нашего приложения. Если же метод не найден, то происходит старт Activity в отдельном стеке.

А как же безопасность?

Вопрос безопасности – тема отдельной статьи, и так уже много. В примере приложения за безопасность отвечает класс Security. Скажу только, что верифицировать покупки нужно не в приложении(как это сделано в примере), а на собственном сервере, дабы не давать логику проверки в руки потенциальных обладателей apk.

Источник

Оцените статью