写点什么

有赞营销逆向域的探索与实践

2020 年 10 月 15 日

有赞营销逆向域的探索与实践

引言


生活中商家经常会遇到这样的问题:订单退款后优惠券没有被回收、退款过程中商家对营销资产没有直观的感知、黑产党尝试薅商家资产羊毛等,给商家造成了不好的体验。为了解决商家的上述难题,我们构建了营销逆向域,负责各种营销资产的逆向操作业务,包括资产的冻结、解冻、回收等能力。


一、业务形态


在一次实际营销场景中,商家设置了一种满 10 元送优惠券的活动,而后消费者下了一笔 20 元的订单得到了一张优惠券,然后申请了订单全额退款,商家希望能回收优惠券;而另一位消费也花了 20 元,只申请 5 元的部分退款,商家表示订单达到了门槛,不打算回收券。这是最基础的一个业务场景,营销逆向域就是处理该券的逆向操作,我们关心触发逆向的条件和对应的营销资产种类。


1.1 营销资产种类


营销资产是指订单满足某些营销活动的门槛后由营销系统发放给消费者的虚拟资产或权益。常见的营销资产有优惠券、优惠码、积分、储值金等;虚拟权益有砍价,助力,抽奖等(消费者在消费后可以获得一定的资格参与其他互动类的活动),各种营销资产的存在有利于促进消费者回购,帮助商家稳定客源,在电商系统中扮演者重要角色。


按虚拟资产的价值属性区分,可分为金本位资产和普通资产。店铺储值就是典型的金本位资产,还有现金红包、京豆等,这类资产的特点是与资金直接挂钩,均可直接用来无门槛消费。而普通资产如优惠券、积分等,本身不与资金直接相关,其营销价值大于资产价值。对于金本位资产的逆向操作会更加严肃一些,普通资产的风险控制更多得由商家去操作。按资产价值区分如下图:



1.2 触发的条件


在买家申请退款时,需要冻结营销资产;买家撤销退款或各种关单场景,需要解冻资产;商家同意退款,退款完成需要回收资产;买家修改退款单时需要看申请金额的变化,来决定冻结还是解冻资产。门槛需要与正向发放的门槛需要保持一致,即不足发放门槛时,需要处理资产。关于冻结解冻回收状态机如下图所示:



在理解触发条件和营销资产后,我们可以构建我们的系统。在整个交易链路中,营销逆向系统在中台的位置处于逆向链路下游,在用户下单行为完成后并且发生退款才会可能涉及,系统特点是流量不高但对计算精准性有很高要求,中台的位置如下图所示:



由产品同学配置好活动的逆向规则,在实际退款执行时按配置的规则执行。下单链路会提供活动的快照信息,包括优惠门槛、发放资产等。营销逆向域依赖于有赞规则引擎,负责底层组件的调用,最终通过发放中心异步操作资产,一次退款的主要业务流程如下图所示:



二、模型构建


为了保持领域层(domain)整洁,只依赖内部的 common 包,依赖层(dependency)和基础设施层(infrastructure)通过依赖倒置的方式依赖于领域层,屏蔽了外围的接口实现。上游应用层(application)以拓展点的形式接入交易系统,处理请求和外部查询。参考 DDD 的规范,我们有如下包结构:



2.1 领域设计


领域模型需要保证高内聚低耦合,有对应的行为支撑模型的属性,以下列举主要的几个模型:


实体(Entity):


  • 商品(goods):包括订单中的商品、活动参与商品和退款商品,具有商品各种计算能力,如判断商品的剩余金额,商品之间各种逻辑关系等。

  • 资产(equity):各类虚拟资产的统一抽象,一般来自正向的快照信息,提供资产操作的行为和各种统计视图。

  • 门槛(conditionTable):抽象活动的发放规则条件,由正向的 snapshot 解析而来。提供通用化的参数转化行为。


值对象(ValueObject):


  • 订单(order):上游交易告知的订单信息,包括订单商品,金额等信息。

  • 退款单(refundOrder):同样由交易产生,包括了申请退款的商品,申请的退款金额,件数以及可退金额等信息。


聚合根(Aggregate):


  • 活动聚合(refundActivity):对门槛、商品和资产实体做一个整体的聚合,抽象成一个退款活动,对外做统一操作,边界清晰。


服务(Service):


  • 在领取层统一提供 refundService 服务,提供三种能力:计算抵扣金额,资产逆向操作以及订单资产信息查询。


上下文(Context):


  • RefundContext:逆向域的上下文信息,包括订单退款单等,在有赞规则引擎中提供上下文服务。



2.2 正逆向领域映射


在开发过程中我们面临这样的问题:正向域产生的优惠快照(snapshot)在逆向域无法被识别,原因是不同领域之间底层数据不互通,使得逆向域解析正向模型时变得十分困难。我们采用模型关系映射的方式,解决不同领域间模型和参数的转化问题。以满 X 条件模型为例,正向模型有两个参数 amountAt 和 amount 分别对应满多少元(件)和实际多少元(件),还有两个 optionBind 绑定条件:amountPrice 和 amountNum 分别表示满多少元和满多少件,这是一个高度抽象灵活的模型,不同参数绑定表示了不同业务含义,但带来了很多问题,比如满多少元和满多少件的业务校验逻辑不同,在流程中除了要关心模型本身是什么更要关心模型绑定的参数,破坏了内聚的原则;再如在用户仅退款退款场景中,是没有件数信息的,存在特殊的产品逻辑。所以在逆向域构建过程中,我们采用含义清晰的积木。实际映射配置如下:


        <identification name="ump.refund.setting.amount.num.resource">            <params>                <param key="amountNum">                    <mapping domain="UMP" meta_id="ump.pbb.condition.amountOver" bind="amountNum"/>                </param>            </params>        </identification>
复制代码


identification标签定义了受体模型, params定义了这个模型下的参数列表, key定义模型下的参数名, mapping定义了参数值的来源,从哪个领域( domain)的哪个模型( meta_id)中取哪个绑定( bind)或者参数( value)。


通过定义模型映射关系,我们可以直接把 A 领域的模型转换成 B 领域的模型(包含参数),省去了业务自己去解析积木,转换参数,再构建的过程,提高开发效率。



三、思考


存在正逆向的门槛条件不同业务需求,比如虽然下单满足指定金额送优惠券,但只要发生退款即回收券,这种情况下逆向的门槛条件高于正向,又或者订单金额全退才回收优惠券等,未来逆向域考虑提供通用的退款模板,只需配置“AtOnce”或者“All”这样的普通条件就可实现条件判断。此外,逆向域作用范围可以再拓展,涉及退款退虚拟资产的业务都可以接入,例如充值储值卡送优惠券,用户退储值账户,也可以接入营销逆向域。最后,金本位资产的逆向流程接入也十分重要。


在逆向域诞生之前,营销活动通过监听退款消息来做逻辑,杂糅在系统各个组件中,非常不利于管理和维护。新系统打散了活动的概念,抽象出各种规则,使退款不再依赖于具体业务,而依赖于各种配置的规则。



结语


本文介绍了营销逆向域的业务形态,以及逆向域的领域实践,解决了资产的逆向回收问题,支持多种退款场景,支持不同业务规则,实现了逆向流程配置化。总体来说,相比于下单域,逆向属于比较稳定的领域,易于收拢业务、方便制定规则、能力可以复用。但在领域设计上还可以更加抽象,未来将更多地与中台其他系统联动,接入更多需求。


本文转载自公众号有赞 coder(ID:youzan_coder)。


原文链接


有赞营销逆向域的探索与实践


2020 年 10 月 15 日 10:00582

评论

发布
暂无评论
发现更多内容

[GitHub] 跟我一起白嫖 GitHub Pages 做个人站点 ?

猴哥一一 cium

git GitHub GitHub Pages

有价值的产品=设计思维+精益创业+敏捷方法

行叔

Scrum 敏捷开发 Agile 设计思维 精益创业

翻译敏捷行业专业外文,不只是谷歌翻译

行叔

翻译 Scrum 敏捷开发 Agile

2020年2月北京BGP机房网络质量评测报告

BonreeAPM

五个“为什么” —— 读《精益创业》

YoungZY

读书笔记

实用贴丨正确的「递归」打开方式:让计算机像计算机一样去计算

博文视点Broadview

Python 递归

Elasticsearch 实战

代码诗人

2020年2月北京BGP机房网络质量评测报告

BonreeAPM

APM 机房 评测 世纪互联

李想解读《高效能人士的七个习惯》

我心依然

习惯 高效能人士的七个习惯 李想 汽车之家

Lean UX 教你设计如何驱动产品

Yanel 说敏捷产品

产品 敏捷 设计

Flutter的staggered GridView详细使用

潘珉

flutter

数仓系列 | Flink 窗口的应用与实现

Apache Flink

大数据 flink 流计算 实时计算 大数据处理

ARTS - Week One

shepherd

js algorithm

一文带你彻底厘清 Kubernetes 中的证书工作机制

首富手记

Kubernetes

软件开发生产率改进之我见(一)

清水

团队管理 软件工程 技术管理

Golang热更新原理

我心依然

golang nginx Linux 信号

面试官问你MyBatis SQL是如何执行的?把这篇文章甩给他

cxuan

mybatis

关于问题的问题 —— 读《你的灯亮着吗?》

YoungZY

读书笔记 读书

游戏夜读 | 如何避免乏味?两则

game1night

python实现·十大排序算法之希尔排序(Shell Sort)

南风以南

Python 排序算法 希尔排序

有点干货 | Jdk1.8新特性实战篇(41个案例)

小傅哥

函数式接口 Lambda 小傅哥 jdk8 编码

Zabbix实战指南

橙子冰

技术 运维 监控 运维自动化 zabbix

内容比形式更重要

Winann

内容 生活 工作 形式主义

RabbitMQ 集群

云淡风轻

读书笔记 RabbitMQ

工厂模式 (一)简单的工厂模式概念以及示例代码

LSJ

Kubectl exec 的工作原理解读

米开朗基杨

Kubernetes kubelet

给学妹的 Java 学习路线

武培轩

Java 学习 程序员 程序媛

学计算机你后悔了吗?

陈辰

学习 技术 前端

[Git] Git 可以这么学

猴哥一一 cium

git

「开放」对协作效率的影响

Tony Wu

产品 产品设计

基于mysqldump聊一聊MySQL的备份和恢复

麦叔

MySQL

NLP领域的2020年大事记及2021展望

NLP领域的2020年大事记及2021展望

有赞营销逆向域的探索与实践-InfoQ