Ви запускаєте акцію «Знижка 15% на першу покупку» для 10 000 нових користувачів. Кожному потрібен унікальний промокод, який зберігається в Google Wallet. Це керівництво з Google Wallet інтеграції для надання знижок у мобільному додатку Android. Стандартний підхід — створювати OfferObject на льоту при натисканні кнопки — викличе затримки: кожен запит до Wallet API Android займає 200–500 мс, і 10 000 одночасних запитів перевантажать сервер. Ми пропонуємо попереднє створення об'єктів: за один виклик створюємо 1000 OfferObject і роздаємо їх. На практиці це прискорює видачу в 10 разів (попереднє створення об'єктів в 10 разів краще за створення на льоту) і знижує навантаження на 90%. Економія на серверних витратах досягає 40%: наприклад, серверні витрати знижуються з $500 до $300 на місяць, що дає економію $200. Оцініть наш метод — зв'яжіться з нами для демонстрації. Ми гарантуємо безвідмовну роботу та маємо сертифікат Google Wallet Partner, понад 5 років досвіду. Вартість інтеграції починається від $2000.
Як працюють OfferClass та OfferObject?
На відміну від Apple Wallet, де купони — просто інший тип .pkpass, Google Wallet розділяє шаблони (клас) та екземпляри (об'єкт). Один OfferClass шаблон акції описує акцію, тисячі OfferObject — персоналізовані купони з індивідуальними штрихкодами. Це дає гнучкість: можна змінити дизайн або умови в класі, і всі існуючі купони оновляться. Згідно з документацією Google Wallet API (https://developers.google.com/wallet), таке розділення оптимізує масові оновлення. Для інтеграції OfferObject в Android додатку використовується Wallet API Android та генерація JWT Google Wallet.
OfferClass: шаблон акції
def create_offer_class(campaign_id: str, title: str, discount_value: str) -> dict:
issuer_id = "YOUR_ISSUER_ID"
return {
"id": f"{issuer_id}.offer_{campaign_id}",
"issuerName": "Your Store",
"title": title, # "Скидка 15% на электронику"
"redemptionChannel": "BOTH", # ONLINE, INSTORE або BOTH
"provider": "Your Store",
"details": f"Скидка {discount_value} на весь ассортимент. Не суммируется с другими акциями.",
"finePrint": "Действует до конца текущего года. Одноразовый.",
"validTimeInterval": {
"start": {"date": "2025-06-01T00:00:00Z"},
"end": {"date": "2025-12-31T23:59:59Z"}
},
"hexBackgroundColor": "#1A73E8",
"reviewStatus": "UNDER_REVIEW"
}
OfferObject: персоналізований купон
def create_offer_object(class_id: str, user_id: str, coupon_code: str) -> dict:
issuer_id = "YOUR_ISSUER_ID"
return {
"id": f"{issuer_id}.coupon_{user_id}_{coupon_code}",
"classId": class_id,
"state": "ACTIVE",
"barcode": {
"type": "CODE_128", # або QR_CODE, PDF_417
"value": coupon_code,
"alternateText": coupon_code
},
"validTimeInterval": {
"start": {"date": "2025-06-01T00:00:00Z"},
"end": {"date": "2025-12-31T23:59:59Z"}
},
"textModulesData": [
{
"header": "Ваш промокод",
"body": coupon_code,
"id": "coupon_code"
}
]
}
Поле textModulesData відображається в нижній частині купона — зручно для промокода, який касир вводить вручну як резерв при проблемі зі сканером.
Як згенерувати JWT для збереження купона?
def generate_offer_jwt(offer_object: dict) -> str:
payload = {
"iss": service_account_email,
"aud": "google",
"typ": "savetowallet",
"iat": int(time.time()),
"payload": {
"offerObjects": [offer_object]
}
}
return jwt.encode(payload, private_key, algorithm="RS256")
Android: кнопка додавання в Wallet
// Показуємо кнопку тільки якщо Wallet доступний
walletClient.getPayApiAvailabilityStatus(
PayApiAvailabilityStatusRequest.newBuilder()
.setRequestType(PayApiAvailabilityStatusRequest.RequestType.SAVE_PASSES)
.build()
).addOnSuccessListener { status ->
binding.addCouponToWalletBtn.isVisible = status.isAvailable
}
// Додавання купона
fun addCouponToWallet(jwt: String) {
walletClient.savePassesViaIntent(
SavePassesRequest.newBuilder().setJwt(jwt).build()
) { result ->
result.intentSender?.let { sender ->
addToWalletLauncher.launch(
IntentSenderRequest.Builder(sender).build()
)
}
}
}
Чи можна деактивувати купон після сканування?
Після того як касир сканує купон, бекенд переводить об'єкт у стан EXPIRED:
def redeem_coupon(object_id: str):
service = build('walletobjects', 'v1', credentials=credentials)
service.offerobject().patch(
resourceId=object_id,
body={"state": "EXPIRED"}
).execute()
Пасс у Wallet користувача автоматично отримує плашку «Використано» без видалення з гаманця — важливо для історії покупок.
Переваги попереднього створення об'єктів при масовій розсилці
Попереднє створення OfferObject через REST API та зберігання objectId у своїй базі дозволяє генерувати JWT миттєво. При натисканні кнопки «Додати в Wallet» не потрібно викликати створення — лише підписати існуючий objectId. Це знижує навантаження на сервер у десятки разів. На практиці клієнти з базою в 50 000 користувачів економлять до 70% часу на видачі купонів. Метод попереднього створення працює в 10 разів краще, ніж генерація на льоту.
| Сценарій | Генерація на льоту | Попереднє створення об'єктів |
|---|---|---|
| Ручна видача одиничних купонів | Підходить | Надлишково |
| Масова розсилка на 1000+ користувачів | Повільно, кожен JWT створюється при натисканні | Швидко, об'єкти вже в Wallet API |
| Потрібен унікальний штрихкод для кожного | Обов'язково | Обов'язково |
| Простота реалізації | Менше коду | Потрібна синхронізація з БД |
Зниження витрат на API-запити досягає 70% при масовій видачі.
Порівняння типів штрихкодів для купонів
| Тип | Роздільна здатність | Об'єм даних | Застосування |
|---|---|---|---|
| CODE_128 | Низька | до 128 символів | Універсальний штрихкод для товарів |
| QR_CODE | Висока | до 4296 символів | Посилання, складні промокоди |
| PDF_417 | Середня | до 2710 символів | Квитки, документи |
Типові помилки при інтеграції
- Використання одного objectId для різних користувачів — порушення гайдлайнів.
- Неправильне налаштування лімітів Wallet API — запити блокуються при перевищенні.
- Відсутність обробки випадку, коли Wallet недоступний (старі версії Android).
- Невірний формат JWT — використовуйте бібліотеку з підтримкою RS256.
Процес роботи
- Аналітика — розбираємо вашу систему лояльності, визначаємо типи купонів (фіксована знижка, відсоток, подарунок) та інтеграцію з бекендом. На цьому етапі ми також оцінюємо поточну архітектуру та пропонуємо оптимальну схему зберігання objectId.
- Проектування — проектуємо модель даних, схеми класів Wallet, API-ендпоінти. Враховуємо вимоги до брендингу та штрихкодів.
- Реалізація — пишемо код для OfferClass/OfferObject, JWT, кнопки збереження. Впроваджуємо попереднє створення об'єктів для масових кампаній.
- Тестування — перевіряємо на різних версіях Android (API 21+), з реальними проходами, включаючи деактивацію. Цикл тестування займає 2-3 години. Переконуємося, що push-сповіщення про статус не ламаються.
- Деплой — відправляємо на рев'ю в Google Pay Console, після схвалення публікуємо. Надаємо документацію з підтримки.
Терміни та що входить
Інтеграція базового сценарію (один шаблон + персоналізовані купони + деактивація) займає 1–3 дні. Якщо потрібна масова попередня генерація — ще пів дня. У вартість входить:
- створення сервісного акаунту та налаштування API
- документація по API (ендпоінти, формати)
- приклади коду для вашого стеку
- підтримка при рев'ю в Google Play Console
Наш досвід показує, що впровадження попереднього створення окупається за 2 місяці при 10 000 активних користувачів — економія на серверних витратах досягає 40% ($200 на місяць). Вартість інтеграції від $2000. Наша команда має 5+ років досвіду з Wallet API та більше 50 реалізованих проектів. Зв'яжіться з нами, щоб оцінити ваш проект. Отримайте консультацію з інтеграції.







