Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
appApi
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
antaile
appApi
Commits
c584e28e
Commit
c584e28e
authored
May 31, 2021
by
XiaHou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
微信扫码登录相关代码提交
parent
ae04051b
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
2103 additions
and
88 deletions
+2103
-88
pom.xml
pom.xml
+7
-1
Constants.java
src/main/java/com/hwstudio/antaile/common/Constants.java
+7
-0
AtlTimeController.java
...va/com/hwstudio/antaile/controller/AtlTimeController.java
+3
-0
AtlWxController.java
...java/com/hwstudio/antaile/controller/AtlWxController.java
+12
-2
LoginController.java
...java/com/hwstudio/antaile/controller/LoginController.java
+10
-0
RegisterController.java
...a/com/hwstudio/antaile/controller/RegisterController.java
+1
-1
SmsController.java
...n/java/com/hwstudio/antaile/controller/SmsController.java
+1
-1
LoginUserDto.java
src/main/java/com/hwstudio/antaile/dto/LoginUserDto.java
+4
-0
OfficialWebsiteAtlTimeParam.java
...com/hwstudio/antaile/dto/OfficialWebsiteAtlTimeParam.java
+3
-0
VerifyCodeLogin.java
src/main/java/com/hwstudio/antaile/dto/VerifyCodeLogin.java
+20
-0
AtlUser.java
src/main/java/com/hwstudio/antaile/entity/AtlUser.java
+32
-26
AtlAdMapper.java
src/main/java/com/hwstudio/antaile/mapper/AtlAdMapper.java
+2
-13
AtlUserMapper.java
src/main/java/com/hwstudio/antaile/mapper/AtlUserMapper.java
+14
-4
AtlTimeService.java
...ain/java/com/hwstudio/antaile/service/AtlTimeService.java
+19
-2
AtlUserService.java
...ain/java/com/hwstudio/antaile/service/AtlUserService.java
+35
-17
AtlWxService.java
src/main/java/com/hwstudio/antaile/service/AtlWxService.java
+29
-14
SmsService.java
src/main/java/com/hwstudio/antaile/service/SmsService.java
+6
-0
CommonPage.java
src/main/java/com/hwstudio/antaile/utils/CommonPage.java
+85
-0
Page.java
src/main/java/com/hwstudio/antaile/utils/Page.java
+24
-0
IWXPayDomain.java
...main/java/com/hwstudio/antaile/utils/wx/IWXPayDomain.java
+43
-0
WXPay.java
src/main/java/com/hwstudio/antaile/utils/wx/WXPay.java
+689
-0
WXPayConfig.java
src/main/java/com/hwstudio/antaile/utils/wx/WXPayConfig.java
+103
-0
WXPayConstants.java
...in/java/com/hwstudio/antaile/utils/wx/WXPayConstants.java
+59
-0
WXPayReport.java
src/main/java/com/hwstudio/antaile/utils/wx/WXPayReport.java
+265
-0
WXPayRequest.java
...main/java/com/hwstudio/antaile/utils/wx/WXPayRequest.java
+257
-0
WXPayUtil.java
src/main/java/com/hwstudio/antaile/utils/wx/WXPayUtil.java
+295
-0
WXPayXmlUtil.java
...main/java/com/hwstudio/antaile/utils/wx/WXPayXmlUtil.java
+30
-0
application.yml
src/main/resources/application.yml
+1
-1
AtlUserMapper.xml
src/main/resources/mapping/AtlUserMapper.xml
+47
-6
No files found.
pom.xml
View file @
c584e28e
...
...
@@ -30,7 +30,7 @@
<dependency>
<groupId>
org.mybatis.spring.boot
</groupId>
<artifactId>
mybatis-spring-boot-starter
</artifactId>
<version>
2.0.
1
</version>
<version>
2.0.
0
</version>
</dependency>
<!-- 打包成war包必备 -->
<!--<dependency>-->
...
...
@@ -226,6 +226,12 @@
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-data-jpa
</artifactId>
</dependency>
<!--微信支付相关sdk-->
<dependency>
<groupId>
com.github.wxpay
</groupId>
<artifactId>
wxpay-sdk
</artifactId>
<version>
0.0.3
</version>
</dependency>
</dependencies>
<repositories>
...
...
src/main/java/com/hwstudio/antaile/common/Constants.java
View file @
c584e28e
...
...
@@ -120,6 +120,13 @@ public class Constants {
public
static
final
String
SMS_TYPE_BINDINGMOBILE_VALUE_INTERNATIONAL
=
"SMS_173406381"
;
/**
* 短信类型:5:验证码登录
*/
public
static
final
int
SMS_TYPE_MOBILELOGIN
=
5
;
public
static
final
String
SMS_TYPE_MOBILELOGIN_VALUE
=
"SMS_153815090"
;
public
static
final
String
SMS_TYPE_MOBILELOGIN_VALUE_INTERNATIONAL
=
"SMS_173406384"
;
/**
* 提现类型 1:咖啡豆
*/
public
static
final
Integer
WITHDRAW_TYPE_BEANS
=
1
;
...
...
src/main/java/com/hwstudio/antaile/controller/AtlTimeController.java
View file @
c584e28e
...
...
@@ -5,6 +5,7 @@ import com.hwstudio.antaile.entity.AtlMemorial;
import
com.hwstudio.antaile.entity.AtlTime
;
import
com.hwstudio.antaile.service.*
;
import
com.hwstudio.antaile.utils.JsonResult
;
import
com.hwstudio.antaile.utils.Page
;
import
com.hwstudio.antaile.vo.*
;
import
io.swagger.annotations.*
;
import
org.apache.commons.lang3.StringUtils
;
...
...
@@ -573,4 +574,6 @@ public class AtlTimeController extends BaseController {
public
JsonResult
selectRandomAtlTime
(
)
{
return
JsonResult
.
success
(
"获取时光纪详情成功"
,
this
.
atlTimeService
.
selectRandomAtlTime
());
}
}
src/main/java/com/hwstudio/antaile/controller/AtlWxController.java
View file @
c584e28e
...
...
@@ -7,6 +7,7 @@ import io.swagger.annotations.Api;
import
io.swagger.annotations.ApiOperation
;
import
io.swagger.annotations.ApiParam
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.*
;
/**
...
...
@@ -14,7 +15,7 @@ import org.springframework.web.bind.annotation.*;
* @Date 2021/5/17
* description:
*/
@
Rest
Controller
@Controller
@RequestMapping
(
value
=
"/wx"
)
@Api
(
tags
=
"用户相关接口"
)
@CrossOrigin
(
origins
=
"*"
,
maxAge
=
3600
)
...
...
@@ -25,18 +26,27 @@ public class AtlWxController extends BaseController{
@RequestMapping
(
value
=
"getQrcodeUrl"
,
method
=
RequestMethod
.
GET
)
@ApiOperation
(
"获取二维码链接地址"
)
@ResponseBody
public
JsonResult
getQrcodeUrl
()
{
return
this
.
atlWxService
.
getQrcodeUrl
();
}
@RequestMapping
(
value
=
"getQrcodeAndState"
,
method
=
RequestMethod
.
GET
)
@ApiOperation
(
"微信二维码回调地址"
)
@ResponseBody
public
JsonResult
getQrcodeAndState
(
@RequestParam
(
value
=
"code"
,
required
=
true
)
String
code
,
@RequestParam
(
value
=
"state"
,
required
=
true
)
String
state
)
{
return
this
.
atlWxService
.
getAccessToken
(
code
,
state
);
}
@RequestMapping
(
value
=
"getQrcodeAndState"
,
method
=
RequestMethod
.
POST
)
@RequestMapping
(
value
=
"returnQrcodeAndState"
,
method
=
RequestMethod
.
GET
)
@ApiOperation
(
"重定向:返回微信Code与state"
)
public
String
returnQrcodeAndState
(
@RequestParam
(
value
=
"code"
,
required
=
true
)
String
code
,
@RequestParam
(
value
=
"state"
,
required
=
true
)
String
state
)
{
return
"redirect:https://www.atl-life.com/#/bindPage?code="
+
code
+
"&state="
+
state
;
}
@RequestMapping
(
value
=
"insertAtlUserByWxLogin"
,
method
=
RequestMethod
.
POST
)
@ApiOperation
(
"新用户微信扫码登录,绑定手机号密码"
)
@ResponseBody
public
JsonResult
insertAtlUserByWxLogin
(
@ApiParam
(
value
=
"传入对象"
)
@RequestBody
WxInsertUserParam
wxInsertUserParam
)
{
return
this
.
atlWxService
.
insertAtlUserByWxLogin
(
wxInsertUserParam
);
}
...
...
src/main/java/com/hwstudio/antaile/controller/LoginController.java
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
controller
;
import
com.hwstudio.antaile.dto.LoginUserDto
;
import
com.hwstudio.antaile.dto.VerifyCodeLogin
;
import
com.hwstudio.antaile.service.AtlUserService
;
import
com.hwstudio.antaile.utils.JsonResult
;
import
com.hwstudio.antaile.utils.RedisUtil
;
...
...
@@ -8,6 +9,7 @@ import com.hwstudio.antaile.vo.LoginUserVo;
import
io.swagger.annotations.*
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.CrossOrigin
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
...
...
@@ -39,6 +41,14 @@ public class LoginController{
return
JsonResult
.
success
(
"请求成功"
,
loginUserDto
);
}
@RequestMapping
(
value
=
"/verifyCodeLogin"
)
@ApiOperation
(
value
=
"手机号验证码登录"
,
httpMethod
=
"POST"
)
@ApiResponses
(
@ApiResponse
(
code
=
200
,
message
=
"请求成功"
,
response
=
LoginUserDto
.
class
))
public
JsonResult
verifyCodeLogin
(
@ApiParam
(
value
=
"传入对象"
)
@RequestBody
VerifyCodeLogin
verifyCodeLogin
)
throws
Exception
{
return
atlUserService
.
verifyCodeLogin
(
verifyCodeLogin
);
}
@RequestMapping
(
value
=
"/appletLogin"
)
@ApiOperation
(
value
=
"小程序登录"
,
httpMethod
=
"POST"
,
notes
=
"手机号+密码登录,成功后返回token,在需要登录的接口头部加入此token"
,
response
=
JsonResult
.
class
)
@ApiResponses
(
@ApiResponse
(
code
=
200
,
message
=
"请求成功"
,
response
=
LoginUserDto
.
class
))
...
...
src/main/java/com/hwstudio/antaile/controller/RegisterController.java
View file @
c584e28e
...
...
@@ -42,7 +42,7 @@ public class RegisterController {
@ApiImplicitParam
(
name
=
"mobile"
,
value
=
"手机号"
,
required
=
true
,
dataType
=
"string"
,
paramType
=
"query"
),
@ApiImplicitParam
(
name
=
"pwd"
,
value
=
"密码"
,
required
=
true
,
dataType
=
"string"
,
paramType
=
"query"
),
@ApiImplicitParam
(
name
=
"verifyCode"
,
value
=
"验证码"
,
required
=
true
,
dataType
=
"string"
,
paramType
=
"query"
),
@ApiImplicitParam
(
name
=
"nickName"
,
value
=
"昵称"
,
required
=
tru
e
,
dataType
=
"string"
,
paramType
=
"query"
)
@ApiImplicitParam
(
name
=
"nickName"
,
value
=
"昵称"
,
required
=
fals
e
,
dataType
=
"string"
,
paramType
=
"query"
)
})
public
JsonResult
registerMobile
(
String
mobile
,
String
pwd
,
String
verifyCode
,
String
nickName
)
{
registerService
.
registerMobile
(
mobile
,
pwd
,
verifyCode
,
nickName
);
...
...
src/main/java/com/hwstudio/antaile/controller/SmsController.java
View file @
c584e28e
...
...
@@ -38,7 +38,7 @@ public class SmsController {
@ApiResponses
(
@ApiResponse
(
code
=
200
,
message
=
"请求成功"
,
response
=
JsonResult
.
class
))
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
"mobile"
,
value
=
"手机号"
,
required
=
true
,
dataType
=
"string"
,
paramType
=
"query"
),
@ApiImplicitParam
(
name
=
"type"
,
value
=
"类型:1:注册"
,
required
=
true
,
dataType
=
"int"
,
paramType
=
"query"
)
@ApiImplicitParam
(
name
=
"type"
,
value
=
"类型:1:注册
3:修改登录密码 4:绑定手机号 5:验证码登录
"
,
required
=
true
,
dataType
=
"int"
,
paramType
=
"query"
)
})
public
JsonResult
sendVerifyCode
(
String
mobile
,
Integer
type
)
{
smsService
.
sendVerifyCode
(
mobile
,
type
);
...
...
src/main/java/com/hwstudio/antaile/dto/LoginUserDto.java
View file @
c584e28e
...
...
@@ -39,4 +39,8 @@ public class LoginUserDto {
private
String
officeOpendId
;
private
String
appletOpenId
;
@ApiModelProperty
(
value
=
"网站应用openId"
)
private
String
webappOpenId
;
@ApiModelProperty
(
value
=
"微信unionid"
)
private
String
unionid
;
}
src/main/java/com/hwstudio/antaile/dto/OfficialWebsiteAtlTimeParam.java
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
dto
;
import
com.hwstudio.antaile.utils.Page
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
...
...
@@ -15,4 +16,6 @@ public class OfficialWebsiteAtlTimeParam implements Serializable {
@ApiModelProperty
(
value
=
"是否首页推荐 0-否 1-是"
)
private
Integer
isCommend
;
@ApiModelProperty
(
value
=
"分页对象,不传递不分页"
)
private
Page
page
;
}
src/main/java/com/hwstudio/antaile/dto/VerifyCodeLogin.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
dto
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* @Author xh
* @Date 2021/5/25
* description:
*/
@Data
public
class
VerifyCodeLogin
implements
Serializable
{
@ApiModelProperty
(
value
=
"手机号"
)
private
String
mobilePhone
;
@ApiModelProperty
(
value
=
"验证码"
)
private
String
verifyCode
;
}
src/main/java/com/hwstudio/antaile/entity/AtlUser.java
View file @
c584e28e
...
...
@@ -8,57 +8,62 @@ import java.util.Date;
@Data
public
class
AtlUser
implements
Serializable
{
@ApiModelProperty
(
value
=
"用户id"
)
private
Long
id
;
@ApiModelProperty
(
value
=
"昵称"
)
private
String
nickName
;
@ApiModelProperty
(
value
=
"真实姓名"
)
private
String
realName
;
@ApiModelProperty
(
value
=
"手机号"
)
private
String
mobilePhone
;
@ApiModelProperty
(
value
=
"登录密码"
)
private
String
loginPassword
;
@ApiModelProperty
(
value
=
"支付密码"
)
private
String
payPassword
;
@ApiModelProperty
(
value
=
"微信openId"
)
private
String
openId
;
@ApiModelProperty
(
value
=
"头像"
)
private
String
avaterImageUrl
;
@ApiModelProperty
(
value
=
"云空间使用次数"
)
private
Integer
cloudSpaceUsage
;
@ApiModelProperty
(
value
=
"备注"
)
private
String
remark
;
@ApiModelProperty
(
value
=
"创建人"
)
private
Integer
createBy
;
@ApiModelProperty
(
value
=
"创建时间"
)
private
String
createTime
;
@ApiModelProperty
(
value
=
"修改人"
)
private
Integer
updateBy
;
@ApiModelProperty
(
value
=
"修改时间"
)
private
String
updateTime
;
@ApiModelProperty
(
value
=
"状态 1-启用 2-禁用"
)
private
Integer
state
;
@ApiModelProperty
(
value
=
"性别 1-男 2-女"
)
private
Integer
sex
;
@ApiModelProperty
(
value
=
"生日"
)
private
Date
birthday
;
@ApiModelProperty
(
value
=
"1:公历 2:农历"
)
private
String
birthdayType
;
@ApiModelProperty
(
value
=
"个性签名"
)
private
String
signature
;
@ApiModelProperty
(
value
=
"最后登录时间"
)
private
Date
loginDate
;
@ApiModelProperty
(
value
=
"推送用户标识id"
)
private
String
clientId
;
@ApiModelProperty
(
value
=
"是否系统消息提醒 0:否 1:是"
)
private
String
isSysPush
;
@ApiModelProperty
(
value
=
"是否社交消息提醒 0:否 1:是"
)
private
String
isScPush
;
@ApiModelProperty
(
value
=
"是否提醒消息提醒 0:否 1:是"
)
private
String
isRemPush
;
@ApiModelProperty
(
value
=
"公众号openId"
)
private
String
officeOpenId
;
@ApiModelProperty
(
value
=
"微信accessToken"
)
private
String
accessToken
;
@ApiModelProperty
(
value
=
"小程序openId"
)
private
String
appletOpenId
;
@ApiModelProperty
(
value
=
"网站应用openId"
)
private
String
webappOpenId
;
@ApiModelProperty
(
value
=
"微信unionid"
)
private
String
unionid
;
}
\ No newline at end of file
src/main/java/com/hwstudio/antaile/mapper/AtlAdMapper.java
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
mapper
;
import
com.hwstudio.antaile.entity.AtlAd
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
import
java.util.Map
;
public
interface
AtlAdMapper
{
int
deleteByPrimaryKey
(
Long
id
);
int
insert
(
AtlAd
record
);
int
insertSelective
(
AtlAd
record
);
AtlAd
selectByPrimaryKey
(
Long
id
);
int
updateByPrimaryKeySelective
(
AtlAd
record
);
int
updateByPrimaryKey
(
AtlAd
record
);
List
<
Map
<
String
,
Object
>>
getShowAd
(
@Param
(
"type"
)
Integer
type
);
List
<
Map
<
String
,
Object
>>
getShowAd
(
@Param
(
"type"
)
Integer
type
);
}
\ No newline at end of file
src/main/java/com/hwstudio/antaile/mapper/AtlUserMapper.java
View file @
c584e28e
...
...
@@ -4,7 +4,6 @@ import com.hwstudio.antaile.dto.AtlUserInfoDto;
import
com.hwstudio.antaile.dto.AtlUserPhoneTypeDto
;
import
com.hwstudio.antaile.entity.AtlUser
;
import
com.hwstudio.antaile.entity.AtlUserPhoneType
;
import
com.hwstudio.antaile.vo.AtlUserPhoneTypeVo
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
...
...
@@ -17,13 +16,13 @@ public interface AtlUserMapper {
void
registerMobile
(
AtlUser
atlUser
);
AtlUserInfoDto
getUserInfo
(
@Param
(
"userId"
)
Long
userId
);
AtlUserInfoDto
getUserInfo
(
@Param
(
"userId"
)
Long
userId
);
void
updateUser
(
AtlUser
atlUser
);
void
updatePushStatus
(
AtlUser
atlUser
);
AtlUser
getAtlUserInfo
(
@Param
(
"userId"
)
Long
userId
);
AtlUser
getAtlUserInfo
(
@Param
(
"userId"
)
Long
userId
);
AtlUser
getByOpenId
(
@Param
(
"openId"
)
String
openId
);
...
...
@@ -31,6 +30,8 @@ public interface AtlUserMapper {
AtlUser
getByAppletOpenId
(
@Param
(
"appletOpenId"
)
String
appletOpenId
);
AtlUser
getByWebappOpenId
(
String
getByWebappOpenId
);
void
updatePwd
(
@Param
(
"pwd"
)
String
pwd
,
@Param
(
"userId"
)
Long
userId
);
void
insert
(
AtlUser
atlUser
);
...
...
@@ -55,5 +56,13 @@ public interface AtlUserMapper {
void
updatePhoneType
(
AtlUserPhoneType
atlUserPhoneType
);
Long
getCommentCount
(
@Param
(
"userId"
)
Long
userId
);
Long
getCommentCount
(
@Param
(
"userId"
)
Long
userId
);
/**
* 根据手机号 查询一条用户数据
*
* @param mobilePhone
* @return
*/
AtlUser
selectOneUserByMobilePhone
(
String
mobilePhone
);
}
\ No newline at end of file
src/main/java/com/hwstudio/antaile/service/AtlTimeService.java
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
service
;
import
com.github.pagehelper.PageHelper
;
import
com.github.pagehelper.PageInfo
;
import
com.github.pagehelper.util.StringUtil
;
import
com.google.common.base.Preconditions
;
import
com.google.common.collect.Lists
;
...
...
@@ -9,6 +10,7 @@ import com.hwstudio.antaile.dto.*;
import
com.hwstudio.antaile.entity.*
;
import
com.hwstudio.antaile.exception.BusinessException
;
import
com.hwstudio.antaile.mapper.*
;
import
com.hwstudio.antaile.utils.CommonPage
;
import
com.hwstudio.antaile.utils.JsonResult
;
import
com.hwstudio.antaile.vo.AtlFineVo
;
import
com.hwstudio.antaile.vo.AtlPrivateVo
;
...
...
@@ -23,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
import
javax.annotation.Resource
;
import
java.text.SimpleDateFormat
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* Created by LENOVO on 2019/5/27.
...
...
@@ -793,8 +796,22 @@ public class AtlTimeService {
*
* @return
*/
public
List
<
OfficialWebsiteAtlTimeVO
>
selectOfficialWebsiteAtlTime
(
OfficialWebsiteAtlTimeParam
officialWebsiteAtlTimeParam
)
{
return
this
.
atlTimeMapper
.
selectOfficialWebsiteAtlTime
(
officialWebsiteAtlTimeParam
);
public
CommonPage
<
OfficialWebsiteAtlTimeVO
>
selectOfficialWebsiteAtlTime
(
OfficialWebsiteAtlTimeParam
officialWebsiteAtlTimeParam
)
{
if
(
officialWebsiteAtlTimeParam
.
getPage
()
!=
null
&&
officialWebsiteAtlTimeParam
.
getPage
().
getPageNum
()
!=
null
&&
officialWebsiteAtlTimeParam
.
getPage
().
getPageSize
()
!=
null
)
{
PageHelper
.
startPage
(
officialWebsiteAtlTimeParam
.
getPage
().
getPageNum
(),
officialWebsiteAtlTimeParam
.
getPage
().
getPageSize
());
}
List
<
OfficialWebsiteAtlTimeVO
>
officialWebsiteAtlTimeVOList
=
this
.
atlTimeMapper
.
selectOfficialWebsiteAtlTime
(
officialWebsiteAtlTimeParam
);
//记录下 pagehelper第一次分页查询的 返回得总条数 等信息
PageInfo
<
OfficialWebsiteAtlTimeVO
>
pageInfo
=
new
PageInfo
<>(
officialWebsiteAtlTimeVOList
);
//因为进行了第二次查询 所以pageHelp得分页总数得到了变化 导致不准确 因此我们需要手动校准一下
CommonPage
<
OfficialWebsiteAtlTimeVO
>
result
=
new
CommonPage
<
OfficialWebsiteAtlTimeVO
>();
result
.
setTotalPage
(
pageInfo
.
getPages
());
result
.
setPageNum
(
pageInfo
.
getPageNum
());
result
.
setPageSize
(
pageInfo
.
getPageSize
());
result
.
setTotal
(
pageInfo
.
getTotal
());
result
.
setList
(
officialWebsiteAtlTimeVOList
);
return
result
;
}
/**
...
...
src/main/java/com/hwstudio/antaile/service/AtlUserService.java
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
service
;
import
com.github.binarywang.java.emoji.EmojiConverter
;
import
com.github.pagehelper.util.StringUtil
;
import
com.google.common.base.Preconditions
;
import
com.google.common.collect.Maps
;
import
com.google.gson.JsonObject
;
import
com.hwstudio.antaile.dto.AtlUserInfoDto
;
import
com.hwstudio.antaile.dto.AtlUserPhoneTypeDto
;
import
com.hwstudio.antaile.dto.BindingMobileDto
;
import
com.hwstudio.antaile.dto.LoginUserDto
;
import
com.hwstudio.antaile.dto.*
;
import
com.hwstudio.antaile.entity.*
;
import
com.hwstudio.antaile.exception.BusinessException
;
import
com.hwstudio.antaile.mapper.*
;
...
...
@@ -21,17 +16,12 @@ import com.hwstudio.antaile.vo.AtlUserPhoneTypeVo;
import
com.hwstudio.antaile.vo.AtlUserUpdateVo
;
import
com.hwstudio.antaile.vo.LoginUserVo
;
import
net.sf.json.JSONObject
;
import
net.sf.json.JsonConfig
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.omg.CORBA.PUBLIC_MEMBER
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.stereotype.Service
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
javax.annotation.Resource
;
import
java.rmi.MarshalledObject
;
import
java.text.ParsePosition
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.List
;
...
...
@@ -202,6 +192,34 @@ public class AtlUserService {
}
/**
* 验证码登录账号
*
* @param verifyCodeLogin
* @return
*/
public
JsonResult
verifyCodeLogin
(
VerifyCodeLogin
verifyCodeLogin
)
{
Sms
sms
=
smsMapper
.
getSmsVerifyCode
(
verifyCodeLogin
.
getMobilePhone
(),
verifyCodeLogin
.
getVerifyCode
(),
5
);
if
(
sms
==
null
)
{
throw
new
BusinessException
(
"验证码错误"
);
}
//校验手机号是否已经存在过
AtlUser
atlUser
=
this
.
atlUserMapper
.
selectOneUserByMobilePhone
(
verifyCodeLogin
.
getMobilePhone
());
if
(
atlUser
==
null
){
throw
new
BusinessException
(
"不存在此手机号"
);
}
//否则有查询到 就登录成功
LoginUserDto
loginUserDto
=
new
LoginUserDto
();
String
token
=
UUID
.
randomUUID
().
toString
();
redisUtil
.
set
(
token
,
atlUser
,
Long
.
valueOf
(
604800
));
loginUserDto
.
setToken
(
token
);
loginUserDto
.
setAvatarUrl
(
atlUser
.
getAvaterImageUrl
());
loginUserDto
.
setNickName
(
atlUser
.
getNickName
());
loginUserDto
.
setPhone
(
atlUser
.
getMobilePhone
());
loginUserDto
.
setOpenId
(
atlUser
.
getOpenId
());
return
JsonResult
.
success
(
"登录成功"
,
loginUserDto
);
}
/**
* 功能描述: <br>账号密码登录
* 〈〉
*
...
...
@@ -211,7 +229,7 @@ public class AtlUserService {
*/
public
JsonResult
appletLogin
(
LoginUserVo
loginUserVo
)
throws
Exception
{
LoginUserDto
loginUserDto
=
new
LoginUserDto
();
AtlUser
atlUser
;
AtlUser
atlUser
;
if
(
"1"
.
equals
(
loginUserVo
.
getIsApplet
()))
{
JSONObject
jsonObject
=
OpenIdUtil
.
oauth2GetAppletOpenId
(
loginUserVo
.
getWxCode
());
if
(
null
!=
jsonObject
.
get
(
"errcode"
))
{
...
...
@@ -224,7 +242,7 @@ public class AtlUserService {
String
mobile
=
atlUser
.
getMobilePhone
();
if
(
StringUtils
.
isNotBlank
(
mobile
))
{
String
sendToken
=
loginUserVo
.
getToken
();
if
(
StringUtils
.
isNotBlank
(
sendToken
))
{
if
(
StringUtils
.
isNotBlank
(
sendToken
))
{
Object
obj
=
redisUtil
.
get
(
sendToken
);
if
(
null
!=
obj
)
{
redisUtil
.
remove
(
sendToken
);
...
...
@@ -265,7 +283,7 @@ public class AtlUserService {
String
appletOpenId
=
atlUser
.
getAppletOpenId
();
if
(
StringUtils
.
isNotBlank
(
appletOpenId
))
{
String
sendToken
=
loginUserVo
.
getToken
();
if
(
StringUtils
.
isNotBlank
(
sendToken
))
{
if
(
StringUtils
.
isNotBlank
(
sendToken
))
{
Object
obj
=
redisUtil
.
get
(
sendToken
);
if
(
null
!=
obj
)
{
redisUtil
.
remove
(
sendToken
);
...
...
@@ -285,7 +303,7 @@ public class AtlUserService {
loginUserDto
.
setOpenId
(
appletOpenId
);
}
}
return
JsonResult
.
success
(
"登录成功"
,
loginUserDto
);
return
JsonResult
.
success
(
"登录成功"
,
loginUserDto
);
}
...
...
@@ -415,7 +433,7 @@ public class AtlUserService {
return
loginUserDto
;
}
public
JsonResult
bindingAppletMobile
(
BindingMobileDto
bindingMobileDto
,
LoginUserVo
loginUserVo
)
throws
Exception
{
public
JsonResult
bindingAppletMobile
(
BindingMobileDto
bindingMobileDto
,
LoginUserVo
loginUserVo
)
throws
Exception
{
String
appletOpenId
=
loginUserVo
.
getOpenId
();
if
(!
VerificationUtil
.
isMobile
(
bindingMobileDto
.
getMobile
()))
{
throw
new
BusinessException
(
"手机号无效"
);
...
...
@@ -457,7 +475,7 @@ public class AtlUserService {
loginUserDto
.
setNickName
(
atlUser
.
getNickName
());
loginUserDto
.
setPhone
(
atlUser
.
getMobilePhone
());
loginUserDto
.
setOpenId
(
appletOpenId
);
return
JsonResult
.
success
(
"绑定成功"
,
loginUserDto
);
return
JsonResult
.
success
(
"绑定成功"
,
loginUserDto
);
}
public
JsonResult
bindingOffice
(
LoginUserVo
loginUserVo
)
throws
Exception
{
...
...
src/main/java/com/hwstudio/antaile/service/AtlWxService.java
View file @
c584e28e
...
...
@@ -78,10 +78,10 @@ public class AtlWxService {
return
JsonResult
.
failed
(
"获取accessToken失败:"
,
dataMap
);
}
//返回了openid等信息 根据openid去查询 如果没有则去新增
AtlUser
atlUser
=
atlUserMapper
.
getByOpenId
(
openid
);
AtlUser
atlUser
=
atlUserMapper
.
getBy
Webapp
OpenId
(
openid
);
//如果是新用户 需要去绑定手机号 和 密码
if
(
atlUser
==
null
)
{
return
JsonResult
.
failed
(
""
,
dataMap
);
return
JsonResult
.
failed
(
"
未查询到网站应用openId相关数据,需要绑定手机号
"
,
dataMap
);
}
else
{
//否则有查询到 就登录成功
LoginUserDto
loginUserDto
=
new
LoginUserDto
();
...
...
@@ -91,7 +91,7 @@ public class AtlWxService {
loginUserDto
.
setAvatarUrl
(
atlUser
.
getAvaterImageUrl
());
loginUserDto
.
setNickName
(
atlUser
.
getNickName
());
loginUserDto
.
setPhone
(
atlUser
.
getMobilePhone
());
loginUserDto
.
setOpenId
(
atlUser
.
getOpenId
());
loginUserDto
.
set
Webapp
OpenId
(
atlUser
.
getOpenId
());
return
JsonResult
.
success
(
"登录成功"
,
loginUserDto
);
}
//{"success":true,"status":"200","message":"获取微信登录链接成功","data":"{\"openid\":\"onUQk6gm0ALTXFtddQrikfhmivR0\",\"nickname\":\"夏侯\",\"sex\":1,\"language\":\"zh_CN\",\"city\":\"Xiamen\",\"province\":\"Fujian\",\"country\":\"CN\",
...
...
@@ -118,16 +118,31 @@ public class AtlWxService {
if
(
openid2
==
null
||
openid2
.
isEmpty
())
{
return
JsonResult
.
failed
(
"获取用户信息失败:"
+
userMap
);
}
//向数据库写入会员信息
//需要判断是否存在手机号 存在则修改 不存在新增
AtlUser
atlUser
=
this
.
atlUserMapper
.
selectOneUserByMobilePhone
(
wxInsertUserParam
.
getMobilePhone
());
AtlUser
insertAtlUser
=
new
AtlUser
();
insertAtlUser
.
setNickName
(
userMap
.
get
(
"nickname"
)
+
""
);
insertAtlUser
.
setOpenId
(
userMap
.
get
(
"openid"
)
+
""
);
insertAtlUser
.
setAvaterImageUrl
(
userMap
.
get
(
"headimgurl"
)
+
""
);
insertAtlUser
.
setState
(
1
);
insertAtlUser
.
setSex
((
Integer
)
userMap
.
get
(
"sex"
));
insertAtlUser
.
setMobilePhone
(
wxInsertUserParam
.
getMobilePhone
());
insertAtlUser
.
setLoginPassword
(
DigestUtils
.
md5Hex
(
wxInsertUserParam
.
getLoginPassword
()));
this
.
atlUserMapper
.
insert
(
insertAtlUser
);
if
(
atlUser
!=
null
){
//修改操作
atlUser
.
setNickName
(
userMap
.
get
(
"nickname"
)
+
""
);
atlUser
.
setWebappOpenId
(
userMap
.
get
(
"openid"
)
+
""
);
atlUser
.
setAvaterImageUrl
(
userMap
.
get
(
"headimgurl"
)
+
""
);
atlUser
.
setState
(
1
);
atlUser
.
setSex
((
Integer
)
userMap
.
get
(
"sex"
));
atlUser
.
setMobilePhone
(
wxInsertUserParam
.
getMobilePhone
());
atlUser
.
setLoginPassword
(
DigestUtils
.
md5Hex
(
wxInsertUserParam
.
getLoginPassword
()));
this
.
atlUserMapper
.
updateUser
(
atlUser
);
}
else
{
//向数据库写入会员信息
insertAtlUser
.
setNickName
(
userMap
.
get
(
"nickname"
)
+
""
);
insertAtlUser
.
setWebappOpenId
(
userMap
.
get
(
"openid"
)
+
""
);
insertAtlUser
.
setAvaterImageUrl
(
userMap
.
get
(
"headimgurl"
)
+
""
);
insertAtlUser
.
setState
(
1
);
insertAtlUser
.
setSex
((
Integer
)
userMap
.
get
(
"sex"
));
insertAtlUser
.
setMobilePhone
(
wxInsertUserParam
.
getMobilePhone
());
insertAtlUser
.
setLoginPassword
(
DigestUtils
.
md5Hex
(
wxInsertUserParam
.
getLoginPassword
()));
this
.
atlUserMapper
.
insert
(
insertAtlUser
);
}
//返回对象数据
LoginUserDto
loginUserDto
=
new
LoginUserDto
();
String
token
=
UUID
.
randomUUID
().
toString
();
...
...
@@ -136,7 +151,7 @@ public class AtlWxService {
loginUserDto
.
setAvatarUrl
(
insertAtlUser
.
getAvaterImageUrl
());
loginUserDto
.
setNickName
(
insertAtlUser
.
getNickName
());
loginUserDto
.
setPhone
(
insertAtlUser
.
getMobilePhone
());
loginUserDto
.
setOpenId
(
insertAtlUser
.
getOpenId
());
loginUserDto
.
set
Webapp
OpenId
(
insertAtlUser
.
getOpenId
());
return
JsonResult
.
success
(
"绑定手机号登录成功"
,
loginUserDto
);
}
...
...
@@ -162,7 +177,7 @@ public class AtlWxService {
if
(
wxInsertUserParam
.
getVerifyCode
()
==
null
||
wxInsertUserParam
.
getVerifyCode
().
isEmpty
())
{
return
JsonResult
.
failed
(
"传入验证码为空"
);
}
else
{
Sms
sms
=
smsMapper
.
getSmsVerifyCode
(
wxInsertUserParam
.
getMobilePhone
(),
wxInsertUserParam
.
getVerifyCode
(),
1
);
Sms
sms
=
smsMapper
.
getSmsVerifyCode
(
wxInsertUserParam
.
getMobilePhone
(),
wxInsertUserParam
.
getVerifyCode
(),
5
);
if
(
sms
==
null
)
{
throw
new
BusinessException
(
"验证码错误"
);
}
...
...
src/main/java/com/hwstudio/antaile/service/SmsService.java
View file @
c584e28e
...
...
@@ -96,6 +96,12 @@ public class SmsService {
templateCode
=
Constants
.
SMS_TYPE_BINDINGMOBILE_VALUE_INTERNATIONAL
;
}
break
;
case
Constants
.
SMS_TYPE_MOBILELOGIN
:
templateCode
=
Constants
.
SMS_TYPE_MOBILELOGIN_VALUE
;
if
(
isMatch
==
false
){
templateCode
=
Constants
.
SMS_TYPE_MOBILELOGIN_VALUE_INTERNATIONAL
;
}
break
;
default
:
{
throw
new
BusinessException
(
"参数异常"
);
}
...
...
src/main/java/com/hwstudio/antaile/utils/CommonPage.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
;
import
com.github.pagehelper.PageInfo
;
import
org.springframework.data.domain.Page
;
import
java.util.List
;
/**
* 分页数据封装类
* Created by macro on 2019/4/19.
*/
public
class
CommonPage
<
T
>
{
private
Integer
pageNum
;
private
Integer
pageSize
;
private
Integer
totalPage
;
private
Long
total
;
private
List
<
T
>
list
;
/**
* 将PageHelper分页后的list转为分页信息
*/
public
static
<
T
>
CommonPage
<
T
>
restPage
(
List
<
T
>
list
)
{
CommonPage
<
T
>
result
=
new
CommonPage
<
T
>();
PageInfo
<
T
>
pageInfo
=
new
PageInfo
<
T
>(
list
);
result
.
setTotalPage
(
pageInfo
.
getPages
());
result
.
setPageNum
(
pageInfo
.
getPageNum
());
result
.
setPageSize
(
pageInfo
.
getPageSize
());
result
.
setTotal
(
pageInfo
.
getTotal
());
result
.
setList
(
pageInfo
.
getList
());
return
result
;
}
/**
* 将SpringData分页后的list转为分页信息
*/
public
static
<
T
>
CommonPage
<
T
>
restPage
(
Page
<
T
>
pageInfo
)
{
CommonPage
<
T
>
result
=
new
CommonPage
<
T
>();
result
.
setTotalPage
(
pageInfo
.
getTotalPages
());
result
.
setPageNum
(
pageInfo
.
getNumber
());
result
.
setPageSize
(
pageInfo
.
getSize
());
result
.
setTotal
(
pageInfo
.
getTotalElements
());
result
.
setList
(
pageInfo
.
getContent
());
return
result
;
}
public
Integer
getPageNum
()
{
return
pageNum
;
}
public
void
setPageNum
(
Integer
pageNum
)
{
this
.
pageNum
=
pageNum
;
}
public
Integer
getPageSize
()
{
return
pageSize
;
}
public
void
setPageSize
(
Integer
pageSize
)
{
this
.
pageSize
=
pageSize
;
}
public
Integer
getTotalPage
()
{
return
totalPage
;
}
public
void
setTotalPage
(
Integer
totalPage
)
{
this
.
totalPage
=
totalPage
;
}
public
List
<
T
>
getList
()
{
return
list
;
}
public
void
setList
(
List
<
T
>
list
)
{
this
.
list
=
list
;
}
public
Long
getTotal
()
{
return
total
;
}
public
void
setTotal
(
Long
total
)
{
this
.
total
=
total
;
}
}
src/main/java/com/hwstudio/antaile/utils/Page.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
/**
* @author chenwf
* @date 2020/4/2
*/
@Data
public
class
Page
{
@ApiModelProperty
(
"页码"
)
private
Integer
pageNum
;
@ApiModelProperty
(
"页数"
)
private
Integer
pageSize
;
public
Page
()
{
}
public
Page
(
Integer
pageNum
,
Integer
pageSize
)
{
this
.
pageNum
=
pageNum
;
this
.
pageSize
=
pageSize
;
}
}
src/main/java/com/hwstudio/antaile/utils/wx/IWXPayDomain.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
.
wx
;
/**
* 域名管理,实现主备域名自动切换
*/
public
abstract
interface
IWXPayDomain
{
/**
* 上报域名网络状况
* @param domain 域名。 比如:api.mch.weixin.qq.com
* @param elapsedTimeMillis 耗时
* @param ex 网络请求中出现的异常。
* null表示没有异常
* ConnectTimeoutException,表示建立网络连接异常
* UnknownHostException, 表示dns解析异常
*/
abstract
void
report
(
final
String
domain
,
long
elapsedTimeMillis
,
final
Exception
ex
);
/**
* 获取域名
* @param config 配置
* @return 域名
*/
abstract
DomainInfo
getDomain
(
final
WXPayConfig
config
);
static
class
DomainInfo
{
public
String
domain
;
//域名
public
boolean
primaryDomain
;
//该域名是否为主域名。例如:api.mch.weixin.qq.com为主域名
public
DomainInfo
(
String
domain
,
boolean
primaryDomain
)
{
this
.
domain
=
domain
;
this
.
primaryDomain
=
primaryDomain
;
}
@Override
public
String
toString
()
{
return
"DomainInfo{"
+
"domain='"
+
domain
+
'\''
+
", primaryDomain="
+
primaryDomain
+
'}'
;
}
}
}
\ No newline at end of file
src/main/java/com/hwstudio/antaile/utils/wx/WXPay.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
.
wx
;
import
com.github.wxpay.sdk.WXPayConstants.SignType
;
import
java.util.HashMap
;
import
java.util.Map
;
public
class
WXPay
{
private
WXPayConfig
config
;
private
SignType
signType
;
private
boolean
autoReport
;
private
boolean
useSandbox
;
private
String
notifyUrl
;
private
WXPayRequest
wxPayRequest
;
public
WXPay
(
final
WXPayConfig
config
)
throws
Exception
{
this
(
config
,
null
,
true
,
false
);
}
public
WXPay
(
final
WXPayConfig
config
,
final
boolean
autoReport
)
throws
Exception
{
this
(
config
,
null
,
autoReport
,
false
);
}
public
WXPay
(
final
WXPayConfig
config
,
final
boolean
autoReport
,
final
boolean
useSandbox
)
throws
Exception
{
this
(
config
,
null
,
autoReport
,
useSandbox
);
}
public
WXPay
(
final
WXPayConfig
config
,
final
String
notifyUrl
)
throws
Exception
{
this
(
config
,
notifyUrl
,
true
,
false
);
}
public
WXPay
(
final
WXPayConfig
config
,
final
String
notifyUrl
,
final
boolean
autoReport
)
throws
Exception
{
this
(
config
,
notifyUrl
,
autoReport
,
false
);
}
public
WXPay
(
final
WXPayConfig
config
,
final
String
notifyUrl
,
final
boolean
autoReport
,
final
boolean
useSandbox
)
throws
Exception
{
this
.
config
=
config
;
this
.
notifyUrl
=
notifyUrl
;
this
.
autoReport
=
autoReport
;
this
.
useSandbox
=
useSandbox
;
if
(
useSandbox
)
{
this
.
signType
=
SignType
.
MD5
;
// 沙箱环境
}
else
{
this
.
signType
=
SignType
.
HMACSHA256
;
}
this
.
wxPayRequest
=
new
WXPayRequest
(
config
);
}
private
void
checkWXPayConfig
()
throws
Exception
{
if
(
this
.
config
==
null
)
{
throw
new
Exception
(
"config is null"
);
}
if
(
this
.
config
.
getAppID
()
==
null
||
this
.
config
.
getAppID
().
trim
().
length
()
==
0
)
{
throw
new
Exception
(
"appid in config is empty"
);
}
if
(
this
.
config
.
getMchID
()
==
null
||
this
.
config
.
getMchID
().
trim
().
length
()
==
0
)
{
throw
new
Exception
(
"appid in config is empty"
);
}
if
(
this
.
config
.
getCertStream
()
==
null
)
{
throw
new
Exception
(
"cert stream in config is empty"
);
}
if
(
this
.
config
.
getWXPayDomain
()
==
null
){
throw
new
Exception
(
"config.getWXPayDomain() is null"
);
}
if
(
this
.
config
.
getHttpConnectTimeoutMs
()
<
10
)
{
throw
new
Exception
(
"http connect timeout is too small"
);
}
if
(
this
.
config
.
getHttpReadTimeoutMs
()
<
10
)
{
throw
new
Exception
(
"http read timeout is too small"
);
}
}
/**
* 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign <br>
* 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口
*
* @param reqData
* @return
* @throws Exception
*/
public
Map
<
String
,
String
>
fillRequestData
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
reqData
.
put
(
"appid"
,
config
.
getAppID
());
reqData
.
put
(
"mch_id"
,
config
.
getMchID
());
reqData
.
put
(
"nonce_str"
,
WXPayUtil
.
generateNonceStr
());
if
(
SignType
.
MD5
.
equals
(
this
.
signType
))
{
reqData
.
put
(
"sign_type"
,
WXPayConstants
.
MD5
);
}
else
if
(
SignType
.
HMACSHA256
.
equals
(
this
.
signType
))
{
reqData
.
put
(
"sign_type"
,
WXPayConstants
.
HMACSHA256
);
}
reqData
.
put
(
"sign"
,
WXPayUtil
.
generateSignature
(
reqData
,
config
.
getKey
(),
this
.
signType
));
return
reqData
;
}
/**
* 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。
*
* @param reqData 向wxpay post的请求数据
* @return 签名是否有效
* @throws Exception
*/
public
boolean
isResponseSignatureValid
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
// 返回数据的签名方式和请求中给定的签名方式是一致的
return
WXPayUtil
.
isSignatureValid
(
reqData
,
this
.
config
.
getKey
(),
this
.
signType
);
}
/**
* 判断支付结果通知中的sign是否有效
*
* @param reqData 向wxpay post的请求数据
* @return 签名是否有效
* @throws Exception
*/
public
boolean
isPayResultNotifySignatureValid
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
String
signTypeInData
=
reqData
.
get
(
WXPayConstants
.
FIELD_SIGN_TYPE
);
SignType
signType
;
if
(
signTypeInData
==
null
)
{
signType
=
SignType
.
MD5
;
}
else
{
signTypeInData
=
signTypeInData
.
trim
();
if
(
signTypeInData
.
length
()
==
0
)
{
signType
=
SignType
.
MD5
;
}
else
if
(
WXPayConstants
.
MD5
.
equals
(
signTypeInData
))
{
signType
=
SignType
.
MD5
;
}
else
if
(
WXPayConstants
.
HMACSHA256
.
equals
(
signTypeInData
))
{
signType
=
SignType
.
HMACSHA256
;
}
else
{
throw
new
Exception
(
String
.
format
(
"Unsupported sign_type: %s"
,
signTypeInData
));
}
}
return
WXPayUtil
.
isSignatureValid
(
reqData
,
this
.
config
.
getKey
(),
signType
);
}
/**
* 不需要证书的请求
* @param urlSuffix String
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 超时时间,单位是毫秒
* @param readTimeoutMs 超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
String
requestWithoutCert
(
String
urlSuffix
,
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
msgUUID
=
reqData
.
get
(
"nonce_str"
);
String
reqBody
=
WXPayUtil
.
mapToXml
(
reqData
);
String
resp
=
this
.
wxPayRequest
.
requestWithoutCert
(
urlSuffix
,
msgUUID
,
reqBody
,
connectTimeoutMs
,
readTimeoutMs
,
autoReport
);
return
resp
;
}
/**
* 需要证书的请求
* @param urlSuffix String
* @param reqData 向wxpay post的请求数据 Map
* @param connectTimeoutMs 超时时间,单位是毫秒
* @param readTimeoutMs 超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
String
requestWithCert
(
String
urlSuffix
,
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
msgUUID
=
reqData
.
get
(
"nonce_str"
);
String
reqBody
=
WXPayUtil
.
mapToXml
(
reqData
);
String
resp
=
this
.
wxPayRequest
.
requestWithCert
(
urlSuffix
,
msgUUID
,
reqBody
,
connectTimeoutMs
,
readTimeoutMs
,
this
.
autoReport
);
return
resp
;
}
/**
* 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。
* @param xmlStr API返回的XML格式数据
* @return Map类型数据
* @throws Exception
*/
public
Map
<
String
,
String
>
processResponseXml
(
String
xmlStr
)
throws
Exception
{
String
RETURN_CODE
=
"return_code"
;
String
return_code
;
Map
<
String
,
String
>
respData
=
WXPayUtil
.
xmlToMap
(
xmlStr
);
if
(
respData
.
containsKey
(
RETURN_CODE
))
{
return_code
=
respData
.
get
(
RETURN_CODE
);
}
else
{
throw
new
Exception
(
String
.
format
(
"No `return_code` in XML: %s"
,
xmlStr
));
}
if
(
return_code
.
equals
(
WXPayConstants
.
FAIL
))
{
return
respData
;
}
else
if
(
return_code
.
equals
(
WXPayConstants
.
SUCCESS
))
{
if
(
this
.
isResponseSignatureValid
(
respData
))
{
return
respData
;
}
else
{
throw
new
Exception
(
String
.
format
(
"Invalid sign value in XML: %s"
,
xmlStr
));
}
}
else
{
throw
new
Exception
(
String
.
format
(
"return_code value %s is invalid in XML: %s"
,
return_code
,
xmlStr
));
}
}
/**
* 作用:提交刷卡支付<br>
* 场景:刷卡支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
microPay
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
microPay
(
reqData
,
this
.
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:提交刷卡支付<br>
* 场景:刷卡支付
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
microPay
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_MICROPAY_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
MICROPAY_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
/**
* 提交刷卡支付,针对软POS,尽可能做成功
* 内置重试机制,最多60s
* @param reqData
* @return
* @throws Exception
*/
public
Map
<
String
,
String
>
microPayWithPos
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
microPayWithPos
(
reqData
,
this
.
config
.
getHttpConnectTimeoutMs
());
}
/**
* 提交刷卡支付,针对软POS,尽可能做成功
* 内置重试机制,最多60s
* @param reqData
* @param connectTimeoutMs
* @return
* @throws Exception
*/
public
Map
<
String
,
String
>
microPayWithPos
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
)
throws
Exception
{
int
remainingTimeMs
=
60
*
1000
;
long
startTimestampMs
=
0
;
Map
<
String
,
String
>
lastResult
=
null
;
Exception
lastException
=
null
;
while
(
true
)
{
startTimestampMs
=
WXPayUtil
.
getCurrentTimestampMs
();
int
readTimeoutMs
=
remainingTimeMs
-
connectTimeoutMs
;
if
(
readTimeoutMs
>
1000
)
{
try
{
lastResult
=
this
.
microPay
(
reqData
,
connectTimeoutMs
,
readTimeoutMs
);
String
returnCode
=
lastResult
.
get
(
"return_code"
);
if
(
returnCode
.
equals
(
"SUCCESS"
))
{
String
resultCode
=
lastResult
.
get
(
"result_code"
);
String
errCode
=
lastResult
.
get
(
"err_code"
);
if
(
resultCode
.
equals
(
"SUCCESS"
))
{
break
;
}
else
{
// 看错误码,若支付结果未知,则重试提交刷卡支付
if
(
errCode
.
equals
(
"SYSTEMERROR"
)
||
errCode
.
equals
(
"BANKERROR"
)
||
errCode
.
equals
(
"USERPAYING"
))
{
remainingTimeMs
=
remainingTimeMs
-
(
int
)(
WXPayUtil
.
getCurrentTimestampMs
()
-
startTimestampMs
);
if
(
remainingTimeMs
<=
100
)
{
break
;
}
else
{
WXPayUtil
.
getLogger
().
info
(
"microPayWithPos: try micropay again"
);
if
(
remainingTimeMs
>
5
*
1000
)
{
Thread
.
sleep
(
5
*
1000
);
}
else
{
Thread
.
sleep
(
1
*
1000
);
}
continue
;
}
}
else
{
break
;
}
}
}
else
{
break
;
}
}
catch
(
Exception
ex
)
{
lastResult
=
null
;
lastException
=
ex
;
}
}
else
{
break
;
}
}
if
(
lastResult
==
null
)
{
throw
lastException
;
}
else
{
return
lastResult
;
}
}
/**
* 作用:统一下单<br>
* 场景:公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
unifiedOrder
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
unifiedOrder
(
reqData
,
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:统一下单<br>
* 场景:公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
unifiedOrder
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_UNIFIEDORDER_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
UNIFIEDORDER_URL_SUFFIX
;
}
if
(
this
.
notifyUrl
!=
null
)
{
reqData
.
put
(
"notify_url"
,
this
.
notifyUrl
);
}
String
respXml
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
/**
* 作用:查询订单<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
orderQuery
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
orderQuery
(
reqData
,
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:查询订单<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据 int
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
orderQuery
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_ORDERQUERY_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
ORDERQUERY_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
/**
* 作用:撤销订单<br>
* 场景:刷卡支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
reverse
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
reverse
(
reqData
,
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:撤销订单<br>
* 场景:刷卡支付<br>
* 其他:需要证书
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
reverse
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_REVERSE_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
REVERSE_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
/**
* 作用:关闭订单<br>
* 场景:公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
closeOrder
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
closeOrder
(
reqData
,
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:关闭订单<br>
* 场景:公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
closeOrder
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_CLOSEORDER_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
CLOSEORDER_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
/**
* 作用:申请退款<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
refund
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
refund
(
reqData
,
this
.
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:申请退款<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付<br>
* 其他:需要证书
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
refund
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_REFUND_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
REFUND_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
/**
* 作用:退款查询<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
refundQuery
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
refundQuery
(
reqData
,
this
.
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:退款查询<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
refundQuery
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_REFUNDQUERY_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
REFUNDQUERY_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
/**
* 作用:对账单下载(成功时返回对账单数据,失败时返回XML格式数据)<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
downloadBill
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
downloadBill
(
reqData
,
this
.
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:对账单下载<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付<br>
* 其他:无论是否成功都返回Map。若成功,返回的Map中含有return_code、return_msg、data,
* 其中return_code为`SUCCESS`,data为对账单数据。
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return 经过封装的API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
downloadBill
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_DOWNLOADBILL_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
DOWNLOADBILL_URL_SUFFIX
;
}
String
respStr
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
).
trim
();
Map
<
String
,
String
>
ret
;
// 出现错误,返回XML数据
if
(
respStr
.
indexOf
(
"<"
)
==
0
)
{
ret
=
WXPayUtil
.
xmlToMap
(
respStr
);
}
else
{
// 正常返回csv数据
ret
=
new
HashMap
<
String
,
String
>();
ret
.
put
(
"return_code"
,
WXPayConstants
.
SUCCESS
);
ret
.
put
(
"return_msg"
,
"ok"
);
ret
.
put
(
"data"
,
respStr
);
}
return
ret
;
}
/**
* 作用:交易保障<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
report
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
report
(
reqData
,
this
.
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:交易保障<br>
* 场景:刷卡支付、公共号支付、扫码支付、APP支付
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
report
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_REPORT_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
REPORT_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
WXPayUtil
.
xmlToMap
(
respXml
);
}
/**
* 作用:转换短链接<br>
* 场景:刷卡支付、扫码支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
shortUrl
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
shortUrl
(
reqData
,
this
.
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:转换短链接<br>
* 场景:刷卡支付、扫码支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
shortUrl
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_SHORTURL_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
SHORTURL_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
/**
* 作用:授权码查询OPENID接口<br>
* 场景:刷卡支付
* @param reqData 向wxpay post的请求数据
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
authCodeToOpenid
(
Map
<
String
,
String
>
reqData
)
throws
Exception
{
return
this
.
authCodeToOpenid
(
reqData
,
this
.
config
.
getHttpConnectTimeoutMs
(),
this
.
config
.
getHttpReadTimeoutMs
());
}
/**
* 作用:授权码查询OPENID接口<br>
* 场景:刷卡支付
* @param reqData 向wxpay post的请求数据
* @param connectTimeoutMs 连接超时时间,单位是毫秒
* @param readTimeoutMs 读超时时间,单位是毫秒
* @return API返回数据
* @throws Exception
*/
public
Map
<
String
,
String
>
authCodeToOpenid
(
Map
<
String
,
String
>
reqData
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
String
url
;
if
(
this
.
useSandbox
)
{
url
=
WXPayConstants
.
SANDBOX_AUTHCODETOOPENID_URL_SUFFIX
;
}
else
{
url
=
WXPayConstants
.
AUTHCODETOOPENID_URL_SUFFIX
;
}
String
respXml
=
this
.
requestWithoutCert
(
url
,
this
.
fillRequestData
(
reqData
),
connectTimeoutMs
,
readTimeoutMs
);
return
this
.
processResponseXml
(
respXml
);
}
}
// end class
src/main/java/com/hwstudio/antaile/utils/wx/WXPayConfig.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
.
wx
;
import
java.io.InputStream
;
public
abstract
class
WXPayConfig
{
/**
* 获取 App ID
*
* @return App ID
*/
abstract
String
getAppID
();
/**
* 获取 Mch ID
*
* @return Mch ID
*/
abstract
String
getMchID
();
/**
* 获取 API 密钥
*
* @return API密钥
*/
abstract
String
getKey
();
/**
* 获取商户证书内容
*
* @return 商户证书内容
*/
abstract
InputStream
getCertStream
();
/**
* HTTP(S) 连接超时时间,单位毫秒
*
* @return
*/
public
int
getHttpConnectTimeoutMs
()
{
return
6
*
1000
;
}
/**
* HTTP(S) 读数据超时时间,单位毫秒
*
* @return
*/
public
int
getHttpReadTimeoutMs
()
{
return
8
*
1000
;
}
/**
* 获取WXPayDomain, 用于多域名容灾自动切换
* @return
*/
abstract
IWXPayDomain
getWXPayDomain
();
/**
* 是否自动上报。
* 若要关闭自动上报,子类中实现该函数返回 false 即可。
*
* @return
*/
public
boolean
shouldAutoReport
()
{
return
true
;
}
/**
* 进行健康上报的线程的数量
*
* @return
*/
public
int
getReportWorkerNum
()
{
return
6
;
}
/**
* 健康上报缓存消息的最大数量。会有线程去独立上报
* 粗略计算:加入一条消息200B,10000消息占用空间 2000 KB,约为2MB,可以接受
*
* @return
*/
public
int
getReportQueueMaxSize
()
{
return
10000
;
}
/**
* 批量上报,一次最多上报多个数据
*
* @return
*/
public
int
getReportBatchSize
()
{
return
10
;
}
}
src/main/java/com/hwstudio/antaile/utils/wx/WXPayConstants.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
.
wx
;
import
org.apache.http.client.HttpClient
;
/**
* 常量
*/
public
class
WXPayConstants
{
public
enum
SignType
{
MD5
,
HMACSHA256
}
public
static
final
String
DOMAIN_API
=
"api.mch.weixin.qq.com"
;
public
static
final
String
DOMAIN_API2
=
"api2.mch.weixin.qq.com"
;
public
static
final
String
DOMAIN_APIHK
=
"apihk.mch.weixin.qq.com"
;
public
static
final
String
DOMAIN_APIUS
=
"apius.mch.weixin.qq.com"
;
public
static
final
String
FAIL
=
"FAIL"
;
public
static
final
String
SUCCESS
=
"SUCCESS"
;
public
static
final
String
HMACSHA256
=
"HMAC-SHA256"
;
public
static
final
String
MD5
=
"MD5"
;
public
static
final
String
FIELD_SIGN
=
"sign"
;
public
static
final
String
FIELD_SIGN_TYPE
=
"sign_type"
;
public
static
final
String
WXPAYSDK_VERSION
=
"WXPaySDK/3.0.9"
;
public
static
final
String
USER_AGENT
=
WXPAYSDK_VERSION
+
" ("
+
System
.
getProperty
(
"os.arch"
)
+
" "
+
System
.
getProperty
(
"os.name"
)
+
" "
+
System
.
getProperty
(
"os.version"
)
+
") Java/"
+
System
.
getProperty
(
"java.version"
)
+
" HttpClient/"
+
HttpClient
.
class
.
getPackage
().
getImplementationVersion
();
public
static
final
String
MICROPAY_URL_SUFFIX
=
"/pay/micropay"
;
public
static
final
String
UNIFIEDORDER_URL_SUFFIX
=
"/pay/unifiedorder"
;
public
static
final
String
ORDERQUERY_URL_SUFFIX
=
"/pay/orderquery"
;
public
static
final
String
REVERSE_URL_SUFFIX
=
"/secapi/pay/reverse"
;
public
static
final
String
CLOSEORDER_URL_SUFFIX
=
"/pay/closeorder"
;
public
static
final
String
REFUND_URL_SUFFIX
=
"/secapi/pay/refund"
;
public
static
final
String
REFUNDQUERY_URL_SUFFIX
=
"/pay/refundquery"
;
public
static
final
String
DOWNLOADBILL_URL_SUFFIX
=
"/pay/downloadbill"
;
public
static
final
String
REPORT_URL_SUFFIX
=
"/payitil/report"
;
public
static
final
String
SHORTURL_URL_SUFFIX
=
"/tools/shorturl"
;
public
static
final
String
AUTHCODETOOPENID_URL_SUFFIX
=
"/tools/authcodetoopenid"
;
// sandbox
public
static
final
String
SANDBOX_MICROPAY_URL_SUFFIX
=
"/sandboxnew/pay/micropay"
;
public
static
final
String
SANDBOX_UNIFIEDORDER_URL_SUFFIX
=
"/sandboxnew/pay/unifiedorder"
;
public
static
final
String
SANDBOX_ORDERQUERY_URL_SUFFIX
=
"/sandboxnew/pay/orderquery"
;
public
static
final
String
SANDBOX_REVERSE_URL_SUFFIX
=
"/sandboxnew/secapi/pay/reverse"
;
public
static
final
String
SANDBOX_CLOSEORDER_URL_SUFFIX
=
"/sandboxnew/pay/closeorder"
;
public
static
final
String
SANDBOX_REFUND_URL_SUFFIX
=
"/sandboxnew/secapi/pay/refund"
;
public
static
final
String
SANDBOX_REFUNDQUERY_URL_SUFFIX
=
"/sandboxnew/pay/refundquery"
;
public
static
final
String
SANDBOX_DOWNLOADBILL_URL_SUFFIX
=
"/sandboxnew/pay/downloadbill"
;
public
static
final
String
SANDBOX_REPORT_URL_SUFFIX
=
"/sandboxnew/payitil/report"
;
public
static
final
String
SANDBOX_SHORTURL_URL_SUFFIX
=
"/sandboxnew/tools/shorturl"
;
public
static
final
String
SANDBOX_AUTHCODETOOPENID_URL_SUFFIX
=
"/sandboxnew/tools/authcodetoopenid"
;
}
src/main/java/com/hwstudio/antaile/utils/wx/WXPayReport.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
.
wx
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.client.HttpClient
;
import
org.apache.http.client.config.RequestConfig
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.config.RegistryBuilder
;
import
org.apache.http.conn.socket.ConnectionSocketFactory
;
import
org.apache.http.conn.socket.PlainConnectionSocketFactory
;
import
org.apache.http.conn.ssl.SSLConnectionSocketFactory
;
import
org.apache.http.entity.StringEntity
;
import
org.apache.http.impl.client.HttpClientBuilder
;
import
org.apache.http.impl.conn.BasicHttpClientConnectionManager
;
import
org.apache.http.util.EntityUtils
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.LinkedBlockingQueue
;
import
java.util.concurrent.ThreadFactory
;
/**
* 交易保障
*/
public
class
WXPayReport
{
public
static
class
ReportInfo
{
/**
* 布尔变量使用int。0为false, 1为true。
*/
// 基本信息
private
String
version
=
"v1"
;
private
String
sdk
=
WXPayConstants
.
WXPAYSDK_VERSION
;
private
String
uuid
;
// 交易的标识
private
long
timestamp
;
// 上报时的时间戳,单位秒
private
long
elapsedTimeMillis
;
// 耗时,单位 毫秒
// 针对主域名
private
String
firstDomain
;
// 第1次请求的域名
private
boolean
primaryDomain
;
//是否主域名
private
int
firstConnectTimeoutMillis
;
// 第1次请求设置的连接超时时间,单位 毫秒
private
int
firstReadTimeoutMillis
;
// 第1次请求设置的读写超时时间,单位 毫秒
private
int
firstHasDnsError
;
// 第1次请求是否出现dns问题
private
int
firstHasConnectTimeout
;
// 第1次请求是否出现连接超时
private
int
firstHasReadTimeout
;
// 第1次请求是否出现连接超时
public
ReportInfo
(
String
uuid
,
long
timestamp
,
long
elapsedTimeMillis
,
String
firstDomain
,
boolean
primaryDomain
,
int
firstConnectTimeoutMillis
,
int
firstReadTimeoutMillis
,
boolean
firstHasDnsError
,
boolean
firstHasConnectTimeout
,
boolean
firstHasReadTimeout
)
{
this
.
uuid
=
uuid
;
this
.
timestamp
=
timestamp
;
this
.
elapsedTimeMillis
=
elapsedTimeMillis
;
this
.
firstDomain
=
firstDomain
;
this
.
primaryDomain
=
primaryDomain
;
this
.
firstConnectTimeoutMillis
=
firstConnectTimeoutMillis
;
this
.
firstReadTimeoutMillis
=
firstReadTimeoutMillis
;
this
.
firstHasDnsError
=
firstHasDnsError
?
1
:
0
;
this
.
firstHasConnectTimeout
=
firstHasConnectTimeout
?
1
:
0
;
this
.
firstHasReadTimeout
=
firstHasReadTimeout
?
1
:
0
;
}
@Override
public
String
toString
()
{
return
"ReportInfo{"
+
"version='"
+
version
+
'\''
+
", sdk='"
+
sdk
+
'\''
+
", uuid='"
+
uuid
+
'\''
+
", timestamp="
+
timestamp
+
", elapsedTimeMillis="
+
elapsedTimeMillis
+
", firstDomain='"
+
firstDomain
+
'\''
+
", primaryDomain="
+
primaryDomain
+
", firstConnectTimeoutMillis="
+
firstConnectTimeoutMillis
+
", firstReadTimeoutMillis="
+
firstReadTimeoutMillis
+
", firstHasDnsError="
+
firstHasDnsError
+
", firstHasConnectTimeout="
+
firstHasConnectTimeout
+
", firstHasReadTimeout="
+
firstHasReadTimeout
+
'}'
;
}
/**
* 转换成 csv 格式
*
* @return
*/
public
String
toLineString
(
String
key
)
{
String
separator
=
","
;
Object
[]
objects
=
new
Object
[]
{
version
,
sdk
,
uuid
,
timestamp
,
elapsedTimeMillis
,
firstDomain
,
primaryDomain
,
firstConnectTimeoutMillis
,
firstReadTimeoutMillis
,
firstHasDnsError
,
firstHasConnectTimeout
,
firstHasReadTimeout
};
StringBuffer
sb
=
new
StringBuffer
();
for
(
Object
obj:
objects
)
{
sb
.
append
(
obj
).
append
(
separator
);
}
try
{
String
sign
=
WXPayUtil
.
HMACSHA256
(
sb
.
toString
(),
key
);
sb
.
append
(
sign
);
return
sb
.
toString
();
}
catch
(
Exception
ex
)
{
return
null
;
}
}
}
private
static
final
String
REPORT_URL
=
"http://report.mch.weixin.qq.com/wxpay/report/default"
;
// private static final String REPORT_URL = "http://127.0.0.1:5000/test";
private
static
final
int
DEFAULT_CONNECT_TIMEOUT_MS
=
6
*
1000
;
private
static
final
int
DEFAULT_READ_TIMEOUT_MS
=
8
*
1000
;
private
LinkedBlockingQueue
<
String
>
reportMsgQueue
=
null
;
private
WXPayConfig
config
;
private
ExecutorService
executorService
;
private
volatile
static
WXPayReport
INSTANCE
;
private
WXPayReport
(
final
WXPayConfig
config
)
{
this
.
config
=
config
;
reportMsgQueue
=
new
LinkedBlockingQueue
<
String
>(
config
.
getReportQueueMaxSize
());
// 添加处理线程
executorService
=
Executors
.
newFixedThreadPool
(
config
.
getReportWorkerNum
(),
new
ThreadFactory
()
{
public
Thread
newThread
(
Runnable
r
)
{
Thread
t
=
Executors
.
defaultThreadFactory
().
newThread
(
r
);
t
.
setDaemon
(
true
);
return
t
;
}
});
if
(
config
.
shouldAutoReport
())
{
WXPayUtil
.
getLogger
().
info
(
"report worker num: {}"
,
config
.
getReportWorkerNum
());
for
(
int
i
=
0
;
i
<
config
.
getReportWorkerNum
();
++
i
)
{
executorService
.
execute
(
new
Runnable
()
{
public
void
run
()
{
while
(
true
)
{
// 先用 take 获取数据
try
{
StringBuffer
sb
=
new
StringBuffer
();
String
firstMsg
=
reportMsgQueue
.
take
();
WXPayUtil
.
getLogger
().
info
(
"get first report msg: {}"
,
firstMsg
);
String
msg
=
null
;
sb
.
append
(
firstMsg
);
//会阻塞至有消息
int
remainNum
=
config
.
getReportBatchSize
()
-
1
;
for
(
int
j
=
0
;
j
<
remainNum
;
++
j
)
{
WXPayUtil
.
getLogger
().
info
(
"try get remain report msg"
);
// msg = reportMsgQueue.poll(); // 不阻塞了
msg
=
reportMsgQueue
.
take
();
WXPayUtil
.
getLogger
().
info
(
"get remain report msg: {}"
,
msg
);
if
(
msg
==
null
)
{
break
;
}
else
{
sb
.
append
(
"\n"
);
sb
.
append
(
msg
);
}
}
// 上报
WXPayReport
.
httpRequest
(
sb
.
toString
(),
DEFAULT_CONNECT_TIMEOUT_MS
,
DEFAULT_READ_TIMEOUT_MS
);
}
catch
(
Exception
ex
)
{
WXPayUtil
.
getLogger
().
warn
(
"report fail. reason: {}"
,
ex
.
getMessage
());
}
}
}
});
}
}
}
/**
* 单例,双重校验,请在 JDK 1.5及更高版本中使用
*
* @param config
* @return
*/
public
static
WXPayReport
getInstance
(
WXPayConfig
config
)
{
if
(
INSTANCE
==
null
)
{
synchronized
(
WXPayReport
.
class
)
{
if
(
INSTANCE
==
null
)
{
INSTANCE
=
new
WXPayReport
(
config
);
}
}
}
return
INSTANCE
;
}
public
void
report
(
String
uuid
,
long
elapsedTimeMillis
,
String
firstDomain
,
boolean
primaryDomain
,
int
firstConnectTimeoutMillis
,
int
firstReadTimeoutMillis
,
boolean
firstHasDnsError
,
boolean
firstHasConnectTimeout
,
boolean
firstHasReadTimeout
)
{
long
currentTimestamp
=
WXPayUtil
.
getCurrentTimestamp
();
ReportInfo
reportInfo
=
new
ReportInfo
(
uuid
,
currentTimestamp
,
elapsedTimeMillis
,
firstDomain
,
primaryDomain
,
firstConnectTimeoutMillis
,
firstReadTimeoutMillis
,
firstHasDnsError
,
firstHasConnectTimeout
,
firstHasReadTimeout
);
String
data
=
reportInfo
.
toLineString
(
config
.
getKey
());
WXPayUtil
.
getLogger
().
info
(
"report {}"
,
data
);
if
(
data
!=
null
)
{
reportMsgQueue
.
offer
(
data
);
}
}
@Deprecated
private
void
reportSync
(
final
String
data
)
throws
Exception
{
httpRequest
(
data
,
DEFAULT_CONNECT_TIMEOUT_MS
,
DEFAULT_READ_TIMEOUT_MS
);
}
@Deprecated
private
void
reportAsync
(
final
String
data
)
throws
Exception
{
new
Thread
(
new
Runnable
()
{
public
void
run
()
{
try
{
httpRequest
(
data
,
DEFAULT_CONNECT_TIMEOUT_MS
,
DEFAULT_READ_TIMEOUT_MS
);
}
catch
(
Exception
ex
)
{
WXPayUtil
.
getLogger
().
warn
(
"report fail. reason: {}"
,
ex
.
getMessage
());
}
}
}).
start
();
}
/**
* http 请求
* @param data
* @param connectTimeoutMs
* @param readTimeoutMs
* @return
* @throws Exception
*/
private
static
String
httpRequest
(
String
data
,
int
connectTimeoutMs
,
int
readTimeoutMs
)
throws
Exception
{
BasicHttpClientConnectionManager
connManager
;
connManager
=
new
BasicHttpClientConnectionManager
(
RegistryBuilder
.<
ConnectionSocketFactory
>
create
()
.
register
(
"http"
,
PlainConnectionSocketFactory
.
getSocketFactory
())
.
register
(
"https"
,
SSLConnectionSocketFactory
.
getSocketFactory
())
.
build
(),
null
,
null
,
null
);
HttpClient
httpClient
=
HttpClientBuilder
.
create
()
.
setConnectionManager
(
connManager
)
.
build
();
HttpPost
httpPost
=
new
HttpPost
(
REPORT_URL
);
RequestConfig
requestConfig
=
RequestConfig
.
custom
().
setSocketTimeout
(
readTimeoutMs
).
setConnectTimeout
(
connectTimeoutMs
).
build
();
httpPost
.
setConfig
(
requestConfig
);
StringEntity
postEntity
=
new
StringEntity
(
data
,
"UTF-8"
);
httpPost
.
addHeader
(
"Content-Type"
,
"text/xml"
);
httpPost
.
addHeader
(
"User-Agent"
,
WXPayConstants
.
USER_AGENT
);
httpPost
.
setEntity
(
postEntity
);
HttpResponse
httpResponse
=
httpClient
.
execute
(
httpPost
);
HttpEntity
httpEntity
=
httpResponse
.
getEntity
();
return
EntityUtils
.
toString
(
httpEntity
,
"UTF-8"
);
}
}
src/main/java/com/hwstudio/antaile/utils/wx/WXPayRequest.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
.
wx
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.client.HttpClient
;
import
org.apache.http.client.config.RequestConfig
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.config.RegistryBuilder
;
import
org.apache.http.conn.ConnectTimeoutException
;
import
org.apache.http.conn.socket.ConnectionSocketFactory
;
import
org.apache.http.conn.socket.PlainConnectionSocketFactory
;
import
org.apache.http.conn.ssl.DefaultHostnameVerifier
;
import
org.apache.http.conn.ssl.SSLConnectionSocketFactory
;
import
org.apache.http.entity.StringEntity
;
import
org.apache.http.impl.client.HttpClientBuilder
;
import
org.apache.http.impl.conn.BasicHttpClientConnectionManager
;
import
org.apache.http.util.EntityUtils
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
java.io.InputStream
;
import
java.net.SocketTimeoutException
;
import
java.net.UnknownHostException
;
import
java.security.KeyStore
;
import
java.security.SecureRandom
;
public
class
WXPayRequest
{
private
WXPayConfig
config
;
public
WXPayRequest
(
WXPayConfig
config
)
throws
Exception
{
this
.
config
=
config
;
}
/**
* 请求,只请求一次,不做重试
*
* @param domain
* @param urlSuffix
* @param uuid
* @param data
* @param connectTimeoutMs
* @param readTimeoutMs
* @param useCert 是否使用证书,针对退款、撤销等操作
* @return
* @throws Exception
*/
private
String
requestOnce
(
final
String
domain
,
String
urlSuffix
,
String
uuid
,
String
data
,
int
connectTimeoutMs
,
int
readTimeoutMs
,
boolean
useCert
)
throws
Exception
{
BasicHttpClientConnectionManager
connManager
;
if
(
useCert
)
{
// 证书
char
[]
password
=
config
.
getMchID
().
toCharArray
();
InputStream
certStream
=
config
.
getCertStream
();
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
ks
.
load
(
certStream
,
password
);
// 实例化密钥库 & 初始化密钥工厂
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
KeyManagerFactory
.
getDefaultAlgorithm
());
kmf
.
init
(
ks
,
password
);
// 创建 SSLContext
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
sslContext
.
init
(
kmf
.
getKeyManagers
(),
null
,
new
SecureRandom
());
SSLConnectionSocketFactory
sslConnectionSocketFactory
=
new
SSLConnectionSocketFactory
(
sslContext
,
new
String
[]{
"TLSv1"
},
null
,
new
DefaultHostnameVerifier
());
connManager
=
new
BasicHttpClientConnectionManager
(
RegistryBuilder
.<
ConnectionSocketFactory
>
create
()
.
register
(
"http"
,
PlainConnectionSocketFactory
.
getSocketFactory
())
.
register
(
"https"
,
sslConnectionSocketFactory
)
.
build
(),
null
,
null
,
null
);
}
else
{
connManager
=
new
BasicHttpClientConnectionManager
(
RegistryBuilder
.<
ConnectionSocketFactory
>
create
()
.
register
(
"http"
,
PlainConnectionSocketFactory
.
getSocketFactory
())
.
register
(
"https"
,
SSLConnectionSocketFactory
.
getSocketFactory
())
.
build
(),
null
,
null
,
null
);
}
HttpClient
httpClient
=
HttpClientBuilder
.
create
()
.
setConnectionManager
(
connManager
)
.
build
();
String
url
=
"https://"
+
domain
+
urlSuffix
;
HttpPost
httpPost
=
new
HttpPost
(
url
);
RequestConfig
requestConfig
=
RequestConfig
.
custom
().
setSocketTimeout
(
readTimeoutMs
).
setConnectTimeout
(
connectTimeoutMs
).
build
();
httpPost
.
setConfig
(
requestConfig
);
StringEntity
postEntity
=
new
StringEntity
(
data
,
"UTF-8"
);
httpPost
.
addHeader
(
"Content-Type"
,
"text/xml"
);
httpPost
.
addHeader
(
"User-Agent"
,
WXPayConstants
.
USER_AGENT
+
" "
+
config
.
getMchID
());
httpPost
.
setEntity
(
postEntity
);
HttpResponse
httpResponse
=
httpClient
.
execute
(
httpPost
);
HttpEntity
httpEntity
=
httpResponse
.
getEntity
();
return
EntityUtils
.
toString
(
httpEntity
,
"UTF-8"
);
}
private
String
request
(
String
urlSuffix
,
String
uuid
,
String
data
,
int
connectTimeoutMs
,
int
readTimeoutMs
,
boolean
useCert
,
boolean
autoReport
)
throws
Exception
{
Exception
exception
=
null
;
long
elapsedTimeMillis
=
0
;
long
startTimestampMs
=
WXPayUtil
.
getCurrentTimestampMs
();
boolean
firstHasDnsErr
=
false
;
boolean
firstHasConnectTimeout
=
false
;
boolean
firstHasReadTimeout
=
false
;
IWXPayDomain
.
DomainInfo
domainInfo
=
config
.
getWXPayDomain
().
getDomain
(
config
);
if
(
domainInfo
==
null
)
{
throw
new
Exception
(
"WXPayConfig.getWXPayDomain().getDomain() is empty or null"
);
}
try
{
String
result
=
requestOnce
(
domainInfo
.
domain
,
urlSuffix
,
uuid
,
data
,
connectTimeoutMs
,
readTimeoutMs
,
useCert
);
elapsedTimeMillis
=
WXPayUtil
.
getCurrentTimestampMs
()
-
startTimestampMs
;
config
.
getWXPayDomain
().
report
(
domainInfo
.
domain
,
elapsedTimeMillis
,
null
);
WXPayReport
.
getInstance
(
config
).
report
(
uuid
,
elapsedTimeMillis
,
domainInfo
.
domain
,
domainInfo
.
primaryDomain
,
connectTimeoutMs
,
readTimeoutMs
,
firstHasDnsErr
,
firstHasConnectTimeout
,
firstHasReadTimeout
);
return
result
;
}
catch
(
UnknownHostException
ex
)
{
// dns 解析错误,或域名不存在
exception
=
ex
;
firstHasDnsErr
=
true
;
elapsedTimeMillis
=
WXPayUtil
.
getCurrentTimestampMs
()
-
startTimestampMs
;
WXPayUtil
.
getLogger
().
warn
(
"UnknownHostException for domainInfo {}"
,
domainInfo
);
WXPayReport
.
getInstance
(
config
).
report
(
uuid
,
elapsedTimeMillis
,
domainInfo
.
domain
,
domainInfo
.
primaryDomain
,
connectTimeoutMs
,
readTimeoutMs
,
firstHasDnsErr
,
firstHasConnectTimeout
,
firstHasReadTimeout
);
}
catch
(
ConnectTimeoutException
ex
)
{
exception
=
ex
;
firstHasConnectTimeout
=
true
;
elapsedTimeMillis
=
WXPayUtil
.
getCurrentTimestampMs
()
-
startTimestampMs
;
WXPayUtil
.
getLogger
().
warn
(
"connect timeout happened for domainInfo {}"
,
domainInfo
);
WXPayReport
.
getInstance
(
config
).
report
(
uuid
,
elapsedTimeMillis
,
domainInfo
.
domain
,
domainInfo
.
primaryDomain
,
connectTimeoutMs
,
readTimeoutMs
,
firstHasDnsErr
,
firstHasConnectTimeout
,
firstHasReadTimeout
);
}
catch
(
SocketTimeoutException
ex
)
{
exception
=
ex
;
firstHasReadTimeout
=
true
;
elapsedTimeMillis
=
WXPayUtil
.
getCurrentTimestampMs
()
-
startTimestampMs
;
WXPayUtil
.
getLogger
().
warn
(
"timeout happened for domainInfo {}"
,
domainInfo
);
WXPayReport
.
getInstance
(
config
).
report
(
uuid
,
elapsedTimeMillis
,
domainInfo
.
domain
,
domainInfo
.
primaryDomain
,
connectTimeoutMs
,
readTimeoutMs
,
firstHasDnsErr
,
firstHasConnectTimeout
,
firstHasReadTimeout
);
}
catch
(
Exception
ex
)
{
exception
=
ex
;
elapsedTimeMillis
=
WXPayUtil
.
getCurrentTimestampMs
()
-
startTimestampMs
;
WXPayReport
.
getInstance
(
config
).
report
(
uuid
,
elapsedTimeMillis
,
domainInfo
.
domain
,
domainInfo
.
primaryDomain
,
connectTimeoutMs
,
readTimeoutMs
,
firstHasDnsErr
,
firstHasConnectTimeout
,
firstHasReadTimeout
);
}
config
.
getWXPayDomain
().
report
(
domainInfo
.
domain
,
elapsedTimeMillis
,
exception
);
throw
exception
;
}
/**
* 可重试的,非双向认证的请求
*
* @param urlSuffix
* @param uuid
* @param data
* @return
*/
public
String
requestWithoutCert
(
String
urlSuffix
,
String
uuid
,
String
data
,
boolean
autoReport
)
throws
Exception
{
return
this
.
request
(
urlSuffix
,
uuid
,
data
,
config
.
getHttpConnectTimeoutMs
(),
config
.
getHttpReadTimeoutMs
(),
false
,
autoReport
);
}
/**
* 可重试的,非双向认证的请求
*
* @param urlSuffix
* @param uuid
* @param data
* @param connectTimeoutMs
* @param readTimeoutMs
* @return
*/
public
String
requestWithoutCert
(
String
urlSuffix
,
String
uuid
,
String
data
,
int
connectTimeoutMs
,
int
readTimeoutMs
,
boolean
autoReport
)
throws
Exception
{
return
this
.
request
(
urlSuffix
,
uuid
,
data
,
connectTimeoutMs
,
readTimeoutMs
,
false
,
autoReport
);
}
/**
* 可重试的,双向认证的请求
*
* @param urlSuffix
* @param uuid
* @param data
* @return
*/
public
String
requestWithCert
(
String
urlSuffix
,
String
uuid
,
String
data
,
boolean
autoReport
)
throws
Exception
{
return
this
.
request
(
urlSuffix
,
uuid
,
data
,
config
.
getHttpConnectTimeoutMs
(),
config
.
getHttpReadTimeoutMs
(),
true
,
autoReport
);
}
/**
* 可重试的,双向认证的请求
*
* @param urlSuffix
* @param uuid
* @param data
* @param connectTimeoutMs
* @param readTimeoutMs
* @return
*/
public
String
requestWithCert
(
String
urlSuffix
,
String
uuid
,
String
data
,
int
connectTimeoutMs
,
int
readTimeoutMs
,
boolean
autoReport
)
throws
Exception
{
return
this
.
request
(
urlSuffix
,
uuid
,
data
,
connectTimeoutMs
,
readTimeoutMs
,
true
,
autoReport
);
}
}
src/main/java/com/hwstudio/antaile/utils/wx/WXPayUtil.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
.
wx
;
import
com.github.wxpay.sdk.WXPayConstants.SignType
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.w3c.dom.Node
;
import
org.w3c.dom.NodeList
;
import
javax.crypto.Mac
;
import
javax.crypto.spec.SecretKeySpec
;
import
javax.xml.parsers.DocumentBuilder
;
import
javax.xml.transform.OutputKeys
;
import
javax.xml.transform.Transformer
;
import
javax.xml.transform.TransformerFactory
;
import
javax.xml.transform.dom.DOMSource
;
import
javax.xml.transform.stream.StreamResult
;
import
java.io.ByteArrayInputStream
;
import
java.io.InputStream
;
import
java.io.StringWriter
;
import
java.security.MessageDigest
;
import
java.security.SecureRandom
;
import
java.util.*
;
public
class
WXPayUtil
{
private
static
final
String
SYMBOLS
=
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
;
private
static
final
Random
RANDOM
=
new
SecureRandom
();
/**
* 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
)
{
WXPayUtil
.
getLogger
().
warn
(
"Invalid XML, can not convert to map. Error message: {}. XML content: {}"
,
ex
.
getMessage
(),
strXML
);
throw
ex
;
}
}
/**
* 将Map转换为XML格式的字符串
*
* @param data Map类型数据
* @return XML格式的字符串
* @throws Exception
*/
public
static
String
mapToXml
(
Map
<
String
,
String
>
data
)
throws
Exception
{
org
.
w3c
.
dom
.
Document
document
=
WXPayXmlUtil
.
newDocument
();
org
.
w3c
.
dom
.
Element
root
=
document
.
createElement
(
"xml"
);
document
.
appendChild
(
root
);
for
(
String
key:
data
.
keySet
())
{
String
value
=
data
.
get
(
key
);
if
(
value
==
null
)
{
value
=
""
;
}
value
=
value
.
trim
();
org
.
w3c
.
dom
.
Element
filed
=
document
.
createElement
(
key
);
filed
.
appendChild
(
document
.
createTextNode
(
value
));
root
.
appendChild
(
filed
);
}
TransformerFactory
tf
=
TransformerFactory
.
newInstance
();
Transformer
transformer
=
tf
.
newTransformer
();
DOMSource
source
=
new
DOMSource
(
document
);
transformer
.
setOutputProperty
(
OutputKeys
.
ENCODING
,
"UTF-8"
);
transformer
.
setOutputProperty
(
OutputKeys
.
INDENT
,
"yes"
);
StringWriter
writer
=
new
StringWriter
();
StreamResult
result
=
new
StreamResult
(
writer
);
transformer
.
transform
(
source
,
result
);
String
output
=
writer
.
getBuffer
().
toString
();
//.replaceAll("\n|\r", "");
try
{
writer
.
close
();
}
catch
(
Exception
ex
)
{
}
return
output
;
}
/**
* 生成带有 sign 的 XML 格式字符串
*
* @param data Map类型数据
* @param key API密钥
* @return 含有sign字段的XML
*/
public
static
String
generateSignedXml
(
final
Map
<
String
,
String
>
data
,
String
key
)
throws
Exception
{
return
generateSignedXml
(
data
,
key
,
SignType
.
MD5
);
}
/**
* 生成带有 sign 的 XML 格式字符串
*
* @param data Map类型数据
* @param key API密钥
* @param signType 签名类型
* @return 含有sign字段的XML
*/
public
static
String
generateSignedXml
(
final
Map
<
String
,
String
>
data
,
String
key
,
SignType
signType
)
throws
Exception
{
String
sign
=
generateSignature
(
data
,
key
,
signType
);
data
.
put
(
WXPayConstants
.
FIELD_SIGN
,
sign
);
return
mapToXml
(
data
);
}
/**
* 判断签名是否正确
*
* @param xmlStr XML格式数据
* @param key API密钥
* @return 签名是否正确
* @throws Exception
*/
public
static
boolean
isSignatureValid
(
String
xmlStr
,
String
key
)
throws
Exception
{
Map
<
String
,
String
>
data
=
xmlToMap
(
xmlStr
);
if
(!
data
.
containsKey
(
WXPayConstants
.
FIELD_SIGN
)
)
{
return
false
;
}
String
sign
=
data
.
get
(
WXPayConstants
.
FIELD_SIGN
);
return
generateSignature
(
data
,
key
).
equals
(
sign
);
}
/**
* 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。
*
* @param data Map类型数据
* @param key API密钥
* @return 签名是否正确
* @throws Exception
*/
public
static
boolean
isSignatureValid
(
Map
<
String
,
String
>
data
,
String
key
)
throws
Exception
{
return
isSignatureValid
(
data
,
key
,
SignType
.
MD5
);
}
/**
* 判断签名是否正确,必须包含sign字段,否则返回false。
*
* @param data Map类型数据
* @param key API密钥
* @param signType 签名方式
* @return 签名是否正确
* @throws Exception
*/
public
static
boolean
isSignatureValid
(
Map
<
String
,
String
>
data
,
String
key
,
SignType
signType
)
throws
Exception
{
if
(!
data
.
containsKey
(
WXPayConstants
.
FIELD_SIGN
)
)
{
return
false
;
}
String
sign
=
data
.
get
(
WXPayConstants
.
FIELD_SIGN
);
return
generateSignature
(
data
,
key
,
signType
).
equals
(
sign
);
}
/**
* 生成签名
*
* @param data 待签名数据
* @param key API密钥
* @return 签名
*/
public
static
String
generateSignature
(
final
Map
<
String
,
String
>
data
,
String
key
)
throws
Exception
{
return
generateSignature
(
data
,
key
,
SignType
.
MD5
);
}
/**
* 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
*
* @param data 待签名数据
* @param key API密钥
* @param signType 签名方式
* @return 签名
*/
public
static
String
generateSignature
(
final
Map
<
String
,
String
>
data
,
String
key
,
SignType
signType
)
throws
Exception
{
Set
<
String
>
keySet
=
data
.
keySet
();
String
[]
keyArray
=
keySet
.
toArray
(
new
String
[
keySet
.
size
()]);
Arrays
.
sort
(
keyArray
);
StringBuilder
sb
=
new
StringBuilder
();
for
(
String
k
:
keyArray
)
{
if
(
k
.
equals
(
WXPayConstants
.
FIELD_SIGN
))
{
continue
;
}
if
(
data
.
get
(
k
).
trim
().
length
()
>
0
)
// 参数值为空,则不参与签名
sb
.
append
(
k
).
append
(
"="
).
append
(
data
.
get
(
k
).
trim
()).
append
(
"&"
);
}
sb
.
append
(
"key="
).
append
(
key
);
if
(
SignType
.
MD5
.
equals
(
signType
))
{
return
MD5
(
sb
.
toString
()).
toUpperCase
();
}
else
if
(
SignType
.
HMACSHA256
.
equals
(
signType
))
{
return
HMACSHA256
(
sb
.
toString
(),
key
);
}
else
{
throw
new
Exception
(
String
.
format
(
"Invalid sign_type: %s"
,
signType
));
}
}
/**
* 获取随机字符串 Nonce Str
*
* @return String 随机字符串
*/
public
static
String
generateNonceStr
()
{
char
[]
nonceChars
=
new
char
[
32
];
for
(
int
index
=
0
;
index
<
nonceChars
.
length
;
++
index
)
{
nonceChars
[
index
]
=
SYMBOLS
.
charAt
(
RANDOM
.
nextInt
(
SYMBOLS
.
length
()));
}
return
new
String
(
nonceChars
);
}
/**
* 生成 MD5
*
* @param data 待处理数据
* @return MD5结果
*/
public
static
String
MD5
(
String
data
)
throws
Exception
{
MessageDigest
md
=
MessageDigest
.
getInstance
(
"MD5"
);
byte
[]
array
=
md
.
digest
(
data
.
getBytes
(
"UTF-8"
));
StringBuilder
sb
=
new
StringBuilder
();
for
(
byte
item
:
array
)
{
sb
.
append
(
Integer
.
toHexString
((
item
&
0xFF
)
|
0x100
).
substring
(
1
,
3
));
}
return
sb
.
toString
().
toUpperCase
();
}
/**
* 生成 HMACSHA256
* @param data 待处理数据
* @param key 密钥
* @return 加密结果
* @throws Exception
*/
public
static
String
HMACSHA256
(
String
data
,
String
key
)
throws
Exception
{
Mac
sha256_HMAC
=
Mac
.
getInstance
(
"HmacSHA256"
);
SecretKeySpec
secret_key
=
new
SecretKeySpec
(
key
.
getBytes
(
"UTF-8"
),
"HmacSHA256"
);
sha256_HMAC
.
init
(
secret_key
);
byte
[]
array
=
sha256_HMAC
.
doFinal
(
data
.
getBytes
(
"UTF-8"
));
StringBuilder
sb
=
new
StringBuilder
();
for
(
byte
item
:
array
)
{
sb
.
append
(
Integer
.
toHexString
((
item
&
0xFF
)
|
0x100
).
substring
(
1
,
3
));
}
return
sb
.
toString
().
toUpperCase
();
}
/**
* 日志
* @return
*/
public
static
Logger
getLogger
()
{
Logger
logger
=
LoggerFactory
.
getLogger
(
"wxpay java sdk"
);
return
logger
;
}
/**
* 获取当前时间戳,单位秒
* @return
*/
public
static
long
getCurrentTimestamp
()
{
return
System
.
currentTimeMillis
()/
1000
;
}
/**
* 获取当前时间戳,单位毫秒
* @return
*/
public
static
long
getCurrentTimestampMs
()
{
return
System
.
currentTimeMillis
();
}
}
src/main/java/com/hwstudio/antaile/utils/wx/WXPayXmlUtil.java
0 → 100644
View file @
c584e28e
package
com
.
hwstudio
.
antaile
.
utils
.
wx
;
import
org.w3c.dom.Document
;
import
javax.xml.XMLConstants
;
import
javax.xml.parsers.DocumentBuilder
;
import
javax.xml.parsers.DocumentBuilderFactory
;
import
javax.xml.parsers.ParserConfigurationException
;
/**
* 2018/7/3
*/
public
final
class
WXPayXmlUtil
{
public
static
DocumentBuilder
newDocumentBuilder
()
throws
ParserConfigurationException
{
DocumentBuilderFactory
documentBuilderFactory
=
DocumentBuilderFactory
.
newInstance
();
documentBuilderFactory
.
setFeature
(
"http://apache.org/xml/features/disallow-doctype-decl"
,
true
);
documentBuilderFactory
.
setFeature
(
"http://xml.org/sax/features/external-general-entities"
,
false
);
documentBuilderFactory
.
setFeature
(
"http://xml.org/sax/features/external-parameter-entities"
,
false
);
documentBuilderFactory
.
setFeature
(
"http://apache.org/xml/features/nonvalidating/load-external-dtd"
,
false
);
documentBuilderFactory
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
true
);
documentBuilderFactory
.
setXIncludeAware
(
false
);
documentBuilderFactory
.
setExpandEntityReferences
(
false
);
return
documentBuilderFactory
.
newDocumentBuilder
();
}
public
static
Document
newDocument
()
throws
ParserConfigurationException
{
return
newDocumentBuilder
().
newDocument
();
}
}
src/main/resources/application.yml
View file @
c584e28e
...
...
@@ -73,7 +73,7 @@ spring:
#此处为微信开放平台的相关参数
appid
:
wx27928349186b6267
appSecret
:
dee9b11ee545bff614abc91ebb042127
redirectUri
:
http
://31673rv944.51vip.biz/atlApp/wx/get
QrcodeAndState
redirectUri
:
http
s://appapi.antaile.net/wx/return
QrcodeAndState
server
:
port
:
8088
...
...
src/main/resources/mapping/AtlUserMapper.xml
View file @
c584e28e
...
...
@@ -72,8 +72,26 @@
<if
test=
"birthdayType != null"
>
birthday_type = #{birthdayType},
</if>
<if
test=
"state != null"
>
state = #{state},
</if>
<if
test=
"signature != null"
>
signature = #{signature}
signature = #{signature},
</if>
<if
test=
"loginDate != null"
>
login_date = #{loginDate},
</if>
<if
test=
"officeOpenId != null and officeOpenId !=''"
>
office_open_id = #{officeOpenId},
</if>
<if
test=
"appletOpenId != null and appletOpenId !=''"
>
applet_open_id = #{appletOpenId},
</if>
<if
test=
"webappOpenId != null and webappOpenId !=''"
>
webapp_open_id = #{webappOpenId},
</if>
<if
test=
"unionid != null and unionid !='' "
>
unionid = #{unionid},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
...
...
@@ -116,6 +134,9 @@
SELECT * FROM atl_user WHERE office_open_id = #{officeOpenId}
</select>
<select
id=
"getByWebappOpenId"
resultType=
"com.hwstudio.antaile.entity.AtlUser"
parameterType=
"java.lang.String"
>
SELECT * FROM atl_user WHERE webapp_open_id = #{webappOpenId}
</select>
<update
id=
"updatePwd"
>
UPDATE atl_user SET
...
...
@@ -180,15 +201,21 @@
<if
test=
"signature != null"
>
signature,
</if>
<if
test=
"signature != null"
>
signature,
</if>
<if
test=
"loginDate != null"
>
login_date,
</if>
<if
test=
"appletOpenId != null"
>
<if
test=
"officeOpenId != null and officeOpenId !=''"
>
office_open_id,
</if>
<if
test=
"appletOpenId != null and appletOpenId !=''"
>
applet_open_id,
</if>
<if
test=
"webappOpenId != null and webappOpenId !=''"
>
webapp_open_id,
</if>
<if
test=
"unionid != null and unionid !='' "
>
unionid,
</if>
create_time, is_sys_push, is_sc_push, is_rem_push
</trim>
<trim
prefix=
"values ("
suffix=
")"
suffixOverrides=
","
>
...
...
@@ -234,9 +261,18 @@
<if
test=
"loginDate != null"
>
#{loginDate},
</if>
<if
test=
"appletOpenId != null"
>
<if
test=
"officeOpenId != null and officeOpenId !='' "
>
#{officeOpenId},
</if>
<if
test=
"appletOpenId != null and appletOpenId !='' "
>
#{appletOpenId},
</if>
<if
test=
"webappOpenId != null and webappOpenId !=''"
>
#{webappOpenId},
</if>
<if
test=
"unionid != null and unionid !='' "
>
#{unionid},
</if>
NOW(), '0', '0', '0'
</trim>
</insert>
...
...
@@ -343,4 +379,8 @@
where create_user_id = #{userId}
</select>
<select
id=
"selectOneUserByMobilePhone"
parameterType=
"java.lang.String"
resultType=
"com.hwstudio.antaile.entity.AtlUser"
>
SELECT * FROM atl_user WHERE mobile_phone=#{mobilePhone}
</select>
</mapper>
\ No newline at end of file
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