CiphertextProcessor.swift 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. //
  2. // CiphertextProcessor.swift
  3. // NotificationServiceExtension
  4. //
  5. // Created by huangfeng on 2024/5/29.
  6. // Copyright © 2024 Fin. All rights reserved.
  7. //
  8. import Foundation
  9. import SwiftyJSON
  10. /// 加密推送
  11. class CiphertextProcessor: NotificationContentProcessor {
  12. func process(identifier: String, content bestAttemptContent: UNMutableNotificationContent) async throws -> UNMutableNotificationContent {
  13. var userInfo = bestAttemptContent.userInfo
  14. guard let ciphertext = userInfo["ciphertext"] as? String else {
  15. return bestAttemptContent
  16. }
  17. // 如果是加密推送,则使用密文配置 bestAttemptContent
  18. do {
  19. var map = try decrypt(ciphertext: ciphertext, iv: userInfo["iv"] as? String)
  20. var alert = [String: Any]()
  21. var soundName: String? = nil
  22. if let title = map["title"] as? String {
  23. bestAttemptContent.title = title
  24. alert["title"] = title
  25. }
  26. if let body = map["body"] as? String {
  27. bestAttemptContent.body = body
  28. alert["body"] = body
  29. }
  30. if let group = map["group"] as? String {
  31. bestAttemptContent.threadIdentifier = group
  32. }
  33. if var sound = map["sound"] as? String {
  34. if !sound.hasSuffix(".caf") {
  35. sound = "\(sound).caf"
  36. }
  37. soundName = sound
  38. bestAttemptContent.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: sound))
  39. }
  40. if let badge = map["badge"] as? Int {
  41. bestAttemptContent.badge = badge as NSNumber
  42. }
  43. var aps: [String: Any] = ["alert": alert]
  44. if let soundName {
  45. aps["sound"] = soundName
  46. }
  47. map["aps"] = aps
  48. userInfo = map
  49. bestAttemptContent.userInfo = userInfo
  50. return bestAttemptContent
  51. } catch {
  52. bestAttemptContent.body = "Decryption Failed"
  53. bestAttemptContent.userInfo = ["aps": ["alert": ["body": bestAttemptContent.body]]]
  54. throw NotificationContentProcessorError.error(content: bestAttemptContent)
  55. }
  56. }
  57. /// 解密文本
  58. /// - Parameters:
  59. /// - ciphertext: 密文
  60. /// - iv: iv 如果不传就用配置保存的,传了就以传的 iv 为准
  61. /// - Returns: 解密后的 json 数据
  62. private func decrypt(ciphertext: String, iv: String? = nil) throws -> [AnyHashable: Any] {
  63. guard var fields = CryptoSettingManager.shared.fields else {
  64. throw "No encryption key set"
  65. }
  66. if let iv = iv {
  67. // Support using specified IV parameter for decryption
  68. fields.iv = iv
  69. }
  70. let aes = try AESCryptoModel(cryptoFields: fields)
  71. let json = try aes.decrypt(ciphertext: ciphertext)
  72. guard let data = json.data(using: .utf8), let map = JSON(data).dictionaryObject else {
  73. throw "JSON parsing failed"
  74. }
  75. var result: [AnyHashable: Any] = [:]
  76. for (key, val) in map {
  77. // 将key重写为小写
  78. result[key.lowercased()] = val
  79. }
  80. return result
  81. }
  82. }