diff --git a/config.yaml.sample b/config.yaml.sample index 2c6c1ae1..a3df0dd9 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -56,7 +56,7 @@ SmsJuhe: Gateway: https://v.juhe.cn/sms/send Key: TplID: - TplVal: "#code#=%d&#m#=%d" + TplVal: "#code#=%s&#m#=%d" Alipay: AppID: InProduction: True diff --git a/docs/README.md b/docs/README.md index d2c7b192..fda64147 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,3 +4,4 @@ * [openapi](openapi): api相关文档 * [proposal](proposal): 开发/设计 提按相关文档 * [deploy](deploy): 部署相关文档 +* [discuss](discuss): 开发者交流 diff --git a/docs/deploy/README.md b/docs/deploy/README.md index a870fd7b..cedbe93f 100644 --- a/docs/deploy/README.md +++ b/docs/deploy/README.md @@ -1,2 +1,9 @@ ## 部署文档 -TODO \ No newline at end of file +本目录包含一些paopao-ce部署相关的帮助文档 + +* [core](./core) - paopao-ce部署帮助文档 +* [aliyun](./aliyun) - Aliyun平台部署文档 +* [huawei](./huawei) - Huawei Cloud平台部署文档 +* [tencnet](./tencent) - Tencent Cloud平台部署文档 +* [local](./local) - 本地部署文档 +* [k8s](./k8s) - 使用Kubernetes部署paopao-ce相关文档 diff --git a/docs/deploy/aliyun/README.md b/docs/deploy/aliyun/README.md new file mode 100644 index 00000000..bae5e98a --- /dev/null +++ b/docs/deploy/aliyun/README.md @@ -0,0 +1,2 @@ +### Aliyun平台部署文档 +本目录包含一些阿里云平台部署paopao-ce的一些帮助文档。 diff --git a/docs/deploy/core/001-配置文件说明.md b/docs/deploy/core/001-配置文件说明.md new file mode 100644 index 00000000..b1af7e2b --- /dev/null +++ b/docs/deploy/core/001-配置文件说明.md @@ -0,0 +1,95 @@ +### 配置文件说明 +paopao-ce使用YAML格式的`conf.yml`作为配置文件。[`config.yaml.sample`](../../../config.yaml.sample) 是一份完整的配置文件模版,paopao-ce启动时会读取`./custom/config.yaml`、`./config.yaml`任意一份配置文件(优先读取最先找到的文件)。 + +```sh +cp config.yaml.sample config.yaml +vim config.yaml # 修改参数 +paopao-ce +``` + +配置文件中的 `Features` 小节是声明paopao-ce运行时开启哪些功能项: + +```yaml +... + +Features: + Default: ["Base", "MySQL", "Option", "LocalOSS", "LoggerFile"] + Develop: ["Base", "MySQL", "Option", "Sms", "AliOSS", "LoggerZinc"] + Demo: ["Base", "MySQL", "Option", "Sms", "MinIO", "LoggerZinc"] + Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile"] + Base: ["Zinc", "Redis", "Alipay",] + Option: ["SimpleCacheIndex"] + Sms: "SmsJuhe" + +... +``` + +如上: +Default/Develop/Demo/Slim 是不同 功能集套件(Features Suite), Base/Option 是子功能套件, Sms是关于短信验证码功能的参数选项。 + +这里 `Default`套件 代表的意思是: 使用`Base/Option` 中的功能,外加 `MySQL/LocalOSS/LoggerFile`功能,也就是说开启了`Zinc/Redis/Alipay/SimpleCacheIndex/MySQL/LocalOSS/LoggerFile` 7项功能; +`Develop`套件依例类推。 + +使用Feautures: + +```sh +release/paopao-ce --help +Usage of release/paopao-ce: + -features value + use special features + -no-default-features + whether use default features + +# 默认使用 Default 功能套件 +release/paopao-ce + +# 不包含 default 中的功能集,仅仅使用 develop 中声明的功能集 +release/paopao-ce --no-default-features --features develop + +# 使用 default 中的功能集,外加 sms 功能 +release/paopao-ce --features sms + +# 手动指定需要开启的功能集 +release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,redis +``` + +目前支持的功能集合: +| 功能项 | 类别 | 状态 | 备注 | +| ----- | ----- | ----- | ----- | +|`OldWeb` | 子服务 | 稳定(默认) | 开启旧的Web服务 | +|`Web` | 子服务 | WIP | 开启Web服务| +|`Admin` | 子服务 | WIP | 开启Admin后台运维服务| +|`SpaceX` | 子服务 | WIP | 开启SpaceX服务| +|`Bot` | 子服务 | WIP | 开启Bot服务| +|`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务| +|`Deprecated:Web` | 子服务 | 稳定 | Deprecated(关闭) OldWeb服务| +|`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM,默认使用 `Gorm` + `MySQL`组合| +|`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM| +|`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库| +|`Postgres`| 数据库 | 稳定 | 使用PostgreSQL作为数据库| +|`Sqlite3`| 数据库 | 稳定 | 使用Sqlite3作为数据库| +|`AliOSS` | 对象存储 | 稳定(推荐) |阿里云对象存储服务| +|`COS` | 对象存储 | 内测 |腾讯云对象存储服务| +|`HuaweiOBS` | 对象存储 | 内测 |华为云对象存储服务| +|`MinIO` | 对象存储 | 稳定 |[MinIO](https://github.com/minio/minio)对象存储服务| +|`S3` | 对象存储 | 内测 |AWS S3兼容的对象存储服务| +|`LocalOSS` | 对象存储 | 内测 |提供使用本地目录文件作为对象存储的功能,仅用于开发调试环境| +|`OSS:Retention` | 对象存储 | 内测 |基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能| +|`OSS:TempDir` | 对象存储 | 内测 |基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能| +|`Redis` | 缓存 | 稳定 | Redis缓存功能 | +|`SimpleCacheIndex` | 缓存 | 稳定 | 提供简单的 广场推文列表 的缓存功能 | +|`BigCacheIndex` | 缓存 | 稳定(推荐) | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 | +|`Zinc` | 搜索 | 稳定(推荐) | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 | +|`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 | +|`Bleve` | 搜索 | WIP | 基于[Bleve](https://github.com/blevesearch/bleve)搜索引擎提供推文搜索服务 | +|`LoggerFile` | 日志 | 稳定 | 使用文件写日志 | +|`LoggerZinc` | 日志 | 稳定(推荐) | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 | +|`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 | +|`Friendship` | 关系模式 | 内测(默认) | 弱关系好友模式,类似微信朋友圈 | +|`Followship` | 关系模式 | WIP | 关注者模式,类似Twitter的Follow模式 | +|`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 | +|`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 | +|`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能,提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) | +|`PhoneBind` | 其他 | 稳定 | 手机绑定功能 | + +> 功能项状态详情参考 [features-status](../../../features-status.md). diff --git a/docs/deploy/core/README.md b/docs/deploy/core/README.md new file mode 100644 index 00000000..fc82b4c2 --- /dev/null +++ b/docs/deploy/core/README.md @@ -0,0 +1,4 @@ +### paopao-ce部署帮助文档 +本目录包含一些部署paopao-ce的一些帮助文档。 + +* [001-配置文件说明](./001-配置文件说明.md '001-配置文件说明') diff --git a/docs/deploy/huawei/README.md b/docs/deploy/huawei/README.md new file mode 100644 index 00000000..8052deaf --- /dev/null +++ b/docs/deploy/huawei/README.md @@ -0,0 +1,2 @@ +### Huawei Cloud平台部署文档 +本目录包含一些华为云平台部署paopao-ce的一些帮助文档。 diff --git a/docs/deploy/k8s/README.md b/docs/deploy/k8s/README.md new file mode 100644 index 00000000..e3b23686 --- /dev/null +++ b/docs/deploy/k8s/README.md @@ -0,0 +1,2 @@ +### 使用Kubernetes部署paopao-ce相关文档 +本目录包含一些k8s环境部署paopao-ce的一些帮助文档。 diff --git a/docs/deploy/local/001-本地开发依赖环境部署.md b/docs/deploy/local/001-本地开发依赖环境部署.md new file mode 100644 index 00000000..9fd293f4 --- /dev/null +++ b/docs/deploy/local/001-本地开发依赖环境部署.md @@ -0,0 +1,119 @@ +### 本地开发依赖环境部署 +本地开发依赖的环境部署帮助文档,包括Zinc/Meili/Minio的部署。 + +#### [Zinc](https://github.com/zinclabs/zinc) 搜索引擎: +* Zinc运行 +```sh +# 创建用于存放zinc数据的目录 +mkdir -p data/zinc/data + +# 使用Docker运行zinc +docker run -d --name zinc --user root -v ${PWD}/data/zinc/data:/data -p 4080:4080 -e ZINC_FIRST_ADMIN_USER=admin -e ZINC_FIRST_ADMIN_PASSWORD=admin -e DATA_PATH=/data public.ecr.aws/zinclabs/zinc:latest + +# 查看zinc运行状态 +docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +41465feea2ff getmeili/meilisearch:v0.27.0 "tini -- /bin/sh -c …" 20 hours ago Up 20 hours 0.0.0.0:7700->7700/tcp paopao-ce-meili-1 +7daf982ca062 public.ecr.aws/prabhat/zinc:latest "/go/bin/zinc" 3 weeks ago Up 6 days 0.0.0.0:4080->4080/tcp zinc + +# 使用docker compose运行 +docker compose up -d zinc +# visit http://localhost:4080 打开自带的ui管理界面 +``` + +* 修改Zinc配置 +```yaml +# features中加上 Zinc 和 LoggerZinc +Features: + Default: ["Zinc", "LoggerZinc", "Base", "Sqlite3", "BigCacheIndex","MinIO"] +... +LoggerZinc: # 使用Zinc写日志 + Host: 127.0.0.1:4080 # 这里的host就是paopao-ce能访问到的zinc主机 + Index: paopao-log + User: admin + Password: admin + Secure: False # 如果使用https访问zinc就设置为True +... +Zinc: # Zinc搜索配置 + Host: 127.0.0.1:4080 + Index: paopao-data + User: admin + Password: admin + Secure: False +``` + +#### [Meilisearch](https://github.com/meilisearch/meilisearch) 搜索引擎: +* Meili运行 +```sh +mkdir -p data/meili/data + +# 使用Docker运行 +docker run -d --name meili -v ${PWD}/data/meili/data:/meili_data -p 7700:7700 -e MEILI_MASTER_KEY=paopao-meilisearch getmeili/meilisearch:v0.29.0 +# visit http://localhost:7700 打开自带的搜索前端ui + +# 使用docker compose运行,需要删除docker-compose.yaml中关于meili的注释 +docker compose up -d meili + +# 使用docker运行meilisearch的ui管理前端 +docker run -d --name uirecord -p 7701:3000 bitriory/uirecord +# visit http://localhost:7701 + +# 使用docker compose运行meilisearch的ui管理前端,需要删除docker-compose.yaml中关于uirecord的注释 +docker compose up -d uirecord +# visit http://loclahost:7701 + +# 查看meili运行状态 +docker compose ps +NAME COMMAND SERVICE STATUS PORTS +paopao-ce-meili-1 "tini -- /bin/sh -c …" meili running 0.0.0.0:7700->7700/tcp +paopao-ce-uirecord-1 "docker-entrypoint.s…" uirecord running 0.0.0.0:7701->3000/tcp +``` + +* 修改Meili配置 +```yaml +# features中加上 Meili 和 LoggerMeili +Features: + Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex","MinIO"] +... +LoggerMeili: # 使用Meili写日志 + Host: 127.0.0.1:7700 + Index: paopao-log + ApiKey: paopao-meilisearch + Secure: False + MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 + MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 +... +Meili: # Meili搜索配置 + Host: 127.0.0.1:7700 # 这里的host就是paopao-ce能访问到的meili主机 + Index: paopao-data + ApiKey: paopao-meilisearch + Secure: False # 如果使用https访问meili就设置为True +``` + +#### [MinIO](https://github.com/minio/minio) 对象存储服务 +* MinIO运行 +```sh +mkdir -p data/minio/data + +# 使用Docker运行 +docker run -d --name minio -v ${PWD}/data/minio/data:/data -p 9000:9000 -p 9001:9001 -e MINIO_ROOT_USER=minio-root-user -e MINIO_ROOT_PASSWORD=minio-root-password -e MINIO_DEFAULT_BUCKETS=paopao:public bitnami/minio:latest + +# 使用docker compose运行, 需要删除docker-compose.yaml中关于minio的注释 +docker compose up -d minio +``` + +* 修改Minio配置 +```yaml +# features中加上 MinIO +Features: + Default: ["MinIO", "Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex"] +... +MinIO: # MinIO 存储配置 + AccessKey: Q3AM3UQ867SPQQA43P2F # AccessKey/SecretKey 需要登入minio管理界面手动创建,管理界面地址: http://127.0.0.1:9001 + SecretKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG + Secure: False + Endpoint: 127.0.0.1:9000 # 根据部署的minio主机修改对应地址 + Bucket: paopao # 如上,需要在管理界面创建bucket并赋予外部可读写权限 + Domain: 127.0.0.1:9000 # minio外网访问的地址(如果想让外网访问,这里需要设置为外网可访问到的minio主机地址) +... +``` \ No newline at end of file diff --git a/docs/deploy/local/README.md b/docs/deploy/local/README.md new file mode 100644 index 00000000..a04b93e1 --- /dev/null +++ b/docs/deploy/local/README.md @@ -0,0 +1,4 @@ +### 本地部署文档 +本目录包含一些本地开发环境部署paopao-ce的一些帮助文档。 + +* [001-本地开发依赖环境部署](001-本地开发依赖环境部署.md '001-本地开发依赖环境部署') diff --git a/docs/deploy/tencent/README.md b/docs/deploy/tencent/README.md new file mode 100644 index 00000000..4674183d --- /dev/null +++ b/docs/deploy/tencent/README.md @@ -0,0 +1,2 @@ +### Tencent Cloud平台部署文档 +本目录包含一些腾讯云平台部署paopao-ce的一些帮助文档。 diff --git a/docs/discuss/0000-讨论样式模版.md b/docs/discuss/0000-讨论样式模版.md new file mode 100644 index 00000000..a7e50871 --- /dev/null +++ b/docs/discuss/0000-讨论样式模版.md @@ -0,0 +1,26 @@ +### <主题标题> +====== <这里写主题描述> ===== + +#### <话题标题> +====== <这里写话题描述> ===== +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的回复 + >> 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 你的回复 + >> 这里就是你的回复 + >>> 这里就是你的观点论述了 + diff --git a/docs/discuss/0001-FAQs.md b/docs/discuss/0001-FAQs.md new file mode 100644 index 00000000..83fb01e9 --- /dev/null +++ b/docs/discuss/0001-FAQs.md @@ -0,0 +1,19 @@ +### FAQs 常见问题 +一些常见问题的解答。 + + +#### 为什么要在代码库[docs](../../docs/)中写开发文档,比如[proposal](../proposal/)提按文档? +* [北野](https://alimy.me) - 2022/12/14 10:20 + > 这里有几个原因 + > * 开发文档跟随代码库对开发者友好; + > * paopao-ce的开发是离散组织式开发,代码寄存在GitHub,并没有一个统一的开发平台; + > * 为什么没有使用GitHub的Wiki写档?这个后续会把一些文档Copy到WiKi。 + > * 文档跟随代码,将更好的与代码共存,而且Markdown足够用于写文档,这才是最核心的,怎么简单怎么来。 + + +#### 为什么要在代码库[docs](../../docs/)中包含一个[discuss](../discuss/)?难道没有其他可用工具更好完成这种工作吗,比瑞slack/discord? +* [北野](https://alimy.me) - 2022/12/14 10:32 + > discuss目录包含一些关于代码库开发的一些方案讨论,偏静态内容,代码库内置这些方案讨论,也便于git进行跟踪归档。 + > 确实有其他一些社交类开发聊天工具可用,比如slack/discord,但是目前paopao-ce的开发者社区还比较小,暂时还没有开通的必要。 +* [北野](https://alimy.me) - 2022/12/14 10:50 + > 再一个国内访问也不是特别方便,暂时采用目前这种土办法过渡一下,或许后期会选择一个社交平台供开发者交流,比如飞书~ diff --git a/docs/discuss/README.md b/docs/discuss/README.md new file mode 100644 index 00000000..3b983ca6 --- /dev/null +++ b/docs/discuss/README.md @@ -0,0 +1,5 @@ +### Discuss 开发者交流 +本目录包含一些开发相关的问题交流论述。 + +* [0000-讨论样式模版](./0000-讨论样式模版.md "讨论样式模版") +* [0001-FAQs](./0001-FAQs.md "FAQs") diff --git a/internal/core/security.go b/internal/core/security.go index 81a428af..ce313635 100644 --- a/internal/core/security.go +++ b/internal/core/security.go @@ -5,6 +5,8 @@ package core import ( + "time" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" ) @@ -19,7 +21,12 @@ type SecurityService interface { SendPhoneCaptcha(phone string) error } -// 附件检测服务 +// AttachmentCheckService 附件检测服务 type AttachmentCheckService interface { CheckAttachment(uri string) error } + +// PhoneVerifyService 手机验证服务 +type PhoneVerifyService interface { + SendPhoneCaptcha(phone string, captcha string, expire time.Duration) error +} diff --git a/internal/dao/jinzhu/jinzhu.go b/internal/dao/jinzhu/jinzhu.go index dd20aeea..f708e064 100644 --- a/internal/dao/jinzhu/jinzhu.go +++ b/internal/dao/jinzhu/jinzhu.go @@ -46,6 +46,7 @@ func NewDataService() (core.DataService, core.VersionInfo) { v core.VersionInfo ) db := conf.MustGormDB() + pvs := security.NewPhoneVerifyService() i := newIndexPostsService(db) if cfg.If("SimpleCacheIndex") { @@ -71,7 +72,7 @@ func NewDataService() (core.DataService, core.VersionInfo) { CommentManageService: newCommentManageService(db), UserManageService: newUserManageService(db), ContactManageService: newContactManageService(db), - SecurityService: newSecurityService(db), + SecurityService: newSecurityService(db, pvs), AttachmentCheckService: security.NewAttachmentCheckService(), } return ds, ds diff --git a/internal/dao/jinzhu/security.go b/internal/dao/jinzhu/security.go index 49f66074..69fc57d4 100644 --- a/internal/dao/jinzhu/security.go +++ b/internal/dao/jinzhu/security.go @@ -5,18 +5,12 @@ package jinzhu import ( - "errors" - "fmt" "math/rand" - "net/http" "strconv" "time" - "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" - "github.com/rocboss/paopao-ce/pkg/json" - "gopkg.in/resty.v1" "gorm.io/gorm" ) @@ -25,71 +19,46 @@ var ( ) type securityServant struct { - db *gorm.DB + db *gorm.DB + phoneVerify core.PhoneVerifyService } -func newSecurityService(db *gorm.DB) core.SecurityService { +func newSecurityService(db *gorm.DB, phoneVerify core.PhoneVerifyService) core.SecurityService { return &securityServant{ - db: db, + db: db, + phoneVerify: phoneVerify, } } -type juhePhoneCaptchaRsp struct { - ErrorCode int `json:"error_code"` - Reason string `json:"reason"` -} - -// 获取最新短信验证码 +// GetLatestPhoneCaptcha 获取最新短信验证码 func (s *securityServant) GetLatestPhoneCaptcha(phone string) (*core.Captcha, error) { return (&dbr.Captcha{ Phone: phone, }).Get(s.db) } -// 更新短信验证码 +// UsePhoneCaptcha 更新短信验证码 func (s *securityServant) UsePhoneCaptcha(captcha *core.Captcha) error { captcha.UseTimes++ return captcha.Update(s.db) } -// 发送短信验证码 +// SendPhoneCaptcha 发送短信验证码 func (s *securityServant) SendPhoneCaptcha(phone string) error { - rand.Seed(time.Now().UnixNano()) - captcha := rand.Intn(900000) + 100000 - m := 5 - - client := resty.New() - client.DisableWarn = true - resp, err := client.R(). - SetFormData(map[string]string{ - "mobile": phone, - "tpl_id": conf.SmsJuheSetting.TplID, - "tpl_value": fmt.Sprintf(conf.SmsJuheSetting.TplVal, captcha, m), - "key": conf.SmsJuheSetting.Key, - }).Post(conf.SmsJuheSetting.Gateway) - if err != nil { - return err - } + expire := time.Duration(5) - if resp.StatusCode() != http.StatusOK { - return errors.New(resp.Status()) - } - - result := &juhePhoneCaptchaRsp{} - err = json.Unmarshal(resp.Body(), result) - if err != nil { + // 发送验证码 + rand.Seed(time.Now().UnixNano()) + captcha := strconv.Itoa(rand.Intn(900000) + 100000) + if err := s.phoneVerify.SendPhoneCaptcha(phone, captcha, expire); err != nil { return err } - if result.ErrorCode != 0 { - return errors.New(result.Reason) - } - // 写入表 captchaModel := &dbr.Captcha{ Phone: phone, - Captcha: strconv.Itoa(captcha), - ExpiredOn: time.Now().Add(time.Minute * time.Duration(m)).Unix(), + Captcha: captcha, + ExpiredOn: time.Now().Add(expire * time.Minute).Unix(), } captchaModel.Create(s.db) return nil diff --git a/internal/dao/security/attachment.go b/internal/dao/security/attachment_check.go similarity index 89% rename from internal/dao/security/attachment.go rename to internal/dao/security/attachment_check.go index 706621ac..aa077aca 100644 --- a/internal/dao/security/attachment.go +++ b/internal/dao/security/attachment_check.go @@ -12,6 +12,10 @@ import ( "github.com/rocboss/paopao-ce/internal/core" ) +var ( + _ core.AttachmentCheckService = (*attachmentCheckServant)(nil) +) + type attachmentCheckServant struct { domain string } diff --git a/internal/dao/security/phone_verify_juhe.go b/internal/dao/security/phone_verify_juhe.go new file mode 100644 index 00000000..5981c6c3 --- /dev/null +++ b/internal/dao/security/phone_verify_juhe.go @@ -0,0 +1,66 @@ +package security + +import ( + "errors" + "fmt" + "net/http" + "time" + + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/pkg/json" + "gopkg.in/resty.v1" +) + +var ( + _ core.PhoneVerifyService = (*juheSmsServant)(nil) +) + +type juhePhoneCaptchaRsp struct { + ErrorCode int `json:"error_code"` + Reason string `json:"reason"` +} + +type juheSmsServant struct { + gateway string + key string + tplID string + tplVal string +} + +// SendPhoneCaptcha 发送短信验证码 +func (s *juheSmsServant) SendPhoneCaptcha(phone string, captcha string, expire time.Duration) error { + client := resty.New() + client.DisableWarn = true + resp, err := client.R(). + SetFormData(map[string]string{ + "mobile": phone, + "tpl_id": s.tplID, + "tpl_value": fmt.Sprintf(s.tplVal, captcha, expire), + "key": s.key, + }).Post(s.gateway) + if err != nil { + return err + } + if resp.StatusCode() != http.StatusOK { + return errors.New(resp.Status()) + } + + result := &juhePhoneCaptchaRsp{} + if err = json.Unmarshal(resp.Body(), result); err != nil { + return err + } + if result.ErrorCode != 0 { + return errors.New(result.Reason) + } + return nil +} + +func newJuheSmsServant() *juheSmsServant { + return &juheSmsServant{ + gateway: conf.SmsJuheSetting.Gateway, + key: conf.SmsJuheSetting.Key, + tplID: conf.SmsJuheSetting.TplID, + tplVal: conf.SmsJuheSetting.TplVal, + } +} diff --git a/internal/dao/security/security.go b/internal/dao/security/security.go new file mode 100644 index 00000000..75cd003b --- /dev/null +++ b/internal/dao/security/security.go @@ -0,0 +1,18 @@ +package security + +import ( + "strings" + + "github.com/alimy/cfg" + "github.com/rocboss/paopao-ce/internal/core" +) + +func NewPhoneVerifyService() core.PhoneVerifyService { + smsVendor, _ := cfg.Val("sms") + switch strings.ToLower(smsVendor) { + case "smsjuhe": + return newJuheSmsServant() + default: + return newJuheSmsServant() + } +}