Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Litemall
Commits
fbc7dc6a
Commit
fbc7dc6a
authored
Jan 30, 2019
by
Junling Bu
Browse files
chore[litemall-admin-api, litemall-wx-api]: 取消编程式事务管理,采用@Transactional注解事务管理
parent
714870bf
Changes
7
Hide whitespace changes
Inline
Side-by-side
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/job/OrderJob.java
View file @
fbc7dc6a
...
...
@@ -5,15 +5,14 @@ import org.apache.commons.logging.LogFactory;
import
org.linlinjava.litemall.db.domain.LitemallGoodsProduct
;
import
org.linlinjava.litemall.db.domain.LitemallOrder
;
import
org.linlinjava.litemall.db.domain.LitemallOrderGoods
;
import
org.linlinjava.litemall.db.service.*
;
import
org.linlinjava.litemall.db.service.LitemallGoodsProductService
;
import
org.linlinjava.litemall.db.service.LitemallOrderGoodsService
;
import
org.linlinjava.litemall.db.service.LitemallOrderService
;
import
org.linlinjava.litemall.db.util.OrderUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
org.springframework.transaction.PlatformTransactionManager
;
import
org.springframework.transaction.TransactionDefinition
;
import
org.springframework.transaction.TransactionStatus
;
import
org.springframework.transaction.support.DefaultTransactionDefinition
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.time.LocalDateTime
;
import
java.util.List
;
...
...
@@ -25,9 +24,6 @@ import java.util.List;
public
class
OrderJob
{
private
final
Log
logger
=
LogFactory
.
getLog
(
OrderJob
.
class
);
@Autowired
private
PlatformTransactionManager
txManager
;
@Autowired
private
LitemallOrderGoodsService
orderGoodsService
;
@Autowired
...
...
@@ -46,6 +42,7 @@ public class OrderJob {
* 这里可以进一步地配合用户订单查询时订单未付款检查,如果订单超时半小时则取消。
*/
@Scheduled
(
fixedDelay
=
30
*
60
*
1000
)
@Transactional
public
void
checkOrderUnpaid
()
{
logger
.
info
(
"系统开启任务检查订单是否已经超期自动取消订单"
);
...
...
@@ -58,35 +55,24 @@ public class OrderJob {
continue
;
}
// 开启事务管理
DefaultTransactionDefinition
def
=
new
DefaultTransactionDefinition
();
def
.
setPropagationBehavior
(
TransactionDefinition
.
PROPAGATION_REQUIRED
);
TransactionStatus
status
=
txManager
.
getTransaction
(
def
);
try
{
// 设置订单已取消状态
order
.
setOrderStatus
(
OrderUtil
.
STATUS_AUTO_CANCEL
);
order
.
setEndTime
(
LocalDateTime
.
now
());
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
throw
new
Exception
(
"更新数据已失效"
);
}
// 设置订单已取消状态
order
.
setOrderStatus
(
OrderUtil
.
STATUS_AUTO_CANCEL
);
order
.
setEndTime
(
LocalDateTime
.
now
());
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
throw
new
RuntimeException
(
"更新数据已失效"
);
}
// 商品货品数量增加
Integer
orderId
=
order
.
getId
();
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
orderId
);
for
(
LitemallOrderGoods
orderGoods
:
orderGoodsList
)
{
Integer
productId
=
orderGoods
.
getProductId
();
LitemallGoodsProduct
product
=
productService
.
findById
(
productId
);
Short
number
=
orderGoods
.
getNumber
();
if
(
productService
.
addStock
(
productId
,
number
)
==
0
)
{
throw
new
Exception
(
"商品货品库存增加失败"
);
}
// 商品货品数量增加
Integer
orderId
=
order
.
getId
();
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
orderId
);
for
(
LitemallOrderGoods
orderGoods
:
orderGoodsList
)
{
Integer
productId
=
orderGoods
.
getProductId
();
LitemallGoodsProduct
product
=
productService
.
findById
(
productId
);
Short
number
=
orderGoods
.
getNumber
();
if
(
productService
.
addStock
(
productId
,
number
)
==
0
)
{
throw
new
RuntimeException
(
"商品货品库存增加失败"
);
}
}
catch
(
Exception
ex
)
{
txManager
.
rollback
(
status
);
logger
.
info
(
"订单 ID="
+
order
.
getId
()
+
" 数据更新失败,放弃自动确认收货"
);
return
;
}
txManager
.
commit
(
status
);
logger
.
info
(
"订单 ID="
+
order
.
getId
()
+
" 已经超期自动取消订单"
);
}
}
...
...
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/AdminGoodsService.java
0 → 100644
View file @
fbc7dc6a
package
org.linlinjava.litemall.admin.service
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.linlinjava.litemall.admin.dao.GoodsAllinone
;
import
org.linlinjava.litemall.admin.util.CatVo
;
import
org.linlinjava.litemall.core.qcode.QCodeService
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.db.domain.*
;
import
org.linlinjava.litemall.db.service.*
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.StringUtils
;
import
java.math.BigDecimal
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
linlinjava
.
litemall
.
admin
.
util
.
AdminResponseCode
.
GOODS_NAME_EXIST
;
import
static
org
.
linlinjava
.
litemall
.
admin
.
util
.
AdminResponseCode
.
GOODS_UPDATE_NOT_ALLOWED
;
@Service
public
class
AdminGoodsService
{
private
final
Log
logger
=
LogFactory
.
getLog
(
AdminGoodsService
.
class
);
@Autowired
private
LitemallGoodsService
goodsService
;
@Autowired
private
LitemallGoodsSpecificationService
specificationService
;
@Autowired
private
LitemallGoodsAttributeService
attributeService
;
@Autowired
private
LitemallGoodsProductService
productService
;
@Autowired
private
LitemallCategoryService
categoryService
;
@Autowired
private
LitemallBrandService
brandService
;
@Autowired
private
LitemallCartService
cartService
;
@Autowired
private
LitemallOrderGoodsService
orderGoodsService
;
@Autowired
private
QCodeService
qCodeService
;
public
Object
list
(
String
goodsSn
,
String
name
,
Integer
page
,
Integer
limit
,
String
sort
,
String
order
)
{
List
<
LitemallGoods
>
goodsList
=
goodsService
.
querySelective
(
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
int
total
=
goodsService
.
countSelective
(
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"total"
,
total
);
data
.
put
(
"items"
,
goodsList
);
return
ResponseUtil
.
ok
(
data
);
}
private
Object
validate
(
GoodsAllinone
goodsAllinone
)
{
LitemallGoods
goods
=
goodsAllinone
.
getGoods
();
String
name
=
goods
.
getName
();
if
(
StringUtils
.
isEmpty
(
name
))
{
return
ResponseUtil
.
badArgument
();
}
String
goodsSn
=
goods
.
getGoodsSn
();
if
(
StringUtils
.
isEmpty
(
goodsSn
))
{
return
ResponseUtil
.
badArgument
();
}
// 品牌商可以不设置,如果设置则需要验证品牌商存在
Integer
brandId
=
goods
.
getBrandId
();
if
(
brandId
!=
null
&&
brandId
!=
0
)
{
if
(
brandService
.
findById
(
brandId
)
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
}
// 分类可以不设置,如果设置则需要验证分类存在
Integer
categoryId
=
goods
.
getCategoryId
();
if
(
categoryId
!=
null
&&
categoryId
!=
0
)
{
if
(
categoryService
.
findById
(
categoryId
)
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
}
LitemallGoodsAttribute
[]
attributes
=
goodsAllinone
.
getAttributes
();
for
(
LitemallGoodsAttribute
attribute
:
attributes
)
{
String
attr
=
attribute
.
getAttribute
();
if
(
StringUtils
.
isEmpty
(
attr
))
{
return
ResponseUtil
.
badArgument
();
}
String
value
=
attribute
.
getValue
();
if
(
StringUtils
.
isEmpty
(
value
))
{
return
ResponseUtil
.
badArgument
();
}
}
LitemallGoodsSpecification
[]
specifications
=
goodsAllinone
.
getSpecifications
();
for
(
LitemallGoodsSpecification
specification
:
specifications
)
{
String
spec
=
specification
.
getSpecification
();
if
(
StringUtils
.
isEmpty
(
spec
))
{
return
ResponseUtil
.
badArgument
();
}
String
value
=
specification
.
getValue
();
if
(
StringUtils
.
isEmpty
(
value
))
{
return
ResponseUtil
.
badArgument
();
}
}
LitemallGoodsProduct
[]
products
=
goodsAllinone
.
getProducts
();
for
(
LitemallGoodsProduct
product
:
products
)
{
Integer
number
=
product
.
getNumber
();
if
(
number
==
null
||
number
<
0
)
{
return
ResponseUtil
.
badArgument
();
}
BigDecimal
price
=
product
.
getPrice
();
if
(
price
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
String
[]
productSpecifications
=
product
.
getSpecifications
();
if
(
productSpecifications
.
length
==
0
)
{
return
ResponseUtil
.
badArgument
();
}
}
return
null
;
}
/**
* 编辑商品
* <p>
* TODO
* 目前商品修改的逻辑是
* 1. 更新litemall_goods表
* 2. 逻辑删除litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
* 3. 添加litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
* <p>
* 这里商品三个表的数据采用删除再添加的策略是因为
* 商品编辑页面,支持管理员添加删除商品规格、添加删除商品属性,因此这里仅仅更新是不可能的,
* 只能删除三个表旧的数据,然后添加新的数据。
* 但是这里又会引入新的问题,就是存在订单商品货品ID指向了失效的商品货品表。
* 因此这里会拒绝管理员编辑商品,如果订单或购物车中存在商品。
* 所以这里可能需要重新设计。
*/
@Transactional
public
Object
update
(
GoodsAllinone
goodsAllinone
)
{
Object
error
=
validate
(
goodsAllinone
);
if
(
error
!=
null
)
{
return
error
;
}
LitemallGoods
goods
=
goodsAllinone
.
getGoods
();
LitemallGoodsAttribute
[]
attributes
=
goodsAllinone
.
getAttributes
();
LitemallGoodsSpecification
[]
specifications
=
goodsAllinone
.
getSpecifications
();
LitemallGoodsProduct
[]
products
=
goodsAllinone
.
getProducts
();
Integer
id
=
goods
.
getId
();
// 检查是否存在购物车商品或者订单商品
// 如果存在则拒绝修改商品。
if
(
orderGoodsService
.
checkExist
(
id
))
{
return
ResponseUtil
.
fail
(
GOODS_UPDATE_NOT_ALLOWED
,
"商品已经在订单中,不能修改"
);
}
if
(
cartService
.
checkExist
(
id
))
{
return
ResponseUtil
.
fail
(
GOODS_UPDATE_NOT_ALLOWED
,
"商品已经在购物车中,不能修改"
);
}
//将生成的分享图片地址写入数据库
String
url
=
qCodeService
.
createGoodShareImage
(
goods
.
getId
().
toString
(),
goods
.
getPicUrl
(),
goods
.
getName
());
goods
.
setShareUrl
(
url
);
// 商品基本信息表litemall_goods
if
(
goodsService
.
updateById
(
goods
)
==
0
)
{
throw
new
RuntimeException
(
"更新数据失败"
);
}
Integer
gid
=
goods
.
getId
();
specificationService
.
deleteByGid
(
gid
);
attributeService
.
deleteByGid
(
gid
);
productService
.
deleteByGid
(
gid
);
// 商品规格表litemall_goods_specification
for
(
LitemallGoodsSpecification
specification
:
specifications
)
{
specification
.
setGoodsId
(
goods
.
getId
());
specificationService
.
add
(
specification
);
}
// 商品参数表litemall_goods_attribute
for
(
LitemallGoodsAttribute
attribute
:
attributes
)
{
attribute
.
setGoodsId
(
goods
.
getId
());
attributeService
.
add
(
attribute
);
}
// 商品货品表litemall_product
for
(
LitemallGoodsProduct
product
:
products
)
{
product
.
setGoodsId
(
goods
.
getId
());
productService
.
add
(
product
);
}
qCodeService
.
createGoodShareImage
(
goods
.
getId
().
toString
(),
goods
.
getPicUrl
(),
goods
.
getName
());
return
ResponseUtil
.
ok
();
}
@Transactional
public
Object
delete
(
LitemallGoods
goods
)
{
Integer
id
=
goods
.
getId
();
if
(
id
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
Integer
gid
=
goods
.
getId
();
goodsService
.
deleteById
(
gid
);
specificationService
.
deleteByGid
(
gid
);
attributeService
.
deleteByGid
(
gid
);
productService
.
deleteByGid
(
gid
);
return
ResponseUtil
.
ok
();
}
@Transactional
public
Object
create
(
GoodsAllinone
goodsAllinone
)
{
Object
error
=
validate
(
goodsAllinone
);
if
(
error
!=
null
)
{
return
error
;
}
LitemallGoods
goods
=
goodsAllinone
.
getGoods
();
LitemallGoodsAttribute
[]
attributes
=
goodsAllinone
.
getAttributes
();
LitemallGoodsSpecification
[]
specifications
=
goodsAllinone
.
getSpecifications
();
LitemallGoodsProduct
[]
products
=
goodsAllinone
.
getProducts
();
String
name
=
goods
.
getName
();
if
(
goodsService
.
checkExistByName
(
name
))
{
return
ResponseUtil
.
fail
(
GOODS_NAME_EXIST
,
"商品名已经存在"
);
}
// 商品基本信息表litemall_goods
goodsService
.
add
(
goods
);
//将生成的分享图片地址写入数据库
String
url
=
qCodeService
.
createGoodShareImage
(
goods
.
getId
().
toString
(),
goods
.
getPicUrl
(),
goods
.
getName
());
if
(!
StringUtils
.
isEmpty
(
url
))
{
goods
.
setShareUrl
(
url
);
if
(
goodsService
.
updateById
(
goods
)
==
0
)
{
throw
new
RuntimeException
(
"更新数据失败"
);
}
}
// 商品规格表litemall_goods_specification
for
(
LitemallGoodsSpecification
specification
:
specifications
)
{
specification
.
setGoodsId
(
goods
.
getId
());
specificationService
.
add
(
specification
);
}
// 商品参数表litemall_goods_attribute
for
(
LitemallGoodsAttribute
attribute
:
attributes
)
{
attribute
.
setGoodsId
(
goods
.
getId
());
attributeService
.
add
(
attribute
);
}
// 商品货品表litemall_product
for
(
LitemallGoodsProduct
product
:
products
)
{
product
.
setGoodsId
(
goods
.
getId
());
productService
.
add
(
product
);
}
return
ResponseUtil
.
ok
();
}
public
Object
list2
()
{
// http://element-cn.eleme.io/#/zh-CN/component/cascader
// 管理员设置“所属分类”
List
<
LitemallCategory
>
l1CatList
=
categoryService
.
queryL1
();
List
<
CatVo
>
categoryList
=
new
ArrayList
<>(
l1CatList
.
size
());
for
(
LitemallCategory
l1
:
l1CatList
)
{
CatVo
l1CatVo
=
new
CatVo
();
l1CatVo
.
setValue
(
l1
.
getId
());
l1CatVo
.
setLabel
(
l1
.
getName
());
List
<
LitemallCategory
>
l2CatList
=
categoryService
.
queryByPid
(
l1
.
getId
());
List
<
CatVo
>
children
=
new
ArrayList
<>(
l2CatList
.
size
());
for
(
LitemallCategory
l2
:
l2CatList
)
{
CatVo
l2CatVo
=
new
CatVo
();
l2CatVo
.
setValue
(
l2
.
getId
());
l2CatVo
.
setLabel
(
l2
.
getName
());
children
.
add
(
l2CatVo
);
}
l1CatVo
.
setChildren
(
children
);
categoryList
.
add
(
l1CatVo
);
}
// http://element-cn.eleme.io/#/zh-CN/component/select
// 管理员设置“所属品牌商”
List
<
LitemallBrand
>
list
=
brandService
.
all
();
List
<
Map
<
String
,
Object
>>
brandList
=
new
ArrayList
<>(
l1CatList
.
size
());
for
(
LitemallBrand
brand
:
list
)
{
Map
<
String
,
Object
>
b
=
new
HashMap
<>(
2
);
b
.
put
(
"value"
,
brand
.
getId
());
b
.
put
(
"label"
,
brand
.
getName
());
brandList
.
add
(
b
);
}
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"categoryList"
,
categoryList
);
data
.
put
(
"brandList"
,
brandList
);
return
ResponseUtil
.
ok
(
data
);
}
public
Object
detail
(
Integer
id
)
{
LitemallGoods
goods
=
goodsService
.
findById
(
id
);
List
<
LitemallGoodsProduct
>
products
=
productService
.
queryByGid
(
id
);
List
<
LitemallGoodsSpecification
>
specifications
=
specificationService
.
queryByGid
(
id
);
List
<
LitemallGoodsAttribute
>
attributes
=
attributeService
.
queryByGid
(
id
);
Integer
categoryId
=
goods
.
getCategoryId
();
LitemallCategory
category
=
categoryService
.
findById
(
categoryId
);
Integer
[]
categoryIds
=
new
Integer
[]{};
if
(
category
!=
null
)
{
Integer
parentCategoryId
=
category
.
getPid
();
categoryIds
=
new
Integer
[]{
parentCategoryId
,
categoryId
};
}
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"goods"
,
goods
);
data
.
put
(
"specifications"
,
specifications
);
data
.
put
(
"products"
,
products
);
data
.
put
(
"attributes"
,
attributes
);
data
.
put
(
"categoryIds"
,
categoryIds
);
return
ResponseUtil
.
ok
(
data
);
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/AdminOrderService.java
0 → 100644
View file @
fbc7dc6a
package
org.linlinjava.litemall.admin.service
;
import
com.github.binarywang.wxpay.bean.request.WxPayRefundRequest
;
import
com.github.binarywang.wxpay.bean.result.WxPayRefundResult
;
import
com.github.binarywang.wxpay.exception.WxPayException
;
import
com.github.binarywang.wxpay.service.WxPayService
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.linlinjava.litemall.core.notify.NotifyService
;
import
org.linlinjava.litemall.core.notify.NotifyType
;
import
org.linlinjava.litemall.core.util.JacksonUtil
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.db.domain.LitemallComment
;
import
org.linlinjava.litemall.db.domain.LitemallOrder
;
import
org.linlinjava.litemall.db.domain.LitemallOrderGoods
;
import
org.linlinjava.litemall.db.domain.UserVo
;
import
org.linlinjava.litemall.db.service.*
;
import
org.linlinjava.litemall.db.util.OrderUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.StringUtils
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
linlinjava
.
litemall
.
admin
.
util
.
AdminResponseCode
.*;
@Service
public
class
AdminOrderService
{
private
final
Log
logger
=
LogFactory
.
getLog
(
AdminOrderService
.
class
);
@Autowired
private
LitemallOrderGoodsService
orderGoodsService
;
@Autowired
private
LitemallOrderService
orderService
;
@Autowired
private
LitemallGoodsProductService
productService
;
@Autowired
private
LitemallUserService
userService
;
@Autowired
private
LitemallCommentService
commentService
;
@Autowired
private
WxPayService
wxPayService
;
@Autowired
private
NotifyService
notifyService
;
public
Object
list
(
Integer
userId
,
String
orderSn
,
List
<
Short
>
orderStatusArray
,
Integer
page
,
Integer
limit
,
String
sort
,
String
order
)
{
List
<
LitemallOrder
>
orderList
=
orderService
.
querySelective
(
userId
,
orderSn
,
orderStatusArray
,
page
,
limit
,
sort
,
order
);
int
total
=
orderService
.
countSelective
(
userId
,
orderSn
,
orderStatusArray
,
page
,
limit
,
sort
,
order
);
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"total"
,
total
);
data
.
put
(
"items"
,
orderList
);
return
ResponseUtil
.
ok
(
data
);
}
public
Object
detail
(
Integer
id
)
{
LitemallOrder
order
=
orderService
.
findById
(
id
);
List
<
LitemallOrderGoods
>
orderGoods
=
orderGoodsService
.
queryByOid
(
id
);
UserVo
user
=
userService
.
findUserVoById
(
order
.
getUserId
());
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"order"
,
order
);
data
.
put
(
"orderGoods"
,
orderGoods
);
data
.
put
(
"user"
,
user
);
return
ResponseUtil
.
ok
(
data
);
}
/**
* 订单退款
* <p>
* 1. 检测当前订单是否能够退款;
* 2. 微信退款操作;
* 3. 设置订单退款确认状态;
* 4. 订单商品库存回库。
* <p>
* TODO
* 虽然接入了微信退款API,但是从安全角度考虑,建议开发者删除这里微信退款代码,采用以下两步走步骤:
* 1. 管理员登录微信官方支付平台点击退款操作进行退款
* 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库
*
* @param body 订单信息,{ orderId:xxx }
* @return 订单退款操作结果
*/
@Transactional
public
Object
refund
(
String
body
)
{
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
String
refundMoney
=
JacksonUtil
.
parseString
(
body
,
"refundMoney"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(
StringUtils
.
isEmpty
(
refundMoney
))
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(
order
.
getActualPrice
().
compareTo
(
new
BigDecimal
(
refundMoney
))
!=
0
)
{
return
ResponseUtil
.
badArgumentValue
();
}
// 如果订单不是退款状态,则不能退款
if
(!
order
.
getOrderStatus
().
equals
(
OrderUtil
.
STATUS_REFUND
))
{
return
ResponseUtil
.
fail
(
ORDER_CONFIRM_NOT_ALLOWED
,
"订单不能确认收货"
);
}
// 微信退款
WxPayRefundRequest
wxPayRefundRequest
=
new
WxPayRefundRequest
();
wxPayRefundRequest
.
setOutTradeNo
(
order
.
getOrderSn
());
wxPayRefundRequest
.
setOutRefundNo
(
"refund_"
+
order
.
getOrderSn
());
// 元转成分
Integer
totalFee
=
order
.
getActualPrice
().
multiply
(
new
BigDecimal
(
100
)).
intValue
();
wxPayRefundRequest
.
setTotalFee
(
totalFee
);
wxPayRefundRequest
.
setRefundFee
(
totalFee
);
WxPayRefundResult
wxPayRefundResult
=
null
;
try
{
wxPayRefundResult
=
wxPayService
.
refund
(
wxPayRefundRequest
);
}
catch
(
WxPayException
e
)
{
e
.
printStackTrace
();
return
ResponseUtil
.
fail
(
ORDER_REFUND_FAILED
,
"订单退款失败"
);
}
if
(!
wxPayRefundResult
.
getReturnCode
().
equals
(
"SUCCESS"
))
{
logger
.
warn
(
"refund fail: "
+
wxPayRefundResult
.
getReturnMsg
());
return
ResponseUtil
.
fail
(
ORDER_REFUND_FAILED
,
"订单退款失败"
);
}
if
(!
wxPayRefundResult
.
getResultCode
().
equals
(
"SUCCESS"
))
{
logger
.
warn
(
"refund fail: "
+
wxPayRefundResult
.
getReturnMsg
());
return
ResponseUtil
.
fail
(
ORDER_REFUND_FAILED
,
"订单退款失败"
);
}
// 设置订单取消状态
order
.
setOrderStatus
(
OrderUtil
.
STATUS_REFUND_CONFIRM
);
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
throw
new
RuntimeException
(
"更新数据已失效"
);
}
// 商品货品数量增加
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
orderId
);
for
(
LitemallOrderGoods
orderGoods
:
orderGoodsList
)
{
Integer
productId
=
orderGoods
.
getProductId
();
Short
number
=
orderGoods
.
getNumber
();
if
(
productService
.
addStock
(
productId
,
number
)
==
0
)
{
throw
new
RuntimeException
(
"商品货品库存增加失败"
);
}
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功,请耐心等待到账。”
// 注意订单号只发后6位
notifyService
.
notifySmsTemplate
(
order
.
getMobile
(),
NotifyType
.
REFUND
,
new
String
[]{
order
.
getOrderSn
().
substring
(
8
,
14
)});
return
ResponseUtil
.
ok
();
}
/**
* 发货
* 1. 检测当前订单是否能够发货
* 2. 设置订单发货状态
*
* @param body 订单信息,{ orderId:xxx, shipSn: xxx, shipChannel: xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
public
Object
ship
(
String
body
)
{
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
String
shipSn
=
JacksonUtil
.
parseString
(
body
,
"shipSn"
);
String
shipChannel
=
JacksonUtil
.
parseString
(
body
,
"shipChannel"
);
if
(
orderId
==
null
||
shipSn
==
null
||
shipChannel
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
// 如果订单不是已付款状态,则不能发货
if
(!
order
.
getOrderStatus
().
equals
(
OrderUtil
.
STATUS_PAY
))
{
return
ResponseUtil
.
fail
(
ORDER_CONFIRM_NOT_ALLOWED
,
"订单不能确认收货"
);
}
order
.
setOrderStatus
(
OrderUtil
.
STATUS_SHIP
);
order
.
setShipSn
(
shipSn
);
order
.
setShipChannel
(
shipChannel
);
order
.
setShipTime
(
LocalDateTime
.
now
());
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
return
ResponseUtil
.
updatedDateExpired
();
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 发货会发送通知短信给用户: *
// "您的订单已经发货,快递公司 {1},快递单 {2} ,请注意查收"
notifyService
.
notifySmsTemplate
(
order
.
getMobile
(),
NotifyType
.
SHIP
,
new
String
[]{
shipChannel
,
shipSn
});
return
ResponseUtil
.
ok
();
}
/**
* 回复订单商品
*
* @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
public
Object
reply
(
String
body
)
{
Integer
commentId
=
JacksonUtil
.
parseInteger
(
body
,
"commentId"
);
if
(
commentId
==
null
||
commentId
==
0
)
{
return
ResponseUtil
.
badArgument
();
}
// 目前只支持回复一次
if
(
commentService
.
findById
(
commentId
)
!=
null
)
{
return
ResponseUtil
.
fail
(
ORDER_REPLY_EXIST
,
"订单商品已回复!"
);
}
String
content
=
JacksonUtil
.
parseString
(
body
,
"content"
);
if
(
StringUtils
.
isEmpty
(
content
))
{
return
ResponseUtil
.
badArgument
();
}
// 创建评价回复
LitemallComment
comment
=
new
LitemallComment
();
comment
.
setType
((
byte
)
2
);
comment
.
setValueId
(
commentId
);
comment
.
setContent
(
content
);
comment
.
setUserId
(
0
);
// 评价回复没有用
comment
.
setStar
((
short
)
0
);
// 评价回复没有用
comment
.
setHasPicture
(
false
);
// 评价回复没有用
comment
.
setPicUrls
(
new
String
[]{});
// 评价回复没有用
commentService
.
save
(
comment
);
return
ResponseUtil
.
ok
();
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminGoodsController.java
View file @
fbc7dc6a
...
...
@@ -5,31 +5,15 @@ import org.apache.commons.logging.LogFactory;
import
org.apache.shiro.authz.annotation.RequiresPermissions
;
import
org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc
;
import
org.linlinjava.litemall.admin.dao.GoodsAllinone
;
import
org.linlinjava.litemall.admin.util.CatVo
;
import
org.linlinjava.litemall.core.qcode.QCodeService
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.admin.service.AdminGoodsService
;
import
org.linlinjava.litemall.core.validator.Order
;
import
org.linlinjava.litemall.core.validator.Sort
;
import
org.linlinjava.litemall.db.domain.*
;
import
org.linlinjava.litemall.db.service.*
;
import
org.linlinjava.litemall.db.domain.LitemallGoods
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.PlatformTransactionManager
;
import
org.springframework.transaction.TransactionDefinition
;
import
org.springframework.transaction.TransactionStatus
;
import
org.springframework.transaction.support.DefaultTransactionDefinition
;
import
org.springframework.util.StringUtils
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.validation.constraints.NotNull
;
import
java.math.BigDecimal
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
linlinjava
.
litemall
.
admin
.
util
.
AdminResponseCode
.
GOODS_NAME_EXIST
;
import
static
org
.
linlinjava
.
litemall
.
admin
.
util
.
AdminResponseCode
.
GOODS_UPDATE_NOT_ALLOWED
;
@RestController
@RequestMapping
(
"/admin/goods"
)
...
...
@@ -38,366 +22,88 @@ public class AdminGoodsController {
private
final
Log
logger
=
LogFactory
.
getLog
(
AdminGoodsController
.
class
);
@Autowired
private
PlatformTransactionManager
txManager
;
@Autowired
private
LitemallGoodsService
goodsService
;
@Autowired
private
LitemallGoodsSpecificationService
specificationService
;
@Autowired
private
LitemallGoodsAttributeService
attributeService
;
@Autowired
private
LitemallGoodsProductService
productService
;
@Autowired
private
LitemallCategoryService
categoryService
;
@Autowired
private
LitemallBrandService
brandService
;
@Autowired
private
LitemallCartService
cartService
;
@Autowired
private
LitemallOrderGoodsService
orderGoodsService
;
@Autowired
private
QCodeService
qCodeService
;
private
AdminGoodsService
adminGoodsService
;
/**
* 查询商品
*
* @param goodsSn
* @param name
* @param page
* @param limit
* @param sort
* @param order
* @return
*/
@RequiresPermissions
(
"admin:goods:list"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"查询"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"查询"
)
@GetMapping
(
"/list"
)
public
Object
list
(
String
goodsSn
,
String
name
,
@RequestParam
(
defaultValue
=
"1"
)
Integer
page
,
@RequestParam
(
defaultValue
=
"10"
)
Integer
limit
,
@Sort
@RequestParam
(
defaultValue
=
"add_time"
)
String
sort
,
@Order
@RequestParam
(
defaultValue
=
"desc"
)
String
order
)
{
List
<
LitemallGoods
>
goodsList
=
goodsService
.
querySelective
(
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
int
total
=
goodsService
.
countSelective
(
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"total"
,
total
);
data
.
put
(
"items"
,
goodsList
);
return
ResponseUtil
.
ok
(
data
);
}
private
Object
validate
(
GoodsAllinone
goodsAllinone
)
{
LitemallGoods
goods
=
goodsAllinone
.
getGoods
();
String
name
=
goods
.
getName
();
if
(
StringUtils
.
isEmpty
(
name
))
{
return
ResponseUtil
.
badArgument
();
}
String
goodsSn
=
goods
.
getGoodsSn
();
if
(
StringUtils
.
isEmpty
(
goodsSn
))
{
return
ResponseUtil
.
badArgument
();
}
// 品牌商可以不设置,如果设置则需要验证品牌商存在
Integer
brandId
=
goods
.
getBrandId
();
if
(
brandId
!=
null
&&
brandId
!=
0
)
{
if
(
brandService
.
findById
(
brandId
)
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
}
// 分类可以不设置,如果设置则需要验证分类存在
Integer
categoryId
=
goods
.
getCategoryId
();
if
(
categoryId
!=
null
&&
categoryId
!=
0
)
{
if
(
categoryService
.
findById
(
categoryId
)
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
}
LitemallGoodsAttribute
[]
attributes
=
goodsAllinone
.
getAttributes
();
for
(
LitemallGoodsAttribute
attribute
:
attributes
)
{
String
attr
=
attribute
.
getAttribute
();
if
(
StringUtils
.
isEmpty
(
attr
))
{
return
ResponseUtil
.
badArgument
();
}
String
value
=
attribute
.
getValue
();
if
(
StringUtils
.
isEmpty
(
value
))
{
return
ResponseUtil
.
badArgument
();
}
}
LitemallGoodsSpecification
[]
specifications
=
goodsAllinone
.
getSpecifications
();
for
(
LitemallGoodsSpecification
specification
:
specifications
)
{
String
spec
=
specification
.
getSpecification
();
if
(
StringUtils
.
isEmpty
(
spec
))
{
return
ResponseUtil
.
badArgument
();
}
String
value
=
specification
.
getValue
();
if
(
StringUtils
.
isEmpty
(
value
))
{
return
ResponseUtil
.
badArgument
();
}
}
LitemallGoodsProduct
[]
products
=
goodsAllinone
.
getProducts
();
for
(
LitemallGoodsProduct
product
:
products
)
{
Integer
number
=
product
.
getNumber
();
if
(
number
==
null
||
number
<
0
)
{
return
ResponseUtil
.
badArgument
();
}
BigDecimal
price
=
product
.
getPrice
();
if
(
price
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
String
[]
productSpecifications
=
product
.
getSpecifications
();
if
(
productSpecifications
.
length
==
0
)
{
return
ResponseUtil
.
badArgument
();
}
}
return
null
;
return
adminGoodsService
.
list
(
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
}
/**
* 编辑商品
* <p>
* TODO
* 目前商品修改的逻辑是
* 1. 更新litemall_goods表
* 2. 逻辑删除litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
* 3. 添加litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
*
* 这里商品三个表的数据采用删除再添加的策略是因为
* 商品编辑页面,支持管理员添加删除商品规格、添加删除商品属性,因此这里仅仅更新是不可能的,
* 只能删除三个表旧的数据,然后添加新的数据。
* 但是这里又会引入新的问题,就是存在订单商品货品ID指向了失效的商品货品表。
* 因此这里会拒绝管理员编辑商品,如果订单或购物车中存在商品。
* 所以这里可能需要重新设计。
* @param goodsAllinone
* @return
*/
@RequiresPermissions
(
"admin:goods:update"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"编辑"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"编辑"
)
@PostMapping
(
"/update"
)
public
Object
update
(
@RequestBody
GoodsAllinone
goodsAllinone
)
{
Object
error
=
validate
(
goodsAllinone
);
if
(
error
!=
null
)
{
return
error
;
}
LitemallGoods
goods
=
goodsAllinone
.
getGoods
();
LitemallGoodsAttribute
[]
attributes
=
goodsAllinone
.
getAttributes
();
LitemallGoodsSpecification
[]
specifications
=
goodsAllinone
.
getSpecifications
();
LitemallGoodsProduct
[]
products
=
goodsAllinone
.
getProducts
();
Integer
id
=
goods
.
getId
();
// 检查是否存在购物车商品或者订单商品
// 如果存在则拒绝修改商品。
if
(
orderGoodsService
.
checkExist
(
id
)){
return
ResponseUtil
.
fail
(
GOODS_UPDATE_NOT_ALLOWED
,
"商品已经在订单中,不能修改"
);
}
if
(
cartService
.
checkExist
(
id
)){
return
ResponseUtil
.
fail
(
GOODS_UPDATE_NOT_ALLOWED
,
"商品已经在购物车中,不能修改"
);
}
// 开启事务管理
DefaultTransactionDefinition
def
=
new
DefaultTransactionDefinition
();
def
.
setPropagationBehavior
(
TransactionDefinition
.
PROPAGATION_REQUIRED
);
TransactionStatus
status
=
txManager
.
getTransaction
(
def
);
try
{
//将生成的分享图片地址写入数据库
String
url
=
qCodeService
.
createGoodShareImage
(
goods
.
getId
().
toString
(),
goods
.
getPicUrl
(),
goods
.
getName
());
goods
.
setShareUrl
(
url
);
// 商品基本信息表litemall_goods
if
(
goodsService
.
updateById
(
goods
)
==
0
)
{
throw
new
Exception
(
"更新数据失败"
);
}
Integer
gid
=
goods
.
getId
();
specificationService
.
deleteByGid
(
gid
);
attributeService
.
deleteByGid
(
gid
);
productService
.
deleteByGid
(
gid
);
// 商品规格表litemall_goods_specification
for
(
LitemallGoodsSpecification
specification
:
specifications
)
{
specification
.
setGoodsId
(
goods
.
getId
());
specificationService
.
add
(
specification
);
}
// 商品参数表litemall_goods_attribute
for
(
LitemallGoodsAttribute
attribute
:
attributes
)
{
attribute
.
setGoodsId
(
goods
.
getId
());
attributeService
.
add
(
attribute
);
}
// 商品货品表litemall_product
for
(
LitemallGoodsProduct
product
:
products
)
{
product
.
setGoodsId
(
goods
.
getId
());
productService
.
add
(
product
);
}
}
catch
(
Exception
ex
)
{
txManager
.
rollback
(
status
);
logger
.
error
(
"系统内部错误"
,
ex
);
return
ResponseUtil
.
fail
();
}
txManager
.
commit
(
status
);
qCodeService
.
createGoodShareImage
(
goods
.
getId
().
toString
(),
goods
.
getPicUrl
(),
goods
.
getName
());
return
ResponseUtil
.
ok
();
return
adminGoodsService
.
update
(
goodsAllinone
);
}
/**
* 删除商品
*
* @param goods
* @return
*/
@RequiresPermissions
(
"admin:goods:delete"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"删除"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"删除"
)
@PostMapping
(
"/delete"
)
public
Object
delete
(
@RequestBody
LitemallGoods
goods
)
{
Integer
id
=
goods
.
getId
();
if
(
id
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
// 开启事务管理
DefaultTransactionDefinition
def
=
new
DefaultTransactionDefinition
();
def
.
setPropagationBehavior
(
TransactionDefinition
.
PROPAGATION_REQUIRED
);
TransactionStatus
status
=
txManager
.
getTransaction
(
def
);
try
{
Integer
gid
=
goods
.
getId
();
goodsService
.
deleteById
(
gid
);
specificationService
.
deleteByGid
(
gid
);
attributeService
.
deleteByGid
(
gid
);
productService
.
deleteByGid
(
gid
);
}
catch
(
Exception
ex
)
{
txManager
.
rollback
(
status
);
logger
.
error
(
"系统内部错误"
,
ex
);
return
ResponseUtil
.
fail
();
}
txManager
.
commit
(
status
);
return
ResponseUtil
.
ok
();
return
adminGoodsService
.
delete
(
goods
);
}
/**
* 添加商品
*
* @param goodsAllinone
* @return
*/
@RequiresPermissions
(
"admin:goods:create"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品上架"
},
button
=
"上架"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品上架"
},
button
=
"上架"
)
@PostMapping
(
"/create"
)
public
Object
create
(
@RequestBody
GoodsAllinone
goodsAllinone
)
{
Object
error
=
validate
(
goodsAllinone
);
if
(
error
!=
null
)
{
return
error
;
}
LitemallGoods
goods
=
goodsAllinone
.
getGoods
();
LitemallGoodsAttribute
[]
attributes
=
goodsAllinone
.
getAttributes
();
LitemallGoodsSpecification
[]
specifications
=
goodsAllinone
.
getSpecifications
();
LitemallGoodsProduct
[]
products
=
goodsAllinone
.
getProducts
();
String
name
=
goods
.
getName
();
if
(
goodsService
.
checkExistByName
(
name
))
{
return
ResponseUtil
.
fail
(
GOODS_NAME_EXIST
,
"商品名已经存在"
);
}
// 开启事务管理
DefaultTransactionDefinition
def
=
new
DefaultTransactionDefinition
();
def
.
setPropagationBehavior
(
TransactionDefinition
.
PROPAGATION_REQUIRED
);
TransactionStatus
status
=
txManager
.
getTransaction
(
def
);
try
{
// 商品基本信息表litemall_goods
goodsService
.
add
(
goods
);
//将生成的分享图片地址写入数据库
String
url
=
qCodeService
.
createGoodShareImage
(
goods
.
getId
().
toString
(),
goods
.
getPicUrl
(),
goods
.
getName
());
if
(!
StringUtils
.
isEmpty
(
url
))
{
goods
.
setShareUrl
(
url
);
if
(
goodsService
.
updateById
(
goods
)
==
0
)
{
throw
new
Exception
(
"更新数据失败"
);
}
}
// 商品规格表litemall_goods_specification
for
(
LitemallGoodsSpecification
specification
:
specifications
)
{
specification
.
setGoodsId
(
goods
.
getId
());
specificationService
.
add
(
specification
);
}
// 商品参数表litemall_goods_attribute
for
(
LitemallGoodsAttribute
attribute
:
attributes
)
{
attribute
.
setGoodsId
(
goods
.
getId
());
attributeService
.
add
(
attribute
);
}
// 商品货品表litemall_product
for
(
LitemallGoodsProduct
product
:
products
)
{
product
.
setGoodsId
(
goods
.
getId
());
productService
.
add
(
product
);
}
}
catch
(
Exception
ex
)
{
txManager
.
rollback
(
status
);
logger
.
error
(
"系统内部错误"
,
ex
);
return
ResponseUtil
.
fail
();
}
txManager
.
commit
(
status
);
return
ResponseUtil
.
ok
();
return
adminGoodsService
.
create
(
goodsAllinone
);
}
@RequiresPermissions
(
"admin:goods:list"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"查询"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"查询"
)
@GetMapping
(
"/catAndBrand"
)
public
Object
list2
()
{
// http://element-cn.eleme.io/#/zh-CN/component/cascader
// 管理员设置“所属分类”
List
<
LitemallCategory
>
l1CatList
=
categoryService
.
queryL1
();
List
<
CatVo
>
categoryList
=
new
ArrayList
<>(
l1CatList
.
size
());
for
(
LitemallCategory
l1
:
l1CatList
)
{
CatVo
l1CatVo
=
new
CatVo
();
l1CatVo
.
setValue
(
l1
.
getId
());
l1CatVo
.
setLabel
(
l1
.
getName
());
List
<
LitemallCategory
>
l2CatList
=
categoryService
.
queryByPid
(
l1
.
getId
());
List
<
CatVo
>
children
=
new
ArrayList
<>(
l2CatList
.
size
());
for
(
LitemallCategory
l2
:
l2CatList
)
{
CatVo
l2CatVo
=
new
CatVo
();
l2CatVo
.
setValue
(
l2
.
getId
());
l2CatVo
.
setLabel
(
l2
.
getName
());
children
.
add
(
l2CatVo
);
}
l1CatVo
.
setChildren
(
children
);
categoryList
.
add
(
l1CatVo
);
}
// http://element-cn.eleme.io/#/zh-CN/component/select
// 管理员设置“所属品牌商”
List
<
LitemallBrand
>
list
=
brandService
.
all
();
List
<
Map
<
String
,
Object
>>
brandList
=
new
ArrayList
<>(
l1CatList
.
size
());
for
(
LitemallBrand
brand
:
list
)
{
Map
<
String
,
Object
>
b
=
new
HashMap
<>(
2
);
b
.
put
(
"value"
,
brand
.
getId
());
b
.
put
(
"label"
,
brand
.
getName
());
brandList
.
add
(
b
);
}
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"categoryList"
,
categoryList
);
data
.
put
(
"brandList"
,
brandList
);
return
ResponseUtil
.
ok
(
data
);
return
adminGoodsService
.
list2
();
}
/**
* 商品详情
*
* @param id
* @return
*/
@RequiresPermissions
(
"admin:goods:read"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"编辑"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品列表"
},
button
=
"编辑"
)
@GetMapping
(
"/detail"
)
public
Object
detail
(
@NotNull
Integer
id
)
{
LitemallGoods
goods
=
goodsService
.
findById
(
id
);
List
<
LitemallGoodsProduct
>
products
=
productService
.
queryByGid
(
id
);
List
<
LitemallGoodsSpecification
>
specifications
=
specificationService
.
queryByGid
(
id
);
List
<
LitemallGoodsAttribute
>
attributes
=
attributeService
.
queryByGid
(
id
);
Integer
categoryId
=
goods
.
getCategoryId
();
LitemallCategory
category
=
categoryService
.
findById
(
categoryId
);
Integer
[]
categoryIds
=
new
Integer
[]{};
if
(
category
!=
null
)
{
Integer
parentCategoryId
=
category
.
getPid
();
categoryIds
=
new
Integer
[]{
parentCategoryId
,
categoryId
};
}
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"goods"
,
goods
);
data
.
put
(
"specifications"
,
specifications
);
data
.
put
(
"products"
,
products
);
data
.
put
(
"attributes"
,
attributes
);
data
.
put
(
"categoryIds"
,
categoryIds
);
return
adminGoodsService
.
detail
(
id
);
return
ResponseUtil
.
ok
(
data
);
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminOrderController.java
View file @
fbc7dc6a
package
org.linlinjava.litemall.admin.web
;
import
com.github.binarywang.wxpay.bean.request.WxPayRefundRequest
;
import
com.github.binarywang.wxpay.bean.result.WxPayRefundResult
;
import
com.github.binarywang.wxpay.exception.WxPayException
;
import
com.github.binarywang.wxpay.service.WxPayService
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.apache.shiro.authz.annotation.RequiresPermissions
;
import
org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc
;
import
org.linlinjava.litemall.core.notify.NotifyService
;
import
org.linlinjava.litemall.core.notify.NotifyType
;
import
org.linlinjava.litemall.core.util.JacksonUtil
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.admin.service.AdminOrderService
;
import
org.linlinjava.litemall.core.validator.Order
;
import
org.linlinjava.litemall.core.validator.Sort
;
import
org.linlinjava.litemall.db.domain.LitemallComment
;
import
org.linlinjava.litemall.db.domain.LitemallOrder
;
import
org.linlinjava.litemall.db.domain.LitemallOrderGoods
;
import
org.linlinjava.litemall.db.domain.UserVo
;
import
org.linlinjava.litemall.db.service.*
;
import
org.linlinjava.litemall.db.util.OrderUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.PlatformTransactionManager
;
import
org.springframework.transaction.TransactionDefinition
;
import
org.springframework.transaction.TransactionStatus
;
import
org.springframework.transaction.support.DefaultTransactionDefinition
;
import
org.springframework.util.StringUtils
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.validation.constraints.NotNull
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
linlinjava
.
litemall
.
admin
.
util
.
AdminResponseCode
.*;
@RestController
@RequestMapping
(
"/admin/order"
)
...
...
@@ -45,25 +21,22 @@ public class AdminOrderController {
private
final
Log
logger
=
LogFactory
.
getLog
(
AdminOrderController
.
class
);
@Autowired
private
PlatformTransactionManager
txManager
;
@Autowired
private
LitemallOrderGoodsService
orderGoodsService
;
@Autowired
private
LitemallOrderService
orderService
;
@Autowired
private
LitemallGoodsProductService
productService
;
@Autowired
private
LitemallUserService
userService
;
@Autowired
private
LitemallCommentService
commentService
;
@Autowired
private
WxPayService
wxPayService
;
@Autowired
private
NotifyService
notifyService
;
private
AdminOrderService
adminOrderService
;
/**
* 查询订单
*
* @param userId
* @param orderSn
* @param orderStatusArray
* @param page
* @param limit
* @param sort
* @param order
* @return
*/
@RequiresPermissions
(
"admin:order:list"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"查询"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"查询"
)
@GetMapping
(
"/list"
)
public
Object
list
(
Integer
userId
,
String
orderSn
,
@RequestParam
(
required
=
false
)
List
<
Short
>
orderStatusArray
,
...
...
@@ -71,218 +44,60 @@ public class AdminOrderController {
@RequestParam
(
defaultValue
=
"10"
)
Integer
limit
,
@Sort
@RequestParam
(
defaultValue
=
"add_time"
)
String
sort
,
@Order
@RequestParam
(
defaultValue
=
"desc"
)
String
order
)
{
List
<
LitemallOrder
>
orderList
=
orderService
.
querySelective
(
userId
,
orderSn
,
orderStatusArray
,
page
,
limit
,
sort
,
order
);
int
total
=
orderService
.
countSelective
(
userId
,
orderSn
,
orderStatusArray
,
page
,
limit
,
sort
,
order
);
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"total"
,
total
);
data
.
put
(
"items"
,
orderList
);
return
ResponseUtil
.
ok
(
data
);
return
adminOrderService
.
list
(
userId
,
orderSn
,
orderStatusArray
,
page
,
limit
,
sort
,
order
);
}
/**
* 订单详情
*
* @param id
* @return
*/
@RequiresPermissions
(
"admin:order:read"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"详情"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"详情"
)
@GetMapping
(
"/detail"
)
public
Object
detail
(
@NotNull
Integer
id
)
{
LitemallOrder
order
=
orderService
.
findById
(
id
);
List
<
LitemallOrderGoods
>
orderGoods
=
orderGoodsService
.
queryByOid
(
id
);
UserVo
user
=
userService
.
findUserVoById
(
order
.
getUserId
());
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"order"
,
order
);
data
.
put
(
"orderGoods"
,
orderGoods
);
data
.
put
(
"user"
,
user
);
return
ResponseUtil
.
ok
(
data
);
return
adminOrderService
.
detail
(
id
);
}
/**
* 订单退款
* <p>
* 1. 检测当前订单是否能够退款;
* 2. 微信退款操作;
* 3. 设置订单退款确认状态;
* 4. 订单商品库存回库。
* <p>
* TODO
* 虽然接入了微信退款API,但是从安全角度考虑,建议开发者删除这里微信退款代码,采用以下两步走步骤:
* 1. 管理员登录微信官方支付平台点击退款操作进行退款
* 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库
*
* @param body
订单信息,{ orderId:xxx }
* @param body 订单信息,{ orderId:xxx }
* @return 订单退款操作结果
*/
@RequiresPermissions
(
"admin:order:refund"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"订单退款"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"订单退款"
)
@PostMapping
(
"refund"
)
public
Object
refund
(
@RequestBody
String
body
)
{
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
String
refundMoney
=
JacksonUtil
.
parseString
(
body
,
"refundMoney"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(
StringUtils
.
isEmpty
(
refundMoney
)){
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(
order
.
getActualPrice
().
compareTo
(
new
BigDecimal
(
refundMoney
))
!=
0
)
{
return
ResponseUtil
.
badArgumentValue
();
}
// 如果订单不是退款状态,则不能退款
if
(!
order
.
getOrderStatus
().
equals
(
OrderUtil
.
STATUS_REFUND
))
{
return
ResponseUtil
.
fail
(
ORDER_CONFIRM_NOT_ALLOWED
,
"订单不能确认收货"
);
}
// 微信退款
WxPayRefundRequest
wxPayRefundRequest
=
new
WxPayRefundRequest
();
wxPayRefundRequest
.
setOutTradeNo
(
order
.
getOrderSn
());
wxPayRefundRequest
.
setOutRefundNo
(
"refund_"
+
order
.
getOrderSn
());
// 元转成分
Integer
totalFee
=
order
.
getActualPrice
().
multiply
(
new
BigDecimal
(
100
)).
intValue
();
wxPayRefundRequest
.
setTotalFee
(
totalFee
);
wxPayRefundRequest
.
setRefundFee
(
totalFee
);
WxPayRefundResult
wxPayRefundResult
=
null
;
try
{
wxPayRefundResult
=
wxPayService
.
refund
(
wxPayRefundRequest
);
}
catch
(
WxPayException
e
)
{
e
.
printStackTrace
();
return
ResponseUtil
.
fail
(
ORDER_REFUND_FAILED
,
"订单退款失败"
);
}
if
(!
wxPayRefundResult
.
getReturnCode
().
equals
(
"SUCCESS"
)){
logger
.
warn
(
"refund fail: "
+
wxPayRefundResult
.
getReturnMsg
());
return
ResponseUtil
.
fail
(
ORDER_REFUND_FAILED
,
"订单退款失败"
);
}
if
(!
wxPayRefundResult
.
getResultCode
().
equals
(
"SUCCESS"
)){
logger
.
warn
(
"refund fail: "
+
wxPayRefundResult
.
getReturnMsg
());
return
ResponseUtil
.
fail
(
ORDER_REFUND_FAILED
,
"订单退款失败"
);
}
// 开启事务管理
DefaultTransactionDefinition
def
=
new
DefaultTransactionDefinition
();
def
.
setPropagationBehavior
(
TransactionDefinition
.
PROPAGATION_REQUIRED
);
TransactionStatus
status
=
txManager
.
getTransaction
(
def
);
try
{
// 设置订单取消状态
order
.
setOrderStatus
(
OrderUtil
.
STATUS_REFUND_CONFIRM
);
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
throw
new
Exception
(
"更新数据已失效"
);
}
// 商品货品数量增加
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
orderId
);
for
(
LitemallOrderGoods
orderGoods
:
orderGoodsList
)
{
Integer
productId
=
orderGoods
.
getProductId
();
Short
number
=
orderGoods
.
getNumber
();
if
(
productService
.
addStock
(
productId
,
number
)
==
0
)
{
throw
new
Exception
(
"商品货品库存增加失败"
);
}
}
}
catch
(
Exception
ex
)
{
txManager
.
rollback
(
status
);
logger
.
error
(
"系统内部错误"
,
ex
);
return
ResponseUtil
.
fail
(
ORDER_REFUND_FAILED
,
"订单退款失败"
);
}
txManager
.
commit
(
status
);
//TODO 发送邮件和短信通知,这里采用异步发送
// 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功,请耐心等待到账。”
// 注意订单号只发后6位
notifyService
.
notifySmsTemplate
(
order
.
getMobile
(),
NotifyType
.
REFUND
,
new
String
[]{
order
.
getOrderSn
().
substring
(
8
,
14
)});
return
ResponseUtil
.
ok
();
return
adminOrderService
.
refund
(
body
);
}
/**
* 发货
* 1. 检测当前订单是否能够发货
* 2. 设置订单发货状态
*
* @param body
订单信息,{ orderId:xxx, shipSn: xxx, shipChannel: xxx }
* @param body 订单信息,{ orderId:xxx, shipSn: xxx, shipChannel: xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
@RequiresPermissions
(
"admin:order:ship"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"订单发货"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"订单发货"
)
@PostMapping
(
"ship"
)
public
Object
ship
(
@RequestBody
String
body
)
{
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
String
shipSn
=
JacksonUtil
.
parseString
(
body
,
"shipSn"
);
String
shipChannel
=
JacksonUtil
.
parseString
(
body
,
"shipChannel"
);
if
(
orderId
==
null
||
shipSn
==
null
||
shipChannel
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
// 如果订单不是已付款状态,则不能发货
if
(!
order
.
getOrderStatus
().
equals
(
OrderUtil
.
STATUS_PAY
))
{
return
ResponseUtil
.
fail
(
ORDER_CONFIRM_NOT_ALLOWED
,
"订单不能确认收货"
);
}
order
.
setOrderStatus
(
OrderUtil
.
STATUS_SHIP
);
order
.
setShipSn
(
shipSn
);
order
.
setShipChannel
(
shipChannel
);
order
.
setShipTime
(
LocalDateTime
.
now
());
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
return
ResponseUtil
.
updatedDateExpired
();
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 发货会发送通知短信给用户: *
// "您的订单已经发货,快递公司 {1},快递单 {2} ,请注意查收"
notifyService
.
notifySmsTemplate
(
order
.
getMobile
(),
NotifyType
.
SHIP
,
new
String
[]{
shipChannel
,
shipSn
});
return
ResponseUtil
.
ok
();
return
adminOrderService
.
ship
(
body
);
}
/**
* 回复订单商品
*
* @param body
订单信息,{ orderId:xxx }
* @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
@RequiresPermissions
(
"admin:order:reply"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"订单商品回复"
)
@RequiresPermissionsDesc
(
menu
=
{
"商城管理"
,
"订单管理"
},
button
=
"订单商品回复"
)
@PostMapping
(
"reply"
)
public
Object
reply
(
@RequestBody
String
body
)
{
Integer
commentId
=
JacksonUtil
.
parseInteger
(
body
,
"commentId"
);
if
(
commentId
==
null
||
commentId
==
0
)
{
return
ResponseUtil
.
badArgument
();
}
// 目前只支持回复一次
if
(
commentService
.
findById
(
commentId
)
!=
null
)
{
return
ResponseUtil
.
fail
(
ORDER_REPLY_EXIST
,
"订单商品已回复!"
);
}
String
content
=
JacksonUtil
.
parseString
(
body
,
"content"
);
if
(
StringUtils
.
isEmpty
(
content
))
{
return
ResponseUtil
.
badArgument
();
}
// 创建评价回复
LitemallComment
comment
=
new
LitemallComment
();
comment
.
setType
((
byte
)
2
);
comment
.
setValueId
(
commentId
);
comment
.
setContent
(
content
);
comment
.
setUserId
(
0
);
// 评价回复没有用
comment
.
setStar
((
short
)
0
);
// 评价回复没有用
comment
.
setHasPicture
(
false
);
// 评价回复没有用
comment
.
setPicUrls
(
new
String
[]{});
// 评价回复没有用
commentService
.
save
(
comment
);
return
ResponseUtil
.
ok
();
return
adminOrderService
.
reply
(
body
);
}
}
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/service/WxOrderService.java
0 → 100644
View file @
fbc7dc6a
package
org.linlinjava.litemall.wx.service
;
import
com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse
;
import
com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult
;
import
com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult
;
import
com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest
;
import
com.github.binarywang.wxpay.bean.result.BaseWxPayResult
;
import
com.github.binarywang.wxpay.exception.WxPayException
;
import
com.github.binarywang.wxpay.service.WxPayService
;
import
org.apache.commons.io.IOUtils
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.linlinjava.litemall.core.express.ExpressService
;
import
org.linlinjava.litemall.core.express.dao.ExpressInfo
;
import
org.linlinjava.litemall.core.notify.NotifyService
;
import
org.linlinjava.litemall.core.notify.NotifyType
;
import
org.linlinjava.litemall.core.qcode.QCodeService
;
import
org.linlinjava.litemall.core.system.SystemConfig
;
import
org.linlinjava.litemall.core.util.DateTimeUtil
;
import
org.linlinjava.litemall.core.util.JacksonUtil
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.db.domain.*
;
import
org.linlinjava.litemall.db.service.*
;
import
org.linlinjava.litemall.db.util.CouponUserConstant
;
import
org.linlinjava.litemall.db.util.OrderHandleOption
;
import
org.linlinjava.litemall.db.util.OrderUtil
;
import
org.linlinjava.litemall.wx.annotation.LoginUser
;
import
org.linlinjava.litemall.wx.util.IpUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.PlatformTransactionManager
;
import
org.springframework.transaction.TransactionDefinition
;
import
org.springframework.transaction.TransactionStatus
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.support.DefaultTransactionDefinition
;
import
org.springframework.util.Assert
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.validation.constraints.NotNull
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
linlinjava
.
litemall
.
wx
.
util
.
WxResponseCode
.*;
/**
* 订单服务
*
* <p>
* 订单状态:
* 101 订单生成,未支付;102,下单后未支付用户取消;103,下单后未支付超时系统自动取消
* 201 支付完成,商家未发货;202,订单生产,已付款未发货,但是退款取消;
* 301 商家发货,用户未确认;
* 401 用户确认收货; 402 用户没有确认收货超过一定时间,系统自动确认收货;
*
* <p>
* 用户操作:
* 当101用户未付款时,此时用户可以进行的操作是取消订单,或者付款操作
* 当201支付完成而商家未发货时,此时用户可以取消订单并申请退款
* 当301商家已发货时,此时用户可以有确认收货的操作
* 当401用户确认收货以后,此时用户可以进行的操作是删除订单,评价商品,或者再次购买
* 当402系统自动确认收货以后,此时用户可以删除订单,评价商品,或者再次购买
*
* <p>
* 注意:目前不支持订单退货和售后服务
*/
@Service
public
class
WxOrderService
{
private
final
Log
logger
=
LogFactory
.
getLog
(
WxOrderService
.
class
);
@Autowired
private
LitemallUserService
userService
;
@Autowired
private
LitemallOrderService
orderService
;
@Autowired
private
LitemallOrderGoodsService
orderGoodsService
;
@Autowired
private
LitemallAddressService
addressService
;
@Autowired
private
LitemallCartService
cartService
;
@Autowired
private
LitemallRegionService
regionService
;
@Autowired
private
LitemallGoodsProductService
productService
;
@Autowired
private
WxPayService
wxPayService
;
@Autowired
private
NotifyService
notifyService
;
@Autowired
private
LitemallUserFormIdService
formIdService
;
@Autowired
private
LitemallGrouponRulesService
grouponRulesService
;
@Autowired
private
LitemallGrouponService
grouponService
;
@Autowired
private
QCodeService
qCodeService
;
@Autowired
private
ExpressService
expressService
;
@Autowired
private
LitemallCommentService
commentService
;
@Autowired
private
LitemallCouponService
couponService
;
@Autowired
private
LitemallCouponUserService
couponUserService
;
@Autowired
private
CouponVerifyService
couponVerifyService
;
private
String
detailedAddress
(
LitemallAddress
litemallAddress
)
{
Integer
provinceId
=
litemallAddress
.
getProvinceId
();
Integer
cityId
=
litemallAddress
.
getCityId
();
Integer
areaId
=
litemallAddress
.
getAreaId
();
String
provinceName
=
regionService
.
findById
(
provinceId
).
getName
();
String
cityName
=
regionService
.
findById
(
cityId
).
getName
();
String
areaName
=
regionService
.
findById
(
areaId
).
getName
();
String
fullRegion
=
provinceName
+
" "
+
cityName
+
" "
+
areaName
;
return
fullRegion
+
" "
+
litemallAddress
.
getAddress
();
}
/**
* 订单列表
*
* @param userId 用户ID
* @param showType 订单信息:
* 0,全部订单;
* 1,待付款;
* 2,待发货;
* 3,待收货;
* 4,待评价。
* @param page 分页页数
* @param size 分页大小
* @return 订单列表
*/
public
Object
list
(
Integer
userId
,
Integer
showType
,
Integer
page
,
Integer
size
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
List
<
Short
>
orderStatus
=
OrderUtil
.
orderStatus
(
showType
);
List
<
LitemallOrder
>
orderList
=
orderService
.
queryByOrderStatus
(
userId
,
orderStatus
);
int
count
=
orderService
.
countByOrderStatus
(
userId
,
orderStatus
);
List
<
Map
<
String
,
Object
>>
orderVoList
=
new
ArrayList
<>(
orderList
.
size
());
for
(
LitemallOrder
order
:
orderList
)
{
Map
<
String
,
Object
>
orderVo
=
new
HashMap
<>();
orderVo
.
put
(
"id"
,
order
.
getId
());
orderVo
.
put
(
"orderSn"
,
order
.
getOrderSn
());
orderVo
.
put
(
"actualPrice"
,
order
.
getActualPrice
());
orderVo
.
put
(
"orderStatusText"
,
OrderUtil
.
orderStatusText
(
order
));
orderVo
.
put
(
"handleOption"
,
OrderUtil
.
build
(
order
));
LitemallGroupon
groupon
=
grouponService
.
queryByOrderId
(
order
.
getId
());
if
(
groupon
!=
null
)
{
orderVo
.
put
(
"isGroupin"
,
true
);
}
else
{
orderVo
.
put
(
"isGroupin"
,
false
);
}
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
order
.
getId
());
List
<
Map
<
String
,
Object
>>
orderGoodsVoList
=
new
ArrayList
<>(
orderGoodsList
.
size
());
for
(
LitemallOrderGoods
orderGoods
:
orderGoodsList
)
{
Map
<
String
,
Object
>
orderGoodsVo
=
new
HashMap
<>();
orderGoodsVo
.
put
(
"id"
,
orderGoods
.
getId
());
orderGoodsVo
.
put
(
"goodsName"
,
orderGoods
.
getGoodsName
());
orderGoodsVo
.
put
(
"number"
,
orderGoods
.
getNumber
());
orderGoodsVo
.
put
(
"picUrl"
,
orderGoods
.
getPicUrl
());
orderGoodsVoList
.
add
(
orderGoodsVo
);
}
orderVo
.
put
(
"goodsList"
,
orderGoodsVoList
);
orderVoList
.
add
(
orderVo
);
}
Map
<
String
,
Object
>
result
=
new
HashMap
<>();
result
.
put
(
"count"
,
count
);
result
.
put
(
"data"
,
orderVoList
);
return
ResponseUtil
.
ok
(
result
);
}
/**
* 订单详情
*
* @param userId 用户ID
* @param orderId 订单ID
* @return 订单详情
*/
public
Object
detail
(
Integer
userId
,
Integer
orderId
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
// 订单信息
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
null
==
order
)
{
return
ResponseUtil
.
fail
(
ORDER_UNKNOWN
,
"订单不存在"
);
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
fail
(
ORDER_INVALID
,
"不是当前用户的订单"
);
}
Map
<
String
,
Object
>
orderVo
=
new
HashMap
<
String
,
Object
>();
orderVo
.
put
(
"id"
,
order
.
getId
());
orderVo
.
put
(
"orderSn"
,
order
.
getOrderSn
());
orderVo
.
put
(
"addTime"
,
order
.
getAddTime
());
orderVo
.
put
(
"consignee"
,
order
.
getConsignee
());
orderVo
.
put
(
"mobile"
,
order
.
getMobile
());
orderVo
.
put
(
"address"
,
order
.
getAddress
());
orderVo
.
put
(
"goodsPrice"
,
order
.
getGoodsPrice
());
orderVo
.
put
(
"freightPrice"
,
order
.
getFreightPrice
());
orderVo
.
put
(
"actualPrice"
,
order
.
getActualPrice
());
orderVo
.
put
(
"orderStatusText"
,
OrderUtil
.
orderStatusText
(
order
));
orderVo
.
put
(
"handleOption"
,
OrderUtil
.
build
(
order
));
orderVo
.
put
(
"expCode"
,
order
.
getShipChannel
());
orderVo
.
put
(
"expNo"
,
order
.
getShipSn
());
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
order
.
getId
());
Map
<
String
,
Object
>
result
=
new
HashMap
<>();
result
.
put
(
"orderInfo"
,
orderVo
);
result
.
put
(
"orderGoods"
,
orderGoodsList
);
// 订单状态为已发货且物流信息不为空
//"YTO", "800669400640887922"
if
(
order
.
getOrderStatus
().
equals
(
OrderUtil
.
STATUS_SHIP
))
{
ExpressInfo
ei
=
expressService
.
getExpressInfo
(
order
.
getShipChannel
(),
order
.
getShipSn
());
result
.
put
(
"expressInfo"
,
ei
);
}
return
ResponseUtil
.
ok
(
result
);
}
/**
* 提交订单
* <p>
* 1. 创建订单表项和订单商品表项;
* 2. 购物车清空;
* 3. 优惠券设置已用;
* 4. 商品货品库存减少;
* 5. 如果是团购商品,则创建团购活动表项。
*
* @param userId 用户ID
* @param body 订单信息,{ cartId:xxx, addressId: xxx, couponId: xxx, message: xxx, grouponRulesId: xxx, grouponLinkId: xxx}
* @return 提交订单操作结果
*/
@Transactional
public
Object
submit
(
Integer
userId
,
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
if
(
body
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
Integer
cartId
=
JacksonUtil
.
parseInteger
(
body
,
"cartId"
);
Integer
addressId
=
JacksonUtil
.
parseInteger
(
body
,
"addressId"
);
Integer
couponId
=
JacksonUtil
.
parseInteger
(
body
,
"couponId"
);
String
message
=
JacksonUtil
.
parseString
(
body
,
"message"
);
Integer
grouponRulesId
=
JacksonUtil
.
parseInteger
(
body
,
"grouponRulesId"
);
Integer
grouponLinkId
=
JacksonUtil
.
parseInteger
(
body
,
"grouponLinkId"
);
//如果是团购项目,验证活动是否有效
if
(
grouponRulesId
!=
null
&&
grouponRulesId
>
0
)
{
LitemallGrouponRules
rules
=
grouponRulesService
.
queryById
(
grouponRulesId
);
//找不到记录
if
(
rules
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
//团购活动已经过期
if
(
grouponRulesService
.
isExpired
(
rules
))
{
return
ResponseUtil
.
fail
(
GROUPON_EXPIRED
,
"团购活动已过期!"
);
}
}
if
(
cartId
==
null
||
addressId
==
null
||
couponId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
// 收货地址
LitemallAddress
checkedAddress
=
addressService
.
findById
(
addressId
);
if
(
checkedAddress
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
// 团购优惠
BigDecimal
grouponPrice
=
new
BigDecimal
(
0.00
);
LitemallGrouponRules
grouponRules
=
grouponRulesService
.
queryById
(
grouponRulesId
);
if
(
grouponRules
!=
null
)
{
grouponPrice
=
grouponRules
.
getDiscount
();
}
// 货品价格
List
<
LitemallCart
>
checkedGoodsList
=
null
;
if
(
cartId
.
equals
(
0
))
{
checkedGoodsList
=
cartService
.
queryByUidAndChecked
(
userId
);
}
else
{
LitemallCart
cart
=
cartService
.
findById
(
cartId
);
checkedGoodsList
=
new
ArrayList
<>(
1
);
checkedGoodsList
.
add
(
cart
);
}
if
(
checkedGoodsList
.
size
()
==
0
)
{
return
ResponseUtil
.
badArgumentValue
();
}
BigDecimal
checkedGoodsPrice
=
new
BigDecimal
(
0.00
);
for
(
LitemallCart
checkGoods
:
checkedGoodsList
)
{
// 只有当团购规格商品ID符合才进行团购优惠
if
(
grouponRules
!=
null
&&
grouponRules
.
getGoodsId
().
equals
(
checkGoods
.
getGoodsId
()))
{
checkedGoodsPrice
=
checkedGoodsPrice
.
add
(
checkGoods
.
getPrice
().
subtract
(
grouponPrice
).
multiply
(
new
BigDecimal
(
checkGoods
.
getNumber
())));
}
else
{
checkedGoodsPrice
=
checkedGoodsPrice
.
add
(
checkGoods
.
getPrice
().
multiply
(
new
BigDecimal
(
checkGoods
.
getNumber
())));
}
}
// 获取可用的优惠券信息
// 使用优惠券减免的金额
BigDecimal
couponPrice
=
new
BigDecimal
(
0.00
);
// 如果couponId=0则没有优惠券,couponId=-1则不使用优惠券
if
(
couponId
!=
0
&&
couponId
!=
-
1
){
LitemallCoupon
coupon
=
couponVerifyService
.
checkCoupon
(
userId
,
couponId
,
checkedGoodsPrice
);
if
(
coupon
==
null
){
return
ResponseUtil
.
badArgumentValue
();
}
couponPrice
=
coupon
.
getDiscount
();
}
// 根据订单商品总价计算运费,满足条件(例如88元)则免运费,否则需要支付运费(例如8元);
BigDecimal
freightPrice
=
new
BigDecimal
(
0.00
);
if
(
checkedGoodsPrice
.
compareTo
(
SystemConfig
.
getFreightLimit
())
<
0
)
{
freightPrice
=
SystemConfig
.
getFreight
();
}
// 可以使用的其他钱,例如用户积分
BigDecimal
integralPrice
=
new
BigDecimal
(
0.00
);
// 订单费用
BigDecimal
orderTotalPrice
=
checkedGoodsPrice
.
add
(
freightPrice
).
subtract
(
couponPrice
);
// 最终支付费用
BigDecimal
actualPrice
=
orderTotalPrice
.
subtract
(
integralPrice
);
Integer
orderId
=
null
;
LitemallOrder
order
=
null
;
// 订单
order
=
new
LitemallOrder
();
order
.
setUserId
(
userId
);
order
.
setOrderSn
(
orderService
.
generateOrderSn
(
userId
));
order
.
setOrderStatus
(
OrderUtil
.
STATUS_CREATE
);
order
.
setConsignee
(
checkedAddress
.
getName
());
order
.
setMobile
(
checkedAddress
.
getMobile
());
order
.
setMessage
(
message
);
String
detailedAddress
=
detailedAddress
(
checkedAddress
);
order
.
setAddress
(
detailedAddress
);
order
.
setGoodsPrice
(
checkedGoodsPrice
);
order
.
setFreightPrice
(
freightPrice
);
order
.
setCouponPrice
(
couponPrice
);
order
.
setIntegralPrice
(
integralPrice
);
order
.
setOrderPrice
(
orderTotalPrice
);
order
.
setActualPrice
(
actualPrice
);
// 有团购活动
if
(
grouponRules
!=
null
)
{
order
.
setGrouponPrice
(
grouponPrice
);
// 团购价格
}
else
{
order
.
setGrouponPrice
(
new
BigDecimal
(
0.00
));
// 团购价格
}
// 添加订单表项
orderService
.
add
(
order
);
orderId
=
order
.
getId
();
// 添加订单商品表项
for
(
LitemallCart
cartGoods
:
checkedGoodsList
)
{
// 订单商品
LitemallOrderGoods
orderGoods
=
new
LitemallOrderGoods
();
orderGoods
.
setOrderId
(
order
.
getId
());
orderGoods
.
setGoodsId
(
cartGoods
.
getGoodsId
());
orderGoods
.
setGoodsSn
(
cartGoods
.
getGoodsSn
());
orderGoods
.
setProductId
(
cartGoods
.
getProductId
());
orderGoods
.
setGoodsName
(
cartGoods
.
getGoodsName
());
orderGoods
.
setPicUrl
(
cartGoods
.
getPicUrl
());
orderGoods
.
setPrice
(
cartGoods
.
getPrice
());
orderGoods
.
setNumber
(
cartGoods
.
getNumber
());
orderGoods
.
setSpecifications
(
cartGoods
.
getSpecifications
());
orderGoods
.
setAddTime
(
LocalDateTime
.
now
());
orderGoodsService
.
add
(
orderGoods
);
}
// 删除购物车里面的商品信息
cartService
.
clearGoods
(
userId
);
// 商品货品数量减少
for
(
LitemallCart
checkGoods
:
checkedGoodsList
)
{
Integer
productId
=
checkGoods
.
getProductId
();
LitemallGoodsProduct
product
=
productService
.
findById
(
productId
);
Integer
remainNumber
=
product
.
getNumber
()
-
checkGoods
.
getNumber
();
if
(
remainNumber
<
0
)
{
throw
new
RuntimeException
(
"下单的商品货品数量大于库存量"
);
}
if
(
productService
.
reduceStock
(
productId
,
checkGoods
.
getNumber
())
==
0
)
{
throw
new
RuntimeException
(
"商品货品库存减少失败"
);
}
}
// 如果使用了优惠券,设置优惠券使用状态
if
(
couponId
!=
0
&&
couponId
!=
-
1
){
LitemallCouponUser
couponUser
=
couponUserService
.
queryOne
(
userId
,
couponId
);
couponUser
.
setStatus
(
CouponUserConstant
.
STATUS_USED
);
couponUser
.
setUsedTime
(
LocalDateTime
.
now
());
couponUser
.
setOrderId
(
orderId
);
couponUserService
.
update
(
couponUser
);
}
//如果是团购项目,添加团购信息
if
(
grouponRulesId
!=
null
&&
grouponRulesId
>
0
)
{
LitemallGroupon
groupon
=
new
LitemallGroupon
();
groupon
.
setOrderId
(
orderId
);
groupon
.
setPayed
(
false
);
groupon
.
setUserId
(
userId
);
groupon
.
setRulesId
(
grouponRulesId
);
//参与者
if
(
grouponLinkId
!=
null
&&
grouponLinkId
>
0
)
{
//参与的团购记录
LitemallGroupon
baseGroupon
=
grouponService
.
queryById
(
grouponLinkId
);
groupon
.
setCreatorUserId
(
baseGroupon
.
getCreatorUserId
());
groupon
.
setGrouponId
(
grouponLinkId
);
groupon
.
setShareUrl
(
baseGroupon
.
getShareUrl
());
}
else
{
groupon
.
setCreatorUserId
(
userId
);
groupon
.
setGrouponId
(
0
);
}
grouponService
.
createGroupon
(
groupon
);
}
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"orderId"
,
orderId
);
return
ResponseUtil
.
ok
(
data
);
}
/**
* 取消订单
* <p>
* 1. 检测当前订单是否能够取消;
* 2. 设置订单取消状态;
* 3. 商品货品库存恢复;
* 4. TODO 优惠券;
* 5. TODO 团购活动。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
* @return 取消订单操作结果
*/
@Transactional
public
Object
cancel
(
Integer
userId
,
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
LocalDateTime
preUpdateTime
=
order
.
getUpdateTime
();
// 检测是否能够取消
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isCancel
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能取消"
);
}
// 设置订单已取消状态
order
.
setOrderStatus
(
OrderUtil
.
STATUS_CANCEL
);
order
.
setEndTime
(
LocalDateTime
.
now
());
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
throw
new
RuntimeException
(
"更新数据已失效"
);
}
// 商品货品数量增加
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
orderId
);
for
(
LitemallOrderGoods
orderGoods
:
orderGoodsList
)
{
Integer
productId
=
orderGoods
.
getProductId
();
Short
number
=
orderGoods
.
getNumber
();
if
(
productService
.
addStock
(
productId
,
number
)
==
0
)
{
throw
new
RuntimeException
(
"商品货品库存增加失败"
);
}
}
return
ResponseUtil
.
ok
();
}
/**
* 付款订单的预支付会话标识
* <p>
* 1. 检测当前订单是否能够付款
* 2. 微信商户平台返回支付订单ID
* 3. 设置订单付款状态
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
* @return 支付订单ID
*/
@Transactional
public
Object
prepay
(
Integer
userId
,
String
body
,
HttpServletRequest
request
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
// 检测是否能够取消
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isPay
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能支付"
);
}
LitemallUser
user
=
userService
.
findById
(
userId
);
String
openid
=
user
.
getWeixinOpenid
();
if
(
openid
==
null
)
{
return
ResponseUtil
.
fail
(
AUTH_OPENID_UNACCESS
,
"订单不能支付"
);
}
WxPayMpOrderResult
result
=
null
;
try
{
WxPayUnifiedOrderRequest
orderRequest
=
new
WxPayUnifiedOrderRequest
();
orderRequest
.
setOutTradeNo
(
order
.
getOrderSn
());
orderRequest
.
setOpenid
(
openid
);
orderRequest
.
setBody
(
"订单:"
+
order
.
getOrderSn
());
// 元转成分
int
fee
=
0
;
BigDecimal
actualPrice
=
order
.
getActualPrice
();
fee
=
actualPrice
.
multiply
(
new
BigDecimal
(
100
)).
intValue
();
orderRequest
.
setTotalFee
(
fee
);
orderRequest
.
setSpbillCreateIp
(
IpUtil
.
getIpAddr
(
request
));
result
=
wxPayService
.
createOrder
(
orderRequest
);
//缓存prepayID用于后续模版通知
String
prepayId
=
result
.
getPackageValue
();
prepayId
=
prepayId
.
replace
(
"prepay_id="
,
""
);
LitemallUserFormid
userFormid
=
new
LitemallUserFormid
();
userFormid
.
setOpenid
(
user
.
getWeixinOpenid
());
userFormid
.
setFormid
(
prepayId
);
userFormid
.
setIsprepay
(
true
);
userFormid
.
setUseamount
(
3
);
userFormid
.
setExpireTime
(
LocalDateTime
.
now
().
plusDays
(
7
));
formIdService
.
addUserFormid
(
userFormid
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
ResponseUtil
.
fail
(
ORDER_PAY_FAIL
,
"订单不能支付"
);
}
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
return
ResponseUtil
.
updatedDateExpired
();
}
return
ResponseUtil
.
ok
(
result
);
}
/**
* 微信付款成功或失败回调接口
* <p>
* 1. 检测当前订单是否是付款状态;
* 2. 设置订单付款成功状态相关信息;
* 3. 响应微信商户平台.
*
* @param request 请求内容
* @param response 响应内容
* @return 操作结果
*/
@Transactional
public
Object
payNotify
(
HttpServletRequest
request
,
HttpServletResponse
response
)
{
String
xmlResult
=
null
;
try
{
xmlResult
=
IOUtils
.
toString
(
request
.
getInputStream
(),
request
.
getCharacterEncoding
());
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
return
WxPayNotifyResponse
.
fail
(
e
.
getMessage
());
}
WxPayOrderNotifyResult
result
=
null
;
try
{
result
=
wxPayService
.
parseOrderNotifyResult
(
xmlResult
);
}
catch
(
WxPayException
e
)
{
e
.
printStackTrace
();
return
WxPayNotifyResponse
.
fail
(
e
.
getMessage
());
}
logger
.
info
(
"处理腾讯支付平台的订单支付"
);
logger
.
info
(
result
);
String
orderSn
=
result
.
getOutTradeNo
();
String
payId
=
result
.
getTransactionId
();
// 分转化成元
String
totalFee
=
BaseWxPayResult
.
fenToYuan
(
result
.
getTotalFee
());
LitemallOrder
order
=
orderService
.
findBySn
(
orderSn
);
if
(
order
==
null
)
{
return
WxPayNotifyResponse
.
fail
(
"订单不存在 sn="
+
orderSn
);
}
// 检查这个订单是否已经处理过
if
(
OrderUtil
.
isPayStatus
(
order
)
&&
order
.
getPayId
()
!=
null
)
{
return
WxPayNotifyResponse
.
success
(
"订单已经处理成功!"
);
}
// 检查支付订单金额
if
(!
totalFee
.
equals
(
order
.
getActualPrice
().
toString
()))
{
return
WxPayNotifyResponse
.
fail
(
order
.
getOrderSn
()
+
" : 支付金额不符合 totalFee="
+
totalFee
);
}
order
.
setPayId
(
payId
);
order
.
setPayTime
(
LocalDateTime
.
now
());
order
.
setOrderStatus
(
OrderUtil
.
STATUS_PAY
);
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
// 这里可能存在这样一个问题,用户支付和系统自动取消订单发生在同时
// 如果数据库首先因为系统自动取消订单而更新了订单状态;
// 此时用户支付完成回调这里也要更新数据库,而由于乐观锁机制这里的更新会失败
// 因此,这里会重新读取数据库检查状态是否是订单自动取消,如果是则更新成支付状态。
order
=
orderService
.
findBySn
(
orderSn
);
int
updated
=
0
;
if
(
OrderUtil
.
isAutoCancelStatus
(
order
))
{
order
.
setPayId
(
payId
);
order
.
setPayTime
(
LocalDateTime
.
now
());
order
.
setOrderStatus
(
OrderUtil
.
STATUS_PAY
);
updated
=
orderService
.
updateWithOptimisticLocker
(
order
);
}
// 如果updated是0,那么数据库更新失败
if
(
updated
==
0
)
{
return
WxPayNotifyResponse
.
fail
(
"更新数据已失效"
);
}
}
// 支付成功,有团购信息,更新团购信息
LitemallGroupon
groupon
=
grouponService
.
queryByOrderId
(
order
.
getId
());
if
(
groupon
!=
null
)
{
LitemallGrouponRules
grouponRules
=
grouponRulesService
.
queryById
(
groupon
.
getRulesId
());
//仅当发起者才创建分享图片
if
(
groupon
.
getGrouponId
()
==
0
)
{
String
url
=
qCodeService
.
createGrouponShareImage
(
grouponRules
.
getGoodsName
(),
grouponRules
.
getPicUrl
(),
groupon
);
groupon
.
setShareUrl
(
url
);
}
groupon
.
setPayed
(
true
);
if
(
grouponService
.
updateById
(
groupon
)
==
0
)
{
return
WxPayNotifyResponse
.
fail
(
"更新数据已失效"
);
}
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 订单支付成功以后,会发送短信给用户,以及发送邮件给管理员
notifyService
.
notifyMail
(
"新订单通知"
,
order
.
toString
());
// 这里微信的短信平台对参数长度有限制,所以将订单号只截取后6位
notifyService
.
notifySmsTemplateSync
(
order
.
getMobile
(),
NotifyType
.
PAY_SUCCEED
,
new
String
[]{
orderSn
.
substring
(
8
,
14
)});
// 请依据自己的模版消息配置更改参数
String
[]
parms
=
new
String
[]{
order
.
getOrderSn
(),
order
.
getOrderPrice
().
toString
(),
DateTimeUtil
.
getDateTimeDisplayString
(
order
.
getAddTime
()),
order
.
getConsignee
(),
order
.
getMobile
(),
order
.
getAddress
()
};
notifyService
.
notifyWxTemplate
(
result
.
getOpenid
(),
NotifyType
.
PAY_SUCCEED
,
parms
,
"pages/index/index?orderId="
+
order
.
getId
());
return
WxPayNotifyResponse
.
success
(
"处理成功!"
);
}
/**
* 订单申请退款
* <p>
* 1. 检测当前订单是否能够退款;
* 2. 设置订单申请退款状态。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
* @return 订单退款操作结果
*/
public
Object
refund
(
Integer
userId
,
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isRefund
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能取消"
);
}
// 设置订单申请退款状态
order
.
setOrderStatus
(
OrderUtil
.
STATUS_REFUND
);
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
return
ResponseUtil
.
updatedDateExpired
();
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 有用户申请退款,邮件通知运营人员
notifyService
.
notifyMail
(
"退款申请"
,
order
.
toString
());
return
ResponseUtil
.
ok
();
}
/**
* 确认收货
* <p>
* 1. 检测当前订单是否能够确认收货;
* 2. 设置订单确认收货状态。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果
*/
public
Object
confirm
(
Integer
userId
,
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isConfirm
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能确认收货"
);
}
Short
comments
=
orderGoodsService
.
getComments
(
orderId
);
order
.
setComments
(
comments
);
order
.
setOrderStatus
(
OrderUtil
.
STATUS_CONFIRM
);
order
.
setConfirmTime
(
LocalDateTime
.
now
());
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
return
ResponseUtil
.
updatedDateExpired
();
}
return
ResponseUtil
.
ok
();
}
/**
* 删除订单
* <p>
* 1. 检测当前订单是否可以删除;
* 2. 删除订单。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果
*/
public
Object
delete
(
Integer
userId
,
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isDelete
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能删除"
);
}
// 订单order_status没有字段用于标识删除
// 而是存在专门的delete字段表示是否删除
orderService
.
deleteById
(
orderId
);
return
ResponseUtil
.
ok
();
}
/**
* 待评价订单商品信息
*
* @param userId 用户ID
* @param orderId 订单ID
* @param goodsId 商品ID
* @return 待评价订单商品信息
*/
public
Object
goods
(
Integer
userId
,
Integer
orderId
,
Integer
goodsId
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
findByOidAndGid
(
orderId
,
goodsId
);
int
size
=
orderGoodsList
.
size
();
Assert
.
state
(
size
<
2
,
"存在多个符合条件的订单商品"
);
if
(
size
==
0
)
{
return
ResponseUtil
.
badArgumentValue
();
}
LitemallOrderGoods
orderGoods
=
orderGoodsList
.
get
(
0
);
return
ResponseUtil
.
ok
(
orderGoods
);
}
/**
* 评价订单商品
* <p>
* 确认商品收货或者系统自动确认商品收货后7天内可以评价,过期不能评价。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果
*/
public
Object
comment
(
Integer
userId
,
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderGoodsId
=
JacksonUtil
.
parseInteger
(
body
,
"orderGoodsId"
);
if
(
orderGoodsId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrderGoods
orderGoods
=
orderGoodsService
.
findById
(
orderGoodsId
);
if
(
orderGoods
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
Integer
orderId
=
orderGoods
.
getOrderId
();
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
Short
orderStatus
=
order
.
getOrderStatus
();
if
(!
OrderUtil
.
isConfirmStatus
(
order
)
&&
!
OrderUtil
.
isAutoConfirmStatus
(
order
))
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"当前商品不能评价"
);
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
fail
(
ORDER_INVALID
,
"当前商品不属于用户"
);
}
Integer
commentId
=
orderGoods
.
getComment
();
if
(
commentId
==
-
1
)
{
return
ResponseUtil
.
fail
(
ORDER_COMMENT_EXPIRED
,
"当前商品评价时间已经过期"
);
}
if
(
commentId
!=
0
)
{
return
ResponseUtil
.
fail
(
ORDER_COMMENTED
,
"订单商品已评价"
);
}
String
content
=
JacksonUtil
.
parseString
(
body
,
"content"
);
Integer
star
=
JacksonUtil
.
parseInteger
(
body
,
"star"
);
if
(
star
==
null
||
star
<
0
||
star
>
5
)
{
return
ResponseUtil
.
badArgumentValue
();
}
Boolean
hasPicture
=
JacksonUtil
.
parseBoolean
(
body
,
"hasPicture"
);
List
<
String
>
picUrls
=
JacksonUtil
.
parseStringList
(
body
,
"picUrls"
);
if
(
hasPicture
==
null
||
!
hasPicture
)
{
picUrls
=
new
ArrayList
<>(
0
);
}
// 1. 创建评价
LitemallComment
comment
=
new
LitemallComment
();
comment
.
setUserId
(
userId
);
comment
.
setType
((
byte
)
0
);
comment
.
setValueId
(
orderGoods
.
getGoodsId
());
comment
.
setStar
(
star
.
shortValue
());
comment
.
setContent
(
content
);
comment
.
setHasPicture
(
hasPicture
);
comment
.
setPicUrls
(
picUrls
.
toArray
(
new
String
[]{}));
commentService
.
save
(
comment
);
// 2. 更新订单商品的评价列表
orderGoods
.
setComment
(
comment
.
getId
());
orderGoodsService
.
updateById
(
orderGoods
);
// 3. 更新订单中未评价的订单商品可评价数量
Short
commentCount
=
order
.
getComments
();
if
(
commentCount
>
0
)
{
commentCount
--;
}
order
.
setComments
(
commentCount
);
orderService
.
updateWithOptimisticLocker
(
order
);
return
ResponseUtil
.
ok
();
}
}
\ No newline at end of file
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/web/WxOrderController.java
View file @
fbc7dc6a
package
org.linlinjava.litemall.wx.web
;
import
com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse
;
import
com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult
;
import
com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult
;
import
com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest
;
import
com.github.binarywang.wxpay.bean.result.BaseWxPayResult
;
import
com.github.binarywang.wxpay.exception.WxPayException
;
import
com.github.binarywang.wxpay.service.WxPayService
;
import
org.apache.commons.io.IOUtils
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.linlinjava.litemall.core.express.ExpressService
;
import
org.linlinjava.litemall.core.express.dao.ExpressInfo
;
import
org.linlinjava.litemall.core.notify.NotifyService
;
import
org.linlinjava.litemall.core.notify.NotifyType
;
import
org.linlinjava.litemall.core.qcode.QCodeService
;
import
org.linlinjava.litemall.core.system.SystemConfig
;
import
org.linlinjava.litemall.core.util.DateTimeUtil
;
import
org.linlinjava.litemall.core.util.JacksonUtil
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.db.domain.*
;
import
org.linlinjava.litemall.db.service.*
;
import
org.linlinjava.litemall.db.util.CouponUserConstant
;
import
org.linlinjava.litemall.db.util.OrderHandleOption
;
import
org.linlinjava.litemall.db.util.OrderUtil
;
import
org.linlinjava.litemall.wx.annotation.LoginUser
;
import
org.linlinjava.litemall.wx.
util.IpUtil
;
import
org.linlinjava.litemall.wx.
service.WxOrderService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.PlatformTransactionManager
;
import
org.springframework.transaction.TransactionDefinition
;
import
org.springframework.transaction.TransactionStatus
;
import
org.springframework.transaction.support.DefaultTransactionDefinition
;
import
org.springframework.util.Assert
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.validation.constraints.NotNull
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
linlinjava
.
litemall
.
wx
.
util
.
WxResponseCode
.*;
/**
* 订单服务
*
* <p>
* 订单状态:
* 101 订单生成,未支付;102,下单后未支付用户取消;103,下单后未支付超时系统自动取消
* 201 支付完成,商家未发货;202,订单生产,已付款未发货,但是退款取消;
* 301 商家发货,用户未确认;
* 401 用户确认收货; 402 用户没有确认收货超过一定时间,系统自动确认收货;
*
* <p>
* 用户操作:
* 当101用户未付款时,此时用户可以进行的操作是取消订单,或者付款操作
* 当201支付完成而商家未发货时,此时用户可以取消订单并申请退款
* 当301商家已发货时,此时用户可以有确认收货的操作
* 当401用户确认收货以后,此时用户可以进行的操作是删除订单,评价商品,或者再次购买
* 当402系统自动确认收货以后,此时用户可以删除订单,评价商品,或者再次购买
*
* <p>
* 注意:目前不支持订单退货和售后服务
*/
@RestController
@RequestMapping
(
"/wx/order"
)
@Validated
...
...
@@ -76,65 +19,13 @@ public class WxOrderController {
private
final
Log
logger
=
LogFactory
.
getLog
(
WxOrderController
.
class
);
@Autowired
private
PlatformTransactionManager
txManager
;
@Autowired
private
LitemallUserService
userService
;
@Autowired
private
LitemallOrderService
orderService
;
@Autowired
private
LitemallOrderGoodsService
orderGoodsService
;
@Autowired
private
LitemallAddressService
addressService
;
@Autowired
private
LitemallCartService
cartService
;
@Autowired
private
LitemallRegionService
regionService
;
@Autowired
private
LitemallGoodsProductService
productService
;
@Autowired
private
WxPayService
wxPayService
;
@Autowired
private
NotifyService
notifyService
;
@Autowired
private
LitemallUserFormIdService
formIdService
;
@Autowired
private
LitemallGrouponRulesService
grouponRulesService
;
@Autowired
private
LitemallGrouponService
grouponService
;
@Autowired
private
QCodeService
qCodeService
;
@Autowired
private
ExpressService
expressService
;
@Autowired
private
LitemallCommentService
commentService
;
@Autowired
private
LitemallCouponService
couponService
;
@Autowired
private
LitemallCouponUserService
couponUserService
;
@Autowired
private
CouponVerifyService
couponVerifyService
;
private
String
detailedAddress
(
LitemallAddress
litemallAddress
)
{
Integer
provinceId
=
litemallAddress
.
getProvinceId
();
Integer
cityId
=
litemallAddress
.
getCityId
();
Integer
areaId
=
litemallAddress
.
getAreaId
();
String
provinceName
=
regionService
.
findById
(
provinceId
).
getName
();
String
cityName
=
regionService
.
findById
(
cityId
).
getName
();
String
areaName
=
regionService
.
findById
(
areaId
).
getName
();
String
fullRegion
=
provinceName
+
" "
+
cityName
+
" "
+
areaName
;
return
fullRegion
+
" "
+
litemallAddress
.
getAddress
();
}
private
WxOrderService
wxOrderService
;
/**
* 订单列表
*
* @param userId 用户ID
* @param showType 订单信息:
* 0,全部订单;
* 1,待付款;
* 2,待发货;
* 3,待收货;
* 4,待评价。
* @param showType 订单信息
* @param page 分页页数
* @param size 分页大小
* @return 订单列表
...
...
@@ -144,50 +35,7 @@ public class WxOrderController {
@RequestParam
(
defaultValue
=
"0"
)
Integer
showType
,
@RequestParam
(
defaultValue
=
"1"
)
Integer
page
,
@RequestParam
(
defaultValue
=
"10"
)
Integer
size
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
List
<
Short
>
orderStatus
=
OrderUtil
.
orderStatus
(
showType
);
List
<
LitemallOrder
>
orderList
=
orderService
.
queryByOrderStatus
(
userId
,
orderStatus
);
int
count
=
orderService
.
countByOrderStatus
(
userId
,
orderStatus
);
List
<
Map
<
String
,
Object
>>
orderVoList
=
new
ArrayList
<>(
orderList
.
size
());
for
(
LitemallOrder
order
:
orderList
)
{
Map
<
String
,
Object
>
orderVo
=
new
HashMap
<>();
orderVo
.
put
(
"id"
,
order
.
getId
());
orderVo
.
put
(
"orderSn"
,
order
.
getOrderSn
());
orderVo
.
put
(
"actualPrice"
,
order
.
getActualPrice
());
orderVo
.
put
(
"orderStatusText"
,
OrderUtil
.
orderStatusText
(
order
));
orderVo
.
put
(
"handleOption"
,
OrderUtil
.
build
(
order
));
LitemallGroupon
groupon
=
grouponService
.
queryByOrderId
(
order
.
getId
());
if
(
groupon
!=
null
)
{
orderVo
.
put
(
"isGroupin"
,
true
);
}
else
{
orderVo
.
put
(
"isGroupin"
,
false
);
}
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
order
.
getId
());
List
<
Map
<
String
,
Object
>>
orderGoodsVoList
=
new
ArrayList
<>(
orderGoodsList
.
size
());
for
(
LitemallOrderGoods
orderGoods
:
orderGoodsList
)
{
Map
<
String
,
Object
>
orderGoodsVo
=
new
HashMap
<>();
orderGoodsVo
.
put
(
"id"
,
orderGoods
.
getId
());
orderGoodsVo
.
put
(
"goodsName"
,
orderGoods
.
getGoodsName
());
orderGoodsVo
.
put
(
"number"
,
orderGoods
.
getNumber
());
orderGoodsVo
.
put
(
"picUrl"
,
orderGoods
.
getPicUrl
());
orderGoodsVoList
.
add
(
orderGoodsVo
);
}
orderVo
.
put
(
"goodsList"
,
orderGoodsVoList
);
orderVoList
.
add
(
orderVo
);
}
Map
<
String
,
Object
>
result
=
new
HashMap
<>();
result
.
put
(
"count"
,
count
);
result
.
put
(
"data"
,
orderVoList
);
return
ResponseUtil
.
ok
(
result
);
return
wxOrderService
.
list
(
userId
,
showType
,
page
,
size
);
}
/**
...
...
@@ -199,58 +47,11 @@ public class WxOrderController {
*/
@GetMapping
(
"detail"
)
public
Object
detail
(
@LoginUser
Integer
userId
,
@NotNull
Integer
orderId
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
// 订单信息
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
null
==
order
)
{
return
ResponseUtil
.
fail
(
ORDER_UNKNOWN
,
"订单不存在"
);
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
fail
(
ORDER_INVALID
,
"不是当前用户的订单"
);
}
Map
<
String
,
Object
>
orderVo
=
new
HashMap
<
String
,
Object
>();
orderVo
.
put
(
"id"
,
order
.
getId
());
orderVo
.
put
(
"orderSn"
,
order
.
getOrderSn
());
orderVo
.
put
(
"addTime"
,
order
.
getAddTime
());
orderVo
.
put
(
"consignee"
,
order
.
getConsignee
());
orderVo
.
put
(
"mobile"
,
order
.
getMobile
());
orderVo
.
put
(
"address"
,
order
.
getAddress
());
orderVo
.
put
(
"goodsPrice"
,
order
.
getGoodsPrice
());
orderVo
.
put
(
"freightPrice"
,
order
.
getFreightPrice
());
orderVo
.
put
(
"actualPrice"
,
order
.
getActualPrice
());
orderVo
.
put
(
"orderStatusText"
,
OrderUtil
.
orderStatusText
(
order
));
orderVo
.
put
(
"handleOption"
,
OrderUtil
.
build
(
order
));
orderVo
.
put
(
"expCode"
,
order
.
getShipChannel
());
orderVo
.
put
(
"expNo"
,
order
.
getShipSn
());
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
order
.
getId
());
Map
<
String
,
Object
>
result
=
new
HashMap
<>();
result
.
put
(
"orderInfo"
,
orderVo
);
result
.
put
(
"orderGoods"
,
orderGoodsList
);
// 订单状态为已发货且物流信息不为空
//"YTO", "800669400640887922"
if
(
order
.
getOrderStatus
().
equals
(
OrderUtil
.
STATUS_SHIP
))
{
ExpressInfo
ei
=
expressService
.
getExpressInfo
(
order
.
getShipChannel
(),
order
.
getShipSn
());
result
.
put
(
"expressInfo"
,
ei
);
}
return
ResponseUtil
.
ok
(
result
);
return
wxOrderService
.
detail
(
userId
,
orderId
);
}
/**
* 提交订单
* <p>
* 1. 创建订单表项和订单商品表项;
* 2. 购物车清空;
* 3. 优惠券设置已用;
* 4. 商品货品库存减少;
* 5. 如果是团购商品,则创建团购活动表项。
*
* @param userId 用户ID
* @param body 订单信息,{ cartId:xxx, addressId: xxx, couponId: xxx, message: xxx, grouponRulesId: xxx, grouponLinkId: xxx}
...
...
@@ -258,219 +59,11 @@ public class WxOrderController {
*/
@PostMapping
(
"submit"
)
public
Object
submit
(
@LoginUser
Integer
userId
,
@RequestBody
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
if
(
body
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
Integer
cartId
=
JacksonUtil
.
parseInteger
(
body
,
"cartId"
);
Integer
addressId
=
JacksonUtil
.
parseInteger
(
body
,
"addressId"
);
Integer
couponId
=
JacksonUtil
.
parseInteger
(
body
,
"couponId"
);
String
message
=
JacksonUtil
.
parseString
(
body
,
"message"
);
Integer
grouponRulesId
=
JacksonUtil
.
parseInteger
(
body
,
"grouponRulesId"
);
Integer
grouponLinkId
=
JacksonUtil
.
parseInteger
(
body
,
"grouponLinkId"
);
//如果是团购项目,验证活动是否有效
if
(
grouponRulesId
!=
null
&&
grouponRulesId
>
0
)
{
LitemallGrouponRules
rules
=
grouponRulesService
.
queryById
(
grouponRulesId
);
//找不到记录
if
(
rules
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
//团购活动已经过期
if
(
grouponRulesService
.
isExpired
(
rules
))
{
return
ResponseUtil
.
fail
(
GROUPON_EXPIRED
,
"团购活动已过期!"
);
}
}
if
(
cartId
==
null
||
addressId
==
null
||
couponId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
// 收货地址
LitemallAddress
checkedAddress
=
addressService
.
findById
(
addressId
);
if
(
checkedAddress
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
// 团购优惠
BigDecimal
grouponPrice
=
new
BigDecimal
(
0.00
);
LitemallGrouponRules
grouponRules
=
grouponRulesService
.
queryById
(
grouponRulesId
);
if
(
grouponRules
!=
null
)
{
grouponPrice
=
grouponRules
.
getDiscount
();
}
// 货品价格
List
<
LitemallCart
>
checkedGoodsList
=
null
;
if
(
cartId
.
equals
(
0
))
{
checkedGoodsList
=
cartService
.
queryByUidAndChecked
(
userId
);
}
else
{
LitemallCart
cart
=
cartService
.
findById
(
cartId
);
checkedGoodsList
=
new
ArrayList
<>(
1
);
checkedGoodsList
.
add
(
cart
);
}
if
(
checkedGoodsList
.
size
()
==
0
)
{
return
ResponseUtil
.
badArgumentValue
();
}
BigDecimal
checkedGoodsPrice
=
new
BigDecimal
(
0.00
);
for
(
LitemallCart
checkGoods
:
checkedGoodsList
)
{
// 只有当团购规格商品ID符合才进行团购优惠
if
(
grouponRules
!=
null
&&
grouponRules
.
getGoodsId
().
equals
(
checkGoods
.
getGoodsId
()))
{
checkedGoodsPrice
=
checkedGoodsPrice
.
add
(
checkGoods
.
getPrice
().
subtract
(
grouponPrice
).
multiply
(
new
BigDecimal
(
checkGoods
.
getNumber
())));
}
else
{
checkedGoodsPrice
=
checkedGoodsPrice
.
add
(
checkGoods
.
getPrice
().
multiply
(
new
BigDecimal
(
checkGoods
.
getNumber
())));
}
}
// 获取可用的优惠券信息
// 使用优惠券减免的金额
BigDecimal
couponPrice
=
new
BigDecimal
(
0.00
);
// 如果couponId=0则没有优惠券,couponId=-1则不使用优惠券
if
(
couponId
!=
0
&&
couponId
!=
-
1
){
LitemallCoupon
coupon
=
couponVerifyService
.
checkCoupon
(
userId
,
couponId
,
checkedGoodsPrice
);
if
(
coupon
==
null
){
return
ResponseUtil
.
badArgumentValue
();
}
couponPrice
=
coupon
.
getDiscount
();
}
// 根据订单商品总价计算运费,满足条件(例如88元)则免运费,否则需要支付运费(例如8元);
BigDecimal
freightPrice
=
new
BigDecimal
(
0.00
);
if
(
checkedGoodsPrice
.
compareTo
(
SystemConfig
.
getFreightLimit
())
<
0
)
{
freightPrice
=
SystemConfig
.
getFreight
();
}
// 可以使用的其他钱,例如用户积分
BigDecimal
integralPrice
=
new
BigDecimal
(
0.00
);
// 订单费用
BigDecimal
orderTotalPrice
=
checkedGoodsPrice
.
add
(
freightPrice
).
subtract
(
couponPrice
);
// 最终支付费用
BigDecimal
actualPrice
=
orderTotalPrice
.
subtract
(
integralPrice
);
// 开启事务管理
DefaultTransactionDefinition
def
=
new
DefaultTransactionDefinition
();
def
.
setPropagationBehavior
(
TransactionDefinition
.
PROPAGATION_REQUIRED
);
TransactionStatus
status
=
txManager
.
getTransaction
(
def
);
Integer
orderId
=
null
;
LitemallOrder
order
=
null
;
try
{
// 订单
order
=
new
LitemallOrder
();
order
.
setUserId
(
userId
);
order
.
setOrderSn
(
orderService
.
generateOrderSn
(
userId
));
order
.
setOrderStatus
(
OrderUtil
.
STATUS_CREATE
);
order
.
setConsignee
(
checkedAddress
.
getName
());
order
.
setMobile
(
checkedAddress
.
getMobile
());
order
.
setMessage
(
message
);
String
detailedAddress
=
detailedAddress
(
checkedAddress
);
order
.
setAddress
(
detailedAddress
);
order
.
setGoodsPrice
(
checkedGoodsPrice
);
order
.
setFreightPrice
(
freightPrice
);
order
.
setCouponPrice
(
couponPrice
);
order
.
setIntegralPrice
(
integralPrice
);
order
.
setOrderPrice
(
orderTotalPrice
);
order
.
setActualPrice
(
actualPrice
);
// 有团购活动
if
(
grouponRules
!=
null
)
{
order
.
setGrouponPrice
(
grouponPrice
);
// 团购价格
}
else
{
order
.
setGrouponPrice
(
new
BigDecimal
(
0.00
));
// 团购价格
}
// 添加订单表项
orderService
.
add
(
order
);
orderId
=
order
.
getId
();
// 添加订单商品表项
for
(
LitemallCart
cartGoods
:
checkedGoodsList
)
{
// 订单商品
LitemallOrderGoods
orderGoods
=
new
LitemallOrderGoods
();
orderGoods
.
setOrderId
(
order
.
getId
());
orderGoods
.
setGoodsId
(
cartGoods
.
getGoodsId
());
orderGoods
.
setGoodsSn
(
cartGoods
.
getGoodsSn
());
orderGoods
.
setProductId
(
cartGoods
.
getProductId
());
orderGoods
.
setGoodsName
(
cartGoods
.
getGoodsName
());
orderGoods
.
setPicUrl
(
cartGoods
.
getPicUrl
());
orderGoods
.
setPrice
(
cartGoods
.
getPrice
());
orderGoods
.
setNumber
(
cartGoods
.
getNumber
());
orderGoods
.
setSpecifications
(
cartGoods
.
getSpecifications
());
orderGoods
.
setAddTime
(
LocalDateTime
.
now
());
orderGoodsService
.
add
(
orderGoods
);
}
// 删除购物车里面的商品信息
cartService
.
clearGoods
(
userId
);
// 商品货品数量减少
for
(
LitemallCart
checkGoods
:
checkedGoodsList
)
{
Integer
productId
=
checkGoods
.
getProductId
();
LitemallGoodsProduct
product
=
productService
.
findById
(
productId
);
Integer
remainNumber
=
product
.
getNumber
()
-
checkGoods
.
getNumber
();
if
(
remainNumber
<
0
)
{
throw
new
RuntimeException
(
"下单的商品货品数量大于库存量"
);
}
if
(
productService
.
reduceStock
(
productId
,
checkGoods
.
getNumber
())
==
0
)
{
throw
new
Exception
(
"商品货品库存减少失败"
);
}
}
// 如果使用了优惠券,设置优惠券使用状态
if
(
couponId
!=
0
&&
couponId
!=
-
1
){
LitemallCouponUser
couponUser
=
couponUserService
.
queryOne
(
userId
,
couponId
);
couponUser
.
setStatus
(
CouponUserConstant
.
STATUS_USED
);
couponUser
.
setUsedTime
(
LocalDateTime
.
now
());
couponUser
.
setOrderId
(
orderId
);
couponUserService
.
update
(
couponUser
);
}
//如果是团购项目,添加团购信息
if
(
grouponRulesId
!=
null
&&
grouponRulesId
>
0
)
{
LitemallGroupon
groupon
=
new
LitemallGroupon
();
groupon
.
setOrderId
(
orderId
);
groupon
.
setPayed
(
false
);
groupon
.
setUserId
(
userId
);
groupon
.
setRulesId
(
grouponRulesId
);
//参与者
if
(
grouponLinkId
!=
null
&&
grouponLinkId
>
0
)
{
//参与的团购记录
LitemallGroupon
baseGroupon
=
grouponService
.
queryById
(
grouponLinkId
);
groupon
.
setCreatorUserId
(
baseGroupon
.
getCreatorUserId
());
groupon
.
setGrouponId
(
grouponLinkId
);
groupon
.
setShareUrl
(
baseGroupon
.
getShareUrl
());
}
else
{
groupon
.
setCreatorUserId
(
userId
);
groupon
.
setGrouponId
(
0
);
}
grouponService
.
createGroupon
(
groupon
);
}
}
catch
(
Exception
ex
)
{
txManager
.
rollback
(
status
);
logger
.
error
(
"系统内部错误"
,
ex
);
return
ResponseUtil
.
fail
(
ORDER_CHECKOUT_FAIL
,
"下单失败"
);
}
txManager
.
commit
(
status
);
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"orderId"
,
orderId
);
return
ResponseUtil
.
ok
(
data
);
return
wxOrderService
.
submit
(
userId
,
body
);
}
/**
* 取消订单
* <p>
* 1. 检测当前订单是否能够取消;
* 2. 设置订单取消状态;
* 3. 商品货品库存恢复;
* 4. TODO 优惠券;
* 5. TODO 团购活动。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
...
...
@@ -478,67 +71,11 @@ public class WxOrderController {
*/
@PostMapping
(
"cancel"
)
public
Object
cancel
(
@LoginUser
Integer
userId
,
@RequestBody
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
LocalDateTime
preUpdateTime
=
order
.
getUpdateTime
();
// 检测是否能够取消
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isCancel
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能取消"
);
}
// 开启事务管理
DefaultTransactionDefinition
def
=
new
DefaultTransactionDefinition
();
def
.
setPropagationBehavior
(
TransactionDefinition
.
PROPAGATION_REQUIRED
);
TransactionStatus
status
=
txManager
.
getTransaction
(
def
);
try
{
// 设置订单已取消状态
order
.
setOrderStatus
(
OrderUtil
.
STATUS_CANCEL
);
order
.
setEndTime
(
LocalDateTime
.
now
());
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
throw
new
Exception
(
"更新数据已失效"
);
}
// 商品货品数量增加
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
queryByOid
(
orderId
);
for
(
LitemallOrderGoods
orderGoods
:
orderGoodsList
)
{
Integer
productId
=
orderGoods
.
getProductId
();
Short
number
=
orderGoods
.
getNumber
();
if
(
productService
.
addStock
(
productId
,
number
)
==
0
)
{
throw
new
Exception
(
"商品货品库存增加失败"
);
}
}
}
catch
(
Exception
ex
)
{
txManager
.
rollback
(
status
);
logger
.
error
(
"系统内部错误"
,
ex
);
return
ResponseUtil
.
fail
(
ORDER_CANCEL_FAIL
,
"订单取消失败"
);
}
txManager
.
commit
(
status
);
return
ResponseUtil
.
ok
();
return
wxOrderService
.
cancel
(
userId
,
body
);
}
/**
* 付款订单的预支付会话标识
* <p>
* 1. 检测当前订单是否能够付款
* 2. 微信商户平台返回支付订单ID
* 3. 设置订单付款状态
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
...
...
@@ -546,77 +83,13 @@ public class WxOrderController {
*/
@PostMapping
(
"prepay"
)
public
Object
prepay
(
@LoginUser
Integer
userId
,
@RequestBody
String
body
,
HttpServletRequest
request
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
// 检测是否能够取消
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isPay
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能支付"
);
}
LitemallUser
user
=
userService
.
findById
(
userId
);
String
openid
=
user
.
getWeixinOpenid
();
if
(
openid
==
null
)
{
return
ResponseUtil
.
fail
(
AUTH_OPENID_UNACCESS
,
"订单不能支付"
);
}
WxPayMpOrderResult
result
=
null
;
try
{
WxPayUnifiedOrderRequest
orderRequest
=
new
WxPayUnifiedOrderRequest
();
orderRequest
.
setOutTradeNo
(
order
.
getOrderSn
());
orderRequest
.
setOpenid
(
openid
);
orderRequest
.
setBody
(
"订单:"
+
order
.
getOrderSn
());
// 元转成分
Integer
fee
=
0
;
BigDecimal
actualPrice
=
order
.
getActualPrice
();
fee
=
actualPrice
.
multiply
(
new
BigDecimal
(
100
)).
intValue
();
orderRequest
.
setTotalFee
(
fee
);
orderRequest
.
setSpbillCreateIp
(
IpUtil
.
getIpAddr
(
request
));
result
=
wxPayService
.
createOrder
(
orderRequest
);
//缓存prepayID用于后续模版通知
String
prepayId
=
result
.
getPackageValue
();
prepayId
=
prepayId
.
replace
(
"prepay_id="
,
""
);
LitemallUserFormid
userFormid
=
new
LitemallUserFormid
();
userFormid
.
setOpenid
(
user
.
getWeixinOpenid
());
userFormid
.
setFormid
(
prepayId
);
userFormid
.
setIsprepay
(
true
);
userFormid
.
setUseamount
(
3
);
userFormid
.
setExpireTime
(
LocalDateTime
.
now
().
plusDays
(
7
));
formIdService
.
addUserFormid
(
userFormid
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
ResponseUtil
.
fail
(
ORDER_PAY_FAIL
,
"订单不能支付"
);
}
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
return
ResponseUtil
.
updatedDateExpired
();
}
return
ResponseUtil
.
ok
(
result
);
return
wxOrderService
.
prepay
(
userId
,
body
,
request
);
}
/**
* 微信付款成功或失败回调接口
* <p>
* 1. 检测当前订单是否是付款状态;
* 2. 设置订单付款成功状态相关信息;
* 3. 响应微信商户平台.
* <p>
* TODO
* 注意,这里pay-notify是示例地址,建议开发者应该设立一个隐蔽的回调地址
*
* @param request 请求内容
...
...
@@ -625,110 +98,11 @@ public class WxOrderController {
*/
@PostMapping
(
"pay-notify"
)
public
Object
payNotify
(
HttpServletRequest
request
,
HttpServletResponse
response
)
{
String
xmlResult
=
null
;
try
{
xmlResult
=
IOUtils
.
toString
(
request
.
getInputStream
(),
request
.
getCharacterEncoding
());
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
return
WxPayNotifyResponse
.
fail
(
e
.
getMessage
());
}
WxPayOrderNotifyResult
result
=
null
;
try
{
result
=
wxPayService
.
parseOrderNotifyResult
(
xmlResult
);
}
catch
(
WxPayException
e
)
{
e
.
printStackTrace
();
return
WxPayNotifyResponse
.
fail
(
e
.
getMessage
());
}
logger
.
info
(
"处理腾讯支付平台的订单支付"
);
logger
.
info
(
result
);
String
orderSn
=
result
.
getOutTradeNo
();
String
payId
=
result
.
getTransactionId
();
// 分转化成元
String
totalFee
=
BaseWxPayResult
.
fenToYuan
(
result
.
getTotalFee
());
LitemallOrder
order
=
orderService
.
findBySn
(
orderSn
);
if
(
order
==
null
)
{
return
WxPayNotifyResponse
.
fail
(
"订单不存在 sn="
+
orderSn
);
}
// 检查这个订单是否已经处理过
if
(
OrderUtil
.
isPayStatus
(
order
)
&&
order
.
getPayId
()
!=
null
)
{
return
WxPayNotifyResponse
.
success
(
"订单已经处理成功!"
);
}
// 检查支付订单金额
if
(!
totalFee
.
equals
(
order
.
getActualPrice
().
toString
()))
{
return
WxPayNotifyResponse
.
fail
(
order
.
getOrderSn
()
+
" : 支付金额不符合 totalFee="
+
totalFee
);
}
order
.
setPayId
(
payId
);
order
.
setPayTime
(
LocalDateTime
.
now
());
order
.
setOrderStatus
(
OrderUtil
.
STATUS_PAY
);
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
// 这里可能存在这样一个问题,用户支付和系统自动取消订单发生在同时
// 如果数据库首先因为系统自动取消订单而更新了订单状态;
// 此时用户支付完成回调这里也要更新数据库,而由于乐观锁机制这里的更新会失败
// 因此,这里会重新读取数据库检查状态是否是订单自动取消,如果是则更新成支付状态。
order
=
orderService
.
findBySn
(
orderSn
);
int
updated
=
0
;
if
(
OrderUtil
.
isAutoCancelStatus
(
order
))
{
order
.
setPayId
(
payId
);
order
.
setPayTime
(
LocalDateTime
.
now
());
order
.
setOrderStatus
(
OrderUtil
.
STATUS_PAY
);
updated
=
orderService
.
updateWithOptimisticLocker
(
order
);
}
// 如果updated是0,那么数据库更新失败
if
(
updated
==
0
)
{
return
WxPayNotifyResponse
.
fail
(
"更新数据已失效"
);
}
}
// 支付成功,有团购信息,更新团购信息
LitemallGroupon
groupon
=
grouponService
.
queryByOrderId
(
order
.
getId
());
if
(
groupon
!=
null
)
{
LitemallGrouponRules
grouponRules
=
grouponRulesService
.
queryById
(
groupon
.
getRulesId
());
//仅当发起者才创建分享图片
if
(
groupon
.
getGrouponId
()
==
0
)
{
String
url
=
qCodeService
.
createGrouponShareImage
(
grouponRules
.
getGoodsName
(),
grouponRules
.
getPicUrl
(),
groupon
);
groupon
.
setShareUrl
(
url
);
}
groupon
.
setPayed
(
true
);
if
(
grouponService
.
updateById
(
groupon
)
==
0
)
{
return
WxPayNotifyResponse
.
fail
(
"更新数据已失效"
);
}
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 订单支付成功以后,会发送短信给用户,以及发送邮件给管理员
notifyService
.
notifyMail
(
"新订单通知"
,
order
.
toString
());
// 这里微信的短信平台对参数长度有限制,所以将订单号只截取后6位
notifyService
.
notifySmsTemplateSync
(
order
.
getMobile
(),
NotifyType
.
PAY_SUCCEED
,
new
String
[]{
orderSn
.
substring
(
8
,
14
)});
// 请依据自己的模版消息配置更改参数
String
[]
parms
=
new
String
[]{
order
.
getOrderSn
(),
order
.
getOrderPrice
().
toString
(),
DateTimeUtil
.
getDateTimeDisplayString
(
order
.
getAddTime
()),
order
.
getConsignee
(),
order
.
getMobile
(),
order
.
getAddress
()
};
notifyService
.
notifyWxTemplate
(
result
.
getOpenid
(),
NotifyType
.
PAY_SUCCEED
,
parms
,
"pages/index/index?orderId="
+
order
.
getId
());
return
WxPayNotifyResponse
.
success
(
"处理成功!"
);
return
wxOrderService
.
payNotify
(
request
,
response
);
}
/**
* 订单申请退款
* <p>
* 1. 检测当前订单是否能够退款;
* 2. 设置订单申请退款状态。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
...
...
@@ -736,45 +110,11 @@ public class WxOrderController {
*/
@PostMapping
(
"refund"
)
public
Object
refund
(
@LoginUser
Integer
userId
,
@RequestBody
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isRefund
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能取消"
);
}
// 设置订单申请退款状态
order
.
setOrderStatus
(
OrderUtil
.
STATUS_REFUND
);
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
return
ResponseUtil
.
updatedDateExpired
();
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 有用户申请退款,邮件通知运营人员
notifyService
.
notifyMail
(
"退款申请"
,
order
.
toString
());
return
ResponseUtil
.
ok
();
return
wxOrderService
.
refund
(
userId
,
body
);
}
/**
* 确认收货
* <p>
* 1. 检测当前订单是否能够确认收货;
* 2. 设置订单确认收货状态。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
...
...
@@ -782,43 +122,11 @@ public class WxOrderController {
*/
@PostMapping
(
"confirm"
)
public
Object
confirm
(
@LoginUser
Integer
userId
,
@RequestBody
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isConfirm
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能确认收货"
);
}
Short
comments
=
orderGoodsService
.
getComments
(
orderId
);
order
.
setComments
(
comments
);
order
.
setOrderStatus
(
OrderUtil
.
STATUS_CONFIRM
);
order
.
setConfirmTime
(
LocalDateTime
.
now
());
if
(
orderService
.
updateWithOptimisticLocker
(
order
)
==
0
)
{
return
ResponseUtil
.
updatedDateExpired
();
}
return
ResponseUtil
.
ok
();
return
wxOrderService
.
confirm
(
userId
,
body
);
}
/**
* 删除订单
* <p>
* 1. 检测当前订单是否可以删除;
* 2. 删除订单。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
...
...
@@ -826,32 +134,7 @@ public class WxOrderController {
*/
@PostMapping
(
"delete"
)
public
Object
delete
(
@LoginUser
Integer
userId
,
@RequestBody
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderId
=
JacksonUtil
.
parseInteger
(
body
,
"orderId"
);
if
(
orderId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
badArgumentValue
();
}
OrderHandleOption
handleOption
=
OrderUtil
.
build
(
order
);
if
(!
handleOption
.
isDelete
())
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"订单不能删除"
);
}
// 订单order_status没有字段用于标识删除
// 而是存在专门的delete字段表示是否删除
orderService
.
deleteById
(
orderId
);
return
ResponseUtil
.
ok
();
return
wxOrderService
.
delete
(
userId
,
body
);
}
/**
...
...
@@ -866,27 +149,11 @@ public class WxOrderController {
public
Object
goods
(
@LoginUser
Integer
userId
,
@NotNull
Integer
orderId
,
@NotNull
Integer
goodsId
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
List
<
LitemallOrderGoods
>
orderGoodsList
=
orderGoodsService
.
findByOidAndGid
(
orderId
,
goodsId
);
int
size
=
orderGoodsList
.
size
();
Assert
.
state
(
size
<
2
,
"存在多个符合条件的订单商品"
);
if
(
size
==
0
)
{
return
ResponseUtil
.
badArgumentValue
();
}
LitemallOrderGoods
orderGoods
=
orderGoodsList
.
get
(
0
);
return
ResponseUtil
.
ok
(
orderGoods
);
return
wxOrderService
.
goods
(
userId
,
orderId
,
goodsId
);
}
/**
* 评价订单商品
* <p>
* 确认商品收货或者系统自动确认商品收货后7天内可以评价,过期不能评价。
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
...
...
@@ -894,73 +161,7 @@ public class WxOrderController {
*/
@PostMapping
(
"comment"
)
public
Object
comment
(
@LoginUser
Integer
userId
,
@RequestBody
String
body
)
{
if
(
userId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
Integer
orderGoodsId
=
JacksonUtil
.
parseInteger
(
body
,
"orderGoodsId"
);
if
(
orderGoodsId
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
LitemallOrderGoods
orderGoods
=
orderGoodsService
.
findById
(
orderGoodsId
);
if
(
orderGoods
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
Integer
orderId
=
orderGoods
.
getOrderId
();
LitemallOrder
order
=
orderService
.
findById
(
orderId
);
if
(
order
==
null
)
{
return
ResponseUtil
.
badArgumentValue
();
}
Short
orderStatus
=
order
.
getOrderStatus
();
if
(!
OrderUtil
.
isConfirmStatus
(
order
)
&&
!
OrderUtil
.
isAutoConfirmStatus
(
order
))
{
return
ResponseUtil
.
fail
(
ORDER_INVALID_OPERATION
,
"当前商品不能评价"
);
}
if
(!
order
.
getUserId
().
equals
(
userId
))
{
return
ResponseUtil
.
fail
(
ORDER_INVALID
,
"当前商品不属于用户"
);
}
Integer
commentId
=
orderGoods
.
getComment
();
if
(
commentId
==
-
1
)
{
return
ResponseUtil
.
fail
(
ORDER_COMMENT_EXPIRED
,
"当前商品评价时间已经过期"
);
}
if
(
commentId
!=
0
)
{
return
ResponseUtil
.
fail
(
ORDER_COMMENTED
,
"订单商品已评价"
);
}
String
content
=
JacksonUtil
.
parseString
(
body
,
"content"
);
Integer
star
=
JacksonUtil
.
parseInteger
(
body
,
"star"
);
if
(
star
==
null
||
star
<
0
||
star
>
5
)
{
return
ResponseUtil
.
badArgumentValue
();
}
Boolean
hasPicture
=
JacksonUtil
.
parseBoolean
(
body
,
"hasPicture"
);
List
<
String
>
picUrls
=
JacksonUtil
.
parseStringList
(
body
,
"picUrls"
);
if
(
hasPicture
==
null
||
!
hasPicture
)
{
picUrls
=
new
ArrayList
<>(
0
);
}
// 1. 创建评价
LitemallComment
comment
=
new
LitemallComment
();
comment
.
setUserId
(
userId
);
comment
.
setType
((
byte
)
0
);
comment
.
setValueId
(
orderGoods
.
getGoodsId
());
comment
.
setStar
(
star
.
shortValue
());
comment
.
setContent
(
content
);
comment
.
setHasPicture
(
hasPicture
);
comment
.
setPicUrls
(
picUrls
.
toArray
(
new
String
[]{}));
commentService
.
save
(
comment
);
// 2. 更新订单商品的评价列表
orderGoods
.
setComment
(
comment
.
getId
());
orderGoodsService
.
updateById
(
orderGoods
);
// 3. 更新订单中未评价的订单商品可评价数量
Short
commentCount
=
order
.
getComments
();
if
(
commentCount
>
0
)
{
commentCount
--;
}
order
.
setComments
(
commentCount
);
orderService
.
updateWithOptimisticLocker
(
order
);
return
ResponseUtil
.
ok
();
return
wxOrderService
.
comment
(
userId
,
body
);
}
}
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment