208 lines
6.2 KiB
Swift
208 lines
6.2 KiB
Swift
//
|
|
// PaymentModels.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// 收款页展示配置接口响应。
|
|
struct PayPageConfigResponse: Decodable, Sendable, Equatable {
|
|
let background: String
|
|
let logo: String
|
|
let title: String
|
|
let subtitle: String
|
|
|
|
init(background: String, logo: String, title: String, subtitle: String) {
|
|
self.background = background
|
|
self.logo = logo
|
|
self.title = title
|
|
self.subtitle = subtitle
|
|
}
|
|
}
|
|
|
|
/// 收款页最终可展示并可持久化的品牌配置。
|
|
struct PayPageConfig: Codable, Sendable, Equatable {
|
|
let background: String
|
|
let logo: String
|
|
let title: String
|
|
let subtitle: String
|
|
|
|
/// 那拉提景区随包默认配置。
|
|
static let nalatiDefault = PayPageConfig(
|
|
background: "",
|
|
logo: "",
|
|
title: "那拉提旅拍管理收费平台",
|
|
subtitle: "那拉提景区"
|
|
)
|
|
|
|
/// 赛里木湖景区随包默认文案,图片由展示层选择本地资源。
|
|
static let sailimuDefault = PayPageConfig(
|
|
background: "",
|
|
logo: "",
|
|
title: "赛里木湖旅拍管理\n收费平台",
|
|
subtitle: "赛里木湖景区"
|
|
)
|
|
|
|
/// 将服务端非空有效字段合并到当前可用配置。
|
|
func merging(_ response: PayPageConfigResponse) -> PayPageConfig {
|
|
PayPageConfig(
|
|
background: Self.validRemoteImageURL(response.background) ?? background,
|
|
logo: Self.validRemoteImageURL(response.logo) ?? logo,
|
|
title: response.title.trimmedNonEmpty ?? title,
|
|
subtitle: response.subtitle.trimmedNonEmpty ?? subtitle
|
|
)
|
|
}
|
|
|
|
private static func validRemoteImageURL(_ value: String) -> String? {
|
|
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
guard let url = URL(string: trimmed),
|
|
url.scheme?.lowercased() == "https",
|
|
url.host != nil else {
|
|
return nil
|
|
}
|
|
return trimmed
|
|
}
|
|
}
|
|
|
|
/// 收款页品牌化景区判定策略。
|
|
enum PayPageBrandingPolicy {
|
|
/// 那拉提景区正式 ID。
|
|
static let nalatiScenicId = 128
|
|
|
|
/// 赛里木湖景区正式 ID。
|
|
static let sailimuScenicId = 125
|
|
|
|
/// 判断当前景区是否为那拉提。
|
|
static func isNalati(scenicId: Int) -> Bool {
|
|
scenicId == nalatiScenicId
|
|
}
|
|
|
|
/// 返回支持品牌收款页的景区默认配置;其他景区继续使用普通页面。
|
|
static func defaultConfig(scenicId: Int) -> PayPageConfig? {
|
|
switch scenicId {
|
|
case nalatiScenicId: return .nalatiDefault
|
|
case sailimuScenicId: return .sailimuDefault
|
|
default: return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 收款页当前账号信息的展示文本格式化规则。
|
|
enum PaymentAccountDisplayFormatter {
|
|
/// 解析当前登录摄影师的真实姓名,空值显示占位符。
|
|
static func photographerName(realName: String) -> String {
|
|
realName.trimmedNonEmpty ?? "-"
|
|
}
|
|
|
|
/// 去除空值与重复项后,合并当前账号的全部店铺名称。
|
|
static func storeNames(_ names: [String]) -> String {
|
|
var seen = Set<String>()
|
|
let resolved = names.compactMap(\.trimmedNonEmpty).filter { seen.insert($0).inserted }
|
|
return resolved.isEmpty ? "-" : resolved.joined(separator: "、")
|
|
}
|
|
}
|
|
|
|
/// 摄影师收款码响应,包含静态与动态支付 URL。
|
|
struct PayCodeResponse: Decodable, Sendable, Equatable {
|
|
let staticPayURL: String
|
|
let dynamicPayURL: String
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case staticPayURL = "static_pay_url"
|
|
case dynamicPayURL = "dynamic_pay_url"
|
|
}
|
|
|
|
init(staticPayURL: String, dynamicPayURL: String) {
|
|
self.staticPayURL = staticPayURL
|
|
self.dynamicPayURL = dynamicPayURL
|
|
}
|
|
}
|
|
|
|
/// 收款记录响应,含按日汇总与明细列表。
|
|
struct RepaymentCollectionRecordResponse: Decodable, Sendable, Equatable {
|
|
let analyse: [RepaymentCollectionRecordAnalyseItem]
|
|
let list: [RepaymentCollectionRecordItem]
|
|
|
|
init(
|
|
analyse: [RepaymentCollectionRecordAnalyseItem] = [],
|
|
list: [RepaymentCollectionRecordItem] = []
|
|
) {
|
|
self.analyse = analyse
|
|
self.list = list
|
|
}
|
|
}
|
|
|
|
/// 收款记录按日汇总项。
|
|
struct RepaymentCollectionRecordAnalyseItem: Decodable, Sendable, Equatable, Hashable {
|
|
let date: String
|
|
let orderCount: Int
|
|
let orderAmountSum: String
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case date
|
|
case orderCount = "order_count"
|
|
case orderAmountSum = "order_amount_sum"
|
|
}
|
|
|
|
init(date: String, orderCount: Int, orderAmountSum: String) {
|
|
self.date = date
|
|
self.orderCount = orderCount
|
|
self.orderAmountSum = orderAmountSum
|
|
}
|
|
}
|
|
|
|
/// 收款记录明细项。
|
|
struct RepaymentCollectionRecordItem: Decodable, Sendable, Equatable, Hashable {
|
|
let orderNumber: String
|
|
let userPhone: String
|
|
let orderAmount: String
|
|
let createDate: String
|
|
let createTime: String
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case orderNumber = "order_number"
|
|
case userPhone = "user_phone"
|
|
case orderAmount = "order_amount"
|
|
case createDate = "create_date"
|
|
case createTime = "create_time"
|
|
}
|
|
|
|
init(
|
|
orderNumber: String,
|
|
userPhone: String,
|
|
orderAmount: String,
|
|
createDate: String,
|
|
createTime: String
|
|
) {
|
|
self.orderNumber = orderNumber
|
|
self.userPhone = userPhone
|
|
self.orderAmount = orderAmount
|
|
self.createDate = createDate
|
|
self.createTime = createTime
|
|
}
|
|
}
|
|
|
|
/// 按日分组的收款记录,对齐 Android `RepaymentCollectionRecordGroup`。
|
|
struct RepaymentCollectionRecordGroup: Sendable, Equatable, Hashable {
|
|
let analyse: RepaymentCollectionRecordAnalyseItem
|
|
let items: [RepaymentCollectionRecordItem]
|
|
}
|
|
|
|
/// 收款商户展示信息。
|
|
struct PaymentMerchantInfo: Sendable, Equatable {
|
|
let name: String
|
|
let company: String
|
|
|
|
static let defaultInfo = PaymentMerchantInfo(
|
|
name: "元智享",
|
|
company: "扬州元智享网络科技有限公司"
|
|
)
|
|
}
|
|
|
|
private extension String {
|
|
var trimmedNonEmpty: String? {
|
|
let value = trimmingCharacters(in: .whitespacesAndNewlines)
|
|
return value.isEmpty ? nil : value
|
|
}
|
|
}
|