Compare commits
197 Commits
2aacbf1c3e
...
b9b7309edc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9b7309edc | ||
|
|
d22be1d676 | ||
|
|
2d0b23e063 | ||
|
|
01b78a099a | ||
|
|
fcfea291e5 | ||
|
|
9c08acc97a | ||
|
|
1203c087d8 | ||
|
|
91c1c580f9 | ||
|
|
b571b1b31c | ||
|
|
62565fac4e | ||
|
|
54613f5be0 | ||
|
|
dd8b864a7f | ||
|
|
8d3fce919f | ||
|
|
c880cba0a3 | ||
|
|
194dc50eaa | ||
|
|
ee6e31473e | ||
|
|
0989faf35a | ||
|
|
93b0cadea9 | ||
|
|
f387e46977 | ||
|
|
c46d9d8fd9 | ||
|
|
ad01dbc0e5 | ||
|
|
26389bf4d6 | ||
|
|
15888a953b | ||
|
|
2c995e9512 | ||
|
|
44fd4f03e3 | ||
|
|
76f4a682ac | ||
|
|
9e6f919fa8 | ||
|
|
e2508cc347 | ||
|
|
d07350969f | ||
|
|
6e9f47ff85 | ||
|
|
42bd585fe9 | ||
|
|
f20b4fad3e | ||
|
|
871a7a278b | ||
|
|
83dc607ec4 | ||
|
|
fae365d59e | ||
|
|
821cbb8879 | ||
|
|
821e36281a | ||
|
|
ef522551e4 | ||
|
|
c7a2cf7d1c | ||
|
|
4dfeebeaed | ||
|
|
31debda97f | ||
|
|
a1d78b7a0c | ||
|
|
03cbe2894e | ||
|
|
82fc0f2b80 | ||
|
|
2747c9ddd9 | ||
|
|
d45a0eb680 | ||
|
|
4cd2e1ce65 | ||
|
|
00b3a974f9 | ||
|
|
f9595aad3f | ||
|
|
85cd2bff8d | ||
|
|
1e444ca616 | ||
|
|
1543e60301 | ||
|
|
600a6edd7b | ||
|
|
407ba29319 | ||
|
|
c42c37f65e | ||
|
|
cdeec5a4e1 | ||
|
|
94088b5aa4 | ||
|
|
e23ee6518d | ||
|
|
79120e1fd9 | ||
|
|
6a41be4f3a | ||
|
|
f7992279e2 | ||
|
|
01cc115a60 | ||
|
|
47a1ecfc79 | ||
|
|
55a4526536 | ||
|
|
7eab65be87 | ||
|
|
fc302ad1be | ||
|
|
87c2d7bf96 | ||
|
|
27f429cdec | ||
|
|
f615e4fe77 | ||
|
|
87ff25a2e6 | ||
|
|
a832a6fa81 | ||
|
|
0e282e741b | ||
|
|
d0323646c5 | ||
|
|
2331979b65 | ||
|
|
c12675698b | ||
|
|
abdf8a43e7 | ||
|
|
3bba720f67 | ||
|
|
46f3b2ff0e | ||
|
|
6c2fba2b3a | ||
|
|
916e050585 | ||
|
|
5b3e3f047e | ||
| b03e2d020f | |||
|
|
cb9b8ed6fd | ||
|
|
7490a3b324 | ||
|
|
3f4b341c33 | ||
|
|
cef9dfa34d | ||
|
|
95cbaea69a | ||
|
|
17b98f83ff | ||
|
|
4261a5a97d | ||
|
|
91acf4d2bc | ||
|
|
f713124154 | ||
|
|
4bbe9aaaa3 | ||
|
|
07185fdb46 | ||
|
|
178cda5402 | ||
|
|
3c094cf201 | ||
|
|
66084f9e96 | ||
|
|
c1203e8989 | ||
|
|
5be1edfa71 | ||
|
|
6005f20c5e | ||
|
|
8fe6e8be74 | ||
|
|
f2a0c7608e | ||
|
|
29c7dc54e3 | ||
|
|
d8d91e9270 | ||
|
|
02b3788dc9 | ||
|
|
a7f21da8da | ||
|
|
287ee4db37 | ||
|
|
0a4368ba7f | ||
|
|
656d5038fe | ||
|
|
c34811df83 | ||
|
|
98bc6294e6 | ||
|
|
2054b9ec97 | ||
|
|
b398da58e1 | ||
|
|
7e400ed761 | ||
|
|
bea1fd230a | ||
|
|
a2b7bfb253 | ||
|
|
646c04eba9 | ||
|
|
1bd2b83bca | ||
|
|
d6134a7407 | ||
|
|
c3011e87eb | ||
|
|
e811bf3e4a | ||
|
|
b3ed5703a8 | ||
|
|
f6e073bb41 | ||
|
|
b6651c4bdc | ||
|
|
bfea40c643 | ||
|
|
c8a52321a5 | ||
|
|
129583d19a | ||
|
|
c2bb174574 | ||
|
|
551f9083e9 | ||
|
|
c36c8ab6f9 | ||
|
|
6fd3bc8a3b | ||
|
|
4005af2040 | ||
|
|
20150a81b5 | ||
|
|
e4c165cd18 | ||
|
|
366a441cf2 | ||
|
|
ec4fe76856 | ||
|
|
173fa23e80 | ||
|
|
b6e994844e | ||
|
|
9a4899558e | ||
|
|
b1675ae0bf | ||
|
|
8b81308bd2 | ||
|
|
cc7d7361d4 | ||
|
|
730491ffed | ||
|
|
9753920595 | ||
|
|
2fc914214c | ||
|
|
ddb4ec944d | ||
|
|
c2723861fa | ||
|
|
c82ae399b7 | ||
|
|
c163cfe234 | ||
|
|
72e75e7858 | ||
|
|
c9af4fb420 | ||
|
|
27ae48991c | ||
|
|
65a7d530cc | ||
|
|
7866a5a369 | ||
|
|
0dcaf2ce09 | ||
|
|
dd6b80ee71 | ||
|
|
4c944c8c72 | ||
|
|
e29e8d8049 | ||
|
|
e1094b9be6 | ||
|
|
fc50bf587f | ||
|
|
11cee190b0 | ||
|
|
21c4907e44 | ||
|
|
951635e7f8 | ||
|
|
2a849dde38 | ||
|
|
caf2f753a5 | ||
|
|
2d224c0d67 | ||
|
|
e925d8c684 | ||
|
|
a6a40a2ad5 | ||
|
|
baa0cc1644 | ||
|
|
db7d53532a | ||
|
|
6985b76e49 | ||
|
|
745cea9617 | ||
|
|
d00089c625 | ||
|
|
0f7514b5bd | ||
|
|
95cd86d103 | ||
|
|
85b391a4d2 | ||
|
|
e2db17c326 | ||
|
|
741963275e | ||
|
|
541627183b | ||
|
|
cd6a919145 | ||
|
|
bb645ce6f6 | ||
|
|
1040f21ca6 | ||
|
|
fead7c6ae9 | ||
|
|
15f589c09d | ||
| c4b4b72947 | |||
| 99f785a7c3 | |||
| c280a661a1 | |||
| b37c2094ed | |||
| e6470719bb | |||
| 6260d29dc7 | |||
| 7aa4a57257 | |||
| 7324aabbd6 | |||
| 0b8f6e69cf | |||
| bd1b6ee23e | |||
| 58e2068170 | |||
| 45ef0b8bc9 | |||
| ff011f6452 | |||
| d3c96184b8 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -44,4 +44,6 @@ shared-state
|
||||
|
||||
*.zip
|
||||
|
||||
vendor
|
||||
vendor
|
||||
|
||||
grpc_server/gen
|
||||
@ -3,7 +3,7 @@ package constants
|
||||
// 订单类型
|
||||
const (
|
||||
DELIVERYMETHODDIRECTMAIL int64 = 1
|
||||
DELIVERYMETHODDSCLOUDSTORE int64 = 1
|
||||
DELIVERYMETHODDSCLOUDSTORE int64 = 2
|
||||
)
|
||||
|
||||
// 货币
|
||||
@ -23,8 +23,8 @@ type ExchangeRateUnit interface{}
|
||||
type PayMethods string
|
||||
|
||||
const (
|
||||
PAYMETHODCARD PayMethods = "CARD"
|
||||
PayMethodVISA PayMethods = "VISA"
|
||||
PAY_METHOD_CARD PayMethods = "CARD"
|
||||
PayMethodVISA PayMethods = "VISA"
|
||||
)
|
||||
|
||||
// 支付状态
|
||||
@ -56,18 +56,21 @@ const (
|
||||
type OrderStatusCode int64
|
||||
|
||||
const (
|
||||
ORDERSTATUSUNPAIDDEPOSIT OrderStatusCode = 0 // 0,未支付定金
|
||||
ORDERSTATUSDIRECTMAILORDERED OrderStatusCode = 10100 // 10100,直邮单--已下单
|
||||
ORDERSTATUSDIRECTMAILCANCEL OrderStatusCode = 10101 // 10101,直邮单--已取消
|
||||
ORDERSTATUSDIRECTMAILSTARTPRODUCTION OrderStatusCode = 10200 // 10200,直邮单--开始生产
|
||||
ORDERSTATUSDIRECTMAILCOMPLETEPRODUCTION OrderStatusCode = 10300 // 10300,直邮单--生产完成
|
||||
ORDERSTATUSDIRECTMAILSHIPPED OrderStatusCode = 10400 // 10400,直邮单--已发货
|
||||
ORDERSTATUSDIRECTMAILARRIVED OrderStatusCode = 10500 // 10500,直邮单--已到达
|
||||
ORDERSTATUSCLOUDSTOREORDERED OrderStatusCode = 20100 // 20100,云仓单--已下单
|
||||
ORDERSTATUSCLOUDSTORECANCEL OrderStatusCode = 20101 // 20101,云仓单--已取消
|
||||
ORDERSTATUSCLOUDSTORESTARTPRODUCTION OrderStatusCode = 20200 // 20200,云仓单--开始生产
|
||||
ORDERSTATUSCLOUDSTOREOMPLETEPRODUCTION OrderStatusCode = 20300 // 20300,云仓单--生产完成
|
||||
ORDERSTATUSCLOUDSTOREARRIVEDWAREHOUSE OrderStatusCode = 20400 // 20400,云仓单--直达仓库
|
||||
ORDER_STATUS_UNPAIDDEPOSIT OrderStatusCode = 0 // 0,未支付定金
|
||||
ORDER_STATUS_DIRECTMAIL_ORDERED OrderStatusCode = 10100 // 10100,直邮单--已下单
|
||||
ORDER_STATUS_DIRECTMAIL_ORDEREDMAINING OrderStatusCode = 10100001 // 10100001,直邮单--已下单--尾款
|
||||
ORDER_STATUS_DIRECTMAIL_CANCEL OrderStatusCode = 10101 // 10101,直邮单--已取消
|
||||
ORDER_STATUS_DIRECTMAIL_STARTPRODUCTION OrderStatusCode = 10200 // 10200,直邮单--开始生产
|
||||
ORDER_STATUS_DIRECTMAIL_COMPLETEPRODUCTION OrderStatusCode = 10300 // 10300,直邮单--生产完成
|
||||
ORDER_STATUS_DIRECTMAIL_SHIPPED OrderStatusCode = 10400 // 10400,直邮单--已发货
|
||||
ORDER_STATUS_DIRECTMAIL_ARRIVED OrderStatusCode = 10500 // 10500,直邮单--已到达
|
||||
ORDER_STATUS_CLOUDSTORE_ORDERED OrderStatusCode = 20100 // 20100,云仓单--已下单
|
||||
ORDER_STATUS_CLOUDSTORE_ORDEREDMAINING OrderStatusCode = 20100001 // 20100001,云仓单--已下单-尾款
|
||||
ORDER_STATUS_CLOUDSTORE_CANCEL OrderStatusCode = 20101 // 20101,云仓单--已取消
|
||||
ORDER_STATUS_CLOUDSTORE_STARTPRODUCTION OrderStatusCode = 20200 // 20200,云仓单--开始生产
|
||||
ORDER_STATUS_CLOUDSTORE_COMPLETEPRODUCTION OrderStatusCode = 20300 // 20300,云仓单--生产完成
|
||||
ORDER_STATUS_CLOUDSTORE_ARRIVEDWAREHOUSE OrderStatusCode = 20400 // 20400,云仓单--直达仓库
|
||||
ORDER_STATUS_COMPLETE OrderStatusCode = 30000 // 30000,订单完成
|
||||
)
|
||||
|
||||
// 订单状态名称
|
||||
@ -85,33 +88,35 @@ var OrderStatusUserCLOUDSTORE []OrderStatusCode
|
||||
func init() {
|
||||
// 订单状态名称
|
||||
PayStatusMessage = make(map[PayStatusCode]string)
|
||||
PayStatusMessage[PAYSTATUSUNPAID] = "Paid"
|
||||
PayStatusMessage[PAYSTATUSPAID] = "Unpaid"
|
||||
PayStatusMessage[PAYSTATUSUNPAID] = "Unpaid"
|
||||
PayStatusMessage[PAYSTATUSPAID] = "Paid"
|
||||
PayStatusMessage[PAYSTATUSREFUNDED] = "Refunded"
|
||||
|
||||
// 订单状态名称
|
||||
OrderStatusMessage = make(map[OrderStatusCode]string)
|
||||
OrderStatusMessage[ORDERSTATUSUNPAIDDEPOSIT] = "未支付定金"
|
||||
OrderStatusMessage[ORDER_STATUS_UNPAIDDEPOSIT] = "未支付定金"
|
||||
|
||||
OrderStatusMessage[ORDERSTATUSDIRECTMAILORDERED] = "直邮单--已下单"
|
||||
OrderStatusMessage[ORDERSTATUSDIRECTMAILSTARTPRODUCTION] = "直邮单--开始生产"
|
||||
OrderStatusMessage[ORDERSTATUSDIRECTMAILCOMPLETEPRODUCTION] = "直邮单--生产完成"
|
||||
OrderStatusMessage[ORDERSTATUSDIRECTMAILSHIPPED] = "直邮单--已发货"
|
||||
OrderStatusMessage[ORDERSTATUSDIRECTMAILARRIVED] = "直邮单--已到达"
|
||||
OrderStatusMessage[ORDER_STATUS_DIRECTMAIL_ORDERED] = "直邮单--已下单"
|
||||
OrderStatusMessage[ORDER_STATUS_DIRECTMAIL_STARTPRODUCTION] = "直邮单--开始生产"
|
||||
OrderStatusMessage[ORDER_STATUS_DIRECTMAIL_COMPLETEPRODUCTION] = "直邮单--生产完成"
|
||||
OrderStatusMessage[ORDER_STATUS_DIRECTMAIL_SHIPPED] = "直邮单--已发货"
|
||||
OrderStatusMessage[ORDER_STATUS_DIRECTMAIL_ARRIVED] = "直邮单--已到达"
|
||||
|
||||
OrderStatusMessage[ORDERSTATUSCLOUDSTOREORDERED] = "云仓单--已下单"
|
||||
OrderStatusMessage[ORDERSTATUSCLOUDSTORESTARTPRODUCTION] = "云仓单--开始生产"
|
||||
OrderStatusMessage[ORDERSTATUSCLOUDSTOREOMPLETEPRODUCTION] = "云仓单--生产完成"
|
||||
OrderStatusMessage[ORDERSTATUSCLOUDSTOREARRIVEDWAREHOUSE] = "云仓单--直达仓库"
|
||||
OrderStatusMessage[ORDER_STATUS_CLOUDSTORE_ORDERED] = "云仓单--已下单"
|
||||
OrderStatusMessage[ORDER_STATUS_CLOUDSTORE_STARTPRODUCTION] = "云仓单--开始生产"
|
||||
OrderStatusMessage[ORDER_STATUS_CLOUDSTORE_COMPLETEPRODUCTION] = "云仓单--生产完成"
|
||||
OrderStatusMessage[ORDER_STATUS_CLOUDSTORE_ARRIVEDWAREHOUSE] = "云仓单--直达仓库"
|
||||
|
||||
OrderStatusMessage[ORDER_STATUS_COMPLETE] = "订单完成"
|
||||
|
||||
// 订单状态--用户可见--直邮
|
||||
OrderStatusUserDIRECTMAIL = []OrderStatusCode{
|
||||
ORDERSTATUSUNPAIDDEPOSIT,
|
||||
ORDERSTATUSDIRECTMAILORDERED, ORDERSTATUSDIRECTMAILSTARTPRODUCTION, ORDERSTATUSDIRECTMAILCOMPLETEPRODUCTION, ORDERSTATUSDIRECTMAILSHIPPED, ORDERSTATUSDIRECTMAILARRIVED,
|
||||
ORDER_STATUS_UNPAIDDEPOSIT, ORDER_STATUS_COMPLETE,
|
||||
ORDER_STATUS_DIRECTMAIL_ORDERED, ORDER_STATUS_DIRECTMAIL_STARTPRODUCTION, ORDER_STATUS_DIRECTMAIL_COMPLETEPRODUCTION, ORDER_STATUS_DIRECTMAIL_SHIPPED, ORDER_STATUS_DIRECTMAIL_ARRIVED,
|
||||
}
|
||||
// 订单状态--用户可见--云仓
|
||||
OrderStatusUserCLOUDSTORE = []OrderStatusCode{
|
||||
ORDERSTATUSUNPAIDDEPOSIT,
|
||||
ORDERSTATUSCLOUDSTOREORDERED, ORDERSTATUSCLOUDSTORESTARTPRODUCTION, ORDERSTATUSCLOUDSTOREOMPLETEPRODUCTION, ORDERSTATUSCLOUDSTOREARRIVEDWAREHOUSE,
|
||||
ORDER_STATUS_UNPAIDDEPOSIT, ORDER_STATUS_COMPLETE,
|
||||
ORDER_STATUS_CLOUDSTORE_ORDERED, ORDER_STATUS_CLOUDSTORE_STARTPRODUCTION, ORDER_STATUS_CLOUDSTORE_COMPLETEPRODUCTION, ORDER_STATUS_CLOUDSTORE_ARRIVEDWAREHOUSE,
|
||||
}
|
||||
}
|
||||
|
||||
8
env.yaml
8
env.yaml
@ -5,3 +5,11 @@ username: ...
|
||||
password: ...
|
||||
namespace: fs_server_api_dev
|
||||
group: FS-SERVER-API
|
||||
|
||||
proxyserver:
|
||||
key: /opt/server.dev.fusenpack.com.key
|
||||
pem: /opt/server.dev.fusenpack.com.pem
|
||||
|
||||
serverbackend:
|
||||
key: /opt/serverbackend.dev.fusenpack.com.key
|
||||
pem: /opt/serverbackend.dev.fusenpack.com.pem
|
||||
2
go.mod
2
go.mod
@ -18,7 +18,7 @@ require (
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/streadway/amqp v1.1.0
|
||||
github.com/stripe/stripe-go/v74 v74.26.0
|
||||
github.com/stripe/stripe-go/v75 v75.7.0
|
||||
github.com/zeromicro/go-zero v1.5.4
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
|
||||
golang.org/x/oauth2 v0.10.0
|
||||
|
||||
4
go.sum
4
go.sum
@ -548,8 +548,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stripe/stripe-go/v74 v74.26.0 h1:enbhLtjKGWvJKcGM0f2CazqFSXzpHXcQ42nG2PNsWK0=
|
||||
github.com/stripe/stripe-go/v74 v74.26.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw=
|
||||
github.com/stripe/stripe-go/v75 v75.7.0 h1:Zk7trlj0kClZOwnpjGz7FgVQRBI0Koi28/eaNATgAs0=
|
||||
github.com/stripe/stripe-go/v75 v75.7.0/go.mod h1:wT44gah+eCY8Z0aSpY/vQlYYbicU9uUAbAqdaUxxDqE=
|
||||
github.com/tidwall/gjson v1.12.0 h1:61wEp/qfvFnqKH/WCI3M8HuRut+mHT6Mr82QrFmM2SY=
|
||||
github.com/tidwall/gjson v1.12.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
|
||||
@ -2,24 +2,28 @@ package gmodel
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// fs_address 用户地址表
|
||||
type FsAddress struct {
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
|
||||
UserId *int64 `gorm:"index;default:0;" json:"user_id"` // 用户ID
|
||||
Name *string `gorm:"default:'';" json:"name"` // 地址名称
|
||||
FirstName *string `gorm:"default:'';" json:"first_name"` // FirstName
|
||||
LastName *string `gorm:"default:'';" json:"last_name"` // LastName
|
||||
Mobile *string `gorm:"default:'';" json:"mobile"` // 手机号码
|
||||
Street *string `gorm:"default:'';" json:"street"` // 街道
|
||||
Suite *string `gorm:"default:'';" json:"suite"` // 房号
|
||||
City *string `gorm:"default:'';" json:"city"` // 城市
|
||||
State *string `gorm:"default:'';" json:"state"` //
|
||||
Country *string `gorm:"default:'';" json:"country"` //
|
||||
ZipCode *string `gorm:"default:'';" json:"zip_code"` //
|
||||
Status *int64 `gorm:"default:0;" json:"status"` // 1正常 0异常
|
||||
IsDefault *int64 `gorm:"index;default:0;" json:"is_default"` // 1默认地址,0非默认地址
|
||||
AddressId int64 `gorm:"primary_key;default:0;auto_increment;" json:"address_id"` //
|
||||
UserId *int64 `gorm:"index;default:0;" json:"user_id"` // 用户ID
|
||||
AddressName *string `gorm:"default:'';" json:"address_name"` //
|
||||
FirstName *string `gorm:"default:'';" json:"first_name"` // FirstName
|
||||
LastName *string `gorm:"default:'';" json:"last_name"` // LastName
|
||||
Mobile *string `gorm:"default:'';" json:"mobile"` // 手机号码
|
||||
Street *string `gorm:"default:'';" json:"street"` // 街道
|
||||
Suite *string `gorm:"default:'';" json:"suite"` // 房号
|
||||
City *string `gorm:"default:'';" json:"city"` // 城市
|
||||
State *string `gorm:"default:'';" json:"state"` //
|
||||
Country *string `gorm:"default:'';" json:"country"` //
|
||||
ZipCode *string `gorm:"default:'';" json:"zip_code"` //
|
||||
Status *int64 `gorm:"default:0;" json:"status"` // 1正常 0异常
|
||||
IsDefault *int64 `gorm:"index;default:0;" json:"is_default"` // 1默认地址,0非默认地址
|
||||
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` // 创建时间
|
||||
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` // 更新时间
|
||||
Ltime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"ltime"` // 上次被使用的时间
|
||||
}
|
||||
type FsAddressModel struct {
|
||||
db *gorm.DB
|
||||
|
||||
@ -2,17 +2,19 @@ package gmodel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (a *FsAddressModel) GetOne(ctx context.Context, id int64, userId int64) (resp *FsAddress, err error) {
|
||||
err = a.db.WithContext(ctx).Model(&FsAddress{}).Where("`id` = ? and `user_id` = ? and `status` = ? ", id, userId, 1).Take(&resp).Error
|
||||
func (a *FsAddressModel) GetOne(ctx context.Context, addressId int64, userId int64) (resp *FsAddress, err error) {
|
||||
err = a.db.WithContext(ctx).Model(&FsAddress{}).Where("`address_id` = ? and `user_id` = ? and `status` = ? ", addressId, userId, 1).Take(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (a *FsAddressModel) GetUserAllAddress(ctx context.Context, userId int64) (resp []FsAddress, err error) {
|
||||
err = a.db.WithContext(ctx).Model(&FsAddress{}).Where("`user_id` = ? and `status` = ?", userId, 1).Order("`id` DESC").Find(&resp).Error
|
||||
err = a.db.WithContext(ctx).Model(&FsAddress{}).Where("`user_id` = ? and `status` = ?", userId, 1).Order("`ltime` DESC").Find(&resp).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -21,25 +23,42 @@ func (a *FsAddressModel) GetUserAllAddress(ctx context.Context, userId int64) (r
|
||||
|
||||
func (a *FsAddressModel) CreateOne(ctx context.Context, address *FsAddress) (result *FsAddress, err error) {
|
||||
|
||||
err = a.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
// now := time.Now().UTC().Unix()
|
||||
err = a.db.WithContext(ctx).Model(&FsAddress{}).Transaction(func(tx *gorm.DB) error {
|
||||
now := time.Now().UTC()
|
||||
result = &FsAddress{
|
||||
UserId: address.UserId,
|
||||
Name: address.Name,
|
||||
FirstName: address.FirstName,
|
||||
LastName: address.LastName,
|
||||
Mobile: address.Mobile,
|
||||
Street: address.Street,
|
||||
Suite: address.Suite,
|
||||
City: address.City,
|
||||
State: address.State,
|
||||
Country: address.Country,
|
||||
ZipCode: address.ZipCode,
|
||||
Status: address.Status,
|
||||
IsDefault: address.IsDefault,
|
||||
UserId: address.UserId,
|
||||
AddressName: address.AddressName,
|
||||
FirstName: address.FirstName,
|
||||
LastName: address.LastName,
|
||||
Mobile: address.Mobile,
|
||||
Street: address.Street,
|
||||
Suite: address.Suite,
|
||||
City: address.City,
|
||||
State: address.State,
|
||||
Country: address.Country,
|
||||
ZipCode: address.ZipCode,
|
||||
Status: address.Status,
|
||||
IsDefault: address.IsDefault,
|
||||
Ctime: &now,
|
||||
Utime: &now,
|
||||
Ltime: &now,
|
||||
}
|
||||
|
||||
return tx.Create(result).Error
|
||||
// lastOne := &FsAddress{}
|
||||
// err = tx.Where("user_id = ?", lastOne.UserId).Order("ltime ASC").Take(&lastOne).Error
|
||||
// if err == gorm.ErrRecordNotFound {
|
||||
// result.Ltime = &now
|
||||
// return tx.Model(&FsAddress{}).Create(result).Error
|
||||
// }
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 根据lastOne处理时间
|
||||
|
||||
// ltime := (*lastOne.Ltime).Add(-time.Second)
|
||||
// result.Ltime = <ime
|
||||
return tx.Model(&FsAddress{}).Create(result).Error
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
@ -49,15 +68,47 @@ func (a *FsAddressModel) CreateOne(ctx context.Context, address *FsAddress) (res
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *FsAddressModel) UpdateAddAddress(ctx context.Context, address *FsAddress) (err error) {
|
||||
err = a.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if *address.IsDefault > 0 {
|
||||
err = tx.Model(&FsAddress{}).Where("user_id = ? and is_default = 1 ", address.UserId).Update("is_default", 0).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (a *FsAddressModel) UpdateAddress(ctx context.Context, address *FsAddress) (err error) {
|
||||
err = a.db.WithContext(ctx).Model(&FsAddress{}).Transaction(func(tx *gorm.DB) error {
|
||||
err = tx.
|
||||
Where("user_id = ? and address_id = ? and status = 1 ", address.UserId, address.AddressId).
|
||||
Updates(address).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&FsAddress{}).Where("id = ? and user_id = ?", address.Id, address.UserId).Omit("id", "user_id").Updates(address).Error
|
||||
return err
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *FsAddressModel) SettingUserDefaultAddress(ctx context.Context, userId int64, addressId int64) (err error) {
|
||||
|
||||
err = a.db.WithContext(ctx).Model(&FsAddress{}).Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
err = tx.Model(&FsAddress{}).Where(" `user_id` = ? and `status` = ? and `address_id` = ? ", userId, 1, addressId).
|
||||
UpdateColumn("ltime", now.AddDate(250, 0, 0)).
|
||||
UpdateColumn("utime", now).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Where(" `user_id` = ? and `status` = ? and `address_id` != ? and `ltime` > ? ", userId, 1, addressId, now.AddDate(10, 0, 0)).
|
||||
UpdateColumn("ltime", now).Error
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a *FsAddressModel) DeleteOne(ctx context.Context, addressId int64, userId int64) (err error) {
|
||||
err = a.db.WithContext(ctx).Model(&FsAddress{}).
|
||||
Where("`address_id` = ? and `user_id` = ? and `status` = ? ", addressId, userId, 1).
|
||||
UpdateColumn("status", 0).Error
|
||||
return err
|
||||
}
|
||||
|
||||
@ -2,17 +2,18 @@ package gmodel
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// fs_change_code 忘记密码code表
|
||||
type FsChangeCode struct {
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // id
|
||||
Email *string `gorm:"default:'';" json:"email"` //
|
||||
Code *string `gorm:"default:'';" json:"code"` //
|
||||
CreatedAt *int64 `gorm:"default:0;" json:"created_at"` // 创建时间
|
||||
IsUse *int64 `gorm:"default:0;" json:"is_use"` // 是否使用 1已使用 0未使用
|
||||
Metadata *[]byte `gorm:"default:'';" json:"metadata"` //
|
||||
Module *string `gorm:"default:'logo';" json:"module"` //
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // id
|
||||
Email *string `gorm:"default:'';" json:"email"` //
|
||||
Code *string `gorm:"default:'';" json:"code"` //
|
||||
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
|
||||
IsUse *int64 `gorm:"default:0;" json:"is_use"` // 是否使用 1已使用 0未使用
|
||||
Metadata *[]byte `gorm:"default:'';" json:"metadata"` //
|
||||
Module *string `gorm:"default:'logo';" json:"module"` //
|
||||
}
|
||||
type FsChangeCodeModel struct {
|
||||
db *gorm.DB
|
||||
|
||||
@ -2,20 +2,17 @@ package gmodel
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// fs_guest 游客表
|
||||
type FsGuest struct {
|
||||
GuestId int64 `gorm:"primary_key;default:0;auto_increment;" json:"guest_id"` // ID
|
||||
AuthKey *string `gorm:"default:'';" json:"auth_key"` // jwt token
|
||||
Status *int64 `gorm:"index;default:1;" json:"status"` // 1正常 0不正常
|
||||
IsDel *int64 `gorm:"index;default:0;" json:"is_del"` // 是否删除 1删除
|
||||
CreatedAt *int64 `gorm:"index;default:0;" json:"created_at"` // 添加时间
|
||||
UpdatedAt *int64 `gorm:"default:0;" json:"updated_at"` // 更新时间
|
||||
IsOpenRender *int64 `gorm:"default:0;" json:"is_open_render"` // 是否打开个性化渲染(1:开启,0:关闭)
|
||||
IsThousandFace *int64 `gorm:"default:0;" json:"is_thousand_face"` // 是否已经存在千人千面(1:存在,0:不存在)
|
||||
IsLowRendering *int64 `gorm:"default:0;" json:"is_low_rendering"` // 是否开启低渲染模型渲染
|
||||
IsRemoveBg *int64 `gorm:"default:1;" json:"is_remove_bg"` // 用户上传logo是否去除背景
|
||||
GuestId int64 `gorm:"primary_key;default:0;auto_increment;" json:"guest_id"` // ID
|
||||
AuthKey *string `gorm:"default:'';" json:"auth_key"` // jwt token
|
||||
Status *int64 `gorm:"index;default:1;" json:"status"` // 1正常 0不正常
|
||||
IsDel *int64 `gorm:"index;default:0;" json:"is_del"` // 是否删除 1删除
|
||||
Ctime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"ctime"` //
|
||||
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
|
||||
}
|
||||
type FsGuestModel struct {
|
||||
db *gorm.DB
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
func (m *FsGuestModel) GenerateGuestID(ctx context.Context, AccessSecret uint64) (authKey string, err error) {
|
||||
|
||||
err = m.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
now := time.Now().UTC().Unix()
|
||||
now := time.Now().UTC()
|
||||
var record = &FsGuest{}
|
||||
tx.Create(record)
|
||||
|
||||
authKey, err = auth.GenerateJwtTokenUint64(AccessSecret, now, 31536000, 0, int64(record.GuestId))
|
||||
authKey, err = auth.GenerateJwtTokenUint64(AccessSecret, now.Unix(), 31536000, 0, int64(record.GuestId))
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
err = tx.Rollback().Error
|
||||
@ -26,7 +26,7 @@ func (m *FsGuestModel) GenerateGuestID(ctx context.Context, AccessSecret uint64)
|
||||
return err
|
||||
}
|
||||
record.AuthKey = &authKey
|
||||
record.CreatedAt = &now
|
||||
record.Ctime = &now
|
||||
err = tx.Updates(record).Error
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
|
||||
@ -40,7 +40,7 @@ type PayInfo struct {
|
||||
Metadata map[string]interface{} `json:"metadata"` // 额外参数
|
||||
PayAmount AmountInfo `json:"pay_amount"` // 金额明细
|
||||
PayMethod string `json:"pay_method"` // 交易方式
|
||||
PayTime **time.Time `json:"pay_time"` // 支付时间
|
||||
PayTime *time.Time `json:"pay_time"` // 支付时间
|
||||
Status PayStatus `json:"status"` // 当前状态
|
||||
StatusLink []PayStatus `json:"status_link"` // 状态链路
|
||||
TradeNo string `json:"trade_no"` // 支付交易号
|
||||
@ -95,23 +95,26 @@ type OrderStatus struct {
|
||||
|
||||
// 订单商品
|
||||
type OrderProduct struct {
|
||||
TotalPrice AmountInfo `json:"amount"` // 商品总价
|
||||
TotalPrice AmountInfo `json:"total_price"` // 商品总价
|
||||
ExpectedDeliveryTime *time.Time `json:"expected_delivery_time"` // 预计到货时间
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"` // 购买数量
|
||||
PurchaseQuantity PurchaseQuantity `json:"purchase_quantity"` // 购买数量
|
||||
ProductID int64 `json:"product_id"` // 商品ID
|
||||
ProductName string `json:"product_name"` // 商品名称
|
||||
ItemPrice AmountInfo `json:"product_price"` // 商品单价
|
||||
ItemPrice AmountInfo `json:"item_price"` // 商品单价
|
||||
ProductSnapshot interface{} `json:"product_snapshot"` // 商品快照
|
||||
ShoppingCartSnapshot *FsShoppingCart `json:"shopping_cart_snapshot"` // 购物车快照
|
||||
ShoppingCartSnapshot *FsShoppingCartData `json:"shopping_cart_snapshot"` // 购物车快照
|
||||
ProductCover string `json:"product_cover"` // 商品封面
|
||||
ProductCoverMetadata map[string]interface{} `json:"product_cover_metadata"` // 商品封面
|
||||
ProductSn string `json:"product_sn"` // 商品编码
|
||||
DiyInformation *UserDiyInformation `json:"diy_information"`
|
||||
SizeInfo *OrderProductSizeInfo `json:"size_info"`
|
||||
FittingInfo *OrderProductFittingInfo `json:"fitting_info"`
|
||||
StepNum []int `json:"step_num"` // 阶梯数量
|
||||
IsHighlyCustomized int64 `json:"is_highly_customized"`
|
||||
}
|
||||
type PurchaseQuantity struct {
|
||||
Current interface{} `json:"current"`
|
||||
Initiate interface{} `json:"initiate"`
|
||||
}
|
||||
|
||||
type OrderProductSizeInfo struct {
|
||||
SizeID int64 `json:"size_id"`
|
||||
|
||||
@ -36,6 +36,7 @@ type FsProduct struct {
|
||||
RecommendProductSort *string `gorm:"default:'';" json:"recommend_product_sort"` //
|
||||
SceneIds *string `gorm:"default:'';" json:"scene_ids"` //
|
||||
IsCustomization *int64 `gorm:"default:0;" json:"is_customization"` // 是否可定制
|
||||
Unit *string `gorm:"default:'';" json:"unit"` //
|
||||
}
|
||||
type FsProductModel struct {
|
||||
db *gorm.DB
|
||||
|
||||
@ -2,30 +2,34 @@ package gmodel
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// fs_product_model3d 产品模型表
|
||||
type FsProductModel3d struct {
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
|
||||
ProductId *int64 `gorm:"index;default:0;" json:"product_id"` // 产品ID
|
||||
Tag *int64 `gorm:"default:1;" json:"tag"` // 类别(1:模型,2:配件,3:场景)
|
||||
Title *string `gorm:"default:'';" json:"title"` // 标题
|
||||
Name *string `gorm:"default:'';" json:"name"` // 详情页展示名称
|
||||
ModelInfo *string `gorm:"default:'';" json:"model_info"` // 模型详情
|
||||
MaterialId *int64 `gorm:"default:0;" json:"material_id"` // 材质ID
|
||||
SizeId *int64 `gorm:"default:0;" json:"size_id"` // 尺寸ID
|
||||
Sort *int64 `gorm:"default:0;" json:"sort"` // 排序
|
||||
Light *int64 `gorm:"default:0;" json:"light"` // 灯光组
|
||||
LightList *string `gorm:"default:'';" json:"light_list"` // 灯光备选项
|
||||
PartId *int64 `gorm:"default:0;" json:"part_id"` // 配件选项id(配件就是模型的id)
|
||||
PartList *string `gorm:"default:'';" json:"part_list"` //
|
||||
Status *int64 `gorm:"default:0;" json:"status"` // 状态位 显示 删除
|
||||
Ctime *int64 `gorm:"default:0;" json:"ctime"` // 添加时间
|
||||
OptionTemplate *int64 `gorm:"default:0;" json:"option_template"` // 配件绑定的公共模板
|
||||
Price *int64 `gorm:"default:0;" json:"price"` // 仅配件用,配件的价格, 单位:美分
|
||||
Sku *string `gorm:"default:'';" json:"sku"` // sku
|
||||
IsHot *int64 `gorm:"default:0;" json:"is_hot"` // 是否热门
|
||||
IsCloudRender *int64 `gorm:"default:0;" json:"is_cloud_render"` // 是否设置为云渲染模型
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
|
||||
ProductId *int64 `gorm:"index;default:0;" json:"product_id"` // 产品ID
|
||||
Tag *int64 `gorm:"default:1;" json:"tag"` // 类别(1:模型,2:配件,3:场景)
|
||||
Title *string `gorm:"default:'';" json:"title"` // 标题
|
||||
Name *string `gorm:"default:'';" json:"name"` // 详情页展示名称
|
||||
ModelInfo *string `gorm:"default:'';" json:"model_info"` // 模型详情
|
||||
MaterialId *int64 `gorm:"default:0;" json:"material_id"` // 材质ID
|
||||
SizeId *int64 `gorm:"default:0;" json:"size_id"` // 尺寸ID
|
||||
Sort *int64 `gorm:"default:0;" json:"sort"` // 排序
|
||||
Light *int64 `gorm:"default:0;" json:"light"` // 灯光组
|
||||
LightList *string `gorm:"default:'';" json:"light_list"` // 灯光备选项
|
||||
PartId *int64 `gorm:"default:0;" json:"part_id"` // 配件选项id(配件就是模型的id)
|
||||
PartList *string `gorm:"default:'';" json:"part_list"` //
|
||||
Status *int64 `gorm:"default:0;" json:"status"` // 状态位 显示 删除
|
||||
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
|
||||
OptionTemplate *int64 `gorm:"default:0;" json:"option_template"` // 配件绑定的公共模板
|
||||
Price *int64 `gorm:"default:0;" json:"price"` //
|
||||
Sku *string `gorm:"default:'';" json:"sku"` // sku
|
||||
IsHot *int64 `gorm:"default:0;" json:"is_hot"` // 是否热门
|
||||
IsCloudRender *int64 `gorm:"default:0;" json:"is_cloud_render"` // 是否设置为云渲染模型
|
||||
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
|
||||
StepPrice *[]byte `gorm:"default:'';" json:"step_price"` //
|
||||
PackedUnit *int64 `gorm:"default:0;" json:"packed_unit"` // 被打包的数量单位
|
||||
}
|
||||
type FsProductModel3dModel struct {
|
||||
db *gorm.DB
|
||||
|
||||
@ -4,8 +4,19 @@ import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// 阶梯价结构
|
||||
type StepPriceJsonStruct struct {
|
||||
PriceRange []struct {
|
||||
Label string `json:"label"`
|
||||
Price int64 `json:"price"`
|
||||
EndQuantity int64 `json:"end_quantity"`
|
||||
StartQuantity int64 `json:"start_quantity"`
|
||||
} `json:"price_range"`
|
||||
MinBuyUnitsNum int64 `json:"min_buy_units_num"`
|
||||
}
|
||||
|
||||
func (d *FsProductModel3dModel) FindOne(ctx context.Context, id int64, fields ...string) (resp *FsProductModel3d, err error) {
|
||||
db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`id` = ? ", id)
|
||||
db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`id` = ? and `status` =? ", id, 1)
|
||||
if len(fields) > 0 {
|
||||
db = db.Select(fields[0])
|
||||
}
|
||||
@ -30,7 +41,7 @@ func (d *FsProductModel3dModel) GetAllByIdsWithoutStatus(ctx context.Context, id
|
||||
if len(ids) == 0 {
|
||||
return
|
||||
}
|
||||
db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`id` in (?)", ids)
|
||||
db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`id` in (?) and `status` = ?", ids, 1)
|
||||
if len(fields) > 0 {
|
||||
db = db.Select(fields[0])
|
||||
}
|
||||
@ -69,13 +80,13 @@ func (d *FsProductModel3dModel) Get3dModelsByParam(ctx context.Context, req Get3
|
||||
return resp, err
|
||||
}
|
||||
func (d *FsProductModel3dModel) Update(ctx context.Context, id int64, data *FsProductModel3d) error {
|
||||
return d.db.WithContext(ctx).Where("`id` = ? ", id).Updates(&data).Error
|
||||
return d.db.WithContext(ctx).Where("`id` = ? and `status` =? ", id, 1).Updates(&data).Error
|
||||
}
|
||||
func (d *FsProductModel3dModel) GetAllBySizeIdsTag(ctx context.Context, sizeIds []int64, tag int64, fields ...string) (resp []FsProductModel3d, err error) {
|
||||
if len(sizeIds) == 0 {
|
||||
return
|
||||
}
|
||||
db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`size_id` in (?) and `tag` = ?", sizeIds, tag)
|
||||
db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`size_id` in (?) and `tag` = ? and `status` = ?", sizeIds, tag, 1)
|
||||
if len(fields) != 0 {
|
||||
db = db.Select(fields[0])
|
||||
}
|
||||
@ -83,7 +94,7 @@ func (d *FsProductModel3dModel) GetAllBySizeIdsTag(ctx context.Context, sizeIds
|
||||
return resp, err
|
||||
}
|
||||
func (d *FsProductModel3dModel) GetAll(ctx context.Context) (resp []FsProductModel3d, err error) {
|
||||
err = d.db.WithContext(ctx).Model(&FsProductModel3d{}).Find(&resp).Error
|
||||
err = d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`status` = ?", 1).Find(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@ -96,7 +107,7 @@ func (d *FsProductModel3dModel) GetGroupPartListByProductIds(ctx context.Context
|
||||
if len(productIds) == 0 {
|
||||
return
|
||||
}
|
||||
err = d.db.WithContext(ctx).Model(&FsProductModel3d{}).
|
||||
err = d.db.WithContext(ctx).Model(&FsProductModel3d{}).Where("`product_id` in(?) and `status` =? ", productIds, 1).
|
||||
Select("product_id,group_concat(part_list) as part_list").
|
||||
Group("product_id").Find(&resp).Error
|
||||
return resp, err
|
||||
@ -120,3 +131,24 @@ func (d *FsProductModel3dModel) GetOneBySizeIdTag(ctx context.Context, sizeId in
|
||||
err = db.Take(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (d *FsProductModel3dModel) GetAllByProductIdTag(ctx context.Context, productId int64, tag int64, fields ...string) (resp []FsProductModel3d, err error) {
|
||||
db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).
|
||||
Where("`product_id` = ? and `tag` = ? and `status` = ?", productId, tag, 1).
|
||||
Order("sort DESC")
|
||||
if len(fields) != 0 {
|
||||
db = db.Select(fields[0])
|
||||
}
|
||||
err = db.Find(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
func (d *FsProductModel3dModel) FindOneByProductIdSizeIdTag(ctx context.Context, productId, sizeId, tag int64, fields ...string) (resp *FsProductModel3d, err error) {
|
||||
db := d.db.WithContext(ctx).Model(&FsProductModel3d{}).
|
||||
Where("`product_id` = ? and `size_id` = ? and `tag` = ? and `status` = ?", productId, sizeId, tag, 1).
|
||||
Order("sort DESC")
|
||||
if len(fields) != 0 {
|
||||
db = db.Select(fields[0])
|
||||
}
|
||||
err = db.Take(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package gmodel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (m *FsShoppingCartModel) TableName() string {
|
||||
@ -11,10 +12,26 @@ func (m *FsShoppingCartModel) TableName() string {
|
||||
// 关联查询
|
||||
type RelaFsShoppingCart struct {
|
||||
FsShoppingCart
|
||||
ShoppingCartProduct *RelaFsProduct `json:"shopping_cart_product" gorm:"foreignkey:product_id;references:id"`
|
||||
ShoppingCartProductPriceList []*FsProductPrice `json:"shopping_cart_product_price_list" gorm:"foreignkey:product_id;references:product_id"`
|
||||
ShoppingCartProductModel3dList []*FsProductModel3d `json:"shopping_cart_product_model3d_list" gorm:"foreignkey:product_id;references:product_id"`
|
||||
ShoppingCartProductModel3dFitting *FsProductModel3d `json:"shopping_cart_product_model3d_list_fitting" gorm:"foreignkey:fitting_id;references:id"`
|
||||
ShoppingCartProduct *RelaFsProduct `json:"shopping_cart_product" gorm:"foreignkey:product_id;references:id"`
|
||||
ShoppingCartProductModel3d *FsProductModel3d `json:"shopping_cart_product_model3d_list" gorm:"foreignkey:model_id;references:id"`
|
||||
ShoppingCartProductModel3dFitting *FsProductModel3d `json:"shopping_cart_product_model3d_list_fitting" gorm:"foreignkey:fitting_id;references:id"`
|
||||
}
|
||||
type FsShoppingCartData struct {
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // id
|
||||
UserId *int64 `gorm:"default:0;" json:"user_id"` // 用户id
|
||||
ProductId *int64 `gorm:"default:0;" json:"product_id"` // 产品id
|
||||
TemplateId *int64 `gorm:"default:0;" json:"template_id"` // 模板id
|
||||
ModelId *int64 `gorm:"default:0;" json:"model_id"` // 模型id
|
||||
SizeId *int64 `gorm:"default:0;" json:"size_id"` // 尺寸id
|
||||
LightId *int64 `gorm:"default:0;" json:"light_id"` // 灯光id
|
||||
FittingId *int64 `gorm:"default:0;" json:"fitting_id"` // 配件id
|
||||
PurchaseQuantity *int64 `gorm:"default:0;" json:"purchase_quantity"` // 购买数量
|
||||
Snapshot *map[string]interface{} `gorm:"default:'';" json:"snapshot"` //
|
||||
SnapshotData *string `gorm:"default:'';" json:"snapshot_data"` //
|
||||
IsSelected *int64 `gorm:"default:0;" json:"is_selected"` // 是否被选中 0非 1是
|
||||
IsHighlyCustomized *int64 `gorm:"default:0;" json:"is_highly_customized"` // 是否高度定制 0非 1是(针对客人高度定制只能后台增加如购物车)
|
||||
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
|
||||
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
|
||||
}
|
||||
|
||||
// 快照json数据结构
|
||||
|
||||
@ -2,35 +2,28 @@ package gmodel
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// fs_user 用户表
|
||||
type FsUser struct {
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // ID
|
||||
FaceId *string `gorm:"default:'0';" json:"face_id"` // facebook的userid
|
||||
GoogleId *string `gorm:"default:'0';" json:"google_id"` // google的sub
|
||||
FirstName *string `gorm:"default:'';" json:"first_name"` // FirstName
|
||||
LastName *string `gorm:"default:'';" json:"last_name"` // LastName
|
||||
Username *string `gorm:"index;default:'';" json:"username"` //
|
||||
Company *string `gorm:"default:'';" json:"company"` // 公司名称
|
||||
Mobile *string `gorm:"default:'';" json:"mobile"` // 手机号码
|
||||
PasswordHash *string `gorm:"default:'';" json:"password_hash"` //
|
||||
VerificationToken *string `gorm:"default:'';" json:"verification_token"` //
|
||||
PasswordResetToken *string `gorm:"default:'';" json:"password_reset_token"` //
|
||||
Email *string `gorm:"unique_key;default:'';" json:"email"` // 邮箱
|
||||
Type *int64 `gorm:"default:0;" json:"type"` // 1普通餐厅 2连锁餐厅
|
||||
Status *int64 `gorm:"default:1;" json:"status"` // 1正常 0不正常
|
||||
IsDel *int64 `gorm:"default:0;" json:"is_del"` // 是否删除 1删除
|
||||
CreatedAt *int64 `gorm:"default:0;" json:"created_at"` // 添加时间
|
||||
UpdatedAt *int64 `gorm:"default:0;" json:"updated_at"` // 更新时间
|
||||
IsOrderStatusEmail *int64 `gorm:"default:0;" json:"is_order_status_email"` // 订单状态改变时是否接收邮件
|
||||
IsEmailAdvertisement *int64 `gorm:"default:0;" json:"is_email_advertisement"` // 是否接收邮件广告
|
||||
IsOrderStatusPhone *int64 `gorm:"default:0;" json:"is_order_status_phone"` // 订单状态改变是是否接收电话
|
||||
IsPhoneAdvertisement *int64 `gorm:"default:0;" json:"is_phone_advertisement"` // 是否接收短信广告
|
||||
IsOpenRender *int64 `gorm:"default:0;" json:"is_open_render"` // 是否打开个性化渲染(1:开启,0:关闭)
|
||||
IsThousandFace *int64 `gorm:"default:0;" json:"is_thousand_face"` // 是否已经存在千人千面(1:存在,0:不存在)
|
||||
IsLowRendering *int64 `gorm:"default:0;" json:"is_low_rendering"` //
|
||||
IsRemoveBg *int64 `gorm:"default:1;" json:"is_remove_bg"` // 用户上传logo是否去除背景
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // ID
|
||||
FaceId *string `gorm:"default:'0';" json:"face_id"` // facebook的userid
|
||||
GoogleId *string `gorm:"default:'0';" json:"google_id"` // google的sub
|
||||
FirstName *string `gorm:"default:'';" json:"first_name"` // FirstName
|
||||
LastName *string `gorm:"default:'';" json:"last_name"` // LastName
|
||||
Username *string `gorm:"index;default:'';" json:"username"` //
|
||||
Company *string `gorm:"default:'';" json:"company"` // 公司名称
|
||||
Mobile *string `gorm:"default:'';" json:"mobile"` //
|
||||
PasswordHash *string `gorm:"default:'';" json:"password_hash"` //
|
||||
VerificationToken *string `gorm:"default:'';" json:"verification_token"` //
|
||||
PasswordResetToken *string `gorm:"default:'';" json:"password_reset_token"` //
|
||||
Email *string `gorm:"unique_key;default:'';" json:"email"` // 邮箱
|
||||
Type *int64 `gorm:"default:0;" json:"type"` // 1普通餐厅 2连锁餐厅
|
||||
Status *int64 `gorm:"default:1;" json:"status"` // 1正常 0不正常
|
||||
IsDel *int64 `gorm:"default:0;" json:"is_del"` // 是否删除 1删除
|
||||
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
|
||||
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
|
||||
}
|
||||
type FsUserModel struct {
|
||||
db *gorm.DB
|
||||
|
||||
@ -4,6 +4,9 @@ package gmodel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"fusenapi/utils/fssql"
|
||||
"fusenapi/utils/handlers"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@ -42,3 +45,39 @@ func (p *FsUserInfoModel) CreateOrUpdate(gormDB *gorm.DB, req *FsUserInfo) (resp
|
||||
}
|
||||
return req, err
|
||||
}
|
||||
|
||||
func (m *FsUserInfoModel) MergeMetadata(userId int64, meta any) error {
|
||||
return fssql.MetadataModulePATCH(m.db, "profile", FsUserInfo{}, map[string]any{
|
||||
"base": meta,
|
||||
}, "user_id = ?", userId)
|
||||
}
|
||||
|
||||
func (m *FsUserInfoModel) GetProfile(ctx context.Context, pkey string, userId int64) (map[string]any, error) {
|
||||
|
||||
var baseinfo map[string]any
|
||||
tname := fssql.GetGormTableName(m.db, FsUserInfo{})
|
||||
|
||||
if pkey == "." {
|
||||
pkey = ""
|
||||
} else {
|
||||
pkey = "." + pkey
|
||||
}
|
||||
|
||||
rawsql := fmt.Sprintf("select JSON_EXTRACT(metadata,'$%s') as query from %s where user_id = ? and module = 'profile' order by ctime DESC limit 1", pkey, tname)
|
||||
err := m.db.Raw(rawsql, userId).Take(&baseinfo).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v, ok := baseinfo["query"].(string)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var info map[string]any
|
||||
err = json.Unmarshal([]byte(v), &info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
@ -4,14 +4,11 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/fssql"
|
||||
"time"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@ -66,28 +63,26 @@ func InheritGuestIdResource(tx *gorm.DB, userId, guestId int64, afterDo func(txR
|
||||
if guestId != 0 {
|
||||
// 继承guest_id的资源表
|
||||
err = txRes.
|
||||
Where("guest_id = ?", guestId).
|
||||
Where("guest_id = ? and source != 'temp' and version != '0.0.0'", guestId).
|
||||
UpdateColumn("user_id", userId).Error
|
||||
|
||||
if err != nil && err != gorm.ErrRecordNotFound {
|
||||
logx.Info(err, "找到user_id1 afterDo")
|
||||
return err
|
||||
}
|
||||
|
||||
err = txUserMaterial.
|
||||
Where("guest_id = ?", guestId).
|
||||
Where("guest_id = ? and module != 'clear' and module != 'temp'", guestId).
|
||||
UpdateColumn("user_id", userId).Error
|
||||
|
||||
if err != nil && err != gorm.ErrRecordNotFound {
|
||||
logx.Info(err, "找到user_id1 afterDo")
|
||||
return err
|
||||
}
|
||||
|
||||
err = txUserInfo.
|
||||
Where("guest_id = ?", guestId).
|
||||
Where("guest_id = ? and module != 'clear' and module != 'temp'", guestId).
|
||||
UpdateColumn("user_id", userId).Error
|
||||
|
||||
if err != nil && err != gorm.ErrRecordNotFound {
|
||||
logx.Info(err, "找到user_id1 afterDo")
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -120,9 +115,9 @@ func (u *FsUserModel) RegisterByGoogleOAuth(ctx context.Context, token *auth.Reg
|
||||
if err != nil {
|
||||
// 没有找到在数据库就创建注册
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
createAt := time.Now().UTC().Unix()
|
||||
createAt := time.Now().UTC()
|
||||
user.Email = &token.Email
|
||||
user.CreatedAt = &createAt
|
||||
user.Ctime = &createAt
|
||||
user.GoogleId = &googleId
|
||||
user.PasswordHash = &token.Password
|
||||
user.FirstName = &firstName
|
||||
@ -150,21 +145,6 @@ func (u *FsUserModel) RegisterByGoogleOAuth(ctx context.Context, token *auth.Reg
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// SubscriptionStatus 订阅状态
|
||||
type SubscriptionStatus struct {
|
||||
SubEmail bool `json:"all_emails"`
|
||||
ItemMap *struct {
|
||||
} `json:"item_map"`
|
||||
}
|
||||
|
||||
// UserProfile 个人信息
|
||||
type UserProfile struct {
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Resetaurant string `json:"resetaurant"`
|
||||
SubStatus SubscriptionStatus `json:"sub_status"`
|
||||
}
|
||||
|
||||
// 自平台的注册流程
|
||||
func (u *FsUserModel) RegisterByFusen(ctx context.Context, token *auth.RegisterToken) (user *FsUser, err error) {
|
||||
|
||||
@ -174,44 +154,41 @@ func (u *FsUserModel) RegisterByFusen(ctx context.Context, token *auth.RegisterT
|
||||
var err error
|
||||
|
||||
err = tx.Model(&FsUser{}).Where("email = ?", token.Email).Take(user).Error
|
||||
log.Println("success", token.TraceId)
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
|
||||
FirstName := token.Extend["first_name"].(string)
|
||||
LastName := token.Extend["last_name"].(string)
|
||||
Resetaurant := token.Extend["resetaurant"].(string)
|
||||
|
||||
createAt := time.Now().UTC().Unix()
|
||||
|
||||
createAt := time.Now().UTC()
|
||||
user.Email = &token.Email
|
||||
user.CreatedAt = &createAt
|
||||
user.Ctime = &createAt
|
||||
user.PasswordHash = &token.Password
|
||||
user.FirstName = &FirstName
|
||||
user.LastName = &LastName
|
||||
|
||||
err = tx.Model(&FsUser{}).Create(user).Error
|
||||
if err != nil && err != gorm.ErrRecordNotFound {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("success", token.TraceId)
|
||||
|
||||
// 继承guest_id的资源表
|
||||
err = InheritGuestIdResource(tx, user.Id, token.GuestId, func(txResouce, txUserMaterial, txUserInfo *gorm.DB) error {
|
||||
log.Println("success", token.TraceId)
|
||||
userProfile := &UserProfile{
|
||||
userProfileBase := UserProfileBase{
|
||||
FirstName: FirstName,
|
||||
LastName: LastName,
|
||||
Resetaurant: Resetaurant,
|
||||
}
|
||||
|
||||
userProfile := &UserProfile{
|
||||
ProfileBase: userProfileBase,
|
||||
}
|
||||
|
||||
metadata, err := json.Marshal(userProfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// txUserInfo.Where("user_id = ?", user.Id).Row().Err()
|
||||
|
||||
now := time.Now().UTC()
|
||||
uinfo := &FsUserInfo{
|
||||
Module: FsString("profile"),
|
||||
@ -222,18 +199,18 @@ func (u *FsUserModel) RegisterByFusen(ctx context.Context, token *auth.RegisterT
|
||||
Utime: &now,
|
||||
}
|
||||
|
||||
err = txUserInfo.Where("module = 'profile' and user_id = ?", uinfo.UserId).Take(nil).Error
|
||||
// txUserInfo.Statement.Table
|
||||
log.Println(err, "找到user_id1")
|
||||
// logx.Error(metadata)
|
||||
|
||||
err = txUserInfo.Where("module = 'profile' and user_id = ?", *uinfo.UserId).Take(nil).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
err = txUserInfo.Create(uinfo).Error
|
||||
err = tx.Model(&FsUserInfo{}).Create(uinfo).Error
|
||||
// logx.Info(err, "*uinfo.UserId:", *uinfo.UserId, " ", uinfo.Id)
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Println("找到user_id2")
|
||||
err = fssql.MetadataModulePATCH(txUserInfo, "profile", FsUserInfo{}, metadata, "user_id = ?", *uinfo.UserId)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@ -35,3 +35,25 @@ func FsFloat(v float64) *float64 {
|
||||
func FsBool(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
// SubscriptionStatus 订阅状态
|
||||
type SubscriptionStatus struct {
|
||||
SubEmail bool `json:"all_emails"`
|
||||
ItemMap *struct {
|
||||
} `json:"item_map"`
|
||||
}
|
||||
|
||||
type UserProfile struct {
|
||||
ProfileBase UserProfileBase `json:"base"`
|
||||
SubStatus SubscriptionStatus `json:"sub_status"`
|
||||
}
|
||||
|
||||
// UserProfileBase 个人信息
|
||||
type UserProfileBase struct {
|
||||
FirstName string `json:"first_name"` // 首名
|
||||
LastName string `json:"last_name"` // 后名
|
||||
UserName string `json:"user_name"` // 用户名
|
||||
Mobile string `json:"mobile"` // 电话
|
||||
Resetaurant string `json:"resetaurant"` // 不知道干什么
|
||||
Company string `json:"company"` // 公司
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
_ "fusenapi/utils/auth"
|
||||
@ -97,14 +96,16 @@ func main() {
|
||||
indexHtmlPath := vueBuild + "/index.html"
|
||||
mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.URL.Path, "/api/") {
|
||||
err := r.ParseMultipartForm(100 << 20)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
}
|
||||
|
||||
r.ParseMultipartForm(100 << 20)
|
||||
// if err != nil {
|
||||
// logx.Error(err)
|
||||
// }
|
||||
|
||||
// 对/api开头的请求进行反向代理
|
||||
proxy := httputil.NewSingleHostReverseProxy(apiURL)
|
||||
proxy.ServeHTTP(w, r)
|
||||
|
||||
return
|
||||
|
||||
} else {
|
||||
@ -208,22 +209,22 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
target := url.URL{Scheme: "ws", Host: strings.Split(backend.HttpAddress, "//")[1], Path: r.URL.Path}
|
||||
|
||||
var transfer = func(src, dest *websocket.Conn) {
|
||||
defer src.Close()
|
||||
defer dest.Close()
|
||||
// TODO: 可以做错误处理
|
||||
for {
|
||||
mType, msg, err := src.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
break
|
||||
return
|
||||
}
|
||||
|
||||
err = dest.WriteMessage(mType, msg)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
break
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
src.Close()
|
||||
dest.Close()
|
||||
}
|
||||
|
||||
header := r.Header.Clone()
|
||||
@ -247,6 +248,7 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
}
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// defer conn.Close()
|
||||
@ -259,14 +261,14 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
// 解析目标URL,包含了查询参数
|
||||
targetURL, err := url.Parse(httpAddress + r.URL.String())
|
||||
if err != nil {
|
||||
http.Error(w, "Error parsing target URL", http.StatusInternalServerError)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建新的请求
|
||||
proxyReq, err := http.NewRequest(r.Method, targetURL.String(), r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, "Error creating proxy request", http.StatusInternalServerError)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -284,7 +286,7 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
// 发送请求
|
||||
resp, err := backend.Client.Do(proxyReq)
|
||||
if err != nil {
|
||||
http.Error(w, "Error sending proxy request", http.StatusInternalServerError)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
@ -300,7 +302,7 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
_, err = io.Copy(w, resp.Body)
|
||||
if err != nil {
|
||||
http.Error(w, "Error copying proxy response", http.StatusInternalServerError)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,64 +4,94 @@ single_server_name=$1
|
||||
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
find /tmp/go-build* -mmin +5 -exec rm -rf {} +
|
||||
find /tmp/go-link* -mmin +5 -exec rm -rf {} +
|
||||
|
||||
run_proxyserver() {
|
||||
# 定义目录和screen名称
|
||||
dir_path="./proxyserver"
|
||||
screen_name="proxyserver"
|
||||
|
||||
# 进入目录
|
||||
cd $dir_path
|
||||
# 检查是否存在screen session
|
||||
if screen -list | grep -q "$screen_name"; then
|
||||
# 结束存在的screen session
|
||||
screen -S $screen_name -X quit
|
||||
fi
|
||||
go build
|
||||
# 启动新的screen session并运行go程序
|
||||
echo "run $screen_name"
|
||||
screen -dmS $screen_name -L ./$screen_name
|
||||
}
|
||||
|
||||
# 定义一个函数来在每个服务器目录下运行 go run <server_name>.go
|
||||
run_server() {
|
||||
server_name=$1
|
||||
echo "Running $server_name"
|
||||
|
||||
|
||||
|
||||
|
||||
# 导航到相应的目录
|
||||
cd server/$server_name
|
||||
echo "build $server_name"
|
||||
go build
|
||||
|
||||
# 如果之前存在相同名字的 screen 会话,先将其终止
|
||||
# 首先尝试关闭已存在的screen会话
|
||||
existing_session=$(screen -ls | grep -w "$server_name")
|
||||
if [ -n "$existing_session" ]; then
|
||||
echo "Terminating existing screen session for $server_name"
|
||||
screen -S "$server_name" -X quit
|
||||
while [[ $(screen -ls | grep "\.$server_name\s") ]]; do
|
||||
sleep 0.1s # 等待0.1秒后再次检查
|
||||
echo "wait for $server_name"
|
||||
done
|
||||
fi
|
||||
# 导航到相应的目录
|
||||
cd server/$server_name
|
||||
go build
|
||||
|
||||
# 循环检查screen进程是否存在
|
||||
|
||||
[ -f .gitignore ] || echo $server_name > .gitignore
|
||||
# 使用 screen 运行 go run <server_name>.go
|
||||
|
||||
echo "Running $server_name"
|
||||
screen -dmS $server_name -L ./$server_name
|
||||
|
||||
# 返回到上一级目录
|
||||
cd - > /dev/null
|
||||
}
|
||||
|
||||
find /tmp/go-build* -mmin +5 -exec rm -rf {} +
|
||||
find /tmp/go-link* -mmin +5 -exec rm -rf {} +
|
||||
if [ "$single_server_name" = "proxyserver" ]; then
|
||||
# 重启proxyserver的逻辑
|
||||
run_proxyserver
|
||||
else
|
||||
|
||||
server_dirs=() # 初始化一个空数组
|
||||
server_dirs=() # 初始化一个空数组
|
||||
|
||||
if [ -n "$single_server_name" ]; then
|
||||
server_dirs=("$single_server_name")
|
||||
else
|
||||
for dir in server/*/ ; do # 遍历 "server/" 下的所有子目录
|
||||
dir=${dir%*/} # 删除末尾的 "/"
|
||||
dir=${dir##*/} # 删除开头的 "server/"
|
||||
server_dirs+=("$dir") # 添加到数组
|
||||
done
|
||||
if [ -n "$single_server_name" ]; then
|
||||
server_dirs=("$single_server_name")
|
||||
else
|
||||
for dir in server/*/ ; do # 遍历 "server/" 下的所有子目录
|
||||
dir=${dir%*/} # 删除末尾的 "/"
|
||||
dir=${dir##*/} # 删除开头的 "server/"
|
||||
server_dirs+=("$dir") # 添加到数组
|
||||
done
|
||||
fi
|
||||
|
||||
# 在每个服务器目录下运行相应的 go 程序
|
||||
for server_dir in "${server_dirs[@]}"; do
|
||||
run_server $server_dir
|
||||
done
|
||||
|
||||
if [ -n "$single_server_name" ]; then
|
||||
echo "no proxyserver restart"
|
||||
else
|
||||
run_proxyserver
|
||||
fi
|
||||
fi
|
||||
|
||||
# 在每个服务器目录下运行相应的 go 程序
|
||||
for server_dir in "${server_dirs[@]}"; do
|
||||
run_server $server_dir
|
||||
done
|
||||
|
||||
|
||||
# 定义目录和screen名称
|
||||
dir_path="./proxyserver"
|
||||
screen_name="proxyserver"
|
||||
|
||||
# 进入目录
|
||||
cd $dir_path
|
||||
# 检查是否存在screen session
|
||||
if screen -list | grep -q "$screen_name"; then
|
||||
# 结束存在的screen session
|
||||
screen -S $screen_name -X quit
|
||||
fi
|
||||
go build
|
||||
# 启动新的screen session并运行go程序
|
||||
screen -dmS $screen_name -L ./$screen_name
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ func CommonNotify(WebsocketAddr, wid string, event *wevent.WebsocketEvent) error
|
||||
func (l *UserEmailConfirmationLogic) UserEmailConfirmation(req *types.RequestEmailConfirmation, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
logx.Error("找到user_id1 UserEmailConfirmation")
|
||||
|
||||
switch auth.OperateType(req.OpType) {
|
||||
case auth.OpTypeRegister:
|
||||
|
||||
|
||||
@ -49,50 +49,50 @@ func (l *UserAddAddressLogic) UserAddAddress(req *types.RequestAddAddress, useri
|
||||
isDefautl int64 = 1 // 默认地址为1
|
||||
)
|
||||
createOne := &gmodel.FsAddress{ // 构建FsAddress结构体
|
||||
Name: &req.Name,
|
||||
FirstName: &req.FirstName,
|
||||
LastName: &req.LastName,
|
||||
Mobile: &req.Mobile,
|
||||
Street: &req.Street,
|
||||
Suite: &req.Suite,
|
||||
City: &req.City,
|
||||
State: &req.State,
|
||||
Country: &country,
|
||||
Status: &status,
|
||||
UserId: &userinfo.UserId,
|
||||
ZipCode: &req.ZipCode,
|
||||
IsDefault: &isDefautl,
|
||||
AddressName: &req.Name,
|
||||
FirstName: &req.FirstName,
|
||||
LastName: &req.LastName,
|
||||
Mobile: &req.Mobile,
|
||||
Street: &req.Street,
|
||||
Suite: &req.Suite,
|
||||
City: &req.City,
|
||||
State: &req.State,
|
||||
Country: &country,
|
||||
Status: &status,
|
||||
UserId: &userinfo.UserId,
|
||||
ZipCode: &req.ZipCode,
|
||||
IsDefault: &isDefautl,
|
||||
}
|
||||
created, err := m.CreateOne(l.ctx, createOne) // 新增地址
|
||||
if err != nil {
|
||||
logx.Error(err) // 日志记录错误
|
||||
return resp.SetStatus(basic.CodeDbCreateErr) // 返回数据库创建错误
|
||||
}
|
||||
return resp.SetStatus(basic.CodeOK, map[string]int64{"id": created.Id}) // 返回成功并返回地址ID
|
||||
return resp.SetStatus(basic.CodeOK, map[string]int64{"id": created.AddressId}) // 返回成功并返回地址ID
|
||||
}
|
||||
|
||||
address := &gmodel.FsAddress{
|
||||
Id: req.Id,
|
||||
Name: &req.Name,
|
||||
FirstName: &req.FirstName,
|
||||
LastName: &req.LastName,
|
||||
Mobile: &req.Mobile,
|
||||
Street: &req.Street,
|
||||
Suite: &req.Suite,
|
||||
City: &req.City,
|
||||
State: &req.State,
|
||||
Status: &status,
|
||||
UserId: &userinfo.UserId,
|
||||
ZipCode: &req.ZipCode,
|
||||
IsDefault: &req.IsDefault,
|
||||
AddressId: req.Id,
|
||||
AddressName: &req.Name,
|
||||
FirstName: &req.FirstName,
|
||||
LastName: &req.LastName,
|
||||
Mobile: &req.Mobile,
|
||||
Street: &req.Street,
|
||||
Suite: &req.Suite,
|
||||
City: &req.City,
|
||||
State: &req.State,
|
||||
Status: &status,
|
||||
UserId: &userinfo.UserId,
|
||||
ZipCode: &req.ZipCode,
|
||||
IsDefault: &req.IsDefault,
|
||||
}
|
||||
|
||||
// 插入数据库 更新地址
|
||||
err := m.UpdateAddAddress(l.ctx, address)
|
||||
err := m.UpdateAddress(l.ctx, address)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatus(basic.CodeDbUpdateErr)
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK, map[string]int64{"id": address.Id})
|
||||
return resp.SetStatus(basic.CodeOK, map[string]int64{"id": address.AddressId})
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"fusenapi/server/home-user-auth/internal/types"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
@ -45,13 +46,13 @@ func (l *UserBasicInfoLogic) UserBasicInfo(req *types.Request, userinfo *auth.Us
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK, types.DataUserBasicInfo{
|
||||
Type: *user.Type,
|
||||
IsOrderStatusEmail: *user.IsOrderStatusEmail,
|
||||
IsEmailAdvertisement: *user.IsEmailAdvertisement,
|
||||
IsOrderStatusPhone: *user.IsOrderStatusPhone,
|
||||
IsPhoneAdvertisement: *user.IsPhoneAdvertisement,
|
||||
IsOpenRender: *user.IsOpenRender,
|
||||
IsLowRendering: *user.IsLowRendering,
|
||||
IsRemoveBg: *user.IsRemoveBg,
|
||||
Type: *user.Type,
|
||||
// IsOrderStatusEmail: *user.IsOrderStatusEmail,
|
||||
// IsEmailAdvertisement: *user.IsEmailAdvertisement,
|
||||
// IsOrderStatusPhone: *user.IsOrderStatusPhone,
|
||||
// IsPhoneAdvertisement: *user.IsPhoneAdvertisement,
|
||||
// IsOpenRender: *user.IsOpenRender,
|
||||
// IsLowRendering: *user.IsLowRendering,
|
||||
// IsRemoveBg: *user.IsRemoveBg,
|
||||
})
|
||||
}
|
||||
|
||||
@ -45,8 +45,31 @@ func (l *UserLogoSetLogic) UserLogoSet(req *types.UserLogoSetReq, userinfo *auth
|
||||
// 如果是,返回未授权的错误码
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
var nowTime = time.Now().UTC()
|
||||
if req.LogoSelectedId == 0 {
|
||||
return resp.SetStatus(basic.CodeLogoSetCategory, "logo logo_selected_id not null")
|
||||
NewFsUserMaterialModel1 := gmodel.NewFsUserMaterialModel(l.svcCtx.MysqlConn)
|
||||
NewFsUserMaterialModelRow1 := NewFsUserMaterialModel1.RowSelectBuilder(nil).Where("id = ?", 0)
|
||||
|
||||
defaultMaterialInfo, err := NewFsUserMaterialModel1.FindOne(l.ctx, NewFsUserMaterialModelRow1.Model(&gmodel.FsUserMaterial{}))
|
||||
if err != nil {
|
||||
logc.Errorf(l.ctx, "defaultMaterialInfo FindOne err:%+v", err)
|
||||
return resp.SetStatus(basic.CodeLogoSetCategory, "logo not find")
|
||||
}
|
||||
var defaultMaterial = gmodel.FsUserMaterial{
|
||||
Module: defaultMaterialInfo.Module,
|
||||
UserId: &userinfo.UserId,
|
||||
GuestId: &userinfo.GuestId,
|
||||
ResourceId: defaultMaterialInfo.ResourceId,
|
||||
ResourceUrl: defaultMaterialInfo.ResourceUrl,
|
||||
Ctime: &nowTime,
|
||||
}
|
||||
MaterialCreateRes := l.svcCtx.MysqlConn.Create(&defaultMaterial)
|
||||
err = MaterialCreateRes.Error
|
||||
if err != nil {
|
||||
logc.Errorf(l.ctx, "defaultMaterialInfo Create err:%+v", err)
|
||||
return resp.SetStatus(basic.CodeLogoSetCategory, "logo not find")
|
||||
}
|
||||
req.LogoSelectedId = defaultMaterial.Id
|
||||
}
|
||||
if req.SetLogoCategory == 1 && req.CategoryId == 0 {
|
||||
return resp.SetStatus(basic.CodeLogoSetCategory, "logo category_id not null")
|
||||
@ -73,7 +96,6 @@ func (l *UserLogoSetLogic) UserLogoSet(req *types.UserLogoSetReq, userinfo *auth
|
||||
return resp.SetStatus(basic.CodeLogoSetCategory, "logo not find")
|
||||
}
|
||||
|
||||
var nowTime = time.Now().UTC()
|
||||
err = l.svcCtx.MysqlConn.WithContext(l.ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var metadataMapOldUserMaterial map[string]interface{}
|
||||
if userMaterialInfo.Metadata != nil {
|
||||
|
||||
@ -6,27 +6,27 @@ import (
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/pay/internal/logic"
|
||||
"fusenapi/server/pay/internal/svc"
|
||||
"fusenapi/server/pay/internal/types"
|
||||
"fusenapi/server/info/internal/logic"
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
)
|
||||
|
||||
func OrderPaymentIntentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
func AddressAddHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.OrderPaymentIntentReq
|
||||
var req types.AddressRequest
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewOrderPaymentIntentLogic(r.Context(), svcCtx)
|
||||
l := logic.NewAddressAddLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.OrderPaymentIntent(&req, userinfo)
|
||||
resp := l.AddressAdd(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
35
server/info/internal/handler/addressdefaulthandler.go
Normal file
35
server/info/internal/handler/addressdefaulthandler.go
Normal file
@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/info/internal/logic"
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
)
|
||||
|
||||
func AddressDefaultHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.AddressIdRequest
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewAddressDefaultLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.AddressDefault(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
35
server/info/internal/handler/addressdeletehandler.go
Normal file
35
server/info/internal/handler/addressdeletehandler.go
Normal file
@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/info/internal/logic"
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
)
|
||||
|
||||
func AddressDeleteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.AddressIdRequest
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewAddressDeleteLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.AddressDelete(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
35
server/info/internal/handler/addresslisthandler.go
Normal file
35
server/info/internal/handler/addresslisthandler.go
Normal file
@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/info/internal/logic"
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
)
|
||||
|
||||
func AddressListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.Request
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewAddressListLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.AddressList(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
35
server/info/internal/handler/addressupdatehandler.go
Normal file
35
server/info/internal/handler/addressupdatehandler.go
Normal file
@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/info/internal/logic"
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
)
|
||||
|
||||
func AddressUpdateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.AddressRequest
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewAddressUpdateLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.AddressUpdate(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,41 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/api/info/user",
|
||||
Handler: InfoHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/info/user/profile",
|
||||
Handler: UserGetProfileHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/info/user/profile/base/update",
|
||||
Handler: UpdateProfileBaseHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/info/address/default",
|
||||
Handler: AddressDefaultHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/info/address/add",
|
||||
Handler: AddressAddHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/info/address/update",
|
||||
Handler: AddressUpdateHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/info/address/delete",
|
||||
Handler: AddressDeleteHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/api/info/address/list",
|
||||
Handler: AddressListHandler(serverCtx),
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
35
server/info/internal/handler/updateprofilebasehandler.go
Normal file
35
server/info/internal/handler/updateprofilebasehandler.go
Normal file
@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/info/internal/logic"
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
)
|
||||
|
||||
func UpdateProfileBaseHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.ProfileBaseRequest
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewUpdateProfileBaseLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.UpdateProfileBase(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
35
server/info/internal/handler/usergetprofilehandler.go
Normal file
35
server/info/internal/handler/usergetprofilehandler.go
Normal file
@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/info/internal/logic"
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
)
|
||||
|
||||
func UserGetProfileHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.QueryProfileRequest
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewUserGetProfileLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.UserGetProfile(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
93
server/info/internal/logic/addressaddlogic.go
Normal file
93
server/info/internal/logic/addressaddlogic.go
Normal file
@ -0,0 +1,93 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AddressAddLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAddressAddLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddressAddLogic {
|
||||
return &AddressAddLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *AddressAddLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *AddressAddLogic) AddressAdd(req *types.AddressRequest, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
|
||||
// 确认这个IsDefault的值范围
|
||||
if !auth.CheckValueRange(req.IsDefault, 0, 1) {
|
||||
return resp.SetStatus(basic.CodeSafeValueRangeErr) // IsDefault值超出范围, 返回安全值范围错误
|
||||
}
|
||||
|
||||
m := l.svcCtx.AllModels.FsAddress // 创建地址模型
|
||||
|
||||
// 如果ID为0, 表示新增地址
|
||||
|
||||
var (
|
||||
country string = "USA" // 国家默认为美国
|
||||
isDefautl int64 = 1 // 默认地址为1
|
||||
status int64 = 1 // 默认地址状态为1(正常)
|
||||
)
|
||||
|
||||
createOne := &gmodel.FsAddress{ // 构建FsAddress结构体
|
||||
AddressName: &req.AddressName,
|
||||
FirstName: &req.FirstName,
|
||||
LastName: &req.LastName,
|
||||
Mobile: &req.Mobile,
|
||||
Street: &req.Street,
|
||||
Suite: &req.Suite,
|
||||
City: &req.City,
|
||||
State: &req.State,
|
||||
Country: &country,
|
||||
Status: &status,
|
||||
UserId: &userinfo.UserId,
|
||||
ZipCode: &req.ZipCode,
|
||||
IsDefault: &isDefautl,
|
||||
}
|
||||
_, err := m.CreateOne(l.ctx, createOne) // 新增地址
|
||||
if err != nil {
|
||||
logx.Error(err) // 日志记录错误
|
||||
return resp.SetStatus(basic.CodeDbCreateErr) // 返回数据库创建错误
|
||||
}
|
||||
|
||||
addresses, err := m.GetUserAllAddress(l.ctx, userinfo.UserId)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatus(basic.CodeDbSqlErr) // 返回数据库创建错误
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK, map[string]any{
|
||||
"address_list": addresses,
|
||||
}) // 返回成功并返回地址ID
|
||||
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *AddressAddLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
52
server/info/internal/logic/addressdefaultlogic.go
Normal file
52
server/info/internal/logic/addressdefaultlogic.go
Normal file
@ -0,0 +1,52 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AddressDefaultLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAddressDefaultLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddressDefaultLogic {
|
||||
return &AddressDefaultLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *AddressDefaultLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *AddressDefaultLogic) AddressDefault(req *types.AddressIdRequest, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
|
||||
err := l.svcCtx.AllModels.FsAddress.SettingUserDefaultAddress(l.ctx, userinfo.UserId, req.AddressId)
|
||||
if err != nil {
|
||||
return resp.SetStatusWithMessage(basic.CodeApiErr, err.Error())
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *AddressDefaultLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
52
server/info/internal/logic/addressdeletelogic.go
Normal file
52
server/info/internal/logic/addressdeletelogic.go
Normal file
@ -0,0 +1,52 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AddressDeleteLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAddressDeleteLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddressDeleteLogic {
|
||||
return &AddressDeleteLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *AddressDeleteLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *AddressDeleteLogic) AddressDelete(req *types.AddressIdRequest, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
|
||||
err := l.svcCtx.AllModels.FsAddress.DeleteOne(l.ctx, req.AddressId, userinfo.UserId)
|
||||
if err != nil {
|
||||
return resp.SetStatusWithMessage(basic.CodeApiErr, err.Error())
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *AddressDeleteLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
56
server/info/internal/logic/addresslistlogic.go
Normal file
56
server/info/internal/logic/addresslistlogic.go
Normal file
@ -0,0 +1,56 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AddressListLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAddressListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddressListLogic {
|
||||
return &AddressListLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *AddressListLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *AddressListLogic) AddressList(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
|
||||
m := l.svcCtx.AllModels.FsAddress // 创建地址模型
|
||||
result, err := m.GetUserAllAddress(l.ctx, userinfo.UserId)
|
||||
if err != nil {
|
||||
logx.Error(err) // 日志记录错误
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, err.Error()) // 返回数据库创建错误
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK, map[string]any{
|
||||
"address_list": result,
|
||||
})
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *AddressListLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
76
server/info/internal/logic/addressupdatelogic.go
Normal file
76
server/info/internal/logic/addressupdatelogic.go
Normal file
@ -0,0 +1,76 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AddressUpdateLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAddressUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddressUpdateLogic {
|
||||
return &AddressUpdateLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *AddressUpdateLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *AddressUpdateLogic) AddressUpdate(req *types.AddressRequest, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
if req.AddressId == 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeApiErr, "address_id must setting")
|
||||
}
|
||||
|
||||
address := gmodel.FsAddress{
|
||||
AddressId: req.AddressId,
|
||||
UserId: &userinfo.UserId,
|
||||
IsDefault: &req.IsDefault,
|
||||
AddressName: &req.AddressName,
|
||||
FirstName: &req.FirstName,
|
||||
LastName: &req.LastName,
|
||||
Mobile: &req.Mobile,
|
||||
ZipCode: &req.ZipCode,
|
||||
Street: &req.Street,
|
||||
Suite: &req.Suite,
|
||||
City: &req.City,
|
||||
State: &req.State,
|
||||
Utime: &now,
|
||||
}
|
||||
|
||||
err := l.svcCtx.AllModels.FsAddress.UpdateAddress(l.ctx, &address)
|
||||
if err != nil {
|
||||
return resp.SetStatusWithMessage(basic.CodeApiErr, err.Error())
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *AddressUpdateLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
@ -39,6 +39,7 @@ func NewInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InfoLogic {
|
||||
var ModuleTable map[string]string = map[string]string{
|
||||
"userinfo": "fs_user_info",
|
||||
"material": "fs_user_material",
|
||||
"address": "fs_address", // TODO: 地址列表
|
||||
}
|
||||
|
||||
type ModuleQuery struct {
|
||||
@ -82,6 +83,38 @@ func (mquery *ModuleQuery) EncodeEmpty() map[string]any {
|
||||
return qstr
|
||||
}
|
||||
|
||||
func QueryDefault(conn *gorm.DB, module string, moduleQuery string, tname string) map[string]any {
|
||||
|
||||
qname := strings.Split(moduleQuery, ".")
|
||||
queryAsName := qname[len(qname)-1]
|
||||
sqlstr := fmt.Sprintf(
|
||||
"select JSON_EXTRACT(metadata,'$.%s') as %s from %s where module = '%s' and user_id = 0 and guest_id = 0 order by ctime DESC limit 1",
|
||||
moduleQuery, // logo_selected
|
||||
queryAsName, // logo_selected
|
||||
tname, // fs_user_info
|
||||
module, // profile
|
||||
)
|
||||
raw := conn.Raw(sqlstr)
|
||||
var info map[string]any
|
||||
err := raw.Scan(&info).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
logx.Error(err)
|
||||
}
|
||||
|
||||
if v, ok := info[queryAsName]; ok {
|
||||
var qinfo map[string]any
|
||||
err := json.Unmarshal([]byte(v.(string)), &qinfo)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
} else {
|
||||
info[queryAsName] = qinfo
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
func (l *InfoLogic) Info(req *types.UserInfoRequest, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
@ -178,9 +211,70 @@ func (l *InfoLogic) Info(req *types.UserInfoRequest, userinfo *auth.UserInfo) (r
|
||||
}
|
||||
}
|
||||
|
||||
// 隐含白板用户逻辑
|
||||
if v, ok := metadict["userinfo.profile"]; ok {
|
||||
|
||||
if v == nil {
|
||||
|
||||
info := QueryDefault(l.svcCtx.MysqlConn, "profile", "logo_selected", "fs_user_info")
|
||||
metadict["userinfo.profile"] = info
|
||||
} else {
|
||||
profileDict := v.(map[string]any)
|
||||
if _, ok := profileDict["logo_selected"]; !ok {
|
||||
info := QueryDefault(l.svcCtx.MysqlConn, "profile", "logo_selected", "fs_user_info")
|
||||
profileDict["logo_selected"] = info["logo_selected"]
|
||||
}
|
||||
}
|
||||
|
||||
} else if v, ok := metadict["userinfo.profile.logo_selected"]; ok {
|
||||
if v == nil {
|
||||
info := QueryDefault(l.svcCtx.MysqlConn, "profile", "logo_selected", "fs_user_info")
|
||||
metadict["userinfo.profile.logo_selected"] = info
|
||||
}
|
||||
} else {
|
||||
var info map[string]any
|
||||
for k, v := range metadict {
|
||||
if v == nil {
|
||||
if strings.HasPrefix(k, "userinfo.profile.logo_selected") {
|
||||
if info == nil {
|
||||
info = QueryDefault(l.svcCtx.MysqlConn, "profile", "logo_selected", "fs_user_info")
|
||||
}
|
||||
|
||||
curValue, err := GetMapValueByKey(info, strings.Split(k, ".")[2:])
|
||||
if err != nil {
|
||||
logx.Error(err, info)
|
||||
continue
|
||||
// return resp.SetStatus(basic.CodeOK, metadict)
|
||||
}
|
||||
metadict[k] = curValue
|
||||
// curValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK, metadict)
|
||||
}
|
||||
|
||||
func GetMapValueByKey(info map[string]interface{}, keys []string) (interface{}, error) {
|
||||
// keys := strings.Split(key, ".")[2:]
|
||||
|
||||
for _, k := range keys {
|
||||
if cur, ok := info[k]; ok {
|
||||
if curMap, ok := cur.(map[string]interface{}); ok {
|
||||
info = curMap
|
||||
} else {
|
||||
// logx.Error(cur)
|
||||
return cur, nil
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("info keys is not exists %#v", keys)
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *InfoLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"fusenapi/initalize"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/check"
|
||||
"fusenapi/utils/fssql"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -117,57 +118,47 @@ func TestMain(t *testing.T) {
|
||||
if v == nil {
|
||||
|
||||
info := QueryDefault(conn, "profile", "logo_selected", "fs_user_info")
|
||||
log.Println(info)
|
||||
metadict["userinfo.profile"] = info
|
||||
// log.Println(metadict)
|
||||
} else {
|
||||
profileDict := v.(map[string]any)
|
||||
if _, ok := profileDict["logo_selected"]; !ok {
|
||||
info := QueryDefault(conn, "profile", "logo_selected", "fs_user_info")
|
||||
profileDict["logo_selected"] = info["logo_selected"]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if v, ok := metadict["userinfo.profile.logo_selected"]; ok {
|
||||
if v == nil {
|
||||
info := QueryDefault(conn, "profile", "logo_selected", "fs_user_info")
|
||||
metadict["userinfo.profile.logo_selected"] = info
|
||||
}
|
||||
} else {
|
||||
var info map[string]any
|
||||
for k, v := range metadict {
|
||||
if v == nil {
|
||||
if strings.HasPrefix(k, "userinfo.profile.logo_selected") {
|
||||
if info == nil {
|
||||
info = QueryDefault(conn, "profile", "logo_selected", "fs_user_info")
|
||||
}
|
||||
|
||||
curValue, err := GetMapValueByKey(info, strings.Split(k, ".")[2:])
|
||||
if err != nil {
|
||||
logx.Error(err, info)
|
||||
continue
|
||||
// return resp.SetStatus(basic.CodeOK, metadict)
|
||||
}
|
||||
metadict[k] = curValue
|
||||
// curValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(metadict)
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func QueryDefault(conn *gorm.DB, module string, moduleQuery string, tname string) map[string]any {
|
||||
|
||||
qname := strings.Split(moduleQuery, ".")
|
||||
queryAsName := qname[len(qname)-1]
|
||||
sqlstr := fmt.Sprintf(
|
||||
"select JSON_EXTRACT(metadata,'$.%s') as %s from %s where module = '%s' and user_id = 0 and guest_id = 0 order by ctime DESC limit 1",
|
||||
moduleQuery, // logo_selected
|
||||
queryAsName, // logo_selected
|
||||
tname, // fs_user_info
|
||||
module, // profile
|
||||
)
|
||||
raw := conn.Raw(sqlstr)
|
||||
var info map[string]any
|
||||
err := raw.Scan(&info).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
logx.Error(err)
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func TestCaseJSON_EXTRACT(t *testing.T) {
|
||||
|
||||
userProfile := &gmodel.UserProfile{
|
||||
FirstName: "FirstName",
|
||||
LastName: "LastName",
|
||||
Resetaurant: "Resetaurant",
|
||||
}
|
||||
userProfile := &gmodel.UserProfile{}
|
||||
metadata, err := json.Marshal(userProfile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -185,6 +176,14 @@ func TestCaseJSON_EXTRACT(t *testing.T) {
|
||||
|
||||
conn := initalize.InitMysql("fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen")
|
||||
// err = conn.Exec(updatesql, 6).Error
|
||||
log.Println(conn.Model(&gmodel.FsChangeCode{}).Select("id").Where("id = 5").Take(nil).Error)
|
||||
info := gmodel.UserProfileBase{}
|
||||
|
||||
var baseinfo map[string]any
|
||||
tname := fssql.GetGormTableName(conn, gmodel.FsUserInfo{})
|
||||
rawsql := fmt.Sprintf("select JSON_EXTRACT(metadata,'$.base') as base from %s where user_id = ? and module = ? order by ctime DESC limit 1", tname)
|
||||
tx := conn.Raw(rawsql, 162, "profile").Take(&baseinfo)
|
||||
log.Println(tx.Error)
|
||||
json.Unmarshal([]byte(baseinfo["base"].(string)), &info)
|
||||
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
52
server/info/internal/logic/updateprofilebaselogic.go
Normal file
52
server/info/internal/logic/updateprofilebaselogic.go
Normal file
@ -0,0 +1,52 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type UpdateProfileBaseLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewUpdateProfileBaseLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateProfileBaseLogic {
|
||||
return &UpdateProfileBaseLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *UpdateProfileBaseLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *UpdateProfileBaseLogic) UpdateProfileBase(req *types.ProfileBaseRequest, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
|
||||
err := l.svcCtx.AllModels.FsUserInfo.MergeMetadata(userinfo.UserId, req)
|
||||
if err != nil {
|
||||
logx.Error(err) // 日志记录错误
|
||||
return resp.SetStatus(basic.CodeDbSqlErr, err.Error()) // 返回数据库创建错误
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *UpdateProfileBaseLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
52
server/info/internal/logic/usergetprofilelogic.go
Normal file
52
server/info/internal/logic/usergetprofilelogic.go
Normal file
@ -0,0 +1,52 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/info/internal/svc"
|
||||
"fusenapi/server/info/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type UserGetProfileLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewUserGetProfileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserGetProfileLogic {
|
||||
return &UserGetProfileLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *UserGetProfileLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *UserGetProfileLogic) UserGetProfile(req *types.QueryProfileRequest, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
|
||||
profileBase, err := l.svcCtx.AllModels.FsUserInfo.GetProfile(l.ctx, req.TopKey, userinfo.UserId)
|
||||
if err != nil {
|
||||
return resp.SetStatusWithMessage(basic.CodeApiErr, err.Error())
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK, profileBase)
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *UserGetProfileLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
@ -9,6 +9,46 @@ type UserInfoRequest struct {
|
||||
Module []string `json:"module"`
|
||||
}
|
||||
|
||||
type AddressObjectRequest struct {
|
||||
AddressId int64 `json:"address_id"` // 地址id
|
||||
AddressName string `json:"address_name"` // 地址
|
||||
}
|
||||
|
||||
type AddressIdRequest struct {
|
||||
AddressId int64 `json:"address_id"` // 地址id
|
||||
}
|
||||
|
||||
type AddressNameRequest struct {
|
||||
AddressName string `json:"address_name"` // 地址
|
||||
}
|
||||
|
||||
type AddressRequest struct {
|
||||
AddressId int64 `json:"address_id,optional"`
|
||||
IsDefault int64 `json:"is_default"` //是否默认
|
||||
AddressName string `json:"address_name"` //收货人
|
||||
FirstName string `json:"first_name"` //first_name
|
||||
LastName string `json:"last_name"` //last_name
|
||||
Mobile string `json:"mobile"` //手机
|
||||
ZipCode string `json:"zip_code"` //邮编
|
||||
Street string `json:"street"` //街道
|
||||
Suite string `json:"suite"` //房号
|
||||
City string `json:"city"` //城市
|
||||
State string `json:"state"` //州
|
||||
}
|
||||
|
||||
type ProfileBaseRequest struct {
|
||||
FirstName *string `json:"first_name,optional,omitempty"` // 首名
|
||||
LastName *string `json:"last_name,optional,omitempty"` // 后名
|
||||
UserName *string `json:"user_name,optional,omitempty"` // 用户名
|
||||
Mobile *string `json:"mobile,optional,omitempty"` // 电话
|
||||
Resetaurant *string `json:"resetaurant,optional,omitempty"` // 不知道干什么
|
||||
Company *string `json:"company,optional,omitempty"` // 公司
|
||||
}
|
||||
|
||||
type QueryProfileRequest struct {
|
||||
TopKey string `json:"top_key"` // 首名
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
}
|
||||
|
||||
@ -32,10 +72,10 @@ type File struct {
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
TotalCount int64 `json:"totalCount"`
|
||||
PageCount int64 `json:"pageCount"`
|
||||
CurrentPage int `json:"currentPage"`
|
||||
PerPage int `json:"perPage"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
PageCount int64 `json:"page_count"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
PerPage int `json:"per_page"`
|
||||
}
|
||||
|
||||
// Set 设置Response的Code和Message值
|
||||
|
||||
@ -3,7 +3,7 @@ Host: 0.0.0.0
|
||||
Port: 9907
|
||||
Timeout: 15000 #服务超时时间(毫秒)
|
||||
SourceMysql: fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen
|
||||
SourceRabbitMq:
|
||||
SourceRabbitMq: 213
|
||||
Log:
|
||||
Stat: false
|
||||
Auth:
|
||||
|
||||
@ -47,7 +47,7 @@ func (l *CreateOrderLogic) CreateOrder(req *types.CreateOrderReq, userinfo *auth
|
||||
OriginalCurrency: string(constants.CURRENCYUSD),
|
||||
UserId: userinfo.UserId,
|
||||
CartIds: req.CartIds,
|
||||
DeliveryMethod: req.DeliveryMethod,
|
||||
DeliveryMethod: constants.DELIVERYMETHODDSCLOUDSTORE,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/service/repositories"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
@ -38,7 +39,22 @@ func (l *CreatePrePaymentByBalanceLogic) CreatePrePaymentByBalance(req *types.Cr
|
||||
return resp.SetStatus(basic.CodeUnAuth)
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
res, err := l.svcCtx.Repositories.NewOrder.CreatePrePaymentByBalance(l.ctx, &repositories.CreatePrePaymentByBalanceReq{
|
||||
UserId: userinfo.UserId,
|
||||
OrderSn: req.OrderSn,
|
||||
Country: "US",
|
||||
Currency: "usd",
|
||||
StripeKey: l.svcCtx.Config.PayConfig.Stripe.Key,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return resp.SetStatus(&res.ErrorCode)
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK, map[string]interface{}{
|
||||
"order_detail": res.OrderDetail,
|
||||
"order_pay": res.OrderPay,
|
||||
})
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
|
||||
@ -10,8 +10,7 @@ type OrderDetailReq struct {
|
||||
}
|
||||
|
||||
type CreateOrderReq struct {
|
||||
CartIds []int64 `json:"cart_ids"`
|
||||
DeliveryMethod int64 `json:"delivery_method,options=[1,2]"`
|
||||
CartIds []int64 `json:"cart_ids"`
|
||||
}
|
||||
|
||||
type CreatePrePaymentByDepositReq struct {
|
||||
|
||||
@ -12,11 +12,6 @@ import (
|
||||
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
server.AddRoutes(
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/pay/payment-intent",
|
||||
Handler: OrderPaymentIntentHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/pay/refund",
|
||||
|
||||
@ -1,181 +0,0 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/pay/internal/svc"
|
||||
"fusenapi/server/pay/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type OrderPaymentIntentLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewOrderPaymentIntentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OrderPaymentIntentLogic {
|
||||
return &OrderPaymentIntentLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *OrderPaymentIntentLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *OrderPaymentIntentLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
|
||||
func (l *OrderPaymentIntentLogic) OrderPaymentIntent(req *types.OrderPaymentIntentReq, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
// if userinfo == nil || userinfo.UserId == 0 {
|
||||
// return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order not found")
|
||||
// }
|
||||
|
||||
// // 查询订单数据
|
||||
// orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn)
|
||||
// orderInfo, err := orderModel.FindOneBySn(l.ctx, userinfo.UserId, req.Sn)
|
||||
|
||||
// if err != nil {
|
||||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order not found")
|
||||
// }
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order info")
|
||||
// }
|
||||
|
||||
// // 校验订单状态
|
||||
// if *orderInfo.IsCancel == 1 {
|
||||
// return resp.SetStatusWithMessage(basic.CodeServiceErr, "order cancelled")
|
||||
// }
|
||||
|
||||
// // 校验地址信息
|
||||
// addressModel := gmodel.NewFsAddressModel(l.svcCtx.MysqlConn)
|
||||
// _, err = addressModel.GetOne(l.ctx, req.AddressId, userinfo.UserId)
|
||||
|
||||
// if err != nil {
|
||||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "address not found")
|
||||
// }
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get address info")
|
||||
// }
|
||||
|
||||
// // 校验订单支付信息
|
||||
// if *orderInfo.IsPayCompleted == 1 {
|
||||
// return resp.SetStatusWithMessage(basic.CodeServiceErr, "order is pay completed")
|
||||
// }
|
||||
|
||||
// // 判断订单状态以及该支付金额
|
||||
// var nowAt int64 = time.Now().UTC().Unix()
|
||||
// var payAmount int64
|
||||
// if *orderInfo.Status == int64(constants.STATUS_NEW_NOT_PAY) {
|
||||
// payAmount = *orderInfo.TotalAmount / 2
|
||||
// *orderInfo.DeliveryMethod = req.DeliveryMethod
|
||||
// *orderInfo.AddressId = req.AddressId
|
||||
// *orderInfo.PayMethod = req.PayMethod
|
||||
// } else {
|
||||
// payAmount = *orderInfo.TotalAmount - *orderInfo.TotalAmount/2
|
||||
// }
|
||||
|
||||
// payConfig := &pay.Config{}
|
||||
// var generatePrepaymentReq = &pay.GeneratePrepaymentReq{
|
||||
// OrderSn: req.Sn,
|
||||
// ProductName: "支付标题",
|
||||
// Amount: payAmount,
|
||||
// Currency: "eur",
|
||||
// Quantity: 1,
|
||||
// ProductDescription: "支付描述",
|
||||
// }
|
||||
|
||||
// var resData types.OrderPaymentIntentRes
|
||||
// // 事务处理
|
||||
// ctx := l.ctx
|
||||
// err = l.svcCtx.MysqlConn.Transaction(func(connGorm *gorm.DB) error {
|
||||
// // 支付记录--处理 //支付记录改为一条订单多条,分首款尾款
|
||||
// var payStatus int64 = 0
|
||||
// var orderSource int64 = 1
|
||||
// var payStage int64
|
||||
// var fspay *gmodel.FsPay
|
||||
// newFsPayModel := gmodel.NewFsPayModel(connGorm)
|
||||
// if *orderInfo.Status == int64(constants.STATUS_NEW_NOT_PAY) {
|
||||
// fspay, err = newFsPayModel.RBGetListByOrderNumberStage(ctx, *orderInfo.Sn, 1)
|
||||
// if err != nil {
|
||||
// if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// payStage = 1
|
||||
// } else {
|
||||
// fspay, err = newFsPayModel.RBGetListByOrderNumberStage(ctx, *orderInfo.Sn, 2)
|
||||
// if err != nil {
|
||||
// if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// payStage = 2
|
||||
// }
|
||||
|
||||
// // 支付预付--生成
|
||||
// if constants.PayMethod(req.PayMethod) == constants.PAYMETHOD_STRIPE {
|
||||
// payConfig.Stripe.Key = l.svcCtx.Config.PayConfig.Stripe.Key
|
||||
// generatePrepaymentReq.SuccessURL = l.svcCtx.Config.PayConfig.Stripe.SuccessURL
|
||||
// generatePrepaymentReq.CancelURL = l.svcCtx.Config.PayConfig.Stripe.CancelURL
|
||||
// }
|
||||
// payDriver := pay.NewPayDriver(req.PayMethod, payConfig)
|
||||
// prepaymentRes, err := payDriver.GeneratePrepayment(generatePrepaymentReq)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 订单信息--修改
|
||||
// err = gmodel.NewFsOrderModel(connGorm).RBUpdate(ctx, orderInfo)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// if fspay == nil {
|
||||
// fspay = &gmodel.FsPay{
|
||||
// UserId: orderInfo.UserId,
|
||||
// OrderNumber: orderInfo.Sn,
|
||||
// CreatedAt: &nowAt,
|
||||
// }
|
||||
// } else {
|
||||
// fspay.UpdatedAt = &nowAt
|
||||
// }
|
||||
// fspay.PayAmount = &payAmount
|
||||
// fspay.PayStage = &payStage
|
||||
// //fspay.TradeNo = &prepaymentRes.TradeNo
|
||||
// fspay.PaymentMethod = &req.PayMethod
|
||||
// fspay.OrderSource = &orderSource
|
||||
// fspay.PayStatus = &payStatus
|
||||
|
||||
// _, err = newFsPayModel.RBCreateOrUpdate(ctx, fspay)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// resData.RedirectUrl = prepaymentRes.URL
|
||||
// resData.ClientSecret = prepaymentRes.ClientSecret
|
||||
|
||||
// return nil
|
||||
// })
|
||||
|
||||
// if err != nil {
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to make payment")
|
||||
// }
|
||||
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "success")
|
||||
}
|
||||
@ -1,16 +1,24 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"fusenapi/constants"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/service/repositories"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/pay/internal/svc"
|
||||
"fusenapi/server/pay/internal/types"
|
||||
|
||||
"github.com/stripe/stripe-go/v74"
|
||||
"github.com/stripe/stripe-go/v75"
|
||||
"github.com/stripe/stripe-go/v75/webhook"
|
||||
"github.com/zeromicro/go-zero/core/logc"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
@ -42,110 +50,116 @@ func (l *StripeWebhookLogic) StripeWebhook(req *types.StripeWebhookReq, userinfo
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
// stripe.Key = l.svcCtx.Config.PayConfig.Stripe.Key
|
||||
// event := stripe.Event{}
|
||||
stripe.Key = l.svcCtx.Config.PayConfig.Stripe.Key
|
||||
event := stripe.Event{}
|
||||
|
||||
// if err := json.Unmarshal(req.Payload, &event); err != nil {
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail")
|
||||
// }
|
||||
if err := json.Unmarshal(req.Payload, &event); err != nil {
|
||||
logc.Errorf(l.ctx, "StripeWebhookLogic StripeWebhook Unmarshal err:%v", err)
|
||||
return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail")
|
||||
}
|
||||
// fmt.Println(req)
|
||||
// fmt.Println(event)
|
||||
|
||||
// endpointSecret := l.svcCtx.Config.PayConfig.Stripe.EndpointSecret
|
||||
// signatureHeader := req.StripeSignature
|
||||
// event, err := webhook.ConstructEvent(req.Payload, signatureHeader, endpointSecret)
|
||||
// if err != nil {
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "Webhook signature verification failed")
|
||||
// }
|
||||
endpointSecret := l.svcCtx.Config.PayConfig.Stripe.EndpointSecret
|
||||
signatureHeader := req.StripeSignature
|
||||
fmt.Println(endpointSecret)
|
||||
event, err := webhook.ConstructEvent(req.Payload, signatureHeader, endpointSecret)
|
||||
if err != nil {
|
||||
logc.Errorf(l.ctx, "webhook.ConstructEvent err:%v", err)
|
||||
return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "Webhook signature verification failed")
|
||||
}
|
||||
|
||||
// // 新增支付回调事件日志
|
||||
// var payMethod = int64(constants.PAYMETHOD_STRIPE)
|
||||
// var nowTime = time.Now().UTC().Unix()
|
||||
// var eventData = string(event.Data.Raw)
|
||||
// var fsPayEvent = &gmodel.FsPayEvent{
|
||||
// PayMethod: &payMethod,
|
||||
// EventId: &event.ID,
|
||||
// EventType: &event.Type,
|
||||
// EventData: &eventData,
|
||||
// EventCreated: &event.Created,
|
||||
// Ip: &req.RemoteAddr,
|
||||
// CreatedAt: &nowTime,
|
||||
// }
|
||||
// l.HandlePayEventCreate(fsPayEvent)
|
||||
// 支付回调事件日志
|
||||
var payMethod = int64(constants.PAYMETHOD_STRIPE)
|
||||
var nowTime = time.Now().UTC()
|
||||
var eventData = []byte(event.Data.Raw)
|
||||
eventType := string(event.Type)
|
||||
l.HandlePayEventCreate(&gmodel.FsOrderTradeEvent{
|
||||
PayMethod: &payMethod,
|
||||
EventId: &event.ID,
|
||||
EventType: &eventType,
|
||||
EventData: &eventData,
|
||||
Ctime: &nowTime,
|
||||
})
|
||||
|
||||
// // Unmarshal the event data into an appropriate struct depending on its Type
|
||||
// switch event.Type {
|
||||
// case "charge.succeeded":
|
||||
// // var charge stripe.Charge
|
||||
// // err := json.Unmarshal(event.Data.Raw, &charge)
|
||||
// // if err != nil {
|
||||
// // logx.Error(err)
|
||||
// // return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type charge.succeeded")
|
||||
// // }
|
||||
// Unmarshal the event data into an appropriate struct depending on its Type
|
||||
fmt.Println("事件类型", event.Type)
|
||||
switch event.Type {
|
||||
case "charge.succeeded":
|
||||
var charge stripe.Charge
|
||||
err := json.Unmarshal(event.Data.Raw, &charge)
|
||||
if err != nil {
|
||||
logx.Errorf("err:%+v,desc:%s", err, "pay notify Unmarshal fail event.Type charge.succeeded")
|
||||
return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type charge.succeeded")
|
||||
}
|
||||
err = l.HandleChargeSucceeded(&charge, event.ID)
|
||||
if err != nil {
|
||||
logx.Errorf("err:%+v,desc:%s", err, "pay notify handle payment_intent.succeeded")
|
||||
return resp.SetStatusWithMessage(basic.CodePaybackNotOk, "pay notify handle payment_intent.succeeded")
|
||||
}
|
||||
case "checkout.session.completed":
|
||||
// checkout checkout.session.completed 处理逻辑
|
||||
// var session stripe.CheckoutSession
|
||||
// err := json.Unmarshal(event.Data.Raw, &session)
|
||||
// if err != nil {
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type payment_intent.succeeded")
|
||||
// }
|
||||
// fmt.Println("checkout.session.completed")
|
||||
// err = l.handlePaymentSessionCompleted(session.ID, session.PaymentIntent.ID)
|
||||
// if err != nil {
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "checkout.session.completed fail")
|
||||
// }
|
||||
case "payment_intent.succeeded":
|
||||
// var paymentIntent stripe.PaymentIntent
|
||||
// err := json.Unmarshal(event.Data.Raw, &paymentIntent)
|
||||
// if err != nil {
|
||||
// logx.Errorf("err:%+v,desc:%s", err, "pay notify Unmarshal fail event.Type payment_intent.succeeded")
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type payment_intent.succeeded")
|
||||
// }
|
||||
// err = l.HandlePaymentIntentSucceeded(&paymentIntent, event.ID)
|
||||
// if err != nil {
|
||||
// logx.Errorf("err:%+v,desc:%s", err, "pay notify handle payment_intent.succeeded")
|
||||
// return resp.SetStatusWithMessage(basic.CodePaybackNotOk, "pay notify handle payment_intent.succeeded")
|
||||
// }
|
||||
case "payment_method.attached":
|
||||
// var paymentMethod stripe.PaymentMethod
|
||||
// err := json.Unmarshal(event.Data.Raw, &paymentMethod)
|
||||
// if err != nil {
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type payment_method.attached")
|
||||
// }
|
||||
case "charge.refunded":
|
||||
var chargeRefunded stripe.Charge
|
||||
err := json.Unmarshal(event.Data.Raw, &chargeRefunded)
|
||||
if err != nil {
|
||||
logx.Errorf("err:%+v,desc:%s", err, "pay notify Unmarshal fail event.Type charge.refunded")
|
||||
return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type charge.refunded")
|
||||
}
|
||||
err = l.HandleChargeRefunded(&chargeRefunded)
|
||||
if err != nil {
|
||||
logx.Errorf("err:%+v,desc:%s", err, "pay notify handle charge.refunded")
|
||||
return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify handle charge.refunded")
|
||||
}
|
||||
|
||||
// case "checkout.session.completed":
|
||||
// // checkout checkout.session.completed 处理逻辑
|
||||
// // var session stripe.CheckoutSession
|
||||
// // err := json.Unmarshal(event.Data.Raw, &session)
|
||||
// // if err != nil {
|
||||
// // logx.Error(err)
|
||||
// // return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type payment_intent.succeeded")
|
||||
// // }
|
||||
// // fmt.Println("checkout.session.completed")
|
||||
// // err = l.handlePaymentSessionCompleted(session.ID, session.PaymentIntent.ID)
|
||||
// // if err != nil {
|
||||
// // return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "checkout.session.completed fail")
|
||||
// // }
|
||||
// case "payment_intent.succeeded":
|
||||
// var paymentIntent stripe.PaymentIntent
|
||||
// err := json.Unmarshal(event.Data.Raw, &paymentIntent)
|
||||
// if err != nil {
|
||||
// logx.Errorf("err:%+v,desc:%s", err, "pay notify Unmarshal fail event.Type payment_intent.succeeded")
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type payment_intent.succeeded")
|
||||
// }
|
||||
// err = l.HandlePaymentIntentSucceeded(&paymentIntent)
|
||||
// if err != nil {
|
||||
// logx.Errorf("err:%+v,desc:%s", err, "pay notify handle payment_intent.succeeded")
|
||||
// return resp.SetStatusWithMessage(basic.CodePaybackNotOk, "pay notify handle payment_intent.succeeded")
|
||||
// }
|
||||
// case "payment_method.attached":
|
||||
// var paymentMethod stripe.PaymentMethod
|
||||
// err := json.Unmarshal(event.Data.Raw, &paymentMethod)
|
||||
// if err != nil {
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type payment_method.attached")
|
||||
// }
|
||||
// case "charge.refunded":
|
||||
// var chargeRefunded stripe.Charge
|
||||
// err := json.Unmarshal(event.Data.Raw, &chargeRefunded)
|
||||
// if err != nil {
|
||||
// logx.Errorf("err:%+v,desc:%s", err, "pay notify Unmarshal fail event.Type charge.refunded")
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type charge.refunded")
|
||||
// }
|
||||
// err = l.HandleChargeRefunded(&chargeRefunded)
|
||||
// if err != nil {
|
||||
// logx.Errorf("err:%+v,desc:%s", err, "pay notify handle charge.refunded")
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify handle charge.refunded")
|
||||
// }
|
||||
|
||||
// // ... handle other event types
|
||||
// default:
|
||||
// logx.Error("Unhandled event")
|
||||
// return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type Unhandled")
|
||||
// }
|
||||
// ... handle other event types
|
||||
default:
|
||||
logx.Error("Unhandled event")
|
||||
return resp.SetStatusWithMessage(basic.CodeAesCbcDecryptionErr, "pay notify Unmarshal fail event.Type Unhandled")
|
||||
}
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
||||
|
||||
// 回调事件日志
|
||||
func (l *StripeWebhookLogic) HandlePayEventCreate(fsPayEvent *gmodel.FsPayEvent) error {
|
||||
_, err := gmodel.NewFsPayEventModel(l.svcCtx.MysqlConn).CreateOrUpdate(l.ctx, fsPayEvent)
|
||||
return err
|
||||
func (l *StripeWebhookLogic) HandlePayEventCreate(fsPayEvent *gmodel.FsOrderTradeEvent) error {
|
||||
result := l.svcCtx.MysqlConn.Create(fsPayEvent)
|
||||
return result.Error
|
||||
}
|
||||
|
||||
// 退款成功
|
||||
func (l *StripeWebhookLogic) HandleChargeRefunded(chargeRefunded *stripe.Charge) (err error) {
|
||||
// // 退款成功
|
||||
// 退款成功
|
||||
// if chargeRefunded.Status == "succeeded" {
|
||||
// ctx := l.ctx
|
||||
// err = l.svcCtx.MysqlConn.Transaction(func(connGorm *gorm.DB) error {
|
||||
@ -227,162 +241,27 @@ func (l *StripeWebhookLogic) HandleChargeRefunded(chargeRefunded *stripe.Charge)
|
||||
// }
|
||||
|
||||
// 付款成功
|
||||
func (l *StripeWebhookLogic) HandlePaymentIntentSucceeded(paymentIntent *stripe.PaymentIntent) error {
|
||||
// orderSn, ok := paymentIntent.Metadata["order_sn"]
|
||||
// if !ok || orderSn == "" {
|
||||
// return errors.New("order_sn not found")
|
||||
// }
|
||||
|
||||
// // 查询支付记录
|
||||
// payModel := gmodel.NewFsPayModel(l.svcCtx.MysqlConn)
|
||||
// rsbPay := payModel.RowSelectBuilder(nil)
|
||||
// rsbPay = rsbPay.Where("order_number = ?", orderSn).Where("pay_status = ?", constants.PAYSTATUS_UNSUCCESS)
|
||||
// payInfo, err := payModel.FindOneByQuery(l.ctx, rsbPay, nil)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// //订单信息
|
||||
// orderDetailTemplateModel := gmodel.NewFsOrderDetailTemplateModel(l.svcCtx.MysqlConn)
|
||||
// orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn)
|
||||
// fsOrderDetailModel := gmodel.NewFsOrderDetailModel(l.svcCtx.MysqlConn)
|
||||
// fsProductDesignModel := gmodel.NewFsProductDesignModel(l.svcCtx.MysqlConn)
|
||||
|
||||
// rsbOrder := orderModel.RowSelectBuilder(nil)
|
||||
// rsbOrder = rsbOrder.Where("sn =?", orderSn).Preload("FsOrderDetails")
|
||||
// rsbOrder = rsbOrder.Preload("FsOrderDetails", func(dbPreload *gorm.DB) *gorm.DB {
|
||||
// return dbPreload.Table(fsOrderDetailModel.TableName()).Preload("FsOrderDetailTemplateInfo", func(dbPreload *gorm.DB) *gorm.DB {
|
||||
// return dbPreload.Table(orderDetailTemplateModel.TableName()).Preload("FsProductDesignInfo", func(dbPreload *gorm.DB) *gorm.DB {
|
||||
// return dbPreload.Table(fsProductDesignModel.TableName())
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// fsOrderRelInfo, err := orderModel.FindOneByQuery(l.ctx, rsbOrder, nil)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// var designIds []int64
|
||||
// var cartIds []int64
|
||||
// if len(fsOrderRelInfo.FsOrderDetails) > 0 {
|
||||
// for _, fsOrderDetail := range fsOrderRelInfo.FsOrderDetails {
|
||||
// if fsOrderDetail.FsOrderDetailTemplateInfo.FsProductDesignInfo.Id != 0 {
|
||||
// designIds = append(designIds, fsOrderDetail.FsOrderDetailTemplateInfo.FsProductDesignInfo.Id)
|
||||
// }
|
||||
// cartIds = append(cartIds, *fsOrderDetail.CartId)
|
||||
// }
|
||||
// }
|
||||
|
||||
// var nowTime int64 = time.Now().UTC().Unix()
|
||||
|
||||
// // 支付成功
|
||||
// if paymentIntent.Status == "succeeded" {
|
||||
// var card string
|
||||
// var brand string
|
||||
// if paymentIntent.LatestCharge.PaymentMethodDetails != nil {
|
||||
// if paymentIntent.LatestCharge.PaymentMethodDetails.Card != nil {
|
||||
// if paymentIntent.LatestCharge.PaymentMethodDetails.Card.Last4 != "" {
|
||||
// card = paymentIntent.LatestCharge.PaymentMethodDetails.Card.Last4
|
||||
// }
|
||||
// if paymentIntent.LatestCharge.PaymentMethodDetails.Card.Brand != "" {
|
||||
// brand = string(paymentIntent.LatestCharge.PaymentMethodDetails.Card.Brand)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// ctx := l.ctx
|
||||
// err = l.svcCtx.MysqlConn.Transaction(func(connGorm *gorm.DB) error {
|
||||
// // 更新支付信息
|
||||
// payModelT := gmodel.NewFsPayModel(connGorm)
|
||||
// *payInfo.PayStatus = 1
|
||||
// *payInfo.PayTime = nowTime
|
||||
// *payInfo.CardNo = card
|
||||
// *payInfo.Brand = brand
|
||||
// *payInfo.TradeNo = paymentIntent.ID
|
||||
// _, err = payModelT.RBCreateOrUpdate(ctx, payInfo)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 更新设计数据
|
||||
// productDesignModelT := gmodel.NewFsProductDesignModel(connGorm)
|
||||
// productDesignModelTRSB := productDesignModelT.BuilderTrans(ctx, nil)
|
||||
// var isPay int64 = 1
|
||||
// err = productDesignModelT.RBUpdateByIds(productDesignModelTRSB, designIds, &gmodel.FsProductDesign{IsPay: &isPay})
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// var orderInfo = &gmodel.FsOrder{}
|
||||
// var orderStatus int64
|
||||
// var orderIsPartPay int64
|
||||
// var orderPayedAmount int64
|
||||
// var orderIsPayCompleted int64
|
||||
// // 支付记录是首款
|
||||
// if *payInfo.PayStage == int64(constants.PAYSTAGE_DEPOSIT) {
|
||||
// orderStatus = int64(constants.STATUS_NEW_PART_PAY)
|
||||
// orderIsPartPay = 1
|
||||
// orderInfo.IsPartPay = &orderIsPartPay
|
||||
// orderPayedAmount = paymentIntent.Amount
|
||||
|
||||
// // 删除购物车
|
||||
// cartModelT := gmodel.NewFsCartModel(connGorm)
|
||||
// cartModelTRSB := cartModelT.BuilderTrans(ctx, nil)
|
||||
// err = cartModelT.RBDeleteCartsByIds(cartModelTRSB, cartIds)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 支付记录是尾款
|
||||
// if *payInfo.PayStage == int64(constants.PAYSTAGE_REMAINING) {
|
||||
// if *fsOrderRelInfo.Status < int64(constants.STATUS_NEW_PAY_COMPLETED) {
|
||||
// orderStatus = int64(constants.STATUS_NEW_PAY_COMPLETED)
|
||||
// }
|
||||
// orderIsPayCompleted = 1
|
||||
// orderInfo.IsPayCompleted = &orderIsPayCompleted
|
||||
// orderPayedAmount = *fsOrderRelInfo.PayedAmount + paymentIntent.Amount
|
||||
// }
|
||||
|
||||
// // 更新订单信息
|
||||
// orderInfo.Id = fsOrderRelInfo.Id
|
||||
// orderInfo.Status = &orderStatus
|
||||
// orderInfo.Ptime = &nowTime
|
||||
// orderInfo.PayedAmount = &orderPayedAmount
|
||||
// orderModelT := gmodel.NewFsOrderModel(connGorm)
|
||||
// err = orderModelT.RBUpdate(ctx, orderInfo)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return err
|
||||
// })
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// //千人千面的处理
|
||||
// // $renderServer = (new RenderService());
|
||||
// // $renderServer->thousandsFacesV2($order->id);
|
||||
// // //清除用户最新的设计
|
||||
// // $cache = \Yii::$app->cache;
|
||||
// // $cache->delete(CacheConfigHelper::LAST_DESIGN . $order->user_id);
|
||||
// // //缓存最新订单编号
|
||||
// // $cache->set(CacheConfigHelper::USER_ORDERNO . $order->user_id, $order->sn);
|
||||
|
||||
// // //查询用户邮箱信息
|
||||
// // $user = \api\models\User::find()->where(['id' => $order->user_id])->one();
|
||||
// // $redisData = [
|
||||
// // 'key' => 'receipt_download',
|
||||
// // 'param' => [
|
||||
// // 'email' => $user->email,
|
||||
// // 'order_id' => $order->id,
|
||||
// // 'pay_id' => $pay->id,
|
||||
// // 'type' => 1,//付款成功为1
|
||||
// // ]
|
||||
// // ];
|
||||
// // Email::timely($redisData);
|
||||
// }
|
||||
|
||||
// 订单记录
|
||||
func (l *StripeWebhookLogic) HandleChargeSucceeded(charge *stripe.Charge, eventId string) error {
|
||||
// 支付成功
|
||||
if charge.Status == "succeeded" {
|
||||
model, ok := charge.Metadata["model"]
|
||||
if !ok {
|
||||
err := errors.New("model is empty")
|
||||
logc.Errorf(l.ctx, "PaymentSuccessful failed param, eventId:%s,err:%v", eventId, err)
|
||||
return err
|
||||
}
|
||||
switch model {
|
||||
case "product_order":
|
||||
res, err := l.svcCtx.Repositories.NewOrder.PaymentSuccessful(l.ctx, &repositories.PaymentSuccessfulReq{
|
||||
EventId: eventId,
|
||||
PaymentMethod: "stripe",
|
||||
Charge: charge,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(res)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -18,8 +18,9 @@ type ServiceContext struct {
|
||||
Config config.Config
|
||||
SharedState *shared.SharedState
|
||||
|
||||
MysqlConn *gorm.DB
|
||||
AllModels *gmodel.AllModelsGen
|
||||
MysqlConn *gorm.DB
|
||||
AllModels *gmodel.AllModelsGen
|
||||
Repositories *initalize.Repositories
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
@ -31,6 +32,9 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
MysqlConn: conn,
|
||||
SharedState: nil,
|
||||
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
|
||||
Repositories: initalize.NewAllRepositories(&initalize.NewAllRepositorieData{
|
||||
GormDB: conn,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,18 +11,6 @@ type OrderRefundReq struct {
|
||||
type OrderRefundRes struct {
|
||||
}
|
||||
|
||||
type OrderPaymentIntentReq struct {
|
||||
Sn string `form:"sn"` //订单编号
|
||||
DeliveryMethod int64 `form:"delivery_method"` //发货方式
|
||||
AddressId int64 `form:"address_id"` //地址id
|
||||
PayMethod int64 `form:"pay_method"` //支付方式
|
||||
}
|
||||
|
||||
type OrderPaymentIntentRes struct {
|
||||
RedirectUrl string `json:"redirect_url"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
}
|
||||
|
||||
type StripeWebhookReq struct {
|
||||
Payload []byte `json:"base_byte_slice,optional"`
|
||||
StripeSignature string `json:"Stripe-Signature"`
|
||||
@ -52,10 +40,10 @@ type File struct {
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
TotalCount int64 `json:"totalCount"`
|
||||
PageCount int64 `json:"pageCount"`
|
||||
CurrentPage int `json:"currentPage"`
|
||||
PerPage int `json:"perPage"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
PageCount int64 `json:"page_count"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
PerPage int `json:"per_page"`
|
||||
}
|
||||
|
||||
// Set 设置Response的Code和Message值
|
||||
|
||||
@ -106,7 +106,7 @@ func (l *GetProductTemplateTagsLogic) GetProductTemplateTags(req *types.GetProdu
|
||||
for templateTag, _ := range mapMaterialTemplateTagColors {
|
||||
templateTagNameList = append(templateTagNameList, templateTag)
|
||||
}
|
||||
productTemplateTags, err = l.svcCtx.AllModels.FsProductTemplateTags.GetListByTagNames(l.ctx, templateTagNameList, req.Limit, 1, "id DESC")
|
||||
productTemplateTags, err = l.svcCtx.AllModels.FsProductTemplateTags.GetListByTagNames(l.ctx, templateTagNameList, len(templateTagNameList), 1, "id DESC")
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get template tags")
|
||||
@ -135,6 +135,7 @@ func (l *GetProductTemplateTagsLogic) GetProductTemplateTags(req *types.GetProdu
|
||||
for k, v := range productTemplateTags {
|
||||
if templateTagStr == *v.TemplateTag {
|
||||
productTemplateTags[k], productTemplateTags[index] = productTemplateTags[index], productTemplateTags[k]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,4 +11,22 @@ type Config struct {
|
||||
SourceMysql string
|
||||
Auth types.Auth
|
||||
ReplicaId uint64
|
||||
AWS struct {
|
||||
S3 struct {
|
||||
Credentials struct {
|
||||
AccessKeyID string
|
||||
Secret string
|
||||
Token string
|
||||
}
|
||||
}
|
||||
}
|
||||
BLMService struct {
|
||||
Url string
|
||||
LogoCombine struct {
|
||||
Url string
|
||||
}
|
||||
}
|
||||
Unity struct {
|
||||
Host string
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/product/internal/logic"
|
||||
"fusenapi/server/product/internal/svc"
|
||||
"fusenapi/server/product/internal/types"
|
||||
)
|
||||
|
||||
func CalculateProductPriceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.CalculateProductPriceReq
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewCalculateProductPriceLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.CalculateProductPrice(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/product/internal/logic"
|
||||
"fusenapi/server/product/internal/svc"
|
||||
"fusenapi/server/product/internal/types"
|
||||
)
|
||||
|
||||
func GetProductStepPriceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.GetProductStepPriceReq
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewGetProductStepPriceLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.GetProductStepPrice(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,6 +72,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/api/product/get_price_by_pid",
|
||||
Handler: GetPriceByPidHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/api/product/get_product_step_price",
|
||||
Handler: GetProductStepPriceHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/product/calculate_product_price",
|
||||
Handler: CalculateProductPriceHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/api/product/get_size_by_pid",
|
||||
|
||||
101
server/product/internal/logic/calculateproductpricelogic.go
Normal file
101
server/product/internal/logic/calculateproductpricelogic.go
Normal file
@ -0,0 +1,101 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fusenapi/constants"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/format"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/product/internal/svc"
|
||||
"fusenapi/server/product/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CalculateProductPriceLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCalculateProductPriceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CalculateProductPriceLogic {
|
||||
return &CalculateProductPriceLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *CalculateProductPriceLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *CalculateProductPriceLogic) CalculateProductPrice(req *types.CalculateProductPriceReq, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
if req.ProductId <= 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:product id")
|
||||
}
|
||||
if req.SizeId <= 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:size id")
|
||||
}
|
||||
if req.PurchaseQuantity <= 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:purchase quantity")
|
||||
}
|
||||
//获取产品信息(只是获取id)
|
||||
_, err := l.svcCtx.AllModels.FsProduct.FindOne(l.ctx, req.ProductId, "id")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists")
|
||||
}
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info")
|
||||
}
|
||||
//根据产品跟尺寸获取模型价格信息
|
||||
modelInfo, err := l.svcCtx.AllModels.FsProductModel3d.FindOneByProductIdSizeIdTag(l.ctx, req.ProductId, req.SizeId, constants.TAG_MODEL, "id,step_price")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "model info is not exists")
|
||||
}
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get model info")
|
||||
}
|
||||
var stepPrice gmodel.StepPriceJsonStruct
|
||||
if modelInfo.StepPrice != nil && len(*modelInfo.StepPrice) != 0 {
|
||||
if err = json.Unmarshal(*modelInfo.StepPrice, &stepPrice); err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse step price")
|
||||
}
|
||||
}
|
||||
//配件
|
||||
fittingPrice := int64(0)
|
||||
if req.FittingId > 0 {
|
||||
fittingInfo, err := l.svcCtx.AllModels.FsProductModel3d.FindOne(l.ctx, req.FittingId, "id,price")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "fitting info is not exists")
|
||||
}
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get fitting info")
|
||||
}
|
||||
fittingPrice = *fittingInfo.Price
|
||||
}
|
||||
totalPrice, itemPrice, err := l.svcCtx.Repositories.NewShoppingCart.CaculateStepPrice(req.PurchaseQuantity, stepPrice, fittingPrice)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to calculate product price ")
|
||||
}
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.CalculateProductPriceRsp{
|
||||
ItemPrice: format.CentitoDollar(itemPrice, 3),
|
||||
TotalPrice: format.CentitoDollarWithNoHalfAdjust(totalPrice, 2),
|
||||
PurchaseQuantity: req.PurchaseQuantity,
|
||||
})
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *CalculateProductPriceLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
@ -2,12 +2,9 @@ package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"fusenapi/server/product/internal/svc"
|
||||
"fusenapi/server/product/internal/types"
|
||||
|
||||
@ -33,18 +30,18 @@ func (l *GetLastProductDesignLogic) GetLastProductDesign(req *types.Request, use
|
||||
return resp.SetStatusAddMessage(basic.CodeUnAuth, "please sign in")
|
||||
}
|
||||
//获取用户信息
|
||||
user, err := l.svcCtx.AllModels.FsUser.FindUserById(l.ctx, userinfo.UserId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeUnAuth, "user not found")
|
||||
}
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user info")
|
||||
}
|
||||
//若没打开了个性化渲染按钮
|
||||
if *user.IsOpenRender != 1 {
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "success:IsOpenRender switch is closed")
|
||||
}
|
||||
// user, err := l.svcCtx.AllModels.FsUser.FindUserById(l.ctx, userinfo.UserId)
|
||||
// if err != nil {
|
||||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// return resp.SetStatusWithMessage(basic.CodeUnAuth, "user not found")
|
||||
// }
|
||||
// logx.Error(err)
|
||||
// return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user info")
|
||||
// }
|
||||
// //若没打开了个性化渲染按钮
|
||||
// if *user.IsOpenRender != 1 {
|
||||
// return resp.SetStatusWithMessage(basic.CodeOK, "success:IsOpenRender switch is closed")
|
||||
// }
|
||||
//查询用户最近下单成功的数据
|
||||
// orderInfo, err := l.svcCtx.AllModels.FsOrder.FindLastSuccessOneOrder(l.ctx, user.Id, int64(constants.STATUS_NEW_NOT_PAY))
|
||||
// if err != nil {
|
||||
|
||||
@ -377,8 +377,8 @@ func (l *GetProductInfoLogic) GetProductInfo(req *types.GetProductInfoReq, useri
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user info")
|
||||
}
|
||||
isLowRendering = *user.IsLowRendering > 0
|
||||
isRemoveBg = *user.IsRemoveBg > 0
|
||||
isLowRendering = true
|
||||
isRemoveBg = true
|
||||
lastDesign = l.getLastDesign(user)
|
||||
}
|
||||
var renderDesign interface{}
|
||||
|
||||
@ -12,12 +12,13 @@ import (
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/format"
|
||||
"fusenapi/utils/image"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||
"gorm.io/gorm"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type GetProductListLogic struct {
|
||||
@ -163,7 +164,7 @@ func (l *GetProductListLogic) GetProductList(req *types.GetProductListReq, useri
|
||||
UserId: user.Id,
|
||||
}
|
||||
if user.Id != 0 {
|
||||
r.IsThousandFace = int(*user.IsThousandFace)
|
||||
r.IsThousandFace = 1
|
||||
}
|
||||
image.ThousandFaceImageFormat(&r)
|
||||
item.Cover = r.Cover
|
||||
|
||||
137
server/product/internal/logic/getproductsteppricelogic.go
Normal file
137
server/product/internal/logic/getproductsteppricelogic.go
Normal file
@ -0,0 +1,137 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"fusenapi/constants"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/format"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"fusenapi/server/product/internal/svc"
|
||||
"fusenapi/server/product/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetProductStepPriceLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetProductStepPriceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductStepPriceLogic {
|
||||
return &GetProductStepPriceLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *GetProductStepPriceLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *GetProductStepPriceLogic) GetProductStepPrice(req *types.GetProductStepPriceReq, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
if req.ProductId <= 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:product id")
|
||||
}
|
||||
//获取产品信息(只是获取id)
|
||||
_, err := l.svcCtx.AllModels.FsProduct.FindOne(l.ctx, req.ProductId, "id")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists")
|
||||
}
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info")
|
||||
}
|
||||
//查询产品价格
|
||||
modelPriceList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByProductIdTag(l.ctx, req.ProductId, constants.TAG_MODEL, "id,size_id,part_id,step_price,packed_unit")
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get model price list")
|
||||
}
|
||||
fittingIds := make([]int64, 0, len(modelPriceList))
|
||||
for _, v := range modelPriceList {
|
||||
if *v.PartId > 0 {
|
||||
fittingIds = append(fittingIds, *v.PartId)
|
||||
}
|
||||
}
|
||||
//查询配件价格列表
|
||||
fittingPriceList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIdsTag(l.ctx, fittingIds, constants.TAG_PARTS, "id,price,packed_unit")
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get fitting price list")
|
||||
}
|
||||
mapFitting := make(map[int64]gmodel.FsProductModel3d)
|
||||
for _, v := range fittingPriceList {
|
||||
mapFitting[v.Id] = v
|
||||
}
|
||||
//遍历处理模型价格
|
||||
mapRsp := make(map[string]interface{})
|
||||
for _, modelPriceInfo := range modelPriceList {
|
||||
var stepPrice gmodel.StepPriceJsonStruct
|
||||
if err = json.Unmarshal(*modelPriceInfo.StepPrice, &stepPrice); err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse step price json")
|
||||
}
|
||||
rangeLen := len(stepPrice.PriceRange)
|
||||
if rangeLen == 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("step price is not set:%d", modelPriceInfo.Id))
|
||||
}
|
||||
//最小单价
|
||||
minPrice := stepPrice.PriceRange[rangeLen-1].Price
|
||||
//最大单价
|
||||
maxPrice := stepPrice.PriceRange[0].Price
|
||||
//购买数步进基数
|
||||
stepPurchaseQuantity := *modelPriceInfo.PackedUnit
|
||||
//购买数步进基数描述
|
||||
stepPurchaseQuantityDescription := "主体装箱数为步进基数"
|
||||
if *modelPriceInfo.PartId > 0 {
|
||||
fittingPriceInfo, ok := mapFitting[*modelPriceInfo.PartId]
|
||||
if !ok {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("fitting price is not exists:%d", *modelPriceInfo.PartId))
|
||||
}
|
||||
//最小价格要加配件
|
||||
minPrice += *fittingPriceInfo.Price
|
||||
//如果配件装箱基数比主体大,则基数以配件为主
|
||||
if *fittingPriceInfo.PackedUnit > stepPurchaseQuantity {
|
||||
stepPurchaseQuantity = *fittingPriceInfo.PackedUnit
|
||||
stepPurchaseQuantityDescription = "配件装箱数为步进基数"
|
||||
}
|
||||
}
|
||||
stepRange := make([]interface{}, 0, rangeLen)
|
||||
for rIndex, rangeInfo := range stepPrice.PriceRange {
|
||||
//最后一个
|
||||
if rIndex+1 == rangeLen {
|
||||
stepRange = append(stepRange, map[string]interface{}{
|
||||
"range_description": fmt.Sprintf(">=%s Units", format.NumToStringWithThousandthPercentile(rangeInfo.StartQuantity)),
|
||||
"item_price": format.CentitoDollar(rangeInfo.Price, 3),
|
||||
})
|
||||
break
|
||||
}
|
||||
stepRange = append(stepRange, map[string]interface{}{
|
||||
"range_description": fmt.Sprintf("%s-%s Units", format.NumToStringWithThousandthPercentile(rangeInfo.StartQuantity), format.NumToStringWithThousandthPercentile(rangeInfo.EndQuantity)),
|
||||
"item_price": format.CentitoDollar(rangeInfo.Price, 3),
|
||||
})
|
||||
}
|
||||
mapRsp[fmt.Sprintf("_%d", *modelPriceInfo.SizeId)] = map[string]interface{}{
|
||||
"step_purchase_quantity": stepPurchaseQuantity,
|
||||
"step_purchase_quantity_description": stepPurchaseQuantityDescription,
|
||||
"min_price": minPrice,
|
||||
"max_price": maxPrice,
|
||||
"step_range": stepRange,
|
||||
"min_buy_units_quantity": stepPrice.MinBuyUnitsNum,
|
||||
}
|
||||
}
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "success", mapRsp)
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *GetProductStepPriceLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
@ -77,8 +77,8 @@ func (l *GetRenderSettingByPidLogic) GetRenderSettingByPid(req *types.GetRenderS
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user info")
|
||||
}
|
||||
isLowRendering = *user.IsLowRendering > 0
|
||||
isRemoveBg = *user.IsRemoveBg > 0
|
||||
isLowRendering = true
|
||||
isRemoveBg = true
|
||||
lastDesign, err = l.checkLastDesignExists(user.Id)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
|
||||
@ -59,7 +59,10 @@ func (l *GetSizeByPidLogic) GetSizeByPid(req *types.GetSizeByPidReq, userinfo *a
|
||||
} else {
|
||||
//根据模板找到模型sizeId
|
||||
defaultModel3d, err := l.svcCtx.AllModels.FsProductModel3d.FindOne(l.ctx, *defaultTemplate.ModelId, "size_id")
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "the template`s model is not exists ")
|
||||
}
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get default model ")
|
||||
}
|
||||
|
||||
@ -1,16 +1,10 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"fusenapi/constants"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/format"
|
||||
"fusenapi/utils/step_price"
|
||||
"strings"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/product/internal/svc"
|
||||
"fusenapi/server/product/internal/types"
|
||||
@ -32,157 +26,18 @@ func NewGetSizeByProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
|
||||
}
|
||||
}
|
||||
|
||||
// 获取分类下的产品以及尺寸
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *GetSizeByProductLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *GetSizeByProductLogic) GetSizeByProduct(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
if userinfo.GetIdType() != auth.IDTYPE_User {
|
||||
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please sign in first")
|
||||
}
|
||||
//获取所有网站目录
|
||||
tagsModel := gmodel.NewFsTagsModel(l.svcCtx.MysqlConn)
|
||||
tagsList, err := tagsModel.GetAllByLevel(l.ctx, constants.TYPE_WEBSITE)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get website tags")
|
||||
}
|
||||
if len(tagsList) == 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "tag list is null")
|
||||
}
|
||||
tagIds := make([]int64, 0, len(tagsList))
|
||||
for _, v := range tagsList {
|
||||
tagIds = append(tagIds, v.Id)
|
||||
}
|
||||
//获取这些类型的产品
|
||||
productModel := gmodel.NewFsProductModel(l.svcCtx.MysqlConn)
|
||||
productList, err := productModel.GetProductListByIds(l.ctx, tagIds, "sort-desc")
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get tag product list")
|
||||
}
|
||||
productIds := make([]int64, 0, len(productList))
|
||||
for _, v := range productList {
|
||||
productIds = append(productIds, v.Id)
|
||||
}
|
||||
productSizeModel := gmodel.NewFsProductSizeModel(l.svcCtx.MysqlConn)
|
||||
productSizeList, err := productSizeModel.GetAllByProductIds(l.ctx, productIds, "sort DESC")
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product size list")
|
||||
}
|
||||
sizeIds := make([]int64, 0, len(productSizeList))
|
||||
for _, v := range productSizeList {
|
||||
sizeIds = append(sizeIds, v.Id)
|
||||
}
|
||||
//获取价格列表
|
||||
productPriceModel := gmodel.NewFsProductPriceModel(l.svcCtx.MysqlConn)
|
||||
productPriceList, err := productPriceModel.GetPriceListByProductIdsSizeIds(l.ctx, productIds, sizeIds)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product proce list")
|
||||
}
|
||||
mapProductPrice := make(map[string]gmodel.FsProductPrice)
|
||||
for _, v := range productPriceList {
|
||||
mapProductPrice[fmt.Sprintf("%d_%d", *v.ProductId, *v.SizeId)] = v
|
||||
}
|
||||
//组装返回
|
||||
list := make([]types.GetSizeByProductRsp, 0, len(tagsList))
|
||||
for _, tag := range tagsList {
|
||||
//获取第一层子类
|
||||
firstChildrenList, err := l.GetFirstChildrenList(tag, productList, productSizeList, mapProductPrice)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get first level children list")
|
||||
}
|
||||
data := types.GetSizeByProductRsp{
|
||||
Id: tag.Id,
|
||||
Name: *tag.Title,
|
||||
Children: firstChildrenList,
|
||||
}
|
||||
list = append(list, data)
|
||||
}
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "success", list)
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
||||
|
||||
// 第一层子层
|
||||
func (l *GetSizeByProductLogic) GetFirstChildrenList(tag gmodel.FsTags, productList []gmodel.FsProduct, productSizeList []gmodel.FsProductSize, mapProductPrice map[string]gmodel.FsProductPrice) (childrenList []types.Children, err error) {
|
||||
childrenList = make([]types.Children, 0, len(productList))
|
||||
for _, product := range productList {
|
||||
if *product.Type != tag.Id {
|
||||
continue
|
||||
}
|
||||
childrenObjList, err := l.GetSecondChildrenList(product, productSizeList, mapProductPrice)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//获取第二层子类
|
||||
data := types.Children{
|
||||
Id: product.Id,
|
||||
Name: *product.Title,
|
||||
Cycle: int(*product.DeliveryDays + *product.ProduceDays),
|
||||
ChildrenList: childrenObjList,
|
||||
}
|
||||
childrenList = append(childrenList, data)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 第2层子层
|
||||
func (l *GetSizeByProductLogic) GetSecondChildrenList(product gmodel.FsProduct, productSizeList []gmodel.FsProductSize, mapProductPrice map[string]gmodel.FsProductPrice) (childrenObjList []types.ChildrenObj, err error) {
|
||||
childrenObjList = make([]types.ChildrenObj, 0, len(productSizeList))
|
||||
for _, productSize := range productSizeList {
|
||||
if product.Id != *productSize.ProductId {
|
||||
continue
|
||||
}
|
||||
priceList := make([]types.PriceObj, 0, len(productSizeList))
|
||||
price, ok := mapProductPrice[fmt.Sprintf("%d_%d", *productSize.ProductId, productSize.Id)]
|
||||
//无对应尺寸价格
|
||||
if !ok {
|
||||
priceList = []types.PriceObj{
|
||||
{Num: 1, Price: 0},
|
||||
{Num: 1, Price: 0},
|
||||
{Num: 1, Price: 0},
|
||||
}
|
||||
childrenObjList = append(childrenObjList, types.ChildrenObj{
|
||||
Id: productSize.Id,
|
||||
Name: *productSize.Capacity,
|
||||
PriceList: priceList,
|
||||
})
|
||||
continue
|
||||
}
|
||||
if price.StepNum == nil || price.StepPrice == nil {
|
||||
continue
|
||||
}
|
||||
*price.StepNum = strings.Trim(*price.StepNum, " ")
|
||||
*price.StepPrice = strings.Trim(*price.StepPrice, " ")
|
||||
|
||||
//阶梯数量切片
|
||||
stepNum, err := format.StrSlicToIntSlice(strings.Split(*price.StepNum, ","))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//阶梯价格切片
|
||||
stepPrice, err := format.StrSlicToIntSlice(strings.Split(*price.StepPrice, ","))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(stepNum) == 0 || len(stepPrice) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("stepNum count or stepPrice count is empty: product size id :%d ,product price id :%d", productSize.Id, price.Id))
|
||||
}
|
||||
index := 0
|
||||
// 最小购买数量小于 最大阶梯数量+5
|
||||
for int(*price.MinBuyNum) < (stepNum[len(stepNum)-1]+5) && index < 3 {
|
||||
priceList = append(priceList, types.PriceObj{
|
||||
Num: int(*price.MinBuyNum * *price.EachBoxNum),
|
||||
Price: step_price.GetStepPrice(int(*price.MinBuyNum), stepNum, stepPrice),
|
||||
})
|
||||
*price.MinBuyNum++
|
||||
index++
|
||||
}
|
||||
data := types.ChildrenObj{
|
||||
Id: productSize.Id,
|
||||
Name: *productSize.Capacity,
|
||||
PriceList: priceList,
|
||||
}
|
||||
childrenObjList = append(childrenObjList, data)
|
||||
}
|
||||
return
|
||||
}
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *GetSizeByProductLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/image"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -75,7 +76,7 @@ func (l *GetSuccessRecommandLogic) GetSuccessRecommand(req *types.GetSuccessReco
|
||||
UserId: user.Id,
|
||||
}
|
||||
if user.Id > 0 {
|
||||
r.IsThousandFace = int(*user.IsThousandFace)
|
||||
r.IsThousandFace = int(1)
|
||||
}
|
||||
image.ThousandFaceImageFormat(&r)
|
||||
data.Cover = r.Cover
|
||||
|
||||
@ -8,9 +8,10 @@ import (
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/format"
|
||||
"fusenapi/utils/image"
|
||||
"gorm.io/gorm"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"fusenapi/server/product/internal/svc"
|
||||
"fusenapi/server/product/internal/types"
|
||||
|
||||
@ -83,7 +84,7 @@ func (l *OtherProductListLogic) OtherProductList(req *types.OtherProductListReq,
|
||||
UserId: user.Id,
|
||||
}
|
||||
if user.Id > 0 {
|
||||
r.IsThousandFace = int(*user.IsThousandFace)
|
||||
r.IsThousandFace = 1
|
||||
}
|
||||
image.ThousandFaceImageFormat(r)
|
||||
v.Cover = r.Cover
|
||||
|
||||
@ -5,6 +5,9 @@ import (
|
||||
"fmt"
|
||||
"fusenapi/server/product/internal/config"
|
||||
"fusenapi/shared"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"net/http"
|
||||
|
||||
"fusenapi/initalize"
|
||||
@ -18,15 +21,28 @@ type ServiceContext struct {
|
||||
Config config.Config
|
||||
SharedState *shared.SharedState
|
||||
|
||||
MysqlConn *gorm.DB
|
||||
AllModels *gmodel.AllModelsGen
|
||||
MysqlConn *gorm.DB
|
||||
AllModels *gmodel.AllModelsGen
|
||||
Repositories *initalize.Repositories
|
||||
AwsSession *session.Session
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
conn := initalize.InitMysql(c.SourceMysql)
|
||||
config := aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials(c.AWS.S3.Credentials.AccessKeyID, c.AWS.S3.Credentials.Secret, c.AWS.S3.Credentials.Token),
|
||||
}
|
||||
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
MysqlConn: initalize.InitMysql(c.SourceMysql),
|
||||
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
|
||||
Config: c,
|
||||
MysqlConn: initalize.InitMysql(c.SourceMysql),
|
||||
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
|
||||
AwsSession: session.Must(session.NewSession(&config)),
|
||||
Repositories: initalize.NewAllRepositories(&initalize.NewAllRepositorieData{
|
||||
GormDB: conn,
|
||||
BLMServiceUrl: &c.BLMService.Url,
|
||||
AwsSession: session.Must(session.NewSession(&config)),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -331,6 +331,23 @@ type PriceItem struct {
|
||||
Price int64 `json:"price"`
|
||||
}
|
||||
|
||||
type GetProductStepPriceReq struct {
|
||||
ProductId int64 `form:"product_id"`
|
||||
}
|
||||
|
||||
type CalculateProductPriceReq struct {
|
||||
ProductId int64 `json:"product_id"`
|
||||
SizeId int64 `json:"size_id"`
|
||||
FittingId int64 `json:"fitting_id,optional"`
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"`
|
||||
}
|
||||
|
||||
type CalculateProductPriceRsp struct {
|
||||
ItemPrice string `json:"item_price"`
|
||||
TotalPrice string `json:"total_price"`
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"`
|
||||
}
|
||||
|
||||
type GetSizeByPidReq struct {
|
||||
Pid string `form:"pid"`
|
||||
TemplateTag string `form:"template_tag"`
|
||||
@ -440,10 +457,10 @@ type File struct {
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
TotalCount int64 `json:"totalCount"`
|
||||
PageCount int64 `json:"pageCount"`
|
||||
CurrentPage int `json:"currentPage"`
|
||||
PerPage int `json:"perPage"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
PageCount int64 `json:"page_count"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
PerPage int `json:"per_page"`
|
||||
}
|
||||
|
||||
// Set 设置Response的Code和Message值
|
||||
|
||||
@ -10,6 +10,8 @@ import (
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/file"
|
||||
"fusenapi/utils/hash"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
|
||||
@ -51,6 +53,31 @@ func (l *AddToCartLogic) AddToCart(req *types.AddToCartReq, userinfo *auth.UserI
|
||||
if cartCount >= 100 {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "sorry,the count of your carts can`t greater than 100")
|
||||
}
|
||||
if req.RenderImage != "" {
|
||||
//上传base64文件
|
||||
// 上传文件
|
||||
var upload = file.Upload{
|
||||
Ctx: l.ctx,
|
||||
MysqlConn: l.svcCtx.MysqlConn,
|
||||
AwsSession: l.svcCtx.AwsSession,
|
||||
}
|
||||
uploadRes, err := upload.UploadFileByBase64(&file.UploadBaseReq{
|
||||
Source: "webGl render image",
|
||||
FileHash: hash.JsonHashKey(req.RenderImage),
|
||||
FileData: req.RenderImage,
|
||||
Metadata: "",
|
||||
UploadBucket: 1,
|
||||
ApiType: 2,
|
||||
UserId: userinfo.UserId,
|
||||
GuestId: userinfo.GuestId,
|
||||
FileByte: nil,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeFileUploadErr, "failed to upload webGl render image")
|
||||
}
|
||||
req.RenderImage = uploadRes.ResourceUrl
|
||||
}
|
||||
//获取产品是否存在
|
||||
productInfo, err := l.svcCtx.AllModels.FsProduct.FindOne(l.ctx, req.ProductId)
|
||||
if err != nil {
|
||||
|
||||
@ -2,9 +2,9 @@ package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"fusenapi/constants"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
@ -53,7 +53,7 @@ func (l *CalculateCartPriceLogic) CalculateCartPrice(req *types.CalculateCartPri
|
||||
//获取购物车列表
|
||||
carts, _, err := l.svcCtx.AllModels.FsShoppingCart.GetAllCartsByParam(l.ctx, gmodel.GetAllCartsByParamReq{
|
||||
Ids: cartIds,
|
||||
Fields: "id,size_id,product_id,fitting_id",
|
||||
Fields: "id,size_id,product_id,fitting_id,model_id",
|
||||
UserId: userinfo.UserId,
|
||||
Page: 1,
|
||||
Limit: len(cartIds),
|
||||
@ -67,33 +67,24 @@ func (l *CalculateCartPriceLogic) CalculateCartPrice(req *types.CalculateCartPri
|
||||
}
|
||||
sizeIds := make([]int64, 0, len(carts))
|
||||
productIds := make([]int64, 0, len(carts))
|
||||
fittingIds := make([]int64, 0, len(carts))
|
||||
modelIds := make([]int64, 0, len(carts)) //模型+配件
|
||||
for _, v := range carts {
|
||||
sizeIds = append(sizeIds, *v.SizeId)
|
||||
productIds = append(productIds, *v.ProductId)
|
||||
modelIds = append(modelIds, *v.ModelId)
|
||||
if *v.FittingId > 0 {
|
||||
fittingIds = append(fittingIds, *v.FittingId)
|
||||
modelIds = append(modelIds, *v.FittingId)
|
||||
}
|
||||
}
|
||||
//根据sizeid获取价格列表
|
||||
priceList, err := l.svcCtx.AllModels.FsProductPrice.GetPriceListByProductIdsSizeIds(l.ctx, productIds, sizeIds)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get price list")
|
||||
}
|
||||
mapPrice := make(map[string]gmodel.FsProductPrice)
|
||||
for _, v := range priceList {
|
||||
mapPrice[fmt.Sprintf("%d_%d", *v.ProductId, *v.SizeId)] = v
|
||||
}
|
||||
//获取配件列表(只有id跟价格)
|
||||
fittingList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIdsTag(l.ctx, fittingIds, constants.TAG_PARTS, "id,price")
|
||||
modelList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIds(l.ctx, modelIds, "id,step_price,price")
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get fitting list")
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get model list")
|
||||
}
|
||||
mapFitting := make(map[int64]int64)
|
||||
for _, v := range fittingList {
|
||||
mapFitting[v.Id] = *v.Price
|
||||
mapModel := make(map[int64]gmodel.FsProductModel3d)
|
||||
for _, v := range modelList {
|
||||
mapModel[v.Id] = v
|
||||
}
|
||||
//开始计算价格
|
||||
calculateResultList := make([]types.CalculateResultItem, 0, len(req.CalculateList))
|
||||
@ -102,9 +93,16 @@ func (l *CalculateCartPriceLogic) CalculateCartPrice(req *types.CalculateCartPri
|
||||
err = l.svcCtx.MysqlConn.Transaction(func(tx *gorm.DB) error {
|
||||
shoppingCartModel := gmodel.NewFsShoppingCartModel(tx)
|
||||
for _, cart := range carts {
|
||||
sizePrice, ok := mapPrice[fmt.Sprintf("%d_%d", *cart.ProductId, *cart.SizeId)]
|
||||
modelInfo, ok := mapModel[*cart.ModelId]
|
||||
if !ok {
|
||||
return errors.New(fmt.Sprintf("there carts contain some one which have no price info:%d_%d", *cart.ProductId, *cart.SizeId))
|
||||
return err
|
||||
}
|
||||
var stepPrice gmodel.StepPriceJsonStruct
|
||||
if modelInfo.StepPrice != nil && len(*modelInfo.StepPrice) != 0 {
|
||||
if err = json.Unmarshal(*modelInfo.StepPrice, &stepPrice); err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
//请求的数量
|
||||
reqPurchaseQuantity := mapCalculateQuantity[cart.Id].PurchaseQuantity
|
||||
@ -115,16 +113,15 @@ func (l *CalculateCartPriceLogic) CalculateCartPrice(req *types.CalculateCartPri
|
||||
//如果有配件,单价也要加入配件价格
|
||||
fittingPrice := int64(0)
|
||||
if *cart.FittingId > 0 {
|
||||
if fPrice, ok := mapFitting[*cart.FittingId]; ok {
|
||||
fittingPrice = fPrice
|
||||
if fittingInfo, ok := mapModel[*cart.FittingId]; ok {
|
||||
fittingPrice = *fittingInfo.Price
|
||||
} else {
|
||||
return errors.New(fmt.Sprintf("cart contain some one witch lose fitting:%d", *cart.FittingId))
|
||||
}
|
||||
}
|
||||
//计算价格
|
||||
itemPrice, totalPrice, _, _, err := l.svcCtx.Repositories.NewShoppingCart.CaculateCartPrice(reqPurchaseQuantity, &sizePrice, fittingPrice)
|
||||
totalPrice, itemPrice, err := l.svcCtx.Repositories.NewShoppingCart.CaculateStepPrice(reqPurchaseQuantity, stepPrice, fittingPrice)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
calculateResultList = append(calculateResultList, types.CalculateResultItem{
|
||||
@ -149,6 +146,7 @@ func (l *CalculateCartPriceLogic) CalculateCartPrice(req *types.CalculateCartPri
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, err.Error())
|
||||
}
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.CalculateCartPriceRsp{
|
||||
|
||||
@ -41,37 +41,28 @@ func (l *GetCartsLogic) GetCarts(req *types.GetCartsReq, userinfo *auth.UserInfo
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please sign in")
|
||||
}
|
||||
if req.CurrentPage <= 0 {
|
||||
req.CurrentPage = constants.DEFAULT_PAGE
|
||||
}
|
||||
currentPage := constants.DEFAULT_PAGE
|
||||
limit := 300
|
||||
//获取用户购物车列表
|
||||
var cartIds []int64
|
||||
if req.CartId > 0 {
|
||||
cartIds = append(cartIds, req.CartId)
|
||||
}
|
||||
carts, total, err := l.svcCtx.AllModels.FsShoppingCart.GetAllCartsByParam(l.ctx, gmodel.GetAllCartsByParamReq{
|
||||
Ids: cartIds,
|
||||
UserId: userinfo.UserId,
|
||||
Sort: "id DESC",
|
||||
Page: req.CurrentPage,
|
||||
Page: currentPage,
|
||||
Limit: limit,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "system err:failed to get your shopping carts")
|
||||
}
|
||||
if len(carts) == 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetCartsRsp{
|
||||
Meta: types.Meta{
|
||||
TotalCount: total,
|
||||
PageCount: int64(math.Ceil(float64(total) / float64(limit))),
|
||||
CurrentPage: req.CurrentPage,
|
||||
PerPage: limit,
|
||||
},
|
||||
CartList: nil,
|
||||
})
|
||||
}
|
||||
var (
|
||||
mapSize = make(map[int64]gmodel.FsProductSize)
|
||||
mapModel = make(map[int64]gmodel.FsProductModel3d)
|
||||
mapTemplate = make(map[int64]gmodel.FsProductTemplateV2)
|
||||
mapSizePrice = make(map[string]gmodel.FsProductPrice)
|
||||
mapProduct = make(map[int64]gmodel.FsProduct)
|
||||
mapResourceMetadata = make(map[string]interface{})
|
||||
)
|
||||
@ -81,7 +72,6 @@ func (l *GetCartsLogic) GetCarts(req *types.GetCartsReq, userinfo *auth.UserInfo
|
||||
MapSize: mapSize,
|
||||
MapModel: mapModel,
|
||||
MapTemplate: mapTemplate,
|
||||
MapSizePrice: mapSizePrice,
|
||||
MapProduct: mapProduct,
|
||||
MapResourceMetadata: mapResourceMetadata,
|
||||
})
|
||||
@ -109,21 +99,34 @@ func (l *GetCartsLogic) GetCarts(req *types.GetCartsReq, userinfo *auth.UserInfo
|
||||
list := make([]types.CartItem, 0, len(carts))
|
||||
for _, cart := range carts {
|
||||
snapShot := mapSnapshot[cart.Id]
|
||||
sizePrice, ok := mapSizePrice[fmt.Sprintf("%d_%d", *cart.ProductId, *cart.SizeId)]
|
||||
modelInfo, ok := mapModel[*cart.ModelId]
|
||||
if !ok {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("the size`s price info is not exists:%d_%d", *cart.ProductId, *cart.SizeId))
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("the size`s model info is not exists:%d_%d", *cart.ProductId, *cart.SizeId))
|
||||
}
|
||||
var stepPrice gmodel.StepPriceJsonStruct
|
||||
if modelInfo.StepPrice != nil && len(*modelInfo.StepPrice) != 0 {
|
||||
if err = json.Unmarshal(*modelInfo.StepPrice, &stepPrice); err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeJsonErr, fmt.Sprintf("failed to parse model step price:%d", *cart.ModelId))
|
||||
}
|
||||
}
|
||||
//购买数量步进量
|
||||
stepPurchaseQuantity := *modelInfo.PackedUnit
|
||||
//如果有配件,单价也要加入配件价格
|
||||
fittingPrice := int64(0)
|
||||
if *cart.FittingId > 0 {
|
||||
if curFittingInfo, ok := mapModel[*cart.FittingId]; ok {
|
||||
fittingPrice = *curFittingInfo.Price
|
||||
} else {
|
||||
curFittingInfo, ok := mapModel[*cart.FittingId]
|
||||
if !ok {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("cart contain some one witch lose fitting:%d", *cart.FittingId))
|
||||
}
|
||||
fittingPrice = *curFittingInfo.Price
|
||||
//取大的为步进量基数
|
||||
if *curFittingInfo.PackedUnit > stepPurchaseQuantity {
|
||||
stepPurchaseQuantity = *curFittingInfo.PackedUnit
|
||||
}
|
||||
}
|
||||
//计算价格
|
||||
itemPrice, totalPrice, _, _, err := l.svcCtx.Repositories.NewShoppingCart.CaculateCartPrice(*cart.PurchaseQuantity, &sizePrice, fittingPrice)
|
||||
//计算阶梯价格
|
||||
totalPrice, itemPrice, err := l.svcCtx.Repositories.NewShoppingCart.CaculateStepPrice(*cart.PurchaseQuantity, stepPrice, fittingPrice)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, err.Error())
|
||||
@ -152,6 +155,10 @@ func (l *GetCartsLogic) GetCarts(req *types.GetCartsReq, userinfo *auth.UserInfo
|
||||
productCoverMetadata = metadata
|
||||
}
|
||||
}
|
||||
templateTag := ""
|
||||
if templateInfo, ok := mapTemplate[*cart.TemplateId]; ok {
|
||||
templateTag = *templateInfo.TemplateTag
|
||||
}
|
||||
item := types.CartItem{
|
||||
CartId: cart.Id,
|
||||
ProductInfo: types.ProductInfo{
|
||||
@ -183,10 +190,12 @@ func (l *GetCartsLogic) GetCarts(req *types.GetCartsReq, userinfo *auth.UserInfo
|
||||
Slogan: snapShot.UserDiyInformation.Slogan,
|
||||
},
|
||||
PurchaseQuantity: *cart.PurchaseQuantity,
|
||||
MinPurchaseQuantity: *sizePrice.EachBoxNum * (*sizePrice.MinBuyNum),
|
||||
StepPurchaseQuantity: *sizePrice.EachBoxNum,
|
||||
MinPurchaseQuantity: stepPrice.MinBuyUnitsNum,
|
||||
StepPurchaseQuantity: stepPurchaseQuantity,
|
||||
IsHighlyCustomized: *cart.IsHighlyCustomized > 0,
|
||||
IsSelected: *cart.IsSelected > 0,
|
||||
TemplateTag: templateTag,
|
||||
Logo: snapShot.Logo,
|
||||
}
|
||||
//是否有失效的
|
||||
if description, ok := mapCartChange[cart.Id]; ok {
|
||||
@ -201,7 +210,7 @@ func (l *GetCartsLogic) GetCarts(req *types.GetCartsReq, userinfo *auth.UserInfo
|
||||
Meta: types.Meta{
|
||||
TotalCount: total,
|
||||
PageCount: int64(math.Ceil(float64(total) / float64(limit))),
|
||||
CurrentPage: req.CurrentPage,
|
||||
CurrentPage: currentPage,
|
||||
PerPage: limit,
|
||||
},
|
||||
CartList: list,
|
||||
@ -214,7 +223,6 @@ type GetRelationInfoReq struct {
|
||||
MapSize map[int64]gmodel.FsProductSize
|
||||
MapModel map[int64]gmodel.FsProductModel3d
|
||||
MapTemplate map[int64]gmodel.FsProductTemplateV2
|
||||
MapSizePrice map[string]gmodel.FsProductPrice
|
||||
MapProduct map[int64]gmodel.FsProduct
|
||||
MapResourceMetadata map[string]interface{}
|
||||
}
|
||||
@ -282,15 +290,6 @@ func (l *GetCartsLogic) GetRelationInfo(req GetRelationInfoReq) error {
|
||||
for _, v := range templateList {
|
||||
req.MapTemplate[v.Id] = v
|
||||
}
|
||||
//根据sizeid获取价格列表
|
||||
priceList, err := l.svcCtx.AllModels.FsProductPrice.GetPriceListByProductIdsSizeIds(l.ctx, productIds, sizeIds)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return errors.New("failed to get cart`s product price list")
|
||||
}
|
||||
for _, v := range priceList {
|
||||
req.MapSizePrice[fmt.Sprintf("%d_%d", *v.ProductId, *v.SizeId)] = v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ type ServiceContext struct {
|
||||
AllModels *gmodel.AllModelsGen
|
||||
RabbitMq *initalize.RabbitMqHandle
|
||||
Repositories *initalize.Repositories
|
||||
AwsSession *session.Session
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
@ -24,10 +25,11 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
Credentials: credentials.NewStaticCredentials(c.AWS.S3.Credentials.AccessKeyID, c.AWS.S3.Credentials.Secret, c.AWS.S3.Credentials.Token),
|
||||
}
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
MysqlConn: conn,
|
||||
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
|
||||
RabbitMq: initalize.InitRabbitMq(c.SourceRabbitMq, nil),
|
||||
Config: c,
|
||||
MysqlConn: conn,
|
||||
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
|
||||
RabbitMq: initalize.InitRabbitMq(c.SourceRabbitMq, nil),
|
||||
AwsSession: session.Must(session.NewSession(&config)),
|
||||
Repositories: initalize.NewAllRepositories(&initalize.NewAllRepositorieData{
|
||||
GormDB: conn,
|
||||
BLMServiceUrl: &c.BLMService.Url,
|
||||
|
||||
@ -30,7 +30,7 @@ type DeleteCartReq struct {
|
||||
}
|
||||
|
||||
type GetCartsReq struct {
|
||||
CurrentPage int `form:"current_page"` //当前页
|
||||
CartId int64 `form:"cart_id,optional"` //购物车ids可选
|
||||
}
|
||||
|
||||
type GetCartsRsp struct {
|
||||
@ -53,6 +53,8 @@ type CartItem struct {
|
||||
IsInvalid bool `json:"is_invalid"` //是否无效
|
||||
InvalidDescription string `json:"invalid_description"` //无效原因
|
||||
IsSelected bool `json:"is_selected"` //是否选中
|
||||
TemplateTag string `json:"template_tag"` //模板标签
|
||||
Logo string `json:"logo"`
|
||||
}
|
||||
|
||||
type ProductInfo struct {
|
||||
|
||||
@ -67,9 +67,9 @@ var (
|
||||
//websocket连接存储
|
||||
mapConnPool = sync.Map{}
|
||||
//每个websocket连接入口缓冲队列长度默认值
|
||||
websocketInChanLen = 500
|
||||
websocketInChanLen = 2000
|
||||
//每个websocket连接出口缓冲队列长度默认值
|
||||
websocketOutChanLen = 500
|
||||
websocketOutChanLen = 2000
|
||||
//是否开启debug
|
||||
openDebug = true
|
||||
//允许跨域的origin
|
||||
@ -192,7 +192,7 @@ func (l *DataTransferLogic) setConnPool(conn *websocket.Conn, userInfo *auth.Use
|
||||
userId: userInfo.UserId,
|
||||
guestId: userInfo.GuestId,
|
||||
extendRenderProperty: extendRenderProperty{
|
||||
renderChan: make(chan []byte, renderChanLen),
|
||||
renderChan: make(chan websocket_data.RenderImageReqMsg, renderChanLen),
|
||||
},
|
||||
}
|
||||
//保存连接
|
||||
|
||||
@ -22,6 +22,8 @@ import (
|
||||
var (
|
||||
//每个websocket渲染任务缓冲队列长度默认值
|
||||
renderChanLen = 500
|
||||
//每个websocket渲染并发数
|
||||
renderChanConcurrency = 500
|
||||
)
|
||||
|
||||
// 渲染处理器
|
||||
@ -30,16 +32,25 @@ type renderProcessor struct {
|
||||
|
||||
// 云渲染属性
|
||||
type extendRenderProperty struct {
|
||||
renderChan chan []byte //渲染消息入口的缓冲队列
|
||||
renderChan chan websocket_data.RenderImageReqMsg //渲染消息入口的缓冲队列
|
||||
}
|
||||
|
||||
// 处理分发到这里的数据
|
||||
func (r *renderProcessor) allocationMessage(w *wsConnectItem, data []byte) {
|
||||
//logx.Info("开始处理渲染任务消息:", string(data))
|
||||
logx.Info("收到渲染任务消息")
|
||||
var renderImageData websocket_data.RenderImageReqMsg
|
||||
if err := json.Unmarshal(data, &renderImageData); err != nil {
|
||||
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "数据格式错误", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
|
||||
logx.Error("invalid format of websocket render image message", err)
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-w.closeChan: //已经关闭
|
||||
return
|
||||
case w.extendRenderProperty.renderChan <- data: //发入到缓冲队列
|
||||
case w.extendRenderProperty.renderChan <- renderImageData: //发入到缓冲队列
|
||||
return
|
||||
case <-time.After(time.Millisecond * 50): //超过50毫秒丢弃
|
||||
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "渲染队列溢出,请稍后再发", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -48,29 +59,37 @@ func (r *renderProcessor) allocationMessage(w *wsConnectItem, data []byte) {
|
||||
func (w *wsConnectItem) consumeRenderImageData() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logx.Error("func renderImage err:", err)
|
||||
logx.Error("func consumeRenderImageData panic:", err)
|
||||
}
|
||||
}()
|
||||
var data []byte
|
||||
//限制并发
|
||||
limitChan := make(chan struct{}, renderChanConcurrency)
|
||||
defer close(limitChan)
|
||||
for {
|
||||
select {
|
||||
case <-w.closeChan: //已关闭
|
||||
return
|
||||
case data = <-w.extendRenderProperty.renderChan: //消费数据
|
||||
w.renderImage(data)
|
||||
case data := <-w.extendRenderProperty.renderChan: //消费数据
|
||||
logx.Info("准备执行任务。。。。。")
|
||||
limitChan <- struct{}{}
|
||||
logx.Info("执行任务中。。。。。")
|
||||
go func(d websocket_data.RenderImageReqMsg) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logx.Error("func renderImage panic:", err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
<-limitChan
|
||||
}()
|
||||
w.renderImage(d)
|
||||
}(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 执行渲染任务
|
||||
func (w *wsConnectItem) renderImage(data []byte) {
|
||||
//logx.Info("消费渲染数据:", string(data))
|
||||
var renderImageData websocket_data.RenderImageReqMsg
|
||||
if err := json.Unmarshal(data, &renderImageData); err != nil {
|
||||
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "数据格式错误", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
|
||||
logx.Error("invalid format of websocket render image message", err)
|
||||
return
|
||||
}
|
||||
func (w *wsConnectItem) renderImage(renderImageData websocket_data.RenderImageReqMsg) {
|
||||
if renderImageData.RenderData.Logo == "" {
|
||||
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "请传入logo", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
|
||||
return
|
||||
@ -188,6 +207,7 @@ func (w *wsConnectItem) renderImage(data []byte) {
|
||||
logx.Error("failed to find render resource:", err)
|
||||
return
|
||||
}
|
||||
logx.Info("无缓存的渲染图,需要unity")
|
||||
} else {
|
||||
//返回给客户端
|
||||
w.sendRenderResultData(websocket_data.RenderImageRspMsg{
|
||||
|
||||
@ -12,10 +12,71 @@ import "basic.api"
|
||||
service info {
|
||||
@handler InfoHandler
|
||||
post /api/info/user(UserInfoRequest) returns (response);
|
||||
|
||||
@handler UserGetProfileHandler
|
||||
post /api/info/user/profile(QueryProfileRequest) returns (response);
|
||||
|
||||
@handler UpdateProfileBaseHandler
|
||||
post /api/info/user/profile/base/update(ProfileBaseRequest) returns (response);
|
||||
|
||||
@handler AddressDefaultHandler
|
||||
post /api/info/address/default(AddressIdRequest) returns (response);
|
||||
|
||||
@handler AddressAddHandler
|
||||
post /api/info/address/add(AddressRequest) returns (response);
|
||||
|
||||
@handler AddressUpdateHandler
|
||||
post /api/info/address/update(AddressRequest) returns (response);
|
||||
|
||||
@handler AddressDeleteHandler
|
||||
post /api/info/address/delete(AddressIdRequest) returns (response);
|
||||
|
||||
@handler AddressListHandler
|
||||
get /api/info/address/list(request) returns (response);
|
||||
}
|
||||
|
||||
type (
|
||||
UserInfoRequest {
|
||||
Module []string `json:"module"`
|
||||
}
|
||||
|
||||
AddressObjectRequest {
|
||||
AddressId int64 `json:"address_id"` // 地址id
|
||||
AddressName string `json:"address_name"` // 地址
|
||||
}
|
||||
|
||||
AddressIdRequest {
|
||||
AddressId int64 `json:"address_id"` // 地址id
|
||||
}
|
||||
|
||||
AddressNameRequest {
|
||||
AddressName string `json:"address_name"` // 地址
|
||||
}
|
||||
|
||||
AddressRequest {
|
||||
AddressId int64 `json:"address_id,optional"`
|
||||
IsDefault int64 `json:"is_default"` //是否默认
|
||||
AddressName string `json:"address_name"` //收货人
|
||||
FirstName string `json:"first_name"` //first_name
|
||||
LastName string `json:"last_name"` //last_name
|
||||
Mobile string `json:"mobile"` //手机
|
||||
ZipCode string `json:"zip_code"` //邮编
|
||||
Street string `json:"street"` //街道
|
||||
Suite string `json:"suite"` //房号
|
||||
City string `json:"city"` //城市
|
||||
State string `json:"state"` //州
|
||||
}
|
||||
|
||||
ProfileBaseRequest {
|
||||
FirstName *string `json:"first_name,optional,omitempty"` // 首名
|
||||
LastName *string `json:"last_name,optional,omitempty"` // 后名
|
||||
UserName *string `json:"user_name,optional,omitempty"` // 用户名
|
||||
Mobile *string `json:"mobile,optional,omitempty"` // 电话
|
||||
Resetaurant *string `json:"resetaurant,optional,omitempty"` // 不知道干什么
|
||||
Company *string `json:"company,optional,omitempty"` // 公司
|
||||
}
|
||||
|
||||
QueryProfileRequest {
|
||||
TopKey string `json:"top_key"` // 首名
|
||||
}
|
||||
)
|
||||
@ -33,8 +33,8 @@ type OrderDetailReq {
|
||||
}
|
||||
|
||||
type CreateOrderReq {
|
||||
CartIds []int64 `json:"cart_ids"`
|
||||
DeliveryMethod int64 `json:"delivery_method,options=[1,2]"`
|
||||
CartIds []int64 `json:"cart_ids"`
|
||||
// DeliveryMethod int64 `json:"delivery_method,optional,options=[1,2],default=2"`
|
||||
}
|
||||
|
||||
type CreatePrePaymentByDepositReq {
|
||||
|
||||
@ -11,9 +11,6 @@ import "basic.api"
|
||||
|
||||
service pay {
|
||||
|
||||
@handler OrderPaymentIntentHandler
|
||||
post /api/pay/payment-intent(OrderPaymentIntentReq) returns (response);
|
||||
|
||||
@handler OrderRefundHandler
|
||||
post /api/pay/refund(OrderRefundReq) returns (response);
|
||||
|
||||
@ -28,20 +25,6 @@ type (
|
||||
OrderRefundRes struct{}
|
||||
)
|
||||
|
||||
// 生成预付款
|
||||
type (
|
||||
OrderPaymentIntentReq {
|
||||
Sn string `form:"sn"` //订单编号
|
||||
DeliveryMethod int64 `form:"delivery_method"` //发货方式
|
||||
AddressId int64 `form:"address_id"` //地址id
|
||||
PayMethod int64 `form:"pay_method"` //支付方式
|
||||
}
|
||||
OrderPaymentIntentRes {
|
||||
RedirectUrl string `json:"redirect_url"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
}
|
||||
)
|
||||
|
||||
// StripeWebhook支付通知
|
||||
type (
|
||||
StripeWebhookReq {
|
||||
|
||||
@ -44,9 +44,15 @@ service product {
|
||||
//获取产品模型信息
|
||||
@handler GetModelByPidHandler
|
||||
get /api/product/get_model_by_pid(GetModelByPidReq) returns (response);
|
||||
//获取产品阶梯价格列表
|
||||
//获取产品阶梯价格列表(即将废弃)
|
||||
@handler GetPriceByPidHandler
|
||||
get /api/product/get_price_by_pid(GetPriceByPidReq) returns (response);
|
||||
//获取产品阶梯价格信息
|
||||
@handler GetProductStepPriceHandler
|
||||
get /api/product/get_product_step_price(GetProductStepPriceReq) returns (response);
|
||||
//根据产品+配件搭配计算价格
|
||||
@handler CalculateProductPriceHandler
|
||||
post /api/product/calculate_product_price(CalculateProductPriceReq) returns (response);
|
||||
//获取产品尺寸列表
|
||||
@handler GetSizeByPidHandler
|
||||
get /api/product/get_size_by_pid(GetSizeByPidReq) returns (response);
|
||||
@ -376,6 +382,22 @@ type PriceItem {
|
||||
TotalNum int64 `json:"total_num"`
|
||||
Price int64 `json:"price"`
|
||||
}
|
||||
//获取产品阶梯价格信息
|
||||
type GetProductStepPriceReq {
|
||||
ProductId int64 `form:"product_id"`
|
||||
}
|
||||
//根据产品+配件搭配计算价格
|
||||
type CalculateProductPriceReq {
|
||||
ProductId int64 `json:"product_id"`
|
||||
SizeId int64 `json:"size_id"`
|
||||
FittingId int64 `json:"fitting_id,optional"`
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"`
|
||||
}
|
||||
type CalculateProductPriceRsp {
|
||||
ItemPrice string `json:"item_price"`
|
||||
TotalPrice string `json:"total_price"`
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"`
|
||||
}
|
||||
//获取产品尺寸列表
|
||||
type GetSizeByPidReq {
|
||||
Pid string `form:"pid"`
|
||||
|
||||
@ -49,7 +49,7 @@ type DeleteCartReq {
|
||||
|
||||
//获取购物车列表
|
||||
type GetCartsReq {
|
||||
CurrentPage int `form:"current_page"` //当前页
|
||||
CartId int64 `form:"cart_id,optional"` //购物车ids可选
|
||||
}
|
||||
type GetCartsRsp {
|
||||
Meta Meta `json:"meta"` //分页信息
|
||||
@ -70,6 +70,8 @@ type CartItem {
|
||||
IsInvalid bool `json:"is_invalid"` //是否无效
|
||||
InvalidDescription string `json:"invalid_description"` //无效原因
|
||||
IsSelected bool `json:"is_selected"` //是否选中
|
||||
TemplateTag string `json:"template_tag"` //模板标签
|
||||
Logo string `json:"logo"`
|
||||
}
|
||||
type ProductInfo {
|
||||
ProductId int64 `json:"product_id"` //产品id
|
||||
|
||||
@ -316,8 +316,9 @@ func (l *defaultImageHandle) LogoCombine(ctx context.Context, in *LogoCombineReq
|
||||
|
||||
var resultBLM constants.BLMServiceUrlResult
|
||||
err = curl.NewClient(ctx, &curl.Config{
|
||||
BaseUrl: *l.BLMServiceUrl,
|
||||
Url: constants.BLMServiceUrlLogoCombine,
|
||||
BaseUrl: *l.BLMServiceUrl,
|
||||
Url: constants.BLMServiceUrlLogoCombine,
|
||||
RequireTimeout: time.Second * 15,
|
||||
}).PostJson(postMap, &resultBLM)
|
||||
|
||||
logc.Infof(ctx, "合图--算法请求--合图--结束时间:%v", time.Now().UTC())
|
||||
|
||||
@ -15,6 +15,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/stripe/stripe-go/v75"
|
||||
"github.com/zeromicro/go-zero/core/logc"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -34,10 +36,22 @@ type (
|
||||
Create(ctx context.Context, in *CreateReq) (res *CreateRes, err error)
|
||||
// 预支付--定金
|
||||
CreatePrePaymentByDeposit(ctx context.Context, in *CreatePrePaymentByDepositReq) (res *CreatePrePaymentByDepositRes, err error)
|
||||
// 预支付--定金
|
||||
CreatePrePaymentByBalance(ctx context.Context, in *CreatePrePaymentByBalanceReq) (res *CreatePrePaymentByBalanceRes, err error)
|
||||
// 列表
|
||||
List(ctx context.Context, in *ListReq) (res *ListRes, err error)
|
||||
// 详情
|
||||
Detail(ctx context.Context, in *DetailReq) (res *DetailRes, err error)
|
||||
// 支付成功
|
||||
PaymentSuccessful(ctx context.Context, in *PaymentSuccessfulReq) (res *PaymentSuccessfulRes, err error)
|
||||
}
|
||||
|
||||
PayInfo struct {
|
||||
PayMethod string `json:"pay_method"` // 交易方式
|
||||
PayTime time.Time `json:"pay_time"` // 支付时间
|
||||
Status gmodel.PayStatus `json:"status"` // 当前状态
|
||||
StatusLink []gmodel.PayStatus `json:"status_link"` // 状态链路
|
||||
TradeNo string `json:"trade_no"` // 支付交易号
|
||||
}
|
||||
|
||||
OrderAddress struct {
|
||||
@ -61,6 +75,16 @@ type (
|
||||
Amount int64 `json:"amount"` // 金额
|
||||
Label string `json:"label"` // 标签
|
||||
}
|
||||
|
||||
/* 支付成功 */
|
||||
PaymentSuccessfulReq struct {
|
||||
EventId string
|
||||
PaymentMethod string
|
||||
Charge *stripe.Charge
|
||||
}
|
||||
PaymentSuccessfulRes struct{}
|
||||
/* 支付成功 */
|
||||
|
||||
/* 预支付--定金 */
|
||||
CreatePrePaymentByDepositReq struct {
|
||||
StripeKey string `json:"stripe_key"`
|
||||
@ -69,7 +93,7 @@ type (
|
||||
UserId int64 `json:"user_id"`
|
||||
OrderSn string `json:"order_sn"`
|
||||
DeliveryMethod int64 `json:"delivery_method"`
|
||||
DeliveryAddress *OrderAddress `json:"delivery_address"` // 收货地址
|
||||
DeliveryAddress *OrderAddress `json:"delivery_address"`
|
||||
}
|
||||
CreatePrePaymentByDepositRes struct {
|
||||
ErrorCode basic.StatusResponse
|
||||
@ -78,6 +102,21 @@ type (
|
||||
}
|
||||
/* 预支付--定金 */
|
||||
|
||||
/* 预支付--尾款 */
|
||||
CreatePrePaymentByBalanceReq struct {
|
||||
StripeKey string `json:"stripe_key"`
|
||||
Currency string `json:"currency"`
|
||||
Country string `json:"country"`
|
||||
UserId int64 `json:"user_id"`
|
||||
OrderSn string `json:"order_sn"`
|
||||
}
|
||||
CreatePrePaymentByBalanceRes struct {
|
||||
ErrorCode basic.StatusResponse
|
||||
OrderDetail gmodel.OrderDetail
|
||||
OrderPay OrderPay
|
||||
}
|
||||
/* 预支付--尾款 */
|
||||
|
||||
/* 下单 */
|
||||
CreateReq struct {
|
||||
ExpectedDeliveryTime time.Time `json:"expected_delivery_time"` // 预计到货时间
|
||||
@ -122,6 +161,312 @@ type (
|
||||
/* 列表 */
|
||||
)
|
||||
|
||||
// 支付成功
|
||||
func (d *defaultOrder) PaymentSuccessful(ctx context.Context, in *PaymentSuccessfulReq) (res *PaymentSuccessfulRes, err error) {
|
||||
var orderSn string
|
||||
var payStage string
|
||||
var ok bool
|
||||
var card string
|
||||
var brand string
|
||||
var country string
|
||||
var currency string
|
||||
var tradeSn string
|
||||
var payAmount int64
|
||||
var payTitle string
|
||||
var payTime time.Time
|
||||
|
||||
var paymentMethod int64 = 1
|
||||
if in.PaymentMethod == "stripe" {
|
||||
paymentMethod = 1
|
||||
}
|
||||
if in.PaymentMethod == "paypal" {
|
||||
paymentMethod = 2
|
||||
}
|
||||
|
||||
if in.Charge != nil {
|
||||
charge := in.Charge
|
||||
orderSn, ok = charge.Metadata["order_sn"]
|
||||
if !ok || orderSn == "" {
|
||||
err = errors.New("order_sn is empty")
|
||||
logc.Errorf(ctx, "PaymentSuccessful failed param, eventId:%s,err:%v", in.EventId, err)
|
||||
return &PaymentSuccessfulRes{}, err
|
||||
}
|
||||
payStage, ok = charge.Metadata["pay_stage"]
|
||||
if !ok || payStage == "" {
|
||||
err = errors.New("pay_stage is empty")
|
||||
logc.Errorf(ctx, "PaymentSuccessful failed param, eventId:%s,err:%v", in.EventId, err)
|
||||
return &PaymentSuccessfulRes{}, err
|
||||
}
|
||||
country, ok = charge.Metadata["country"]
|
||||
if !ok || country == "" {
|
||||
err = errors.New("country is empty")
|
||||
logc.Errorf(ctx, "PaymentSuccessful failed param, eventId:%s,err:%v", in.EventId, err)
|
||||
return &PaymentSuccessfulRes{}, err
|
||||
}
|
||||
if charge.PaymentMethodDetails != nil {
|
||||
if charge.PaymentMethodDetails.Card != nil {
|
||||
if charge.PaymentMethodDetails.Card.Last4 != "" {
|
||||
card = charge.PaymentMethodDetails.Card.Last4
|
||||
}
|
||||
if charge.PaymentMethodDetails.Card.Brand != "" {
|
||||
brand = string(charge.PaymentMethodDetails.Card.Brand)
|
||||
}
|
||||
}
|
||||
}
|
||||
if charge.Currency != "" {
|
||||
currency = string(charge.Currency)
|
||||
}
|
||||
tradeSn = charge.ID
|
||||
payAmount = charge.Amount
|
||||
payTitle = charge.Description
|
||||
payTime = time.Unix(charge.Created, 0).UTC()
|
||||
}
|
||||
err = d.MysqlConn.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var orderInfo gmodel.FsOrder
|
||||
result := tx.Where("is_del = ?", 0).Where("order_sn = ?", orderSn).Take(&orderInfo)
|
||||
err = result.Error
|
||||
if err != nil {
|
||||
logx.Errorf("PaymentSuccessful failed order Take, eventId:%s,err: %v", in.EventId, err)
|
||||
return err
|
||||
}
|
||||
ress, err := d.OrderDetailHandler(ctx, &orderInfo, 0)
|
||||
if err != nil {
|
||||
logx.Errorf("PaymentSuccessful failed DetailOrderDetailHandler,eventId:%s, err: %v", in.EventId, err)
|
||||
return err
|
||||
}
|
||||
var ntime = time.Now().UTC()
|
||||
if (payStage == "deposit" && *orderInfo.PayStatus == int64(constants.ORDERPAYSTATUSUNPAIDDEPOSIT)) || (payStage == "remaining_balance" && *orderInfo.PayStatus == int64(constants.ORDERPAYSTATUSPAIDDEPOSIT)) {
|
||||
var payStatus = int64(constants.PAYSTATUSPAID)
|
||||
var payStageInt int64
|
||||
var orderPayStatusCode constants.OrderPayStatusCode
|
||||
// 订单状态--当前
|
||||
var status gmodel.OrderStatus
|
||||
var statusLink []gmodel.OrderStatus
|
||||
var uOrderDetail = make(map[string]interface{})
|
||||
var payInfo PayInfo
|
||||
payInfo.PayMethod = in.PaymentMethod
|
||||
payInfo.PayTime = payTime
|
||||
payInfo.TradeNo = tradeSn
|
||||
// 当前状态
|
||||
var statusCode constants.OrderStatusCode
|
||||
var statusCodePre constants.OrderStatusCode
|
||||
if payStage == "deposit" {
|
||||
if *orderInfo.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL {
|
||||
// 直邮
|
||||
statusCode = constants.ORDER_STATUS_DIRECTMAIL_ORDERED
|
||||
}
|
||||
if *orderInfo.DeliveryMethod == constants.DELIVERYMETHODDSCLOUDSTORE {
|
||||
// 云仓
|
||||
statusCode = constants.ORDER_STATUS_CLOUDSTORE_ORDERED
|
||||
}
|
||||
payStageInt = 1
|
||||
orderPayStatusCode = constants.ORDERPAYSTATUSPAIDDEPOSIT
|
||||
status = gmodel.OrderStatus{
|
||||
Ctime: &ntime,
|
||||
Utime: &ntime,
|
||||
StatusCode: statusCode,
|
||||
StatusTitle: constants.OrderStatusMessage[statusCode],
|
||||
}
|
||||
statusLink = order.UpdateOrderStatusLink(ress.OrderDetailOriginal.OrderInfo.StatusLink, gmodel.OrderStatus{
|
||||
Ctime: &ntime,
|
||||
Utime: &ntime,
|
||||
StatusCode: statusCode,
|
||||
StatusTitle: constants.OrderStatusMessage[statusCode],
|
||||
})
|
||||
payInfo.Status = gmodel.PayStatus{
|
||||
StatusCode: int64(constants.PAYSTATUSPAID),
|
||||
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSPAID],
|
||||
}
|
||||
payInfo.StatusLink = append(ress.OrderDetail.OrderAmount.Deposit.StatusLink, payInfo.Status)
|
||||
uOrderDetail["order_amount"] = struct {
|
||||
Deposit PayInfo `json:"deposit"`
|
||||
}{
|
||||
Deposit: payInfo,
|
||||
}
|
||||
}
|
||||
if payStage == "remaining_balance" {
|
||||
if *orderInfo.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL {
|
||||
// 直邮
|
||||
statusCodePre = constants.ORDER_STATUS_DIRECTMAIL_ORDERED
|
||||
statusCode = constants.ORDER_STATUS_DIRECTMAIL_ORDEREDMAINING
|
||||
}
|
||||
if *orderInfo.DeliveryMethod == constants.DELIVERYMETHODDSCLOUDSTORE {
|
||||
// 云仓
|
||||
statusCodePre = constants.ORDER_STATUS_CLOUDSTORE_ORDERED
|
||||
statusCode = constants.ORDER_STATUS_CLOUDSTORE_ORDEREDMAINING
|
||||
}
|
||||
payStageInt = 2
|
||||
orderPayStatusCode = constants.ORDERPAYSTATUSPAIDDREMAINING
|
||||
|
||||
var statusChildren []*gmodel.OrderStatus
|
||||
// 更新订单状态链路--子状态
|
||||
for oStatusLinkKey, oStatusLink := range ress.OrderDetail.OrderInfo.StatusLink {
|
||||
if oStatusLink.StatusCode == statusCodePre {
|
||||
statusChildren = append(oStatusLink.Children, &gmodel.OrderStatus{
|
||||
Ctime: &ntime,
|
||||
Utime: &ntime,
|
||||
StatusCode: statusCode,
|
||||
StatusTitle: constants.OrderStatusMessage[statusCode],
|
||||
})
|
||||
ress.OrderDetail.OrderInfo.StatusLink[oStatusLinkKey].Children = statusChildren
|
||||
}
|
||||
}
|
||||
statusLink = ress.OrderDetail.OrderInfo.StatusLink
|
||||
|
||||
if ress.OrderDetail.OrderInfo.Status.StatusCode == constants.ORDER_STATUS_DIRECTMAIL_ORDERED || ress.OrderDetail.OrderInfo.Status.StatusCode == constants.ORDER_STATUS_CLOUDSTORE_ORDERED {
|
||||
status = ress.OrderDetail.OrderInfo.Status
|
||||
status.Children = statusChildren
|
||||
}
|
||||
payInfo.Status = gmodel.PayStatus{
|
||||
StatusCode: int64(constants.PAYSTATUSPAID),
|
||||
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSPAID],
|
||||
}
|
||||
|
||||
payInfo.StatusLink = append(ress.OrderDetail.OrderAmount.RemainingBalance.StatusLink, payInfo.Status)
|
||||
uOrderDetail["order_amount"] = struct {
|
||||
RemainingBalance PayInfo `json:"remaining_balance"`
|
||||
}{
|
||||
RemainingBalance: payInfo,
|
||||
}
|
||||
}
|
||||
|
||||
// 新增交易信息
|
||||
tx.Create(&gmodel.FsOrderTrade{
|
||||
UserId: orderInfo.UserId,
|
||||
OrderSn: &orderSn,
|
||||
OrderSource: orderInfo.OrderSource,
|
||||
TradeSn: &tradeSn,
|
||||
PayAmount: &payAmount,
|
||||
PayStatus: &payStatus,
|
||||
PaymentMethod: &paymentMethod,
|
||||
PayStage: &payStageInt,
|
||||
CardSn: &card,
|
||||
CardBrand: &brand,
|
||||
Country: &country,
|
||||
Currency: ¤cy,
|
||||
Ctime: &ntime,
|
||||
Utime: &ntime,
|
||||
PayTitle: &payTitle,
|
||||
})
|
||||
var sql string
|
||||
if *orderInfo.Status == int64(constants.ORDER_STATUS_UNPAIDDEPOSIT) {
|
||||
sql = fmt.Sprintf(", `utime` = '%s', `pay_status` = %d, `status` = %d ", ntime, orderPayStatusCode, statusCode)
|
||||
} else {
|
||||
sql = fmt.Sprintf(", `utime` = '%s', `pay_status` = %d", ntime, orderPayStatusCode)
|
||||
}
|
||||
|
||||
// 更新订单信息
|
||||
uOrderDetail["pay_status"] = orderPayStatusCode
|
||||
uOrderDetail["order_info"] = struct {
|
||||
Utime *time.Time `json:"utime"`
|
||||
Status gmodel.OrderStatus `json:"status"`
|
||||
StatusLink []gmodel.OrderStatus `json:"status_link"`
|
||||
}{
|
||||
Utime: &ntime,
|
||||
Status: status,
|
||||
StatusLink: statusLink,
|
||||
}
|
||||
fmt.Printf("uOrderDetail :%+v", uOrderDetail)
|
||||
if len(uOrderDetail) > 0 {
|
||||
err = fssql.MetadataOrderPATCH(d.MysqlConn, sql, orderSn, gmodel.FsOrder{}, uOrderDetail, "id = ?", orderInfo.Id)
|
||||
if err != nil {
|
||||
logx.Errorf("PaymentSuccessful failed MetadataOrderPATCH,eventId:%s, err: %v", in.EventId, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return &PaymentSuccessfulRes{}, nil
|
||||
}
|
||||
|
||||
// 预支付--尾款
|
||||
func (d *defaultOrder) CreatePrePaymentByBalance(ctx context.Context, in *CreatePrePaymentByBalanceReq) (res *CreatePrePaymentByBalanceRes, err error) {
|
||||
var errorCode basic.StatusResponse
|
||||
var order gmodel.FsOrder
|
||||
model := d.MysqlConn.Where("is_del = ?", 0)
|
||||
if in.UserId != 0 {
|
||||
model.Where("user_id = ?", in.UserId)
|
||||
}
|
||||
if in.OrderSn != "" {
|
||||
model.Where("order_sn = ?", in.OrderSn)
|
||||
}
|
||||
result := model.Take(&order)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound
|
||||
} else {
|
||||
errorCode = *basic.CodeServiceErr
|
||||
}
|
||||
logx.Errorf("create prePayment balance failed, err: %v", err)
|
||||
return &CreatePrePaymentByBalanceRes{
|
||||
ErrorCode: errorCode,
|
||||
}, result.Error
|
||||
}
|
||||
// 非未支付
|
||||
if *order.PayStatus != int64(constants.ORDERPAYSTATUSPAIDDEPOSIT) {
|
||||
errorCode = *basic.CodeErrOrderCreatePrePaymentNoUnPaid
|
||||
err = errors.New("order balance pay status is not unPaid")
|
||||
logx.Errorf("create prePayment balance failed, err: %v", err)
|
||||
return &CreatePrePaymentByBalanceRes{
|
||||
ErrorCode: errorCode,
|
||||
}, err
|
||||
}
|
||||
|
||||
ress, err := d.OrderDetailHandler(ctx, &order, 1)
|
||||
if err != nil {
|
||||
logx.Errorf("create prePayment balance failed DetailOrderDetailHandler, err: %v", err)
|
||||
errorCode = *basic.CodeServiceErr
|
||||
return &CreatePrePaymentByBalanceRes{
|
||||
ErrorCode: errorCode,
|
||||
}, err
|
||||
}
|
||||
// 支付初始化
|
||||
amount := int64(ress.OrderDetailOriginal.OrderAmount.RemainingBalance.PayAmount.Current.CurrentAmount.(float64) / float64(10))
|
||||
payConfig := &pay.Config{}
|
||||
payConfig.Stripe.PayType = "intent"
|
||||
payConfig.Stripe.Key = in.StripeKey
|
||||
var metadata = make(map[string]string, 2)
|
||||
metadata["model"] = "product_order"
|
||||
metadata["order_sn"] = in.OrderSn
|
||||
metadata["pay_stage"] = "remaining_balance"
|
||||
metadata["country"] = in.Country
|
||||
var generatePrepaymentReq = &pay.GeneratePrepaymentReq{
|
||||
Metadata: metadata,
|
||||
ProductName: "支付尾款后期统一调整",
|
||||
Amount: amount,
|
||||
Currency: "usd",
|
||||
Quantity: 1,
|
||||
ProductDescription: "支付尾款后期统一调整",
|
||||
}
|
||||
payDriver := pay.NewPayDriver(1, payConfig)
|
||||
|
||||
prepaymentRes, err := payDriver.GeneratePrepayment(generatePrepaymentReq)
|
||||
if err != nil {
|
||||
logx.Errorf("create prePayment balance failed GeneratePrepayment, err: %v", err)
|
||||
errorCode = *basic.CodeServiceErr
|
||||
return &CreatePrePaymentByBalanceRes{
|
||||
ErrorCode: errorCode,
|
||||
}, nil
|
||||
}
|
||||
return &CreatePrePaymentByBalanceRes{
|
||||
OrderDetail: ress.OrderDetail,
|
||||
OrderPay: OrderPay{
|
||||
ClientSecret: prepaymentRes.ClientSecret,
|
||||
Country: in.Country,
|
||||
Currency: in.Currency,
|
||||
Method: payConfig.Stripe.PayType,
|
||||
OrderSn: in.OrderSn,
|
||||
PayStage: 2,
|
||||
Total: OrderPayTotal{
|
||||
Amount: amount,
|
||||
Label: "支付尾款后期统一调整",
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 预支付--定金
|
||||
func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *CreatePrePaymentByDepositReq) (res *CreatePrePaymentByDepositRes, err error) {
|
||||
var errorCode basic.StatusResponse
|
||||
@ -148,7 +493,7 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
|
||||
|
||||
// 非未支付
|
||||
if *order.PayStatus != int64(constants.ORDERPAYSTATUSUNPAIDDEPOSIT) {
|
||||
errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound
|
||||
errorCode = *basic.CodeErrOrderCreatePrePaymentNoUnPaid
|
||||
err = errors.New("order pay status is not unPaidDeposit")
|
||||
logx.Errorf("create prePayment deposit failed, err: %v", err)
|
||||
return &CreatePrePaymentByDepositRes{
|
||||
@ -161,6 +506,8 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
|
||||
ctime := *order.Ctime
|
||||
ctimeTimeOut := ctime.Add(30 * time.Minute).UTC().Unix()
|
||||
ntimeTimeOut := ntime.Unix()
|
||||
|
||||
// 测试超时支付不限制
|
||||
if ctimeTimeOut == ntimeTimeOut {
|
||||
errorCode = *basic.CodeErrOrderCreatePrePaymentTimeout
|
||||
err = errors.New("order pay timeout")
|
||||
@ -170,7 +517,7 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
|
||||
}, err
|
||||
}
|
||||
|
||||
ress, err := d.OrderDetailHandler(ctx, &order)
|
||||
ress, err := d.OrderDetailHandler(ctx, &order, 0)
|
||||
if err != nil {
|
||||
logx.Errorf("create prePayment deposit failed DetailOrderDetailHandler, err: %v", err)
|
||||
errorCode = *basic.CodeServiceErr
|
||||
@ -182,13 +529,11 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
|
||||
var uOrderDetail = make(map[string]interface{})
|
||||
|
||||
var orderAddress *gmodel.OrderAddress
|
||||
if in.DeliveryAddress != nil {
|
||||
if in.DeliveryAddress.Name != ress.OrderDetailOriginal.DeliveryAddress.Name || in.DeliveryAddress.Address != ress.OrderDetail.DeliveryAddress.Address || in.DeliveryAddress.Mobile != ress.OrderDetail.DeliveryAddress.Mobile {
|
||||
orderAddress = &gmodel.OrderAddress{
|
||||
Name: in.DeliveryAddress.Name,
|
||||
Mobile: in.DeliveryAddress.Mobile,
|
||||
Address: in.DeliveryAddress.Address,
|
||||
}
|
||||
if in.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL {
|
||||
orderAddress = &gmodel.OrderAddress{
|
||||
Name: in.DeliveryAddress.Name,
|
||||
Mobile: in.DeliveryAddress.Mobile,
|
||||
Address: in.DeliveryAddress.Address,
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,31 +568,7 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
|
||||
}
|
||||
}
|
||||
}
|
||||
// 支付初始化
|
||||
amount := int64(ress.OrderDetailOriginal.OrderAmount.Deposit.PayAmount.Current.CurrentAmount.(float64) / float64(10))
|
||||
payConfig := &pay.Config{}
|
||||
payConfig.Stripe.PayType = "intent"
|
||||
payConfig.Stripe.Key = in.StripeKey
|
||||
var generatePrepaymentReq = &pay.GeneratePrepaymentReq{
|
||||
OrderSn: in.OrderSn,
|
||||
ProductName: "支付标题",
|
||||
Amount: amount,
|
||||
Currency: "usd",
|
||||
Quantity: 1,
|
||||
ProductDescription: "支付描述",
|
||||
}
|
||||
payDriver := pay.NewPayDriver(1, payConfig)
|
||||
|
||||
prepaymentRes, err := payDriver.GeneratePrepayment(generatePrepaymentReq)
|
||||
if err != nil {
|
||||
logx.Errorf("create prePayment deposit failed GeneratePrepayment, err: %v", err)
|
||||
errorCode = *basic.CodeServiceErr
|
||||
return &CreatePrePaymentByDepositRes{
|
||||
ErrorCode: errorCode,
|
||||
}, nil
|
||||
} else {
|
||||
//uOrderDetail["order_amount"] = map[type]type
|
||||
}
|
||||
if len(uOrderDetail) > 0 {
|
||||
err = fssql.MetadataOrderPATCH(d.MysqlConn, sql, in.OrderSn, gmodel.FsOrder{}, uOrderDetail, "id = ?", order.Id)
|
||||
if err != nil {
|
||||
@ -263,6 +584,34 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
|
||||
ress.OrderDetail.OrderInfo.DeliveryMethod = in.DeliveryMethod
|
||||
ress.OrderDetail.DeliveryAddress = orderAddress
|
||||
|
||||
// 支付初始化
|
||||
amount := int64(ress.OrderDetailOriginal.OrderAmount.Deposit.PayAmount.Current.CurrentAmount.(float64) / float64(10))
|
||||
payConfig := &pay.Config{}
|
||||
payConfig.Stripe.PayType = "intent"
|
||||
payConfig.Stripe.Key = in.StripeKey
|
||||
var metadata = make(map[string]string, 2)
|
||||
metadata["model"] = "product_order"
|
||||
metadata["order_sn"] = in.OrderSn
|
||||
metadata["pay_stage"] = "deposit"
|
||||
metadata["country"] = in.Country
|
||||
var generatePrepaymentReq = &pay.GeneratePrepaymentReq{
|
||||
Metadata: metadata,
|
||||
ProductName: "支付首款",
|
||||
Amount: amount,
|
||||
Currency: "usd",
|
||||
Quantity: 1,
|
||||
ProductDescription: "支付首款",
|
||||
}
|
||||
payDriver := pay.NewPayDriver(1, payConfig)
|
||||
|
||||
prepaymentRes, err := payDriver.GeneratePrepayment(generatePrepaymentReq)
|
||||
if err != nil {
|
||||
logx.Errorf("create prePayment deposit failed GeneratePrepayment, err: %v", err)
|
||||
errorCode = *basic.CodeServiceErr
|
||||
return &CreatePrePaymentByDepositRes{
|
||||
ErrorCode: errorCode,
|
||||
}, nil
|
||||
}
|
||||
return &CreatePrePaymentByDepositRes{
|
||||
OrderDetail: ress.OrderDetail,
|
||||
OrderPay: OrderPay{
|
||||
@ -320,7 +669,7 @@ func (d *defaultOrder) List(ctx context.Context, in *ListReq) (res *ListRes, err
|
||||
return nil, result.Error
|
||||
}
|
||||
for _, order := range orderList {
|
||||
ress, err := d.OrderDetailHandler(ctx, &order)
|
||||
ress, err := d.OrderDetailHandler(ctx, &order, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -365,19 +714,21 @@ func (d *defaultOrder) Detail(ctx context.Context, in *DetailReq) (res *DetailRe
|
||||
}
|
||||
|
||||
// 是否超时支付
|
||||
ctime := *order.Ctime
|
||||
ctimeTimeOut := ctime.Add(30 * time.Minute).UTC().Unix()
|
||||
ntimeTimeOut := time.Now().UTC().Unix()
|
||||
if ctimeTimeOut < ntimeTimeOut {
|
||||
errorCode = *basic.CodeErrOrderCreatePrePaymentTimeout
|
||||
err = errors.New("order pay timeout")
|
||||
logx.Errorf("order detail failed, err: %v", err)
|
||||
return &DetailRes{
|
||||
ErrorCode: errorCode,
|
||||
}, err
|
||||
if *order.Status == int64(constants.ORDER_STATUS_UNPAIDDEPOSIT) {
|
||||
ctime := *order.Ctime
|
||||
ctimeTimeOut := ctime.Add(30 * time.Minute).UTC().Unix()
|
||||
ntimeTimeOut := time.Now().UTC().Unix()
|
||||
if ctimeTimeOut < ntimeTimeOut {
|
||||
errorCode = *basic.CodeErrOrderCreatePrePaymentTimeout
|
||||
err = errors.New("order pay timeout")
|
||||
logx.Errorf("order detail failed, err: %v", err)
|
||||
return &DetailRes{
|
||||
ErrorCode: errorCode,
|
||||
}, err
|
||||
}
|
||||
}
|
||||
|
||||
ress, err := d.OrderDetailHandler(ctx, &order)
|
||||
ress, err := d.OrderDetailHandler(ctx, &order, 1)
|
||||
if err != nil {
|
||||
logx.Errorf("order detail failed, err: %v", err)
|
||||
errorCode = *basic.CodeServiceErr
|
||||
@ -403,8 +754,8 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
resShoppingCartFind := tx.Table(gmodel.NewFsShoppingCartModel(tx).TableName()).
|
||||
Preload("ShoppingCartProduct", func(dbPreload *gorm.DB) *gorm.DB {
|
||||
return dbPreload.Table(gmodel.NewFsProductModel(tx).TableName()).Preload("CoverResource")
|
||||
}).Preload("ShoppingCartProductPriceList").
|
||||
Preload("ShoppingCartProductModel3dList").
|
||||
}).
|
||||
Preload("ShoppingCartProductModel3d").
|
||||
Preload("ShoppingCartProductModel3dFitting").
|
||||
Where("id IN ?", in.CartIds).
|
||||
Where("user_id = ?", in.UserId).
|
||||
@ -465,10 +816,6 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
for _, shoppingCart := range shoppingCartList {
|
||||
// 购物车快照
|
||||
var shoppingCartSnapshot gmodel.CartSnapshot
|
||||
// 购物车商品价格
|
||||
var shoppingCartProductPrice *gmodel.FsProductPrice
|
||||
// 购物车商品模型
|
||||
var shoppingCartProductModel3d *gmodel.FsProductModel3d
|
||||
if shoppingCart.Snapshot != nil {
|
||||
json.Unmarshal([]byte(*shoppingCart.Snapshot), &shoppingCartSnapshot)
|
||||
}
|
||||
@ -478,69 +825,21 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
errorCode.Message = "create order failed, product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
|
||||
return errors.New(errorCode.Message)
|
||||
}
|
||||
// 商品价格异常
|
||||
if len(shoppingCart.ShoppingCartProductPriceList) == 0 {
|
||||
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
|
||||
errorCode.Message = "create order failed, price of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
|
||||
return errors.New(errorCode.Message)
|
||||
} else {
|
||||
var isProductPrice bool
|
||||
for _, shoppingCartProductPriceInfo := range shoppingCart.ShoppingCartProductPriceList {
|
||||
if *shoppingCart.SizeId == *shoppingCartProductPriceInfo.SizeId {
|
||||
shoppingCartProductPrice = shoppingCartProductPriceInfo
|
||||
isProductPrice = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isProductPrice {
|
||||
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
|
||||
errorCode.Message = "create order failed, price of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
|
||||
return errors.New(errorCode.Message)
|
||||
}
|
||||
shoppingCart.ShoppingCartProductPriceList = []*gmodel.FsProductPrice{shoppingCartProductPrice}
|
||||
}
|
||||
|
||||
// 商品模型异常
|
||||
if len(shoppingCart.ShoppingCartProductModel3dList) == 0 {
|
||||
errorCode = *basic.CodeErrOrderCreatProductAccessoryAbsent
|
||||
errorCode.Message = "create order failed, accessoryof product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
|
||||
return errors.New(errorCode.Message)
|
||||
} else {
|
||||
var isProductModel bool
|
||||
for _, shoppingCartProductModel3dInfo := range shoppingCart.ShoppingCartProductModel3dList {
|
||||
if *shoppingCart.SizeId == *shoppingCartProductModel3dInfo.SizeId {
|
||||
shoppingCartProductModel3d = shoppingCartProductModel3dInfo
|
||||
isProductModel = true
|
||||
break
|
||||
}
|
||||
var stepPriceJson gmodel.StepPriceJsonStruct
|
||||
if shoppingCart.ShoppingCartProductModel3d.StepPrice != nil {
|
||||
err = json.Unmarshal(*shoppingCart.ShoppingCartProductModel3d.StepPrice, &stepPriceJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isProductModel {
|
||||
errorCode = *basic.CodeErrOrderCreatProductAccessoryAbsent
|
||||
errorCode.Message = "create order failed, accessory of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
|
||||
return errors.New(errorCode.Message)
|
||||
}
|
||||
shoppingCart.ShoppingCartProductModel3dList = []*gmodel.FsProductModel3d{shoppingCartProductModel3d}
|
||||
}
|
||||
|
||||
var stepNum []int
|
||||
var stepPrice []int
|
||||
if *shoppingCartProductPrice.StepNum == "" {
|
||||
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
|
||||
errorCode.Message = "create order failed, step num of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is failed"
|
||||
return errors.New(errorCode.Message)
|
||||
} else {
|
||||
json.Unmarshal([]byte(*shoppingCartProductPrice.StepNum), &stepNum)
|
||||
}
|
||||
if *shoppingCartProductPrice.StepPrice == "" {
|
||||
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
|
||||
errorCode.Message = "create order failed, step price of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is failed"
|
||||
return errors.New(errorCode.Message)
|
||||
} else {
|
||||
json.Unmarshal([]byte(*shoppingCartProductPrice.StepPrice), &stepPrice)
|
||||
return errors.New("shoppingCartProductModel3d.StepPrice nil")
|
||||
}
|
||||
|
||||
/* 计算价格 */
|
||||
productPrice, productTotalPrice, stepNum, stepPrice, err := NewShoppingCart(tx, nil, nil).CaculateCartPrice(*shoppingCart.PurchaseQuantity, shoppingCartProductPrice, *shoppingCart.ShoppingCartProductModel3dFitting.Price)
|
||||
productTotalPrice, productPrice, err := NewShoppingCart(tx, nil, nil).CaculateStepPrice(*shoppingCart.PurchaseQuantity, stepPriceJson, *shoppingCart.ShoppingCartProductModel3dFitting.Price)
|
||||
if err != nil {
|
||||
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
|
||||
errorCode.Message = "create order failed, step price of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is failed"
|
||||
@ -556,7 +855,32 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
if shoppingCart.ShoppingCartProduct.CoverResource != nil && shoppingCart.ShoppingCartProduct.CoverResource.Metadata != nil {
|
||||
json.Unmarshal(*shoppingCart.ShoppingCartProduct.CoverResource.Metadata, &productCoverMetadata)
|
||||
}
|
||||
orderProductList = append(orderProductList, gmodel.OrderProduct{
|
||||
snapshot, err := d.OrderDetailSnapshotHandler(ctx, shoppingCart.FsShoppingCart.Snapshot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var shoppingCartSnapshotInter = &gmodel.FsShoppingCartData{
|
||||
Id: shoppingCart.FsShoppingCart.Id,
|
||||
UserId: shoppingCart.FsShoppingCart.UserId,
|
||||
ProductId: shoppingCart.FsShoppingCart.ProductId,
|
||||
TemplateId: shoppingCart.FsShoppingCart.TemplateId,
|
||||
ModelId: shoppingCart.FsShoppingCart.ModelId,
|
||||
SizeId: shoppingCart.FsShoppingCart.SizeId,
|
||||
LightId: shoppingCart.FsShoppingCart.LightId,
|
||||
FittingId: shoppingCart.FsShoppingCart.FittingId,
|
||||
PurchaseQuantity: shoppingCart.FsShoppingCart.PurchaseQuantity,
|
||||
Snapshot: &snapshot,
|
||||
SnapshotData: shoppingCart.FsShoppingCart.Snapshot,
|
||||
IsSelected: shoppingCart.FsShoppingCart.IsSelected,
|
||||
IsHighlyCustomized: shoppingCart.FsShoppingCart.IsHighlyCustomized,
|
||||
Ctime: shoppingCart.FsShoppingCart.Ctime,
|
||||
Utime: shoppingCart.FsShoppingCart.Utime,
|
||||
}
|
||||
var purchaseQuantityInter = gmodel.PurchaseQuantity{
|
||||
Current: *shoppingCart.PurchaseQuantity,
|
||||
Initiate: *shoppingCart.PurchaseQuantity,
|
||||
}
|
||||
productInter := gmodel.OrderProduct{
|
||||
TotalPrice: order.GetAmountInfo(order.GetAmountInfoReq{
|
||||
ExchangeRate: in.ExchangeRate,
|
||||
Initiate: productTotalPrice,
|
||||
@ -565,7 +889,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
OriginalCurrency: in.OriginalCurrency,
|
||||
}),
|
||||
ExpectedDeliveryTime: &in.ExpectedDeliveryTime,
|
||||
PurchaseQuantity: *shoppingCart.PurchaseQuantity,
|
||||
PurchaseQuantity: purchaseQuantityInter,
|
||||
ProductID: *shoppingCart.ProductId,
|
||||
ProductCover: *shoppingCart.ShoppingCartProduct.Cover,
|
||||
ProductCoverMetadata: productCoverMetadata,
|
||||
@ -578,7 +902,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
OriginalCurrency: in.OriginalCurrency,
|
||||
}),
|
||||
ProductSnapshot: shoppingCart.ShoppingCartProduct,
|
||||
ShoppingCartSnapshot: &shoppingCart.FsShoppingCart,
|
||||
ShoppingCartSnapshot: shoppingCartSnapshotInter,
|
||||
ProductSn: *shoppingCart.ShoppingCartProduct.Sn,
|
||||
DiyInformation: &shoppingCartSnapshot.UserDiyInformation,
|
||||
FittingInfo: &gmodel.OrderProductFittingInfo{
|
||||
@ -593,9 +917,9 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
Cm: shoppingCartSnapshot.SizeInfo.Cm,
|
||||
},
|
||||
},
|
||||
StepNum: stepNum,
|
||||
IsHighlyCustomized: *shoppingCart.IsHighlyCustomized,
|
||||
})
|
||||
}
|
||||
orderProductList = append(orderProductList, productInter)
|
||||
}
|
||||
|
||||
subtotal = order.GetAmountInfo(order.GetAmountInfoReq{
|
||||
@ -621,6 +945,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
StatusCode: int64(constants.PAYSTATUSUNPAID),
|
||||
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSUNPAID],
|
||||
},
|
||||
StatusLink: make([]gmodel.PayStatus, 0),
|
||||
PayAmount: order.GetAmountInfo(order.GetAmountInfoReq{
|
||||
ExchangeRate: in.ExchangeRate,
|
||||
Initiate: depositInt,
|
||||
@ -637,6 +962,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
StatusCode: int64(constants.PAYSTATUSUNPAID),
|
||||
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSUNPAID],
|
||||
},
|
||||
StatusLink: make([]gmodel.PayStatus, 0),
|
||||
PayAmount: order.GetAmountInfo(order.GetAmountInfoReq{
|
||||
ExchangeRate: in.ExchangeRate,
|
||||
Initiate: remainingBalanceInt,
|
||||
@ -659,8 +985,8 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
var status = gmodel.OrderStatus{
|
||||
Ctime: &nowTime,
|
||||
Utime: &nowTime,
|
||||
StatusCode: constants.ORDERSTATUSUNPAIDDEPOSIT,
|
||||
StatusTitle: constants.OrderStatusMessage[constants.ORDERSTATUSUNPAIDDEPOSIT],
|
||||
StatusCode: constants.ORDER_STATUS_UNPAIDDEPOSIT,
|
||||
StatusTitle: constants.OrderStatusMessage[constants.ORDER_STATUS_UNPAIDDEPOSIT],
|
||||
}
|
||||
// 订单状态--链路
|
||||
var statusLink = order.GenerateOrderStatusLink(in.DeliveryMethod, nowTime, in.ExpectedDeliveryTime)
|
||||
@ -719,8 +1045,68 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 处理订单购物车快照
|
||||
func (d *defaultOrder) OrderDetailSnapshotHandler(ctx context.Context, req *string) (res map[string]interface{}, err error) {
|
||||
var snapshot map[string]interface{}
|
||||
json.Unmarshal([]byte(*req), &snapshot)
|
||||
snapshotFittingInfoData, snapshotFittingInfoEx := snapshot["fitting_info"]
|
||||
var fittingInfoMap map[string]interface{}
|
||||
if snapshotFittingInfoEx {
|
||||
var snapshotFittingInfoJson map[string]interface{}
|
||||
var fittingName string
|
||||
snapshotFittingInfo := snapshotFittingInfoData.(map[string]interface{})
|
||||
snapshotFittingInfoJsonData, snapshotFittingInfoJsonEx := snapshotFittingInfo["fitting_json"]
|
||||
if snapshotFittingInfoJsonEx {
|
||||
json.Unmarshal([]byte(snapshotFittingInfoJsonData.(string)), &snapshotFittingInfoJson)
|
||||
}
|
||||
fittingNameData, fittingNameEx := snapshotFittingInfo["fitting_name"]
|
||||
if fittingNameEx {
|
||||
fittingName = fittingNameData.(string)
|
||||
}
|
||||
fittingInfoMap = make(map[string]interface{}, 2)
|
||||
fittingInfoMap["fitting_json"] = snapshotFittingInfoJson
|
||||
fittingInfoMap["fitting_name"] = fittingName
|
||||
}
|
||||
snapshot["fitting_info"] = fittingInfoMap
|
||||
|
||||
snapshotModelInfoData, snapshotModelInfoEx := snapshot["model_info"]
|
||||
var modelInfoMap map[string]interface{}
|
||||
if snapshotModelInfoEx {
|
||||
var snapshotModelInfoJson map[string]interface{}
|
||||
snapshotModelInfo := snapshotModelInfoData.(map[string]interface{})
|
||||
snapshotModelInfoJsonData, snapshotModelInfoJsonEx := snapshotModelInfo["model_json"]
|
||||
if snapshotModelInfoJsonEx {
|
||||
json.Unmarshal([]byte(snapshotModelInfoJsonData.(string)), &snapshotModelInfoJson)
|
||||
}
|
||||
modelInfoMap = make(map[string]interface{}, 1)
|
||||
modelInfoMap["model_json"] = snapshotModelInfoJson
|
||||
}
|
||||
snapshot["model_info"] = modelInfoMap
|
||||
|
||||
snapshotTemplateInfoData, snapshotTemplateInfoEx := snapshot["template_info"]
|
||||
var templateInfoMap map[string]interface{}
|
||||
if snapshotTemplateInfoEx {
|
||||
var snapshotTemplateInfoJson map[string]interface{}
|
||||
var templateTag string
|
||||
snapshotTemplateInfo := snapshotTemplateInfoData.(map[string]interface{})
|
||||
snapshotTemplateInfoJsonData, snapshotTemplateInfoJsonEx := snapshotTemplateInfo["template_json"]
|
||||
if snapshotTemplateInfoJsonEx {
|
||||
json.Unmarshal([]byte(snapshotTemplateInfoJsonData.(string)), &snapshotTemplateInfoJson)
|
||||
}
|
||||
templateTagData, templateTagEx := snapshotTemplateInfo["template_tag"]
|
||||
if templateTagEx {
|
||||
templateTag = templateTagData.(string)
|
||||
}
|
||||
templateInfoMap = make(map[string]interface{}, 2)
|
||||
templateInfoMap["template_json"] = snapshotTemplateInfoJson
|
||||
templateInfoMap["template_tag"] = templateTag
|
||||
}
|
||||
snapshot["template_info"] = templateInfoMap
|
||||
return snapshot, nil
|
||||
}
|
||||
|
||||
// 详情处理
|
||||
func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel.FsOrder) (res *DetailRes, err error) {
|
||||
func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel.FsOrder, original int64) (res *DetailRes, err error) {
|
||||
var orderDetail gmodel.OrderDetail
|
||||
|
||||
err = json.Unmarshal(*orderInfo.Metadata, &orderDetail)
|
||||
@ -729,18 +1115,21 @@ func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel
|
||||
return nil, err
|
||||
}
|
||||
orderDetailOriginal := orderDetail
|
||||
for orderProductKey, orderProduct := range orderDetail.OrderProduct {
|
||||
orderDetail.OrderProduct[orderProductKey].TotalPrice = order.GetAmountInfoFormat(&orderProduct.TotalPrice)
|
||||
orderDetail.OrderProduct[orderProductKey].ItemPrice = order.GetAmountInfoFormat(&orderProduct.ItemPrice)
|
||||
orderDetail.OrderProduct[orderProductKey].ShoppingCartSnapshot = nil
|
||||
orderDetail.OrderProduct[orderProductKey].ProductSnapshot = nil
|
||||
if original == 1 {
|
||||
for orderProductKey, orderProduct := range orderDetail.OrderProduct {
|
||||
orderDetail.OrderProduct[orderProductKey].TotalPrice = order.GetAmountInfoFormat(&orderProduct.TotalPrice)
|
||||
orderDetail.OrderProduct[orderProductKey].TotalPrice = order.GetAmountInfoFormat(&orderProduct.TotalPrice)
|
||||
orderDetail.OrderProduct[orderProductKey].PurchaseQuantity = order.GetPurchaseQuantity(&orderProduct.PurchaseQuantity)
|
||||
orderDetail.OrderProduct[orderProductKey].ProductSnapshot = nil
|
||||
orderDetail.OrderProduct[orderProductKey].ShoppingCartSnapshot.SnapshotData = nil
|
||||
}
|
||||
orderDetail.OrderInfo.StatusLink = order.GetOrderStatusLinkUser(orderDetail.OrderInfo.DeliveryMethod, orderDetail.OrderInfo.StatusLink)
|
||||
orderDetail.OrderAmount.Deposit.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Deposit.PayAmount)
|
||||
orderDetail.OrderAmount.RemainingBalance.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.RemainingBalance.PayAmount)
|
||||
orderDetail.OrderAmount.Subtotal = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Subtotal)
|
||||
orderDetail.OrderAmount.Total = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Total)
|
||||
orderDetail.PayTimeout = time.Duration(orderDetail.OrderInfo.Ctime.Add(orderDetail.PayTimeout).UTC().Unix() - time.Now().UTC().Unix())
|
||||
}
|
||||
orderDetail.OrderInfo.StatusLink = order.GetOrderStatusLinkUser(orderDetail.OrderInfo.DeliveryMethod, orderDetail.OrderInfo.StatusLink)
|
||||
orderDetail.OrderAmount.Deposit.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Deposit.PayAmount)
|
||||
orderDetail.OrderAmount.RemainingBalance.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.RemainingBalance.PayAmount)
|
||||
orderDetail.OrderAmount.Subtotal = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Subtotal)
|
||||
orderDetail.OrderAmount.Total = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Total)
|
||||
orderDetail.PayTimeout = time.Duration(orderDetail.OrderInfo.Ctime.Add(orderDetail.PayTimeout).UTC().Unix() - time.Now().UTC().Unix())
|
||||
|
||||
return &DetailRes{
|
||||
OrderDetail: orderDetail,
|
||||
|
||||
@ -3,15 +3,10 @@ package repositories
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/format"
|
||||
"fusenapi/utils/hash"
|
||||
"fusenapi/utils/step_price"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"gorm.io/gorm"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -33,7 +28,7 @@ type (
|
||||
// 校验订单
|
||||
VerifyShoppingCartSnapshotDataChange(req VerifyShoppingCartSnapshotDataChangeReq) error
|
||||
//计算购物车价格
|
||||
CaculateCartPrice(purchaseQuantity int64, productPrice *gmodel.FsProductPrice, fittingPrice int64) (ItemPrice, totalPrice int64, stepNum, stepPrice []int, err error)
|
||||
CaculateStepPrice(purchaseQuantity int64, stepPrice gmodel.StepPriceJsonStruct, fittingPrice int64) (totalPrice, itemPrice int64, err error)
|
||||
}
|
||||
)
|
||||
|
||||
@ -132,33 +127,23 @@ func (d *defaultShoppingCart) VerifyShoppingCartSnapshotDataChange(req VerifySho
|
||||
}
|
||||
|
||||
// 计算价格
|
||||
func (d *defaultShoppingCart) CaculateCartPrice(purchaseQuantity int64, productPrice *gmodel.FsProductPrice, fittingPrice int64) (ItemPrice, totalPrice int64, stepNum, stepPrice []int, err error) {
|
||||
//阶梯数量切片
|
||||
stepNum, err = format.StrSlicToIntSlice(strings.Split(*productPrice.StepNum, ","))
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return 0, 0, nil, nil, errors.New(fmt.Sprintf("failed to parse step number:%d_%d", *productPrice.ProductId, *productPrice.SizeId))
|
||||
func (d *defaultShoppingCart) CaculateStepPrice(purchaseQuantity int64, stepPrice gmodel.StepPriceJsonStruct, fittingPrice int64) (totalPrice, itemPrice int64, err error) {
|
||||
l := len(stepPrice.PriceRange)
|
||||
if l == 0 {
|
||||
return 0, 0, errors.New("price range is not set")
|
||||
}
|
||||
lenStepNum := len(stepNum)
|
||||
//阶梯价格切片
|
||||
stepPrice, err = format.StrSlicToIntSlice(strings.Split(*productPrice.StepPrice, ","))
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return 0, 0, nil, nil, errors.New(fmt.Sprintf("failed to parse step price:%d_%d", *productPrice.ProductId, *productPrice.SizeId))
|
||||
//遍历查询合适的价格
|
||||
for k, v := range stepPrice.PriceRange {
|
||||
//购买数量>起点
|
||||
if purchaseQuantity > v.StartQuantity {
|
||||
//最后一个 || 小于等于终点
|
||||
if k == l-1 || purchaseQuantity <= v.EndQuantity {
|
||||
itemPrice = v.Price + fittingPrice
|
||||
return itemPrice * purchaseQuantity, itemPrice, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
lenStepPrice := len(stepPrice)
|
||||
if lenStepPrice == 0 || lenStepNum == 0 {
|
||||
return 0, 0, nil, nil, errors.New(fmt.Sprintf("step price or step number is not set:%d_%d", *productPrice.ProductId, *productPrice.SizeId))
|
||||
}
|
||||
//请求的数量
|
||||
reqPurchaseQuantity := purchaseQuantity
|
||||
//购买箱数
|
||||
boxQuantity := int(math.Ceil(float64(reqPurchaseQuantity) / float64(*productPrice.EachBoxNum)))
|
||||
//根据数量获取阶梯价格中对应的价格
|
||||
itemPrice := step_price.GetCentStepPrice(boxQuantity, stepNum, stepPrice)
|
||||
//如果有配件,单价也要加入配件价格
|
||||
itemPrice += fittingPrice
|
||||
//单个购物车总价
|
||||
totalPrice = itemPrice * reqPurchaseQuantity
|
||||
return itemPrice, totalPrice, stepNum, stepPrice, nil
|
||||
//遍历里面没有则返回第一个
|
||||
itemPrice = stepPrice.PriceRange[0].Price + fittingPrice
|
||||
return itemPrice * purchaseQuantity, itemPrice, nil
|
||||
}
|
||||
|
||||
@ -107,9 +107,10 @@ var (
|
||||
CodeErrOrderCreatProductPriceAbsent = &StatusResponse{5304, "create order failed, price of product is absent"} // 订单创建失败,商品价格不存在
|
||||
CodeErrOrderCreatProductAccessoryAbsent = &StatusResponse{5305, "create order failed, accessory of product is absent"} // 订单创建失败,商品配件不存在
|
||||
CodeErrOrderCreatePrePaymentParam = &StatusResponse{5306, "create payment failed, the shipping address is illegal"} // 订单创建失败,商品配件不存在
|
||||
CodeErrOrderCreatePrePaymentInfoNoFound = &StatusResponse{5307, "create payment failed, order info not found"}
|
||||
CodeErrOrderCreatePrePaymentPaidDeposit = &StatusResponse{5308, "create payment failed, order is paid"}
|
||||
CodeErrOrderCreatePrePaymentTimeout = &StatusResponse{5309, "create payment failed, timeout"}
|
||||
CodeErrOrderCreatePrePaymentInfoNoFound = &StatusResponse{5307, "order info not found"}
|
||||
CodeErrOrderCreatePrePaymentNoUnPaid = &StatusResponse{5308, "create payment failed, order is not unpaid"}
|
||||
CodeErrOrderCreatePrePaymentPaid = &StatusResponse{5309, "create payment failed, order is paid"}
|
||||
CodeErrOrderCreatePrePaymentTimeout = &StatusResponse{5310, "create payment failed, timeout"}
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
|
||||
@ -20,8 +20,9 @@ func NewClient(ctx context.Context, c *Config) Client {
|
||||
client := resty.New().SetBaseURL(c.BaseUrl)
|
||||
|
||||
// 设置超时时间为 5 分钟
|
||||
client.SetTimeout(5 * time.Minute)
|
||||
|
||||
if c.RequireTimeout == 0 {
|
||||
client.SetTimeout(5 * time.Minute)
|
||||
}
|
||||
/* 传输链路 */
|
||||
tracer := otel.GetTracerProvider().Tracer(trace.TraceName)
|
||||
spanCtx, span := tracer.Start(
|
||||
@ -60,11 +61,12 @@ func NewClient(ctx context.Context, c *Config) Client {
|
||||
|
||||
type (
|
||||
Config struct {
|
||||
BaseUrl string `json:"base_url"`
|
||||
Url string `json:"url"`
|
||||
HeaderData map[string]string `json:"header_data"`
|
||||
RetryCount int64 `json:"retry_count"`
|
||||
RetryWaitTime int64 `json:"retry_wait_time"`
|
||||
BaseUrl string `json:"base_url"`
|
||||
Url string `json:"url"`
|
||||
HeaderData map[string]string `json:"header_data"`
|
||||
RetryCount int64 `json:"retry_count"`
|
||||
RetryWaitTime int64 `json:"retry_wait_time"`
|
||||
RequireTimeout time.Duration `json:"require_timeout"`
|
||||
}
|
||||
defaultClient struct {
|
||||
c *Config
|
||||
|
||||
25
utils/format/number.go
Normal file
25
utils/format/number.go
Normal file
@ -0,0 +1,25 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 数字变成带千分位的字符串
|
||||
func NumToStringWithThousandthPercentile(number int64) string {
|
||||
s := fmt.Sprintf("%d", number)
|
||||
l := len(s)
|
||||
if l <= 3 {
|
||||
return s
|
||||
}
|
||||
r := l % 3 //前面第几位开始加入千分位
|
||||
b := strings.Builder{}
|
||||
for i := 0; i < l; i++ {
|
||||
b.WriteString(string(s[i]))
|
||||
if i+1 == r && i != l-1 {
|
||||
b.WriteString(",")
|
||||
r += 3
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
@ -59,7 +59,7 @@ func MetadataModulePATCH(tx *gorm.DB, module string, tableStructPointer any, upd
|
||||
WHEN metadata IS NULL THEN ?
|
||||
ELSE JSON_MERGE_PATCH(metadata, ?)
|
||||
END
|
||||
WHERE order_sn = '%s' and %s;`
|
||||
WHERE module = '%s' and %s;`
|
||||
|
||||
var err error
|
||||
var metadata []byte
|
||||
@ -191,3 +191,12 @@ func MetadataOrderPATCH(tx *gorm.DB, sql string, orderSn string, tableStructPoin
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetGormTableName(tx *gorm.DB, tableStructPointer any) string {
|
||||
stype := reflect.TypeOf(tableStructPointer)
|
||||
if stype.Kind() == reflect.Pointer {
|
||||
stype = stype.Elem()
|
||||
}
|
||||
tname := tx.NamingStrategy.TableName(stype.Name())
|
||||
return tname
|
||||
}
|
||||
|
||||
@ -8,10 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func TestCase1(t *testing.T) {
|
||||
u := gmodel.UserProfile{
|
||||
FirstName: "h",
|
||||
LastName: "sm",
|
||||
}
|
||||
u := gmodel.UserProfile{}
|
||||
|
||||
conn := initalize.InitMysql("fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen")
|
||||
err := fssql.MetadataModulePATCH(conn, "profile", gmodel.FsUserInfo{}, u, "id = ?", 90)
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"fusenapi/constants"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/format"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -112,6 +113,14 @@ func GetAmountInfoFormat(req *gmodel.AmountInfo) gmodel.AmountInfo {
|
||||
}
|
||||
}
|
||||
|
||||
// 处理商品数量
|
||||
func GetPurchaseQuantity(req *gmodel.PurchaseQuantity) gmodel.PurchaseQuantity {
|
||||
return gmodel.PurchaseQuantity{
|
||||
Initiate: strconv.FormatInt(int64(req.Initiate.(float64)), 10),
|
||||
Current: strconv.FormatInt(int64(req.Current.(float64)), 10),
|
||||
}
|
||||
}
|
||||
|
||||
// 生成订单编号
|
||||
func GenerateOrderNumber() string {
|
||||
t := time.Now()
|
||||
@ -120,7 +129,7 @@ func GenerateOrderNumber() string {
|
||||
return orderNumber
|
||||
}
|
||||
|
||||
// 初始化订单状态
|
||||
// 初始化订单状态--链路
|
||||
func GenerateOrderStatusLink(deliveryMethod int64, noTime time.Time, expectedTime time.Time) []gmodel.OrderStatus {
|
||||
var list []gmodel.OrderStatus
|
||||
|
||||
@ -142,6 +151,42 @@ func GenerateOrderStatusLink(deliveryMethod int64, noTime time.Time, expectedTim
|
||||
return list
|
||||
}
|
||||
|
||||
// 更新订单状态--链路
|
||||
func UpdateOrderStatusLink(statusLink []gmodel.OrderStatus, status gmodel.OrderStatus) []gmodel.OrderStatus {
|
||||
var list []gmodel.OrderStatus
|
||||
for _, v := range statusLink {
|
||||
if v.StatusCode == status.StatusCode {
|
||||
item := v
|
||||
if status.StatusTitle != "" {
|
||||
item.StatusTitle = status.StatusTitle
|
||||
}
|
||||
if status.StatusCode != 0 {
|
||||
item.StatusCode = status.StatusCode
|
||||
}
|
||||
if status.Utime != nil {
|
||||
item.Utime = status.Utime
|
||||
}
|
||||
if status.Ctime != nil {
|
||||
item.Ctime = status.Ctime
|
||||
}
|
||||
if status.Metadata != nil {
|
||||
item.Metadata = status.Metadata
|
||||
}
|
||||
if status.ExpectedTime != nil {
|
||||
item.ExpectedTime = status.ExpectedTime
|
||||
}
|
||||
if status.Children != nil || len(status.Children) > 0 {
|
||||
item.Children = status.Children
|
||||
}
|
||||
|
||||
list = append(list, item)
|
||||
} else {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// 获取订单状态
|
||||
func GetOrderStatusLinkUser(deliveryMethod int64, statusLink []gmodel.OrderStatus) []gmodel.OrderStatus {
|
||||
var list []gmodel.OrderStatus
|
||||
|
||||
@ -29,15 +29,15 @@ type Pay interface {
|
||||
}
|
||||
|
||||
type GeneratePrepaymentReq struct {
|
||||
OrderSn string `json:"order_sn"` // 订单编号
|
||||
Amount int64 `json:"amount"` // 支付金额
|
||||
Currency string `json:"currency"` // 支付货币
|
||||
ProductName string `json:"product_name"` // 商品名称
|
||||
ProductDescription string `json:"product_description"` // 商品描述
|
||||
ProductImages []*string `json:"product_imageso"` // 商品照片
|
||||
Quantity int64 `json:"quantity"` //数量
|
||||
SuccessURL string `json:"success_url"` // 支付成功回调
|
||||
CancelURL string `json:"cancel_url"` // 支付取消回调
|
||||
Metadata map[string]string `json:"metadata"` // 元数据
|
||||
Amount int64 `json:"amount"` // 支付金额
|
||||
Currency string `json:"currency"` // 支付货币
|
||||
ProductName string `json:"product_name"` // 商品名称
|
||||
ProductDescription string `json:"product_description"` // 商品描述
|
||||
ProductImages []*string `json:"product_imageso"` // 商品照片
|
||||
Quantity int64 `json:"quantity"` //数量
|
||||
SuccessURL string `json:"success_url"` // 支付成功回调
|
||||
CancelURL string `json:"cancel_url"` // 支付取消回调
|
||||
}
|
||||
|
||||
type GeneratePrepaymentRes struct {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package pay
|
||||
|
||||
import (
|
||||
"github.com/stripe/stripe-go/v74"
|
||||
"github.com/stripe/stripe-go/v74/checkout/session"
|
||||
"github.com/stripe/stripe-go/v74/paymentintent"
|
||||
"github.com/stripe/stripe-go/v74/refund"
|
||||
"github.com/stripe/stripe-go/v75"
|
||||
"github.com/stripe/stripe-go/v75/checkout/session"
|
||||
"github.com/stripe/stripe-go/v75/paymentintent"
|
||||
"github.com/stripe/stripe-go/v75/refund"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
@ -50,7 +50,7 @@ func (stripePay *Stripe) GeneratePrepayment(req *GeneratePrepaymentReq) (res *Ge
|
||||
case "session":
|
||||
// session 方式
|
||||
params := &stripe.CheckoutSessionParams{
|
||||
PaymentIntentData: &stripe.CheckoutSessionPaymentIntentDataParams{Metadata: map[string]string{"order_sn": req.OrderSn}},
|
||||
PaymentIntentData: &stripe.CheckoutSessionPaymentIntentDataParams{Metadata: req.Metadata},
|
||||
// Params: stripe.Params{Metadata: map[string]string{"order_id": "1111111111111"}},
|
||||
PaymentMethodTypes: stripe.StringSlice([]string{
|
||||
"card",
|
||||
@ -86,6 +86,9 @@ func (stripePay *Stripe) GeneratePrepayment(req *GeneratePrepaymentReq) (res *Ge
|
||||
// "ideal",
|
||||
}),
|
||||
}
|
||||
for key, item := range req.Metadata {
|
||||
params.AddMetadata(key, item)
|
||||
}
|
||||
resPaymentintent, err := paymentintent.New(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -1,22 +1,6 @@
|
||||
package step_price
|
||||
|
||||
// 返回美元
|
||||
func GetStepPrice(minBuyNum int, stepNum []int, stepPrice []int) float64 {
|
||||
if minBuyNum > stepNum[len(stepNum)-1] {
|
||||
return float64(stepPrice[len(stepPrice)-1]) / float64(1000)
|
||||
}
|
||||
for k, v := range stepNum {
|
||||
if minBuyNum <= v {
|
||||
if k <= (len(stepPrice) - 1) {
|
||||
return float64(stepPrice[k]) / float64(1000)
|
||||
}
|
||||
return float64(stepPrice[len(stepPrice)-1]) / float64(1000)
|
||||
}
|
||||
}
|
||||
return float64(stepPrice[len(stepPrice)-1]) / float64(1000)
|
||||
}
|
||||
|
||||
// 返回厘
|
||||
// 旧的返回厘(即将废弃)
|
||||
func GetCentStepPrice(minBuyNum int, stepNum []int, stepPrice []int) int64 {
|
||||
if minBuyNum > stepNum[len(stepNum)-1] {
|
||||
return int64(stepPrice[len(stepPrice)-1])
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user