Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gxpt_ht
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
pseer
gxpt_ht
Commits
538f83d0
Commit
538f83d0
authored
Oct 23, 2023
by
wuwenlong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
create order dev;
parent
81caf6da
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
631 additions
and
60 deletions
+631
-60
WeChatConfig.java
...ommon/src/main/java/share/common/config/WeChatConfig.java
+3
-0
Constants.java
...common/src/main/java/share/common/constant/Constants.java
+4
-0
OrderTypeEnum.java
...ommon/src/main/java/share/common/enums/OrderTypeEnum.java
+36
-0
SOrderController.java
...in/java/share/web/controller/system/SOrderController.java
+6
-5
application-dev.yml
share-front/src/main/resources/application-dev.yml
+2
-1
application-prod.yml
share-front/src/main/resources/application-prod.yml
+2
-1
SOrder.java
share-system/src/main/java/share/system/domain/SOrder.java
+16
-42
CreateOrderRequestVo.java
...ain/java/share/system/domain/vo/CreateOrderRequestVo.java
+0
-3
WxPayJsResultVo.java
...src/main/java/share/system/domain/vo/WxPayJsResultVo.java
+40
-0
CreateOrderRequest.java
...rc/main/java/share/system/request/CreateOrderRequest.java
+3
-0
OrderPayRequest.java
...m/src/main/java/share/system/request/OrderPayRequest.java
+42
-0
OrderPayResultResponse.java
...in/java/share/system/response/OrderPayResultResponse.java
+35
-0
ISOrderService.java
...em/src/main/java/share/system/service/ISOrderService.java
+2
-1
OrderPayService.java
...m/src/main/java/share/system/service/OrderPayService.java
+19
-0
OrderPayServiceImpl.java
...n/java/share/system/service/impl/OrderPayServiceImpl.java
+136
-0
SOrderServiceImpl.java
...ain/java/share/system/service/impl/SOrderServiceImpl.java
+65
-6
WechatNewServiceImpl.java
.../java/share/system/service/impl/WechatNewServiceImpl.java
+1
-1
WxPayUtil.java
share-system/src/main/java/share/system/util/WxPayUtil.java
+219
-0
No files found.
share-common/src/main/java/share/common/config/WeChatConfig.java
View file @
538f83d0
...
...
@@ -19,6 +19,9 @@ public class WeChatConfig
private
String
appSecret
;
private
String
mchId
;
private
String
signKey
;
private
String
publicAppId
;
...
...
share-common/src/main/java/share/common/constant/Constants.java
View file @
538f83d0
...
...
@@ -9,6 +9,10 @@ import io.jsonwebtoken.Claims;
*/
public
class
Constants
{
public
static
final
String
CONFIG_KEY_SITE_URL
=
"site_url"
;
//域名
public
static
final
String
CONFIG_KEY_API_URL
=
"api_url"
;
//admin接口地址
// 订单取消Key
public
static
final
String
ORDER_AUTO_CANCEL_KEY
=
"order_auto_cancel_key"
;
//测试环境,经测试需要,手机验证码测试环境可以不需要就能登录,value为1,则不验证验证码
public
static
final
String
PHONE_TEST_KEY
=
"phone_test_key"
;
//通过uuid缓存的key 查找对应的 token数据 WX_TOKEN_USER:TOKEN
...
...
share-common/src/main/java/share/common/enums/OrderTypeEnum.java
0 → 100644
View file @
538f83d0
package
share
.
common
.
enums
;
/**
* @Author wwl
* @Date 2023/10/20 10:57
*/
public
enum
OrderTypeEnum
{
RESERVER
(
1
,
"预定"
),
RENEW
(
2
,
"续费"
),
RECHARGE
(
3
,
"充值"
);
private
Integer
code
;
private
String
name
;
OrderTypeEnum
(
Integer
code
,
String
name
)
{
this
.
code
=
code
;
this
.
name
=
name
;
}
public
static
OrderTypeEnum
getEnumByCode
(
Integer
code
){
for
(
OrderTypeEnum
type
:
OrderTypeEnum
.
values
())
{
if
(
type
.
code
.
compareTo
(
code
)==
0
)
{
return
type
;
}
}
return
null
;
}
public
Integer
getCode
(){
return
code
;
}
public
String
getName
()
{
return
name
;
}
}
share-front/src/main/java/share/web/controller/system/SOrderController.java
View file @
538f83d0
...
...
@@ -18,6 +18,7 @@ import share.system.domain.vo.MyRecord;
import
share.system.request.CreateOrderRequest
;
import
share.system.request.OrderComputedPriceRequest
;
import
share.system.response.ComputedOrderPriceResponse
;
import
share.system.response.OrderPayResultResponse
;
import
share.system.service.ISOrderService
;
import
share.common.core.page.TableDataInfo
;
...
...
@@ -63,17 +64,17 @@ public class SOrderController extends BaseController
/**
* 下单
*/
//
@ApiOperation(value = "下单")
@ApiOperation
(
value
=
"下单"
)
@RequestMapping
(
value
=
"/creat"
,
method
=
RequestMethod
.
POST
)
public
R
<
MyRecord
>
createOrder
(
@RequestBody
@Validated
CreateOrderRequest
request
)
{
public
R
<
OrderPayResultResponse
>
createOrder
(
@RequestBody
@Validated
CreateOrderRequest
request
)
{
if
(
"1"
.
equals
(
redisUtil
.
frontInOutLogSwitch
()))
{
log
.
info
(
"SOrderController method preOrder 入参 {}"
,
JsonConvertUtil
.
write2JsonStr
(
request
));
}
MyRecord
record
=
sOrderService
.
createOrder
(
request
);
OrderPayResultResponse
response
=
sOrderService
.
createOrder
(
request
);
if
(
"1"
.
equals
(
redisUtil
.
frontInOutLogSwitch
()))
{
log
.
info
(
"SOrderController method preOrder 出参 {}"
,
JsonConvertUtil
.
write2JsonStr
(
re
cord
));
log
.
info
(
"SOrderController method preOrder 出参 {}"
,
JsonConvertUtil
.
write2JsonStr
(
re
sponse
));
}
return
R
.
ok
(
re
cord
);
return
R
.
ok
(
re
sponse
);
}
...
...
share-front/src/main/resources/application-dev.yml
View file @
538f83d0
...
...
@@ -18,7 +18,8 @@ ruoyi:
wechat
:
appId
:
wx0802dd3453f72cc9
appSecret
:
0f36e45668b4cc714affc4fa6ecdb4bf
mchId
:
0
signKey
:
0
# 开发环境配置
server
:
# 服务器的HTTP端口,默认为8080
...
...
share-front/src/main/resources/application-prod.yml
View file @
538f83d0
...
...
@@ -18,7 +18,8 @@ ruoyi:
wechat
:
appId
:
wx0802dd3453f72cc9
appSecret
:
0f36e45668b4cc714affc4fa6ecdb4bf
mchId
:
0
signKey
:
0
# 开发环境配置
server
:
# 服务器的HTTP端口,默认为8080
...
...
share-system/src/main/java/share/system/domain/SOrder.java
View file @
538f83d0
...
...
@@ -22,30 +22,22 @@ import javax.validation.constraints.NotBlank;
* @date 2023-10-09
*/
@Data
public
class
SOrder
extends
BaseEntity
{
public
class
SOrder
extends
BaseEntity
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 订单ID
*/
/** 订单ID */
private
Long
id
;
/**
* 订单流水号
*/
/** 订单流水号 */
@Excel
(
name
=
"订单编号"
)
private
String
orderNo
;
/**
* 订单流水号
*/
@Excel
(
name
=
"订单编号"
)
@Excel
(
name
=
"商户订单号"
)
private
String
outTradeNo
;
/**
* 订单类型(0:订房订单,1:续房订单,2:充值订单)
*/
@Excel
(
name
=
"订单类型(0:订房订单,1:续房订单,2:充值订单)"
)
/** 订单类型(0:订房订单,1:续房订单,2:充值订单) */
@Excel
(
name
=
"订单类型(1:订房订单,2:续房订单,3:充值订单)"
)
private
Integer
orderType
;
@Excel
(
name
=
"支付类型(1:微信,2:支付宝)"
)
...
...
@@ -60,21 +52,15 @@ public class SOrder extends BaseEntity {
@Excel
(
name
=
"房间ID"
)
private
Long
roomId
;
/**
* 用户ID
*/
/** 用户ID */
@Excel
(
name
=
"用户ID"
)
private
Long
consumerId
;
/**
* 用户名称
*/
/** 用户名称 */
@Excel
(
name
=
"用户名称"
)
private
String
consumerName
;
/**
* 用户手机号
*/
/** 用户手机号 */
@Excel
(
name
=
"用户手机号"
)
private
String
consumerPhone
;
...
...
@@ -84,9 +70,7 @@ public class SOrder extends BaseEntity {
@ApiModelProperty
(
value
=
"套餐金额"
)
private
BigDecimal
packPrice
;
/**
* 优惠券id
*/
/** 优惠券id */
@Excel
(
name
=
"优惠券id"
)
private
String
couponId
;
...
...
@@ -105,37 +89,27 @@ public class SOrder extends BaseEntity {
@Excel
(
name
=
"订单时长(H)"
)
private
String
timeLong
;
/**
* 预约开始时间
*/
/** 预约开始时间 */
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm"
)
@Excel
(
name
=
"预约开始时间"
,
width
=
30
,
dateFormat
=
"yyyy-MM-dd HH:mm"
)
private
Date
preStartDate
;
/**
* 预约结束时间
*/
/** 预约结束时间 */
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm"
)
@Excel
(
name
=
"预约结束时间"
,
width
=
30
,
dateFormat
=
"yyyy-MM-dd HH:mm"
)
private
Date
preEndDate
;
/**
* 开始时间
*/
/** 开始时间 */
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm"
)
@Excel
(
name
=
"开始时间"
,
width
=
30
,
dateFormat
=
"yyyy-MM-dd HH:mm"
)
private
Date
startDate
;
/**
* 结束时间
*/
/** 结束时间 */
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm"
)
@Excel
(
name
=
"结束时间"
,
width
=
30
,
dateFormat
=
"yyyy-MM-dd HH:mm"
)
private
Date
endDate
;
/**
* 订单状态(0:待使用/已预约,1:使用中,2:已使用,3:已取消预约/退款中)
*/
/** 订单状态(0:待使用/已预约,1:使用中,2:已使用,3:已取消预约/退款中) */
@Excel
(
name
=
"订单状态(0:待使用/已预约,1:使用中,2:已使用)"
)
private
Integer
status
;
...
...
share-system/src/main/java/share/system/domain/vo/CreateOrderRequestVo.java
View file @
538f83d0
...
...
@@ -50,9 +50,6 @@ public class CreateOrderRequestVo {
@ApiModelProperty
(
value
=
"订单总金额,单位为分"
,
required
=
true
)
private
int
total_fee
;
@ApiModelProperty
(
value
=
"必须传正确的用户端IP,支持ipv4、ipv6格式,获取方式详见获取用户ip指引"
,
required
=
true
)
private
String
spbill_create_ip
;
@ApiModelProperty
(
value
=
"订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则"
)
private
String
time_start
;
...
...
share-system/src/main/java/share/system/domain/vo/WxPayJsResultVo.java
0 → 100644
View file @
538f83d0
package
share
.
system
.
domain
.
vo
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
/**
* 微信调起支付参数对象
*/
@Data
@ApiModel
(
value
=
"WxPayJsResultVo对象"
,
description
=
"微信调起支付参数对象"
)
public
class
WxPayJsResultVo
{
@ApiModelProperty
(
value
=
"微信分配的小程序ID"
)
private
String
appId
;
@ApiModelProperty
(
value
=
"随机字符串,不长于32位"
)
private
String
nonceStr
;
@ApiModelProperty
(
value
=
"统一下单接口返回的 prepay_id 参数值"
)
private
String
packages
;
@ApiModelProperty
(
value
=
"签名类型,默认为MD5,支持HMAC-SHA256和MD5。"
)
private
String
signType
;
@ApiModelProperty
(
value
=
"时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间"
)
private
String
timeStamp
;
@ApiModelProperty
(
value
=
"支付签名"
)
private
String
paySign
;
@ApiModelProperty
(
value
=
"H5支付跳转链接"
)
private
String
mwebUrl
;
@ApiModelProperty
(
value
=
"微信商户号"
)
private
String
partnerid
;
@ApiModelProperty
(
value
=
"拉起收银台的ticket"
)
private
String
ticket
;
}
share-system/src/main/java/share/system/request/CreateOrderRequest.java
View file @
538f83d0
...
...
@@ -38,6 +38,9 @@ public class CreateOrderRequest {
@NotBlank
(
message
=
"订单类型不能为空"
)
private
Integer
orderType
;
@ApiModelProperty
(
value
=
"续房订单的上一笔订单编号"
,
required
=
true
)
private
String
preOrderNo
;
@ApiModelProperty
(
value
=
"购买方式(1:小时,2:套餐)"
,
required
=
true
)
@NotBlank
(
message
=
"购买方式不能为空"
)
private
Integer
buyType
;
...
...
share-system/src/main/java/share/system/request/OrderPayRequest.java
0 → 100644
View file @
538f83d0
package
share
.
system
.
request
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.NotNull
;
import
java.math.BigDecimal
;
/**
* 支付订单参数
*/
@Data
@EqualsAndHashCode
(
callSuper
=
false
)
@Accessors
(
chain
=
true
)
@ApiModel
(
value
=
"OrderPayRequest对象"
,
description
=
"订单支付"
)
public
class
OrderPayRequest
{
@ApiModelProperty
(
value
=
"订单id"
)
private
String
uni
;
@ApiModelProperty
(
value
=
"订单编号"
)
@NotNull
(
message
=
"订单编号不能为空"
)
private
String
orderNo
;
@ApiModelProperty
(
value
=
"支付类型:weixin-微信支付,yue-余额支付,offline-线下支付,alipay-支付包支付"
)
@NotNull
(
message
=
"支付类型不能为空"
)
private
String
payType
;
@ApiModelProperty
(
value
=
"支付渠道:weixinh5-微信H5支付,public-公众号支付,routine-小程序支付,weixinAppIos-微信appios支付,weixinAppAndroid-微信app安卓支付,alipay-支付包支付,appAliPay-App支付宝支付"
)
@NotNull
(
message
=
"支付渠道不能为空"
)
private
String
payChannel
;
@ApiModelProperty
(
value
=
"支付平台"
)
private
String
from
;
@ApiModelProperty
(
value
=
"下单时小程序的场景值"
)
private
Integer
scene
;
}
share-system/src/main/java/share/system/response/OrderPayResultResponse.java
0 → 100644
View file @
538f83d0
package
share
.
system
.
response
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.experimental.Accessors
;
import
share.system.domain.vo.WxPayJsResultVo
;
/**
* 订单支付结果 Response
*/
@Data
@EqualsAndHashCode
(
callSuper
=
false
)
@Accessors
(
chain
=
true
)
@ApiModel
(
value
=
"OrderPayResultResponse对象"
,
description
=
"订单支付结果响应对象"
)
public
class
OrderPayResultResponse
{
private
static
final
long
serialVersionUID
=
1L
;
@ApiModelProperty
(
value
=
"支付状态"
)
private
Boolean
status
;
@ApiModelProperty
(
value
=
"微信调起支付参数对象"
)
private
WxPayJsResultVo
jsConfig
;
@ApiModelProperty
(
value
=
"支付类型"
)
private
String
payType
;
@ApiModelProperty
(
value
=
"订单编号"
)
private
String
orderNo
;
@ApiModelProperty
(
value
=
"微信支付回调的url"
)
private
String
notifyUrl
;
}
share-system/src/main/java/share/system/service/ISOrderService.java
View file @
538f83d0
...
...
@@ -9,6 +9,7 @@ import share.system.domain.vo.MyRecord;
import
share.system.request.CreateOrderRequest
;
import
share.system.request.OrderComputedPriceRequest
;
import
share.system.response.ComputedOrderPriceResponse
;
import
share.system.response.OrderPayResultResponse
;
/**
* 订单Service接口
...
...
@@ -80,7 +81,7 @@ public interface ISOrderService extends IService<SOrder>
* @param request 预下单请求参数
* @return PreOrderResponse
*/
MyRecord
createOrder
(
CreateOrderRequest
request
);
OrderPayResultResponse
createOrder
(
CreateOrderRequest
request
);
/**
* 计算订单价格
...
...
share-system/src/main/java/share/system/service/OrderPayService.java
0 → 100644
View file @
538f83d0
package
share
.
system
.
service
;
import
share.system.domain.SOrder
;
import
share.system.request.OrderPayRequest
;
import
share.system.response.OrderPayResultResponse
;
/**
* @Author wwl
* @Date 2023/10/23 15:46
*/
public
interface
OrderPayService
{
/**
* 订单支付
* @param sOrder 支付参数
* @return OrderPayResultResponse
*/
OrderPayResultResponse
payment
(
SOrder
sOrder
);
}
share-system/src/main/java/share/system/service/impl/OrderPayServiceImpl.java
0 → 100644
View file @
538f83d0
package
share
.
system
.
service
.
impl
;
import
cn.hutool.core.util.ObjectUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
share.common.config.WeChatConfig
;
import
share.common.constant.Constants
;
import
share.common.constant.PayConstants
;
import
share.common.enums.PayTypeEnum
;
import
share.common.enums.YesNoEnum
;
import
share.common.exception.base.BaseException
;
import
share.common.utils.BaseUtil
;
import
share.common.utils.DateUtil
;
import
share.common.utils.JsonConvertUtil
;
import
share.system.domain.SConsumerToken
;
import
share.system.domain.SOrder
;
import
share.system.domain.vo.CreateOrderRequestVo
;
import
share.system.domain.vo.CreateOrderResponseVo
;
import
share.system.domain.vo.WxPayJsResultVo
;
import
share.system.request.OrderPayRequest
;
import
share.system.response.OrderPayResultResponse
;
import
share.system.service.ISOrderService
;
import
share.system.service.OrderPayService
;
import
share.system.service.SConsumerTokenService
;
import
share.system.service.WechatNewService
;
import
share.system.util.WxPayUtil
;
import
java.math.BigDecimal
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* @Author wwl
* @Date 2023/10/23 15:47
*/
@Service
public
class
OrderPayServiceImpl
implements
OrderPayService
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
OrderPayServiceImpl
.
class
);
@Autowired
private
WeChatConfig
weChatConfig
;
@Autowired
private
SConsumerTokenService
consumerTokenService
;
@Autowired
private
WechatNewService
wechatNewService
;
@Autowired
private
ISOrderService
orderService
;
@Override
public
OrderPayResultResponse
payment
(
SOrder
sOrder
)
{
OrderPayResultResponse
response
=
new
OrderPayResultResponse
();
response
.
setOrderNo
(
sOrder
.
getOrderNo
());
response
.
setPayType
(
PayTypeEnum
.
getEnumByCode
(
sOrder
.
getPayType
()).
getValue
());
response
.
setStatus
(
YesNoEnum
.
no
.
getFlag
());
ConcurrentHashMap
<
String
,
String
>
unifiedorder
=
unifiedorder
(
sOrder
);
WxPayJsResultVo
vo
=
new
WxPayJsResultVo
();
vo
.
setAppId
(
unifiedorder
.
get
(
"appId"
));
vo
.
setNonceStr
(
unifiedorder
.
get
(
"nonceStr"
));
vo
.
setPackages
(
unifiedorder
.
get
(
"package"
));
vo
.
setSignType
(
unifiedorder
.
get
(
"signType"
));
vo
.
setTimeStamp
(
unifiedorder
.
get
(
"timeStamp"
));
vo
.
setPaySign
(
unifiedorder
.
get
(
"paySign"
));
// 更新商户订单号
sOrder
.
setOutTradeNo
(
unifiedorder
.
get
(
"outTradeNo"
));
orderService
.
updateById
(
sOrder
);
response
.
setJsConfig
(
vo
);
return
null
;
}
/**
* 预下单
* @param sOrder 订单
* @return 预下单返回对象
*/
private
ConcurrentHashMap
<
String
,
String
>
unifiedorder
(
SOrder
sOrder
)
{
// 获取用户openId
SConsumerToken
userToken
=
consumerTokenService
.
getTokenByUserId
(
sOrder
.
getConsumerId
());
if
(
ObjectUtil
.
isNull
(
userToken
))
{
throw
new
BaseException
(
"该用户没有openId"
);
}
// 获取appid、mch_id
// 微信签名key
String
appId
=
weChatConfig
.
getAppId
();
String
mchId
=
weChatConfig
.
getMchId
();
String
signKey
=
weChatConfig
.
getSignKey
();
// 获取微信预下单对象
CreateOrderRequestVo
unifiedorderVo
=
getUnifiedorderVo
(
sOrder
,
userToken
.
getToken
(),
appId
,
mchId
,
signKey
);
// 预下单(统一下单)
CreateOrderResponseVo
responseVo
=
wechatNewService
.
payUnifiedorder
(
unifiedorderVo
);
logger
.
info
(
"CreateOrderResponseVo :"
,
JsonConvertUtil
.
write2JsonStr
(
responseVo
));
// 组装前端预下单参数
ConcurrentHashMap
<
String
,
String
>
map
=
new
ConcurrentHashMap
<>();
map
.
put
(
"appId"
,
unifiedorderVo
.
getAppid
());
map
.
put
(
"nonceStr"
,
unifiedorderVo
.
getAppid
());
map
.
put
(
"package"
,
"prepay_id="
.
concat
(
responseVo
.
getPrepayId
()));
map
.
put
(
"signType"
,
unifiedorderVo
.
getSign_type
());
Long
currentTimestamp
=
WxPayUtil
.
getCurrentTimestamp
();
map
.
put
(
"timeStamp"
,
Long
.
toString
(
currentTimestamp
));
String
paySign
=
WxPayUtil
.
getSign
(
map
,
signKey
);
map
.
put
(
"paySign"
,
paySign
);
map
.
put
(
"prepayId"
,
responseVo
.
getPrepayId
());
map
.
put
(
"prepayTime"
,
DateUtil
.
nowDateTimeStr
());
map
.
put
(
"outTradeNo"
,
unifiedorderVo
.
getOut_trade_no
());
return
map
;
}
/**
* 获取微信预下单对象
* @return 微信预下单对象
*/
private
CreateOrderRequestVo
getUnifiedorderVo
(
SOrder
sOrder
,
String
openid
,
String
appId
,
String
mchId
,
String
signKey
)
{
// 获取域名
String
apiDomain
=
Constants
.
CONFIG_KEY_API_URL
;
CreateOrderRequestVo
vo
=
new
CreateOrderRequestVo
();
vo
.
setAppid
(
appId
);
vo
.
setMch_id
(
mchId
);
vo
.
setNonce_str
(
WxPayUtil
.
getNonceStr
());
vo
.
setSign_type
(
PayConstants
.
WX_PAY_SIGN_TYPE_MD5
);
vo
.
setOut_trade_no
(
BaseUtil
.
getOrderNo
(
"wxNo"
));
// 订单中使用的是BigDecimal,这里要转为Integer类型
vo
.
setTotal_fee
(
sOrder
.
getPayPrice
().
multiply
(
BigDecimal
.
TEN
).
multiply
(
BigDecimal
.
TEN
).
intValue
());
vo
.
setNotify_url
(
apiDomain
+
PayConstants
.
WX_PAY_NOTIFY_API_URI
);
vo
.
setTrade_type
(
PayConstants
.
WX_PAY_TRADE_TYPE_JS
);
vo
.
setOpenid
(
openid
);
String
sign
=
WxPayUtil
.
getSign
(
vo
,
signKey
);
vo
.
setSign
(
sign
);
return
vo
;
}
}
share-system/src/main/java/share/system/service/impl/SOrderServiceImpl.java
View file @
538f83d0
...
...
@@ -4,6 +4,7 @@ import java.math.BigDecimal;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.stream.Collectors
;
import
cn.hutool.core.collection.CollUtil
;
...
...
@@ -11,8 +12,14 @@ import cn.hutool.core.util.ObjectUtil;
import
com.alibaba.fastjson.JSONObject
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.math.NumberUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
share.common.constant.Constants
;
import
share.common.constant.PayConstants
;
import
share.common.core.redis.RedisUtil
;
import
share.common.enums.*
;
import
share.common.exception.base.BaseException
;
import
share.common.utils.BaseUtil
;
...
...
@@ -26,15 +33,14 @@ import share.system.domain.SConsumerCoupon;
import
share.system.domain.SRoom
;
import
share.system.domain.vo.FrontTokenComponent
;
import
share.system.domain.vo.MyRecord
;
import
share.system.domain.vo.WxPayJsResultVo
;
import
share.system.mapper.SOrderMapper
;
import
share.system.domain.SOrder
;
import
share.system.request.CreateOrderRequest
;
import
share.system.request.OrderComputedPriceRequest
;
import
share.system.response.ComputedOrderPriceResponse
;
import
share.system.service.ISConsumerCouponService
;
import
share.system.service.ISOrderService
;
import
share.system.service.ISRoomService
;
import
share.system.service.SConsumerService
;
import
share.system.response.OrderPayResultResponse
;
import
share.system.service.*
;
/**
* 订单Service业务层处理
...
...
@@ -45,6 +51,10 @@ import share.system.service.SConsumerService;
@Service
public
class
SOrderServiceImpl
extends
ServiceImpl
<
SOrderMapper
,
SOrder
>
implements
ISOrderService
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SOrderServiceImpl
.
class
);
@Autowired
private
SOrderMapper
sOrderMapper
;
...
...
@@ -57,6 +67,12 @@ public class SOrderServiceImpl extends ServiceImpl<SOrderMapper,SOrder> implemen
@Autowired
private
ISRoomService
roomService
;
@Autowired
private
OrderPayService
orderPayService
;
@Autowired
private
RedisUtil
redisUtil
;
/**
* 查询订单
*
...
...
@@ -145,7 +161,7 @@ public class SOrderServiceImpl extends ServiceImpl<SOrderMapper,SOrder> implemen
}
@Override
public
MyRecord
createOrder
(
CreateOrderRequest
request
)
{
public
OrderPayResultResponse
createOrder
(
CreateOrderRequest
request
)
{
SConsumer
user
=
FrontTokenComponent
.
getWxSConsumerEntry
();
if
(
ObjectUtil
.
isNull
(
user
))
{
throw
new
BaseException
(
"您的登录已过期,请先登录"
);
...
...
@@ -154,8 +170,51 @@ public class SOrderServiceImpl extends ServiceImpl<SOrderMapper,SOrder> implemen
//校验订单金额
checkOrderPrice
(
sOrder
,
user
);
//校验订单预约时间
checkOrderDate
(
request
);
OrderPayResultResponse
response
=
new
OrderPayResultResponse
();
if
(
request
.
getPayFee
().
compareTo
(
BigDecimal
.
ZERO
)
<=
0
)
{
response
.
setPayType
(
PayTypeEnum
.
WECHAT
.
getValue
());
response
.
setStatus
(
YesNoEnum
.
yes
.
getFlag
());
response
.
setOrderNo
(
sOrder
.
getOrderNo
());
sOrder
.
setPayStatus
(
YesNoEnum
.
yes
.
getIndex
());
}
else
{
response
=
orderPayService
.
payment
(
sOrder
);
// 加入自动未支付自动取消队列 TODO 自动取消定时任务待开发
redisUtil
.
lPush
(
Constants
.
ORDER_AUTO_CANCEL_KEY
,
sOrder
.
getOrderNo
());
}
save
(
sOrder
);
return
response
;
}
private
void
checkOrderDate
(
CreateOrderRequest
request
)
{
LambdaQueryWrapper
<
SOrder
>
queryWrapper
=
new
LambdaQueryWrapper
<>();
//订单开始时间在 【预定开始时间 和 预定结束时间+30分保洁】区间内
//订单结束时间在 【预定开始时间-30分钟保洁 和 预定结束时间】区间内
queryWrapper
.
apply
(
"IFNULL(start_date,pre_start_date) BETWEEN '"
+
DateUtils
.
parseDateToStr
(
DateUtils
.
YYYY_MM_DD_HH_MM_SS
,
request
.
getPreStartDate
())
+
"' AND '"
+
DateUtils
.
parseDateToStr
(
DateUtils
.
YYYY_MM_DD_HH_MM_SS
,
DateUtils
.
addMinutes
(
request
.
getPreEndDate
(),
30
))
+
"' "
+
"OR IFNULL(end_date,pre_end_date) BETWEEN '"
+
DateUtils
.
parseDateToStr
(
DateUtils
.
YYYY_MM_DD_HH_MM_SS
,
DateUtils
.
addMinutes
(
request
.
getPreStartDate
(),-
30
))
+
"' AND '"
+
DateUtils
.
parseDateToStr
(
DateUtils
.
YYYY_MM_DD_HH_MM_SS
,
request
.
getPreEndDate
())
+
"' "
);
switch
(
OrderTypeEnum
.
getEnumByCode
(
request
.
getOrderType
())){
case
RESERVER:
//预定
break
;
case
RENEW:
//续费
if
(
StringUtils
.
isBlank
(
request
.
getPreOrderNo
())){
throw
new
BaseException
(
"续房订单编号不能为空!"
);
}
//排除上笔订单
queryWrapper
.
ne
(
SOrder:
:
getOrderNo
,
request
.
getPreOrderNo
());
break
;
default
:
throw
new
BaseException
(
"订单类型异常!"
);
}
List
<
SOrder
>
orderList
=
list
(
queryWrapper
);
if
(
CollectionUtils
.
isNotEmpty
(
orderList
)){
throw
new
BaseException
(
"下单时间已被预定!"
);
}
return
null
;
}
private
void
checkOrderPrice
(
SOrder
order
,
SConsumer
user
){
...
...
share-system/src/main/java/share/system/service/impl/WechatNewServiceImpl.java
View file @
538f83d0
...
...
@@ -392,7 +392,7 @@ public class WechatNewServiceImpl implements WechatNewService {
payInfo
.
setOutTradeNo
(
vo
.
getOut_trade_no
());
payInfo
.
setFeeType
(
vo
.
getFee_type
());
payInfo
.
setTotalFee
(
vo
.
getTotal_fee
());
payInfo
.
setSpbillCreateIp
(
vo
.
getSpbill_create_ip
());
//
payInfo.setSpbillCreateIp(vo.getSpbill_create_ip());
payInfo
.
setTimeStart
(
vo
.
getTime_start
());
payInfo
.
setTimeExpire
(
vo
.
getTime_expire
());
payInfo
.
setNotifyUrl
(
vo
.
getNotify_url
());
...
...
share-system/src/main/java/share/system/util/WxPayUtil.java
0 → 100644
View file @
538f83d0
package
share
.
system
.
util
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.crypto.SecureUtil
;
import
com.alibaba.fastjson.JSONObject
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.w3c.dom.Node
;
import
org.w3c.dom.NodeList
;
import
share.common.constant.Constants
;
import
share.common.constant.PayConstants
;
import
share.common.exception.base.BaseException
;
import
share.common.utils.BaseUtil
;
import
share.common.utils.XmlUtil
;
import
share.common.utils.wx.WXPayXmlUtil
;
import
share.system.domain.vo.CreateOrderRequestVo
;
import
share.system.domain.vo.WxRefundVo
;
import
javax.xml.parsers.DocumentBuilder
;
import
java.io.ByteArrayInputStream
;
import
java.io.InputStream
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Set
;
/**
* 微信支付工具类
*/
public
class
WxPayUtil
{
/**
* 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。
*
* @param xmlStr API返回的XML格式数据
* @return Map类型数据
* @throws Exception
*/
public
static
HashMap
<
String
,
Object
>
processResponseXml
(
String
xmlStr
)
throws
Exception
{
String
RETURN_CODE
=
"return_code"
;
String
return_code
;
HashMap
<
String
,
Object
>
respData
=
XmlUtil
.
xmlToMap
(
xmlStr
);
if
(
respData
.
containsKey
(
RETURN_CODE
))
{
return_code
=
(
String
)
respData
.
get
(
RETURN_CODE
);
}
else
{
throw
new
BaseException
(
String
.
format
(
"No `return_code` in XML: %s"
,
xmlStr
));
}
if
(
return_code
.
equals
(
Constants
.
FAIL
))
{
return
respData
;
}
else
if
(
return_code
.
equals
(
Constants
.
SUCCESS
))
{
return
respData
;
}
else
{
throw
new
BaseException
(
String
.
format
(
"return_code value %s is invalid in XML: %s"
,
return_code
,
xmlStr
));
}
}
/**
* 获取随机字符串,长度要求在32位以内。
*/
public
static
String
getNonceStr
()
{
return
DigestUtils
.
md5Hex
(
BaseUtil
.
getUuid
()
+
BaseUtil
.
randomCount
(
111111
,
666666
));
}
/**
* 获取sign
* @param vo 微信公共下单对象
* @param signKey 微信签名key
* @return String
*/
public
static
String
getSign
(
CreateOrderRequestVo
vo
,
String
signKey
)
{
// 对象转map
Map
<
String
,
Object
>
map
=
JSONObject
.
parseObject
(
JSONObject
.
toJSONString
(
vo
),
Map
.
class
);
// map排序
Set
<
String
>
keySet
=
map
.
keySet
();
String
[]
keyArray
=
keySet
.
toArray
(
new
String
[
keySet
.
size
()]);
Arrays
.
sort
(
keyArray
);
StringBuilder
sb
=
new
StringBuilder
();
for
(
String
k
:
keyArray
)
{
if
(
k
.
equals
(
PayConstants
.
FIELD_SIGN
))
{
continue
;
}
if
(
ObjectUtil
.
isNotNull
(
map
.
get
(
k
)))
// 参数值为空,则不参与签名
sb
.
append
(
k
).
append
(
"="
).
append
(
map
.
get
(
k
)).
append
(
"&"
);
}
sb
.
append
(
"key="
).
append
(
signKey
);
String
sign
=
SecureUtil
.
md5
(
sb
.
toString
()).
toUpperCase
();
System
.
out
.
println
(
"sign ========== "
+
sign
);
return
sign
;
}
/**
* 获取sign
* @param wxRefundVo 微信退款对象
* @param signKey 微信签名key
* @return String
*/
public
static
String
getSign
(
WxRefundVo
wxRefundVo
,
String
signKey
)
{
// 对象转map
Map
<
String
,
Object
>
map
=
JSONObject
.
parseObject
(
JSONObject
.
toJSONString
(
wxRefundVo
),
Map
.
class
);
// map排序
Set
<
String
>
keySet
=
map
.
keySet
();
String
[]
keyArray
=
keySet
.
toArray
(
new
String
[
keySet
.
size
()]);
Arrays
.
sort
(
keyArray
);
StringBuilder
sb
=
new
StringBuilder
();
for
(
String
k
:
keyArray
)
{
if
(
k
.
equals
(
PayConstants
.
FIELD_SIGN
))
{
continue
;
}
if
(
ObjectUtil
.
isNotNull
(
map
.
get
(
k
)))
// 参数值为空,则不参与签名
sb
.
append
(
k
).
append
(
"="
).
append
(
map
.
get
(
k
)).
append
(
"&"
);
}
sb
.
append
(
"key="
).
append
(
signKey
);
String
sign
=
SecureUtil
.
md5
(
sb
.
toString
()).
toUpperCase
();
System
.
out
.
println
(
"sign ========== "
+
sign
);
return
sign
;
}
/**
* 获取sign
* @param map 待签名数据
* @param signKey 微信签名key
* @return String
*/
public
static
String
getSign
(
Map
<
String
,
String
>
map
,
String
signKey
)
{
// map排序
Set
<
String
>
keySet
=
map
.
keySet
();
String
[]
keyArray
=
keySet
.
toArray
(
new
String
[
keySet
.
size
()]);
Arrays
.
sort
(
keyArray
);
StringBuilder
sb
=
new
StringBuilder
();
for
(
String
k
:
keyArray
)
{
if
(
k
.
equals
(
PayConstants
.
FIELD_SIGN
))
{
continue
;
}
if
(
StrUtil
.
isNotBlank
(
map
.
get
(
k
))
&&
map
.
get
(
k
).
trim
().
length
()
>
0
)
// 参数值为空,则不参与签名
sb
.
append
(
k
).
append
(
"="
).
append
(
map
.
get
(
k
).
trim
()).
append
(
"&"
);
}
sb
.
append
(
"key="
).
append
(
signKey
);
String
sign
=
SecureUtil
.
md5
(
sb
.
toString
()).
toUpperCase
();
System
.
out
.
println
(
"sign ========== "
+
sign
);
return
sign
;
}
/**
* 获取sign
* @param map 待签名数据
* @param signKey 微信签名key
* @return String
*/
public
static
String
getSignObject
(
Map
<
String
,
Object
>
map
,
String
signKey
)
{
// map排序
Set
<
String
>
keySet
=
map
.
keySet
();
String
[]
keyArray
=
keySet
.
toArray
(
new
String
[
keySet
.
size
()]);
Arrays
.
sort
(
keyArray
);
StringBuilder
sb
=
new
StringBuilder
();
for
(
String
k
:
keyArray
)
{
if
(
k
.
equals
(
PayConstants
.
FIELD_SIGN
))
{
continue
;
}
if
(
ObjectUtil
.
isNotNull
(
map
.
get
(
k
)))
// 参数值为空,则不参与签名
sb
.
append
(
k
).
append
(
"="
).
append
(
map
.
get
(
k
)).
append
(
"&"
);
}
sb
.
append
(
"key="
).
append
(
signKey
);
String
sign
=
SecureUtil
.
md5
(
sb
.
toString
()).
toUpperCase
();
System
.
out
.
println
(
"sign ========== "
+
sign
);
return
sign
;
}
/**
* 获取当前时间戳,单位秒
* @return Long
*/
public
static
Long
getCurrentTimestamp
()
{
return
System
.
currentTimeMillis
()/
1000
;
}
/**
* 获取当前时间戳,单位毫秒
* @return Long
*/
public
static
Long
getCurrentTimestampMs
()
{
return
System
.
currentTimeMillis
();
}
/**
* XML格式字符串转换为Map
*
* @param strXML XML字符串
* @return XML数据转换后的Map
* @throws Exception
*/
public
static
Map
<
String
,
String
>
xmlToMap
(
String
strXML
)
throws
Exception
{
try
{
Map
<
String
,
String
>
data
=
new
HashMap
<
String
,
String
>();
DocumentBuilder
documentBuilder
=
WXPayXmlUtil
.
newDocumentBuilder
();
InputStream
stream
=
new
ByteArrayInputStream
(
strXML
.
getBytes
(
"UTF-8"
));
org
.
w3c
.
dom
.
Document
doc
=
documentBuilder
.
parse
(
stream
);
doc
.
getDocumentElement
().
normalize
();
NodeList
nodeList
=
doc
.
getDocumentElement
().
getChildNodes
();
for
(
int
idx
=
0
;
idx
<
nodeList
.
getLength
();
++
idx
)
{
Node
node
=
nodeList
.
item
(
idx
);
if
(
node
.
getNodeType
()
==
Node
.
ELEMENT_NODE
)
{
org
.
w3c
.
dom
.
Element
element
=
(
org
.
w3c
.
dom
.
Element
)
node
;
data
.
put
(
element
.
getNodeName
(),
element
.
getTextContent
());
}
}
try
{
stream
.
close
();
}
catch
(
Exception
ex
)
{
// do nothing
}
return
data
;
}
catch
(
Exception
ex
)
{
System
.
out
.
println
(
StrUtil
.
format
(
"Invalid XML, can not convert to map. Error message: {}. XML content: {}"
,
ex
.
getMessage
(),
strXML
));
throw
ex
;
}
}
}
Write
Preview
Markdown
is supported
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