17 KiB
Larry的工作内容交接
卡券服务
注:可以结合intergartion guide for third-parties一起阅读关于卡券的内容。
源代码库
https://github.com/iamhubin/loreal.com/tree/master/dit/cmd/coupon-service 目前已经做了转移给 @iamhubin 等待approve
源代码结构
├── Dockerfile 制作编译卡券服务的docker 镜像 ├── app.go app对象,包含卡券服务的一些初始化和各种配置 ├── base │ ├── baseerror.go 卡券服务错误的结构定义 │ ├── baseerror_test.go │ ├── config.default.go 服务的默认配置 │ ├── config.go 服务配置的数据结构 │ ├── lightutils.go 轻量的工具函数 │ ├── lightutils_test.go │ └── requester.go 封装了请求者的信息,比如角色,品牌等 ├── config │ ├── accounts.json 暂未用到,hubin之前的代码遗留 │ └── config.json 程序的运行时配置,将会覆盖默认配置 ├── coupon │ ├── db.coupon.go 卡券服务的dao层 │ ├── db.coupon_test.go │ ├── errors.go 卡券服务的各种错误定义 │ ├── logic.coupon.go 卡券结构的一些方法 │ ├── logic.couponservice.go 卡券服务的一些方法,比如创建卡券,查询卡券,核销卡券 │ ├── logic.couponservice_test.go │ ├── logic.judge.go 规则校验者的定义,如果返回错误,则校验失败。 │ ├── logic.judge_test.go │ ├── logic.rulecomposer.go 签发卡券时,生成卡券的规则体,比如核销有效时间 │ ├── logic.rulecomposer_test.go │ ├── message.go 核销卡券时,可以通知一些相关方核销的信息,这是消息结构。 │ ├── module.coupon.go 卡券以及卡券类型的数据结构 │ ├── module.rule.go 规则以及各个规则细节的结构 │ ├── ruleengine.go 规则引擎,统一调用各个规则体生产规则字符串,以及调用规则校验者校验卡券 │ ├── ruleengine_test.go │ ├── statics.go 一些常量 │ ├── test │ │ ├── coupon_types.json 定义一些卡券类型,用来api测试的。关于api测试,参考后面章节 │ │ └── rules.json 用于单元测试的一些规则 │ └── testbase_test.go ├── data │ ├── data.db 运行时的sqlite数据库(api测试也会用这个数据库) │ └── testdata.sqlite 单元测试时的数据库 ├── db.go 初始化数据库以及每次启动时执行升级脚本 ├── docs │ ├── authorization\ server\ handbook.md 认证服务器手册 │ ├── context\ of\ coupon\ service.md 部署目标服务器的上下文环境 │ ├── go-live\ handbook.md 上线手册 │ ├── intergartion\ guide\ for\ third-parties.md 第三方开发手册 │ └── technical\ and\ functional\ specification.md 卡券服务功能/技术规格 ├── endpoints.debug.go ├── endpoints.gateway.go 暂未涉及,hubin之前的代码遗留 ├── endpoints.go 服务的http入口定义,以及做为api成对一些参数进行校验 ├── logic.db.go 暂未涉及,hubin之前的代码遗留 ├── logic.gateway.go 暂未涉及,hubin之前的代码遗留 ├── logic.gateway.upstream.token.go 暂未涉及,hubin之前的代码遗留 ├── logic.gateway_test.go ├── logic.go 暂未涉及,hubin之前的代码遗留 ├── logic.task.maintenance.go 暂未涉及,hubin之前的代码遗留 ├── main.go 主函数入口,载入资源,程序初始化。 ├── makefile ├── message.go 暂未涉及,hubin之前的代码遗留 ├── model.brand.go 暂未涉及,hubin之前的代码遗留 ├── model.const.go 暂未涉及,hubin之前的代码遗留 ├── model.go 暂未涉及,hubin之前的代码遗留 ├── module.predefineddata.go 因为卡券类型尚未开发,这里hardcode一些初始化的卡券类型数据。 ├── net.config.go 暂未涉及,hubin之前的代码遗留 ├── oauth │ └── oauthcheck.go 校验requester的token ├── pre-defined │ └── predefined-data.json hardcode的卡券类型数据,以及规则数据。 ├── restful 该文件夹下的文件暂未涉及,hubin之前的代码遗留 ├── sql-migrations │ └── init-20191213144434.sql 数据库升级脚本 └── task.register.go 暂未涉及,hubin之前的代码遗留
重要源代码文件列表
endpoints.go
定义了api入口,部分采用了restful风格,方法内会对输入参数进行接口层的校验。
func (a *App) initEndpoints() {
rt := a.getRuntime("prod")
a.Endpoints = map[string]EndpointEntry{
"api/kvstore": {Handler: a.kvstoreHandler, Middlewares: a.noAuthMiddlewares("api/kvstore")},
"api/visit": {Handler: a.pvHandler},
"error": {Handler: a.errorHandler, Middlewares: a.noAuthMiddlewares("error")},
"debug": {Handler: a.debugHandler},
"maintenance/fe/upgrade": {Handler: a.feUpgradeHandler},
"api/gw": {Handler: a.gatewayHandler},
"api/events/": {Handler: longPollingHandler},
"api/coupontypes": {Handler: couponTypeHandler},
"api/coupons/": {Handler: couponHandler},
"api/redemptions": {Handler: redemptionHandler},
"api/apitester": {Handler: apitesterHandler},
}
postPrepareDB(rt)
}
db.go
下面的代码段是打包数据库升级脚本文件以及执行升级脚本的代码。
注意:在mac和windows成功执行了从打包文件中读取脚本,但CentOS没有成功,所以目前是手动拷贝的。
migrations := &migrate.PackrMigrationSource{
Box: packr.New("sql-migrations", "./sql-migrations"),
}
n, err := migrate.Exec(env.db, "sqlite3", migrations, migrate.Up)
sql-migrations/init-20191213144434.sql
这是初始数据库升级脚本。
注意:升级脚本一旦发布,只可增加,不可修改。
pre-defined/predefined-data.json
因为卡券类型模块(用户可以通过api创建卡券类型)尚未开发,所以目前是根据业务的需要hard code卡券类型到这里。代码中的第一个卡券类型是测试用。其他6个是正式的卡券。
coupon/ruleengine.go
创建卡券时,规则引擎将会检查用户是否可以创建,如果可以,这里会生成各种规则体,附加到卡券上。
核销卡券是,规则引擎检查是否可以核销。
coupon/module.rule.go
规则结构,用来描述一个规则,比如核销几次。
coupon/logic.rulecomposer.go
rule composer将会根据卡券类型中配置的规则来生成某个规则的规则体,比如
"REDEEM_TIMES": {
"times": 3
}
表示可以核销3次。
注意,卡券结构中的规则体是json格式字符串。
coupon/logic.judge.go
judge是每个规则的校验者,如果有问题就返回错误。
比如卡券超兑,会返回 ErrCouponRulesRedeemTimesExceeded
{
"error-code": 1006,
"error-message": "coupon redeem times exceeded"
}
coupon/logic.couponservice.go
相当于传统3层架构的业务层,主要处理卡券相关的业务,签发,查询,核销等。
coupon/db.coupon.go
相当于传统3层架构的数据层
base/requester.go
表示api请求者身份的。
重要的数据结构
Rule
rule是描述一个规则,因为尚未开发卡券类型模块,没有对应的数据库表。
这里的结构可以映射为一个数据库表。
其中InternalID是uniqu human readable字符串,比如 REDEEM_TIMES, 表示核销次数规则。
RuleBody是一个json格式的字符串。未来在数据库中应该是一个字符串。
type Rule struct {
ID string `json:"id"`
Name string `json:"name"`
InternalID string `json:"internal_id"`
Description string `json:"description,omitempty"`
RuleBody string `json:"rule_body"`
Creator string `json:"creator"`
CreatedTime time.Time `json:"created_time,omitempty" type:"DATETIME" default:"datetime('now','localtime')"`
UpdatedTime time.Time `json:"updated_time,omitempty" type:"DATETIME"`
DeletedTime time.Time `json:"deleted_time,omitempty" type:"DATETIME"`
}
Template
这是一个卡券的原始模板,品牌可以根据末班创建自己的卡券类型。
Creator是创建者,未来可以用于访问控制。
Rules是一个map,保存若干规则,参见 pre-defined/predefined-data.json
type Template struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Creator string `json:"creator"`
Rules map[string]interface{} `json:"rules"`
CreatedTime time.Time `json:"created_time,omitempty" type:"DATETIME" default:"datetime('now','localtime')"`
UpdatedTime time.Time `json:"updated_time,omitempty" type:"DATETIME"`
DeletedTime time.Time `json:"deleted_time,omitempty" type:"DATETIME"`
}
PublishedCouponType
这是根据Template创建的卡券类型。前台系统可以根据卡券类型签发卡券。
TemplateID是基于卡券模板。
Publisher 发布者,未来可以据此进行访问控制。
StrRules 字符串类型的规则。
Rules是 struct类型的规则,用于系统内部处理业务。
type PublishedCouponType struct {
ID string `json:"id"`
Name string `json:"name"`
TemplateID string `json:"template_id"`
Description string `json:"description"`
InternalDescription string `json:"internal_description"`
State CTState `json:"state"`
Publisher string `json:"publisher"`
VisibleStartTime time.Time `json:"visible_start_time" type:"DATETIME"`
VisibleEndTime time.Time `json:"visible_end_time"`
StrRules map[string]string `json:"rules"`
Rules map[string]map[string]interface{}
CreatedTime time.Time `json:"created_time" type:"DATETIME" default:"datetime('now','localtime')"`
DeletedTime time.Time `json:"deleted_time" type:"DATETIME"`
}
Coupon
描述一个卡券。
CouponTypeID是PublishedCouponType的ID.
请参考intergartion guide for third-parties 了解更多
type Coupon struct {
ID string
CouponTypeID string
ConsumerID string
ConsumerRefID string
ChannelID string
State State
Properties map[string]interface{}
CreatedTime *time.Time
}
Transaction
用户针对卡券做一个操作后,Transaction将描述这一行为。
ActorID是操作者的id。
TransType是操作类型。
ExtraInfo 是操作者附加的信息,用于后期获取后处理前台业务。
type Transaction struct {
ID string
CouponID string
ActorID string
TransType TransType
ExtraInfo string
CreatedTime time.Time
}
重要的接口
TemplateJudge
签发卡券时,验证卡券模板。
// TemplateJudge 发卡券时用来验证是否符合rules
type TemplateJudge interface {
// JudgeTemplate 验证模板
JudgeTemplate(consumerID string, couponTypeID string, ruleBody map[string]interface{}, pct *PublishedCouponType) error
}
Judge
核销卡券时,验证卡券。
// Judge 兑换卡券时用来验证是否符合rules
type Judge interface {
// JudgeCoupon 验证模板
JudgeCoupon(requester *base.Requester, consumerID string, ruleBody map[string]interface{}, c *Coupon) error
}
BodyComposer
签发卡券时,生成规则的规则体,用于附加在卡券上。
// BodyComposer 发卡时生成rule的body,用来存在coupon中
type BodyComposer interface {
Compose(requester *base.Requester, couponTypeID string, ruleBody map[string]interface{}) (map[string]interface{}, error)
}
单元测试
目前代码中针对coupon文件夹下增加了若干单元测试。
知识准备
阅读单元测试,请先了解:
github.com/smartystreets/goconvey/convey 这是一个可以使用易于描述的方式组织单元测试结构。
bou.ke/monkey 这是一个mock方法的第三方库。
运行单元测试
命令行进入 /coupon, 执行
go test -gcflags=-l
因为内联函数的缘故,需要加上 -gcflags=-l
API测试
目前代码中针对coupon相关的api增加了若干测试。
代码路径: https://github.com/iamhubin/loreal.com/tree/master/dit/cmd/api-tests-for-coupon-service
知识准备
阅读API测试,请先了解:
github.com/smartystreets/goconvey/convey 这是一个可以使用易于描述的方式组织单元测试结构。
github.com/gavv/httpexpect 这是一个api调用并且可以验证结果的第三方库。
执行测试
命令行进入 /api-tests-for-coupon-service, 执行
go test
相关文档
请参阅 https://github.com/iamhubin/loreal.com/tree/master/dit/cmd/coupon-service/docs
其他文档
文档压缩包中包含如下几个文件:
| 文件名 | 备注 | |
|---|---|---|
| 02_卡券类型申请表单_入会礼_0224.xlsx | dennis提交的入会礼卡券 | |
| 副本03_客户端申请表单_线上渠道_0219.xlsx | dennis提交的客户端 | |
| 副本05_用户申请表单_Yiyun_0219.xlsx | dennis提交的用户 | |
| 卡券类型申请表单_生日礼_0224.xlsx | dennis提交的生日礼卡券 | |
| 02_Web Application Criticality Determination Form_0219.xlsx | pt测试申请表单 | |
| 03_Penetration Test Request Form_0219.xlsx | pt测试申请表单 | |
| 卡券服务组件架构图.vsdx | 早期文档,用处不大。 | |
| 卡券中心最简MVP实施计划.xlsx | larry个人做了一点记录,用处不大 | |
| CardServiceDBSchema.graphml | 数据库设计,用处不大,建议看代码中的DDL | |
| Loreal卡券服务思维导图.pdf | 早期构思卡券服务功能时的思维导图 | |
| data flow diagram.pdf | pt测试需要的数据流图 | |
| network architecture.pdf | pt测试需要的网络架构图 |
oAuth2认证服务
认证服务采用了https://hub.docker.com/r/jboss/keycloak。
数据库是https://hub.docker.com/_/mysql。
启动服务的关键命令如下:
#创建docker的虚拟网络
sudo docker network create keycloak-network
#启动mysql,注意参数,这不是产线环境参数。
docker run --name mysql -d --net keycloak-network -e MYSQL_DATABASE=keycloak -e MYSQL_USER=keycloak -e MYSQL_PASSWORD=password -e MYSQL_ROOT_PASSWORD=root_password mysql
#启动keycloak,注意参数,这不是产线环境参数。
docker run --name keycloak --net keycloak-network -p 8080:8080 -e KEYCLOAK_USER=yhl10000 -e KEYCLOAK_PASSWORD=Passw0rd jboss/keycloak
如何使用认证服务请参阅:卡券服务-相关文档章节。
开发测试环境
开发测试环境的服务器从兰伯特那边接过来的。
服务地址:https://gua.e-loreal.cn/#/
服务登录方式请询问hubin。
认证服务请docker ps 相关容器。
卡券服务目录: /home/larryyu/coupon-service。
关于目录结构以及相关功能请咨询hubin。
卡券服务测试服务器是否启动请访问:http://52.130.73.180/ceh/cvc/health
认证服务管理入口:http://52.130.73.180/auth/
SIT集成测试环境
SIT集成环境用来给供应商开发测试用。
服务登录方式请询问hubin。
服务器有两台,10.162.66.29 和 10.162.66.30 。
卡券服务器目前只用了一台10.162.66.29,类似开发测试环境,包含了认证和卡券两个服务。服务器登录账号目前用的是arvato的账号 arvatoadmin 密码是:【请询问hubin】
认证服务请docker ps 相关容器。
卡券服务目录: /home/arvatoadmin/coupon-service。
卡券服务测试服务器是否启动请访问:https://dl-api-uat.lorealchina.com/ceh/cvc/health
认证服务管理入口:跳板机内配置bitvise后,浏览器访问 http://10.162.66.29/auth/
PRD产线环境
服务登录方式请询问hubin。
服务器有两台:
10.162.65.217 :认证服务器
10.162.65.218 :卡券服务器
服务器登录账号目前用的是appdmin 密码是:【请询问hubin】
认证服务请docker ps 相关容器。
注意:认证服务数据库在/data1t
卡券服务目录: /home/appadmin/coupon-service。
注意:卡券数据库在/data1t