新增后台管理
This commit is contained in:
parent
9f51a4c403
commit
7762ad46fe
21
app/main/api/.air.toml
Normal file
21
app/main/api/.air.toml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# 用户api服务的air配置
|
||||||
|
root = "."
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
cmd = "go build -o ./tmp/user-api ."
|
||||||
|
bin = "./tmp/user-api -f etc/user.yaml"
|
||||||
|
include_ext = ["go", "yaml"]
|
||||||
|
exclude_dir = ["tmp", "vendor"]
|
||||||
|
include_dir = ["internal", "etc"]
|
||||||
|
exclude_regex = ["_test\\.go"]
|
||||||
|
delay = 1000
|
||||||
|
|
||||||
|
[log]
|
||||||
|
time = true
|
||||||
|
|
||||||
|
[color]
|
||||||
|
main = "red"
|
||||||
|
watcher = "cyan"
|
||||||
|
build = "yellow"
|
||||||
|
runner = "green"
|
31
app/main/api/Dockerfile
Normal file
31
app/main/api/Dockerfile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
FROM golang:1.22.4-alpine AS builder
|
||||||
|
|
||||||
|
LABEL stage=gobuilder
|
||||||
|
|
||||||
|
ENV CGO_ENABLED 0
|
||||||
|
ENV GOPROXY https://goproxy.cn,direct
|
||||||
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
|
||||||
|
RUN apk update --no-cache && apk add --no-cache tzdata
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
ADD go.mod .
|
||||||
|
ADD go.sum .
|
||||||
|
RUN go mod download
|
||||||
|
COPY . .
|
||||||
|
COPY app/user/cmd/api/etc /app/etc
|
||||||
|
RUN go build -ldflags="-s -w" -o /app/user app/user/cmd/api/main.go
|
||||||
|
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||||
|
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
|
||||||
|
ENV TZ Asia/Shanghai
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/user /app/user
|
||||||
|
COPY --from=builder /app/etc /app/etc
|
||||||
|
|
||||||
|
CMD ["./user", "-f", "etc/main.yaml"]
|
362
app/main/api/desc/agent.api
Normal file
362
app/main/api/desc/agent.api
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "代理服务"
|
||||||
|
desc: "代理服务接口"
|
||||||
|
author: "Liangzai"
|
||||||
|
email: "2440983361@qq.com"
|
||||||
|
version: "v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 代理服务基本类型定义
|
||||||
|
type AgentProductConfig {
|
||||||
|
ProductID int64 `json:"product_id"`
|
||||||
|
CostPrice float64 `json:"cost_price"`
|
||||||
|
PriceRangeMin float64 `json:"price_range_min"`
|
||||||
|
PriceRangeMax float64 `json:"price_range_max"`
|
||||||
|
PPricingStandard float64 `json:"p_pricing_standard"`
|
||||||
|
POverpricingRatio float64 `json:"p_overpricing_ratio"`
|
||||||
|
APricingStandard float64 `json:"a_pricing_standard"`
|
||||||
|
APricingEnd float64 `json:"a_pricing_end"`
|
||||||
|
AOverpricingRatio float64 `json:"a_overpricing_ratio"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AgentMembershipUserConfig {
|
||||||
|
ProductID int64 `json:"product_id"`
|
||||||
|
PriceIncreaseAmount float64 `json:"price_increase_amount"`
|
||||||
|
PriceRangeFrom float64 `json:"price_range_from"`
|
||||||
|
PriceRangeTo float64 `json:"price_range_to"`
|
||||||
|
PriceRatio float64 `json:"price_ratio"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductConfig {
|
||||||
|
ProductID int64 `json:"product_id"`
|
||||||
|
CostPrice float64 `json:"cost_price"`
|
||||||
|
PriceRangeMin float64 `json:"price_range_min"`
|
||||||
|
PriceRangeMax float64 `json:"price_range_max"`
|
||||||
|
}
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1/agent
|
||||||
|
group: agent
|
||||||
|
jwt: JwtAuth
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
// 查看代理信息
|
||||||
|
@handler GetAgentInfo
|
||||||
|
get /info returns (AgentInfoResp)
|
||||||
|
|
||||||
|
// 查询代理申请状态
|
||||||
|
@handler GetAgentAuditStatus
|
||||||
|
get /audit/status returns (AgentAuditStatusResp)
|
||||||
|
|
||||||
|
// 生成推广标识
|
||||||
|
@handler GeneratingLink
|
||||||
|
post /generating_link (AgentGeneratingLinkReq) returns (AgentGeneratingLinkResp)
|
||||||
|
|
||||||
|
// 获取推广定价配置
|
||||||
|
@handler GetAgentProductConfig
|
||||||
|
get /product_config returns (AgentProductConfigResp)
|
||||||
|
|
||||||
|
// 获取下级分页列表
|
||||||
|
@handler GetAgentSubordinateList
|
||||||
|
get /subordinate/list (GetAgentSubordinateListReq) returns (GetAgentSubordinateListResp)
|
||||||
|
|
||||||
|
// 下级贡献详情
|
||||||
|
@handler GetAgentSubordinateContributionDetail
|
||||||
|
get /subordinate/contribution/detail (GetAgentSubordinateContributionDetailReq) returns (GetAgentSubordinateContributionDetailResp)
|
||||||
|
|
||||||
|
@handler AgentRealName
|
||||||
|
post /real_name (AgentRealNameReq) returns (AgentRealNameResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
AgentInfoResp {
|
||||||
|
status int64 `json:"status"` // 0=待审核,1=审核通过,2=审核未通过,3=未申请
|
||||||
|
isAgent bool `json:"is_agent"`
|
||||||
|
agentID int64 `json:"agent_id"`
|
||||||
|
level string `json:"level"`
|
||||||
|
region string `json:"region"`
|
||||||
|
mobile string `json:"mobile"`
|
||||||
|
expiryTime string `json:"expiry_time"`
|
||||||
|
isRealName bool `json:"is_real_name"`
|
||||||
|
}
|
||||||
|
// 查询代理申请状态响应
|
||||||
|
AgentAuditStatusResp {
|
||||||
|
Status int64 `json:"status"` // 0=待审核,1=审核通过,2=审核未通过
|
||||||
|
AuditReason string `json:"audit_reason"`
|
||||||
|
}
|
||||||
|
AgentGeneratingLinkReq {
|
||||||
|
Product string `json:"product"`
|
||||||
|
Price string `json:"price"`
|
||||||
|
}
|
||||||
|
AgentGeneratingLinkResp {
|
||||||
|
LinkIdentifier string `json:"link_identifier"`
|
||||||
|
}
|
||||||
|
AgentProductConfigResp {
|
||||||
|
AgentProductConfig []AgentProductConfig
|
||||||
|
}
|
||||||
|
GetAgentSubordinateListReq {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
}
|
||||||
|
GetAgentSubordinateListResp {
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
List []AgentSubordinateList `json:"list"` // 查询列表
|
||||||
|
}
|
||||||
|
AgentSubordinateList {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
LevelName string `json:"level_name"`
|
||||||
|
TotalOrders int64 `json:"total_orders"` // 总单量
|
||||||
|
TotalEarnings float64 `json:"total_earnings"` // 总金额
|
||||||
|
TotalContribution float64 `json:"total_contribution"` // 总贡献
|
||||||
|
}
|
||||||
|
GetAgentSubordinateContributionDetailReq {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
SubordinateID int64 `form:"subordinate_id"` // 下级ID
|
||||||
|
}
|
||||||
|
GetAgentSubordinateContributionDetailResp {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
TotalEarnings float64 `json:"total_earnings"` // 总金额
|
||||||
|
TotalContribution float64 `json:"total_contribution"` // 总贡献
|
||||||
|
TotalOrders int64 `json:"total_orders"` // 总单量
|
||||||
|
LevelName string `json:"level_name"` // 等级名称
|
||||||
|
List []AgentSubordinateContributionDetail `json:"list"` // 查询列表
|
||||||
|
Stats AgentSubordinateContributionStats `json:"stats"` // 统计数据
|
||||||
|
}
|
||||||
|
AgentSubordinateContributionDetail {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
AgentSubordinateContributionStats {
|
||||||
|
CostCount int64 `json:"cost_count"` // 成本扣除次数
|
||||||
|
CostAmount float64 `json:"cost_amount"` // 成本扣除总额
|
||||||
|
PricingCount int64 `json:"pricing_count"` // 定价扣除次数
|
||||||
|
PricingAmount float64 `json:"pricing_amount"` // 定价扣除总额
|
||||||
|
DescendantPromotionCount int64 `json:"descendant_promotion_count"` // 下级推广次数
|
||||||
|
DescendantPromotionAmount float64 `json:"descendant_promotion_amount"` // 下级推广总额
|
||||||
|
DescendantUpgradeVipCount int64 `json:"descendant_upgrade_vip_count"` // 下级升级VIP次数
|
||||||
|
DescendantUpgradeVipAmount float64 `json:"descendant_upgrade_vip_amount"` // 下级升级VIP总额
|
||||||
|
DescendantUpgradeSvipCount int64 `json:"descendant_upgrade_svip_count"` // 下级升级SVIP次数
|
||||||
|
DescendantUpgradeSvipAmount float64 `json:"descendant_upgrade_svip_amount"` // 下级升级SVIP总额
|
||||||
|
DescendantStayActiveCount int64 `json:"descendant_stay_active_count"` // 下级保持活跃次数
|
||||||
|
DescendantStayActiveAmount float64 `json:"descendant_stay_active_amount"` // 下级保持活跃总额
|
||||||
|
DescendantNewActiveCount int64 `json:"descendant_new_active_count"` // 下级新增活跃次数
|
||||||
|
DescendantNewActiveAmount float64 `json:"descendant_new_active_amount"` // 下级新增活跃总额
|
||||||
|
DescendantWithdrawCount int64 `json:"descendant_withdraw_count"` // 下级提现次数
|
||||||
|
DescendantWithdrawAmount float64 `json:"descendant_withdraw_amount"` // 下级提现总额
|
||||||
|
}
|
||||||
|
|
||||||
|
AgentRealNameReq {
|
||||||
|
Name string `json:"name"`
|
||||||
|
IDCard string `json:"id_card"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
}
|
||||||
|
AgentRealNameResp {
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1/agent
|
||||||
|
group: agent
|
||||||
|
jwt: JwtAuth
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@handler GetAgentMembershipProductConfig
|
||||||
|
get /membership/user_config (AgentMembershipProductConfigReq) returns (AgentMembershipProductConfigResp)
|
||||||
|
|
||||||
|
@handler SaveAgentMembershipUserConfig
|
||||||
|
post /membership/save_user_config (SaveAgentMembershipUserConfigReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
// 获取会员当前配置
|
||||||
|
AgentMembershipProductConfigReq {
|
||||||
|
ProductID int64 `form:"product_id"`
|
||||||
|
}
|
||||||
|
// 获取会员当前配置
|
||||||
|
AgentMembershipProductConfigResp {
|
||||||
|
AgentMembershipUserConfig AgentMembershipUserConfig `json:"agent_membership_user_config"`
|
||||||
|
ProductConfig ProductConfig `json:"product_config"`
|
||||||
|
PriceIncreaseMax float64 `json:"price_increase_max"`
|
||||||
|
PriceIncreaseAmount float64 `json:"price_increase_amount"`
|
||||||
|
PriceRatio float64 `json:"price_ratio"`
|
||||||
|
}
|
||||||
|
SaveAgentMembershipUserConfigReq {
|
||||||
|
ProductID int64 `json:"product_id"`
|
||||||
|
PriceIncreaseAmount float64 `json:"price_increase_amount"`
|
||||||
|
PriceRangeFrom float64 `json:"price_range_from"`
|
||||||
|
PriceRangeTo float64 `json:"price_range_to"`
|
||||||
|
PriceRatio float64 `json:"price_ratio"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1/agent
|
||||||
|
group: agent
|
||||||
|
jwt: JwtAuth
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@handler GetAgentRevenueInfo
|
||||||
|
get /revenue (GetAgentRevenueInfoReq) returns (GetAgentRevenueInfoResp)
|
||||||
|
|
||||||
|
@handler GetAgentCommission
|
||||||
|
get /commission (GetCommissionReq) returns (GetCommissionResp)
|
||||||
|
|
||||||
|
@handler GetAgentRewards
|
||||||
|
get /rewards (GetRewardsReq) returns (GetRewardsResp)
|
||||||
|
|
||||||
|
@handler GetAgentWithdrawal
|
||||||
|
get /withdrawal (GetWithdrawalReq) returns (GetWithdrawalResp)
|
||||||
|
|
||||||
|
@handler AgentWithdrawal
|
||||||
|
post /withdrawal (WithdrawalReq) returns (WithdrawalResp)
|
||||||
|
|
||||||
|
@handler ActivateAgentMembership
|
||||||
|
post /membership/activate (AgentActivateMembershipReq) returns (AgentActivateMembershipResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
// 收益信息
|
||||||
|
GetAgentRevenueInfoReq {}
|
||||||
|
GetAgentRevenueInfoResp {
|
||||||
|
Balance float64 `json:"balance"`
|
||||||
|
FrozenBalance float64 `json:"frozen_balance"`
|
||||||
|
TotalEarnings float64 `json:"total_earnings"`
|
||||||
|
DirectPush DirectPushReport `json:"direct_push"` // 直推报告数据
|
||||||
|
ActiveReward ActiveReward `json:"active_reward"` // 活跃下级奖励数据
|
||||||
|
}
|
||||||
|
// 直推报告数据结构
|
||||||
|
DirectPushReport {
|
||||||
|
TotalCommission float64 `json:"total_commission"`
|
||||||
|
TotalReport int `json:"total_report"`
|
||||||
|
Today TimeRangeReport `json:"today"` // 近24小时数据
|
||||||
|
Last7D TimeRangeReport `json:"last7d"` // 近7天数据
|
||||||
|
Last30D TimeRangeReport `json:"last30d"` // 近30天数据
|
||||||
|
}
|
||||||
|
// 活跃下级奖励数据结构
|
||||||
|
ActiveReward {
|
||||||
|
TotalReward float64 `json:"total_reward"`
|
||||||
|
Today ActiveRewardData `json:"today"` // 今日数据
|
||||||
|
Last7D ActiveRewardData `json:"last7d"` // 近7天数据
|
||||||
|
Last30D ActiveRewardData `json:"last30d"` // 近30天数据
|
||||||
|
}
|
||||||
|
// 通用时间范围报告结构
|
||||||
|
TimeRangeReport {
|
||||||
|
Commission float64 `json:"commission"` // 佣金
|
||||||
|
Report int `json:"report"` // 报告量
|
||||||
|
}
|
||||||
|
// 活跃奖励专用结构
|
||||||
|
ActiveRewardData {
|
||||||
|
NewActiveReward float64 `json:"active_reward"`
|
||||||
|
SubPromoteReward float64 `json:"sub_promote_reward"`
|
||||||
|
SubUpgradeReward float64 `json:"sub_upgrade_reward"`
|
||||||
|
SubWithdrawReward float64 `json:"sub_withdraw_reward"`
|
||||||
|
}
|
||||||
|
Commission {
|
||||||
|
ProductName string `json:"product_name"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
}
|
||||||
|
GetCommissionReq {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
}
|
||||||
|
GetCommissionResp {
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
List []Commission `json:"list"` // 查询列表
|
||||||
|
}
|
||||||
|
Rewards {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
}
|
||||||
|
GetRewardsReq {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
}
|
||||||
|
GetRewardsResp {
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
List []Rewards `json:"list"` // 查询列表
|
||||||
|
}
|
||||||
|
Withdrawal {
|
||||||
|
Status int64 `json:"status"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
WithdrawalNo string `json:"withdrawal_no"`
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
payeeAccount string `json:"payee_account"`
|
||||||
|
CreateTime string `json:"create_time"`
|
||||||
|
}
|
||||||
|
GetWithdrawalReq {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
}
|
||||||
|
GetWithdrawalResp {
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
List []Withdrawal `json:"list"` // 查询列表
|
||||||
|
}
|
||||||
|
WithdrawalReq {
|
||||||
|
Amount float64 `json:"amount"` // 提现金额
|
||||||
|
payeeAccount string `json:"payee_account"`
|
||||||
|
payeeName string `json:"payee_name"`
|
||||||
|
}
|
||||||
|
WithdrawalResp {
|
||||||
|
Status int64 `json:"status"` // 1申请中 2成功 3失败
|
||||||
|
failMsg string `json:"fail_msg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开通代理会员请求参数
|
||||||
|
AgentActivateMembershipReq {
|
||||||
|
Type string `json:"type,oneof=VIP SVIP"` // 会员类型:vip/svip
|
||||||
|
}
|
||||||
|
// 开通代理会员响应
|
||||||
|
AgentActivateMembershipResp {
|
||||||
|
Id string `json:"id"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1/agent
|
||||||
|
group: agent
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
// 提交代理申请
|
||||||
|
@handler ApplyForAgent
|
||||||
|
post /apply (AgentApplyReq) returns (AgentApplyResp)
|
||||||
|
|
||||||
|
// 获取推广标识数据
|
||||||
|
@handler GetLinkData
|
||||||
|
get /link (GetLinkDataReq) returns (GetLinkDataResp)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
// 代理申请请求参数
|
||||||
|
AgentApplyReq {
|
||||||
|
Region string `json:"region"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
Ancestor string `json:"ancestor,optional"`
|
||||||
|
}
|
||||||
|
AgentApplyResp{
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
AccessExpire int64 `json:"accessExpire"`
|
||||||
|
RefreshAfter int64 `json:"refreshAfter"`
|
||||||
|
}
|
||||||
|
GetLinkDataReq {
|
||||||
|
LinkIdentifier string `form:"link_identifier"`
|
||||||
|
}
|
||||||
|
GetLinkDataResp {
|
||||||
|
Product
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
39
app/main/api/desc/app.api
Normal file
39
app/main/api/desc/app.api
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "APP服务"
|
||||||
|
desc: "APP服务"
|
||||||
|
author: "Liangzai"
|
||||||
|
email: "2440983361@qq.com"
|
||||||
|
version: "v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: app
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc(
|
||||||
|
summary: "心跳检测接口"
|
||||||
|
)
|
||||||
|
@handler healthCheck
|
||||||
|
get /health/check returns (HealthCheckResp)
|
||||||
|
|
||||||
|
@handler getAppVersion
|
||||||
|
get /app/version returns (getAppVersionResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
// 心跳检测响应
|
||||||
|
HealthCheckResp {
|
||||||
|
Status string `json:"status"` // 服务状态
|
||||||
|
Message string `json:"message"` // 状态信息
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
getAppVersionResp {
|
||||||
|
Version string `json:"version"`
|
||||||
|
WgtUrl string `json:"wgtUrl"`
|
||||||
|
}
|
||||||
|
)
|
16
app/main/api/desc/main.api
Normal file
16
app/main/api/desc/main.api
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "单体服务中心"
|
||||||
|
desc: "单体服务中心"
|
||||||
|
author: "Liangzai"
|
||||||
|
email: "2440983361@qq.com"
|
||||||
|
version: "v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
import "user.api"
|
||||||
|
import "query.api"
|
||||||
|
import "pay.api"
|
||||||
|
import "product.api"
|
||||||
|
import "agent.api"
|
||||||
|
import "app.api"
|
72
app/main/api/desc/pay.api
Normal file
72
app/main/api/desc/pay.api
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "支付服务"
|
||||||
|
desc: "支付服务"
|
||||||
|
author: "Liangzai"
|
||||||
|
email: "2440983361@qq.com"
|
||||||
|
version: "v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: pay
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
// 微信支付回调
|
||||||
|
@handler WechatPayCallback
|
||||||
|
post /pay/wechat/callback
|
||||||
|
|
||||||
|
// 支付宝支付回调
|
||||||
|
@handler AlipayCallback
|
||||||
|
post /pay/alipay/callback
|
||||||
|
|
||||||
|
// 微信退款回调
|
||||||
|
@handler WechatPayRefundCallback
|
||||||
|
post /pay/wechat/refund_callback
|
||||||
|
}
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: pay
|
||||||
|
jwt: JwtAuth
|
||||||
|
middleware: SourceInterceptor
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
// 支付
|
||||||
|
@handler Payment
|
||||||
|
post /pay/payment (PaymentReq) returns (PaymentResp)
|
||||||
|
|
||||||
|
@handler IapCallback
|
||||||
|
post /pay/iap_callback (IapCallbackReq)
|
||||||
|
|
||||||
|
@handler PaymentCheck
|
||||||
|
post /pay/check (PaymentCheckReq) returns (PaymentCheckResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
PaymentReq {
|
||||||
|
Id string `json:"id"`
|
||||||
|
PayMethod string `json:"pay_method"`
|
||||||
|
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip"`
|
||||||
|
}
|
||||||
|
PaymentResp {
|
||||||
|
PrepayData interface{} `json:"prepay_data"`
|
||||||
|
PrepayId string `json:"prepay_id"`
|
||||||
|
OrderNo string `json:"order_no"`
|
||||||
|
}
|
||||||
|
PaymentCheckReq {
|
||||||
|
OrderNo string `json:"order_no" validate:"required"`
|
||||||
|
}
|
||||||
|
PaymentCheckResp {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
IapCallbackReq {
|
||||||
|
OrderID int64 `json:"order_id" validate:"required"`
|
||||||
|
TransactionReceipt string `json:"transaction_receipt" validate:"required"`
|
||||||
|
}
|
||||||
|
)
|
57
app/main/api/desc/product.api
Normal file
57
app/main/api/desc/product.api
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "产品服务"
|
||||||
|
desc: "产品服务"
|
||||||
|
author: "Liangzai"
|
||||||
|
email: "2440983361@qq.com"
|
||||||
|
version: "v1"
|
||||||
|
)
|
||||||
|
type Feature {
|
||||||
|
ID int64 `json:"id"` // 功能ID
|
||||||
|
ApiID string `json:"api_id"` // API标识
|
||||||
|
Name string `json:"name"` // 功能描述
|
||||||
|
}
|
||||||
|
// 产品基本类型定义
|
||||||
|
type Product {
|
||||||
|
ProductName string `json:"product_name"`
|
||||||
|
ProductEn string `json:"product_en"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Notes string `json:"notes,optional"`
|
||||||
|
SellPrice float64 `json:"sell_price"`
|
||||||
|
Features []Feature `json:"features"` // 关联功能列表
|
||||||
|
}
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1/product
|
||||||
|
group: product
|
||||||
|
jwt: JwtAuth
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@handler GetProductByID
|
||||||
|
get /:id (GetProductByIDRequest) returns (ProductResponse)
|
||||||
|
|
||||||
|
@handler GetProductByEn
|
||||||
|
get /en/:product_en (GetProductByEnRequest) returns (ProductResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetProductByIDRequest {
|
||||||
|
Id int64 `path:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetProductByEnRequest {
|
||||||
|
ProductEn string `path:"product_en"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductResponse {
|
||||||
|
Product
|
||||||
|
}
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1/product
|
||||||
|
group: product
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@handler GetProductAppByEn
|
||||||
|
get /app_en/:product_en (GetProductByEnRequest) returns (ProductResponse)
|
||||||
|
}
|
234
app/main/api/desc/query.api
Normal file
234
app/main/api/desc/query.api
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "产品查询服务"
|
||||||
|
desc: "产品查询服务"
|
||||||
|
author: "Liangzai"
|
||||||
|
email: "2440983361@qq.com"
|
||||||
|
version: "v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
//============================> query v1 <============================
|
||||||
|
// 查询基本类型定义
|
||||||
|
type Query {
|
||||||
|
Id int64 `json:"id"` // 主键ID
|
||||||
|
OrderId int64 `json:"order_id"` // 订单ID
|
||||||
|
UserId int64 `json:"user_id"` // 用户ID
|
||||||
|
ProductName string `json:"product_name"` // 产品ID
|
||||||
|
QueryParams map[string]interface{} `json:"query_params"`
|
||||||
|
QueryData []QueryItem `json:"query_data"`
|
||||||
|
CreateTime string `json:"create_time"` // 创建时间
|
||||||
|
UpdateTime string `json:"update_time"` // 更新时间
|
||||||
|
QueryState string `json:"query_state"` // 查询状态
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type QueryItem {
|
||||||
|
Feature interface{} `json:"feature"`
|
||||||
|
Data interface{} `json:"data"` // 这里可以是 map 或 具体的 struct
|
||||||
|
}
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: query
|
||||||
|
middleware: AuthInterceptor
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc "query service agent"
|
||||||
|
@handler queryServiceAgent
|
||||||
|
post /query/service_agent/:product (QueryServiceReq) returns (QueryServiceResp)
|
||||||
|
|
||||||
|
@handler queryServiceApp
|
||||||
|
post /query/service_app/:product (QueryServiceReq) returns (QueryServiceResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
QueryReq {
|
||||||
|
Data string `json:"data" validate:"required"`
|
||||||
|
}
|
||||||
|
QueryResp {
|
||||||
|
Id string `json:"id"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
QueryServiceReq {
|
||||||
|
Product string `path:"product"`
|
||||||
|
Data string `json:"data" validate:"required"`
|
||||||
|
AgentIdentifier string `json:"agent_identifier,optional"`
|
||||||
|
App bool `json:"app,optional"`
|
||||||
|
}
|
||||||
|
QueryServiceResp {
|
||||||
|
Id string `json:"id"`
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
AccessExpire int64 `json:"accessExpire"`
|
||||||
|
RefreshAfter int64 `json:"refreshAfter"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: query
|
||||||
|
jwt: JwtAuth
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc "query service"
|
||||||
|
@handler queryService
|
||||||
|
post /query/service/:product (QueryServiceReq) returns (QueryServiceResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: query
|
||||||
|
jwt: JwtAuth
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc "获取查询临时订单"
|
||||||
|
@handler queryProvisionalOrder
|
||||||
|
get /query/provisional_order/:id (QueryProvisionalOrderReq) returns (QueryProvisionalOrderResp)
|
||||||
|
|
||||||
|
@doc "查询列表"
|
||||||
|
@handler queryList
|
||||||
|
get /query/list (QueryListReq) returns (QueryListResp)
|
||||||
|
|
||||||
|
@doc "查询详情 按订单号 付款查询时"
|
||||||
|
@handler queryDetailByOrderId
|
||||||
|
get /query/orderId/:order_id (QueryDetailByOrderIdReq) returns (QueryDetailByOrderIdResp)
|
||||||
|
|
||||||
|
@doc "查询详情 按订单号"
|
||||||
|
@handler queryDetailByOrderNo
|
||||||
|
get /query/orderNo/:order_no (QueryDetailByOrderNoReq) returns (QueryDetailByOrderNoResp)
|
||||||
|
|
||||||
|
@doc "重试查询"
|
||||||
|
@handler queryRetry
|
||||||
|
post /query/retry/:id (QueryRetryReq) returns (QueryRetryResp)
|
||||||
|
|
||||||
|
@doc "更新查询数据"
|
||||||
|
@handler updateQueryData
|
||||||
|
post /query/update_data (UpdateQueryDataReq) returns (UpdateQueryDataResp)
|
||||||
|
|
||||||
|
@doc "生成分享链接"
|
||||||
|
@handler QueryGenerateShareLink
|
||||||
|
post /query/generate_share_link (QueryGenerateShareLinkReq) returns (QueryGenerateShareLinkResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
QueryGenerateShareLinkReq {
|
||||||
|
OrderId *int64 `json:"order_id,optional"`
|
||||||
|
OrderNo *string `json:"order_no,optional"`
|
||||||
|
}
|
||||||
|
QueryGenerateShareLinkResp {
|
||||||
|
ShareLink string `json:"share_link"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 获取查询临时订单
|
||||||
|
type (
|
||||||
|
QueryProvisionalOrderReq {
|
||||||
|
Id string `path:"id"`
|
||||||
|
}
|
||||||
|
QueryProvisionalOrderResp {
|
||||||
|
Name string `json:"name"`
|
||||||
|
IdCard string `json:"id_card"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Product Product `json:"product"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
QueryListReq {
|
||||||
|
Page int64 `form:"page"` // 页码
|
||||||
|
PageSize int64 `form:"page_size"` // 每页数据量
|
||||||
|
}
|
||||||
|
QueryListResp {
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
List []Query `json:"list"` // 查询列表
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
QueryExampleReq {
|
||||||
|
Feature string `form:"feature"`
|
||||||
|
}
|
||||||
|
QueryExampleResp {
|
||||||
|
Query
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type (
|
||||||
|
QueryDetailByOrderIdReq {
|
||||||
|
OrderId int64 `path:"order_id"`
|
||||||
|
}
|
||||||
|
QueryDetailByOrderIdResp {
|
||||||
|
Query
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
QueryDetailByOrderNoReq {
|
||||||
|
OrderNo string `path:"order_no"`
|
||||||
|
}
|
||||||
|
QueryDetailByOrderNoResp {
|
||||||
|
Query
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
QueryRetryReq {
|
||||||
|
Id int64 `path:"id"`
|
||||||
|
}
|
||||||
|
QueryRetryResp {
|
||||||
|
Query
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type (
|
||||||
|
UpdateQueryDataReq {
|
||||||
|
Id int64 `json:"id"` // 查询ID
|
||||||
|
QueryData string `json:"query_data"` // 查询数据(未加密的JSON)
|
||||||
|
}
|
||||||
|
UpdateQueryDataResp {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
UpdatedAt string `json:"updated_at"` // 更新时间
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: query
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@handler querySingleTest
|
||||||
|
post /query/single/test (QuerySingleTestReq) returns (QuerySingleTestResp)
|
||||||
|
|
||||||
|
@doc "查询详情"
|
||||||
|
@handler queryShareDetail
|
||||||
|
get /query/share/:id (QueryShareDetailReq) returns (QueryShareDetailResp)
|
||||||
|
|
||||||
|
@doc "查询示例"
|
||||||
|
@handler queryExample
|
||||||
|
get /query/example (QueryExampleReq) returns (QueryExampleResp)
|
||||||
|
|
||||||
|
}
|
||||||
|
type (
|
||||||
|
QueryShareDetailReq {
|
||||||
|
Id string `path:"id"`
|
||||||
|
}
|
||||||
|
QueryShareDetailResp {
|
||||||
|
Status string `json:"status"`
|
||||||
|
Query
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type QuerySingleTestReq {
|
||||||
|
Params map[string]interface{} `json:"params"`
|
||||||
|
Api string `json:"api"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QuerySingleTestResp {
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
Api string `json:"api"`
|
||||||
|
}
|
||||||
|
|
192
app/main/api/desc/user.api
Normal file
192
app/main/api/desc/user.api
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "用户中心服务"
|
||||||
|
desc: "用户中心服务"
|
||||||
|
author: "Liangzai"
|
||||||
|
email: "2440983361@qq.com"
|
||||||
|
version: "v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
//============================> user v1 <============================
|
||||||
|
// 用户基本类型定义
|
||||||
|
type User {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
NickName string `json:"nickName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//no need login
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: user
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc "register"
|
||||||
|
@handler register
|
||||||
|
post /user/register (RegisterReq) returns (RegisterResp)
|
||||||
|
|
||||||
|
@doc "mobile login"
|
||||||
|
@handler mobileLogin
|
||||||
|
post /user/mobileLogin (MobileLoginReq) returns (MobileLoginResp)
|
||||||
|
|
||||||
|
@doc "mobile code login"
|
||||||
|
@handler mobileCodeLogin
|
||||||
|
post /user/mobileCodeLogin (MobileCodeLoginReq) returns (MobileCodeLoginResp)
|
||||||
|
|
||||||
|
@doc "agent mobile code login"
|
||||||
|
@handler agentMobileCodeLogin
|
||||||
|
post /user/agent_mobile_code_login (MobileCodeLoginReq) returns (MobileCodeLoginResp)
|
||||||
|
|
||||||
|
@doc "wechat mini auth"
|
||||||
|
@handler wxMiniAuth
|
||||||
|
post /user/wxMiniAuth (WXMiniAuthReq) returns (WXMiniAuthResp)
|
||||||
|
|
||||||
|
@doc "wechat h5 auth"
|
||||||
|
@handler wxH5Auth
|
||||||
|
post /user/wxh5Auth (WXH5AuthReq) returns (WXH5AuthResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
RegisterReq {
|
||||||
|
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||||
|
Password string `json:"password" validate:"required,min=11,max=11,password"`
|
||||||
|
Code string `json:"code" validate:"required"`
|
||||||
|
}
|
||||||
|
RegisterResp {
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
AccessExpire int64 `json:"accessExpire"`
|
||||||
|
RefreshAfter int64 `json:"refreshAfter"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
MobileLoginReq {
|
||||||
|
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||||
|
Password string `json:"password" validate:"required"`
|
||||||
|
}
|
||||||
|
MobileLoginResp {
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
AccessExpire int64 `json:"accessExpire"`
|
||||||
|
RefreshAfter int64 `json:"refreshAfter"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
MobileCodeLoginReq {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Code string `json:"code" validate:"required"`
|
||||||
|
}
|
||||||
|
MobileCodeLoginResp {
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
AccessExpire int64 `json:"accessExpire"`
|
||||||
|
RefreshAfter int64 `json:"refreshAfter"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
WXMiniAuthReq {
|
||||||
|
Code string `json:"code"`
|
||||||
|
IV string `json:"iv"`
|
||||||
|
EncryptedData string `json:"encryptedData"`
|
||||||
|
}
|
||||||
|
WXMiniAuthResp {
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
AccessExpire int64 `json:"accessExpire"`
|
||||||
|
RefreshAfter int64 `json:"refreshAfter"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
WXH5AuthReq {
|
||||||
|
Code string `json:"code"`
|
||||||
|
}
|
||||||
|
WXH5AuthResp {
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
AccessExpire int64 `json:"accessExpire"`
|
||||||
|
RefreshAfter int64 `json:"refreshAfter"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
//need login
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: user
|
||||||
|
jwt: JwtAuth
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc "get user info"
|
||||||
|
@handler detail
|
||||||
|
get /user/detail returns (UserInfoResp)
|
||||||
|
|
||||||
|
@doc "get new token"
|
||||||
|
@handler getToken
|
||||||
|
post /user/getToken returns (MobileCodeLoginResp)
|
||||||
|
|
||||||
|
@handler cancelOut
|
||||||
|
post /user/cancelOut
|
||||||
|
|
||||||
|
@doc "绑定手机号"
|
||||||
|
@handler bindMobile
|
||||||
|
post /user/bindMobile (BindMobileReq) returns (BindMobileResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
UserInfoResp {
|
||||||
|
UserInfo User `json:"userInfo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
BindMobileReq {
|
||||||
|
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||||
|
Code string `json:"code" validate:"required"`
|
||||||
|
}
|
||||||
|
BindMobileResp {
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
//============================> auth v1 <============================
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: auth
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc "get mobile verify code"
|
||||||
|
@handler sendSms
|
||||||
|
post /auth/sendSms (sendSmsReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
sendSmsReq {
|
||||||
|
Mobile string `json:"mobile" validate:"required,mobile"`
|
||||||
|
ActionType string `json:"actionType" validate:"required,oneof=login register query agentApply realName bindMobile"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
//============================> notification v1 <============================
|
||||||
|
@server (
|
||||||
|
prefix: api/v1
|
||||||
|
group: notification
|
||||||
|
)
|
||||||
|
service main {
|
||||||
|
@doc "get notifications"
|
||||||
|
@handler getNotifications
|
||||||
|
get /notification/list returns (GetNotificationsResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Notification {
|
||||||
|
Title string `json:"title"` // 通知标题
|
||||||
|
Content string `json:"content"` // 通知内容 (富文本)
|
||||||
|
NotificationPage string `json:"notificationPage"` // 通知页面
|
||||||
|
StartDate string `json:"startDate"` // 通知开始日期,格式 "YYYY-MM-DD"
|
||||||
|
EndDate string `json:"endDate"` // 通知结束日期,格式 "YYYY-MM-DD"
|
||||||
|
StartTime string `json:"startTime"` // 每天通知开始时间,格式 "HH:MM:SS"
|
||||||
|
EndTime string `json:"endTime"` // 每天通知结束时间,格式 "HH:MM:SS"
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
// 获取通知响应体(分页)
|
||||||
|
GetNotificationsResp {
|
||||||
|
Notifications []Notification `json:"notifications"` // 通知列表
|
||||||
|
Total int64 `json:"total"` // 总记录数
|
||||||
|
}
|
||||||
|
)
|
68
app/main/api/etc/main.dev.yaml
Normal file
68
app/main/api/etc/main.dev.yaml
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
Name: main
|
||||||
|
Host: 0.0.0.0
|
||||||
|
Port: 8888
|
||||||
|
DataSource: "tydata:5vg67b3UNHu8@tcp(127.0.0.1:21001)/tydata?charset=utf8mb4&parseTime=True&loc=Local"
|
||||||
|
CacheRedis:
|
||||||
|
- Host: "127.0.0.1:21002"
|
||||||
|
Pass: "3m3WsgyCKWqz" # Redis 密码,如果未设置则留空
|
||||||
|
Type: "node" # 单节点模式
|
||||||
|
JwtAuth:
|
||||||
|
AccessSecret: "WUvoIwL-FK0qnlxhvxR9tV6SjfOpeJMpKmY2QvT99lA"
|
||||||
|
AccessExpire: 2592000
|
||||||
|
RefreshAfter: 1296000
|
||||||
|
VerifyCode:
|
||||||
|
AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9"
|
||||||
|
AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65"
|
||||||
|
EndpointURL: "dysmsapi.aliyuncs.com"
|
||||||
|
SignName: "天远数据"
|
||||||
|
TemplateCode: "SMS_302641455"
|
||||||
|
ValidTime: 300
|
||||||
|
Encrypt:
|
||||||
|
SecretKey: "ff83609b2b24fc73196aac3d3dfb874f"
|
||||||
|
WestConfig:
|
||||||
|
Url: "http://proxy.tianyuanapi.com/api/invoke"
|
||||||
|
Key: "121a1e41fc1690dd6b90afbcacd80cf4"
|
||||||
|
SecretId: "449159"
|
||||||
|
SecretSecondId: "296804"
|
||||||
|
YushanConfig:
|
||||||
|
ApiKey: "4c566c4a4b543164535455685655316c"
|
||||||
|
AcctID: "YSSJ843926726"
|
||||||
|
Url: "https://api.yushanshuju.com/credit-gw/service"
|
||||||
|
Alipay:
|
||||||
|
AppID: "2021005113664540"
|
||||||
|
PrivateKey: "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCA1mtTVZmB/7/wWV37Z8hUXEXFs0Gn1/Ie7c6rPQQRUlPHyJGcPAZvDii+ySC1/bplneMENRAjCuoJEM1z4X1FMt8rLggCqnF1xzUN2p9fdXUwcRPmSV4yi9ggMiFXldm0/eyaobV2fj0/VSLED2Qc8xBStM9pqkfszwf2rsAAKL15WQXOUiQw0s25s+Du18H4+YgkQ0HBr0+VPfhL4QoOvsE34ZYP0TuTwxVheYNkvSOPXFXmtE3z/b+75y2n2msa9S4HItNVYpOkB7z3GDB+0/rvX+Q+GvYI9BSBbgJwEuqiMN2SwQyAjH608JBoAUGnk0ygfG8juF77shBxzr/vAgMBAAECggEAQTlL2EJrlm59IxZ7B72Ao4SbJf0b7fba8mF90R7wojxFgcy+OpQAxdQrOHrl/nxXEv6dYRHj+3mZBcHl4RZ0rsWUSW3iTEcxbWjOKRdWu6LhEwcMBfd6oqg9X/9A9fA86O3sDFR1Y2mBZECbexo3mphK2TQEFQBJrU8aPv404V784u0wTh1oLO0Z3NjgvXOAy3ZsM64oZROVCkObXnZGyrY8Hf6W+YLmCoI7eajOQ9QTFy1x24fm8LFdWNizG9/DFa4EC7ZjiYzFhGpfpKb4964QnN3Krlf18Ryhgf3PO6IDO04JOdnHLKhR8+kHIN5m6AMIyKxbZ/vKw4X09Z8XoQKBgQD7jNHzEhIo4IOmRzgdoGxSCLXe1cUbwFL4tU3n7miUCYL/k6wpiNkCGwikaHMiSG0Om2D6+I9gX/rBrTrp2MAmcHA6ymn1GARSYMv7rz+5afGygfBDNr/7xQ2ASCatB65TObH+AUZzdq82B5dpr46AJhilRcHnQEyc/SyIelft2QKBgQCDHeDYt3vTDJ1vIPtXeyO1NHbGQY7cUucx3sZ+QVdF0abstcutT0LrHOgDCWFtnvjia1f0QRPDnTzUtq4GQxj63/9zZr1pMGsd7gjgIvVjM0LqUQXU0TMpO1DuU2zyemRyJTfWDDN+vTvA2+376cW0QxKq2CKOhX45WZRrUBbXBwKBgQCPVFe0ZlGOlQ6uSdpBl0zhGTF3vNpIy7b7G2M+ietwnlLUCXKJX/42YuzzsMgZeqcZMZN6rPIU+dtJS8lLwUMLI/nupbLmAj9EKP9RczOeFC2xhrQ9uA6ACHF+7J2M7dl4dmFi15sq4y9GW+D8SRmrDwnv8eVgPJTqxp7/TKaZUQKBgCMMI4QKV7DsWFDSMh0KL1tKcM1BzNwb1OzBrbEl6hwhlEsFtTHYU/zgtyvIoCBbNA/hvZruokfRiecaBZ5q5Qx6P6ArQEoTxS406G5xKcKgeyyDB9oBKXnF/zYVWrPd/2d7h1dR35nrH0PIBe8mZ9BtdVnxeBs8l6bgyQl+WPyVAoGBAPW7XxyLUAZ4X6JD4b5Iqq4E40xmDO3rUysrH8Zj7MN47ykZI0SlwA9B6hqliRLLJXkzhaAamecWb1RNJFDWfcg4bIyew4ukRbYB07RI+l0DXEgOxxTBcvN6BNUoIiQSEKXkOv+xt7Ez2TBoDm67xD58vwSXT4aPt4qxnd4i7Ves"
|
||||||
|
AlipayPublicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0kkRL7lgKYs7f8Xi4DNKzp2ggjwy4By7RunwT4Ur4A71HVOqRQed9r45a6/W4JPuVv51tiHMojZifEKX7ixSlDG6be677RiNslMJ5G3mjw/+Ku01tV9Qzw5YyhvxbqmS8Qp9vgL8VPYhxqTxKO6WW+xiyVvxko+mrU+dbSFIVbBjp88NVVcquu+vZT/uwtjriKSwsesAm8DkKT6mTqY5P/JroMzTU7xa3/ErAMte6t2dOsxPS7kqWjJyoLBHRk+AH87X5lNBEjLgYPk1ADU7zFsLdC+nv4fm7nihYre7fCrdCTVKguXmPCEFBjqwSkag7BSIxRQjS3qHxi+DUMst7wIDAQAB"
|
||||||
|
AppCertPath: "etc/merchant/appCertPublicKey_2021005113664540.crt"
|
||||||
|
AlipayCertPath: "etc/merchant/alipayCertPublicKey_RSA2.crt"
|
||||||
|
AlipayRootCertPath: "etc/merchant/alipayRootCert.crt"
|
||||||
|
IsProduction: true
|
||||||
|
NotifyUrl: "https://6m4685017o.goho.co/api/v1/pay/alipay/callback"
|
||||||
|
ReturnURL: "http://localhost:5678/inquire"
|
||||||
|
|
||||||
|
Wxpay:
|
||||||
|
AppID: "wxa581992dc74d860e"
|
||||||
|
MchID: "1704330055"
|
||||||
|
MchCertificateSerialNumber: "749065854D0CECCE8F98EAFEA55AD4FB17F868C4"
|
||||||
|
MchApiv3Key: "A9f3G7kL2mP5sQ8tV1xY4zB6nC0dE3hJ"
|
||||||
|
MchPrivateKeyPath: "etc/merchant/apiclient_key.pem"
|
||||||
|
MchPublicKeyID: "PUB_KEY_ID_0117043300552025010900447500000187"
|
||||||
|
MchPublicKeyPath: "etc/merchant/pub_key.pem"
|
||||||
|
NotifyUrl: "https://6m4685017o.goho.co/api/v1/pay/wechat/callback"
|
||||||
|
RefundNotifyUrl: "https://6m4685017o.goho.co/api/v1/wechat/refund_callback"
|
||||||
|
Applepay:
|
||||||
|
ProductionVerifyURL: "https://api.storekit.itunes.apple.com/inApps/v1/transactions/receipt"
|
||||||
|
SandboxVerifyURL: "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/receipt"
|
||||||
|
Sandbox: false
|
||||||
|
BundleID: "com.allinone.check"
|
||||||
|
IssuerID: "bf828d85-5269-4914-9660-c066e09cd6ef"
|
||||||
|
KeyID: "LAY65829DQ"
|
||||||
|
LoadPrivateKeyPath: "etc/merchant/AuthKey_LAY65829DQ.p8"
|
||||||
|
Ali:
|
||||||
|
Code: "d55b58829efb41c8aa8e86769cba4844"
|
||||||
|
SystemConfig:
|
||||||
|
ThreeVerify: false
|
||||||
|
WechatH5:
|
||||||
|
AppID: "wxa581992dc74d860e"
|
||||||
|
AppSecret: "ba37510206df321279222cecb8614e00"
|
||||||
|
Query:
|
||||||
|
ShareLinkExpire: 604800 # 7天 = 7 * 24 * 60 * 60 = 604800秒
|
69
app/main/api/etc/main.yaml
Normal file
69
app/main/api/etc/main.yaml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
Name: main
|
||||||
|
Host: 0.0.0.0
|
||||||
|
Port: 8888
|
||||||
|
DataSource: "tydata:5vg67b3UNHu8@tcp(tydata_mysql:3306)/tydata?charset=utf8mb4&parseTime=True&loc=Local"
|
||||||
|
CacheRedis:
|
||||||
|
- Host: "tydata_redis:6379"
|
||||||
|
Pass: "3m3WsgyCKWqz" # Redis 密码,如果未设置则留空
|
||||||
|
Type: "node" # 单节点模式
|
||||||
|
|
||||||
|
JwtAuth:
|
||||||
|
AccessSecret: "WUvoIwL-FK0qnlxhvxR9tV6SjfOpeJMpKmY2QvT99lA"
|
||||||
|
AccessExpire: 2592000
|
||||||
|
RefreshAfter: 1296000
|
||||||
|
|
||||||
|
VerifyCode:
|
||||||
|
AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9"
|
||||||
|
AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65"
|
||||||
|
EndpointURL: "dysmsapi.aliyuncs.com"
|
||||||
|
SignName: "天远数据"
|
||||||
|
TemplateCode: "SMS_302641455"
|
||||||
|
ValidTime: 300
|
||||||
|
Encrypt:
|
||||||
|
SecretKey: "ff83609b2b24fc73196aac3d3dfb874f"
|
||||||
|
WestConfig:
|
||||||
|
Url: "https://apimaster.westdex.com.cn/api/invoke"
|
||||||
|
Key: "121a1e41fc1690dd6b90afbcacd80cf4"
|
||||||
|
SecretId: "449159"
|
||||||
|
SecretSecondId: "296804"
|
||||||
|
YushanConfig:
|
||||||
|
ApiKey: "4c566c4a4b543164535455685655316c"
|
||||||
|
AcctID: "YSSJ843926726"
|
||||||
|
Url: "https://api.yushanshuju.com/credit-gw/service"
|
||||||
|
Alipay:
|
||||||
|
AppID: "2021005113664540"
|
||||||
|
PrivateKey: "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCA1mtTVZmB/7/wWV37Z8hUXEXFs0Gn1/Ie7c6rPQQRUlPHyJGcPAZvDii+ySC1/bplneMENRAjCuoJEM1z4X1FMt8rLggCqnF1xzUN2p9fdXUwcRPmSV4yi9ggMiFXldm0/eyaobV2fj0/VSLED2Qc8xBStM9pqkfszwf2rsAAKL15WQXOUiQw0s25s+Du18H4+YgkQ0HBr0+VPfhL4QoOvsE34ZYP0TuTwxVheYNkvSOPXFXmtE3z/b+75y2n2msa9S4HItNVYpOkB7z3GDB+0/rvX+Q+GvYI9BSBbgJwEuqiMN2SwQyAjH608JBoAUGnk0ygfG8juF77shBxzr/vAgMBAAECggEAQTlL2EJrlm59IxZ7B72Ao4SbJf0b7fba8mF90R7wojxFgcy+OpQAxdQrOHrl/nxXEv6dYRHj+3mZBcHl4RZ0rsWUSW3iTEcxbWjOKRdWu6LhEwcMBfd6oqg9X/9A9fA86O3sDFR1Y2mBZECbexo3mphK2TQEFQBJrU8aPv404V784u0wTh1oLO0Z3NjgvXOAy3ZsM64oZROVCkObXnZGyrY8Hf6W+YLmCoI7eajOQ9QTFy1x24fm8LFdWNizG9/DFa4EC7ZjiYzFhGpfpKb4964QnN3Krlf18Ryhgf3PO6IDO04JOdnHLKhR8+kHIN5m6AMIyKxbZ/vKw4X09Z8XoQKBgQD7jNHzEhIo4IOmRzgdoGxSCLXe1cUbwFL4tU3n7miUCYL/k6wpiNkCGwikaHMiSG0Om2D6+I9gX/rBrTrp2MAmcHA6ymn1GARSYMv7rz+5afGygfBDNr/7xQ2ASCatB65TObH+AUZzdq82B5dpr46AJhilRcHnQEyc/SyIelft2QKBgQCDHeDYt3vTDJ1vIPtXeyO1NHbGQY7cUucx3sZ+QVdF0abstcutT0LrHOgDCWFtnvjia1f0QRPDnTzUtq4GQxj63/9zZr1pMGsd7gjgIvVjM0LqUQXU0TMpO1DuU2zyemRyJTfWDDN+vTvA2+376cW0QxKq2CKOhX45WZRrUBbXBwKBgQCPVFe0ZlGOlQ6uSdpBl0zhGTF3vNpIy7b7G2M+ietwnlLUCXKJX/42YuzzsMgZeqcZMZN6rPIU+dtJS8lLwUMLI/nupbLmAj9EKP9RczOeFC2xhrQ9uA6ACHF+7J2M7dl4dmFi15sq4y9GW+D8SRmrDwnv8eVgPJTqxp7/TKaZUQKBgCMMI4QKV7DsWFDSMh0KL1tKcM1BzNwb1OzBrbEl6hwhlEsFtTHYU/zgtyvIoCBbNA/hvZruokfRiecaBZ5q5Qx6P6ArQEoTxS406G5xKcKgeyyDB9oBKXnF/zYVWrPd/2d7h1dR35nrH0PIBe8mZ9BtdVnxeBs8l6bgyQl+WPyVAoGBAPW7XxyLUAZ4X6JD4b5Iqq4E40xmDO3rUysrH8Zj7MN47ykZI0SlwA9B6hqliRLLJXkzhaAamecWb1RNJFDWfcg4bIyew4ukRbYB07RI+l0DXEgOxxTBcvN6BNUoIiQSEKXkOv+xt7Ez2TBoDm67xD58vwSXT4aPt4qxnd4i7Ves"
|
||||||
|
AlipayPublicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0kkRL7lgKYs7f8Xi4DNKzp2ggjwy4By7RunwT4Ur4A71HVOqRQed9r45a6/W4JPuVv51tiHMojZifEKX7ixSlDG6be677RiNslMJ5G3mjw/+Ku01tV9Qzw5YyhvxbqmS8Qp9vgL8VPYhxqTxKO6WW+xiyVvxko+mrU+dbSFIVbBjp88NVVcquu+vZT/uwtjriKSwsesAm8DkKT6mTqY5P/JroMzTU7xa3/ErAMte6t2dOsxPS7kqWjJyoLBHRk+AH87X5lNBEjLgYPk1ADU7zFsLdC+nv4fm7nihYre7fCrdCTVKguXmPCEFBjqwSkag7BSIxRQjS3qHxi+DUMst7wIDAQAB"
|
||||||
|
AppCertPath: "etc/merchant/appCertPublicKey_2021005113664540.crt"
|
||||||
|
AlipayCertPath: "etc/merchant/alipayCertPublicKey_RSA2.crt"
|
||||||
|
AlipayRootCertPath: "etc/merchant/alipayRootCert.crt"
|
||||||
|
IsProduction: true
|
||||||
|
NotifyUrl: "https://www.tianyuandb.com/api/v1/pay/alipay/callback"
|
||||||
|
ReturnURL: "https://www.tianyuandb.com/payment/result"
|
||||||
|
Wxpay:
|
||||||
|
AppID: "wxa581992dc74d860e"
|
||||||
|
MchID: "1704330055"
|
||||||
|
MchCertificateSerialNumber: "749065854D0CECCE8F98EAFEA55AD4FB17F868C4"
|
||||||
|
MchApiv3Key: "A9f3G7kL2mP5sQ8tV1xY4zB6nC0dE3hJ"
|
||||||
|
MchPrivateKeyPath: "etc/merchant/apiclient_key.pem"
|
||||||
|
MchPublicKeyID: "PUB_KEY_ID_0117043300552025010900447500000187"
|
||||||
|
MchPublicKeyPath: "etc/merchant/pub_key.pem"
|
||||||
|
NotifyUrl: "https://www.tianyuandb.com/api/v1/pay/wechat/callback"
|
||||||
|
RefundNotifyUrl: "https://www.tianyuandb.com/api/v1/wechat/refund_callback"
|
||||||
|
Applepay:
|
||||||
|
ProductionVerifyURL: "https://api.storekit.itunes.apple.com/inApps/v1/transactions/receipt"
|
||||||
|
SandboxVerifyURL: "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/receipt"
|
||||||
|
Sandbox: true
|
||||||
|
BundleID: "com.allinone.check"
|
||||||
|
IssuerID: "bf828d85-5269-4914-9660-c066e09cd6ef"
|
||||||
|
KeyID: "LAY65829DQ"
|
||||||
|
LoadPrivateKeyPath: "etc/merchant/AuthKey_LAY65829DQ.p8"
|
||||||
|
Ali:
|
||||||
|
Code: "d55b58829efb41c8aa8e86769cba4844"
|
||||||
|
SystemConfig:
|
||||||
|
ThreeVerify: true
|
||||||
|
WechatH5:
|
||||||
|
AppID: "wxa581992dc74d860e"
|
||||||
|
AppSecret: "ba37510206df321279222cecb8614e00"
|
||||||
|
Query:
|
||||||
|
ShareLinkExpire: 604800 # 7天 = 7 * 24 * 60 * 60 = 604800秒
|
6
app/main/api/etc/merchant/AuthKey_LAY65829DQ.p8
Normal file
6
app/main/api/etc/merchant/AuthKey_LAY65829DQ.p8
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgkidSHV1OeJN84sDD
|
||||||
|
xWLGIVjTyhn6sAQDyHfqKW6lxnGgCgYIKoZIzj0DAQehRANCAAQSAlAcuuuRNFqk
|
||||||
|
aMPVpXxsiR/pwhyM62tFhdFsbULq1C7MItQxKVMKCiwz3r5rZZy7HcbkqL47LPZ1
|
||||||
|
q6V8Wyop
|
||||||
|
-----END PRIVATE KEY-----
|
43
app/main/api/etc/merchant/alipayCertPublicKey_RSA2.crt
Normal file
43
app/main/api/etc/merchant/alipayCertPublicKey_RSA2.crt
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDtTCCAp2gAwIBAgIQICUDBjgAYvSDOiVZlr/A9zANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE
|
||||||
|
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs
|
||||||
|
YXNzIDIgUjEwHhcNMjUwMzA2MTE1ODQ2WhcNMzAwMzA1MTE1ODQ2WjCBlTELMAkGA1UEBhMCQ04x
|
||||||
|
MDAuBgNVBAoMJ+a1t+WNl+Wkqei/nOWkp+aVsOaNruenkeaKgOaciemZkOWFrOWPuDEPMA0GA1UE
|
||||||
|
CwwGQWxpcGF5MUMwQQYDVQQDDDrmlK/ku5jlrp0o5Lit5Zu9Kee9kee7nOaKgOacr+aciemZkOWF
|
||||||
|
rOWPuC0yMDg4MDUxMDMyOTk4NDkyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0kkR
|
||||||
|
L7lgKYs7f8Xi4DNKzp2ggjwy4By7RunwT4Ur4A71HVOqRQed9r45a6/W4JPuVv51tiHMojZifEKX
|
||||||
|
7ixSlDG6be677RiNslMJ5G3mjw/+Ku01tV9Qzw5YyhvxbqmS8Qp9vgL8VPYhxqTxKO6WW+xiyVvx
|
||||||
|
ko+mrU+dbSFIVbBjp88NVVcquu+vZT/uwtjriKSwsesAm8DkKT6mTqY5P/JroMzTU7xa3/ErAMte
|
||||||
|
6t2dOsxPS7kqWjJyoLBHRk+AH87X5lNBEjLgYPk1ADU7zFsLdC+nv4fm7nihYre7fCrdCTVKguXm
|
||||||
|
PCEFBjqwSkag7BSIxRQjS3qHxi+DUMst7wIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCA/gwDQYJKoZI
|
||||||
|
hvcNAQELBQADggEBAIrXa4HfvKtjIb+F5YRi1GuhdPn20tkyQaw8GB/xZ30kpe1NyQdr2D3JPSIi
|
||||||
|
wd+MBGEhAF2HrD+UT9AnqsHQOwFrWJUNFArw1joMkMJQtnpD9nH1po1l0ECR5KF0gzsDroXOFXsW
|
||||||
|
QVicHhbZ4J54LswgedEKURETP74o/NdTD24IzXt+rjQe1Nsu7mgkj+VqmXVtqjOIS5IllRo3TD30
|
||||||
|
h031HCg+OLGpGmJylYiD5C5Y+7YkPzJC0pzsvqLvT1yGNForSlujPB/s7rCBq4ZEX08/u2fbfMpd
|
||||||
|
PuZJgZdRmF7Xr5LV7JeeYrTzOKmzSEByXIFM0NsEdggpSD8eyqclQd4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIE4jCCAsqgAwIBAgIIYsSr5bKAMl8wDQYJKoZIhvcNAQELBQAwejELMAkGA1UEBhMCQ04xFjAU
|
||||||
|
BgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEw
|
||||||
|
LwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMy
|
||||||
|
MjE0MzQxNVoXDTM3MTEyNjE0MzQxNVowgYIxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1BbnQgRmlu
|
||||||
|
YW5jaWFsMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE5MDcGA1UEAwwwQW50IEZp
|
||||||
|
bmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDbGFzcyAyIFIxMIIBIjANBgkqhkiG9w0B
|
||||||
|
AQEFAAOCAQ8AMIIBCgKCAQEAsLMfYaoRoPRbmDcAfXPCmKf43pWRN5yTXa/KJWO0l+mrgQvs89bA
|
||||||
|
NEvbDUxlkGwycwtwi5DgBuBgVhLliXu+R9CYgr2dXs8D8Hx/gsggDcyGPLmVrDOnL+dyeauheARZ
|
||||||
|
fA3du60fwEwwbGcVIpIxPa/4n3IS/ElxQa6DNgqxh8J9Xwh7qMGl0JK9+bALuxf7B541Gr4p0WEN
|
||||||
|
G8fhgjBV4w4ut9eQLOoa1eddOUSZcy46Z7allwowwgt7b5VFfx/P1iKJ3LzBMgkCK7GZ2kiLrL7R
|
||||||
|
iqV+h482J7hkJD+ardoc6LnrHO/hIZymDxok+VH9fVeUdQa29IZKrIDVj65THQIDAQABo2MwYTAf
|
||||||
|
BgNVHSMEGDAWgBRfdLQEwE8HWurlsdsio4dBspzhATAdBgNVHQ4EFgQUSqHkYINtUSAtDPnS8Xoy
|
||||||
|
oP9p7qEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIB
|
||||||
|
AIQ8TzFy4bVIVb8+WhHKCkKNPcJe2EZuIcqvRoi727lZTJOfYy/JzLtckyZYfEI8J0lasZ29wkTt
|
||||||
|
a1IjSo+a6XdhudU4ONVBrL70U8Kzntplw/6TBNbLFpp7taRALjUgbCOk4EoBMbeCL0GiYYsTS0mw
|
||||||
|
7xdySzmGQku4GTyqutIGPQwKxSj9iSFw1FCZqr4VP4tyXzMUgc52SzagA6i7AyLedd3tbS6lnR5B
|
||||||
|
L+W9Kx9hwT8L7WANAxQzv/jGldeuSLN8bsTxlOYlsdjmIGu/C9OWblPYGpjQQIRyvs4Cc/mNhrh+
|
||||||
|
14EQgwuemIIFDLOgcD+iISoN8CqegelNcJndFw1PDN6LkVoiHz9p7jzsge8RKay/QW6C03KNDpWZ
|
||||||
|
EUCgCUdfHfo8xKeR+LL1cfn24HKJmZt8L/aeRZwZ1jwePXFRVtiXELvgJuM/tJDIFj2KD337iV64
|
||||||
|
fWcKQ/ydDVGqfDZAdcU4hQdsrPWENwPTQPfVPq2NNLMyIH9+WKx9Ed6/WzeZmIy5ZWpX1TtTolo6
|
||||||
|
OJXQFeItMAjHxW/ZSZTok5IS3FuRhExturaInnzjYpx50a6kS34c5+c8hYq7sAtZ/CNLZmBnBCFD
|
||||||
|
aMQqT8xFZJ5uolUaSeXxg7JFY1QsYp5RKvj4SjFwCGKJ2+hPPe9UyyltxOidNtxjaknOCeBHytOr
|
||||||
|
-----END CERTIFICATE-----
|
88
app/main/api/etc/merchant/alipayRootCert.crt
Normal file
88
app/main/api/etc/merchant/alipayRootCert.crt
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG
|
||||||
|
EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw
|
||||||
|
MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO
|
||||||
|
UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE
|
||||||
|
MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT
|
||||||
|
V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti
|
||||||
|
W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ
|
||||||
|
MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b
|
||||||
|
53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI
|
||||||
|
pDoiVhsLwg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE
|
||||||
|
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj
|
||||||
|
YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj
|
||||||
|
YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0
|
||||||
|
MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV
|
||||||
|
BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j
|
||||||
|
aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF
|
||||||
|
AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk
|
||||||
|
rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2
|
||||||
|
xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp
|
||||||
|
dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6
|
||||||
|
vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl
|
||||||
|
YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1
|
||||||
|
Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H
|
||||||
|
DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98
|
||||||
|
SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG
|
||||||
|
PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe
|
||||||
|
9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC
|
||||||
|
AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90
|
||||||
|
tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy
|
||||||
|
nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf
|
||||||
|
tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq
|
||||||
|
JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3
|
||||||
|
IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW
|
||||||
|
05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41
|
||||||
|
T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI
|
||||||
|
kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop
|
||||||
|
PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N
|
||||||
|
1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y
|
||||||
|
jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02
|
||||||
|
77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi
|
||||||
|
kT9qhqn+lw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG
|
||||||
|
EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh
|
||||||
|
dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh
|
||||||
|
dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0
|
||||||
|
WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE
|
||||||
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp
|
||||||
|
YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA
|
||||||
|
IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU
|
||||||
|
WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt
|
||||||
|
rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ
|
||||||
|
4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2
|
||||||
|
zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg
|
||||||
|
wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH
|
||||||
|
Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF
|
||||||
|
BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM
|
||||||
|
E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg
|
||||||
|
MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq
|
||||||
|
MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp
|
||||||
|
bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv
|
||||||
|
b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV
|
||||||
|
nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5
|
||||||
|
4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg
|
||||||
|
wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw
|
||||||
|
WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN
|
||||||
|
z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g
|
||||||
|
KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA
|
||||||
|
uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF
|
||||||
|
MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp
|
||||||
|
emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3
|
||||||
|
U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I
|
||||||
|
UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn
|
||||||
|
DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU
|
||||||
|
1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX
|
||||||
|
Yf4Zr0fJsGuv
|
||||||
|
-----END CERTIFICATE-----
|
28
app/main/api/etc/merchant/apiclient_key.pem
Normal file
28
app/main/api/etc/merchant/apiclient_key.pem
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDd7p4NV2SkjF3d
|
||||||
|
zLDltShURK21VIMalnjimqpXiFSuwwIlMb3Ad6rQyClpRAHA4V/POnRlPEDc7ddm
|
||||||
|
W97uw01Fyn1Hapta3aeHTA4EOdzUVk9i74ZiLKP1SJgNNelonAD6YFmqlVvvBV9w
|
||||||
|
ufCUu+9GAM8h9tdHlVR6o+BG3hP5A7FH/yuPuXplf1SuQh/SBahxX37zP0Av14g+
|
||||||
|
FS9slawJiAn9wEpDb2moj3Y6i+afDA8nsgZNBhnMcv49VV0pwx/oKTQMATcavR0d
|
||||||
|
DKgohqLiUG+KtgoJU3KutiarQZRiVf4iSTHw+G8IGl8f/3LqgUK18QoX81hGp68F
|
||||||
|
hnWp/5KdAgMBAAECggEBAMY+lrS4MlDCij7Mz+ABmQrdZoYp/grMCyPwoOUcBPkv
|
||||||
|
fUUYT7YTr2RcyJEdjKttJxaH0t1zm0U+uEDZJCUIFIiZPpuC4U+j3DiBeavQvDB5
|
||||||
|
AOURrWsZEUTUGe8DD4LAiCcf1jkIvlye4ghiMEPMNQrFQkHGq7tn61S5+meTjSfL
|
||||||
|
uJz1Ta587R/2ptAyo/QE0iKTFRRvymekOb0OLu7nyIC9vTCD7V9xjARwp2OwBDBu
|
||||||
|
Ztdv7WTFLeoO3Xt+Liopvwk1DNiqhamnLeBr/UttqYbtkotGO7wUlwZW9yM5fCnp
|
||||||
|
GHhuaejVk4eEw34lurEo8X7HMc+WwQ0/s9+5iM62RgECgYEA9Mki8eIaD2Wk0FdA
|
||||||
|
9PL7diW1h4KHMi/lb2AUXGkH4zNxp6k0bmT4n5S588OkXsT8YgUdAhwfTz+M3Olz
|
||||||
|
e39rwcN7u4NCoOmNcwfpW1o7w6rn04aC2Iz1SpZhtM+DBVhuS87VmC3ViGt242FW
|
||||||
|
bfSrSw0vDrvjMIj/5ApiVpwf2N0CgYEA6Blz0IBedtQkjBf+OC33wnBNwq/5VICs
|
||||||
|
V8eAHsq/EexRf2Z/JtCkPDYCiLddLjRt+jIPFCPyR8AsKQf8vdUFfhZ029GBCCrZ
|
||||||
|
usn1hoN3rDv4GuOMXJWCvpS45KoXZt8h31NTRAVqKRWXsIWkARu0++J6NfZR8FO7
|
||||||
|
Jrx/QnKWJMECgYEA5HDlHMk+OspH8mrLYw1z4UG11H3a/9o1CyimN8uJId57ndVJ
|
||||||
|
6hBu+jaJB1W4ivzY7/0HolVuXr3XDr8LF+DFRnHRgiAwSQ1NBWIHxEpEZgmUChKI
|
||||||
|
/+EkdXQ8QMo74vwxCqw/J6L2mTZ5ICBR0ZG5XfQyy1RK5Jul+0I5ncxb6D0CgYAJ
|
||||||
|
6aRfoEvoiVDyRsgNwDDXthIsIXXlnQU/Tn7zUbdtXYlxhoAhuUF6bNgY3LP3GDgm
|
||||||
|
OmMYehyL4fJA4l1yAhoU84KULNN09NeNubhpwU2oJnuHMna5MY1+9D0dTwJm21rH
|
||||||
|
/fgNbKnHDWwIFv0VKwjExTxw948yU3Eny18oCFrPQQKBgQCCHWUVIzzci/YkX3lv
|
||||||
|
IzSgs4VTs4979hGeUYB4u+ihVU3cpXGLbuhm37Cgf0aX+I5vyxplKURgxg8jGnPB
|
||||||
|
KDuI2+1TlwXYt+5zCrpmBtZXpQbknde5Pfser+PMuGjybeWWpHzek7kZKPNCHwTL
|
||||||
|
BJG/ccbM6dULpIVcziB/hQMvLA==
|
||||||
|
-----END PRIVATE KEY-----
|
@ -0,0 +1,23 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEozCCA4ugAwIBAgIQICUDBmfevHFjK0cMiK6zxDANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE
|
||||||
|
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs
|
||||||
|
YXNzIDEgUjEwHhcNMjUwMzA2MTE1ODQ1WhcNMzAwMzA1MTE1ODQ1WjBrMQswCQYDVQQGEwJDTjEw
|
||||||
|
MC4GA1UECgwn5rW35Y2X5aSp6L+c5aSn5pWw5o2u56eR5oqA5pyJ6ZmQ5YWs5Y+4MQ8wDQYDVQQL
|
||||||
|
DAZBbGlwYXkxGTAXBgNVBAMMEDIwODgwNTEwMzI5OTg0OTIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
||||||
|
DwAwggEKAoIBAQCA1mtTVZmB/7/wWV37Z8hUXEXFs0Gn1/Ie7c6rPQQRUlPHyJGcPAZvDii+ySC1
|
||||||
|
/bplneMENRAjCuoJEM1z4X1FMt8rLggCqnF1xzUN2p9fdXUwcRPmSV4yi9ggMiFXldm0/eyaobV2
|
||||||
|
fj0/VSLED2Qc8xBStM9pqkfszwf2rsAAKL15WQXOUiQw0s25s+Du18H4+YgkQ0HBr0+VPfhL4QoO
|
||||||
|
vsE34ZYP0TuTwxVheYNkvSOPXFXmtE3z/b+75y2n2msa9S4HItNVYpOkB7z3GDB+0/rvX+Q+GvYI
|
||||||
|
9BSBbgJwEuqiMN2SwQyAjH608JBoAUGnk0ygfG8juF77shBxzr/vAgMBAAGjggEpMIIBJTAfBgNV
|
||||||
|
HSMEGDAWgBRxB+IEYRbk5fJl6zEPyeD0PJrVkTAdBgNVHQ4EFgQU8Izqtjr8qvIpRYglmzELt22E
|
||||||
|
b7MwQAYDVR0gBDkwNzA1BgdggRwBbgEBMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9jYS5hbGlwYXku
|
||||||
|
Y29tL2Nwcy5wZGYwDgYDVR0PAQH/BAQDAgbAMC8GA1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9jYS5h
|
||||||
|
bGlwYXkuY29tL2NybDk5LmNybDBgBggrBgEFBQcBAQRUMFIwKAYIKwYBBQUHMAKGHGh0dHA6Ly9j
|
||||||
|
YS5hbGlwYXkuY29tL2NhNi5jZXIwJgYIKwYBBQUHMAGGGmh0dHA6Ly9jYS5hbGlwYXkuY29tOjgz
|
||||||
|
NDAvMA0GCSqGSIb3DQEBCwUAA4IBAQC5j9d26HpXXf/eC40ejQ8E/r5PwN87129jfdDpCQGVJopL
|
||||||
|
ZyrJzxAHoPW+pG5lbDGmlDC9g8CRgeVcpNNkKDshyDAjlAoKbedTSaI8Bacly6fKPlCwAipepiy3
|
||||||
|
fBTovcQYgPNl4aw3spi/0ZsnoTJ3Ye8n7KD4j3j3iBwptXdWFDVSQCJFSdC5tSMQSnm6WUgW3Duw
|
||||||
|
UalPi2I5CjxCZK35Pbk0GFP5dJwtz4h3YGkLX20TP18HZi0hVrxOErH5U2mP+dlq72DclJEZZZj0
|
||||||
|
PPMyOLUqmcQRWMmaVmGhDKpkcx81jSowFKuPlSQfU0dCXZGdqpnXVnAYlLMuMAILQqE+
|
||||||
|
-----END CERTIFICATE-----
|
9
app/main/api/etc/merchant/pub_key.pem
Normal file
9
app/main/api/etc/merchant/pub_key.pem
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsNH2kztg9gybkuulreL+
|
||||||
|
BMyakxmKTFqrujYLm+S40v64KbNH3+sWdf1XR59vWjSvGWo+BAbuSIHNmIIFMFKE
|
||||||
|
sUxqHAYbta4oD9Ogr0+88drnXv+AA6vxQML0KaaTuHessvUhGC5GEUxa+TFefO9/
|
||||||
|
EjbwL1E/XQ8oBkxHJO6RjKevuts39RjEyocnNhV7m8RP6WIBQeJDXhbfO1etcwdJ
|
||||||
|
B2yQ1eoPK9kGAqQ7wL4pDXrLXMfS1DXlNHsLf4if7rwu3fibk/qfkKdtmqvUw39f
|
||||||
|
tCKZRiexIq6ad9kTTjouXUU5EMRAn3ocRvNzCD4RaW1qVYMxFQ8AraQ8W3MXlPeL
|
||||||
|
EQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
98
app/main/api/internal/config/config.go
Normal file
98
app/main/api/internal/config/config.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||||
|
"github.com/zeromicro/go-zero/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
rest.RestConf
|
||||||
|
DataSource string
|
||||||
|
CacheRedis cache.CacheConf
|
||||||
|
JwtAuth JwtAuth // JWT 鉴权相关配置
|
||||||
|
VerifyCode VerifyCode
|
||||||
|
Encrypt Encrypt
|
||||||
|
Alipay AlipayConfig
|
||||||
|
Wxpay WxpayConfig
|
||||||
|
Applepay ApplepayConfig
|
||||||
|
Ali AliConfig
|
||||||
|
WestConfig WestConfig
|
||||||
|
YushanConfig YushanConfig
|
||||||
|
SystemConfig SystemConfig
|
||||||
|
WechatH5 WechatH5Config
|
||||||
|
Query QueryConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// JwtAuth 用于 JWT 鉴权配置
|
||||||
|
type JwtAuth struct {
|
||||||
|
AccessSecret string // JWT 密钥,用于签发 Token
|
||||||
|
AccessExpire int64 // Token 过期时间,单位为秒
|
||||||
|
RefreshAfter int64
|
||||||
|
}
|
||||||
|
type VerifyCode struct {
|
||||||
|
AccessKeyID string
|
||||||
|
AccessKeySecret string
|
||||||
|
EndpointURL string
|
||||||
|
SignName string
|
||||||
|
TemplateCode string
|
||||||
|
ValidTime int
|
||||||
|
}
|
||||||
|
type Encrypt struct {
|
||||||
|
SecretKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
type AlipayConfig struct {
|
||||||
|
AppID string
|
||||||
|
PrivateKey string
|
||||||
|
AlipayPublicKey string
|
||||||
|
AppCertPath string // 应用公钥证书路径
|
||||||
|
AlipayCertPath string // 支付宝公钥证书路径
|
||||||
|
AlipayRootCertPath string // 根证书路径
|
||||||
|
IsProduction bool
|
||||||
|
NotifyUrl string
|
||||||
|
ReturnURL string
|
||||||
|
}
|
||||||
|
type WxpayConfig struct {
|
||||||
|
AppID string
|
||||||
|
MchID string
|
||||||
|
MchCertificateSerialNumber string
|
||||||
|
MchApiv3Key string
|
||||||
|
MchPrivateKeyPath string
|
||||||
|
MchPublicKeyID string
|
||||||
|
MchPublicKeyPath string
|
||||||
|
NotifyUrl string
|
||||||
|
RefundNotifyUrl string
|
||||||
|
}
|
||||||
|
type AliConfig struct {
|
||||||
|
Code string
|
||||||
|
}
|
||||||
|
type ApplepayConfig struct {
|
||||||
|
ProductionVerifyURL string
|
||||||
|
SandboxVerifyURL string // 沙盒环境的验证 URL
|
||||||
|
Sandbox bool
|
||||||
|
BundleID string
|
||||||
|
IssuerID string
|
||||||
|
KeyID string
|
||||||
|
LoadPrivateKeyPath string
|
||||||
|
}
|
||||||
|
type WestConfig struct {
|
||||||
|
Url string
|
||||||
|
Key string
|
||||||
|
SecretId string
|
||||||
|
SecretSecondId string
|
||||||
|
}
|
||||||
|
type YushanConfig struct {
|
||||||
|
ApiKey string
|
||||||
|
AcctID string
|
||||||
|
Url string
|
||||||
|
}
|
||||||
|
type SystemConfig struct {
|
||||||
|
ThreeVerify bool
|
||||||
|
}
|
||||||
|
type WechatH5Config struct {
|
||||||
|
AppID string
|
||||||
|
AppSecret string
|
||||||
|
}
|
||||||
|
type QueryConfig struct {
|
||||||
|
ShareLinkExpire int64
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ActivateAgentMembershipHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.AgentActivateMembershipReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewActivateAgentMembershipLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.ActivateAgentMembership(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
29
app/main/api/internal/handler/agent/agentrealnamehandler.go
Normal file
29
app/main/api/internal/handler/agent/agentrealnamehandler.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AgentRealNameHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.AgentRealNameReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewAgentRealNameLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.AgentRealName(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AgentWithdrawalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.WithdrawalReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewAgentWithdrawalLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.AgentWithdrawal(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/agent/applyforagenthandler.go
Normal file
30
app/main/api/internal/handler/agent/applyforagenthandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ApplyForAgentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.AgentApplyReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewApplyForAgentLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.ApplyForAgent(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/agent/generatinglinkhandler.go
Normal file
30
app/main/api/internal/handler/agent/generatinglinkhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GeneratingLinkHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.AgentGeneratingLinkReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGeneratingLinkLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GeneratingLink(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentAuditStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := agent.NewGetAgentAuditStatusLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentAuditStatus()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentCommissionHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetCommissionReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentCommissionLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentCommission(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
17
app/main/api/internal/handler/agent/getagentinfohandler.go
Normal file
17
app/main/api/internal/handler/agent/getagentinfohandler.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := agent.NewGetAgentInfoLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentInfo()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentMembershipProductConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.AgentMembershipProductConfigReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentMembershipProductConfigLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentMembershipProductConfig(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentProductConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := agent.NewGetAgentProductConfigLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentProductConfig()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentRevenueInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetAgentRevenueInfoReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentRevenueInfoLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentRevenueInfo(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentRewardsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetRewardsReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentRewardsLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentRewards(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentSubordinateContributionDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetAgentSubordinateContributionDetailReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentSubordinateContributionDetailLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentSubordinateContributionDetail(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentSubordinateListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetAgentSubordinateListReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentSubordinateListLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentSubordinateList(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAgentWithdrawalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetWithdrawalReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetAgentWithdrawalLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAgentWithdrawal(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/agent/getlinkdatahandler.go
Normal file
30
app/main/api/internal/handler/agent/getlinkdatahandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetLinkDataHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetLinkDataReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewGetLinkDataLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetLinkData(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/agent"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SaveAgentMembershipUserConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.SaveAgentMembershipUserConfigReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := agent.NewSaveAgentMembershipUserConfigLogic(r.Context(), svcCtx)
|
||||||
|
err := l.SaveAgentMembershipUserConfig(&req)
|
||||||
|
result.HttpResult(r, w, nil, err)
|
||||||
|
}
|
||||||
|
}
|
17
app/main/api/internal/handler/app/getappversionhandler.go
Normal file
17
app/main/api/internal/handler/app/getappversionhandler.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/app"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAppVersionHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := app.NewGetAppVersionLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetAppVersion()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
17
app/main/api/internal/handler/app/healthcheckhandler.go
Normal file
17
app/main/api/internal/handler/app/healthcheckhandler.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/app"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HealthCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := app.NewHealthCheckLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.HealthCheck()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/auth/sendsmshandler.go
Normal file
30
app/main/api/internal/handler/auth/sendsmshandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/auth"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SendSmsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.SendSmsReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := auth.NewSendSmsLogic(r.Context(), svcCtx)
|
||||||
|
err := l.SendSms(&req)
|
||||||
|
result.HttpResult(r, w, nil, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package notification
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/notification"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetNotificationsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := notification.NewGetNotificationsLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetNotifications()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
17
app/main/api/internal/handler/pay/alipaycallbackhandler.go
Normal file
17
app/main/api/internal/handler/pay/alipaycallbackhandler.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/pay"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AlipayCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := pay.NewAlipayCallbackLogic(r.Context(), svcCtx)
|
||||||
|
err := l.AlipayCallback(w, r)
|
||||||
|
result.HttpResult(r, w, nil, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/pay/iapcallbackhandler.go
Normal file
30
app/main/api/internal/handler/pay/iapcallbackhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/pay"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IapCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.IapCallbackReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := pay.NewIapCallbackLogic(r.Context(), svcCtx)
|
||||||
|
err := l.IapCallback(&req)
|
||||||
|
result.HttpResult(r, w, nil, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/pay/paymentcheckhandler.go
Normal file
30
app/main/api/internal/handler/pay/paymentcheckhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/pay"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PaymentCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.PaymentCheckReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := pay.NewPaymentCheckLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.PaymentCheck(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/pay/paymenthandler.go
Normal file
30
app/main/api/internal/handler/pay/paymenthandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/pay"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PaymentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.PaymentReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := pay.NewPaymentLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.Payment(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/pay"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WechatPayCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := pay.NewWechatPayCallbackLogic(r.Context(), svcCtx)
|
||||||
|
err := l.WechatPayCallback(w, r)
|
||||||
|
result.HttpResult(r, w, nil, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/pay"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WechatPayRefundCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := pay.NewWechatPayRefundCallbackLogic(r.Context(), svcCtx)
|
||||||
|
err := l.WechatPayRefundCallback(w, r)
|
||||||
|
result.HttpResult(r, w, nil, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/product"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProductAppByEnHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetProductByEnRequest
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := product.NewGetProductAppByEnLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetProductAppByEn(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/product"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProductByEnHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetProductByEnRequest
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := product.NewGetProductByEnLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetProductByEn(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/product"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProductByIDHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetProductByIDRequest
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := product.NewGetProductByIDLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetProductByID(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryDetailByOrderIdHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryDetailByOrderIdReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryDetailByOrderIdLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryDetailByOrderId(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryDetailByOrderNoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryDetailByOrderNoReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryDetailByOrderNoLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryDetailByOrderNo(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/query/queryexamplehandler.go
Normal file
30
app/main/api/internal/handler/query/queryexamplehandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryExampleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryExampleReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryExampleLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryExample(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryGenerateShareLinkHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryGenerateShareLinkReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryGenerateShareLinkLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryGenerateShareLink(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/query/querylisthandler.go
Normal file
30
app/main/api/internal/handler/query/querylisthandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryListReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryListLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryList(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryProvisionalOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryProvisionalOrderReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryProvisionalOrderLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryProvisionalOrder(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/query/queryretryhandler.go
Normal file
30
app/main/api/internal/handler/query/queryretryhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryRetryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryRetryReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryRetryLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryRetry(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryServiceAgentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryServiceReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryServiceLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryService(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryServiceAppHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryServiceReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryServiceLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryService(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
25
app/main/api/internal/handler/query/queryservicehandler.go
Normal file
25
app/main/api/internal/handler/query/queryservicehandler.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryServiceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryServiceReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryServiceLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryService(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryShareDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QueryShareDetailReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQueryShareDetailLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QueryShareDetail(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QuerySingleTestHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.QuerySingleTestReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewQuerySingleTestLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.QuerySingleTest(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/query"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 更新查询数据
|
||||||
|
func UpdateQueryDataHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.UpdateQueryDataReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := query.NewUpdateQueryDataLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.UpdateQueryData(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
424
app/main/api/internal/handler/routes.go
Normal file
424
app/main/api/internal/handler/routes.go
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
agent "tydata-server/app/user/cmd/api/internal/handler/agent"
|
||||||
|
app "tydata-server/app/user/cmd/api/internal/handler/app"
|
||||||
|
auth "tydata-server/app/user/cmd/api/internal/handler/auth"
|
||||||
|
notification "tydata-server/app/user/cmd/api/internal/handler/notification"
|
||||||
|
pay "tydata-server/app/user/cmd/api/internal/handler/pay"
|
||||||
|
product "tydata-server/app/user/cmd/api/internal/handler/product"
|
||||||
|
query "tydata-server/app/user/cmd/api/internal/handler/query"
|
||||||
|
user "tydata-server/app/user/cmd/api/internal/handler/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/audit/status",
|
||||||
|
Handler: agent.GetAgentAuditStatusHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/generating_link",
|
||||||
|
Handler: agent.GeneratingLinkHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/info",
|
||||||
|
Handler: agent.GetAgentInfoHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/product_config",
|
||||||
|
Handler: agent.GetAgentProductConfigHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/real_name",
|
||||||
|
Handler: agent.AgentRealNameHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/subordinate/contribution/detail",
|
||||||
|
Handler: agent.GetAgentSubordinateContributionDetailHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/subordinate/list",
|
||||||
|
Handler: agent.GetAgentSubordinateListHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1/agent"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/membership/save_user_config",
|
||||||
|
Handler: agent.SaveAgentMembershipUserConfigHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/membership/user_config",
|
||||||
|
Handler: agent.GetAgentMembershipProductConfigHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1/agent"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/commission",
|
||||||
|
Handler: agent.GetAgentCommissionHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/membership/activate",
|
||||||
|
Handler: agent.ActivateAgentMembershipHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/revenue",
|
||||||
|
Handler: agent.GetAgentRevenueInfoHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/rewards",
|
||||||
|
Handler: agent.GetAgentRewardsHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/withdrawal",
|
||||||
|
Handler: agent.GetAgentWithdrawalHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/withdrawal",
|
||||||
|
Handler: agent.AgentWithdrawalHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1/agent"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/apply",
|
||||||
|
Handler: agent.ApplyForAgentHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/link",
|
||||||
|
Handler: agent.GetLinkDataHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1/agent"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/app/version",
|
||||||
|
Handler: app.GetAppVersionHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 心跳检测接口
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/health/check",
|
||||||
|
Handler: app.HealthCheckHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// get mobile verify code
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/auth/sendSms",
|
||||||
|
Handler: auth.SendSmsHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// get notifications
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/notification/list",
|
||||||
|
Handler: notification.GetNotificationsHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/pay/alipay/callback",
|
||||||
|
Handler: pay.AlipayCallbackHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/pay/wechat/callback",
|
||||||
|
Handler: pay.WechatPayCallbackHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/pay/wechat/refund_callback",
|
||||||
|
Handler: pay.WechatPayRefundCallbackHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
rest.WithMiddlewares(
|
||||||
|
[]rest.Middleware{serverCtx.SourceInterceptor},
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/pay/check",
|
||||||
|
Handler: pay.PaymentCheckHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/pay/iap_callback",
|
||||||
|
Handler: pay.IapCallbackHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/pay/payment",
|
||||||
|
Handler: pay.PaymentHandler(serverCtx),
|
||||||
|
},
|
||||||
|
}...,
|
||||||
|
),
|
||||||
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/:id",
|
||||||
|
Handler: product.GetProductByIDHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/en/:product_en",
|
||||||
|
Handler: product.GetProductByEnHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1/product"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/app_en/:product_en",
|
||||||
|
Handler: product.GetProductAppByEnHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1/product"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
rest.WithMiddlewares(
|
||||||
|
[]rest.Middleware{serverCtx.AuthInterceptor},
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// query service agent
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/query/service_agent/:product",
|
||||||
|
Handler: query.QueryServiceAgentHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/query/service_app/:product",
|
||||||
|
Handler: query.QueryServiceAppHandler(serverCtx),
|
||||||
|
},
|
||||||
|
}...,
|
||||||
|
),
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// query service
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/query/service/:product",
|
||||||
|
Handler: query.QueryServiceHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// 生成分享链接
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/query/generate_share_link",
|
||||||
|
Handler: query.QueryGenerateShareLinkHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 查询列表
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/query/list",
|
||||||
|
Handler: query.QueryListHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 查询详情 按订单号 付款查询时
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/query/orderId/:order_id",
|
||||||
|
Handler: query.QueryDetailByOrderIdHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 查询详情 按订单号
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/query/orderNo/:order_no",
|
||||||
|
Handler: query.QueryDetailByOrderNoHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 获取查询临时订单
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/query/provisional_order/:id",
|
||||||
|
Handler: query.QueryProvisionalOrderHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 重试查询
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/query/retry/:id",
|
||||||
|
Handler: query.QueryRetryHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 更新查询数据
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/query/update_data",
|
||||||
|
Handler: query.UpdateQueryDataHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// 查询示例
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/query/example",
|
||||||
|
Handler: query.QueryExampleHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 查询详情
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/query/share/:id",
|
||||||
|
Handler: query.QueryShareDetailHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/query/single/test",
|
||||||
|
Handler: query.QuerySingleTestHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// agent mobile code login
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/agent_mobile_code_login",
|
||||||
|
Handler: user.AgentMobileCodeLoginHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// mobile code login
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/mobileCodeLogin",
|
||||||
|
Handler: user.MobileCodeLoginHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// mobile login
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/mobileLogin",
|
||||||
|
Handler: user.MobileLoginHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// register
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/register",
|
||||||
|
Handler: user.RegisterHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// wechat mini auth
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/wxMiniAuth",
|
||||||
|
Handler: user.WxMiniAuthHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// wechat h5 auth
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/wxh5Auth",
|
||||||
|
Handler: user.WxH5AuthHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// 绑定手机号
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/bindMobile",
|
||||||
|
Handler: user.BindMobileHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/cancelOut",
|
||||||
|
Handler: user.CancelOutHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// get user info
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/user/detail",
|
||||||
|
Handler: user.DetailHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// get new token
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/user/getToken",
|
||||||
|
Handler: user.GetTokenHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1"),
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AgentMobileCodeLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.MobileCodeLoginReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := user.NewAgentMobileCodeLoginLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.AgentMobileCodeLogin(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/user/bindmobilehandler.go
Normal file
30
app/main/api/internal/handler/user/bindmobilehandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BindMobileHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.BindMobileReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := user.NewBindMobileLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.BindMobile(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
17
app/main/api/internal/handler/user/cancelouthandler.go
Normal file
17
app/main/api/internal/handler/user/cancelouthandler.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CancelOutHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := user.NewCancelOutLogic(r.Context(), svcCtx)
|
||||||
|
err := l.CancelOut()
|
||||||
|
result.HttpResult(r, w, nil, err)
|
||||||
|
}
|
||||||
|
}
|
17
app/main/api/internal/handler/user/detailhandler.go
Normal file
17
app/main/api/internal/handler/user/detailhandler.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := user.NewDetailLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.Detail()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
17
app/main/api/internal/handler/user/gettokenhandler.go
Normal file
17
app/main/api/internal/handler/user/gettokenhandler.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTokenHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := user.NewGetTokenLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetToken()
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/user/mobilecodeloginhandler.go
Normal file
30
app/main/api/internal/handler/user/mobilecodeloginhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MobileCodeLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.MobileCodeLoginReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := user.NewMobileCodeLoginLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.MobileCodeLogin(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/user/mobileloginhandler.go
Normal file
30
app/main/api/internal/handler/user/mobileloginhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MobileLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.MobileLoginReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := user.NewMobileLoginLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.MobileLogin(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/user/registerhandler.go
Normal file
30
app/main/api/internal/handler/user/registerhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.RegisterReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := user.NewRegisterLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.Register(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/user/wxh5authhandler.go
Normal file
30
app/main/api/internal/handler/user/wxh5authhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WxH5AuthHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.WXH5AuthReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := user.NewWxH5AuthLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.WxH5Auth(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
30
app/main/api/internal/handler/user/wxminiauthhandler.go
Normal file
30
app/main/api/internal/handler/user/wxminiauthhandler.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/logic/user"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/result"
|
||||||
|
"tydata-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WxMiniAuthHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.WXMiniAuthReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
result.ParamErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := validator.Validate(req); err != nil {
|
||||||
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := user.NewWxMiniAuthLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.WxMiniAuth(&req)
|
||||||
|
result.HttpResult(r, w, resp, err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ActivateAgentMembershipLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewActivateAgentMembershipLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ActivateAgentMembershipLogic {
|
||||||
|
return &ActivateAgentMembershipLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (l *ActivateAgentMembershipLogic) ActivateAgentMembership(req *types.AgentActivateMembershipReq) (resp *types.AgentActivateMembershipResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败: %v", err)
|
||||||
|
}
|
||||||
|
// 查询用户代理信息
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
|
||||||
|
}
|
||||||
|
// 定义等级顺序映射
|
||||||
|
levelOrder := map[string]int{
|
||||||
|
"": 1,
|
||||||
|
model.AgentLeveNameNormal: 1,
|
||||||
|
model.AgentLeveNameVIP: 2,
|
||||||
|
model.AgentLeveNameSVIP: 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证请求等级合法性
|
||||||
|
if _, valid := levelOrder[req.Type]; !valid {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "无效的代理等级: %s", req.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果存在代理记录,进行等级验证
|
||||||
|
if agentModel != nil {
|
||||||
|
currentLevel, exists := levelOrder[agentModel.LevelName]
|
||||||
|
if !exists {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR),
|
||||||
|
"非法的当前代理等级: %s", agentModel.LevelName)
|
||||||
|
}
|
||||||
|
|
||||||
|
requestedLevel := levelOrder[req.Type]
|
||||||
|
if requestedLevel < currentLevel {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR),
|
||||||
|
"禁止降级操作(当前等级:%s,请求等级:%s)", agentModel.LevelName, req.Type)
|
||||||
|
}
|
||||||
|
// 同等级视为续费,允许操作
|
||||||
|
}
|
||||||
|
outTradeNo := "A_" + l.svcCtx.AlipayService.GenerateOutTradeNo()
|
||||||
|
redisKey := fmt.Sprintf(types.AgentVipCacheKey, userID, outTradeNo)
|
||||||
|
agentVipCache := types.AgentVipCache{Type: req.Type}
|
||||||
|
jsonData, err := json.Marshal(agentVipCache)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "序列化代理VIP缓存失败: %v", err)
|
||||||
|
}
|
||||||
|
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
|
||||||
|
if cacheErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "设置缓存失败: %v", cacheErr)
|
||||||
|
}
|
||||||
|
return &types.AgentActivateMembershipResp{
|
||||||
|
Id: outTradeNo,
|
||||||
|
}, nil
|
||||||
|
}
|
99
app/main/api/internal/logic/agent/agentrealnamelogic.go
Normal file
99
app/main/api/internal/logic/agent/agentrealnamelogic.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/service"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AgentRealNameLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAgentRealNameLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AgentRealNameLogic {
|
||||||
|
return &AgentRealNameLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *AgentRealNameLogic) AgentRealName(req *types.AgentRealNameReq) (resp *types.AgentRealNameResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败, %v", err)
|
||||||
|
}
|
||||||
|
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||||
|
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理实名, 加密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
// 检查手机号是否在一分钟内已发送过验证码
|
||||||
|
redisKey := fmt.Sprintf("%s:%s", "realName", encryptedMobile)
|
||||||
|
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, redis.Nil) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "代理实名, 验证码过期: %s", encryptedMobile)
|
||||||
|
}
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理实名, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err)
|
||||||
|
}
|
||||||
|
if cacheCode != req.Code {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "代理实名, 验证码不正确: %s", encryptedMobile)
|
||||||
|
}
|
||||||
|
agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息失败, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentRealName, err := l.svcCtx.AgentRealNameModel.FindOneByAgentId(l.ctx, agent.Id)
|
||||||
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理实名信息失败, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if agentRealName != nil && agentRealName.Status == model.AgentRealNameStatusApproved {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("代理实名信息已审核通过"), "代理实名信息已审核通过")
|
||||||
|
}
|
||||||
|
// 三要素验证
|
||||||
|
threeVerification := service.ThreeFactorVerificationRequest{
|
||||||
|
Name: req.Name,
|
||||||
|
IDCard: req.IDCard,
|
||||||
|
Mobile: req.Mobile,
|
||||||
|
}
|
||||||
|
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "三要素验证失败: %v", err)
|
||||||
|
}
|
||||||
|
if !verification.Passed {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "三要素验证不通过: %v", err)
|
||||||
|
}
|
||||||
|
agentRealName = &model.AgentRealName{
|
||||||
|
AgentId: agent.Id,
|
||||||
|
Status: model.AgentRealNameStatusApproved,
|
||||||
|
Name: req.Name,
|
||||||
|
IdCard: req.IDCard,
|
||||||
|
ApproveTime: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
|
}
|
||||||
|
_, err = l.svcCtx.AgentRealNameModel.Insert(l.ctx, nil, agentRealName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "添加代理实名信息失败, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.AgentRealNameResp{
|
||||||
|
Status: agentRealName.Status,
|
||||||
|
}, nil
|
||||||
|
}
|
327
app/main/api/internal/logic/agent/agentwithdrawallogic.go
Normal file
327
app/main/api/internal/logic/agent/agentwithdrawallogic.go
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/lzUtils"
|
||||||
|
|
||||||
|
"github.com/cenkalti/backoff/v4"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/smartwalle/alipay/v3"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 状态常量
|
||||||
|
const (
|
||||||
|
StatusProcessing = 1 // 处理中
|
||||||
|
StatusSuccess = 2 // 成功
|
||||||
|
StatusFailed = 3 // 失败
|
||||||
|
)
|
||||||
|
|
||||||
|
// 前端响应状态
|
||||||
|
const (
|
||||||
|
WithdrawStatusProcessing = 1
|
||||||
|
WithdrawStatusSuccess = 2
|
||||||
|
WithdrawStatusFailed = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type AgentWithdrawalLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAgentWithdrawalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AgentWithdrawalLogic {
|
||||||
|
return &AgentWithdrawalLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types.WithdrawalResp, error) {
|
||||||
|
var (
|
||||||
|
outBizNo string
|
||||||
|
withdrawRes = &types.WithdrawalResp{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 使用事务处理核心操作
|
||||||
|
err := l.svcCtx.AgentModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询代理信息
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
|
||||||
|
}
|
||||||
|
agentRealName, err := l.svcCtx.AgentRealNameModel.FindOneByAgentId(l.ctx, agentModel.Id)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
|
return errors.Wrapf(xerr.NewErrMsg("您未进行实名认证, 无法提现"), "您未进行实名认证")
|
||||||
|
}
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询代理实名信息失败: %v", err)
|
||||||
|
}
|
||||||
|
if agentRealName.Status != model.AgentRealNameStatusApproved {
|
||||||
|
return errors.Wrapf(xerr.NewErrMsg("您的实名认证未通过, 无法提现"), "您的实名认证未通过")
|
||||||
|
}
|
||||||
|
if agentRealName.Name != req.PayeeName {
|
||||||
|
return errors.Wrapf(xerr.NewErrMsg("您的实名认证信息不匹配, 无法提现"), "您的实名认证信息不匹配")
|
||||||
|
}
|
||||||
|
// 查询钱包
|
||||||
|
agentWallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agentModel.Id)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理钱包失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验可提现金额
|
||||||
|
if req.Amount > agentWallet.Balance {
|
||||||
|
return errors.Wrapf(xerr.NewErrMsg("您可提现的余额不足"), "获取用户ID失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成交易号
|
||||||
|
outBizNo = "W_" + l.svcCtx.AlipayService.GenerateOutTradeNo()
|
||||||
|
|
||||||
|
// 创建提现记录(初始状态为处理中)
|
||||||
|
if err = l.createWithdrawalRecord(session, agentModel.Id, req, outBizNo); err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建提现记录失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 冻结资金(事务内操作)
|
||||||
|
if err = l.freezeFunds(session, agentWallet, req.Amount); err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "资金冻结失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同步调用支付宝转账
|
||||||
|
transferResp, err := l.svcCtx.AlipayService.AliTransfer(l.ctx, req.PayeeAccount, req.PayeeName, req.Amount, "代理提现", outBizNo)
|
||||||
|
if err != nil {
|
||||||
|
l.handleTransferError(outBizNo, err, "支付宝接口调用失败")
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "支付宝接口调用失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case transferResp.Status == "SUCCESS":
|
||||||
|
// 立即处理成功状态
|
||||||
|
l.handleTransferSuccess(outBizNo, transferResp)
|
||||||
|
withdrawRes.Status = WithdrawStatusSuccess
|
||||||
|
case transferResp.Status == "FAIL" || transferResp.SubCode != "":
|
||||||
|
// 处理明确失败
|
||||||
|
errorMsg := l.mapAlipayError(transferResp.SubCode)
|
||||||
|
l.handleTransferFailure(outBizNo, transferResp)
|
||||||
|
withdrawRes.Status = WithdrawStatusFailed
|
||||||
|
withdrawRes.FailMsg = errorMsg
|
||||||
|
case transferResp.Status == "DEALING":
|
||||||
|
// 处理中状态,启动异步轮询
|
||||||
|
go l.startAsyncPolling(outBizNo)
|
||||||
|
withdrawRes.Status = WithdrawStatusProcessing
|
||||||
|
default:
|
||||||
|
// 未知状态按失败处理
|
||||||
|
l.handleTransferError(outBizNo, fmt.Errorf("未知状态:%s", transferResp.Status), "支付宝返回未知状态")
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "支付宝接口调用失败: %v", err)
|
||||||
|
}
|
||||||
|
return withdrawRes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 错误类型映射
|
||||||
|
func (l *AgentWithdrawalLogic) mapAlipayError(code string) string {
|
||||||
|
errorMapping := map[string]string{
|
||||||
|
// 账户存在性错误
|
||||||
|
"PAYEE_ACCOUNT_NOT_EXSIT": "收款账户不存在,请检查账号是否正确",
|
||||||
|
"PAYEE_NOT_EXIST": "收款账户不存在或姓名有误,请核实信息",
|
||||||
|
"PAYEE_ACC_OCUPIED": "收款账号存在多个账户,无法确认唯一性",
|
||||||
|
"PAYEE_MID_CANNOT_SAME": "收款方和中间方不能是同一个人,请修改收款方或者中间方信息",
|
||||||
|
|
||||||
|
// 实名认证问题
|
||||||
|
"PAYEE_CERTIFY_LEVEL_LIMIT": "收款方未完成实名认证",
|
||||||
|
"PAYEE_NOT_RELNAME_CERTIFY": "收款方未完成实名认证",
|
||||||
|
"PAYEE_CERT_INFO_ERROR": "收款方证件信息不匹配",
|
||||||
|
|
||||||
|
// 账户状态异常
|
||||||
|
"PAYEE_ACCOUNT_STATUS_ERROR": "收款账户状态异常,请更换账号",
|
||||||
|
"PAYEE_USERINFO_STATUS_ERROR": "收款账户状态异常,无法收款",
|
||||||
|
"PERMIT_LIMIT_PAYEE": "收款账户异常,请更换账号",
|
||||||
|
"BLOCK_USER_FORBBIDEN_RECIEVE": "账户冻结无法收款",
|
||||||
|
"PAYEE_TRUSTEESHIP_ACC_OVER_LIMIT": "收款方托管子户累计收款金额超限",
|
||||||
|
|
||||||
|
// 账户信息错误
|
||||||
|
"PAYEE_USERINFO_ERROR": "收款方姓名或信息不匹配",
|
||||||
|
"PAYEE_CARD_INFO_ERROR": "收款支付宝账号及户名不一致",
|
||||||
|
"PAYEE_IDENTITY_NOT_MATCH": "收款方身份信息不匹配",
|
||||||
|
"PAYEE_USER_IS_INST": "收款方为金融机构,不能使用提现功能,请更换收款账号",
|
||||||
|
"PAYEE_USER_TYPE_ERROR": "该支付宝账号类型不支持提现,请更换收款账号",
|
||||||
|
|
||||||
|
// 权限与限制
|
||||||
|
"PAYEE_RECEIVE_COUNT_EXCEED_LIMIT": "收款次数超限,请明日再试",
|
||||||
|
"PAYEE_OUT_PERMLIMIT_CHECK_FAILURE": "收款方权限校验不通过",
|
||||||
|
"PERMIT_NON_BANK_LIMIT_PAYEE": "收款方未完善身份信息,无法收款",
|
||||||
|
}
|
||||||
|
if msg, ok := errorMapping[code]; ok {
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
return "系统错误,请联系客服"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建提现记录(事务内操作)
|
||||||
|
func (l *AgentWithdrawalLogic) createWithdrawalRecord(session sqlx.Session, agentID int64, req *types.WithdrawalReq, outBizNo string) error {
|
||||||
|
record := &model.AgentWithdrawal{
|
||||||
|
AgentId: agentID,
|
||||||
|
WithdrawNo: outBizNo,
|
||||||
|
PayeeAccount: req.PayeeAccount,
|
||||||
|
Amount: req.Amount,
|
||||||
|
Status: StatusProcessing,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := l.svcCtx.AgentWithdrawalModel.Insert(l.ctx, session, record)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 冻结资金(事务内操作)
|
||||||
|
func (l *AgentWithdrawalLogic) freezeFunds(session sqlx.Session, wallet *model.AgentWallet, amount float64) error {
|
||||||
|
wallet.Balance -= amount
|
||||||
|
wallet.FrozenBalance += amount
|
||||||
|
err := l.svcCtx.AgentWalletModel.UpdateWithVersion(l.ctx, session, wallet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理异步轮询
|
||||||
|
func (l *AgentWithdrawalLogic) startAsyncPolling(outBizNo string) {
|
||||||
|
go func() {
|
||||||
|
detachedCtx := context.WithoutCancel(l.ctx)
|
||||||
|
retryConfig := &backoff.ExponentialBackOff{
|
||||||
|
InitialInterval: 10 * time.Second,
|
||||||
|
RandomizationFactor: 0.5, // 增加随机因子防止惊群
|
||||||
|
Multiplier: 2,
|
||||||
|
MaxInterval: 30 * time.Second,
|
||||||
|
MaxElapsedTime: 5 * time.Minute, // 缩短总超时
|
||||||
|
Clock: backoff.SystemClock,
|
||||||
|
}
|
||||||
|
retryConfig.Reset()
|
||||||
|
operation := func() error {
|
||||||
|
statusRsp, err := l.svcCtx.AlipayService.QueryTransferStatus(detachedCtx, outBizNo)
|
||||||
|
if err != nil {
|
||||||
|
return err // 触发重试
|
||||||
|
}
|
||||||
|
|
||||||
|
switch statusRsp.Status {
|
||||||
|
case "SUCCESS":
|
||||||
|
l.handleTransferSuccess(outBizNo, statusRsp)
|
||||||
|
return nil
|
||||||
|
case "FAIL":
|
||||||
|
l.handleTransferFailure(outBizNo, statusRsp)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("转账处理中")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := backoff.RetryNotify(operation,
|
||||||
|
backoff.WithContext(retryConfig, detachedCtx),
|
||||||
|
func(err error, duration time.Duration) {
|
||||||
|
l.Logger.Infof("轮询延迟 outBizNo:%s 等待:%v", outBizNo, duration)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
l.handleTransferTimeout(outBizNo)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一状态更新
|
||||||
|
func (l *AgentWithdrawalLogic) updateWithdrawalStatus(outBizNo string, status int64, errorMsg string) {
|
||||||
|
detachedCtx := context.WithoutCancel(l.ctx)
|
||||||
|
|
||||||
|
err := l.svcCtx.AgentModel.Trans(detachedCtx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
|
// 获取提现记录
|
||||||
|
record, err := l.svcCtx.AgentWithdrawalModel.FindOneByWithdrawNo(l.ctx, outBizNo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新状态
|
||||||
|
record.Status = status
|
||||||
|
record.Remark = lzUtils.StringToNullString(errorMsg)
|
||||||
|
if _, err = l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 失败时解冻资金
|
||||||
|
if status == StatusFailed {
|
||||||
|
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet.Balance += record.Amount
|
||||||
|
wallet.FrozenBalance -= record.Amount
|
||||||
|
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if status == StatusSuccess {
|
||||||
|
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet.FrozenBalance -= record.Amount
|
||||||
|
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
l.Logger.Errorf("状态更新失败 outBizNo:%s error:%v", outBizNo, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 成功处理
|
||||||
|
func (l *AgentWithdrawalLogic) handleTransferSuccess(outBizNo string, rsp interface{}) {
|
||||||
|
l.updateWithdrawalStatus(outBizNo, StatusSuccess, "")
|
||||||
|
l.Logger.Infof("提现成功 outBizNo:%s", outBizNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 失败处理
|
||||||
|
func (l *AgentWithdrawalLogic) handleTransferFailure(outBizNo string, rsp interface{}) {
|
||||||
|
var errorMsg string
|
||||||
|
if resp, ok := rsp.(*alipay.FundTransUniTransferRsp); ok {
|
||||||
|
errorMsg = l.mapAlipayError(resp.SubCode)
|
||||||
|
}
|
||||||
|
l.updateWithdrawalStatus(outBizNo, StatusFailed, errorMsg)
|
||||||
|
l.Logger.Errorf("提现失败 outBizNo:%s reason:%s", outBizNo, errorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 超时处理
|
||||||
|
func (l *AgentWithdrawalLogic) handleTransferTimeout(outBizNo string) {
|
||||||
|
l.updateWithdrawalStatus(outBizNo, StatusFailed, "系统处理超时")
|
||||||
|
l.Logger.Errorf("轮询超时 outBizNo:%s", outBizNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 错误处理
|
||||||
|
func (l *AgentWithdrawalLogic) handleTransferError(outBizNo string, err error, contextMsg string) {
|
||||||
|
l.updateWithdrawalStatus(outBizNo, StatusFailed, "系统处理异常")
|
||||||
|
l.Logger.Errorf("%s outBizNo:%s error:%v", contextMsg, outBizNo, err)
|
||||||
|
}
|
184
app/main/api/internal/logic/agent/applyforagentlogic.go
Normal file
184
app/main/api/internal/logic/agent/applyforagentlogic.go
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
jwtx "tydata-server/common/jwt"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ApplyForAgentLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApplyForAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ApplyForAgentLogic {
|
||||||
|
return &ApplyForAgentLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *types.AgentApplyResp, err error) {
|
||||||
|
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||||
|
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
// 校验验证码
|
||||||
|
redisKey := fmt.Sprintf("%s:%s", "agentApply", encryptedMobile)
|
||||||
|
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, redis.Nil) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "代理申请, 验证码过期: %s", encryptedMobile)
|
||||||
|
}
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err)
|
||||||
|
}
|
||||||
|
if cacheCode != req.Code {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "代理申请, 验证码不正确: %s", encryptedMobile)
|
||||||
|
}
|
||||||
|
if req.Ancestor == req.Mobile {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("不能成为自己的代理"), "")
|
||||||
|
}
|
||||||
|
var userID int64
|
||||||
|
transErr := l.svcCtx.AgentAuditModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
|
||||||
|
// 两种情况,1. 已注册账号然后申请代理 2. 未注册账号申请代理
|
||||||
|
user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
|
||||||
|
if findUserErr != nil && !errors.Is(findUserErr, model.ErrNotFound) {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err)
|
||||||
|
}
|
||||||
|
if user == nil {
|
||||||
|
user = &model.User{Mobile: sql.NullString{String: encryptedMobile, Valid: true}}
|
||||||
|
// if len(user.Nickname) == 0 {
|
||||||
|
// user.Nickname = encryptedMobile
|
||||||
|
// }
|
||||||
|
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(transCtx, session, user)
|
||||||
|
if userInsertErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 数据库插入新用户失败, mobile%s, err: %+v", encryptedMobile, userInsertErr)
|
||||||
|
}
|
||||||
|
lastId, lastInsertIdErr := insertResult.LastInsertId()
|
||||||
|
if lastInsertIdErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 获取新用户ID失败, err:%+v, user:%+v", lastInsertIdErr, user)
|
||||||
|
}
|
||||||
|
user.Id = lastId
|
||||||
|
userID = lastId
|
||||||
|
userAuth := new(model.UserAuth)
|
||||||
|
userAuth.UserId = lastId
|
||||||
|
userAuth.AuthKey = encryptedMobile
|
||||||
|
userAuth.AuthType = model.UserAuthTypeAgentDirect
|
||||||
|
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(transCtx, session, userAuth); userAuthInsertErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userID = user.Id
|
||||||
|
|
||||||
|
// 使用SelectBuilder构建查询,查找符合user_id的记录并按创建时间降序排序获取最新一条
|
||||||
|
builder := l.svcCtx.AgentAuditModel.SelectBuilder().Where("user_id = ?", user.Id).OrderBy("create_time DESC").Limit(1)
|
||||||
|
agentAuditList, findAgentAuditErr := l.svcCtx.AgentAuditModel.FindAll(transCtx, builder, "")
|
||||||
|
if findAgentAuditErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 查找审核列表失败%+v", findAgentAuditErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(agentAuditList) > 0 {
|
||||||
|
agentAuditModel := agentAuditList[0]
|
||||||
|
if agentAuditModel.Status == 0 {
|
||||||
|
return errors.Wrapf(xerr.NewErrMsg("您的代理申请中"), "代理申请, 代理申请中")
|
||||||
|
} else {
|
||||||
|
return errors.Wrapf(xerr.NewErrMsg("您已申请过代理"), "代理申请, 代理已申请过")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var agentAudit model.AgentAudit
|
||||||
|
agentAudit.UserId = user.Id
|
||||||
|
agentAudit.Mobile = encryptedMobile
|
||||||
|
agentAudit.Region = req.Region
|
||||||
|
agentAudit.Status = 1
|
||||||
|
_, insetAgentAuditErr := l.svcCtx.AgentAuditModel.Insert(transCtx, session, &agentAudit)
|
||||||
|
if insetAgentAuditErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 保存代理审核信息失败: %v", insetAgentAuditErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//agentAuditID, _ := agentAuditInsert.LastInsertId()
|
||||||
|
//agentAuditRow, findAgentAuditModelErr := l.svcCtx.AgentAuditModel.FindOne(l.ctx, agentAuditID)
|
||||||
|
//if findAgentAuditModelErr != nil {
|
||||||
|
// return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 查找代理审核信息失败: %v", insetAgentAuditErr)
|
||||||
|
//}
|
||||||
|
//agentAuditRow.Status = 1
|
||||||
|
//updateAgentAuditErr := l.svcCtx.AgentAuditModel.UpdateWithVersion(transCtx, session, agentAuditRow)
|
||||||
|
//if updateAgentAuditErr != nil {
|
||||||
|
// return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 通过代理审核失败: %+v", updateAgentAuditErr)
|
||||||
|
//}
|
||||||
|
|
||||||
|
// 新增代理
|
||||||
|
var agentModel model.Agent
|
||||||
|
agentModel.Mobile = agentAudit.Mobile
|
||||||
|
agentModel.Region = agentAudit.Region
|
||||||
|
agentModel.LevelName = model.AgentLeveNameNormal
|
||||||
|
agentModel.UserId = agentAudit.UserId
|
||||||
|
agentModelInsert, insertAgentModelErr := l.svcCtx.AgentModel.Insert(transCtx, session, &agentModel)
|
||||||
|
if insertAgentModelErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 新增代理失败: %+v", insertAgentModelErr)
|
||||||
|
}
|
||||||
|
agentID, _ := agentModelInsert.LastInsertId()
|
||||||
|
|
||||||
|
// 关联上级
|
||||||
|
if req.Ancestor != "" {
|
||||||
|
ancestorEncryptedMobile, err := crypto.EncryptMobile(req.Ancestor, secretKey)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
ancestorAgentModel, findAgentModelErr := l.svcCtx.AgentModel.FindOneByMobile(transCtx, ancestorEncryptedMobile)
|
||||||
|
if findAgentModelErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 查找上级代理失败: %+v", findAgentModelErr)
|
||||||
|
}
|
||||||
|
agentClosureModel := model.AgentClosure{
|
||||||
|
AncestorId: ancestorAgentModel.Id,
|
||||||
|
DescendantId: agentID,
|
||||||
|
Depth: 1,
|
||||||
|
}
|
||||||
|
_, insertAgentClosureModelErr := l.svcCtx.AgentClosureModel.Insert(transCtx, session, &agentClosureModel)
|
||||||
|
if insertAgentClosureModelErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 添加代理上下级关联失败: %+v", insertAgentClosureModelErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增代理钱包
|
||||||
|
var agentWallet model.AgentWallet
|
||||||
|
agentWallet.AgentId = agentID
|
||||||
|
_, insertAgentWalletModelErr := l.svcCtx.AgentWalletModel.Insert(transCtx, session, &agentWallet)
|
||||||
|
if insertAgentWalletModelErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 新增代理钱包失败: %+v", insertAgentWalletModelErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if transErr != nil {
|
||||||
|
return nil, transErr
|
||||||
|
}
|
||||||
|
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
|
||||||
|
if generaErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 生成token失败 : %d", userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前时间戳
|
||||||
|
now := time.Now().Unix()
|
||||||
|
return &types.AgentApplyResp{
|
||||||
|
AccessToken: token,
|
||||||
|
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
|
||||||
|
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
|
||||||
|
}, nil
|
||||||
|
}
|
111
app/main/api/internal/logic/agent/generatinglinklogic.go
Normal file
111
app/main/api/internal/logic/agent/generatinglinklogic.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GeneratingLinkLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGeneratingLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GeneratingLinkLogic {
|
||||||
|
return &GeneratingLinkLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GeneratingLinkLogic) GeneratingLink(req *types.AgentGeneratingLinkReq) (resp *types.AgentGeneratingLinkResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成代理链接, %v", err)
|
||||||
|
}
|
||||||
|
productModel, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, req.Product)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成代理链接, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentProductConfig, err := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, productModel.Id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成代理链接, %v", err)
|
||||||
|
}
|
||||||
|
price, err := strconv.ParseFloat(req.Price, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成代理链接, %v", err)
|
||||||
|
}
|
||||||
|
if price < agentProductConfig.PriceRangeMin || price > agentProductConfig.PriceRangeMax {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("请设定范围区间内的价格"), "")
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
build := l.svcCtx.AgentLinkModel.SelectBuilder().Where(squirrel.And{
|
||||||
|
squirrel.Eq{"user_id": userID},
|
||||||
|
squirrel.Eq{"product_id": productModel.Id}, // 添加 product_id 的匹配条件
|
||||||
|
squirrel.Eq{"price": price}, // 添加 price 的匹配条件
|
||||||
|
squirrel.Eq{"agent_id": agentModel.Id}, // 添加 agent_id 的匹配条件
|
||||||
|
})
|
||||||
|
|
||||||
|
agentLinkModel, err := l.svcCtx.AgentLinkModel.FindAll(l.ctx, build, "")
|
||||||
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成代理链接, %v", err)
|
||||||
|
}
|
||||||
|
if len(agentLinkModel) > 0 {
|
||||||
|
return &types.AgentGeneratingLinkResp{
|
||||||
|
LinkIdentifier: agentLinkModel[0].LinkIdentifier,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var agentIdentifier types.AgentIdentifier
|
||||||
|
agentIdentifier.AgentID = agentModel.Id
|
||||||
|
agentIdentifier.Product = req.Product
|
||||||
|
agentIdentifier.Price = req.Price
|
||||||
|
agentIdentifierByte, err := json.Marshal(agentIdentifier)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单,序列化标识失败, %v", err)
|
||||||
|
}
|
||||||
|
key, decodeErr := hex.DecodeString("8e3e7a2f60edb49221e953b9c029ed10")
|
||||||
|
if decodeErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取AES密钥失败: %+v", decodeErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt the params
|
||||||
|
encrypted, err := crypto.AesEncryptURL(agentIdentifierByte, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成代理链接, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var agentLink model.AgentLink
|
||||||
|
agentLink.AgentId = agentModel.Id
|
||||||
|
agentLink.UserId = userID
|
||||||
|
agentLink.LinkIdentifier = encrypted
|
||||||
|
agentLink.ProductId = productModel.Id
|
||||||
|
agentLink.Price = price
|
||||||
|
_, err = l.svcCtx.AgentLinkModel.Insert(l.ctx, nil, &agentLink)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成代理链接, %v", err)
|
||||||
|
}
|
||||||
|
return &types.AgentGeneratingLinkResp{
|
||||||
|
LinkIdentifier: encrypted,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentAuditStatusLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentAuditStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentAuditStatusLogic {
|
||||||
|
return &GetAgentAuditStatusLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentAuditStatusLogic) GetAgentAuditStatus() (resp *types.AgentAuditStatusResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理审核信息, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用SelectBuilder构建查询,查找符合user_id的记录并按创建时间降序排序获取最新一条
|
||||||
|
builder := l.svcCtx.AgentAuditModel.SelectBuilder().Where("user_id = ?", userID).OrderBy("create_time DESC").Limit(1)
|
||||||
|
agentAuditList, err := l.svcCtx.AgentAuditModel.FindAll(l.ctx, builder, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理审核信息, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(agentAuditList) == 0 {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "未找到代理审核信息")
|
||||||
|
}
|
||||||
|
|
||||||
|
agentAuditModel := agentAuditList[0]
|
||||||
|
var agentAuditStautsResp types.AgentAuditStatusResp
|
||||||
|
copier.Copy(&agentAuditStautsResp, agentAuditModel)
|
||||||
|
return &agentAuditStautsResp, nil
|
||||||
|
}
|
71
app/main/api/internal/logic/agent/getagentcommissionlogic.go
Normal file
71
app/main/api/internal/logic/agent/getagentcommissionlogic.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentCommissionLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentCommissionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentCommissionLogic {
|
||||||
|
return &GetAgentCommissionLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentCommissionLogic) GetAgentCommission(req *types.GetCommissionReq) (resp *types.GetCommissionResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理佣金列表, %v", err)
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理佣金列表, %v", err)
|
||||||
|
}
|
||||||
|
builder := l.svcCtx.AgentCommissionModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": agentModel.Id,
|
||||||
|
})
|
||||||
|
agentCommissionModelList, total, err := l.svcCtx.AgentCommissionModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理佣金列表, 查找列表错误, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = make([]types.Commission, 0)
|
||||||
|
|
||||||
|
if len(agentCommissionModelList) > 0 {
|
||||||
|
for _, agentCommissionModel := range agentCommissionModelList {
|
||||||
|
var commission types.Commission
|
||||||
|
copyErr := copier.Copy(&commission, agentCommissionModel)
|
||||||
|
if copyErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理佣金列表, %v", err)
|
||||||
|
}
|
||||||
|
product, findProductErr := l.svcCtx.ProductModel.FindOne(l.ctx, agentCommissionModel.ProductId)
|
||||||
|
if findProductErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理佣金列表, %v", err)
|
||||||
|
}
|
||||||
|
commission.CreateTime = agentCommissionModel.CreateTime.Format("2006-01-02 15:04:05")
|
||||||
|
commission.ProductName = product.ProductName
|
||||||
|
list = append(list, commission)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &types.GetCommissionResp{
|
||||||
|
Total: total,
|
||||||
|
List: list,
|
||||||
|
}, nil
|
||||||
|
}
|
86
app/main/api/internal/logic/agent/getagentinfologic.go
Normal file
86
app/main/api/internal/logic/agent/getagentinfologic.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentInfoLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentInfoLogic {
|
||||||
|
return &GetAgentInfoLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentInfoLogic) GetAgentInfo() (resp *types.AgentInfoResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, %v", err)
|
||||||
|
}
|
||||||
|
agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
builder := l.svcCtx.AgentAuditModel.SelectBuilder().Where("user_id = ?", userID).OrderBy("create_time DESC").Limit(1)
|
||||||
|
agentAuditList, findAgentAuditErr := l.svcCtx.AgentAuditModel.FindAll(l.ctx, builder, "")
|
||||||
|
|
||||||
|
if findAgentAuditErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理信息, %v", findAgentAuditErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(agentAuditList) == 0 {
|
||||||
|
return &types.AgentInfoResp{
|
||||||
|
IsAgent: false,
|
||||||
|
Status: 3,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
agentAuditModel := agentAuditList[0]
|
||||||
|
return &types.AgentInfoResp{
|
||||||
|
IsAgent: false,
|
||||||
|
Status: agentAuditModel.Status,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理信息, %v", err)
|
||||||
|
}
|
||||||
|
agent.Mobile, err = crypto.DecryptMobile(agent.Mobile, l.svcCtx.Config.Encrypt.SecretKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, 解密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
IsRealName := false
|
||||||
|
agentRealName, err := l.svcCtx.AgentRealNameModel.FindOneByAgentId(l.ctx, agent.Id)
|
||||||
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理实名信息失败, %v", err)
|
||||||
|
}
|
||||||
|
if agentRealName != nil {
|
||||||
|
IsRealName = true
|
||||||
|
}
|
||||||
|
return &types.AgentInfoResp{
|
||||||
|
AgentID: agent.Id,
|
||||||
|
Level: agent.LevelName,
|
||||||
|
IsAgent: true,
|
||||||
|
Status: 1,
|
||||||
|
Region: agent.Region,
|
||||||
|
Mobile: agent.Mobile,
|
||||||
|
ExpiryTime: agent.MembershipExpiryTime.Time.Format("2006-01-02 15:04:05"),
|
||||||
|
IsRealName: IsRealName,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/lzUtils"
|
||||||
|
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentMembershipProductConfigLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentMembershipProductConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentMembershipProductConfigLogic {
|
||||||
|
return &GetAgentMembershipProductConfigLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentMembershipProductConfigLogic) GetAgentMembershipProductConfig(req *types.AgentMembershipProductConfigReq) (resp *types.AgentMembershipProductConfigResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,获取用户ID失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,获取代理信息失败: %v", err)
|
||||||
|
}
|
||||||
|
if agentModel.LevelName == "" {
|
||||||
|
agentModel.LevelName = model.AgentLeveNameNormal
|
||||||
|
}
|
||||||
|
agentMembershipConfigModel, err := l.svcCtx.AgentMembershipConfigModel.FindOneByLevelName(l.ctx, agentModel.LevelName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,获取平台配置会员信息失败: %v", err)
|
||||||
|
}
|
||||||
|
agentMembershipUserConfigModel, err := l.svcCtx.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(l.ctx, agentModel.Id, req.ProductID)
|
||||||
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var agentMembershipUserConfig types.AgentMembershipUserConfig
|
||||||
|
if agentMembershipUserConfigModel != nil {
|
||||||
|
err = copier.Copy(&agentMembershipUserConfig, agentMembershipUserConfigModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,复制平台配置会员信息失败: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
agentMembershipUserConfig.ProductID = req.ProductID
|
||||||
|
}
|
||||||
|
agentProductConfigModelAll, err := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, req.ProductID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取会员用户报告配置, 获取产品配置%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var productConfig types.ProductConfig
|
||||||
|
err = copier.Copy(&productConfig, agentProductConfigModelAll)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,复制平台产品配置失败: %v", err)
|
||||||
|
}
|
||||||
|
return &types.AgentMembershipProductConfigResp{
|
||||||
|
AgentMembershipUserConfig: agentMembershipUserConfig,
|
||||||
|
ProductConfig: productConfig,
|
||||||
|
PriceIncreaseAmount: lzUtils.NullFloat64ToFloat64(agentMembershipConfigModel.PriceIncreaseAmount),
|
||||||
|
PriceIncreaseMax: lzUtils.NullFloat64ToFloat64(agentMembershipConfigModel.PriceIncreaseMax),
|
||||||
|
PriceRatio: lzUtils.NullFloat64ToFloat64(agentMembershipConfigModel.PriceRatio),
|
||||||
|
}, nil
|
||||||
|
}
|
140
app/main/api/internal/logic/agent/getagentproductconfiglogic.go
Normal file
140
app/main/api/internal/logic/agent/getagentproductconfiglogic.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/mr"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentProductConfigLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentProductConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentProductConfigLogic {
|
||||||
|
return &GetAgentProductConfigLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type AgentProductConfigResp struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentProductConfigLogic) GetAgentProductConfig() (resp *types.AgentProductConfigResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取推广项目配置失败, %v", err)
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("您不是代理"), "")
|
||||||
|
}
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取推广项目配置失败, %v", err)
|
||||||
|
}
|
||||||
|
// 1. 查询推广项目配置数据
|
||||||
|
builder := l.svcCtx.AgentProductConfigModel.SelectBuilder()
|
||||||
|
agentProductConfigModelAll, err := l.svcCtx.AgentProductConfigModel.FindAll(l.ctx, builder, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取推广项目配置失败, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用于存放最终组装好的响应数据
|
||||||
|
var respList []types.AgentProductConfig
|
||||||
|
|
||||||
|
// 2. 使用 mr.MapReduceVoid 并行处理每个推广项目配置项
|
||||||
|
mrMapErr := mr.MapReduceVoid(
|
||||||
|
// source 函数:遍历所有推广项目配置,将每个配置项发送到 channel 中
|
||||||
|
func(source chan<- interface{}) {
|
||||||
|
for _, config := range agentProductConfigModelAll {
|
||||||
|
source <- config
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// map 函数:处理每个推广项目配置项,根据 ProductId 查询会员用户配置,并组装响应数据
|
||||||
|
func(item interface{}, writer mr.Writer[*types.AgentProductConfig], cancel func(error)) {
|
||||||
|
// 将 item 转换为推广项目配置模型
|
||||||
|
config := item.(*model.AgentProductConfig)
|
||||||
|
var agentProductConfig types.AgentProductConfig
|
||||||
|
// 配置平台成本价和定价成本
|
||||||
|
agentProductConfigModel, findAgentProductConfigErr := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, config.ProductId)
|
||||||
|
if findAgentProductConfigErr != nil {
|
||||||
|
cancel(findAgentProductConfigErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
agentProductConfig.ProductID = config.ProductId
|
||||||
|
agentProductConfig.CostPrice = agentProductConfigModel.CostPrice
|
||||||
|
agentProductConfig.PriceRangeMin = agentProductConfigModel.PriceRangeMin
|
||||||
|
agentProductConfig.PriceRangeMax = agentProductConfigModel.PriceRangeMax
|
||||||
|
agentProductConfig.PPricingStandard = agentProductConfigModel.PricingStandard
|
||||||
|
agentProductConfig.POverpricingRatio = agentProductConfigModel.OverpricingRatio
|
||||||
|
|
||||||
|
// 看推广人是否有上级,上级是否有这个配置权限,上级是否有相关配置
|
||||||
|
agentClosureModel, findAgentClosureErr := l.svcCtx.AgentClosureModel.FindOneByDescendantIdDepth(l.ctx, agentModel.Id, 1)
|
||||||
|
if findAgentClosureErr != nil && !errors.Is(findAgentClosureErr, model.ErrNotFound) {
|
||||||
|
cancel(findAgentClosureErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if agentClosureModel != nil {
|
||||||
|
ancestorAgentModel, findAncestorAgentErr := l.svcCtx.AgentModel.FindOne(l.ctx, agentClosureModel.AncestorId)
|
||||||
|
if findAncestorAgentErr != nil {
|
||||||
|
cancel(findAncestorAgentErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ancestorAgentModel.LevelName == "" {
|
||||||
|
ancestorAgentModel.LevelName = model.AgentLeveNameNormal
|
||||||
|
}
|
||||||
|
agentMembershipConfigModel, findAgentMembershipErr := l.svcCtx.AgentMembershipConfigModel.FindOneByLevelName(l.ctx, ancestorAgentModel.LevelName)
|
||||||
|
if findAgentMembershipErr != nil {
|
||||||
|
cancel(findAgentMembershipErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 是否有提成本价
|
||||||
|
if agentMembershipConfigModel.PriceIncreaseAmount.Valid {
|
||||||
|
// 根据产品ID查询会员用户配置数据
|
||||||
|
membershipUserConfigModel, membershipConfigErr := l.svcCtx.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(l.ctx, agentClosureModel.AncestorId, config.ProductId)
|
||||||
|
if membershipConfigErr != nil {
|
||||||
|
if errors.Is(membershipConfigErr, model.ErrNotFound) {
|
||||||
|
writer.Write(&agentProductConfig)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cancel(membershipConfigErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
agentProductConfig.CostPrice += membershipUserConfigModel.PriceIncreaseAmount
|
||||||
|
agentProductConfig.PriceRangeMin += membershipUserConfigModel.PriceIncreaseAmount
|
||||||
|
agentProductConfig.APricingStandard = membershipUserConfigModel.PriceRangeFrom
|
||||||
|
agentProductConfig.APricingEnd = membershipUserConfigModel.PriceRangeTo
|
||||||
|
agentProductConfig.AOverpricingRatio = membershipUserConfigModel.PriceRatio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.Write(&agentProductConfig)
|
||||||
|
|
||||||
|
},
|
||||||
|
// reduce 函数:收集 map 阶段写入的响应数据,并汇总到 respList 中
|
||||||
|
func(pipe <-chan *types.AgentProductConfig, cancel func(error)) {
|
||||||
|
for item := range pipe {
|
||||||
|
respList = append(respList, *item)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if mrMapErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取推广项目配置失败, %+v", mrMapErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 组装最终响应返回
|
||||||
|
return &types.AgentProductConfigResp{
|
||||||
|
AgentProductConfig: respList,
|
||||||
|
}, nil
|
||||||
|
}
|
199
app/main/api/internal/logic/agent/getagentrevenueinfologic.go
Normal file
199
app/main/api/internal/logic/agent/getagentrevenueinfologic.go
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentRevenueInfoLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentRevenueInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentRevenueInfoLogic {
|
||||||
|
return &GetAgentRevenueInfoLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentRevenueInfoLogic) GetAgentRevenueInfo(req *types.GetAgentRevenueInfoReq) (resp *types.GetAgentRevenueInfoResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理奖励, %v", err)
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
|
||||||
|
}
|
||||||
|
agentWalletModel, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agentModel.Id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
|
||||||
|
}
|
||||||
|
resp = &types.GetAgentRevenueInfoResp{}
|
||||||
|
resp.Balance = agentWalletModel.Balance
|
||||||
|
resp.TotalEarnings = agentWalletModel.TotalEarnings
|
||||||
|
resp.FrozenBalance = agentWalletModel.FrozenBalance
|
||||||
|
|
||||||
|
// 直推报告统计
|
||||||
|
//now := time.Now()
|
||||||
|
//startTime := now.AddDate(0, 0, -30).Format("2006-01-02 15:04:05")
|
||||||
|
//endTime := now.Format("2006-01-02 15:04:05")
|
||||||
|
|
||||||
|
// 直推报告佣金
|
||||||
|
agentCommissionModelBuild := l.svcCtx.AgentCommissionModel.SelectBuilder().
|
||||||
|
Where(squirrel.Eq{"agent_id": agentModel.Id})
|
||||||
|
//.Where(squirrel.Expr("create_time BETWEEN ? AND ?", startTime, endTime))
|
||||||
|
|
||||||
|
agentCommissionsModel, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, agentCommissionModelBuild, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
|
||||||
|
}
|
||||||
|
// 筛选分类
|
||||||
|
directPush, err := calculateDirectPushReport(agentCommissionsModel, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
|
||||||
|
}
|
||||||
|
// 绑定到响应体
|
||||||
|
resp.DirectPush = directPush
|
||||||
|
|
||||||
|
// 活跃下级统计
|
||||||
|
agentRewardsModelBuilder := l.svcCtx.AgentRewardsModel.SelectBuilder().Where("agent_id = ?", agentModel.Id)
|
||||||
|
agentRewardsModel, err := l.svcCtx.AgentRewardsModel.FindAll(l.ctx, agentRewardsModelBuilder, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
|
||||||
|
}
|
||||||
|
activeReward := calculateActiveReward(agentRewardsModel)
|
||||||
|
resp.ActiveReward = activeReward
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计直推报告的独立函数
|
||||||
|
func calculateDirectPushReport(commissions []*model.AgentCommission, loc *time.Location) (types.DirectPushReport, error) {
|
||||||
|
// 初始化报告结构
|
||||||
|
report := types.DirectPushReport{
|
||||||
|
Today: types.TimeRangeReport{},
|
||||||
|
Last7D: types.TimeRangeReport{},
|
||||||
|
Last30D: types.TimeRangeReport{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前中国时间
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
// 计算时间分界点
|
||||||
|
todayStart := now.Add(-24 * time.Hour)
|
||||||
|
last7dStart := now.AddDate(0, 0, -7)
|
||||||
|
last30dStart := now.AddDate(0, 0, -30)
|
||||||
|
|
||||||
|
// 遍历所有佣金记录
|
||||||
|
for _, c := range commissions {
|
||||||
|
// 转换时区
|
||||||
|
createTime := c.CreateTime
|
||||||
|
|
||||||
|
// 统计总量
|
||||||
|
report.TotalCommission += c.Amount
|
||||||
|
report.TotalReport++
|
||||||
|
|
||||||
|
// 近24小时(滚动周期)
|
||||||
|
if createTime.After(todayStart) {
|
||||||
|
report.Today.Commission += c.Amount
|
||||||
|
report.Today.Report++
|
||||||
|
}
|
||||||
|
|
||||||
|
// 近7天(滚动周期)
|
||||||
|
if createTime.After(last7dStart) {
|
||||||
|
report.Last7D.Commission += c.Amount
|
||||||
|
report.Last7D.Report++
|
||||||
|
}
|
||||||
|
|
||||||
|
// 近30天(滚动周期)
|
||||||
|
if createTime.After(last30dStart) {
|
||||||
|
report.Last30D.Commission += c.Amount
|
||||||
|
report.Last30D.Report++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return report, nil
|
||||||
|
}
|
||||||
|
func calculateActiveReward(rewards []*model.AgentRewards) types.ActiveReward {
|
||||||
|
result := types.ActiveReward{
|
||||||
|
Today: types.ActiveRewardData{},
|
||||||
|
Last7D: types.ActiveRewardData{},
|
||||||
|
Last30D: types.ActiveRewardData{},
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
todayStart := now.Add(-24 * time.Hour) // 近24小时
|
||||||
|
last7dStart := now.AddDate(0, 0, -7) // 近7天
|
||||||
|
last30dStart := now.AddDate(0, 0, -30) // 近30天
|
||||||
|
|
||||||
|
for _, r := range rewards {
|
||||||
|
createTime := r.CreateTime
|
||||||
|
amount := r.Amount
|
||||||
|
|
||||||
|
// 总奖励累加
|
||||||
|
result.TotalReward += amount
|
||||||
|
|
||||||
|
// 时间范围判断
|
||||||
|
isToday := createTime.After(todayStart)
|
||||||
|
isLast7d := createTime.After(last7dStart)
|
||||||
|
isLast30d := createTime.After(last30dStart)
|
||||||
|
|
||||||
|
// 类型分类统计
|
||||||
|
switch r.Type {
|
||||||
|
case model.AgentRewardsTypeDescendantWithdraw:
|
||||||
|
addToPeriods(&result, amount, isToday, isLast7d, isLast30d, "withdraw")
|
||||||
|
|
||||||
|
case model.AgentRewardsTypeDescendantNewActive:
|
||||||
|
addToPeriods(&result, amount, isToday, isLast7d, isLast30d, "new_active")
|
||||||
|
|
||||||
|
case model.AgentRewardsTypeDescendantUpgradeSvip, model.AgentRewardsTypeDescendantUpgradeVip:
|
||||||
|
addToPeriods(&result, amount, isToday, isLast7d, isLast30d, "upgrade")
|
||||||
|
|
||||||
|
case model.AgentRewardsTypeDescendantPromotion:
|
||||||
|
addToPeriods(&result, amount, isToday, isLast7d, isLast30d, "promotion")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一处理时间段累加
|
||||||
|
func addToPeriods(res *types.ActiveReward, amount float64, today, last7d, last30d bool, t string) {
|
||||||
|
if today {
|
||||||
|
addToData(&res.Today, amount, t)
|
||||||
|
}
|
||||||
|
if last7d {
|
||||||
|
addToData(&res.Last7D, amount, t)
|
||||||
|
}
|
||||||
|
if last30d {
|
||||||
|
addToData(&res.Last30D, amount, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分类添加具体字段
|
||||||
|
func addToData(data *types.ActiveRewardData, amount float64, t string) {
|
||||||
|
switch t {
|
||||||
|
case "withdraw":
|
||||||
|
data.SubWithdrawReward += amount
|
||||||
|
case "new_active":
|
||||||
|
data.NewActiveReward += amount
|
||||||
|
case "upgrade":
|
||||||
|
data.SubUpgradeReward += amount
|
||||||
|
case "promotion":
|
||||||
|
data.SubPromoteReward += amount
|
||||||
|
}
|
||||||
|
}
|
68
app/main/api/internal/logic/agent/getagentrewardslogic.go
Normal file
68
app/main/api/internal/logic/agent/getagentrewardslogic.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentRewardsLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentRewardsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentRewardsLogic {
|
||||||
|
return &GetAgentRewardsLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentRewardsLogic) GetAgentRewards(req *types.GetRewardsReq) (resp *types.GetRewardsResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理奖励列表, %v", err)
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励列表, %v", err)
|
||||||
|
}
|
||||||
|
builder := l.svcCtx.AgentRewardsModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": agentModel.Id,
|
||||||
|
})
|
||||||
|
agentRewardsModelList, total, err := l.svcCtx.AgentRewardsModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励列表, 查找列表错误, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = make([]types.Rewards, 0)
|
||||||
|
if len(agentRewardsModelList) > 0 {
|
||||||
|
for _, agentRewardsModel := range agentRewardsModelList {
|
||||||
|
var rewards types.Rewards
|
||||||
|
copyErr := copier.Copy(&rewards, agentRewardsModel)
|
||||||
|
if copyErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理奖励列表, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rewards.CreateTime = agentRewardsModel.CreateTime.Format("2006-01-02 15:04:05")
|
||||||
|
list = append(list, rewards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &types.GetRewardsResp{
|
||||||
|
Total: total,
|
||||||
|
List: list,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
@ -0,0 +1,200 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentSubordinateContributionDetailLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentSubordinateContributionDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentSubordinateContributionDetailLogic {
|
||||||
|
return &GetAgentSubordinateContributionDetailLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentSubordinateContributionDetailLogic) GetAgentSubordinateContributionDetail(req *types.GetAgentSubordinateContributionDetailReq) (resp *types.GetAgentSubordinateContributionDetailResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 获取用户ID%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前代理信息
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取代理信息%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取下级代理信息
|
||||||
|
subordinateAgent, err := l.svcCtx.AgentModel.FindOne(l.ctx, req.SubordinateID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取下级代理信息%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证是否是当前代理的下级
|
||||||
|
closureBuilder := l.svcCtx.AgentClosureModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"ancestor_id": agentModel.Id,
|
||||||
|
"descendant_id": req.SubordinateID,
|
||||||
|
})
|
||||||
|
closureList, err := l.svcCtx.AgentClosureModel.FindAll(l.ctx, closureBuilder, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 验证代理关系%v", err)
|
||||||
|
}
|
||||||
|
if len(closureList) == 0 {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 非法的代理关系")
|
||||||
|
}
|
||||||
|
closure := closureList[0]
|
||||||
|
|
||||||
|
// 获取佣金扣除记录
|
||||||
|
deductionBuilder := l.svcCtx.AgentCommissionDeductionModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": agentModel.Id,
|
||||||
|
"deducted_agent_id": req.SubordinateID,
|
||||||
|
})
|
||||||
|
deductionList, err := l.svcCtx.AgentCommissionDeductionModel.FindAll(l.ctx, deductionBuilder, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取佣金扣除记录%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取奖励记录
|
||||||
|
rewardsBuilder := l.svcCtx.AgentRewardsModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": agentModel.Id,
|
||||||
|
"relation_agent_id": req.SubordinateID,
|
||||||
|
})
|
||||||
|
rewards, err := l.svcCtx.AgentRewardsModel.FindAll(l.ctx, rewardsBuilder, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取奖励记录%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算总贡献
|
||||||
|
var totalContribution float64
|
||||||
|
for _, v := range deductionList {
|
||||||
|
totalContribution += v.Amount
|
||||||
|
}
|
||||||
|
// 加上奖励金额
|
||||||
|
for _, v := range rewards {
|
||||||
|
totalContribution += v.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取佣金记录
|
||||||
|
commissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": req.SubordinateID,
|
||||||
|
})
|
||||||
|
commissionList, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, commissionBuilder, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取佣金记录%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算总收益和总单量
|
||||||
|
var totalEarnings float64
|
||||||
|
for _, v := range commissionList {
|
||||||
|
totalEarnings += v.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化统计数据
|
||||||
|
stats := types.AgentSubordinateContributionStats{
|
||||||
|
CostCount: 0,
|
||||||
|
CostAmount: 0,
|
||||||
|
PricingCount: 0,
|
||||||
|
PricingAmount: 0,
|
||||||
|
DescendantPromotionCount: 0,
|
||||||
|
DescendantPromotionAmount: 0,
|
||||||
|
DescendantUpgradeVipCount: 0,
|
||||||
|
DescendantUpgradeVipAmount: 0,
|
||||||
|
DescendantUpgradeSvipCount: 0,
|
||||||
|
DescendantUpgradeSvipAmount: 0,
|
||||||
|
DescendantStayActiveCount: 0,
|
||||||
|
DescendantStayActiveAmount: 0,
|
||||||
|
DescendantNewActiveCount: 0,
|
||||||
|
DescendantNewActiveAmount: 0,
|
||||||
|
DescendantWithdrawCount: 0,
|
||||||
|
DescendantWithdrawAmount: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计佣金扣除记录
|
||||||
|
for _, v := range deductionList {
|
||||||
|
switch v.Type {
|
||||||
|
case "cost":
|
||||||
|
stats.CostCount++
|
||||||
|
stats.CostAmount += v.Amount
|
||||||
|
case "pricing":
|
||||||
|
stats.PricingCount++
|
||||||
|
stats.PricingAmount += v.Amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计奖励记录
|
||||||
|
for _, v := range rewards {
|
||||||
|
switch v.Type {
|
||||||
|
case "descendant_promotion":
|
||||||
|
stats.DescendantPromotionCount++
|
||||||
|
stats.DescendantPromotionAmount += v.Amount
|
||||||
|
case "descendant_upgrade_vip":
|
||||||
|
stats.DescendantUpgradeVipCount++
|
||||||
|
stats.DescendantUpgradeVipAmount += v.Amount
|
||||||
|
case "descendant_upgrade_svip":
|
||||||
|
stats.DescendantUpgradeSvipCount++
|
||||||
|
stats.DescendantUpgradeSvipAmount += v.Amount
|
||||||
|
case "descendant_stay_active":
|
||||||
|
stats.DescendantStayActiveCount++
|
||||||
|
stats.DescendantStayActiveAmount += v.Amount
|
||||||
|
case "descendant_new_active":
|
||||||
|
stats.DescendantNewActiveCount++
|
||||||
|
stats.DescendantNewActiveAmount += v.Amount
|
||||||
|
case "descendant_withdraw":
|
||||||
|
stats.DescendantWithdrawCount++
|
||||||
|
stats.DescendantWithdrawAmount += v.Amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解密手机号
|
||||||
|
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||||
|
mobile, err := crypto.DecryptMobile(subordinateAgent.Mobile, secretKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 解密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取合并后的分页列表
|
||||||
|
unionDetails, total, err := l.svcCtx.AgentClosureModel.FindUnionPageListByPageWithTotal(l.ctx, agentModel.Id, req.SubordinateID, req.Page, req.PageSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取分页列表%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为响应类型
|
||||||
|
detailList := make([]types.AgentSubordinateContributionDetail, 0, len(unionDetails))
|
||||||
|
for _, v := range unionDetails {
|
||||||
|
detail := types.AgentSubordinateContributionDetail{
|
||||||
|
ID: v.Id,
|
||||||
|
CreateTime: v.CreateTime,
|
||||||
|
Amount: v.Amount,
|
||||||
|
Type: v.Type,
|
||||||
|
}
|
||||||
|
detailList = append(detailList, detail)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.GetAgentSubordinateContributionDetailResp{
|
||||||
|
Mobile: maskPhone(mobile),
|
||||||
|
Total: total,
|
||||||
|
CreateTime: closure.CreateTime.Format("2006-01-02 15:04:05"),
|
||||||
|
TotalEarnings: totalEarnings,
|
||||||
|
TotalContribution: totalContribution,
|
||||||
|
TotalOrders: int64(len(commissionList)),
|
||||||
|
LevelName: subordinateAgent.LevelName,
|
||||||
|
List: detailList,
|
||||||
|
Stats: stats,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,173 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/mr"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentSubordinateListLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentSubordinateListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentSubordinateListLogic {
|
||||||
|
return &GetAgentSubordinateListLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentSubordinateListLogic) GetAgentSubordinateList(req *types.GetAgentSubordinateListReq) (resp *types.GetAgentSubordinateListResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级列表, 获取用户ID%v", err)
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理信息%v", err)
|
||||||
|
}
|
||||||
|
agentID := agentModel.Id
|
||||||
|
|
||||||
|
builder := l.svcCtx.AgentClosureModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"ancestor_id": agentID,
|
||||||
|
})
|
||||||
|
agentClosureModelList, total, err := l.svcCtx.AgentClosureModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理关系%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建ID到CreateTime的映射
|
||||||
|
createTimeMap := make(map[int64]time.Time)
|
||||||
|
descendantIDs := make([]int64, 0)
|
||||||
|
for _, v := range agentClosureModelList {
|
||||||
|
descendantIDs = append(descendantIDs, v.DescendantId)
|
||||||
|
createTimeMap[v.DescendantId] = v.CreateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// 并发查询代理信息
|
||||||
|
agentMap := make(map[int64]*model.Agent)
|
||||||
|
var descendantList []types.AgentSubordinateList
|
||||||
|
err = mr.Finish(func() error {
|
||||||
|
return mr.MapReduceVoid(func(source chan<- interface{}) {
|
||||||
|
for _, id := range descendantIDs {
|
||||||
|
source <- id
|
||||||
|
}
|
||||||
|
}, func(item interface{}, writer mr.Writer[interface{}], cancel func(error)) {
|
||||||
|
id := item.(int64)
|
||||||
|
agent, err := l.svcCtx.AgentModel.FindOne(l.ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
cancel(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writer.Write(agent)
|
||||||
|
}, func(pipe <-chan interface{}, cancel func(error)) {
|
||||||
|
for item := range pipe {
|
||||||
|
agent := item.(*model.Agent)
|
||||||
|
agentMap[agent.Id] = agent
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, func() error {
|
||||||
|
// 并发查询佣金扣除信息
|
||||||
|
deductionBuilder := l.svcCtx.AgentCommissionDeductionModel.SelectBuilder().
|
||||||
|
Where(squirrel.Eq{"agent_id": agentID}).
|
||||||
|
Where(squirrel.Eq{"deducted_agent_id": descendantIDs})
|
||||||
|
deductionList, err := l.svcCtx.AgentCommissionDeductionModel.FindAll(l.ctx, deductionBuilder, "")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理佣金扣除信息%v", err)
|
||||||
|
}
|
||||||
|
deductionMap := make(map[int64]float64)
|
||||||
|
for _, v := range deductionList {
|
||||||
|
deductionMap[v.DeductedAgentId] += v.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// 并发查询奖励信息
|
||||||
|
rewardsBuilder := l.svcCtx.AgentRewardsModel.SelectBuilder().
|
||||||
|
Where(squirrel.Eq{"agent_id": agentID}).
|
||||||
|
Where(squirrel.Eq{"relation_agent_id": descendantIDs})
|
||||||
|
rewardsList, err := l.svcCtx.AgentRewardsModel.FindAll(l.ctx, rewardsBuilder, "")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理奖励信息%v", err)
|
||||||
|
}
|
||||||
|
rewardsMap := make(map[int64]float64)
|
||||||
|
for _, v := range rewardsList {
|
||||||
|
if v.RelationAgentId.Valid {
|
||||||
|
rewardsMap[v.RelationAgentId.Int64] += v.Amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 并发查询佣金信息
|
||||||
|
commissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder().
|
||||||
|
Where(squirrel.Eq{"agent_id": descendantIDs})
|
||||||
|
commissionList, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, commissionBuilder, "")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理佣金信息%v", err)
|
||||||
|
}
|
||||||
|
commissionMap := make(map[int64]float64)
|
||||||
|
orderCountMap := make(map[int64]int64)
|
||||||
|
for _, v := range commissionList {
|
||||||
|
commissionMap[v.AgentId] += v.Amount
|
||||||
|
orderCountMap[v.AgentId]++
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建返回结果
|
||||||
|
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||||
|
descendantList = make([]types.AgentSubordinateList, 0, len(descendantIDs))
|
||||||
|
for _, id := range descendantIDs {
|
||||||
|
agent, exists := agentMap[id]
|
||||||
|
if !exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mobile, err := crypto.DecryptMobile(agent.Mobile, secretKey)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, 解密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
subordinate := types.AgentSubordinateList{
|
||||||
|
ID: id,
|
||||||
|
Mobile: maskPhone(mobile),
|
||||||
|
LevelName: agent.LevelName,
|
||||||
|
CreateTime: createTimeMap[id].Format("2006-01-02 15:04:05"),
|
||||||
|
TotalContribution: deductionMap[id] + rewardsMap[id],
|
||||||
|
TotalEarnings: commissionMap[id],
|
||||||
|
TotalOrders: orderCountMap[id],
|
||||||
|
}
|
||||||
|
descendantList = append(descendantList, subordinate)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.GetAgentSubordinateListResp{
|
||||||
|
Total: total,
|
||||||
|
List: descendantList,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手机号脱敏
|
||||||
|
func maskPhone(phone string) string {
|
||||||
|
length := len(phone)
|
||||||
|
if length < 8 {
|
||||||
|
return phone // 如果长度太短,可能不是手机号,不处理
|
||||||
|
}
|
||||||
|
// 保留前3位和后4位
|
||||||
|
return phone[:3] + strings.Repeat("*", length-7) + phone[length-4:]
|
||||||
|
}
|
66
app/main/api/internal/logic/agent/getagentwithdrawallogic.go
Normal file
66
app/main/api/internal/logic/agent/getagentwithdrawallogic.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAgentWithdrawalLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAgentWithdrawalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentWithdrawalLogic {
|
||||||
|
return &GetAgentWithdrawalLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAgentWithdrawalLogic) GetAgentWithdrawal(req *types.GetWithdrawalReq) (resp *types.GetWithdrawalResp, err error) {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理提现列表, %v", err)
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理提现列表, %v", err)
|
||||||
|
}
|
||||||
|
builder := l.svcCtx.AgentWithdrawalModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"agent_id": agentModel.Id,
|
||||||
|
})
|
||||||
|
agentWithdrawalModelList, total, err := l.svcCtx.AgentWithdrawalModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理提现列表, 查找列表错误, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = make([]types.Withdrawal, 0)
|
||||||
|
|
||||||
|
if len(agentWithdrawalModelList) > 0 {
|
||||||
|
for _, agentWithdrawalModel := range agentWithdrawalModelList {
|
||||||
|
var withdrawal types.Withdrawal
|
||||||
|
copyErr := copier.Copy(&withdrawal, agentWithdrawalModel)
|
||||||
|
if copyErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理提现列表, %v", err)
|
||||||
|
}
|
||||||
|
withdrawal.CreateTime = agentWithdrawalModel.CreateTime.Format("2006-01-02 15:04:05")
|
||||||
|
list = append(list, withdrawal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &types.GetWithdrawalResp{
|
||||||
|
Total: total,
|
||||||
|
List: list,
|
||||||
|
}, nil
|
||||||
|
}
|
46
app/main/api/internal/logic/agent/getlinkdatalogic.go
Normal file
46
app/main/api/internal/logic/agent/getlinkdatalogic.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetLinkDataLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetLinkDataLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLinkDataLogic {
|
||||||
|
return &GetLinkDataLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetLinkDataLogic) GetLinkData(req *types.GetLinkDataReq) (resp *types.GetLinkDataResp, err error) {
|
||||||
|
agentLinkModel, err := l.svcCtx.AgentLinkModel.FindOneByLinkIdentifier(l.ctx, req.LinkIdentifier)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理链接数据, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
productModel, err := l.svcCtx.ProductModel.FindOne(l.ctx, agentLinkModel.ProductId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理链接数据, %v", err)
|
||||||
|
}
|
||||||
|
var product types.Product
|
||||||
|
copier.Copy(&product, productModel)
|
||||||
|
product.SellPrice = agentLinkModel.Price
|
||||||
|
return &types.GetLinkDataResp{
|
||||||
|
Product: product,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SaveAgentMembershipUserConfigLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSaveAgentMembershipUserConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveAgentMembershipUserConfigLogic {
|
||||||
|
return &SaveAgentMembershipUserConfigLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *SaveAgentMembershipUserConfigLogic) SaveAgentMembershipUserConfig(req *types.SaveAgentMembershipUserConfigReq) error {
|
||||||
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置,获取用户ID失败: %v", err)
|
||||||
|
}
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var agentMembershipUserConfigModel *model.AgentMembershipUserConfig
|
||||||
|
agentMembershipUserConfigModel, err = l.svcCtx.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(l.ctx, agentModel.Id, req.ProductID)
|
||||||
|
|
||||||
|
// 检查记录是否存在
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
|
// 记录不存在,创建新的配置对象
|
||||||
|
agentMembershipUserConfigModel = &model.AgentMembershipUserConfig{
|
||||||
|
UserId: userID,
|
||||||
|
AgentId: agentModel.Id,
|
||||||
|
ProductId: req.ProductID,
|
||||||
|
PriceRatio: req.PriceRatio,
|
||||||
|
PriceIncreaseAmount: req.PriceIncreaseAmount,
|
||||||
|
PriceRangeFrom: req.PriceRangeFrom,
|
||||||
|
PriceRangeTo: req.PriceRangeTo,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入新记录
|
||||||
|
_, err = l.svcCtx.AgentMembershipUserConfigModel.Insert(l.ctx, nil, agentMembershipUserConfigModel)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置,插入新记录失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他错误
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置,查询记录失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录存在,更新现有配置
|
||||||
|
agentMembershipUserConfigModel.PriceRatio = req.PriceRatio
|
||||||
|
agentMembershipUserConfigModel.PriceIncreaseAmount = req.PriceIncreaseAmount
|
||||||
|
agentMembershipUserConfigModel.PriceRangeFrom = req.PriceRangeFrom
|
||||||
|
agentMembershipUserConfigModel.PriceRangeTo = req.PriceRangeTo
|
||||||
|
|
||||||
|
_, err = l.svcCtx.AgentMembershipUserConfigModel.Update(l.ctx, nil, agentMembershipUserConfigModel)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置,更新记录失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
31
app/main/api/internal/logic/app/getappversionlogic.go
Normal file
31
app/main/api/internal/logic/app/getappversionlogic.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetAppVersionLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetAppVersionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAppVersionLogic {
|
||||||
|
return &GetAppVersionLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetAppVersionLogic) GetAppVersion() (resp *types.GetAppVersionResp, err error) {
|
||||||
|
return &types.GetAppVersionResp{
|
||||||
|
Version: "1.0.0",
|
||||||
|
WgtUrl: "https://www.quannengcha.com/app_version/qnc_1.0.0.wgt",
|
||||||
|
}, nil
|
||||||
|
}
|
31
app/main/api/internal/logic/app/healthchecklogic.go
Normal file
31
app/main/api/internal/logic/app/healthchecklogic.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HealthCheckLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHealthCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HealthCheckLogic {
|
||||||
|
return &HealthCheckLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *HealthCheckLogic) HealthCheck() (resp *types.HealthCheckResp, err error) {
|
||||||
|
return &types.HealthCheckResp{
|
||||||
|
Status: "UP",
|
||||||
|
Message: "Service is healthy HahaHa",
|
||||||
|
}, nil
|
||||||
|
}
|
105
app/main/api/internal/logic/auth/sendsmslogic.go
Normal file
105
app/main/api/internal/logic/auth/sendsmslogic.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||||
|
dysmsapi "github.com/alibabacloud-go/dysmsapi-20170525/v3/client"
|
||||||
|
"github.com/alibabacloud-go/tea-utils/v2/service"
|
||||||
|
"github.com/alibabacloud-go/tea/tea"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SendSmsLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSendSmsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendSmsLogic {
|
||||||
|
return &SendSmsLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *SendSmsLogic) SendSms(req *types.SendSmsReq) error {
|
||||||
|
secretKey := l.svcCtx.Config.Encrypt.SecretKey
|
||||||
|
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 加密手机号失败: %v", err)
|
||||||
|
}
|
||||||
|
// 检查手机号是否在一分钟内已发送过验证码
|
||||||
|
limitCodeKey := fmt.Sprintf("limit:%s:%s", req.ActionType, encryptedMobile)
|
||||||
|
exists, err := l.svcCtx.Redis.Exists(limitCodeKey)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 读取redis缓存失败: %s", encryptedMobile)
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
// 如果 Redis 中已经存在标记,说明在 1 分钟内请求过,返回错误
|
||||||
|
return errors.Wrapf(xerr.NewErrMsg("一分钟内不能重复发送验证码"), "短信发送, 手机号1分钟内重复请求发送验证码: %s", encryptedMobile)
|
||||||
|
}
|
||||||
|
|
||||||
|
code := fmt.Sprintf("%06d", rand.New(rand.NewSource(time.Now().UnixNano())).Intn(1000000))
|
||||||
|
|
||||||
|
// 发送短信
|
||||||
|
smsResp, err := l.sendSmsRequest(req.Mobile, code)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 调用阿里客户端失败: %v", err)
|
||||||
|
}
|
||||||
|
if *smsResp.Body.Code != "OK" {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 阿里客户端响应失败: %s", *smsResp.Body.Message)
|
||||||
|
}
|
||||||
|
codeKey := fmt.Sprintf("%s:%s", req.ActionType, encryptedMobile)
|
||||||
|
// 将验证码保存到 Redis,设置过期时间
|
||||||
|
err = l.svcCtx.Redis.Setex(codeKey, code, l.svcCtx.Config.VerifyCode.ValidTime) // 验证码有效期5分钟
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 验证码设置过期时间失败: %v", err)
|
||||||
|
}
|
||||||
|
// 在 Redis 中设置 1 分钟的标记,限制重复请求
|
||||||
|
err = l.svcCtx.Redis.Setex(limitCodeKey, code, 60) // 标记 1 分钟内不能重复请求
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 验证码设置限制重复请求失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateClient 创建阿里云短信客户端
|
||||||
|
func (l *SendSmsLogic) CreateClient() (*dysmsapi.Client, error) {
|
||||||
|
config := &openapi.Config{
|
||||||
|
AccessKeyId: &l.svcCtx.Config.VerifyCode.AccessKeyID,
|
||||||
|
AccessKeySecret: &l.svcCtx.Config.VerifyCode.AccessKeySecret,
|
||||||
|
}
|
||||||
|
config.Endpoint = tea.String(l.svcCtx.Config.VerifyCode.EndpointURL)
|
||||||
|
return dysmsapi.NewClient(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendSmsRequest 发送短信请求
|
||||||
|
func (l *SendSmsLogic) sendSmsRequest(mobile, code string) (*dysmsapi.SendSmsResponse, error) {
|
||||||
|
// 初始化阿里云短信客户端
|
||||||
|
cli, err := l.CreateClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &dysmsapi.SendSmsRequest{
|
||||||
|
SignName: tea.String(l.svcCtx.Config.VerifyCode.SignName),
|
||||||
|
TemplateCode: tea.String(l.svcCtx.Config.VerifyCode.TemplateCode),
|
||||||
|
PhoneNumbers: tea.String(mobile),
|
||||||
|
TemplateParam: tea.String(fmt.Sprintf("{\"code\":\"%s\"}", code)),
|
||||||
|
}
|
||||||
|
runtime := &service.RuntimeOptions{}
|
||||||
|
return cli.SendSmsWithOptions(request, runtime)
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package notification
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetNotificationsLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetNotificationsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetNotificationsLogic {
|
||||||
|
return &GetNotificationsLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetNotificationsLogic) GetNotifications() (resp *types.GetNotificationsResp, err error) {
|
||||||
|
// 获取今天的日期
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
// 获取开始和结束日期的时间戳
|
||||||
|
todayStart := now.Format("2006-01-02") + " 00:00:00"
|
||||||
|
todayEnd := now.Format("2006-01-02") + " 23:59:59"
|
||||||
|
|
||||||
|
// 构建查询条件
|
||||||
|
builder := l.svcCtx.GlobalNotificationsModel.SelectBuilder().
|
||||||
|
Where("status = ?", "active").
|
||||||
|
Where("(start_date IS NULL OR start_date <= ?)", todayEnd). // start_date 是 NULL 或者小于等于今天结束时间
|
||||||
|
Where("(end_date IS NULL OR end_date >= ?)", todayStart) // end_date 是 NULL 或者大于等于今天开始时间
|
||||||
|
|
||||||
|
notificationsModelList, findErr := l.svcCtx.GlobalNotificationsModel.FindAll(l.ctx, builder, "")
|
||||||
|
if findErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "全局通知, 查找通知失败, err:%+v", findErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var notifications []types.Notification
|
||||||
|
copyErr := copier.Copy(¬ifications, ¬ificationsModelList)
|
||||||
|
if copyErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "全局通知, 复制结构体失败, err:%+v", copyErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.GetNotificationsResp{Notifications: notifications}, nil
|
||||||
|
}
|
216
app/main/api/internal/logic/pay/alipaycallbacklogic.go
Normal file
216
app/main/api/internal/logic/pay/alipaycallbacklogic.go
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"tydata-server/pkg/lzkit/lzUtils"
|
||||||
|
|
||||||
|
"github.com/smartwalle/alipay/v3"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AlipayCallbackLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAlipayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AlipayCallbackLogic {
|
||||||
|
return &AlipayCallbackLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
notification, err := l.svcCtx.AlipayService.HandleAliPaymentNotification(r)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("支付宝支付回调,%v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据订单号前缀判断订单类型
|
||||||
|
orderNo := notification.OutTradeNo
|
||||||
|
if strings.HasPrefix(orderNo, "Q_") {
|
||||||
|
// 查询订单处理
|
||||||
|
return l.handleQueryOrderPayment(w, notification)
|
||||||
|
} else if strings.HasPrefix(orderNo, "A_") {
|
||||||
|
// 代理会员订单处理
|
||||||
|
return l.handleAgentVipOrderPayment(w, notification)
|
||||||
|
} else {
|
||||||
|
// 兼容旧订单,假设没有前缀的是查询订单
|
||||||
|
return l.handleQueryOrderPayment(w, notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理查询订单支付
|
||||||
|
func (l *AlipayCallbackLogic) handleQueryOrderPayment(w http.ResponseWriter, notification *alipay.Notification) error {
|
||||||
|
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, notification.OutTradeNo)
|
||||||
|
if findOrderErr != nil {
|
||||||
|
logx.Errorf("支付宝支付回调,查找订单失败: %+v", findOrderErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if order.Status != "pending" {
|
||||||
|
alipay.ACKNotification(w)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := l.svcCtx.UserModel.FindOne(l.ctx, order.UserId)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("支付宝支付回调,查找用户失败: %+v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
amount := lzUtils.ToAlipayAmount(order.Amount)
|
||||||
|
if user.Inside != 1 {
|
||||||
|
// 确保订单金额和状态正确,防止重复更新
|
||||||
|
if amount != notification.TotalAmount {
|
||||||
|
logx.Errorf("支付宝支付回调,金额不一致")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch notification.TradeStatus {
|
||||||
|
case alipay.TradeStatusSuccess:
|
||||||
|
order.Status = "paid"
|
||||||
|
order.PayTime = lzUtils.TimeToNullTime(time.Now())
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
order.PlatformOrderId = lzUtils.StringToNullString(notification.TradeNo)
|
||||||
|
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
|
||||||
|
logx.Errorf("支付宝支付回调,修改订单信息失败: %+v", updateErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if order.Status == "paid" {
|
||||||
|
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
|
||||||
|
logx.Errorf("异步任务调度失败: %v", asyncErr)
|
||||||
|
return asyncErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alipay.ACKNotification(w)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理代理会员订单支付
|
||||||
|
func (l *AlipayCallbackLogic) handleAgentVipOrderPayment(w http.ResponseWriter, notification *alipay.Notification) error {
|
||||||
|
agentOrder, findAgentOrderErr := l.svcCtx.AgentMembershipRechargeOrderModel.FindOneByOrderNo(l.ctx, notification.OutTradeNo)
|
||||||
|
if findAgentOrderErr != nil {
|
||||||
|
logx.Errorf("支付宝支付回调,查找代理会员订单失败: %+v", findAgentOrderErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if agentOrder.Status != "pending" {
|
||||||
|
alipay.ACKNotification(w)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := l.svcCtx.UserModel.FindOne(l.ctx, agentOrder.UserId)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("支付宝支付回调,查找用户失败: %+v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
amount := lzUtils.ToAlipayAmount(agentOrder.Amount)
|
||||||
|
if user.Inside != 1 {
|
||||||
|
// 确保订单金额和状态正确,防止重复更新
|
||||||
|
if amount != notification.TotalAmount {
|
||||||
|
logx.Errorf("支付宝支付回调,金额不一致")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch notification.TradeStatus {
|
||||||
|
case alipay.TradeStatusSuccess:
|
||||||
|
agentOrder.Status = "paid"
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if agentOrder.Status == "paid" {
|
||||||
|
err = l.svcCtx.AgentModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOne(transCtx, agentOrder.AgentId)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("查找代理信息失败: %+v", err)
|
||||||
|
}
|
||||||
|
agentOrder.PlatformOrderId = lzUtils.StringToNullString(notification.TradeNo)
|
||||||
|
if updateErr := l.svcCtx.AgentMembershipRechargeOrderModel.UpdateWithVersion(l.ctx, nil, agentOrder); updateErr != nil {
|
||||||
|
return fmt.Errorf("修改代理会员订单信息失败: %+v", updateErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置会员等级
|
||||||
|
agentModel.LevelName = agentOrder.LevelName
|
||||||
|
|
||||||
|
// 延长会员时间
|
||||||
|
// 检查是否是同级续费并记录到日志
|
||||||
|
isRenewal := agentModel.LevelName == agentOrder.LevelName && agentModel.MembershipExpiryTime.Valid
|
||||||
|
if isRenewal {
|
||||||
|
logx.Infof("代理会员续费成功,会员ID:%d,等级:%s", agentModel.Id, agentModel.LevelName)
|
||||||
|
} else {
|
||||||
|
logx.Infof("代理会员新购或升级成功,会员ID:%d,等级:%s", agentModel.Id, agentModel.LevelName)
|
||||||
|
}
|
||||||
|
agentModel.MembershipExpiryTime = lzUtils.RenewMembership(agentModel.MembershipExpiryTime)
|
||||||
|
|
||||||
|
if updateErr := l.svcCtx.AgentModel.UpdateWithVersion(l.ctx, nil, agentModel); updateErr != nil {
|
||||||
|
return fmt.Errorf("修改代理信息失败: %+v", updateErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("支付宝支付回调,处理代理会员订单失败: %+v", err)
|
||||||
|
refundErr := l.handleRefund(agentOrder)
|
||||||
|
if refundErr != nil {
|
||||||
|
logx.Errorf("支付宝支付回调,退款失败: %+v", refundErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alipay.ACKNotification(w)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *AlipayCallbackLogic) handleRefund(order *model.AgentMembershipRechargeOrder) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
// 退款
|
||||||
|
if order.PaymentMethod == "wechat" {
|
||||||
|
refundErr := l.svcCtx.WechatPayService.WeChatRefund(ctx, order.OrderNo, order.Amount, order.Amount)
|
||||||
|
if refundErr != nil {
|
||||||
|
return refundErr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount)
|
||||||
|
if refundErr != nil {
|
||||||
|
return refundErr
|
||||||
|
}
|
||||||
|
if refund.IsSuccess() {
|
||||||
|
logx.Errorf("支付宝退款成功, orderID: %d", order.Id)
|
||||||
|
// 更新订单状态为退款
|
||||||
|
order.Status = "refunded"
|
||||||
|
updateOrderErr := l.svcCtx.AgentMembershipRechargeOrderModel.UpdateWithVersion(ctx, nil, order)
|
||||||
|
if updateOrderErr != nil {
|
||||||
|
logx.Errorf("更新订单状态失败,订单ID: %d, 错误: %v", order.Id, updateOrderErr)
|
||||||
|
return fmt.Errorf("更新订单状态失败: %v", updateOrderErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
logx.Errorf("支付宝退款失败:%v", refundErr)
|
||||||
|
return refundErr
|
||||||
|
}
|
||||||
|
// 直接成功
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
82
app/main/api/internal/logic/pay/iapcallbacklogic.go
Normal file
82
app/main/api/internal/logic/pay/iapcallbacklogic.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/lzUtils"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IapCallbackLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIapCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *IapCallbackLogic {
|
||||||
|
return &IapCallbackLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *IapCallbackLogic) IapCallback(req *types.IapCallbackReq) error {
|
||||||
|
// Step 1: 查找订单
|
||||||
|
order, findOrderErr := l.svcCtx.OrderModel.FindOne(l.ctx, req.OrderID)
|
||||||
|
if findOrderErr != nil {
|
||||||
|
logx.Errorf("苹果内购支付回调,查找订单失败: %+v", findOrderErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: 验证订单状态
|
||||||
|
if order.Status != "pending" {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "苹果内购支付回调, 订单状态异常: %+v", order)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: 调用 VerifyReceipt 验证苹果支付凭证
|
||||||
|
//receipt := req.TransactionReceipt // 从请求中获取支付凭证
|
||||||
|
//verifyResponse, verifyErr := l.svcCtx.ApplePayService.VerifyReceipt(l.ctx, receipt)
|
||||||
|
//if verifyErr != nil {
|
||||||
|
// return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "苹果内购支付回调, 验证订单异常: %+v", verifyErr)
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Step 4: 验证订单
|
||||||
|
//product, findProductErr := l.svcCtx.ProductModel.FindOne(l.ctx, order.Id)
|
||||||
|
//if findProductErr != nil {
|
||||||
|
// return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "苹果内购支付回调, 获取订单相关商品失败: %+v", findProductErr)
|
||||||
|
//}
|
||||||
|
//isProductMatched := false
|
||||||
|
//appleProductID := l.svcCtx.ApplePayService.GetIappayAppID(product.ProductEn)
|
||||||
|
//for _, item := range verifyResponse.Receipt.InApp {
|
||||||
|
// if item.ProductID == appleProductID {
|
||||||
|
// isProductMatched = true
|
||||||
|
// order.PlatformOrderId = lzUtils.StringToNullString(item.TransactionID) // 记录交易 ID
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//if !isProductMatched {
|
||||||
|
// return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "苹果内购支付回调, 商品 ID 不匹配,订单 ID: %d, 回调苹果商品 ID: %s", order.Id, verifyResponse.Receipt.InApp[0].ProductID)
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Step 5: 更新订单状态 mm
|
||||||
|
order.Status = "paid"
|
||||||
|
order.PayTime = lzUtils.TimeToNullTime(time.Now())
|
||||||
|
|
||||||
|
// 更新订单到数据库
|
||||||
|
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "苹果内购支付回调, 修改订单信息失败: %+v", updateErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 6: 处理订单完成后的逻辑
|
||||||
|
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "苹果内购支付回调,异步任务调度失败: %v", asyncErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
49
app/main/api/internal/logic/pay/paymentchecklogic.go
Normal file
49
app/main/api/internal/logic/pay/paymentchecklogic.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PaymentCheckLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPaymentCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentCheckLogic {
|
||||||
|
return &PaymentCheckLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *PaymentCheckLogic) PaymentCheck(req *types.PaymentCheckReq) (resp *types.PaymentCheckResp, err error) {
|
||||||
|
if strings.HasPrefix(req.OrderNo, "A_") {
|
||||||
|
order, err := l.svcCtx.AgentMembershipRechargeOrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询订单失败: %v", err)
|
||||||
|
}
|
||||||
|
return &types.PaymentCheckResp{
|
||||||
|
Type: "agent_vip",
|
||||||
|
Status: order.Status,
|
||||||
|
}, nil
|
||||||
|
} else {
|
||||||
|
order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询订单失败: %v", err)
|
||||||
|
}
|
||||||
|
return &types.PaymentCheckResp{
|
||||||
|
Type: "query",
|
||||||
|
Status: order.Status,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
227
app/main/api/internal/logic/pay/paymentlogic.go
Normal file
227
app/main/api/internal/logic/pay/paymentlogic.go
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/ctxdata"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
"tydata-server/pkg/lzkit/crypto"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PaymentLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
type PaymentTypeResp struct {
|
||||||
|
amount float64
|
||||||
|
outTradeNo string
|
||||||
|
description string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLogic {
|
||||||
|
return &PaymentLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp, err error) {
|
||||||
|
var paymentTypeResp *PaymentTypeResp
|
||||||
|
var prepayData interface{}
|
||||||
|
l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
|
switch req.PayType {
|
||||||
|
case "agent_vip":
|
||||||
|
paymentTypeResp, err = l.AgentVipOrderPayment(req, session)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case "query":
|
||||||
|
paymentTypeResp, err = l.QueryOrderPayment(req, session)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var createOrderErr error
|
||||||
|
if req.PayMethod == "wechat" {
|
||||||
|
prepayData, createOrderErr = l.svcCtx.WechatPayService.CreateWechatOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
|
||||||
|
} else if req.PayMethod == "alipay" {
|
||||||
|
prepayData, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
|
||||||
|
} else if req.PayMethod == "appleiap" {
|
||||||
|
prepayData = l.svcCtx.ApplePayService.GetIappayAppID(paymentTypeResp.outTradeNo)
|
||||||
|
}
|
||||||
|
if createOrderErr != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 创建支付订单失败: %+v", createOrderErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch v := prepayData.(type) {
|
||||||
|
case string:
|
||||||
|
// 如果 prepayData 是字符串类型,直接返回
|
||||||
|
return &types.PaymentResp{PrepayId: v, OrderNo: paymentTypeResp.outTradeNo}, nil
|
||||||
|
default:
|
||||||
|
return &types.PaymentResp{PrepayData: prepayData, OrderNo: paymentTypeResp.outTradeNo}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Session) (resp *PaymentTypeResp, err error) {
|
||||||
|
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if getUidErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取用户信息失败, %+v", getUidErr)
|
||||||
|
}
|
||||||
|
outTradeNo := req.Id
|
||||||
|
redisKey := fmt.Sprintf(types.QueryCacheKey, userID, outTradeNo)
|
||||||
|
cache, cacheErr := l.svcCtx.Redis.GetCtx(l.ctx, redisKey)
|
||||||
|
if cacheErr != nil {
|
||||||
|
if cacheErr == redis.Nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("订单已过期"), "生成订单, 缓存不存在, %+v", cacheErr)
|
||||||
|
}
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取缓存失败, %+v", cacheErr)
|
||||||
|
}
|
||||||
|
var data types.QueryCacheLoad
|
||||||
|
err = json.Unmarshal([]byte(cache), &data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解析缓存内容失败, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
product, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, data.Product)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 查找产品错误: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var amount float64
|
||||||
|
user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取用户信息失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.AgentIdentifier != "" {
|
||||||
|
agentLinkModel, findAgentLinkErr := l.svcCtx.AgentLinkModel.FindOneByLinkIdentifier(l.ctx, data.AgentIdentifier)
|
||||||
|
if findAgentLinkErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取代理订单失败: %+v", findAgentLinkErr)
|
||||||
|
}
|
||||||
|
amount = agentLinkModel.Price
|
||||||
|
} else {
|
||||||
|
amount = product.SellPrice
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Inside == 1 {
|
||||||
|
amount = 0.01
|
||||||
|
}
|
||||||
|
var orderID int64
|
||||||
|
order := model.Order{
|
||||||
|
OrderNo: outTradeNo,
|
||||||
|
UserId: userID,
|
||||||
|
ProductId: product.Id,
|
||||||
|
PaymentPlatform: req.PayMethod,
|
||||||
|
PaymentScene: "app",
|
||||||
|
Amount: amount,
|
||||||
|
Status: "pending",
|
||||||
|
}
|
||||||
|
orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(l.ctx, session, &order)
|
||||||
|
if insertOrderErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存订单失败: %+v", insertOrderErr)
|
||||||
|
}
|
||||||
|
insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId()
|
||||||
|
if lastInsertIdErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取保存订单ID失败: %+v", lastInsertIdErr)
|
||||||
|
}
|
||||||
|
orderID = insertedOrderID
|
||||||
|
|
||||||
|
if data.AgentIdentifier != "" {
|
||||||
|
agent, parsingErr := l.agentParsing(data.AgentIdentifier)
|
||||||
|
if parsingErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 解析代理标识符失败: %+v", parsingErr)
|
||||||
|
}
|
||||||
|
var agentOrder model.AgentOrder
|
||||||
|
agentOrder.OrderId = orderID
|
||||||
|
agentOrder.AgentId = agent.AgentID
|
||||||
|
_, agentOrderInsert := l.svcCtx.AgentOrderModel.Insert(l.ctx, session, &agentOrder)
|
||||||
|
if agentOrderInsert != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理订单失败: %+v", agentOrderInsert)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &PaymentTypeResp{amount: amount, outTradeNo: outTradeNo, description: product.ProductName}, nil
|
||||||
|
}
|
||||||
|
func (l *PaymentLogic) AgentVipOrderPayment(req *types.PaymentReq, session sqlx.Session) (resp *PaymentTypeResp, err error) {
|
||||||
|
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
|
||||||
|
if getUidErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取用户信息失败, %+v", getUidErr)
|
||||||
|
}
|
||||||
|
user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取用户信息失败: %v", err)
|
||||||
|
}
|
||||||
|
// 查询用户代理信息
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
|
||||||
|
}
|
||||||
|
redisKey := fmt.Sprintf(types.AgentVipCacheKey, userID, req.Id)
|
||||||
|
cache, cacheErr := l.svcCtx.Redis.GetCtx(l.ctx, redisKey)
|
||||||
|
if cacheErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取缓存失败, %+v", cacheErr)
|
||||||
|
}
|
||||||
|
var agentVipCache types.AgentVipCache
|
||||||
|
err = json.Unmarshal([]byte(cache), &agentVipCache)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解析缓存内容失败, %+v", err)
|
||||||
|
}
|
||||||
|
agentMembershipConfig, err := l.svcCtx.AgentMembershipConfigModel.FindOneByLevelName(l.ctx, agentVipCache.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取代理会员配置失败, %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
amount := agentMembershipConfig.Price.Float64
|
||||||
|
if user.Inside == 1 {
|
||||||
|
amount = 0.01
|
||||||
|
}
|
||||||
|
agentMembershipRechargeOrder := model.AgentMembershipRechargeOrder{
|
||||||
|
OrderNo: req.Id,
|
||||||
|
UserId: userID,
|
||||||
|
AgentId: agentModel.Id,
|
||||||
|
Amount: amount,
|
||||||
|
PaymentMethod: req.PayMethod,
|
||||||
|
LevelName: agentVipCache.Type,
|
||||||
|
Status: "pending",
|
||||||
|
}
|
||||||
|
_, err = l.svcCtx.AgentMembershipRechargeOrderModel.Insert(l.ctx, session, &agentMembershipRechargeOrder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理会员充值订单失败: %+v", err)
|
||||||
|
}
|
||||||
|
return &PaymentTypeResp{amount: amount, outTradeNo: req.Id, description: fmt.Sprintf("%s代理会员充值", agentMembershipConfig.LevelName)}, nil
|
||||||
|
}
|
||||||
|
func (l *PaymentLogic) agentParsing(agentIdentifier string) (*types.AgentIdentifier, error) {
|
||||||
|
key, decodeErr := hex.DecodeString("8e3e7a2f60edb49221e953b9c029ed10")
|
||||||
|
if decodeErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取AES密钥失败: %+v", decodeErr)
|
||||||
|
}
|
||||||
|
// Encrypt the params
|
||||||
|
|
||||||
|
encrypted, err := crypto.AesDecryptURL(agentIdentifier, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, %v", err)
|
||||||
|
}
|
||||||
|
var agentIdentifierStruct types.AgentIdentifier
|
||||||
|
err = json.Unmarshal(encrypted, &agentIdentifierStruct)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务,反序列化失败 %v", err)
|
||||||
|
}
|
||||||
|
return &agentIdentifierStruct, nil
|
||||||
|
}
|
215
app/main/api/internal/logic/pay/wechatpaycallbacklogic.go
Normal file
215
app/main/api/internal/logic/pay/wechatpaycallbacklogic.go
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/service"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/pkg/lzkit/lzUtils"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
|
||||||
|
"github.com/wechatpay-apiv3/wechatpay-go/services/payments"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WechatPayCallbackLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWechatPayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatPayCallbackLogic {
|
||||||
|
return &WechatPayCallbackLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *WechatPayCallbackLogic) WechatPayCallback(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
notification, err := l.svcCtx.WechatPayService.HandleWechatPayNotification(l.ctx, r)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("微信支付回调,%v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据订单号前缀判断订单类型
|
||||||
|
orderNo := *notification.OutTradeNo
|
||||||
|
if strings.HasPrefix(orderNo, "Q_") {
|
||||||
|
// 查询订单处理
|
||||||
|
return l.handleQueryOrderPayment(w, notification)
|
||||||
|
} else if strings.HasPrefix(orderNo, "A_") {
|
||||||
|
// 代理会员订单处理
|
||||||
|
return l.handleAgentVipOrderPayment(w, notification)
|
||||||
|
} else {
|
||||||
|
// 兼容旧订单,假设没有前缀的是查询订单
|
||||||
|
return l.handleQueryOrderPayment(w, notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理查询订单支付
|
||||||
|
func (l *WechatPayCallbackLogic) handleQueryOrderPayment(w http.ResponseWriter, notification *payments.Transaction) error {
|
||||||
|
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)
|
||||||
|
if findOrderErr != nil {
|
||||||
|
logx.Errorf("微信支付回调,查找订单信息失败: %+v", findOrderErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
amount := lzUtils.ToWechatAmount(order.Amount)
|
||||||
|
if amount != *notification.Amount.Total {
|
||||||
|
logx.Errorf("微信支付回调,金额不一致")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if order.Status != "pending" {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("success"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch *notification.TradeState {
|
||||||
|
case service.TradeStateSuccess:
|
||||||
|
order.Status = "paid"
|
||||||
|
order.PayTime = lzUtils.TimeToNullTime(time.Now())
|
||||||
|
case service.TradeStateClosed:
|
||||||
|
order.Status = "closed"
|
||||||
|
order.CloseTime = lzUtils.TimeToNullTime(time.Now())
|
||||||
|
case service.TradeStateRevoked:
|
||||||
|
order.Status = "failed"
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
order.PlatformOrderId = lzUtils.StringToNullString(*notification.TransactionId)
|
||||||
|
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
|
||||||
|
logx.Errorf("微信支付回调,更新订单失败%+v", updateErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if order.Status == "paid" {
|
||||||
|
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
|
||||||
|
logx.Errorf("异步任务调度失败: %v", asyncErr)
|
||||||
|
return asyncErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("success"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理代理会员订单支付
|
||||||
|
func (l *WechatPayCallbackLogic) handleAgentVipOrderPayment(w http.ResponseWriter, notification *payments.Transaction) error {
|
||||||
|
agentOrder, findAgentOrderErr := l.svcCtx.AgentMembershipRechargeOrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)
|
||||||
|
if findAgentOrderErr != nil {
|
||||||
|
logx.Errorf("微信支付回调,查找代理会员订单失败: %+v", findAgentOrderErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if agentOrder.Status != "pending" {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("success"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := l.svcCtx.UserModel.FindOne(l.ctx, agentOrder.UserId)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("微信支付回调,查找用户失败: %+v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
amount := lzUtils.ToWechatAmount(agentOrder.Amount)
|
||||||
|
if user.Inside != 1 {
|
||||||
|
if amount != *notification.Amount.Total {
|
||||||
|
logx.Errorf("微信支付回调,金额不一致")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch *notification.TradeState {
|
||||||
|
case service.TradeStateSuccess:
|
||||||
|
agentOrder.Status = "paid"
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if agentOrder.Status == "paid" {
|
||||||
|
err = l.svcCtx.AgentModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
|
||||||
|
agentModel, err := l.svcCtx.AgentModel.FindOne(transCtx, agentOrder.AgentId)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("查找代理信息失败: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentOrder.PlatformOrderId = lzUtils.StringToNullString(*notification.TransactionId)
|
||||||
|
if updateErr := l.svcCtx.AgentMembershipRechargeOrderModel.UpdateWithVersion(l.ctx, nil, agentOrder); updateErr != nil {
|
||||||
|
return fmt.Errorf("修改代理会员订单信息失败: %+v", updateErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置会员等级
|
||||||
|
agentModel.LevelName = agentOrder.LevelName
|
||||||
|
|
||||||
|
// 延长会员时间
|
||||||
|
isRenewal := agentModel.LevelName == agentOrder.LevelName && agentModel.MembershipExpiryTime.Valid
|
||||||
|
if isRenewal {
|
||||||
|
logx.Infof("代理会员续费成功,会员ID:%d,等级:%s", agentModel.Id, agentModel.LevelName)
|
||||||
|
} else {
|
||||||
|
logx.Infof("代理会员新购或升级成功,会员ID:%d,等级:%s", agentModel.Id, agentModel.LevelName)
|
||||||
|
}
|
||||||
|
agentModel.MembershipExpiryTime = lzUtils.RenewMembership(agentModel.MembershipExpiryTime)
|
||||||
|
|
||||||
|
if updateErr := l.svcCtx.AgentModel.UpdateWithVersion(l.ctx, nil, agentModel); updateErr != nil {
|
||||||
|
return fmt.Errorf("修改代理信息失败: %+v", updateErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("微信支付回调,处理代理会员订单失败: %+v", err)
|
||||||
|
refundErr := l.handleRefund(agentOrder)
|
||||||
|
if refundErr != nil {
|
||||||
|
logx.Errorf("微信支付回调,退款失败: %+v", refundErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("success"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *WechatPayCallbackLogic) handleRefund(order *model.AgentMembershipRechargeOrder) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
// 退款
|
||||||
|
if order.PaymentMethod == "wechat" {
|
||||||
|
refundErr := l.svcCtx.WechatPayService.WeChatRefund(ctx, order.OrderNo, order.Amount, order.Amount)
|
||||||
|
if refundErr != nil {
|
||||||
|
return refundErr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount)
|
||||||
|
if refundErr != nil {
|
||||||
|
return refundErr
|
||||||
|
}
|
||||||
|
if refund.IsSuccess() {
|
||||||
|
logx.Errorf("支付宝退款成功, orderID: %d", order.Id)
|
||||||
|
// 更新订单状态为退款
|
||||||
|
order.Status = "refunded"
|
||||||
|
updateOrderErr := l.svcCtx.AgentMembershipRechargeOrderModel.UpdateWithVersion(ctx, nil, order)
|
||||||
|
if updateOrderErr != nil {
|
||||||
|
logx.Errorf("更新订单状态失败,订单ID: %d, 错误: %v", order.Id, updateOrderErr)
|
||||||
|
return fmt.Errorf("更新订单状态失败: %v", updateOrderErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
logx.Errorf("支付宝退款失败:%v", refundErr)
|
||||||
|
return refundErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package pay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
|
||||||
|
"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WechatPayRefundCallbackLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWechatPayRefundCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatPayRefundCallbackLogic {
|
||||||
|
return &WechatPayRefundCallbackLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *WechatPayRefundCallbackLogic) WechatPayRefundCallback(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
notification, err := l.svcCtx.WechatPayService.HandleRefundNotification(l.ctx, r)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("微信退款回调,%v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)
|
||||||
|
if findOrderErr != nil {
|
||||||
|
logx.Errorf("微信退款回调,查找订单信息失败: %+v", findOrderErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch *notification.Status {
|
||||||
|
case refunddomestic.STATUS_SUCCESS:
|
||||||
|
order.Status = "refunded"
|
||||||
|
case refunddomestic.STATUS_ABNORMAL:
|
||||||
|
// 异常
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
|
||||||
|
logx.Errorf("微信退款回调,更新订单失败%+v", updateErr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 响应微信回调成功
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("success")) // 确保只写入一次响应
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tydata-server/app/user/model"
|
||||||
|
"tydata-server/common/xerr"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zeromicro/go-zero/core/mr"
|
||||||
|
|
||||||
|
"tydata-server/app/user/cmd/api/internal/svc"
|
||||||
|
"tydata-server/app/user/cmd/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetProductAppByEnLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetProductAppByEnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductAppByEnLogic {
|
||||||
|
return &GetProductAppByEnLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetProductAppByEnLogic) GetProductAppByEn(req *types.GetProductByEnRequest) (resp *types.ProductResponse, err error) {
|
||||||
|
productModel, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, req.ProductEn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "产品查询, 查找产品错误: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
build := l.svcCtx.ProductFeatureModel.SelectBuilder().Where(squirrel.Eq{
|
||||||
|
"product_id": productModel.Id,
|
||||||
|
})
|
||||||
|
productFeatureAll, err := l.svcCtx.ProductFeatureModel.FindAll(l.ctx, build, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "产品查询, 查找产品关联错误: %v", err)
|
||||||
|
}
|
||||||
|
var product types.Product
|
||||||
|
err = copier.Copy(&product, productModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %v", err)
|
||||||
|
}
|
||||||
|
mr.MapReduceVoid(func(source chan<- interface{}) {
|
||||||
|
for _, productFeature := range productFeatureAll {
|
||||||
|
source <- productFeature.FeatureId
|
||||||
|
}
|
||||||
|
}, func(item interface{}, writer mr.Writer[*model.Feature], cancel func(error)) {
|
||||||
|
id := item.(int64)
|
||||||
|
|
||||||
|
feature, findFeatureErr := l.svcCtx.FeatureModel.FindOne(l.ctx, id)
|
||||||
|
if findFeatureErr != nil {
|
||||||
|
logx.WithContext(l.ctx).Errorf("产品查询, 查找关联feature错误: %d, err:%v", id, findFeatureErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if feature != nil && feature.Id > 0 {
|
||||||
|
writer.Write(feature)
|
||||||
|
}
|
||||||
|
}, func(pipe <-chan *model.Feature, cancel func(error)) {
|
||||||
|
for item := range pipe {
|
||||||
|
var feature types.Feature
|
||||||
|
_ = copier.Copy(&feature, item)
|
||||||
|
product.Features = append(product.Features, feature)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return &types.ProductResponse{Product: product}, nil
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user