feat: 增加门店身份注销流程
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
import Foundation
|
||||
import CoreFoundation
|
||||
|
||||
/// 本机提交意图记录,不代表后端已受理或任何注销业务状态。
|
||||
protocol StoreAccountDeregistrationSubmissionTracking {
|
||||
/// 是否存在本机尚无法确定结果的提交意图。
|
||||
var hasUnresolvedSubmission: Bool { get }
|
||||
/// 在发出 POST 前记录意图;无法记录时不允许发出申请。
|
||||
func recordSubmissionIntent(previousStatus: StoreAccountDeregistrationStatus?) throws
|
||||
/// 仅在服务端明确拒绝本次申请时清除此意图。
|
||||
func clearRejectedSubmission()
|
||||
/// 用新撤销记录核销提交意图;与重新申请前相同的旧撤销响应不能放行。
|
||||
func clearCancelledSubmission(matching status: StoreAccountDeregistrationStatus) -> Bool
|
||||
}
|
||||
|
||||
/// 按环境和门店用户 ID 隔离提交意图;不按手机号保存,不存储凭证、验证码或资产。
|
||||
final class StoreAccountDeregistrationSubmissionStore: StoreAccountDeregistrationSubmissionTracking {
|
||||
private let defaults: UserDefaults
|
||||
private let key: String
|
||||
|
||||
/// 注入持久化容器便于测试;生产环境使用当前服务域名隔离测试/正式账号。
|
||||
init(storeUserID: String, environment: APIEnvironment = .current, defaults: UserDefaults = .standard) {
|
||||
self.defaults = defaults
|
||||
key = "store_deregister_submission_intent_v1_\(environment.baseURL.host ?? "unknown")_\(storeUserID)"
|
||||
}
|
||||
|
||||
/// 任何残留记录都按待核实处理,不因不认识的本地值而允许重新提交。
|
||||
var hasUnresolvedSubmission: Bool { defaults.object(forKey: key) != nil }
|
||||
|
||||
/// UserDefaults 记录提交意图;不把本地写入成功等同于后端收到申请。
|
||||
func recordSubmissionIntent(previousStatus: StoreAccountDeregistrationStatus? = nil) throws {
|
||||
defaults.set(["previous_cancellation": previousStatus?.cancellationFingerprint ?? ""], forKey: key)
|
||||
guard hasUnresolvedSubmission else { throw SubmissionPersistenceError.unavailable }
|
||||
}
|
||||
|
||||
/// 只删除当前环境、当前门店用户对应的意图,不影响其他身份。
|
||||
func clearRejectedSubmission() { defaults.removeObject(forKey: key) }
|
||||
|
||||
/// 旧版本只会从无记录/草稿提交,其布尔意图可由完整撤销记录核销。
|
||||
func clearCancelledSubmission(matching status: StoreAccountDeregistrationStatus) -> Bool {
|
||||
guard let fingerprint = status.cancellationFingerprint else { return false }
|
||||
if let stored = defaults.object(forKey: key) {
|
||||
if let record = stored as? [String: String], let previous = record["previous_cancellation"] {
|
||||
guard previous != fingerprint else { return false }
|
||||
} else {
|
||||
// 仅兼容旧版本写入的 true;损坏或未知结构继续等待核验。
|
||||
guard let value = stored as? NSNumber,
|
||||
CFGetTypeID(value) == CFBooleanGetTypeID(), value.boolValue else { return false }
|
||||
}
|
||||
}
|
||||
defaults.removeObject(forKey: key)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/// 无法保存提交意图时阻止申请,避免在重启后失去重复提交保护。
|
||||
private enum SubmissionPersistenceError: LocalizedError {
|
||||
case unavailable
|
||||
var errorDescription: String? { "无法保存提交核验记录,请稍后重试" }
|
||||
}
|
||||
Reference in New Issue
Block a user