Compare commits
12 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
3d09bd9a1f | 2 years ago |
|
|
d51f04a8d1 | 2 years ago |
|
|
f36b98f9f9 | 2 years ago |
|
|
21d924ffb4 | 2 years ago |
|
|
32d193c603 | 2 years ago |
|
|
8ebd1ec3f6 | 2 years ago |
|
|
6260a1f013 | 2 years ago |
|
|
335b79f482 | 2 years ago |
|
|
e4a276eea3 | 2 years ago |
|
|
eee26f52e4 | 2 years ago |
|
|
814258931b | 2 years ago |
|
|
be6eca5128 | 2 years ago |
@ -1,215 +0,0 @@
|
|||||||
{
|
|
||||||
"id": 1416,
|
|
||||||
"type": "normal",
|
|
||||||
"title": "多规格123123",
|
|
||||||
"subtitle": "多规格",
|
|
||||||
"weigh": 0,
|
|
||||||
"category_ids": "46",
|
|
||||||
"image": "https://demo.shopro.top/uploads/20230821/00e97b4723771626fb44bdbf56d35a73.jpg",
|
|
||||||
"images": [
|
|
||||||
"https://demo.shopro.top/uploads/20230823/170a1630b9b3124e28feacd95646b453.png",
|
|
||||||
"https://demo.shopro.top/uploads/20230823/16f27aeea875d3ff395786ad48f2e38b.png",
|
|
||||||
"https://demo.shopro.top/uploads/20230821/00e97b4723771626fb44bdbf56d35a73.jpg"
|
|
||||||
],
|
|
||||||
"params": null,
|
|
||||||
"content": "\u003cp\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230821/00e97b4723771626fb44bdbf56d35a73.jpg\" style=\"width: 612px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230821/da48a8a2595d0efd619984ebd7e22bd9.jpg\" style=\"width: 612px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230819/8659310afe6e0f2680457c26da4f6d3d.jpg\" style=\"width: 612px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230819/655d7da134ea4669625007c65f934931.jpg\" style=\"width: 612px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230819/a6a57d00022b06e5b412dcfc6df06f1d.jpg\" style=\"width: 612px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230819/8a477ec231722200e268c722f87d95a3.jpg\" style=\"width: 612px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230818/18889719294b8c8bef913a3bbcc73e60.png\" style=\"width: 612px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230817/5aea7892240b08ee32e3b47c8b210053.png\" style=\"width: 500px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230816/f0238ed4eef0068f18f03699c4b8979c.png\" style=\"width: 612px;\"\u003e\u003cimg src=\"https://demo.shopro.top/uploads/20230815/f68d107a4c703780c900c049a65cd47c.jpeg\" style=\"width: 612px;\"\u003e\u003cbr\u003e\u003c/p\u003e",
|
|
||||||
"price": "11.00",
|
|
||||||
"original_price": "22.00",
|
|
||||||
"is_sku": 1,
|
|
||||||
"likes": 0,
|
|
||||||
"views": 623,
|
|
||||||
"sales": 0,
|
|
||||||
"show_sales": 0,
|
|
||||||
"total_sales": 4,
|
|
||||||
"service_ids": "28",
|
|
||||||
"dispatch_type": "express",
|
|
||||||
"dispatch_ids": "23",
|
|
||||||
"deletetime": null,
|
|
||||||
"activity": {
|
|
||||||
"id": 0,
|
|
||||||
"title": "",
|
|
||||||
"type": "",
|
|
||||||
"richtext_id": 0,
|
|
||||||
"richtext_title": "",
|
|
||||||
"starttime": 0,
|
|
||||||
"endtime": 0,
|
|
||||||
"rules": {
|
|
||||||
"activity_auto_close": "",
|
|
||||||
"fictitious_num": "",
|
|
||||||
"is_alone": "",
|
|
||||||
"is_fictitious": "",
|
|
||||||
"limit_buy": "",
|
|
||||||
"order_auto_close": "",
|
|
||||||
"team_card": "",
|
|
||||||
"team_num": "",
|
|
||||||
"valid_time": ""
|
|
||||||
},
|
|
||||||
"status_code": ""
|
|
||||||
},
|
|
||||||
"activity_type": "",
|
|
||||||
"buyers": null,
|
|
||||||
"sku_price": [
|
|
||||||
{
|
|
||||||
"id": 2365,
|
|
||||||
"goods_sku_ids": [
|
|
||||||
1676,
|
|
||||||
1679
|
|
||||||
],
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"image": "https://demo.shopro.top/uploads/20230819/8659310afe6e0f2680457c26da4f6d3d.jpg",
|
|
||||||
"stock": 1,
|
|
||||||
"stock_warning": null,
|
|
||||||
"sales": 0,
|
|
||||||
"sn": "",
|
|
||||||
"weight": 0,
|
|
||||||
"price": "1.00",
|
|
||||||
"goods_sku_text": "红色,xl",
|
|
||||||
"status": "up",
|
|
||||||
"groupon_price": "",
|
|
||||||
"activity_type": "",
|
|
||||||
"activity_id": 0,
|
|
||||||
"item_goods_sku_price": {
|
|
||||||
"id": 0,
|
|
||||||
"activity_id": 0,
|
|
||||||
"sku_price_id": 0,
|
|
||||||
"goods_id": 0,
|
|
||||||
"stock": 0,
|
|
||||||
"sales": 0,
|
|
||||||
"price": "",
|
|
||||||
"status": ""
|
|
||||||
},
|
|
||||||
"goods_sku_id_arr": [
|
|
||||||
"1676",
|
|
||||||
"1679"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2366,
|
|
||||||
"goods_sku_ids": [
|
|
||||||
1677,
|
|
||||||
1679
|
|
||||||
],
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"image": "",
|
|
||||||
"stock": 1,
|
|
||||||
"stock_warning": null,
|
|
||||||
"sales": 0,
|
|
||||||
"sn": "",
|
|
||||||
"weight": 0,
|
|
||||||
"price": "2.00",
|
|
||||||
"goods_sku_text": "绿色,xl",
|
|
||||||
"status": "up",
|
|
||||||
"groupon_price": "",
|
|
||||||
"activity_type": "",
|
|
||||||
"activity_id": 0,
|
|
||||||
"item_goods_sku_price": {
|
|
||||||
"id": 0,
|
|
||||||
"activity_id": 0,
|
|
||||||
"sku_price_id": 0,
|
|
||||||
"goods_id": 0,
|
|
||||||
"stock": 0,
|
|
||||||
"sales": 0,
|
|
||||||
"price": "",
|
|
||||||
"status": ""
|
|
||||||
},
|
|
||||||
"goods_sku_id_arr": [
|
|
||||||
"1677",
|
|
||||||
"1679"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2367,
|
|
||||||
"goods_sku_ids": [
|
|
||||||
1676,
|
|
||||||
1680
|
|
||||||
],
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"image": "",
|
|
||||||
"stock": 1,
|
|
||||||
"stock_warning": null,
|
|
||||||
"sales": 0,
|
|
||||||
"sn": "",
|
|
||||||
"weight": 0,
|
|
||||||
"price": "3.00",
|
|
||||||
"goods_sku_text": "红色,m",
|
|
||||||
"status": "up",
|
|
||||||
"groupon_price": "",
|
|
||||||
"activity_type": "",
|
|
||||||
"activity_id": 0,
|
|
||||||
"item_goods_sku_price": {
|
|
||||||
"id": 0,
|
|
||||||
"activity_id": 0,
|
|
||||||
"sku_price_id": 0,
|
|
||||||
"goods_id": 0,
|
|
||||||
"stock": 0,
|
|
||||||
"sales": 0,
|
|
||||||
"price": "",
|
|
||||||
"status": ""
|
|
||||||
},
|
|
||||||
"goods_sku_id_arr": [
|
|
||||||
"1676",
|
|
||||||
"1680"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2368,
|
|
||||||
"goods_sku_ids": [
|
|
||||||
1677,
|
|
||||||
1680
|
|
||||||
],
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"image": "",
|
|
||||||
"stock": 1,
|
|
||||||
"stock_warning": null,
|
|
||||||
"sales": 0,
|
|
||||||
"sn": "",
|
|
||||||
"weight": 0,
|
|
||||||
"price": "4.00",
|
|
||||||
"goods_sku_text": "绿色,m",
|
|
||||||
"status": "up",
|
|
||||||
"groupon_price": "",
|
|
||||||
"activity_type": "",
|
|
||||||
"activity_id": 0,
|
|
||||||
"item_goods_sku_price": {
|
|
||||||
"id": 0,
|
|
||||||
"activity_id": 0,
|
|
||||||
"sku_price_id": 0,
|
|
||||||
"goods_id": 0,
|
|
||||||
"stock": 0,
|
|
||||||
"sales": 0,
|
|
||||||
"price": "",
|
|
||||||
"status": ""
|
|
||||||
},
|
|
||||||
"goods_sku_id_arr": [
|
|
||||||
"1677",
|
|
||||||
"1680"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stock": 1,
|
|
||||||
"activity_discounts": [
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"activity_discounts_types": "",
|
|
||||||
"activity_discounts_tags": [],
|
|
||||||
"favorite": null,
|
|
||||||
"dispatch_type_arr": [
|
|
||||||
"express"
|
|
||||||
],
|
|
||||||
"service": [
|
|
||||||
{
|
|
||||||
"id": 28,
|
|
||||||
"name": "免费包邮",
|
|
||||||
"image": "https://demo.shopro.top/uploads/20230710/f7f6bf60f2898f583bbe09acd221d9f1.png",
|
|
||||||
"description": "123"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sku": null,
|
|
||||||
"coupons": null,
|
|
||||||
"groupon_price": ""
|
|
||||||
}
|
|
||||||
@ -1,226 +0,0 @@
|
|||||||
{
|
|
||||||
"id": 1416,
|
|
||||||
"type": "normal",
|
|
||||||
"title": "多规格",
|
|
||||||
"subtitle": "多规格",
|
|
||||||
"weigh": 0,
|
|
||||||
"category_ids": "46",
|
|
||||||
"image": "https://demo.shopro.top/uploads/20230821/00e97b4723771626fb44bdbf56d35a73.jpg",
|
|
||||||
"images": [
|
|
||||||
"https://demo.shopro.top/uploads/20230823/170a1630b9b3124e28feacd95646b453.png",
|
|
||||||
"https://demo.shopro.top/uploads/20230823/16f27aeea875d3ff395786ad48f2e38b.png",
|
|
||||||
"https://demo.shopro.top/uploads/20230821/00e97b4723771626fb44bdbf56d35a73.jpg"
|
|
||||||
],
|
|
||||||
"params": [],
|
|
||||||
"content": "<p><img src=\"https://demo.shopro.top/uploads/20230821/00e97b4723771626fb44bdbf56d35a73.jpg\" style=\"width: 612px;\"><img src=\"https://demo.shopro.top/uploads/20230821/da48a8a2595d0efd619984ebd7e22bd9.jpg\" style=\"width: 612px;\"><img src=\"https://demo.shopro.top/uploads/20230819/8659310afe6e0f2680457c26da4f6d3d.jpg\" style=\"width: 612px;\"><img src=\"https://demo.shopro.top/uploads/20230819/655d7da134ea4669625007c65f934931.jpg\" style=\"width: 612px;\"><img src=\"https://demo.shopro.top/uploads/20230819/a6a57d00022b06e5b412dcfc6df06f1d.jpg\" style=\"width: 612px;\"><img src=\"https://demo.shopro.top/uploads/20230819/8a477ec231722200e268c722f87d95a3.jpg\" style=\"width: 612px;\"><img src=\"https://demo.shopro.top/uploads/20230818/18889719294b8c8bef913a3bbcc73e60.png\" style=\"width: 612px;\"><img src=\"https://demo.shopro.top/uploads/20230817/5aea7892240b08ee32e3b47c8b210053.png\" style=\"width: 500px;\"><img src=\"https://demo.shopro.top/uploads/20230816/f0238ed4eef0068f18f03699c4b8979c.png\" style=\"width: 612px;\"><img src=\"https://demo.shopro.top/uploads/20230815/f68d107a4c703780c900c049a65cd47c.jpeg\" style=\"width: 612px;\"><br></p>",
|
|
||||||
"price": "11",
|
|
||||||
"original_price": "22.00",
|
|
||||||
"is_sku": 1,
|
|
||||||
"likes": 0,
|
|
||||||
"views": 631,
|
|
||||||
"sales": 0,
|
|
||||||
"show_sales": 0,
|
|
||||||
"service_ids": "28",
|
|
||||||
"dispatch_type": "express",
|
|
||||||
"dispatch_ids": "23",
|
|
||||||
"deletetime": null,
|
|
||||||
"activity": null,
|
|
||||||
"activity_type": null,
|
|
||||||
"buyers": [],
|
|
||||||
"sku_price": [
|
|
||||||
{
|
|
||||||
"id": 2365,
|
|
||||||
"goods_sku_ids": "1676,1679",
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"image": "https://demo.shopro.top/uploads/20230819/8659310afe6e0f2680457c26da4f6d3d.jpg",
|
|
||||||
"stock": 1,
|
|
||||||
"stock_warning": null,
|
|
||||||
"sales": 0,
|
|
||||||
"sn": "",
|
|
||||||
"weight": 0,
|
|
||||||
"price": "1.00",
|
|
||||||
"goods_sku_text": "红色,xl",
|
|
||||||
"status": "up",
|
|
||||||
"goods_sku_id_arr": [
|
|
||||||
"1676",
|
|
||||||
"1679"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2366,
|
|
||||||
"goods_sku_ids": "1677,1679",
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"image": "",
|
|
||||||
"stock": 1,
|
|
||||||
"stock_warning": null,
|
|
||||||
"sales": 0,
|
|
||||||
"sn": "",
|
|
||||||
"weight": 0,
|
|
||||||
"price": "2.00",
|
|
||||||
"goods_sku_text": "绿色,xl",
|
|
||||||
"status": "up",
|
|
||||||
"goods_sku_id_arr": [
|
|
||||||
"1677",
|
|
||||||
"1679"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2367,
|
|
||||||
"goods_sku_ids": "1676,1680",
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"image": "",
|
|
||||||
"stock": 1,
|
|
||||||
"stock_warning": null,
|
|
||||||
"sales": 0,
|
|
||||||
"sn": "",
|
|
||||||
"weight": 0,
|
|
||||||
"price": "3.00",
|
|
||||||
"goods_sku_text": "红色,m",
|
|
||||||
"status": "up",
|
|
||||||
"goods_sku_id_arr": [
|
|
||||||
"1676",
|
|
||||||
"1680"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2368,
|
|
||||||
"goods_sku_ids": "1677,1680",
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"image": "",
|
|
||||||
"stock": 1,
|
|
||||||
"stock_warning": null,
|
|
||||||
"sales": 0,
|
|
||||||
"sn": "",
|
|
||||||
"weight": 0,
|
|
||||||
"price": "4.00",
|
|
||||||
"goods_sku_text": "绿色,m",
|
|
||||||
"status": "up",
|
|
||||||
"goods_sku_id_arr": [
|
|
||||||
"1677",
|
|
||||||
"1680"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stock": 4,
|
|
||||||
"activity_discounts": [],
|
|
||||||
"activity_discounts_types": "",
|
|
||||||
"activity_discounts_tags": [],
|
|
||||||
"favorite": null,
|
|
||||||
"dispatch_type_arr": [
|
|
||||||
"express"
|
|
||||||
],
|
|
||||||
"service": [
|
|
||||||
{
|
|
||||||
"id": 28,
|
|
||||||
"name": "免费包邮",
|
|
||||||
"image": "https://demo.shopro.top/uploads/20230710/f7f6bf60f2898f583bbe09acd221d9f1.png",
|
|
||||||
"description": "123"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sku": [
|
|
||||||
{
|
|
||||||
"id": 1675,
|
|
||||||
"name": "颜色",
|
|
||||||
"pid": 0,
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"content": [
|
|
||||||
{
|
|
||||||
"id": 1676,
|
|
||||||
"name": "红色",
|
|
||||||
"pid": 1675,
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1677,
|
|
||||||
"name": "绿色",
|
|
||||||
"pid": 1675,
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1678,
|
|
||||||
"name": "尺码",
|
|
||||||
"pid": 0,
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0,
|
|
||||||
"content": [
|
|
||||||
{
|
|
||||||
"id": 1679,
|
|
||||||
"name": "xl",
|
|
||||||
"pid": 1678,
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1680,
|
|
||||||
"name": "m",
|
|
||||||
"pid": 1678,
|
|
||||||
"goods_id": 1416,
|
|
||||||
"weigh": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"coupons": [
|
|
||||||
{
|
|
||||||
"id": 35,
|
|
||||||
"name": "新人优惠券",
|
|
||||||
"type": "cash",
|
|
||||||
"goods_ids": "0",
|
|
||||||
"amount": "10.00",
|
|
||||||
"enough": "100.00",
|
|
||||||
"stock": 999760,
|
|
||||||
"limit": 1,
|
|
||||||
"gettime": {
|
|
||||||
"start": 1665849600,
|
|
||||||
"end": 1732896000
|
|
||||||
},
|
|
||||||
"usetime": {
|
|
||||||
"start": 1732896000,
|
|
||||||
"end": 1764345600
|
|
||||||
},
|
|
||||||
"description": "新人可领asdfasd",
|
|
||||||
"usetimestart": 1732896000,
|
|
||||||
"usetimeend": 1764345600,
|
|
||||||
"gettimestart": 1665849600,
|
|
||||||
"gettimeend": 1732896000,
|
|
||||||
"status_code": "can_get",
|
|
||||||
"status_name": "可以领取",
|
|
||||||
"user_coupons": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 83,
|
|
||||||
"name": "111",
|
|
||||||
"type": "cash",
|
|
||||||
"goods_ids": "0",
|
|
||||||
"amount": "5.00",
|
|
||||||
"enough": "10.00",
|
|
||||||
"stock": 99992,
|
|
||||||
"limit": 1,
|
|
||||||
"gettime": {
|
|
||||||
"start": 1699200000,
|
|
||||||
"end": 1703520000
|
|
||||||
},
|
|
||||||
"usetime": {
|
|
||||||
"start": 1699200000,
|
|
||||||
"end": 1703692800
|
|
||||||
},
|
|
||||||
"description": "1",
|
|
||||||
"usetimestart": 1699200000,
|
|
||||||
"usetimeend": 1703692800,
|
|
||||||
"gettimestart": 1699200000,
|
|
||||||
"gettimeend": 1703520000,
|
|
||||||
"status_code": "can_get",
|
|
||||||
"status_name": "可以领取",
|
|
||||||
"user_coupons": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"pid":36728}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
case $3 in
|
||||||
|
"")
|
||||||
|
goarch="amd64"
|
||||||
|
releasePath="x86_64"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
"arm")
|
||||||
|
goarch="arm"
|
||||||
|
releasePath="arm"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
"arm64")
|
||||||
|
goarch="arm64"
|
||||||
|
releasePath="arm64"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
"loong64")
|
||||||
|
goarch="loong64"
|
||||||
|
releasePath="loong64"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo '目标 ' $3 ' 无法编译'
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
buildfile=$1
|
||||||
|
|
||||||
|
|
||||||
|
case $2 in
|
||||||
|
"linux") echo '交叉编译目标为linux+'$goarch
|
||||||
|
echo "CGO_ENABLED=0 GOOS=linux GOARCH="$goarch" go build "$1
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=$goarch go build -o ./"${buildfile%%.*}-"$releasePath $1
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
"windows") echo '交叉编译目标为windows+'$goarch
|
||||||
|
echo "CGO_ENABLED=0 GOOS=windows GOARCH="$goarch" go build "$1
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=$goarch go build -o ././"${buildfile%%.*}-"$releasePath".exe" $1
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
"darwin") echo '交叉编译目标为maxos+'$goarch
|
||||||
|
echo "CGO_ENABLED=0 GOOS=darwin GOARCH="$goarch" go build "$1
|
||||||
|
CGO_ENABLED=0 GOOS=darwin GOARCH=$goarch go build -o ./"${buildfile%%.*}-"$releasePath $1
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*) echo '参数不正确:'$goarch
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo '脚本执行结束...'
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"serverport":"9001"
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"DbType":"mysql",
|
||||||
|
"IsMaster":true,
|
||||||
|
"Dsn":"root:Password1!@tcp(mysql-a.fanhaninfo.test:3306)/dev_digital?charset=utf8mb4",
|
||||||
|
"sqlMaxIdleConns":100,
|
||||||
|
"sqlMaxOpenConns":100,
|
||||||
|
"sqlLogLevel":2
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"DbType":"mysql",
|
||||||
|
"IsMaster":true,
|
||||||
|
"Dsn":"root:12345678@tcp(127.0.0.1:3306)/fushouxian?charset=utf8mb4",
|
||||||
|
"sqlMaxIdleConns":1,
|
||||||
|
"sqlMaxOpenConns":1,
|
||||||
|
"sqlLogLevel":2
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"rpa_url": "http://172.0.0.19:19005",
|
||||||
|
"username": "admin",
|
||||||
|
"password": "123"
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"Priority":100,
|
||||||
|
"ModuleName":"go",
|
||||||
|
"ServerUrls":[
|
||||||
|
"wss://shop.ruixininfo.com/websocket/jsonrpc"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
_ "src/init"
|
||||||
|
|
||||||
|
"github.com/towgo/towgo/dao/basedboperat"
|
||||||
|
"github.com/towgo/towgo/dao/ormDriver/xormDriver"
|
||||||
|
"github.com/towgo/towgo/lib/processmanager"
|
||||||
|
"github.com/towgo/towgo/lib/system"
|
||||||
|
"github.com/towgo/towgo/towgo"
|
||||||
|
)
|
||||||
|
|
||||||
|
var appName string = "fushouxian-server"
|
||||||
|
var appVersion string = "1.0.0"
|
||||||
|
|
||||||
|
var basePath = system.GetPathOfProgram()
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
//初始化xorm数据库驱动
|
||||||
|
var dbconfig []xormDriver.DsnConfig
|
||||||
|
system.ScanConfigJson(basePath+"/config/dbconfig.json", &dbconfig)
|
||||||
|
xormDriver.New(dbconfig)
|
||||||
|
|
||||||
|
//设定默认orm引擎
|
||||||
|
err := basedboperat.SetOrmEngine("xorm")
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func main() {
|
||||||
|
pm := processmanager.GetManager()
|
||||||
|
for k, v := range os.Args {
|
||||||
|
switch v {
|
||||||
|
case "start":
|
||||||
|
if k == 1 {
|
||||||
|
if pm.Start() {
|
||||||
|
log.Print("启动成功")
|
||||||
|
start()
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
log.Print("启动失败:" + pm.Error.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "restart":
|
||||||
|
if k == 1 {
|
||||||
|
if pm.ReStart() {
|
||||||
|
log.Print("重启成功")
|
||||||
|
start()
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
log.Print("重启失败:" + pm.Error.Error())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "stop":
|
||||||
|
if k == 1 {
|
||||||
|
if pm.Stop() {
|
||||||
|
log.Print("程序停止成功")
|
||||||
|
} else {
|
||||||
|
log.Print("程序停止失败:程序没有运行")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "version":
|
||||||
|
if k == 1 {
|
||||||
|
fmt.Print(appName + ":" + appVersion + "\n")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Print("参数传递错误,有效参数如下:\n" + os.Args[0] + " start | stop | reload | stop")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func start() {
|
||||||
|
|
||||||
|
moduleClientInit()
|
||||||
|
|
||||||
|
conf := struct {
|
||||||
|
Serverport string `json:"serverport"`
|
||||||
|
}{}
|
||||||
|
system.ScanConfigJson(basePath+"/config/config.json", &conf)
|
||||||
|
|
||||||
|
http.HandleFunc("/jsonrpc", towgo.HttpHandller)
|
||||||
|
|
||||||
|
log.Print("http服务运行中:0.0.0.0:" + conf.Serverport + "\n")
|
||||||
|
http.ListenAndServe("0.0.0.0:"+conf.Serverport, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func moduleClientInit() {
|
||||||
|
var node towgo.EdgeServerNodeConfig
|
||||||
|
system.ScanConfigJson(basePath+"config/togocdn.client.config.json", &node)
|
||||||
|
node.Methods = towgo.GetMethods()
|
||||||
|
node.ModuleName = appName
|
||||||
|
for _, v := range node.ServerUrls {
|
||||||
|
node.ServerUrl = v
|
||||||
|
client := towgo.NewEdgeServerNode(node)
|
||||||
|
client.Connect()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1 +1 @@
|
|||||||
{"pid":42691}
|
{"pid":36728}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package init
|
||||||
|
|
||||||
|
import "src/module/usercenter"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
usercenter.InitManageApi()
|
||||||
|
}
|
||||||
@ -0,0 +1,139 @@
|
|||||||
|
{
|
||||||
|
"id": 8405,
|
||||||
|
"type": "goods",
|
||||||
|
"order_sn": "202303165939181001191100",
|
||||||
|
"user_id": 11911,
|
||||||
|
"activity_type": "",
|
||||||
|
"goods_amount": "8.00",
|
||||||
|
"dispatch_amount": "0.00",
|
||||||
|
"phone": "13369437728",
|
||||||
|
"consignee": "我去",
|
||||||
|
"province_name": "上海市",
|
||||||
|
"city_name": "上海市",
|
||||||
|
"area_name": "黄浦区",
|
||||||
|
"address": "123123",
|
||||||
|
"province_id": 310000,
|
||||||
|
"city_id": 310100,
|
||||||
|
"area_id": 310101,
|
||||||
|
"status": 0,
|
||||||
|
"invoice_status": "0",
|
||||||
|
"memo": null,
|
||||||
|
"remark": "",
|
||||||
|
"total_amount": "8.00",
|
||||||
|
"score_amount": 0,
|
||||||
|
"total_fee": "8.00",
|
||||||
|
"last_total_fee": "0.00",
|
||||||
|
"discount_fee": "0.00",
|
||||||
|
"coupon_fee": "0.00",
|
||||||
|
"activity_discount_money": "0.00",
|
||||||
|
"dispatch_discount_money": "0.00",
|
||||||
|
"pay_fee": "0.00",
|
||||||
|
"score_fee": 0,
|
||||||
|
"goods_original_amount": "44.00",
|
||||||
|
"coupons_id": 0,
|
||||||
|
"transaction_id": null,
|
||||||
|
"payment_json": null,
|
||||||
|
"pay_type": null,
|
||||||
|
"paytime": null,
|
||||||
|
"ext": "{\"buy_type\":\"alone\",\"groupon_id\":0,\"expired_time\":1703748719}",
|
||||||
|
"platform": "H5",
|
||||||
|
"createtime": 1703747819,
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"id": 9257,
|
||||||
|
"user_id": 11911,
|
||||||
|
"order_id": 8405,
|
||||||
|
"goods_id": 1416,
|
||||||
|
"goods_type": "normal",
|
||||||
|
"goods_sku_price_id": 2368,
|
||||||
|
"activity_id": 0,
|
||||||
|
"activity_type": null,
|
||||||
|
"item_goods_sku_price_id": 0,
|
||||||
|
"goods_sku_text": "绿色,m",
|
||||||
|
"goods_title": "多规格",
|
||||||
|
"goods_image": "https:\/\/demo.shopro.top\/uploads\/20230821\/00e97b4723771626fb44bdbf56d35a73.jpg",
|
||||||
|
"goods_original_price": "22.00",
|
||||||
|
"discount_fee": "0.00",
|
||||||
|
"goods_price": "4.00",
|
||||||
|
"goods_num": 1,
|
||||||
|
"goods_weight": 0,
|
||||||
|
"pay_price": "4.00",
|
||||||
|
"dispatch_status": 0,
|
||||||
|
"dispatch_fee": "0.00",
|
||||||
|
"dispatch_type": "express",
|
||||||
|
"dispatch_id": 23,
|
||||||
|
"store_id": 0,
|
||||||
|
"aftersale_status": 0,
|
||||||
|
"comment_status": 0,
|
||||||
|
"refund_status": 0,
|
||||||
|
"refund_fee": null,
|
||||||
|
"refund_msg": null,
|
||||||
|
"express_name": null,
|
||||||
|
"express_code": null,
|
||||||
|
"express_no": null,
|
||||||
|
"ext": "[]",
|
||||||
|
"createtime": 1703747819,
|
||||||
|
"updatetime": 1703747819,
|
||||||
|
"status_code": "nopay",
|
||||||
|
"status_name": "",
|
||||||
|
"status_desc": "",
|
||||||
|
"btns": [],
|
||||||
|
"ext_arr": [],
|
||||||
|
"status_text": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9258,
|
||||||
|
"user_id": 11911,
|
||||||
|
"order_id": 8405,
|
||||||
|
"goods_id": 1416,
|
||||||
|
"goods_type": "normal",
|
||||||
|
"goods_sku_price_id": 2368,
|
||||||
|
"activity_id": 0,
|
||||||
|
"activity_type": null,
|
||||||
|
"item_goods_sku_price_id": 0,
|
||||||
|
"goods_sku_text": "绿色,m",
|
||||||
|
"goods_title": "多规格",
|
||||||
|
"goods_image": "https:\/\/demo.shopro.top\/uploads\/20230821\/00e97b4723771626fb44bdbf56d35a73.jpg",
|
||||||
|
"goods_original_price": "22.00",
|
||||||
|
"discount_fee": "0.00",
|
||||||
|
"goods_price": "4.00",
|
||||||
|
"goods_num": 1,
|
||||||
|
"goods_weight": 0,
|
||||||
|
"pay_price": "4.00",
|
||||||
|
"dispatch_status": 0,
|
||||||
|
"dispatch_fee": "0.00",
|
||||||
|
"dispatch_type": "express",
|
||||||
|
"dispatch_id": 23,
|
||||||
|
"store_id": 0,
|
||||||
|
"aftersale_status": 0,
|
||||||
|
"comment_status": 0,
|
||||||
|
"refund_status": 0,
|
||||||
|
"refund_fee": null,
|
||||||
|
"refund_msg": null,
|
||||||
|
"express_name": null,
|
||||||
|
"express_code": null,
|
||||||
|
"express_no": null,
|
||||||
|
"ext": "[]",
|
||||||
|
"createtime": 1703747819,
|
||||||
|
"updatetime": 1703747819,
|
||||||
|
"status_code": "nopay",
|
||||||
|
"status_name": "",
|
||||||
|
"status_desc": "",
|
||||||
|
"btns": [],
|
||||||
|
"ext_arr": [],
|
||||||
|
"status_text": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"status_code": "nopay",
|
||||||
|
"status_name": "待付款",
|
||||||
|
"status_desc": "等待买家付款",
|
||||||
|
"btns": [
|
||||||
|
"cancel",
|
||||||
|
"pay"
|
||||||
|
],
|
||||||
|
"ext_arr": {
|
||||||
|
"buy_type": "alone",
|
||||||
|
"groupon_id": 0,
|
||||||
|
"expired_time": 1703748719
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"id": 8405,
|
||||||
|
"type": "goods",
|
||||||
|
"order_sn": "202303165939181001191100",
|
||||||
|
"user_id": 11911,
|
||||||
|
"activity_type": "",
|
||||||
|
"goods_amount": "8.00",
|
||||||
|
"dispatch_amount": "0.00",
|
||||||
|
"phone": "13369437728",
|
||||||
|
"consignee": "我去",
|
||||||
|
"province_name": "上海市",
|
||||||
|
"city_name": "上海市",
|
||||||
|
"area_name": "黄浦区",
|
||||||
|
"address": "123123",
|
||||||
|
"province_id": 310000,
|
||||||
|
"city_id": 310100,
|
||||||
|
"area_id": 310101,
|
||||||
|
"status": 0,
|
||||||
|
"invoice_status": "0",
|
||||||
|
"memo": null,
|
||||||
|
"remark": "",
|
||||||
|
"total_amount": "8.00",
|
||||||
|
"score_amount": 0,
|
||||||
|
"total_fee": "8.00",
|
||||||
|
"last_total_fee": "0.00",
|
||||||
|
"discount_fee": "0.00",
|
||||||
|
"coupon_fee": "0.00",
|
||||||
|
"activity_discount_money": "0.00",
|
||||||
|
"dispatch_discount_money": "0.00",
|
||||||
|
"pay_fee": "0.00",
|
||||||
|
"score_fee": 0,
|
||||||
|
"goods_original_amount": "44.00",
|
||||||
|
"coupons_id": 0,
|
||||||
|
"transaction_id": null,
|
||||||
|
"payment_json": null,
|
||||||
|
"pay_type": null,
|
||||||
|
"paytime": null,
|
||||||
|
"ext": "{\"buy_type\":\"alone\",\"groupon_id\":0,\"expired_time\":1703748719}",
|
||||||
|
"platform": "H5",
|
||||||
|
"createtime": 1703747819,
|
||||||
|
"status_code": "nopay",
|
||||||
|
"status_name": "待付款",
|
||||||
|
"status_desc": "等待买家付款",
|
||||||
|
"btns": [
|
||||||
|
"cancel",
|
||||||
|
"pay"
|
||||||
|
],
|
||||||
|
"ext_arr": {
|
||||||
|
"buy_type": "alone",
|
||||||
|
"groupon_id": 0,
|
||||||
|
"expired_time": 1703748719
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
package cart
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/towgo/towgo/dao/basedboperat"
|
||||||
|
"log"
|
||||||
|
"src/module/goods"
|
||||||
|
skuPrice "src/module/skuPrice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (Cart) TableName() string {
|
||||||
|
return "cart"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrderItem 表示订单项信息
|
||||||
|
type Cart struct {
|
||||||
|
ID int64 `json:"id"` // 订单项ID
|
||||||
|
UserID int64 `json:"user_id"` // 用户ID
|
||||||
|
CartType string `json:"cart_type"` // 购物车类型
|
||||||
|
|
||||||
|
GoodsId int64 `json:"goods_id"` // 商品ID
|
||||||
|
GoodsIds string `json:"goods_ids"` // 商品IDs
|
||||||
|
GoodsNum int64 `json:"goods_num"` // 商品数量
|
||||||
|
Goods goods.Goods `json:"goods"xorm:"-"` // 商品
|
||||||
|
|
||||||
|
ActivityID int64 `json:"activity_id"` // 活动ID
|
||||||
|
ActivityType string `json:"activity_type"` // 活动类型
|
||||||
|
|
||||||
|
SkuPriceId int64 `json:"sku_price_id"` //规格价格
|
||||||
|
SkuPrice skuPrice.SKUPrice `json:"sku_price" xorm:"-"` //规格价格
|
||||||
|
|
||||||
|
}
|
||||||
|
type ExtArr struct {
|
||||||
|
BuyType string `json:"buy_type"`
|
||||||
|
GrouponId int64 `json:"groupon_id"`
|
||||||
|
ExpiredTime int64 `json:"expired_time"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cart *Cart) AfterQuery(session basedboperat.DbTransactionSession) {
|
||||||
|
var good goods.Goods
|
||||||
|
err := session.Get(&good, nil, "id = ?", cart.GoodsId)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cart.Goods = good
|
||||||
|
var skuP skuPrice.SKUPrice
|
||||||
|
err = session.Get(&skuP, nil, "id = ?", cart.SkuPriceId)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cart.SkuPrice = skuP
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
package cart
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/towgo/towgo/dao/basedboperat"
|
||||||
|
"github.com/towgo/towgo/dao/ormDriver/xormDriver"
|
||||||
|
"github.com/towgo/towgo/towgo"
|
||||||
|
"src/module/usercenter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
xormDriver.Sync2(new(Cart))
|
||||||
|
towgo.NewCRUDJsonrpcAPI("/cart", Cart{}, []Cart{}).RegAPI()
|
||||||
|
towgo.SetFunc("/cart/mycart", GetMyCart)
|
||||||
|
towgo.SetFunc("/cart/add", CartAdd)
|
||||||
|
towgo.SetFunc("/cart/edit", CartEdit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMyCart(rpc towgo.JsonRpcConnection) {
|
||||||
|
user, err := usercenter.LoginByToken(rpc.GetRpcRequest().Session)
|
||||||
|
//user, err := usercenter.LoginByToken("15c59252b34734f5f106be41a8108cf3")
|
||||||
|
user.Token = rpc.GetRpcRequest().Session
|
||||||
|
if err != nil {
|
||||||
|
rpc.GetRpcResponse().Error.Set(401, err.Error())
|
||||||
|
rpc.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var c Cart
|
||||||
|
var cs []Cart
|
||||||
|
var listCart basedboperat.List
|
||||||
|
listCart.Limit = -1
|
||||||
|
listCart.Where = append(listCart.Where, basedboperat.Condition{
|
||||||
|
Field: "user_id",
|
||||||
|
Operator: "=",
|
||||||
|
Value: user.ID,
|
||||||
|
})
|
||||||
|
basedboperat.ListScan(&listCart, &c, &cs)
|
||||||
|
|
||||||
|
rpc.WriteResult(cs)
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddParams struct {
|
||||||
|
GoodsList []struct {
|
||||||
|
GoodsId int64 `json:"goods_id"`
|
||||||
|
GoodsNum int64 `json:"goods_num"`
|
||||||
|
SkuPriceId int64 `json:"sku_price_id"`
|
||||||
|
GoodsPrice string `json:"goods_price"`
|
||||||
|
} `json:"goods_list"`
|
||||||
|
Form string `json:"form"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func CartAdd(rpc towgo.JsonRpcConnection) {
|
||||||
|
var params AddParams
|
||||||
|
rpc.ReadParams(¶ms)
|
||||||
|
user, err := usercenter.LoginByToken(rpc.GetRpcRequest().Session)
|
||||||
|
//user, err := usercenter.LoginByToken("15c59252b34734f5f106be41a8108cf3")
|
||||||
|
user.Token = rpc.GetRpcRequest().Session
|
||||||
|
if err != nil {
|
||||||
|
rpc.GetRpcResponse().Error.Set(401, err.Error())
|
||||||
|
rpc.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var c Cart
|
||||||
|
for _, v := range params.GoodsList {
|
||||||
|
c = Cart{
|
||||||
|
UserID: user.ID,
|
||||||
|
GoodsId: v.GoodsId,
|
||||||
|
GoodsNum: v.GoodsNum,
|
||||||
|
SkuPriceId: v.SkuPriceId,
|
||||||
|
}
|
||||||
|
basedboperat.Create(&c)
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
UserId int64 `json:"user_id"`
|
||||||
|
GoodsId int64 `json:"goods_id"`
|
||||||
|
GoodsNum int64 `json:"goods_num"`
|
||||||
|
SkuPriceId int64 `json:"sku_price_id"`
|
||||||
|
}
|
||||||
|
rpc.WriteResult(res{
|
||||||
|
Id: c.ID,
|
||||||
|
UserId: user.UserID,
|
||||||
|
GoodsId: c.GoodsId,
|
||||||
|
GoodsNum: c.GoodsNum,
|
||||||
|
SkuPriceId: c.SkuPriceId,
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type EditParams struct {
|
||||||
|
CartList []int64 `json:"cart_list"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
Act string `json:"act"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func CartEdit(rpc towgo.JsonRpcConnection) {
|
||||||
|
var params EditParams
|
||||||
|
rpc.ReadParams(¶ms)
|
||||||
|
if len(params.CartList) == 0 {
|
||||||
|
rpc.WriteError(200, "请选择商品")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var c Cart
|
||||||
|
if params.Act == "delete" {
|
||||||
|
for _, v := range params.CartList {
|
||||||
|
basedboperat.Delete(&c, v, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc.WriteResult(true)
|
||||||
|
}
|
||||||
@ -0,0 +1,323 @@
|
|||||||
|
package order
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/towgo/towgo/dao/basedboperat"
|
||||||
|
"github.com/towgo/towgo/dao/ormDriver/xormDriver"
|
||||||
|
"github.com/towgo/towgo/towgo"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"src/module/cart"
|
||||||
|
"src/module/goods"
|
||||||
|
skuPrice "src/module/skuPrice"
|
||||||
|
"src/module/usercenter"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
xormDriver.Sync2(new(Order))
|
||||||
|
towgo.NewCRUDJsonrpcAPI("/order", Order{}, []Order{}).RegAPI()
|
||||||
|
towgo.SetFunc("/order/createOrder", CreateOrder)
|
||||||
|
towgo.SetFunc("/order/pre", Pre)
|
||||||
|
towgo.SetFunc("/order/index", OrderList)
|
||||||
|
//towgo.SetFunc("/order/detail", Detail)
|
||||||
|
}
|
||||||
|
func OrderList(rpc towgo.JsonRpcConnection) {
|
||||||
|
type params struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Page int64 `json:"page"`
|
||||||
|
}
|
||||||
|
var p params
|
||||||
|
rpc.ReadParams(&p)
|
||||||
|
var listOrder basedboperat.List
|
||||||
|
listOrder.Limit = -1
|
||||||
|
if p.Type != "all" {
|
||||||
|
listOrder.Where = append(listOrder.Where, basedboperat.Condition{
|
||||||
|
Field: "status_code",
|
||||||
|
Operator: "=",
|
||||||
|
Value: p.Type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
var o Order
|
||||||
|
var os []Order
|
||||||
|
basedboperat.ListScan(&listOrder, &o, &os)
|
||||||
|
type data struct {
|
||||||
|
ResultOrder []Order `json:"result_order"`
|
||||||
|
CurrentPage int64 `json:"current_Page"`
|
||||||
|
LastPage int64 `json:"last_page"`
|
||||||
|
PerPage int64 `json:"per_page"`
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
}
|
||||||
|
sql := "select count(id) as `count` from `" + o.TableName() + "`"
|
||||||
|
var m []map[string]interface{}
|
||||||
|
err := basedboperat.SqlQueryScan(&m, sql)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
count := int64(m[0]["count"].(float64))
|
||||||
|
|
||||||
|
var lastPage int64
|
||||||
|
if count%10 == 0 {
|
||||||
|
lastPage = count / 10
|
||||||
|
} else {
|
||||||
|
lastPage = count/10 + 1
|
||||||
|
}
|
||||||
|
d := data{
|
||||||
|
ResultOrder: os,
|
||||||
|
CurrentPage: p.Page,
|
||||||
|
LastPage: lastPage,
|
||||||
|
PerPage: 10,
|
||||||
|
Total: count,
|
||||||
|
}
|
||||||
|
rpc.WriteResult(d)
|
||||||
|
}
|
||||||
|
func Detail(rpc towgo.JsonRpcConnection) {
|
||||||
|
type idst struct {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
}
|
||||||
|
var i idst
|
||||||
|
rpc.ReadParams(&i)
|
||||||
|
log.Println(i)
|
||||||
|
|
||||||
|
var o Order
|
||||||
|
err := basedboperat.Get(&o, nil, "id = ?", i.Id)
|
||||||
|
log.Println("123")
|
||||||
|
if err != nil {
|
||||||
|
rpc.WriteError(500, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("312")
|
||||||
|
|
||||||
|
rpc.WriteResult(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrePamars struct {
|
||||||
|
GoodsList []struct {
|
||||||
|
GoodsId int64 `json:"goods_id"`
|
||||||
|
SkuPriceId int64 `json:"sku_price_id"`
|
||||||
|
GoodsPrice string `json:"goods_price"`
|
||||||
|
GoodsNum int64 `json:"goods_num"`
|
||||||
|
} `json:"goods_list"`
|
||||||
|
From string `json:"from"`
|
||||||
|
AddressId int64 `json:"address_id"`
|
||||||
|
CouponsId int64 `json:"coupons_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pre(rpc towgo.JsonRpcConnection) {
|
||||||
|
var params PrePamars
|
||||||
|
rpc.ReadParams(¶ms)
|
||||||
|
var s skuPrice.SKUPrice
|
||||||
|
var gs []tempGoods
|
||||||
|
var g goods.Goods
|
||||||
|
var total_pre float64
|
||||||
|
for _, v := range params.GoodsList {
|
||||||
|
total := 0.0
|
||||||
|
if v.SkuPriceId != 0 {
|
||||||
|
basedboperat.Get(&s, nil, "id=?", v.SkuPriceId)
|
||||||
|
p, err := strconv.ParseFloat(s.Price, 64)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
total += p * float64(v.GoodsNum)
|
||||||
|
} else {
|
||||||
|
gp, _ := strconv.ParseFloat(v.GoodsPrice, 64)
|
||||||
|
total += gp * float64(v.GoodsNum)
|
||||||
|
}
|
||||||
|
total_pre += total
|
||||||
|
basedboperat.Get(&g, nil, "id=?", v.GoodsId)
|
||||||
|
gres := tempGoods{
|
||||||
|
GoodsId: g.ID,
|
||||||
|
SkuPriceId: "",
|
||||||
|
GoodsPrice: g.Price,
|
||||||
|
GoodsNum: v.GoodsNum,
|
||||||
|
DispatchType: "express",
|
||||||
|
Detail: g,
|
||||||
|
GoodsOriginalAmount: g.Price,
|
||||||
|
GoodsAmount: "",
|
||||||
|
DispatchAmount: "0.00",
|
||||||
|
ScoreAmount: 0,
|
||||||
|
DispatchId: 0,
|
||||||
|
StoreId: 0,
|
||||||
|
ActivityType: "",
|
||||||
|
DiscountFee: "",
|
||||||
|
PayPrice: strconv.FormatFloat(total, 'f', -1, 64),
|
||||||
|
}
|
||||||
|
gs = append(gs, gres)
|
||||||
|
}
|
||||||
|
free := strconv.FormatFloat(total_pre, 'f', -1, 64)
|
||||||
|
|
||||||
|
rpc.WriteResult(PreRes{
|
||||||
|
GoodsOriginalAmount: free,
|
||||||
|
GoodsAmount: free,
|
||||||
|
OriginDispatchAmount: "",
|
||||||
|
DispatchAmount: "",
|
||||||
|
TotalAmount: free,
|
||||||
|
TotalFee: free,
|
||||||
|
DiscountFee: "",
|
||||||
|
CouponFee: "",
|
||||||
|
ActivityDiscountMoney: "",
|
||||||
|
DispatchDiscountMoney: "",
|
||||||
|
InvoiceAmount: "",
|
||||||
|
ActivityType: "",
|
||||||
|
ScoreAmount: 0,
|
||||||
|
NewGoodsList: gs,
|
||||||
|
NeedAddress: 1,
|
||||||
|
ActivityDiscountInfos: nil,
|
||||||
|
Msg: nil,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type PreRes struct {
|
||||||
|
GoodsOriginalAmount string `json:"goods_original_amount"`
|
||||||
|
GoodsAmount string `json:"goods_amount"`
|
||||||
|
OriginDispatchAmount string `json:"origin_dispatch_amount"`
|
||||||
|
DispatchAmount string `json:"dispatch_amount"`
|
||||||
|
TotalAmount string `json:"total_amount"`
|
||||||
|
TotalFee string `json:"total_fee"`
|
||||||
|
DiscountFee string `json:"discount_fee"`
|
||||||
|
CouponFee string `json:"coupon_fee"`
|
||||||
|
ActivityDiscountMoney string `json:"activity_discount_money"`
|
||||||
|
DispatchDiscountMoney string `json:"dispatch_discount_money"`
|
||||||
|
InvoiceAmount string `json:"invoice_amount"`
|
||||||
|
ActivityType string `json:"activity_type"`
|
||||||
|
ScoreAmount int `json:"score_amount"`
|
||||||
|
NewGoodsList []tempGoods `json:"new_goods_list"`
|
||||||
|
NeedAddress int `json:"need_address"`
|
||||||
|
ActivityDiscountInfos []interface{} `json:"activity_discount_infos"`
|
||||||
|
Msg interface{} `json:"msg"`
|
||||||
|
}
|
||||||
|
type tempGoods struct {
|
||||||
|
GoodsId int64 `json:"goods_id"`
|
||||||
|
SkuPriceId string `json:"sku_price_id"`
|
||||||
|
GoodsPrice string `json:"goods_price"`
|
||||||
|
GoodsNum int64 `json:"goods_num"`
|
||||||
|
DispatchType string `json:"dispatch_type"`
|
||||||
|
Detail goods.Goods `json:"detail"`
|
||||||
|
GoodsOriginalAmount string `json:"goods_original_amount"`
|
||||||
|
GoodsAmount string `json:"goods_amount"`
|
||||||
|
DispatchAmount string `json:"dispatch_amount"`
|
||||||
|
ScoreAmount int64 `json:"score_amount"`
|
||||||
|
DispatchId int64 `json:"dispatch_id"`
|
||||||
|
StoreId int64 `json:"store_id"`
|
||||||
|
ActivityType string `json:"activity_type"`
|
||||||
|
DiscountFee string `json:"discount_fee"`
|
||||||
|
PayPrice string `json:"pay_price"`
|
||||||
|
}
|
||||||
|
type CreateOrderParams struct {
|
||||||
|
GoodsList []struct {
|
||||||
|
GoodsId int64 `json:"goods_id"`
|
||||||
|
CartId int64 `json:"cart_id"`
|
||||||
|
SkuPriceId int64 `json:"sku_price_id"`
|
||||||
|
GoodsPrice string `json:"goods_price"`
|
||||||
|
GoodsNum int64 `json:"goods_num"`
|
||||||
|
DispatchType string `json:"dispatch_type"`
|
||||||
|
} `json:"goods_list"`
|
||||||
|
From string `json:"from"`
|
||||||
|
AddressId int64 `json:"address_id"`
|
||||||
|
CouponsId int64 `json:"coupons_id"`
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
Invoice struct {
|
||||||
|
} `json:"invoice"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateOrder(rpc towgo.JsonRpcConnection) {
|
||||||
|
user, err := usercenter.LoginByToken(rpc.GetRpcRequest().Session)
|
||||||
|
//user, err := usercenter.LoginByToken("15c59252b34734f5f106be41a8108cf3")
|
||||||
|
user.Token = rpc.GetRpcRequest().Session
|
||||||
|
if err != nil {
|
||||||
|
rpc.GetRpcResponse().Error.Set(401, err.Error())
|
||||||
|
rpc.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var params CreateOrderParams
|
||||||
|
rpc.ReadParams(¶ms)
|
||||||
|
var is []cart.Cart
|
||||||
|
var totalFree float64
|
||||||
|
for _, v := range params.GoodsList {
|
||||||
|
var i cart.Cart
|
||||||
|
basedboperat.Get(&i, nil, "id=?", v.CartId)
|
||||||
|
is = append(is, i)
|
||||||
|
basedboperat.Delete(&i, i.ID, nil, nil)
|
||||||
|
floatTemp, err := strconv.ParseFloat(v.GoodsPrice, 64)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
totalFree += float64(v.GoodsNum) * floatTemp
|
||||||
|
}
|
||||||
|
marshal, err := json.Marshal(ExtArr{
|
||||||
|
BuyType: "alone",
|
||||||
|
GrouponId: params.CouponsId,
|
||||||
|
ExpiredTime: time.Now().Unix(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
o := Order{
|
||||||
|
Type: "goods",
|
||||||
|
OrderSN: generateOrderNumber(),
|
||||||
|
UserID: user.ID,
|
||||||
|
ActivityType: "",
|
||||||
|
GoodsAmount: strconv.FormatFloat(totalFree, 'f', -1, 64),
|
||||||
|
DispatchAmount: "0.00",
|
||||||
|
Phone: user.Mobile,
|
||||||
|
Consignee: "我去",
|
||||||
|
ProvinceName: "上海市",
|
||||||
|
CityName: "上海市",
|
||||||
|
AreaName: "黄埔区",
|
||||||
|
Address: strconv.FormatInt(params.AddressId, 10),
|
||||||
|
ProvinceID: 310000,
|
||||||
|
CityID: 310100,
|
||||||
|
AreaID: 310101,
|
||||||
|
Status: 0,
|
||||||
|
InvoiceStatus: "0",
|
||||||
|
Memo: "",
|
||||||
|
Remark: "",
|
||||||
|
TotalAmount: "0",
|
||||||
|
ScoreAmount: 0,
|
||||||
|
TotalFee: strconv.FormatFloat(totalFree, 'f', -1, 64),
|
||||||
|
LastTotalFee: "0.00",
|
||||||
|
DiscountFee: "0.00",
|
||||||
|
CouponFee: "0.00",
|
||||||
|
ActivityDiscountMoney: "0.00",
|
||||||
|
DispatchDiscountMoney: "",
|
||||||
|
PayFee: "0.00",
|
||||||
|
ScoreFee: 0,
|
||||||
|
GoodsOriginalAmount: "66.00",
|
||||||
|
CouponsID: 0,
|
||||||
|
TransactionID: "",
|
||||||
|
PaymentJSON: "",
|
||||||
|
PayType: "",
|
||||||
|
Paytime: 0,
|
||||||
|
Ext: string(marshal),
|
||||||
|
Platform: "H5",
|
||||||
|
Createtime: time.Now().Unix(),
|
||||||
|
Item: is,
|
||||||
|
StatusCode: "nopay",
|
||||||
|
StatusName: "待付款",
|
||||||
|
StatusDesc: "等待买家付款",
|
||||||
|
Btns: []string{"cancel", "pay"},
|
||||||
|
}
|
||||||
|
_, err = basedboperat.Create(&o)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err.Error())
|
||||||
|
rpc.WriteError(500, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rpc.WriteResult(o)
|
||||||
|
}
|
||||||
|
func generateOrderNumber() string {
|
||||||
|
// 生成一个时间戳字符串
|
||||||
|
timestamp := time.Now().UnixNano() / int64(time.Millisecond)
|
||||||
|
|
||||||
|
// 生成一个随机数字符串
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
randomNumber := rand.Intn(10000) // 这里可以根据需要调整随机数的范围
|
||||||
|
|
||||||
|
// 构造订单号
|
||||||
|
orderNumber := fmt.Sprintf("%d%d", timestamp, randomNumber)
|
||||||
|
|
||||||
|
return orderNumber
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package usercenter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"math/big"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var loginOrRegSMSVerificationCode sync.Map
|
||||||
|
|
||||||
|
// 登记注册用验证码
|
||||||
|
func StoreLoginOrloginOrRegSMSVerificationCode(mobile string) (string, error) {
|
||||||
|
codeInterface, ok := loginOrRegSMSVerificationCode.Load(mobile)
|
||||||
|
if ok {
|
||||||
|
return codeInterface.(string), nil
|
||||||
|
}
|
||||||
|
//verificationCode := randCharNumber(6)
|
||||||
|
verificationCode := "666666"
|
||||||
|
loginOrRegSMSVerificationCode.Store(mobile, verificationCode)
|
||||||
|
go func(mobile string) {
|
||||||
|
time.Sleep(time.Second * 5 * 60)
|
||||||
|
loginOrRegSMSVerificationCode.Delete(mobile)
|
||||||
|
}(mobile)
|
||||||
|
return verificationCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证注册验证码
|
||||||
|
func LoginOrRegSMSVerification(mobile, verificationCode string) bool {
|
||||||
|
codeInterface, ok := loginOrRegSMSVerificationCode.LoadAndDelete(mobile)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if codeInterface.(string) == verificationCode {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 随机验证码
|
||||||
|
func randCharNumber(size int) string {
|
||||||
|
char := "0123456789"
|
||||||
|
len64 := int64(len(char))
|
||||||
|
var s bytes.Buffer
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
in, _ := rand.Int(rand.Reader, big.NewInt(len64))
|
||||||
|
s.WriteByte(char[in.Int64()])
|
||||||
|
}
|
||||||
|
return s.String()
|
||||||
|
}
|
||||||
@ -0,0 +1,361 @@
|
|||||||
|
package usercenter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/towgo/towgo/dao/basedboperat"
|
||||||
|
"github.com/towgo/towgo/towgo"
|
||||||
|
"log"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitManageApi() {
|
||||||
|
|
||||||
|
//初始化API加载器
|
||||||
|
initLoader()
|
||||||
|
|
||||||
|
//注册JSON-RPC服务处理器method路由
|
||||||
|
//账户登录 F
|
||||||
|
|
||||||
|
towgo.SetFunc(_methodHead+"/user/loginOrRegByMobile", userLoginOrRegByMobile)
|
||||||
|
|
||||||
|
//获取自己的账户信息
|
||||||
|
towgo.SetFunc(_methodHead+"/user/myinfo", userMyinfo)
|
||||||
|
|
||||||
|
//账户注销 F
|
||||||
|
towgo.SetFunc(_methodHead+"/user/logoff", userLogoff)
|
||||||
|
|
||||||
|
//账户注册移动用户注册
|
||||||
|
towgo.SetFunc(_methodHead+"/user/regByMobile", userRegByMobile)
|
||||||
|
|
||||||
|
//获取注册短信验证码
|
||||||
|
towgo.SetFunc(_methodHead+"/user/getLoginOrRegSMSVerificationCode", getLoginOrRegSMSVerificationCode)
|
||||||
|
|
||||||
|
//修改密码 F
|
||||||
|
towgo.SetFunc(_methodHead+"/user/changepassword", userChangepassword)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPhoneNumber(input string) bool {
|
||||||
|
// 中国手机号码正则表达式
|
||||||
|
// 13[0-9], 14[5,7,9], 15[0-3,5-9], 16[6], 17[0-8], 18[0-9], 19[1,8,9]
|
||||||
|
phoneNumberPattern := `^1([38][0-9]|14[579]|5[^4]|6[6]|7[0-8]|9[189])\d{8}$`
|
||||||
|
reg := regexp.MustCompile(phoneNumberPattern)
|
||||||
|
return reg.MatchString(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLoginOrRegSMSVerificationCode(rpcConn towgo.JsonRpcConnection) {
|
||||||
|
var params struct {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
}
|
||||||
|
rpcConn.ReadParams(¶ms)
|
||||||
|
|
||||||
|
if !isPhoneNumber(params.Mobile) {
|
||||||
|
rpcConn.WriteError(500, "手机号码非法")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
code, err := StoreLoginOrloginOrRegSMSVerificationCode(params.Mobile)
|
||||||
|
if err != nil {
|
||||||
|
rpcConn.WriteError(500, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Print("code = ", code)
|
||||||
|
/* err = tencent.SendSMSVerificationCode("2030693", "蕊鑫信息科技", params.Mobile, code)
|
||||||
|
if err != nil {
|
||||||
|
rpcConn.WriteError(500, err.Error())
|
||||||
|
return
|
||||||
|
}*/
|
||||||
|
|
||||||
|
rpcConn.WriteResult("验证码已经发送,请查收")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册用户
|
||||||
|
func userRegByMobile(rpcConn towgo.JsonRpcConnection) {
|
||||||
|
result := map[string]interface{}{} //初始化结果参数
|
||||||
|
|
||||||
|
var params struct {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
VerificationCode string `json:"verification_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcConn.ReadParams(¶ms)
|
||||||
|
|
||||||
|
if params.Mobile == "" {
|
||||||
|
rpcConn.WriteError(500, "手机号码不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if params.VerificationCode == "" {
|
||||||
|
rpcConn.WriteError(500, "验证码不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !LoginOrRegSMSVerification(params.Mobile, params.VerificationCode) {
|
||||||
|
rpcConn.WriteError(500, "验证码错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var user User
|
||||||
|
user.Username = params.Mobile
|
||||||
|
user.Password = randCharNumber(8)
|
||||||
|
|
||||||
|
/*
|
||||||
|
user := user{}
|
||||||
|
user.Nickname = jsonObj.Params.Nickname
|
||||||
|
user.Email = jsonObj.Params.Email
|
||||||
|
*/
|
||||||
|
Err := user.Reg(user.Username, user.Password)
|
||||||
|
if Err != nil {
|
||||||
|
rpcConn.WriteError(500, Err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//拼装结果返回
|
||||||
|
result["id"] = user.ID
|
||||||
|
result["username"] = user.Username
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户登陆
|
||||||
|
func userLogin(rpcConn towgo.JsonRpcConnection) {
|
||||||
|
result := map[string]interface{}{} //初始化结果参数
|
||||||
|
var err error
|
||||||
|
|
||||||
|
rpcResponse := rpcConn.GetRpcResponse()
|
||||||
|
jsonObj := struct {
|
||||||
|
Params struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
} `json:"params"`
|
||||||
|
}{}
|
||||||
|
err = json.Unmarshal([]byte(rpcConn.Read()), &jsonObj)
|
||||||
|
if err != nil {
|
||||||
|
rpcResponse.Error.Set(1, err.Error())
|
||||||
|
rpcConn.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if jsonObj.Params.Username == "" {
|
||||||
|
rpcResponse.Error.Set(1001, "")
|
||||||
|
rpcConn.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if jsonObj.Params.Password == "" {
|
||||||
|
rpcResponse.Error.Set(1002, "")
|
||||||
|
rpcConn.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{}
|
||||||
|
loginErr := user.Login(jsonObj.Params.Username, jsonObj.Params.Password)
|
||||||
|
|
||||||
|
if loginErr != nil { //模型层登陆成功
|
||||||
|
//dblog.Write("user:info", fmt.Sprintf("%s@%s 登录失败! 错误信息:%s", user.Username, rpcConn.GetRemoteAddr(), loginErr.Error()))
|
||||||
|
rpcResponse.Error.Set(1, "用户名或密码错误")
|
||||||
|
rpcConn.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result["id"] = user.ID
|
||||||
|
result["username"] = user.Username
|
||||||
|
|
||||||
|
result["token"] = user.UserToken.TokenKey
|
||||||
|
|
||||||
|
//dblog.Write("user:info", fmt.Sprintf("%s@%s 登录成功!", user.Username, rpcConn.GetRemoteAddr()))
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户手机验证码登陆
|
||||||
|
func userLoginOrRegByMobile(rpcConn towgo.JsonRpcConnection) {
|
||||||
|
|
||||||
|
var params struct {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
VerificationCode string `json:"verification_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcConn.ReadParams(¶ms)
|
||||||
|
|
||||||
|
if params.Mobile == "" {
|
||||||
|
rpcConn.WriteError(500, "手机号码不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if params.VerificationCode == "" {
|
||||||
|
rpcConn.WriteError(500, "验证码不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !LoginOrRegSMSVerification(params.Mobile, params.VerificationCode) {
|
||||||
|
rpcConn.WriteError(500, "验证码错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//验证通过
|
||||||
|
|
||||||
|
user := User{}
|
||||||
|
|
||||||
|
basedboperat.Get(&user, nil, "username = ?", params.Mobile)
|
||||||
|
|
||||||
|
if user.ID > 0 {
|
||||||
|
loginErr := user.LoginNoAuth(params.Mobile)
|
||||||
|
|
||||||
|
if loginErr != nil { //模型层登陆成功
|
||||||
|
log.Print(loginErr.Error())
|
||||||
|
//dblog.Write("user:info", fmt.Sprintf("%s@%s 登录失败! 错误信息:%s", user.Username, rpcConn.GetRemoteAddr(), loginErr.Error()))
|
||||||
|
rpcConn.WriteError(500, "用户名或密码错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Password = ""
|
||||||
|
user.Salt = ""
|
||||||
|
|
||||||
|
//dblog.Write("user:info", fmt.Sprintf("%s@%s 登录成功!", user.Username, rpcConn.GetRemoteAddr()))
|
||||||
|
rpcConn.WriteResult(user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Username = params.Mobile
|
||||||
|
user.Password = randCharNumber(8)
|
||||||
|
|
||||||
|
Err := user.Reg(user.Username, user.Password)
|
||||||
|
if Err != nil {
|
||||||
|
rpcConn.WriteError(500, Err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Password = ""
|
||||||
|
user.Salt = ""
|
||||||
|
rpcConn.WriteResult(user)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// token check
|
||||||
|
func userTokenCheck(rpcConn towgo.JsonRpcConnection) {
|
||||||
|
result := map[string]interface{}{} //初始化结果参数
|
||||||
|
var err error
|
||||||
|
|
||||||
|
rpcResponse := rpcConn.GetRpcResponse()
|
||||||
|
jsonObj := struct {
|
||||||
|
Session string `json:"session"`
|
||||||
|
Params struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Userid int `json:"userid"`
|
||||||
|
Token string `json:"token"`
|
||||||
|
} `json:"params"`
|
||||||
|
}{}
|
||||||
|
err = json.Unmarshal([]byte(rpcConn.Read()), &jsonObj)
|
||||||
|
if err != nil {
|
||||||
|
rpcResponse.Error.Set(1, err.Error())
|
||||||
|
rpcConn.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var user *User
|
||||||
|
user, err = user.LoginByToken(jsonObj.Params.Token)
|
||||||
|
if err != nil {
|
||||||
|
result["valid"] = false
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if user.ID == 0 {
|
||||||
|
result["valid"] = false
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !user.UserToken.Valid() {
|
||||||
|
result["valid"] = false
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result["valid"] = true
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户注销
|
||||||
|
func userLogoff(rpcConn towgo.JsonRpcConnection) {
|
||||||
|
//result := map[string]interface{}{} //初始化结果参数
|
||||||
|
var err error
|
||||||
|
|
||||||
|
rpcResponse := rpcConn.GetRpcResponse()
|
||||||
|
jsonObj := struct {
|
||||||
|
Session string `json:"session"`
|
||||||
|
}{}
|
||||||
|
err = json.Unmarshal([]byte(rpcConn.Read()), &jsonObj)
|
||||||
|
if err != nil {
|
||||||
|
rpcResponse.Error.Set(1, err.Error())
|
||||||
|
rpcConn.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var user *User
|
||||||
|
user, err = user.LoginByToken(jsonObj.Session)
|
||||||
|
if err != nil {
|
||||||
|
rpcConn.WriteResult(map[string]string{"success": "ok"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if user.ID > 0 {
|
||||||
|
user.Logoff()
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcConn.WriteResult(map[string]string{"success": "ok"})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func userMyinfo(rpcConn towgo.JsonRpcConnection) {
|
||||||
|
userSession, err := LoginByToken(rpcConn.GetRpcRequest().Session)
|
||||||
|
userSession.Token = rpcConn.GetRpcRequest().Session
|
||||||
|
if err != nil {
|
||||||
|
rpcConn.GetRpcResponse().Error.Set(401, err.Error())
|
||||||
|
rpcConn.Write()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rpcConn.WriteResult(userSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
func userChangepassword(rpcConn towgo.JsonRpcConnection) {
|
||||||
|
result := map[string]interface{}{} //初始化结果参数
|
||||||
|
var err error
|
||||||
|
|
||||||
|
rpcResponse := rpcConn.GetRpcResponse()
|
||||||
|
jsonObj := struct {
|
||||||
|
Session string `json:"session"`
|
||||||
|
Params struct {
|
||||||
|
Oldpassword string `json:"oldpassword"`
|
||||||
|
Newpassword string `json:"newpassword"`
|
||||||
|
} `json:"params"`
|
||||||
|
}{}
|
||||||
|
err = json.Unmarshal([]byte(rpcConn.Read()), &jsonObj)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
rpcResponse.Error.Set(1, err.Error())
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var user *User
|
||||||
|
user, err = user.LoginByToken(jsonObj.Session)
|
||||||
|
if err != nil {
|
||||||
|
rpcResponse.Error.Set(401, err.Error())
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.ID == 0 {
|
||||||
|
rpcResponse.Error.Set(1003, "")
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = user.Changepassword(jsonObj.Params.Oldpassword, jsonObj.Params.Newpassword)
|
||||||
|
if err != nil {
|
||||||
|
rpcResponse.Error.Set(1, err.Error())
|
||||||
|
rpcConn.WriteResult(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcConn.WriteResult(struct {
|
||||||
|
Success string `json:"success"`
|
||||||
|
}{Success: "ok"})
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package usercenter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/towgo/towgo/dao/ormDriver/xormDriver"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _methodHead string
|
||||||
|
var _tableHead string
|
||||||
|
|
||||||
|
func SetMethodHead(methodHead string) {
|
||||||
|
_methodHead = methodHead
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetTableHead(tableHead string) {
|
||||||
|
_tableHead = tableHead
|
||||||
|
}
|
||||||
|
|
||||||
|
func initLoader() {
|
||||||
|
|
||||||
|
//token任务
|
||||||
|
InitTokenTask()
|
||||||
|
|
||||||
|
xormDriver.Sync2(new(User), new(UserToken))
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,331 @@
|
|||||||
|
package usercenter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/towgo/towgo/dao/basedboperat"
|
||||||
|
"github.com/towgo/towgo/lib/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (User) TableName() string {
|
||||||
|
return _tableHead + "users"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*User) CacheExpire() int64 {
|
||||||
|
return 5000
|
||||||
|
}
|
||||||
|
|
||||||
|
// 账户对象 关联账户信息
|
||||||
|
type User struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Nickname string `json:"nickname"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Salt string `json:"-"` //密码加盐
|
||||||
|
Email string `json:"email"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
CanDelete bool `json:"-"`
|
||||||
|
AccessToken string `json:"-"`
|
||||||
|
Token string `json:"token" gorm:"-" xorm:"-"`
|
||||||
|
UserToken *UserToken `json:"-" gorm:"-" xorm:"-"`
|
||||||
|
CreatedAt int64 `json:"created_at"` //创建时间
|
||||||
|
UpdatedAt int64 `json:"updated_at"` //更新时间
|
||||||
|
GroupID int64 `json:"group_id"` // 用户组ID
|
||||||
|
Avatar string `json:"avatar"` // 用户头像
|
||||||
|
Birthday string `json:"birthday"` // 用户生日
|
||||||
|
Money string `json:"money"` // 用户资金
|
||||||
|
Score int64 `json:"score"` // 用户积分
|
||||||
|
//Verification Verification `json:"verification"` // 用户验证信息
|
||||||
|
ChildUserCount int64 `json:"child_user_count"` // 子用户数量
|
||||||
|
ChildUserCount1 int64 `json:"child_user_count_1"` // 第一层子用户数量
|
||||||
|
ChildUserCount2 int64 `json:"child_user_count_2"` // 第二层子用户数量
|
||||||
|
TotalConsume string `json:"total_consume"` // 总消费金额
|
||||||
|
UserID int64 `json:"user_id" xorm:"-"` // 用户ID
|
||||||
|
Createtime int64 `json:"createtime"` // 创建时间
|
||||||
|
Expiretime int64 `json:"expiretime"` // 过期时间
|
||||||
|
ExpiresIn int64 `json:"expires_in"` // 过期时长
|
||||||
|
//Group Group `json:"group"` // 用户组信息
|
||||||
|
}
|
||||||
|
|
||||||
|
type Verification struct {
|
||||||
|
Email int `json:"email"` // 邮箱验证状态
|
||||||
|
Mobile int `json:"mobile"` // 手机验证状态
|
||||||
|
}
|
||||||
|
|
||||||
|
type Group struct {
|
||||||
|
Name string `json:"name"` // 用户组名
|
||||||
|
Image string `json:"image"` // 用户组图片
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册
|
||||||
|
func (a *User) Reg(username, password string) error {
|
||||||
|
|
||||||
|
e := a.CheckForInput(username, password)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
//数据库查询出用户信息
|
||||||
|
|
||||||
|
finduser := User{}
|
||||||
|
basedboperat.Get(&finduser, nil, "username = ?", username)
|
||||||
|
|
||||||
|
//检查用户名是否存在
|
||||||
|
if username == finduser.Username {
|
||||||
|
return errors.New("账户已经存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成密码
|
||||||
|
a.NewPassword(password)
|
||||||
|
|
||||||
|
a.Username = username
|
||||||
|
a.Mobile = username
|
||||||
|
a.CanDelete = true
|
||||||
|
|
||||||
|
_, err := basedboperat.Create(a) // 通过数据的指针来创建
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = a.CreateRelation()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查输入参数
|
||||||
|
func (a *User) CheckForInput(username, password string) error {
|
||||||
|
|
||||||
|
if username == "" {
|
||||||
|
return errors.New("用户名不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if password == "" {
|
||||||
|
return errors.New("密码不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
//防sql注入
|
||||||
|
if system.FilteredSQLInject(username) {
|
||||||
|
return errors.New("用户名存在系统保留或非法的字符")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *User) NewPassword(newpassword string) {
|
||||||
|
if newpassword == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//加密密码
|
||||||
|
|
||||||
|
password := system.MD5(newpassword)
|
||||||
|
|
||||||
|
//生成salt
|
||||||
|
salt := system.RandCharCrypto(6)
|
||||||
|
|
||||||
|
//密码加盐
|
||||||
|
password = password + salt
|
||||||
|
|
||||||
|
//混合加密
|
||||||
|
password = system.MD5(password)
|
||||||
|
|
||||||
|
a.Password = password
|
||||||
|
a.Salt = salt
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户登陆
|
||||||
|
func (a *User) Login(username, password string) error {
|
||||||
|
|
||||||
|
erro := a.CheckForInput(username, password)
|
||||||
|
if erro != nil {
|
||||||
|
return erro
|
||||||
|
}
|
||||||
|
|
||||||
|
//通过用户名查询用户数据
|
||||||
|
err := basedboperat.Get(a, nil, "username = ?", username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//检查用户名是否存在
|
||||||
|
|
||||||
|
//判断用户是否存在
|
||||||
|
if a.Username == "" {
|
||||||
|
return errors.New("用户名不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
//加密密码
|
||||||
|
upassword := system.MD5(password)
|
||||||
|
|
||||||
|
//撒盐
|
||||||
|
upassword = upassword + a.Salt
|
||||||
|
|
||||||
|
//混合加密
|
||||||
|
upassword = system.MD5(upassword)
|
||||||
|
|
||||||
|
//判断密码是否一致
|
||||||
|
if a.Password != upassword {
|
||||||
|
//不一致:返回错误
|
||||||
|
return errors.New("密码错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
//验证通过
|
||||||
|
|
||||||
|
//生成用户信息
|
||||||
|
a.UserToken = NewToken(a)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户登陆
|
||||||
|
func (a *User) LoginNoAuth(username string) error {
|
||||||
|
|
||||||
|
//通过用户名查询用户数据
|
||||||
|
err := basedboperat.Get(a, nil, "username = ?", username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//检查用户名是否存在
|
||||||
|
|
||||||
|
//判断用户是否存在
|
||||||
|
if a.Username == "" {
|
||||||
|
return errors.New("用户名不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
//验证通过
|
||||||
|
|
||||||
|
//生成用户信息
|
||||||
|
a.UserToken = NewToken(a)
|
||||||
|
a.Token = a.UserToken.TokenKey
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户注销
|
||||||
|
func (a *User) Logoff() {
|
||||||
|
DeleteToken(a.UserToken.TokenKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoginByToken(tokenKey string) (*User, error) {
|
||||||
|
userToken, err := GetToken(tokenKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sessionuser := userToken.Payload.(*User)
|
||||||
|
sessionuser.UserToken = userToken
|
||||||
|
return sessionuser, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *User) LoginByToken(tokenKey string) (*User, error) {
|
||||||
|
userToken, err := GetToken(tokenKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sessionuser := userToken.Payload.(*User)
|
||||||
|
sessionuser.UserToken = userToken
|
||||||
|
return sessionuser, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *User) CheckToken(s string) bool {
|
||||||
|
//判断token是否正确
|
||||||
|
if s != a.UserToken.TokenKey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
//再判断token是否过期
|
||||||
|
return a.UserToken.Valid()
|
||||||
|
}
|
||||||
|
func (a *User) Get() error {
|
||||||
|
|
||||||
|
if a.ID > 0 {
|
||||||
|
return basedboperat.Get(a, nil, "id = ?", a.ID)
|
||||||
|
}
|
||||||
|
if a.Username != "" {
|
||||||
|
return basedboperat.Get(a, nil, "username = ?", a.Username)
|
||||||
|
}
|
||||||
|
return errors.New("id或username不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改密码
|
||||||
|
func (a *User) Changepassword(oldpassword, newpassword string) error {
|
||||||
|
|
||||||
|
//通过用户名查询用户数据
|
||||||
|
|
||||||
|
err := basedboperat.Get(a, nil, "id = ?", a.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//检查用户名是否存在
|
||||||
|
|
||||||
|
//判断用户是否存在
|
||||||
|
if a.Username == "" {
|
||||||
|
return errors.New("用户名不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
//加密密码
|
||||||
|
upassword := system.MD5(oldpassword)
|
||||||
|
|
||||||
|
//撒盐
|
||||||
|
upassword = upassword + a.Salt
|
||||||
|
|
||||||
|
//混合加密
|
||||||
|
upassword = system.MD5(upassword)
|
||||||
|
|
||||||
|
//判断密码是否一致
|
||||||
|
if a.Password != upassword {
|
||||||
|
//不一致:返回错误
|
||||||
|
return errors.New("原始密码错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
a.NewPassword(newpassword)
|
||||||
|
|
||||||
|
basedboperat.Update(a, []string{"password", "salt"}, "id = ?", a.ID)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *User) Update() error {
|
||||||
|
var findModel User
|
||||||
|
basedboperat.Get(&findModel, nil, "id = ?", a.ID)
|
||||||
|
if findModel.ID <= 0 {
|
||||||
|
return errors.New("记录不存在")
|
||||||
|
}
|
||||||
|
a.DeleteRelation()
|
||||||
|
_, err := a.CreateRelation()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
basedboperat.Update(a, []string{"nickname", "email"}, "id = ?", a.ID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *User) Delete() (int64, error) {
|
||||||
|
var findModel User
|
||||||
|
basedboperat.Get(&findModel, nil, "id = ?", a.ID)
|
||||||
|
if !findModel.CanDelete {
|
||||||
|
return 0, errors.New("无法删除系统用户")
|
||||||
|
}
|
||||||
|
a.DeleteRelation()
|
||||||
|
return basedboperat.Delete(a, a.ID, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除关联数据
|
||||||
|
func (a *User) DeleteRelation() {
|
||||||
|
if a.ID == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建关联数据
|
||||||
|
func (a *User) CreateRelation() (int64, error) {
|
||||||
|
if a.ID == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
var rowsAffected int64
|
||||||
|
|
||||||
|
return rowsAffected, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *User) AfterQuery() {
|
||||||
|
if a.ID == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.UserID = a.ID
|
||||||
|
}
|
||||||
@ -0,0 +1,227 @@
|
|||||||
|
package usercenter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/towgo/towgo/dao/basedboperat"
|
||||||
|
"github.com/towgo/towgo/lib/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 缓存有效期
|
||||||
|
var memCacheTimer int64 = 60 * 10
|
||||||
|
|
||||||
|
// token有效期 秒单位计算
|
||||||
|
var expirationLimit int64 = 86400 * 20
|
||||||
|
|
||||||
|
var autoClearLimit int64 = 60 * 10 //10分钟清理一次过期的token
|
||||||
|
|
||||||
|
// var expirationLimit int64 = 60
|
||||||
|
var memCache *MemCache
|
||||||
|
|
||||||
|
// UserToken结构体
|
||||||
|
func (UserToken) TableName() string {
|
||||||
|
return _tableHead + "users_token"
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserToken struct {
|
||||||
|
TokenKey string
|
||||||
|
Uid int64
|
||||||
|
Payload any `gorm:"-" xorm:"-"`
|
||||||
|
Expiration int64
|
||||||
|
UpdatedAt int64
|
||||||
|
CreatedAt int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitTokenTask() {
|
||||||
|
memCache = &MemCache{}
|
||||||
|
autoTimeToClear()
|
||||||
|
}
|
||||||
|
|
||||||
|
type MemCache struct {
|
||||||
|
timers sync.Map
|
||||||
|
cacheObject sync.Map
|
||||||
|
cancels sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MemCache) CreateTimerToDelete(tokenKey string) {
|
||||||
|
timer := time.NewTimer(time.Second * time.Duration(memCacheTimer))
|
||||||
|
mc.timers.Store(tokenKey, timer)
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
mc.cancels.Store(tokenKey, cancel)
|
||||||
|
go mc.DeleteWhenTimeOut(ctx, tokenKey, timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MemCache) DeleteWhenTimeOut(ctx context.Context, tokenKey string, timer *time.Timer) {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
mc.timers.Delete(tokenKey)
|
||||||
|
mc.cacheObject.Delete(tokenKey)
|
||||||
|
mc.cancels.Delete(tokenKey)
|
||||||
|
return
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MemCache) ResetTimer(tokenKey string) {
|
||||||
|
timerInterface, ok := mc.timers.Load(tokenKey)
|
||||||
|
if ok {
|
||||||
|
timer := timerInterface.(*time.Timer)
|
||||||
|
timer.Reset(time.Second * time.Duration(memCacheTimer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MemCache) Add(tokenKey string, value any) {
|
||||||
|
mc.cacheObject.Store(tokenKey, value)
|
||||||
|
mc.CreateTimerToDelete(tokenKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MemCache) Del(tokenKey string) {
|
||||||
|
timerInterface, ok := mc.timers.Load(tokenKey)
|
||||||
|
if ok {
|
||||||
|
timer := timerInterface.(*time.Timer)
|
||||||
|
timer.Stop() //关闭定时器
|
||||||
|
cancel_any, isLoaded := mc.cancels.LoadAndDelete(tokenKey) //关闭定时器线程
|
||||||
|
if isLoaded {
|
||||||
|
cancel := cancel_any.(context.CancelFunc)
|
||||||
|
if cancel != nil {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mc.timers.Delete(tokenKey) //清除定时器委托
|
||||||
|
}
|
||||||
|
mc.cacheObject.Delete(tokenKey) //清除内存
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MemCache) Get(tokenKey string) (any, bool) {
|
||||||
|
return mc.cacheObject.Load(tokenKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动清理过期token定时器
|
||||||
|
func autoTimeToClear() {
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
err := recover()
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
autoTimeToClear()
|
||||||
|
}()
|
||||||
|
var userToken UserToken
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Second * time.Duration(autoClearLimit))
|
||||||
|
basedboperat.SqlExec("delete from "+userToken.TableName()+" where expiration < ?", time.Now().Unix())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *UserToken) NewTokenGUID(salt string) {
|
||||||
|
guid := system.GetGUID().Hex()
|
||||||
|
saltEncode := system.MD5(salt)
|
||||||
|
tokenCode := system.MD5(guid + saltEncode)
|
||||||
|
t.TokenKey = tokenCode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回一个唯一标识的token令牌
|
||||||
|
func (t *UserToken) String() string {
|
||||||
|
return t.TokenKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// token是否有效 检查有效期
|
||||||
|
// 有效返回true
|
||||||
|
// 无效返回false
|
||||||
|
func (t *UserToken) Valid() bool {
|
||||||
|
return time.Now().Unix() < t.Expiration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *UserToken) Check(tokenKey string) bool {
|
||||||
|
return tokenKey == t.TokenKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新token有效期
|
||||||
|
func (t *UserToken) Update(expiration int64) {
|
||||||
|
if expiration > 0 {
|
||||||
|
t.Expiration = time.Now().Unix() + expiration
|
||||||
|
} else {
|
||||||
|
t.Expiration = time.Now().Unix() + expirationLimit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新建一个token
|
||||||
|
func NewToken(user *User) *UserToken {
|
||||||
|
timenow := time.Now().Unix()
|
||||||
|
token := &UserToken{
|
||||||
|
CreatedAt: timenow,
|
||||||
|
Uid: user.ID,
|
||||||
|
Payload: user,
|
||||||
|
Expiration: timenow + expirationLimit,
|
||||||
|
}
|
||||||
|
user.Token = token.TokenKey
|
||||||
|
token.NewTokenGUID(user.Salt)
|
||||||
|
basedboperat.Create(token)
|
||||||
|
memCache.Add(token.TokenKey, token)
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetToken(tokenKey string) (*UserToken, error) {
|
||||||
|
var userToken *UserToken = &UserToken{}
|
||||||
|
|
||||||
|
//缓存查询
|
||||||
|
userTokenInterface, ok := memCache.Get(tokenKey)
|
||||||
|
if ok {
|
||||||
|
//缓存命中
|
||||||
|
userToken = userTokenInterface.(*UserToken)
|
||||||
|
//缓存过期 清理
|
||||||
|
if !userToken.Valid() {
|
||||||
|
memCache.Del(tokenKey)
|
||||||
|
return nil, errors.New("token过期(登录失效,请重新登录)")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//数据库查询
|
||||||
|
|
||||||
|
//查询持久化数据
|
||||||
|
err := basedboperat.Get(userToken, nil, "token_key = ?", tokenKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if userToken.Uid == 0 {
|
||||||
|
return nil, errors.New("token不存在(登录失效,请重新登录)") //数据不存在
|
||||||
|
}
|
||||||
|
|
||||||
|
//token过期
|
||||||
|
if !userToken.Valid() {
|
||||||
|
return nil, errors.New("token过期(登录失效,请重新登录)")
|
||||||
|
}
|
||||||
|
|
||||||
|
//查询token关联的用户
|
||||||
|
var user *User = &User{}
|
||||||
|
basedboperat.Get(user, nil, "id = ?", userToken.Uid)
|
||||||
|
if user.ID == 0 {
|
||||||
|
return nil, errors.New("token关联用户不存在(登录失效,请重新登录)") //用户不存在
|
||||||
|
}
|
||||||
|
|
||||||
|
//写入缓存
|
||||||
|
userToken.Payload = user
|
||||||
|
memCache.Add(userToken.TokenKey, userToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
return userToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteToken(tokenKey string) {
|
||||||
|
memCache.Del(tokenKey)
|
||||||
|
var userToken *UserToken = &UserToken{}
|
||||||
|
userToken.TokenKey = tokenKey
|
||||||
|
|
||||||
|
basedboperat.Delete(userToken, nil, "token_key = ?", tokenKey)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetExpiration(hour int64) {
|
||||||
|
expirationLimit = 3600 * hour
|
||||||
|
}
|
||||||
Loading…
Reference in new issue