![](https://habrastorage.org/getpro/habr/upload_files/4cd/1eb/8cc/4cd1eb8cc9095b83cb1d432378c39efd.gif)
Конечно, нельзя называть Apple Pay анонимным в принципе, хотя бы потому что к ней привязана наша банковская карта. Однако, в момент оплаты что о нас узнаёт продавец? Какие наши персональные данные получает продавец от Apple Pay? Можно ли избежать передачи данных и, тем самым, сделать оплату анонимной в глазах продавца?
Когда мы полагаем, что оплачиваем через Apple Pay, то можем заблуждаться. В зависимости от того что мы приобретаем, используется один из двух механизмов Apple. При покупке любой материальной услуги действительно применяется Apple Pay. Однако, когда мы приобретаем цифровой контент в экосистеме Apple, применяется In-App Purchase. Заказываете Uber через Apple Pay? Верно, это Apple Pay. Оформляете подписку в Apple Music? Это уже In-App Purchase.
Ниже мы рассказываем, какие данные утекают продавцу при оплате внутри приложений. Мы не стали разбирать ситуацию, когда товар оплачивается через POS-терминал, так как она требует отдельного внимания.
![Визуально оба механизма очень похожи, но “под капотом” все иначе. Визуально оба механизма очень похожи, но “под капотом” все иначе.](https://habrastorage.org/getpro/habr/upload_files/ca7/e77/c8d/ca7e77c8d2bcd03c8f5dbca1fc53893b.png)
![](https://habrastorage.org/getpro/habr/upload_files/ab5/3c9/e98/ab53c9e98cc290d8298a9020b30e8a81.png)
In-App Purchase
Как уже было сказано выше, данный механизм оплаты используется только для цифрового контента. Электронные книги в Amazon Kindle, дополнительное пространство в Dropbox, скины в PUBG - это всё примеры цифрового контента.
При анализе In-App Purchase выяснилось, что мы анонимны перед продавцом. Некоторая информация о нас все же передается продавцу, но в обезличенном виде. Если мы купим неприличную книгу в LitRes, то разработчики приложения не узнают, что именно мы её приобрели. При условии, что мы не поделились с приложением личной информацией иным путем.
Какие данные передаются продавцу
Ниже представлена таблица, где мы видим какие данные In-App Purchase передает продавцу.
In-App Purchase | Как предотвратить передачу? |
Дата первой установки приложения | Никак |
Список всех сделанных покупок | Никак |
Биллинговая ошибка на стороне клиента (не хватает денег, карта неактивна) | Никак |
Дата первой установки приложения
Можно определить, когда мы первый раз скачали приложение, даже если удалим сейчас, но скачаем заново через пол года.
Список всех сделанных покупок
По сути, только дата покупки и что за продукт был приобретен.
Биллинговая ошибка на стороне клиента
Если мы оформим автовозобновляемую подписку, а потом на карте закончатся деньги или карта будет неактивной, то разработчик узнает об этом.
Технические подробности
Спойлер
Приложение предлагает пользователю какой-то контент.
Пользователь инициирует процесс покупки.
Приложение показывает ему окно для совершения транзакции.
После подтверждения приложение какое-то время думает.
Контент предоставлен.
В это время в приложении происходит целая череда событий. Большая часть из них скрыта внутри самой операционной системы, а именно системной библиотеки StoreKit. В результате покупки разработчик получит специальную строку receipt
.
Пример receipt
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
receipt
нужен для того, чтобы приложение смогло проверить, действительно ли пользователь совершил эту покупку. Обычно приложение передает эту строку на свой бекенд, а тот - в Apple, чтобы проверить покупку. Apple в ответ на запрос пришлет JSON. Он то нам и нужен:
{
"receipt": {
"receipt_type": "ProductionSandbox",
"adam_id": 0,
"app_item_id": 0,
"bundle_id": "com.belive.app.ios",
"application_version": "3",
"download_id": 0,
"version_external_identifier": 0,
"receipt_creation_date": "2018-11-13 16:46:31 Etc/GMT",
"receipt_creation_date_ms": "1542127591000",
"receipt_creation_date_pst": "2018-11-13 08:46:31 America/Los_Angeles",
"request_date": "2018-11-13 17:10:31 Etc/GMT",
"request_date_ms": "1542129031280",
"request_date_pst": "2018-11-13 09:10:31 America/Los_Angeles",
"original_purchase_date": "2013-08-01 07:00:00 Etc/GMT",
"original_purchase_date_ms": "1375340400000",
"original_purchase_date_pst": "2013-08-01 00:00:00 America/Los_Angeles",
"original_application_version": "1.0",
"in_app": [{
"quantity": "1",
"product_id": "test2",
"transaction_id": "1000000472106082",
"original_transaction_id": "1000000472106082",
"purchase_date": "2018-11-13 16:46:31 Etc/GMT",
"purchase_date_ms": "1542127591000",
"purchase_date_pst": "2018-11-13 08:46:31 America/Los_Angeles",
"original_purchase_date": "2018-11-13 16:46:31 Etc/GMT",
"original_purchase_date_ms": "1542127591000",
"original_purchase_date_pst": "2018-11-13 08:46:31 America/Los_Angeles",
"is_trial_period": "false"
}]
},
"status": 0,
"environment": "Sandbox"
}
Оба примера взяты со StackOverflow.
Чтобы определить дату первой установки, в JSON необходимо найти поле original_purchase_date. Это просто дата, когда приложение было скачано тем самым iTunes аккаунтом, через который совершается покупка.
Поле in_app даст информацию о почти всех покупках, совершенных с этого iTunes аккаунта. Почти, потому что в нем не хранится информация о всех consumable покупках, только о текущей (как в примере выше). Consumable покупки - это покупки, которые можно совершать любое число раз, например, наборы монеток или кристаллов, за которые в приложении можно купить что-то. Все остальные покупки будут всегда храниться в этом поле. Причем, что интересно, если мы сделаем возврат покупки через Apple, то это действие также отобразится в этом массиве. То есть, когда мы в следующий раз придем покупать или восстанавливать покупку, разработчик может узнать не только как часто мы покупаем, но и как часто отменяем покупку.
О нехватке баланса на карте можно будет узнать только в случае продления автовозобновляемой подписки. Эту информацию можно получить через App Store Server Notifications. Это система нотификаций от App Store, на которую подписывается бекенд и может обрабатывать разного рода сообщения. В конкретном случае нас интересует событие DID_FAIL_TO_RENEW
Apple Pay
Просто напомню, что Apple Pay предназначен для материальных товаров и услуг. Примерами могут быть: доставка еды в UberEATS, аренда дома в Airbnb, авиабилеты в Skyscanner.
Исследование Apple Pay показало нам, что продавец однозначно понимает, кто у него покупает товар/услугу. Мы полностью открыты в глазах продавца. Можно ограничить доступ к некоторой информации о себе, но кардинально ситуацию не изменить.
Какие данные передаются продавцу
Ниже представлена таблица, где мы видим какие данные Apple Pay передает продавцу.
До подтверждения оплаты
В момент, когда у нас выскакивает шторка с просьбой подтвердить оплату, продавец уже получает о нас информацию.
Поле | Значение | Как предотвратить передачу? |
Тип карты | Дебетовая/Кредитная | Никак |
Примерный адрес доставки пользователя | Страна, область, город, почтовый индекс | Исказить или убрать в iOS. Настройки iOS → Wallet и Apple Pay → Параметры оплаты по умолчанию |
Примерный платежный адрес пользователя (если не запрошен адрес доставки) | Страна, область, город, почтовый индекс | Исказить или убрать в iOS. Приложение Wallet → Карта → Настройки → Адрес плательщика[1] |
Информация о банке эмитенте карты (при наличии договоренности между разработчиком и банком) | Название банка | Никак |
После подтверждения оплаты
Как только мы подтверждаем оплату с помощью Face ID, Touch ID или пароля, продавец получает новую порцию данных.
Поле | Значение | Как предотвратить передачу? |
Платежная система | Mastercard | Никак |
Название карты с последними символами реальной карты | MasterCard 2780 | Никак |
Точный адрес доставки пользователя | Страна, область, город, почтовый индекс, улица, дом, квартира | До подтверждения оплаты исказить текст в самой шторке |
Точный платежный адрес пользователя | Страна, область, город, почтовый индекс, улица, дом, квартира | Исказить или убрать в iOS. Приложение Wallet → Карта → Настройки → Адрес плательщика[1] |
Имя Фамилия | Иван Иванов | Исказить или убрать в iOS. Находится там же, где и адрес доставки или платежный адрес. |
Номер телефона | +77990001122 | 1. Либо до подтверждения оплаты исказить текст в самой шторке 2. Либо исказить/убрать в iOS. Настройки → Wallet и Apple Pay → Параметры оплаты по умолчанию[2] |
Ivan@gmail.com |
От банка-эквайера
После успешной оплаты продавец может запросить дополнительную информацию о нас. Информация запрашивается у того, кто непосредственно обрабатывает нашу оплату (эквайер).
Поле | Значение | Как предотвратить передачу? |
IP покупателя | 81.18.144.51 | Никак |
Страна банка эмитента | Россия | Никак |
Имя держателя карты | IVAN IVANOV | Никак |
Срок истечения действия карты | 202109 | Никак |
Маскированный номер карты, использованной для оплаты (указывается не реальный номер карты, а токен, который был привязан к устройству) | 520424**0010 | Никак |
Как выглядит подтверждение оплаты
Шторка с подтверждением оплаты может выглядеть по-разному. Все зависит от того, какую информацию о нас запрашивает продавец. Любая запрошенная информация обязательна к заполнению.
![](https://habrastorage.org/getpro/habr/upload_files/5af/37f/9aa/5af37f9aa3023c5e99d62037702369da.png)
Технические подробности
Спойлер
Обратимся к официальной документации и к тестовому приложению и попробуем сделать в нем платеж. Как только приложение показывает окно с суммой и просьбой подтвердить покупку, вызывается метод:
func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void)
Eсли при формировании let paymentRequest = PKPaymentRequest()
еще запросить requiredShippingContactFields
, то вызывается следующее:
func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectShippingContact contact: PKContact, handler completion: @escaping (PKPaymentRequestShippingContactUpdate) -> Void)
Целью этих методов является предоставление разработчикам возможности посчитать стоимость доставки, налогов или сделать скидку пользователям определенных карт. Они то и являются источником данных о типе карты, частичном адресе и информации о банке эмитенте. Если пользователь будет выбирать разные карты или адреса доставки, то эти методы будут вызываться при каждом изменении.
По умолчанию адрес возвращаться не будет, но его можно запросить при показе окна с подтверждением. Сделать это можно, передав в соответствующие поля requiredShippingContactFields
и requiredBillingContactFields
те данные о пользователе, которые мы хотим получить.
let paymentRequest = PKPaymentRequest()
paymentRequest.requiredShippingContactFields = [
.postalAddress,
.name,
.phoneNumber,
.emailAddress
]
paymentRequest.requiredBillingContactFields = [
.postalAddress,
.name,
.phoneNumber,
.emailAddress
]
Стоит отметить, что если запрашивать requiredBillingContactFields
вместе с requiredShippingContactFields
, то billingAddress
не будет возвращаться до подтверждения покупки.
Если запросить только requiredBillingContactFields
, то при выборе карты вызовется метод:
func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void)
Из объекта paymentMethod: PKPaymentMethod
мы получим:
payment.token.paymentMethod.billingAddress givenName nil
payment.token.paymentMethod.billingAddress middleName nil
payment.token.paymentMethod.billingAddress familyName nil
payment.token.paymentMethod.billingAddress
street=,
subLocality=,
city=Москва,
subAdministrativeArea=,
state=Москва,
postalCode=125009,
country=Россия,
countryCode=RU
payment.token.paymentMethod.type 2
А если запросим requiredShippingContactFields
, то из метода didSelectShippingContact
мы получим:
payment.shippingContact email nil
payment.shippingContact name
namePrefix:
givenName:
middleName:
familyName:
nameSuffix:
nickname:
phoneticRepresentation:
givenName:
middleName:
familyName:
payment.shippingContact postalAddress
street=,
subLocality=,
city=Москва,
subAdministrativeArea=,
state=Москва,
postalCode=125009,
country=Россия,
countryCode=RU
payment.shippingContact phoneNumber nil
Пользователь узнает требуются ли эти данные только после того, как окно платежа уже покажется, а данные - уйдут.
Но если пользователь подтвердит покупку - мы получим еще больше:
payment.billingContact
street=Тверская улица 1 123,
subLocality=,
city=Москва,
subAdministrativeArea=,
state=Москва,
postalCode=125009,
country=Россия,
countryCode=RU
Кроме адреса можно запросить еще ФИО, email и номер телефона. Они будут получены после подтверждения оплаты:
payment.shippingContact email ivan@ivanov.ru
payment.shippingContact name
namePrefix:
givenName: Иван
middleName:
familyName: Иванов
nameSuffix:
nickname:
phoneticRepresentation:
givenName: Ivan
middleName:
familyName: Ivanov
payment.shippingContact phoneNumber stringValue=+77990001122
Но email и номер телефона можно получить только в случае запроса адреса доставки. При запросе адреса платежа такая информация не возвращается:
payment.billingContact email nil
payment.billingContact name
namePrefix:
givenName: Иван
middleName:
familyName: Иванов
nameSuffix:
nickname:
phoneticRepresentation:
givenName: Ivan
middleName:
familyName: Ivanov
payment.billingContact phoneNumber nil
Также после подтверждения платежа мы получим последние 4 цифры карты, ее платежную систему и название. Ниже пример такой информации для одной из тестовых карт Apple:
paymentMethod.displayName Discover 2780
payment.token.paymentMethod.network PKPaymentNetwork(_rawValue: Discover)
Чтобы разобраться с тем, что можно получить от эквайера, обратимся к документации Сбербанка
Там много разной информации, но самыми интересными выглядят следующие параметры:
ip
- IP покупателяbankInfo
- наименование страны банка-эмитента, если доступноcardAuthInfo
- данные карты, привязанной к устройствуexpiration
- срок истечения действия картыpan
- маскированный номер картыномер, привязанный к мобильному устройству покупателя и выполняющий функции номера платёжной карты в системе Apple Pay
cardholderName
- имя держателя карты латиницей, если доступно
Примечания
Если адрес не выбран явно, то будет подтягиваться тот, что указан в адресе доставки.
В этих настройках данные могут быть заданы напрямую, либо подтягиваться из карточки контакта из телефонной книги. Если данные были заданы здесь, то в телефонной книге их нельзя будет найти. Если же данные были введены в телефонной книге, то здесь они будут видны, но удалить их можно только через телефонную книгу. Это будет заметно по подписи под email или телефоном (домашний, рабочий и тд) и по тому, что не будет возможности удалить его.