完成 支付宝子商户的二维码自主授权;
This commit is contained in:
parent
2b7a2cbdee
commit
9dad80f948
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
<!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: 50px;}
|
||||
.mainDiv2 {text-align:center; margin-top: 10px;}
|
||||
.mainDiv3 {text-align:center; margin-top: 200px;}
|
||||
.mainDivTitle {text-align:center; margin-top: 20px; 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(/MicroMessenger/i)=="micromessenger") {
|
||||
WeixinJSBridge.call('closeWindow');
|
||||
} else if(ua.indexOf("alipay")!=-1){
|
||||
AlipayJSBridge.call('closeWebview');
|
||||
}
|
||||
else{
|
||||
window.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue