- Вопрос или проблема
- Ответ или решение
- Проектирование Масштабируемой Системы Реферальных Кодовых для Приложения iOS/Swift с Использованием Firebase
- Введение
- Архитектура Системы
- 1. Пользовательские Реферальные Коды
- 2. Бонусы за Рефералы и Ведение Учетов
- 3. Использование Безопасных Правил Firestore
- 4. Интеграция Уведомлений
- 5. Хранение Изображений Пользователей
- Заключение
Вопрос или проблема
Я разрабатываю приложение для iOS, используя Swift и Firebase, и ищу способ реализовать надежную реферальную систему. Основные требования к реферальной системе:
Коды рефералов пользователей: У каждого пользователя должен быть уникальный реферальный код, который он может делиться с другими.
Бонусы за рефералы: Когда пользователь использует реферальный код другого пользователя, как текущий пользователь, так и пригласивший пользователь должны получить бонус в кредиты (например, по 5 кредитов каждому).
Награды за рефералы: Пользователь, пригласивший, должен накапливать «награды за рефералы», которые отслеживают количество успешных рефералов, которые они сделали.
Безопасные обновления данных: Реферальная система должна быть разработана в соответствии с лучшими практиками безопасности Firebase Firestore, обеспечивая, что пользователи могут обновлять только свои данные и не обходить правила.
Система уведомлений: Когда реферальный код пользователя используется, пользователь-пригласитель должен получать push-уведомление, информирующее его об успешном реферале и полученном бонусе в кредитах.
Хранение изображений профиля пользователей: Пользователи должны иметь возможность загружать изображения профиля, которые должны храниться в Firebase Storage.
Я уже добился определенного прогресса в реализации реферальной системы, и привел соответствующий код ниже:
func generateAndSaveReferralCode(userId: String) async throws -> String {
let code = String(UUID().uuidString.prefix(8)).uppercased()
try await db.collection("users").document(userId).setData([
"referralCode": code,
"referralRewards": 0,
"lastUpdated": FieldValue.serverTimestamp()
], merge: true)
return code
}
func processReferralCode(_ code: String, currentUserId: String) async throws {
let currentUserRef = db.collection("users").document(currentUserId)
do {
// Получаем документ текущего пользователя
let currentUserDoc = try await currentUserRef.getDocument()
guard let currentUserData = currentUserDoc.data() else {
throw ReferralError.invalidCode
}
// Проверяем, был ли уже использован реферал
if currentUserData["usedReferralCode"] as? Bool == true {
throw ReferralError.alreadyUsedReferral
}
// Проверяем, используется ли собственный код
if currentUserData["referralCode"] as? String == code {
throw ReferralError.cannotUseSelfCode
}
// Получаем информацию о пригласившем
let referrerQuery = db.collection("users")
.whereField("referralCode", isEqualTo: code)
.limit(to: 1)
let referrerDocs = try await referrerQuery.getDocuments()
guard let referrerDoc = referrerDocs.documents.first else {
throw ReferralError.invalidCode
}
let referrerData = referrerDoc.data()
let referrerId = referrerDoc.documentID
// Получаем текущие значения
let currentCredits = currentUserData["creditBalance"] as? Int ?? 0
let currentReferralRewards = currentUserData["referralRewards"] as? Int ?? 0
// Обновляем данные текущего пользователя
try await currentUserRef.updateData([
"creditBalance": currentCredits + 5,
"usedReferralCode": true,
"referredByCode": code,
"referralRewards": currentReferralRewards + 1,
"lastUpdated": FieldValue.serverTimestamp()
])
// Обновляем данные реферера
let referrerRef = db.collection("users").document(referrerId)
try await referrerRef.updateData([
"creditBalance": (referrerData["creditBalance"] as? Int ?? 0) + 5,
"referralRewards": (referrerData["referralRewards"] as? Int ?? 0) + 1,
"lastUpdated": FieldValue.serverTimestamp()
])
// Создаем транзакции по кредитам
let batch = db.batch()
let timestamp = FieldValue.serverTimestamp()
// Транзакция текущего пользователя
let currentUserTransactionRef = db.collection("creditTransactions").document()
batch.setData([
"userId": currentUserId,
"amount": 5,
"type": "received_referral",
"timestamp": timestamp,
"status": "completed"
], forDocument: currentUserTransactionRef)
// Транзакция реферера
let referrerTransactionRef = db.collection("creditTransactions").document()
batch.setData([
"userId": referrerId,
"amount": 5,
"type": "referral_bonus",
"timestamp": timestamp,
"status": "completed"
], forDocument: referrerTransactionRef)
try await batch.commit()
// Отправляем уведомление пользователю-пригласителю
await sendReferralNotification(to: referrerId, forCurrentUser: currentUserData)
} catch {
throw error
}
// Уведомляем управляющего кредитами
DispatchQueue.main.async {
NotificationCenter.default.post(name: .creditsDidChange, object: nil)
}
}
private func sendReferralNotification(to referrerId: String, forCurrentUser currentUserData: [String: Any]) async {
let referrerRef = db.collection("users").document(referrerId)
do {
// Получаем данные реферера
let referrerDoc = try await referrerRef.getDocument()
guard let referrerData = referrerDoc.data() else {
return
}
// Подготавливаем данные для уведомления
let notificationData: [String: Any] = [
"referrerName": referrerData["displayName"] ?? "Друг",
"currentUserName": currentUserData["displayName"] ?? "Вы",
"creditAmount": 5,
"referralRewards": (referrerData["referralRewards"] as? Int ?? 0) + 1
]
// Отправляем push-уведомление рефереру
let message = Messaging.messaging().newSendableMessage(withData: notificationData)
try await Messaging.messaging().send(message)
} catch {
print("Ошибка при отправке уведомления о реферале: \(error.localizedDescription)")
}
}
Я столкнулся с несколькими проблемами при реализации этой реферальной системы:
Правила безопасности Firebase Firestore: Мне трудно найти правильный баланс между разрешением пользователям обновлять свои данные (например, баланс кредитов, реферальный код, изображение профиля), и предотвращением изменения данных других пользователей.
Атомарность обновления кредитов: Мне нужно убедиться, что обновление кредитов как для текущего пользователя, так и для реферера происходит атомарно, чтобы один пользователь не упустил бонус.
Интеграция push-уведомлений: Я не уверен, как лучше интегрировать систему push-уведомлений с реферальным потоком, учитывая также аспекты безопасности.
Интеграция с Firebase Storage: Я хотел бы понять лучшие практики для хранения и извлечения изображений профиля пользователей в Firebase Storage и как защитить доступ к этим ресурсам.
Может кто-то предоставить рекомендации о том, как разработать масштабируемую и безопасную реферальную систему, используя Firebase для приложения iOS/Swift? Я открыт для архитектурных паттернов, подходов к дизайну и конкретных примеров кода, которые могли бы помочь решить возникающие проблемы.
Буду очень признателен за любую помощь!
Ответ или решение
Проектирование Масштабируемой Системы Реферальных Кодовых для Приложения iOS/Swift с Использованием Firebase
Введение
Создание масштабируемой реферальной системы для iOS приложения с использованием Firebase включает в себя ряд ключевых аспектов. Данная система должна поддерживать уникальные реферальные коды, бонусы для пользователей, защиту данных и интеграцию уведомлений. В этом руководстве мы рассмотрим лучшие практики проектирования такой системы, а также ответим на ваши конкретные вопросы.
Архитектура Системы
1. Пользовательские Реферальные Коды
Каждый пользователь вашего приложения должен иметь уникальный реферальный код. Для генерации таких кодов можно использовать функцию, аналогичную следующей:
func generateUniqueReferralCode() -> String {
return String(UUID().uuidString.prefix(8)).uppercased()
}
Этот код гарантирует уникальность, автоматизируя процесс генерации.
2. Бонусы за Рефералы и Ведение Учетов
Когда пользователь использует реферальный код другого пользователя, необходимо обновить учетные записи обеих сторон. Для этого лучше использовать транзакции, чтобы обеспечить атомарность обновления данных:
let batch = db.batch()
// Обновление данных текущего пользователя
batch.updateData(["creditBalance": newCreditBalanceCurrent], forDocument: currentUserRef)
// Обновление данных реферера
batch.updateData(["creditBalance": newCreditBalanceReferrer], forDocument: referrerRef)
try await batch.commit()
Таким образом, мы гарантируем, что данные обновятся одновременно, предотвращая ситуации, когда один пользователь может потерять свой бонус.
3. Использование Безопасных Правил Firestore
Чтобы обеспечить безопасность данных в Firebase Firestore, используйте правила, которые позволят пользователям изменять только свои данные. Пример правил:
match /users/{userId} {
allow read, write: if request.auth.uid == userId;
}
Эти правила гарантируют, что пользователи смогут изменять только свою информацию.
4. Интеграция Уведомлений
Интеграция системы пуш-уведомлений может быть выполнена с использованием Firebase Cloud Messaging (FCM). Для отправки уведомлений рефереру, необходимо сделать это после успешного обновления данных пользователя:
private func sendReferralNotification(to referrerId: String) {
let notification = [
"to": referrerId,
"notification": [
"title": "Новый реферал!",
"body": "Вы получили бонус за реферал."
]
]
// Отправка уведомления через FCM
...
}
5. Хранение Изображений Пользователей
Для хранения пользовательских изображений рекомендуется использовать Firebase Storage. Чтобы обеспечить безопасность, необходимо создать правила для доступа к изображениям:
service firebase.storage {
match /b/{bucket}/o {
match /profileImages/{imageId} {
allow read, write: if request.auth.uid != null && request.auth.uid == imageId;
}
}
}
Это позволит пользователям загружать и загружать только свои изображения.
Заключение
Проектирование масштабируемой реферальной системы с использованием Firebase для iOS приложения требует учета различных аспектов: от безопасности данных до интеграции уведомлений. Применение предоставленных методов и рекомендаций поможет вам создать надежную и безопасную систему.
Если у вас возникли дальнейшие вопросы или потребность в подробной помощи, не стесняйтесь обращаться за дополнительной информацией. Удачи с вашим проектом!