Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Jeepay
Commits
9dad80f9
Commit
9dad80f9
authored
Jul 16, 2021
by
terrfly
Browse files
完成 支付宝子商户的二维码自主授权;
parent
2b7a2cbd
Changes
9
Hide whitespace changes
Inline
Side-by-side
jeepay-core/src/main/java/com/jeequan/jeepay/core/model/DBApplicationConfig.java
View file @
9dad80f9
...
...
@@ -64,4 +64,9 @@ public class DBApplicationConfig implements Serializable {
return
getPaySiteUrl
()
+
"/api/scan/imgs/"
+
JeepayKit
.
aesEncode
(
url
)
+
".png"
;
}
/** 生成 【支付宝 isv子商户的授权链接地址】 **/
public
String
genAlipayIsvsubMchAuthUrl
(
String
isvNo
,
String
mchAppId
){
return
getPaySiteUrl
()
+
"/api/channelbiz/alipay/redirectAppToAppAuth/"
+
isvNo
+
"_"
+
mchAppId
;
}
}
jeepay-core/src/main/java/com/jeequan/jeepay/core/model/params/alipay/AlipayConfig.java
View file @
9dad80f9
...
...
@@ -38,6 +38,11 @@ public class AlipayConfig{
public
static
String
PROD_OAUTH_URL
=
"https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=%s&scope=auth_base&state=&redirect_uri=%s"
;
public
static
String
SANDBOX_OAUTH_URL
=
"https://openauth.alipaydev.com/oauth2/publicAppAuthorize.htm?app_id=%s&scope=auth_base&state=&redirect_uri=%s"
;
/** isv获取授权商户URL地址 **/
public
static
String
PROD_APP_TO_APP_AUTH_URL
=
"https://openauth.alipay.com/oauth2/appToAppAuth.htm?app_id=%s&redirect_uri=%s&state=%s"
;
public
static
String
SANDBOX_APP_TO_APP_AUTH_URL
=
"https://openauth.alipaydev.com/oauth2/appToAppAuth.htm?app_id=%s&redirect_uri=%s&state=%s"
;
public
static
String
FORMAT
=
"json"
;
public
static
String
CHARSET
=
"UTF-8"
;
...
...
jeepay-manager/src/main/java/com/jeequan/jeepay/mgr/ctrl/merchant/MchPayInterfaceConfigController.java
View file @
9dad80f9
...
...
@@ -32,7 +32,6 @@ import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import
com.jeequan.jeepay.service.impl.MchAppService
;
import
com.jeequan.jeepay.service.impl.MchInfoService
;
import
com.jeequan.jeepay.service.impl.PayInterfaceConfigService
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.web.bind.annotation.*
;
...
...
@@ -52,8 +51,8 @@ import java.util.List;
public
class
MchPayInterfaceConfigController
extends
CommonCtrl
{
@Autowired
private
PayInterfaceConfigService
payInterfaceConfigService
;
@Autowired
private
MqCommonService
mqCommonService
;
@Autowired
private
MchAppService
mchAppService
;
@Autowired
private
MqCommonService
mqCommonService
;
@Autowired
private
MchInfoService
mchInfoService
;
/**
...
...
@@ -158,4 +157,21 @@ public class MchPayInterfaceConfigController extends CommonCtrl {
return
ApiRes
.
ok
();
}
/** 查询支付宝商户授权URL **/
@GetMapping
(
"/alipayIsvsubMchAuthUrls/{mchAppId}"
)
public
ApiRes
queryAlipayIsvsubMchAuthUrl
(
@PathVariable
String
mchAppId
)
{
MchApp
mchApp
=
mchAppService
.
getById
(
mchAppId
);
MchInfo
mchInfo
=
mchInfoService
.
getById
(
mchApp
.
getMchNo
());
String
authUrl
=
sysConfigService
.
getDBApplicationConfig
().
genAlipayIsvsubMchAuthUrl
(
mchInfo
.
getIsvNo
(),
mchAppId
);
String
authQrImgUrl
=
sysConfigService
.
getDBApplicationConfig
().
genScanImgUrl
(
authUrl
);
JSONObject
result
=
new
JSONObject
();
result
.
put
(
"authUrl"
,
authUrl
);
result
.
put
(
"authQrImgUrl"
,
authQrImgUrl
);
return
ApiRes
.
ok
(
result
);
}
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/alipay/ctrl/AlipayBizController.java
0 → 100644
View file @
9dad80f9
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jeequan.jeepay.pay.channel.alipay.ctrl
;
import
cn.hutool.core.util.URLUtil
;
import
com.alibaba.fastjson.JSONObject
;
import
com.alipay.api.domain.AlipayOpenAuthTokenAppModel
;
import
com.alipay.api.request.AlipayOpenAuthTokenAppRequest
;
import
com.alipay.api.response.AlipayOpenAuthTokenAppResponse
;
import
com.jeequan.jeepay.core.constants.CS
;
import
com.jeequan.jeepay.core.ctrls.AbstractCtrl
;
import
com.jeequan.jeepay.core.entity.MchApp
;
import
com.jeequan.jeepay.core.entity.PayInterfaceConfig
;
import
com.jeequan.jeepay.core.exception.BizException
;
import
com.jeequan.jeepay.core.model.params.alipay.AlipayConfig
;
import
com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams
;
import
com.jeequan.jeepay.core.mq.MqCommonService
;
import
com.jeequan.jeepay.core.utils.JsonKit
;
import
com.jeequan.jeepay.pay.channel.alipay.AlipayKit
;
import
com.jeequan.jeepay.pay.model.AlipayClientWrapper
;
import
com.jeequan.jeepay.pay.model.IsvConfigContext
;
import
com.jeequan.jeepay.pay.service.ConfigContextService
;
import
com.jeequan.jeepay.service.impl.MchAppService
;
import
com.jeequan.jeepay.service.impl.PayInterfaceConfigService
;
import
com.jeequan.jeepay.service.impl.SysConfigService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
/**
* 渠道侧自定义业务ctrl
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/7/15 11:49
*/
@Slf4j
@Controller
@RequestMapping
(
"/api/channelbiz/alipay"
)
public
class
AlipayBizController
extends
AbstractCtrl
{
@Autowired
private
ConfigContextService
configContextService
;
@Autowired
private
SysConfigService
sysConfigService
;
@Autowired
private
PayInterfaceConfigService
payInterfaceConfigService
;
@Autowired
private
MqCommonService
mqCommonService
;
@Autowired
private
MchAppService
mchAppService
;
/** 跳转到支付宝的授权页面 (统一从pay项目获取到isv配置信息)
* isvAndMchNo 格式: ISVNO_MCHAPPID
* example: https://pay.jeepay.cn/api/channelbiz/alipay/redirectAppToAppAuth/V1623998765_60cc41694ee0e6685f57eb1f
* **/
@RequestMapping
(
"/redirectAppToAppAuth/{isvAndMchAppId}"
)
public
void
redirectAppToAppAuth
(
@PathVariable
(
"isvAndMchAppId"
)
String
isvAndMchAppId
)
throws
IOException
{
String
isvNo
=
isvAndMchAppId
.
split
(
"_"
)[
0
];
IsvConfigContext
isvConfigContext
=
configContextService
.
getIsvConfigContext
(
isvNo
);
AlipayIsvParams
alipayIsvParams
=
isvConfigContext
.
getIsvParamsByIfCode
(
CS
.
IF_CODE
.
ALIPAY
,
AlipayIsvParams
.
class
);
alipayIsvParams
.
getSandbox
();
String
oauthUrl
=
AlipayConfig
.
PROD_APP_TO_APP_AUTH_URL
;
if
(
alipayIsvParams
.
getSandbox
()
!=
null
&&
alipayIsvParams
.
getSandbox
()
==
CS
.
YES
){
oauthUrl
=
AlipayConfig
.
SANDBOX_APP_TO_APP_AUTH_URL
;
}
String
redirectUrl
=
sysConfigService
.
getDBApplicationConfig
().
getPaySiteUrl
()
+
"/api/channelbiz/alipay/appToAppAuthCallback"
;
response
.
sendRedirect
(
String
.
format
(
oauthUrl
,
alipayIsvParams
.
getAppId
(),
URLUtil
.
encode
(
redirectUrl
),
isvAndMchAppId
));
}
/** 支付宝授权回调地址 **/
@RequestMapping
(
"/appToAppAuthCallback"
)
public
String
appToAppAuthCallback
()
{
String
errMsg
=
null
;
boolean
isAlipaySysAuth
=
true
;
//是否 服务商登录支付宝后台系统发起的商户授权, 此时无法获取authCode和商户的信息。
try
{
// isvAndMchAppId 格式: ISVNO_MCHAPPID, 如果isvAndMchNo为空说明是: 支付宝后台的二维码授权之后的跳转链接。
String
isvAndMchAppId
=
getValString
(
"state"
);
String
appAuthCode
=
getValString
(
"app_auth_code"
);
// 支付宝授权code
if
(
StringUtils
.
isNotEmpty
(
isvAndMchAppId
)
&&
StringUtils
.
isNotEmpty
(
appAuthCode
)){
isAlipaySysAuth
=
false
;
String
isvNo
=
isvAndMchAppId
.
split
(
"_"
)[
0
];
String
mchAppId
=
isvAndMchAppId
.
split
(
"_"
)[
1
];
AlipayClientWrapper
alipayClientWrapper
=
configContextService
.
getIsvConfigContext
(
isvNo
).
getAlipayClientWrapper
();
AlipayOpenAuthTokenAppRequest
request
=
new
AlipayOpenAuthTokenAppRequest
();
AlipayOpenAuthTokenAppModel
model
=
new
AlipayOpenAuthTokenAppModel
();
model
.
setGrantType
(
"authorization_code"
);
model
.
setCode
(
appAuthCode
);
request
.
setBizModel
(
model
);
// expiresIn: 该字段已作废,应用令牌长期有效,接入方不需要消费该字段
// reExpiresIn: 刷新令牌的有效时间(从接口调用时间作为起始时间),单位到秒
// DateUtil.offsetSecond(new Date(), Integer.parseInt(resp.getExpiresIn()));
AlipayOpenAuthTokenAppResponse
resp
=
alipayClientWrapper
.
execute
(
request
);
if
(!
resp
.
isSuccess
()){
throw
new
BizException
(
AlipayKit
.
appendErrMsg
(
resp
.
getMsg
(),
resp
.
getSubMsg
()));
}
String
appAuthToken
=
resp
.
getAppAuthToken
();
JSONObject
ifParams
=
new
JSONObject
();
ifParams
.
put
(
"appAuthToken"
,
appAuthToken
);
ifParams
.
put
(
"refreshToken"
,
resp
.
getAppRefreshToken
());
ifParams
.
put
(
"expireTimestamp"
,
resp
.
getExpiresIn
());
PayInterfaceConfig
dbRecord
=
payInterfaceConfigService
.
getByInfoIdAndIfCode
(
CS
.
INFO_TYPE_MCH_APP
,
mchAppId
,
CS
.
IF_CODE
.
ALIPAY
);
if
(
dbRecord
!=
null
){
PayInterfaceConfig
updateRecord
=
new
PayInterfaceConfig
();
updateRecord
.
setId
(
dbRecord
.
getId
());
updateRecord
.
setIfParams
(
ifParams
.
toJSONString
());
payInterfaceConfigService
.
updateById
(
updateRecord
);
}
else
{
dbRecord
=
new
PayInterfaceConfig
();
dbRecord
.
setInfoType
(
CS
.
INFO_TYPE_MCH_APP
);
dbRecord
.
setInfoId
(
mchAppId
);
dbRecord
.
setIfCode
(
CS
.
IF_CODE
.
ALIPAY
);
dbRecord
.
setIfParams
(
ifParams
.
toJSONString
());
dbRecord
.
setIfRate
(
new
BigDecimal
(
"0.006"
));
//默认费率
dbRecord
.
setState
(
CS
.
YES
);
dbRecord
.
setCreatedBy
(
"SYS"
);
dbRecord
.
setCreatedUid
(
0L
);
payInterfaceConfigService
.
save
(
dbRecord
);
}
MchApp
mchApp
=
mchAppService
.
getById
(
mchAppId
);
JSONObject
jsonObject
=
JsonKit
.
newJson
(
"mchNo"
,
mchApp
.
getMchNo
());
jsonObject
.
put
(
"appId"
,
mchApp
.
getAppId
());
mqCommonService
.
send
(
jsonObject
.
toJSONString
(),
CS
.
MQ
.
MQ_TYPE_MODIFY_MCH_APP
);
// 推送mq到目前节点进行更新数据
}
}
catch
(
Exception
e
)
{
log
.
error
(
"error"
,
e
);
errMsg
=
StringUtils
.
defaultIfBlank
(
e
.
getMessage
(),
"系统异常!"
);
}
request
.
setAttribute
(
"errMsg"
,
errMsg
);
request
.
setAttribute
(
"isAlipaySysAuth"
,
isAlipaySysAuth
);
return
"channel/alipay/isvsubMchAuth"
;
}
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/mq/ActiveMqMessage.java
View file @
9dad80f9
...
...
@@ -22,6 +22,7 @@ import com.jeequan.jeepay.pay.mq.receive.MqReceiveCommon;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.activemq.ScheduledMessage
;
import
org.apache.activemq.command.ActiveMQQueue
;
import
org.apache.activemq.command.ActiveMQTopic
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.context.annotation.Bean
;
...
...
@@ -75,6 +76,16 @@ public class ActiveMqMessage extends MqCommonService {
@Qualifier
(
"activePayOrderMchNotifyInner"
)
private
Queue
mqQueue4PayOrderMchNotifyInner
;
@Bean
(
"activeMqSendModifyMchApp"
)
public
ActiveMQTopic
mqTopic4ModifyMchApp
(){
return
new
ActiveMQTopic
(
CS
.
MQ
.
TOPIC_MODIFY_MCH_APP
);
}
@Lazy
@Autowired
@Qualifier
(
"activeMqSendModifyMchApp"
)
private
ActiveMQTopic
mqTopic4ModifyMchApp
;
/**
* 发送消息
* @param msg
...
...
@@ -86,6 +97,8 @@ public class ActiveMqMessage extends MqCommonService {
channelOrderQuery
(
msg
);
}
else
if
(
sendType
.
equals
(
CS
.
MQ
.
MQ_TYPE_PAY_ORDER_MCH_NOTIFY
))
{
payOrderMchNotify
(
msg
);
}
else
if
(
sendType
.
equals
(
CS
.
MQ
.
MQ_TYPE_MODIFY_MCH_APP
))
{
// 商户应用修改
this
.
jmsTemplate
.
convertAndSend
(
mqTopic4ModifyMchApp
,
msg
);
}
}
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/mq/RabbitMqMessage.java
View file @
9dad80f9
...
...
@@ -53,6 +53,8 @@ public class RabbitMqMessage extends MqCommonService {
channelOrderQuery
(
msg
);
}
else
if
(
sendType
.
equals
(
CS
.
MQ
.
MQ_TYPE_PAY_ORDER_MCH_NOTIFY
))
{
payOrderMchNotify
(
msg
);
}
else
if
(
sendType
.
equals
(
CS
.
MQ
.
MQ_TYPE_MODIFY_MCH_APP
))
{
// 商户应用修改
directModifyMchApp
(
msg
);
}
}
...
...
@@ -91,6 +93,12 @@ public class RabbitMqMessage extends MqCommonService {
});
}
/** 发送商户应用修改消息 **/
public
void
directModifyMchApp
(
String
msg
)
{
rabbitTemplate
.
convertAndSend
(
CS
.
DIRECT_EXCHANGE
,
CS
.
MQ
.
TOPIC_MODIFY_MCH_APP
,
msg
);
}
/** 接收 查单消息 **/
@RabbitListener
(
queues
=
CS
.
MQ
.
QUEUE_CHANNEL_ORDER_QUERY
)
public
void
receiveChannelOrderQuery
(
String
msg
)
{
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/mq/RocketMqMessage.java
View file @
9dad80f9
...
...
@@ -57,6 +57,8 @@ public class RocketMqMessage extends MqCommonService {
channelOrderQuery
(
msg
);
}
else
if
(
sendType
.
equals
(
CS
.
MQ
.
MQ_TYPE_PAY_ORDER_MCH_NOTIFY
))
{
payOrderMchNotify
(
msg
);
}
else
if
(
sendType
.
equals
(
CS
.
MQ
.
MQ_TYPE_MODIFY_MCH_INFO
))
{
// 商户信息修改
modifyMchInfo
(
msg
);
}
}
...
...
@@ -127,4 +129,17 @@ public class RocketMqMessage extends MqCommonService {
mqReceiveCommon
.
payOrderMchNotify
(
msg
);
}
}
/** 发送商户信息修改消息 **/
public
void
modifyMchInfo
(
String
msg
)
{
sendMsg
(
msg
,
CS
.
MQ
.
TOPIC_MODIFY_MCH_INFO
);
}
public
void
sendMsg
(
String
msg
,
String
group
)
{
// 这里的分组和消息名称未做区分
rocketMQTemplate
.
getProducer
().
setProducerGroup
(
group
);
this
.
rocketMQTemplate
.
convertAndSend
(
group
,
msg
);
}
}
jeepay-payment/src/main/resources/templates/channel/alipay/isvsubMchAuth.ftl
0 → 100644
View file @
9dad80f9
<!
DOCTYPE
html>
<
html
>
<
head
>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>授权提示</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/layui/2.4.3/css/layui.css">
<style>
.mainDiv1
{
color
:
lightseagreen
;
text-align
:
center
;
margin-top
:
50
px
;
}
.mainDiv2
{
text-align
:
center
;
margin-top
:
10
px
;
}
.mainDiv3
{
text-align
:
center
;
margin-top
:
200
px
;
}
.mainDivTitle
{
text-align
:
center
;
margin-top
:
20
px
;
color
:
orangered
}
</style>
</
head
>
<
body
>
<#
if
errMsg != null >
<div class="mainDiv1 layui-fluid">
<i class="layui-icon" style="font-size:100px; color:orangered">ဇ</i>
</div>
<div class="mainDiv2 layui-fluid">
<span style="font-size:16px; ">授权失败</span>
<div class="mainDivTitle layui-fluid">
<span style="font-size:14px">错误提示:$
{
errMsg
!''
}
</span>
</div>
</div>
<#
else
>
<div class="mainDiv1 layui-fluid">
<i class="layui-icon" style="font-size:100px;">စ</i>
</div>
<div class="mainDiv2 layui-fluid">
<span style="font-size:16px">授权成功</span>
</div>
<#if isAlipaySysAuth>
<div class="mainDivTitle layui-fluid">
<span style="font-size:14px">提示: 请联系您的 [服务商]
登录支付宝管理平台获取 [<span style="font-style: oblique">授权Token</span>] 进行下一步配置!</span>
</div>
</#if>
</#
if
>
<
div
class="mainDiv3 layui-fluid">
<a class="layui-btn layui-btn-primary closeBtn">关闭页面</a>
</
div
>
<
script
src="https://cdn.staticfile.org/layui/2.4.3/layui.min.js"></script>
<
script
>
layui.use(['jquery'], function()
{
layui
.$
(
".closeBtn"
)
.click
(
function
(){
var
ua
=
navigator
.userAgent.toLowerCase
()
;
if
(
ua
.match
(
/
M
icroMessenger
/
i
)
==
"micromessenger"
)
{
W
eixinJSBridge
.call
(
'
closeWindow
'
)
;
}
else
if
(
ua
.indexOf
(
"alipay"
)
!=
-1
){
A
lipayJSBridge
.call
(
'
closeWebview
'
)
;
}
else
{
window
.close
()
;
}
})
;
}
);
</
script
>
</
body
>
</
html
>
jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/PayInterfaceConfigService.java
View file @
9dad80f9
...
...
@@ -127,6 +127,7 @@ public class PayInterfaceConfigService extends ServiceImpl<PayInterfaceConfigMap
.
isNotNull
(
PayInterfaceConfig:
:
getIfParams
));
for
(
PayInterfaceConfig
config
:
isvConfigList
)
{
config
.
addExt
(
"mchType"
,
mchInfo
.
getType
());
isvPayConfigMap
.
put
(
config
.
getIfCode
(),
config
);
}
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment