Compare commits

...

197 Commits

Author SHA1 Message Date
momo
b9b7309edc Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 18:47:08 +08:00
momo
d22be1d676 fix:支付 2023-09-26 18:46:44 +08:00
laodaming
2d0b23e063 fix 2023-09-26 18:38:36 +08:00
laodaming
01b78a099a fix 2023-09-26 18:35:27 +08:00
momo
fcfea291e5 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 18:21:13 +08:00
momo
9c08acc97a fix:支付 2023-09-26 18:20:48 +08:00
momo
1203c087d8 fix:支付 2023-09-26 18:18:48 +08:00
eson
91c1c580f9 info get profile 2023-09-26 18:03:29 +08:00
eson
b571b1b31c info get profile 2023-09-26 17:57:54 +08:00
eson
62565fac4e Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-26 17:45:12 +08:00
eson
54613f5be0 info get profile 2023-09-26 17:45:07 +08:00
momo
dd8b864a7f Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 17:32:30 +08:00
momo
8d3fce919f fix:支付 2023-09-26 17:32:21 +08:00
eson
c880cba0a3 info get profile 2023-09-26 17:21:01 +08:00
eson
194dc50eaa info get profile 2023-09-26 17:20:44 +08:00
momo
ee6e31473e Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 17:18:20 +08:00
momo
0989faf35a fix:支付 2023-09-26 17:18:04 +08:00
eson
93b0cadea9 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-26 17:16:15 +08:00
eson
f387e46977 info get profile 2023-09-26 17:16:10 +08:00
momo
c46d9d8fd9 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 17:12:27 +08:00
momo
ad01dbc0e5 fix:支付 2023-09-26 17:12:12 +08:00
laodaming
26389bf4d6 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 17:08:56 +08:00
laodaming
15888a953b fix 2023-09-26 17:08:49 +08:00
momo
2c995e9512 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 17:04:45 +08:00
momo
44fd4f03e3 fix:支付 2023-09-26 17:04:27 +08:00
laodaming
76f4a682ac fix 2023-09-26 17:01:31 +08:00
momo
9e6f919fa8 fix:支付 2023-09-26 16:53:34 +08:00
laodaming
e2508cc347 fix 2023-09-26 16:40:13 +08:00
laodaming
d07350969f fix 2023-09-26 16:36:35 +08:00
momo
6e9f47ff85 fix:支付 2023-09-26 16:30:51 +08:00
laodaming
42bd585fe9 fix 2023-09-26 16:20:53 +08:00
momo
f20b4fad3e fix:支付 2023-09-26 16:16:58 +08:00
laodaming
871a7a278b Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 15:30:20 +08:00
momo
83dc607ec4 fix:支付 2023-09-26 15:29:33 +08:00
laodaming
fae365d59e Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 15:28:27 +08:00
laodaming
821cbb8879 fix 2023-09-26 15:28:17 +08:00
momo
821e36281a fix:支付 2023-09-26 15:25:05 +08:00
momo
ef522551e4 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 15:14:12 +08:00
momo
c7a2cf7d1c fix:支付 2023-09-26 15:14:08 +08:00
eson
4dfeebeaed Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-26 15:02:13 +08:00
eson
31debda97f info update profile 2023-09-26 15:02:09 +08:00
laodaming
a1d78b7a0c fix 2023-09-26 14:56:32 +08:00
laodaming
03cbe2894e fix 2023-09-26 14:48:49 +08:00
laodaming
82fc0f2b80 fix 2023-09-26 14:46:12 +08:00
laodaming
2747c9ddd9 fix 2023-09-26 14:38:34 +08:00
laodaming
d45a0eb680 fix 2023-09-26 14:23:09 +08:00
momo
4cd2e1ce65 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 13:54:51 +08:00
momo
00b3a974f9 fix:支付 2023-09-26 13:54:39 +08:00
eson
f9595aad3f info fix table 2023-09-26 13:31:42 +08:00
eson
85cd2bff8d Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-26 13:23:55 +08:00
eson
1e444ca616 info delete table 2023-09-26 13:23:49 +08:00
laodaming
1543e60301 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 13:06:59 +08:00
laodaming
600a6edd7b fix 2023-09-26 13:06:51 +08:00
eson
407ba29319 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-26 12:24:14 +08:00
eson
c42c37f65e info address 2023-09-26 12:24:09 +08:00
momo
cdeec5a4e1 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 12:21:30 +08:00
momo
94088b5aa4 fix:支付 2023-09-26 12:21:26 +08:00
laodaming
e23ee6518d fix 2023-09-26 12:12:50 +08:00
eson
79120e1fd9 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-26 12:08:57 +08:00
eson
6a41be4f3a info address 2023-09-26 12:08:51 +08:00
laodaming
f7992279e2 fix 2023-09-26 11:47:31 +08:00
laodaming
01cc115a60 fix 2023-09-26 11:40:27 +08:00
eson
47a1ecfc79 info address 2023-09-26 11:32:43 +08:00
eson
55a4526536 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-26 11:21:48 +08:00
eson
7eab65be87 info address 2023-09-26 11:21:43 +08:00
laodaming
fc302ad1be Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 11:11:58 +08:00
eson
87c2d7bf96 info address 2023-09-26 11:11:34 +08:00
laodaming
27f429cdec Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 11:11:27 +08:00
laodaming
f615e4fe77 fix 2023-09-26 11:10:41 +08:00
eson
87ff25a2e6 info address 2023-09-26 11:08:32 +08:00
eson
a832a6fa81 info address 2023-09-26 11:07:45 +08:00
eson
0e282e741b info address 2023-09-26 11:06:37 +08:00
eson
d0323646c5 info address 2023-09-26 11:05:31 +08:00
eson
2331979b65 info address 2023-09-26 11:04:12 +08:00
eson
c12675698b info address 2023-09-26 11:01:42 +08:00
eson
abdf8a43e7 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-26 10:58:28 +08:00
eson
3bba720f67 info address 2023-09-26 10:58:24 +08:00
momo
46f3b2ff0e Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-26 10:57:08 +08:00
momo
6c2fba2b3a fix:支付 2023-09-26 10:56:57 +08:00
laodaming
916e050585 fix 2023-09-26 10:54:11 +08:00
eson
5b3e3f047e info address 2023-09-26 10:45:53 +08:00
b03e2d020f info address 2023-09-26 00:02:50 +08:00
laodaming
cb9b8ed6fd Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-25 18:44:54 +08:00
laodaming
7490a3b324 fix 2023-09-25 18:44:47 +08:00
eson
3f4b341c33 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-25 18:42:53 +08:00
eson
cef9dfa34d info 2023-09-25 18:42:45 +08:00
momo
95cbaea69a fix:支付 2023-09-25 18:28:53 +08:00
momo
17b98f83ff fix:支付 2023-09-25 17:35:02 +08:00
momo
4261a5a97d fix:支付 2023-09-25 17:31:42 +08:00
laodaming
91acf4d2bc fix 2023-09-25 17:22:58 +08:00
laodaming
f713124154 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-25 17:21:37 +08:00
laodaming
4bbe9aaaa3 fix 2023-09-25 17:20:44 +08:00
momo
07185fdb46 fix:支付 2023-09-25 17:17:09 +08:00
momo
178cda5402 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-25 17:06:35 +08:00
momo
3c094cf201 fix:支付 2023-09-25 17:06:12 +08:00
eson
66084f9e96 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-25 16:01:34 +08:00
eson
c1203e8989 info 2023-09-25 16:01:28 +08:00
momo
5be1edfa71 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-25 16:01:03 +08:00
momo
6005f20c5e fix:支付 2023-09-25 16:00:50 +08:00
eson
8fe6e8be74 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-25 15:58:40 +08:00
eson
f2a0c7608e info 2023-09-25 15:58:33 +08:00
laodaming
29c7dc54e3 fix 2023-09-25 15:49:59 +08:00
laodaming
d8d91e9270 fix 2023-09-25 11:34:53 +08:00
laodaming
02b3788dc9 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-25 11:17:03 +08:00
laodaming
a7f21da8da fix 2023-09-25 11:16:55 +08:00
momo
287ee4db37 fix:支付 2023-09-22 17:39:20 +08:00
momo
0a4368ba7f Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 17:32:30 +08:00
momo
656d5038fe fix:支付 2023-09-22 17:32:23 +08:00
laodaming
c34811df83 fix 2023-09-22 17:21:40 +08:00
laodaming
98bc6294e6 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 17:04:08 +08:00
laodaming
2054b9ec97 fix 2023-09-22 17:04:01 +08:00
momo
b398da58e1 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 16:27:21 +08:00
momo
7e400ed761 fix:支付 2023-09-22 16:27:17 +08:00
laodaming
bea1fd230a Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 15:52:40 +08:00
laodaming
a2b7bfb253 fix 2023-09-22 15:52:32 +08:00
eson
646c04eba9 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 15:52:26 +08:00
eson
1bd2b83bca info 2023-09-22 15:52:20 +08:00
laodaming
d6134a7407 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 15:43:49 +08:00
laodaming
c3011e87eb fix 2023-09-22 15:43:42 +08:00
eson
e811bf3e4a Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 15:42:15 +08:00
eson
b3ed5703a8 info 2023-09-22 15:42:09 +08:00
laodaming
f6e073bb41 fix 2023-09-22 15:24:16 +08:00
laodaming
b6651c4bdc fix 2023-09-22 15:19:41 +08:00
laodaming
bfea40c643 fix 2023-09-22 15:12:44 +08:00
laodaming
c8a52321a5 fix 2023-09-22 15:00:08 +08:00
laodaming
129583d19a fix 2023-09-22 14:57:56 +08:00
laodaming
c2bb174574 fix 2023-09-22 14:44:55 +08:00
laodaming
551f9083e9 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 14:38:32 +08:00
laodaming
c36c8ab6f9 fix 2023-09-22 14:38:26 +08:00
eson
6fd3bc8a3b Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 14:34:46 +08:00
eson
4005af2040 info 2023-09-22 14:34:23 +08:00
laodaming
20150a81b5 fix 2023-09-22 14:33:16 +08:00
laodaming
e4c165cd18 fix 2023-09-22 14:29:21 +08:00
laodaming
366a441cf2 fix 2023-09-22 14:14:04 +08:00
eson
ec4fe76856 info 2023-09-22 13:37:23 +08:00
eson
173fa23e80 info 2023-09-22 13:35:05 +08:00
eson
b6e994844e info 2023-09-22 13:21:06 +08:00
eson
9a4899558e info 2023-09-22 13:18:31 +08:00
eson
b1675ae0bf info 2023-09-22 13:14:53 +08:00
eson
8b81308bd2 info 2023-09-22 12:31:24 +08:00
eson
cc7d7361d4 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 12:28:42 +08:00
eson
730491ffed info 2023-09-22 12:28:38 +08:00
laodaming
9753920595 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 12:15:23 +08:00
laodaming
2fc914214c fix 2023-09-22 12:15:16 +08:00
momo
ddb4ec944d Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 12:12:44 +08:00
momo
c2723861fa fix:支付 2023-09-22 12:12:33 +08:00
eson
c82ae399b7 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 12:09:47 +08:00
eson
c163cfe234 info 2023-09-22 12:09:41 +08:00
laodaming
72e75e7858 fix 2023-09-22 12:05:20 +08:00
laodaming
c9af4fb420 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 12:05:17 +08:00
laodaming
27ae48991c fix 2023-09-22 12:05:05 +08:00
eson
65a7d530cc Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 12:03:11 +08:00
eson
7866a5a369 proxyserver 2023-09-22 12:03:04 +08:00
laodaming
0dcaf2ce09 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 11:59:44 +08:00
laodaming
dd6b80ee71 fix 2023-09-22 11:59:37 +08:00
eson
4c944c8c72 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 11:55:45 +08:00
eson
e29e8d8049 proxyserver 2023-09-22 11:55:39 +08:00
laodaming
e1094b9be6 fix 2023-09-22 11:47:32 +08:00
eson
fc50bf587f Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 11:46:02 +08:00
eson
11cee190b0 nacos config 2023-09-22 11:45:56 +08:00
laodaming
21c4907e44 fix 2023-09-22 11:37:44 +08:00
laodaming
951635e7f8 fix 2023-09-22 11:36:38 +08:00
laodaming
2a849dde38 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 11:36:16 +08:00
laodaming
caf2f753a5 fix 2023-09-22 11:36:10 +08:00
eson
2d224c0d67 nacos config 2023-09-22 11:35:40 +08:00
eson
e925d8c684 nacos config 2023-09-22 11:32:16 +08:00
eson
a6a40a2ad5 nacos config 2023-09-22 11:31:39 +08:00
eson
baa0cc1644 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 11:27:24 +08:00
eson
db7d53532a nacos config 2023-09-22 11:27:19 +08:00
laodaming
6985b76e49 fix 2023-09-22 11:25:51 +08:00
laodaming
745cea9617 fix 2023-09-22 11:22:32 +08:00
momo
d00089c625 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 11:01:03 +08:00
momo
0f7514b5bd fix:支付 2023-09-22 11:00:54 +08:00
eson
95cd86d103 Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 10:53:10 +08:00
eson
85b391a4d2 nacos config 2023-09-22 10:53:05 +08:00
laodaming
e2db17c326 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 10:49:15 +08:00
laodaming
741963275e fix 2023-09-22 10:49:07 +08:00
eson
541627183b Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop 2023-09-22 10:44:09 +08:00
eson
cd6a919145 nacos config 2023-09-22 10:44:04 +08:00
laodaming
bb645ce6f6 fix 2023-09-22 10:41:38 +08:00
momo
1040f21ca6 Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop 2023-09-22 10:39:09 +08:00
momo
fead7c6ae9 fix:支付 2023-09-22 10:39:02 +08:00
eson
15f589c09d nacos config 2023-09-22 10:37:34 +08:00
c4b4b72947 fix 2023-09-22 00:46:05 +08:00
99f785a7c3 fix 2023-09-22 00:35:10 +08:00
c280a661a1 fix 2023-09-22 00:31:58 +08:00
b37c2094ed fix 2023-09-22 00:28:35 +08:00
e6470719bb fix 2023-09-22 00:22:53 +08:00
6260d29dc7 fix 2023-09-22 00:21:18 +08:00
7aa4a57257 fix 2023-09-22 00:18:04 +08:00
7324aabbd6 fix 2023-09-22 00:12:23 +08:00
0b8f6e69cf fix 2023-09-22 00:03:01 +08:00
bd1b6ee23e fix 2023-09-21 23:59:01 +08:00
58e2068170 fix 2023-09-21 23:47:34 +08:00
45ef0b8bc9 fix 2023-09-21 23:39:15 +08:00
ff011f6452 fix 2023-09-21 23:32:58 +08:00
d3c96184b8 fix 2023-09-21 23:21:57 +08:00
93 changed files with 2806 additions and 1299 deletions

4
.gitignore vendored
View File

@ -44,4 +44,6 @@ shared-state
*.zip
vendor
vendor
grpc_server/gen

View File

@ -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,
}
}

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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

View File

@ -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 = &ltime
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
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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"`

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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数据结构

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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"` // 公司
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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:

View File

@ -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})
}

View File

@ -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,
})
}

View File

@ -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 {

View File

@ -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)

View 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)
}
}
}

View 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)
}
}
}

View 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)
}
}
}

View 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)
}
}
}

View File

@ -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),
},
},
)
}

View 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)
}
}
}

View 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)
}
}
}

View 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)
// }

View 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)
// }

View 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)
// }

View 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)
// }

View 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)
// }

View File

@ -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)

View File

@ -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)
}

View 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)
// }

View 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)
// }

View File

@ -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值

View File

@ -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:

View File

@ -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 {

View File

@ -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 必须重新处理

View File

@ -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 {

View File

@ -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",

View File

@ -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")
}

View File

@ -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%+vdesc%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%+vdesc%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%+vdesc%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%+vdesc%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%+vdesc%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%+vdesc%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%+vdesc%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%+vdesc%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%+vdesc%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%+vdesc%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
}

View File

@ -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,
}),
}
}

View File

@ -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值

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}
}

View File

@ -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",

View 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)
// }

View File

@ -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 {

View File

@ -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{}

View File

@ -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

View 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)
// }

View File

@ -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)

View File

@ -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 ")
}

View File

@ -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)
// }

View File

@ -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

View File

@ -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

View File

@ -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)),
}),
}
}

View File

@ -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值

View File

@ -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 {

View File

@ -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{

View File

@ -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
}

View File

@ -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,

View File

@ -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 {

View File

@ -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),
},
}
//保存连接

View File

@ -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{

View File

@ -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"` // 首名
}
)

View File

@ -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 {

View File

@ -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 {

View File

@ -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"`

View File

@ -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

View File

@ -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())

View File

@ -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: &currency,
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,

View File

@ -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
}

View File

@ -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 {

View File

@ -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
View 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()
}

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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])