- PVSM.RU - https://www.pvsm.ru -
iMessage в свежих версиях iOS научился работать со сторонними расширениями. Например, теперь можно добавлять котиков к сообщениям или даже переводить кому-то деньги без дополнительных реквизитов. Это же мечта лентяя — отправлять деньги не выходя из мессенджера, поэтому разработка Яндекс.Денег засела за реализацию.
При разработке модной магии без квестов не обошлось, ведь iMessage практически ничего не рассказывает о получателе сообщения. Нет ни номера кошелька, ни ФИО, ни хотя бы статичного ID. Но мы придумали способ узнать об адресате все необходимое для отправки денег.
… ведь есть «родное» приложение Яндекс.Денег, где нужно только указать номер кошелька получателя. На это можно ответить встречным вопросом: а почему бы не реализовать упрощенный механизм, который не будет требовать от пользователя знания номера кошелька и переключений между приложениями в процессе перевода денег?
Или можно ответить еще короче — потому что люди этого хотят, а мы это можем.
… и никаких вопросов в духе «какой у тебя номер кошелька?», «куда перевести деньги?».
И тут начинается самое интересное. Apple ответственно относится к защите персональных данных, поэтому расширение iMessage практически ничего не знает о вашем собеседнике. Более того, оно не получит от iOS даже ваш собственный телефонный номер, что не позволяет реализовать перевод «в лоб» с запросом номера кошелька у платежного сервиса Яндекс.Денег по каким-то уникальным признакам абонента iMessage.
Раз от iMessage никакой конкретики не получить, придется действовать в обход. Например, можно обмениваться необходимой информацией в виде сервисных фоновых сообщений. Чтобы было понятнее, разберем все это в коде на примере с основным приложением Яндекс.Денег и нашим расширением для iMessage.
Разумеется, все описанное далее можно использовать и в других сценариях или приложениях, не обязательно ограничиваться переводами.
В первую очередь нужно наладить обмен данными между iMessage и основным приложением, для чего Яндекс.Деньги включили в App Groups:
// Общие user defaults:
let appGroupUserDefaults = NSUserDefaults(suiteName: "com.bundle.group") // Путь к общим ресурсам — нужен для доступа к общей базе данных
let appGroupDirectoryPath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "com.bundle.group")
После этого для iMessage-расширения открывается доступ к списку пользовательских параметров NSUserDefaults и локальной базе данных приложения. Добавим еще Keychain Sharing для доступа к хранилищу Keychain мобильных Яндекс.Денег — там хранится платежный токен:
Для переводов наверняка потребуется показ отдельных экранов приложения с предварительно заполненной информацией, поэтому очень кстати оказалась заранее реализованная в мобильных Яндекс.Деньгах обработка собственных URL-схем. Это позволило открывать нужное окно программы прямо из iMessage простым переходом по определенному URL. На этом приготовления заканчиваются, и можно переходить к настройке сообщений.
Для создания интерактивных сообщений используем класс MSMessage, в котором задаем внешний вид нового элемента через свойство layout:
let layout = MSMessageTemplateLayout()
layout.image = UIImage(named: "moneyTransfer")
layout.caption = "$(conversation.localParticipantIdentifier.uuidString) хочет отправить деньги"
message.layout = layout
Такой получился интерфейс переводов в сообщении.
Для большей кастомизации в MSMessage можно задать свою картинку, текстовые поля и URL.
В любой беседе iMessage собеседники представлены абстрактными идентификаторами UUID вида «154D1B67-FF3B-40E2-AB53-49DD127BB1FA». По UUID можно понять число собеседников в чате или использовать его для получения читаемых имен пользователей в текстовых полях.
Например, мы можем добавить текстовое описание в новое сообщение, в котором система заменит UUID на имя отправителя:
let newMessage = MSMessage(session: activeConversation.selectedMessage.session)
newMessage.summaryText = "$(conversation.localParticipantIdentifier.uuidString) перевел (amount) ₽"
…
conversation.insert(newMessage)
Можно подумать, что UUID уникален во всей сети iMessage и за ним всегда прячется один и тот же собеседник, но это было бы слишком просто. В действительности UUID отличается на каждом устройстве одного и того же пользователя, а также создается заново при переустановке приложения, к которому привязано расширение. Поэтому для точной идентификации пользователя и понимания, что «отсюда» платеж точно выполнен, мы решили использовать UID Яндекс-аккаунта.
Как мы уже знаем, экземпляры класса MSMessage (сообщения) могут содержать множественные текстовые данные, которые кодируются в одном веб-адресе:
http://yamoney.ru?account=1234567&amount=100&comment=за%20пиццу
Такой строкой мы сразу сообщаем номер счета получателя, сумму перевода и пояснение для пользователя. Если в сообщении использовать URL-схему HTTP или HTTPS, то этот адрес будет открываться в браузере macOS с переходом на мобильный веб-интерфейс Яндекс.Денег. В iOS вместо этого вызывается соответствующее расширение.
Потом мы решили хранить всю текстовую информацию в объекте JSON, закодированном в base64:
"?data= TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdC…"
Использование JSON позволяет избежать длинных неудобных URL, а также добавляет универсальности и экономит трафик. Таким образом, сбор необходимой для перевода информации выполняется с помощью сервисных сообщений с закодированными URL.
Сначала вы отправляете Иннокентию сообщение, что хотите сделать перевод через интерфейс расширения Яндекс.Денег. Из полезной информации в этом сообщении только сумма перевода и комментарий.
{
"status": "created", // Статус сообщения
"amount": "1000", // Сумма платежа
"senderId": "dc47160234144e198baa62a3e5edafe5", // Яндекс аккаунт отправителя сообщения
"text": "Возврат долга" // Комментарий к переводу
}
Иннокентий тапает по сообщению и у него тоже открывается iMessage-расширение с предложением принять перевод. В ответное сообщение от Иннокентия добавляется номер его электронного кошелька в Яндекс.Деньгах, если он авторизован в основном приложении. Если же нет, с помощью URL-схемы расширение вызывает окно приложения для авторизации.
{
"status": "accepted",
"amount": "1000",
"to": "4100145388962", // Номер Яндекс кошелька Иннокентия
"senderId": "af865bc2575a803dc9726e876f6ee23f", // Яндекс аккаунт Иннокентия
"text": "Возврат долга"
}
Подтверждение платежа.
Как только Иннокентий согласится на перевод, можно отправлять деньги. Если вы уже авторизованы в приложении, откроется экран ввода ПИН-кода. С его помощью расширение iMessage расшифрует платежный токен их Keychain-приложения, после чего проведет с его помощью платеж. Подробнее про API Яндекс.Денег можно почитать в специальном разделе справки [1].
{
"status": "paid",
"amount": "1000",
"to": "4100145388962",
"senderId": "dc47160234144e198baa62a3e5edafe5",
"text": "Возврат долга"
}
Подтверждение ПИНом и экран успеха.
Когда нужно собрать деньги с нескольких участников беседы в iMessage, инициатор создает сообщение с одной суммой для каждого получателя, в котором содержится номер целевого кошелька. Получателям остается только тапнуть на сообщение и подтвердить перевод по уже знакомому нам алгоритму.
В отличие от большинства проектов Яндекс.Денег, над интерфейсом платежного расширения работали в первую очередь программисты. Отчасти из интереса, отчасти из желания быстрее выкатить первую версию платежного расширения для внутреннего теста. Вопреки расхожему мнению, вышло очень даже неплохо. По крайней мере, UX-дизайнеров возмутил только подбор цветов, которые и были заменены на те, что вы видите на скриншотах.
Вообще, на момент первых разработок платежного расширения под iMessage фреймворк был довольно сырым, из-за чего приходилось бороться с разного рода диссонансами:
Вот тут выяснилось, что «из коробки» расширение не очень дружит в альбомной ориентацией.
А этот пример вообще самый любимый — впервые на iOS диагональный интерфейс.
Раз уж мы коснулись интерфейсов, то подробнее остановимся на особенностях работы с GUI расширениями iMessage.
Основным View Controller для расширения является наследуемый от MSMessagesAppViewController класс, который и отображает интерфейс при активации расширения. Если же мы хотим отобразить другие view controller, то обычные вызовы present или push тут не сработают — необходимо накладывать контроллеры вручную.
Для этого мы написали небольшое расширение к классу UIViewController:
extension UIViewController {
func presentChild(_ controller: UIViewController) {
addChildViewController(controller)
controller.view.frame = view.bounds
view.addSubview(controller.view)
controller.didMove(toParentViewController: self)
}
func dismissChild() {
willMove(toParentViewController: nil)
view.removeFromSuperview()
removeFromParentViewController()
}
}
Вспомогательной функцией основного контроллера можно назвать слежение за жизненным циклом расширения, для чего используются переопределяемые методы наподобие UIApplicationDelegate.
Для расширения Яндекс.Денег мы обошлись тремя из них:
class MessagesViewController: MSMessagesAppViewController {
override func willBecomeActive(with conversation: MSConversation) {
super.willBecomeActive(with: conversation)
// Скрываем кнопку перевода, если это групповой чат. Иначе получится, что перевод получит тот, кто первый его подтвердит.
transferButton.isHidden = conversation.remoteParticipantIdentifiers.count > 1
}
override func willSelect(_ message: MSMessage, conversation: MSConversation) {
super.willSelect(message, conversation: conversation)
// При нажатии на сообщение открываем экран подходящий для его отображения
present(message: message)
}
override func willTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
super.willTransition(to: presentationStyle)
// При смене формата отображения расширения меняем отображаемый view controller
switch presentationStyle {
case .compact: presentChild(selectViewController)
case .expanded: present(message: activeConversation.selectedMessage)
}
}
...
}
Из заслуживающих внимания особенностей построения интерфейса на этом, пожалуй, все.
Наш сценарий можно использовать не только для переводов денег, но и в других сферах, где нужно узнать какую-то информацию об адресате. К примеру, расширения iMessage можно приспособить для удобного обмена контактами из социальных сетей или для рассылки индивидуальных приглашений на какое-либо мероприятие.
Какие еще платежные фишки, по-вашему, могут быть полезны в мессенджере?
Автор: Яндекс.Деньги
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/razrabotka-pod-ios/248689
Ссылки в тексте:
[1] специальном разделе справки: https://tech.yandex.ru/money/doc/dg/concepts/About-docpage/
[2] Источник: https://habrahabr.ru/post/323520/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.