package pay import ( "strings" "yunyan/pb" ) // 订单「来源设备快照」:渠道分成月结算的归属依据。 // // 取值优先级(与前端约定一致): // 1. 客户端下单时带的【当前使用设备】(devicemac 优先,其次 license); // 2. 用户的【最后绑定设备】(userdevice 里最近绑定的一台,等价于 DBUser.Lastbind*, // 但能一并拿到 license/mac); // 3. 都没有 → 只用 DBUser.Lastbind* 里的产品/渠道商,license/mac 留空; // 4. 用户从未绑过设备 → 全空,该订单在结算时归入「无渠道归属」。 // // 快照在下单那一刻冻结进订单行:用户之后换设备、换绑、渠道商停用,都不影响历史订单的归属。 // orderSource 一次下单解析出的来源设备快照。 type orderSource struct { License string Mac string ProductId uint32 BrandId uint32 ChannelId string } // resolveOrderSource 解析订单的来源设备。任何一步查库失败都只是降级,不阻断下单。 func (this *apiComp) resolveOrderSource(uid, devicemac, license string) orderSource { var src orderSource dev := this.lookupOrderDevice(uid, devicemac, license) if dev != nil { src.License = dev.License src.Mac = dev.Devicemac src.ProductId = dev.Productid src.ChannelId = dev.Channelid } // 设备行缺产品/渠道时(老数据),退回用户身上记的最后绑定信息补齐。 if src.ProductId == 0 || src.ChannelId == "" { if u, err := this.module.model.getUser(uid); err == nil && u != nil { if src.ProductId == 0 { src.ProductId = u.Lastbindproductid } if src.ChannelId == "" { src.ChannelId = u.Lastbindchannelid } } } // 品牌商由产品反查(产品表在平台公共库,是品牌商归属的唯一权威)。 if src.ProductId != 0 { if p, err := this.module.model.getProduct(src.ProductId); err == nil && p != nil { src.BrandId = p.Brandid } } return src } // lookupOrderDevice 按优先级定位来源设备行:当前使用设备(mac → license) → 最后绑定设备。 func (this *apiComp) lookupOrderDevice(uid, devicemac, license string) *pb.DBUserDivice { if mac := strings.TrimSpace(devicemac); mac != "" { if dev, err := this.module.model.getUserDeviceByMac(uid, mac); err == nil && dev != nil && dev.Id != 0 { return dev } } if lic := strings.TrimSpace(license); lic != "" { if dev, err := this.module.model.getUserDeviceByLicense(uid, lic); err == nil && dev != nil && dev.Id != 0 { return dev } } // 客户端没带、或带的设备不属于该用户 → 回退最后绑定设备。 if dev, err := this.module.model.getUserLastDevice(uid); err == nil && dev != nil && dev.Id != 0 { return dev } return nil }