添加支付测试ctrl; 添加webSocket监听推送到端程序;
This commit is contained in:
parent
ff0623cced
commit
0758a0da23
|
|
@ -95,6 +95,12 @@
|
|||
<artifactId>jeepay-sdk-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- webSocket -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<!-- 作为可执行jar -->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* 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.mch.ctrl.paytest;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.JeepayClient;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApp;
|
||||
import com.jeequan.jeepay.core.entity.MchPayPassage;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.ApiRes;
|
||||
import com.jeequan.jeepay.exception.JeepayException;
|
||||
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
|
||||
import com.jeequan.jeepay.model.PayOrderCreateReqModel;
|
||||
import com.jeequan.jeepay.request.PayOrderCreateRequest;
|
||||
import com.jeequan.jeepay.response.PayOrderCreateResponse;
|
||||
import com.jeequan.jeepay.service.impl.MchAppService;
|
||||
import com.jeequan.jeepay.service.impl.MchPayPassageService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
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.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/*
|
||||
* 支付测试类
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/6/22 9:43
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/paytest")
|
||||
public class PaytestController extends CommonCtrl {
|
||||
|
||||
@Autowired private MchAppService mchAppService;
|
||||
@Autowired private MchPayPassageService mchPayPassageService;
|
||||
@Autowired private SysConfigService sysConfigService;
|
||||
|
||||
/** 查询商户对应应用下支持的支付方式 **/
|
||||
@PreAuthorize("hasAuthority('ENT_MCH_PAY_TEST_PAYWAY_LIST')")
|
||||
@GetMapping("/payways/{appId}")
|
||||
public ApiRes payWayList(@PathVariable("appId") String appId) {
|
||||
|
||||
Set<String> payWaySet = new HashSet<>();
|
||||
mchPayPassageService.list(
|
||||
MchPayPassage.gw().select(MchPayPassage::getWayCode)
|
||||
.eq(MchPayPassage::getMchNo, getCurrentMchNo())
|
||||
.eq(MchPayPassage::getAppId, appId)
|
||||
.eq(MchPayPassage::getState, CS.PUB_USABLE)
|
||||
).stream().forEach(r -> payWaySet.add(r.getWayCode()));
|
||||
|
||||
return ApiRes.ok(payWaySet);
|
||||
}
|
||||
|
||||
|
||||
/** 调起下单接口 **/
|
||||
@PreAuthorize("hasAuthority('ENT_MCH_PAY_TEST_DO')")
|
||||
@PostMapping("/payOrders")
|
||||
public ApiRes doPay() {
|
||||
|
||||
//获取请求参数
|
||||
String appId = getValStringRequired("appId");
|
||||
Long amount = getRequiredAmountL("amount");
|
||||
String mchOrderNo = getValStringRequired("mchOrderNo");
|
||||
String wayCode = getValStringRequired("wayCode");
|
||||
|
||||
// 前端明确了支付参数的类型 payDataType
|
||||
String payDataType = getValString("payDataType");
|
||||
String authCode = getValString("authCode");
|
||||
|
||||
|
||||
MchApp mchApp = mchAppService.getById(appId);
|
||||
if(mchApp == null || mchApp.getState() != CS.PUB_USABLE || !mchApp.getAppId().equals(appId)){
|
||||
throw new BizException("商户应用不存在或不可用");
|
||||
}
|
||||
|
||||
PayOrderCreateRequest request = new PayOrderCreateRequest();
|
||||
PayOrderCreateReqModel model = new PayOrderCreateReqModel();
|
||||
request.setBizModel(model);
|
||||
|
||||
model.setMchNo(getCurrentMchNo()); // 商户号
|
||||
model.setAppId(appId);
|
||||
model.setMchOrderNo(mchOrderNo);
|
||||
model.setWayCode(wayCode);
|
||||
model.setAmount(amount);
|
||||
model.setCurrency("CNY");
|
||||
model.setClientIp(getClientIp());
|
||||
model.setSubject(getCurrentMchNo() + "商户联调");
|
||||
model.setBody(getCurrentMchNo() + "商户联调");
|
||||
model.setNotifyUrl(sysConfigService.getDBApplicationConfig().getMchSiteUrl() + "/api/anon/paytestNotify/payOrder"); //回调地址
|
||||
|
||||
//设置扩展参数
|
||||
JSONObject extParams = new JSONObject();
|
||||
if(StringUtils.isNotEmpty(payDataType)) extParams.put("payDataType", payDataType.trim());
|
||||
if(StringUtils.isNotEmpty(authCode)) extParams.put("authCode", authCode.trim());
|
||||
model.setChannelExtra(extParams.toString());
|
||||
|
||||
JeepayClient jeepayClient = new JeepayClient(sysConfigService.getDBApplicationConfig().getPaySiteUrl(), mchApp.getAppSecret());
|
||||
|
||||
try {
|
||||
PayOrderCreateResponse response = jeepayClient.execute(request);
|
||||
if(response.getCode() != 0){
|
||||
throw new BizException(response.getMsg());
|
||||
}
|
||||
return ApiRes.ok(response.get());
|
||||
} catch (JeepayException e) {
|
||||
throw new BizException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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.mch.ctrl.paytest;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.MchApp;
|
||||
import com.jeequan.jeepay.core.model.OriginalRes;
|
||||
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
|
||||
import com.jeequan.jeepay.mch.websocket.server.WsPayOrderServer;
|
||||
import com.jeequan.jeepay.service.impl.MchAppService;
|
||||
import com.jeequan.jeepay.service.impl.MchPayPassageService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.util.JeepayKit;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* 支付测试 - 回调函数
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/6/22 14:22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/anon/paytestNotify")
|
||||
public class PaytestNotifyController extends CommonCtrl {
|
||||
|
||||
@Autowired private MchAppService mchAppService;
|
||||
|
||||
@RequestMapping("/payOrder")
|
||||
public void payOrderNotify() throws IOException {
|
||||
|
||||
//请求参数
|
||||
JSONObject params = getReqParamJSON();
|
||||
|
||||
String mchNo = params.getString("mchNo");
|
||||
String appId = params.getString("appId");
|
||||
String sign = params.getString("sign");
|
||||
MchApp mchApp = mchAppService.getById(appId);
|
||||
if(mchApp == null || !mchApp.getMchNo().equals(mchNo)){
|
||||
response.getWriter().print("app is not exists");
|
||||
return;
|
||||
}
|
||||
|
||||
params.remove("sign");
|
||||
if(!JeepayKit.getSign(params, mchApp.getAppSecret()).equalsIgnoreCase(sign)){
|
||||
response.getWriter().print("sign fail");
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject msg = new JSONObject();
|
||||
msg.put("state", params.getIntValue("state"));
|
||||
msg.put("errCode", params.getString("errCode"));
|
||||
msg.put("errMsg", params.getString("errMsg"));
|
||||
|
||||
//推送到前端
|
||||
WsPayOrderServer.sendMsgByOrderId(params.getString("payOrderId"), msg.toJSONString());
|
||||
|
||||
response.getWriter().print("SUCCESS");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.mch.websocket.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
/*
|
||||
* 开启WebSocket支持
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/6/22 12:57
|
||||
*/
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
}
|
||||
|
|
@ -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.mch.websocket.server;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.websocket.OnClose;
|
||||
import javax.websocket.OnError;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/*
|
||||
* WebSocket服务类
|
||||
* /ws/payOrder/{訂單ID}/{客戶端自定義ID}
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/6/22 12:57
|
||||
*/
|
||||
@ServerEndpoint("/api/anon/ws/payOrder/{payOrderId}/{cid}")
|
||||
@Component
|
||||
public class WsPayOrderServer {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(WsPayOrderServer.class);
|
||||
|
||||
//当前在线客户端 数量
|
||||
private static int onlineClientSize = 0;
|
||||
|
||||
// payOrderId 与 WsPayOrderServer 存储关系, ConcurrentHashMap保证线程安全
|
||||
private static Map<String, Set<WsPayOrderServer>> wsOrderIdMap = new ConcurrentHashMap<>();
|
||||
|
||||
//与某个客户端的连接会话,需要通过它来给客户端发送数据
|
||||
private Session session;
|
||||
|
||||
//客户端自定义ID
|
||||
private String cid = "";
|
||||
|
||||
//支付订单号
|
||||
private String payOrderId = "";
|
||||
|
||||
/**
|
||||
* 连接建立成功调用的方法
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("payOrderId") String payOrderId, @PathParam("cid") String cid) {
|
||||
|
||||
try {
|
||||
//设置当前属性
|
||||
this.cid = cid;
|
||||
this.payOrderId = payOrderId;
|
||||
this.session = session;
|
||||
|
||||
Set<WsPayOrderServer> wsServerSet = wsOrderIdMap.get(payOrderId);
|
||||
if(wsServerSet == null) wsServerSet = new CopyOnWriteArraySet<>();
|
||||
wsServerSet.add(this);
|
||||
wsOrderIdMap.put(payOrderId, wsServerSet);
|
||||
|
||||
addOnlineCount(); //在线数加1
|
||||
logger.info("cid[{}],payOrderId[{}]连接开启监听!当前在线人数为{}", cid, payOrderId, onlineClientSize);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("ws监听异常cid[{}],payOrderId[{}]", cid, payOrderId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接关闭调用的方法
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose() {
|
||||
|
||||
Set wsSet = wsOrderIdMap.get(this.payOrderId);
|
||||
wsSet.remove(this);
|
||||
if(wsSet.isEmpty()) wsOrderIdMap.remove(this.payOrderId);
|
||||
|
||||
subOnlineCount(); //在线数减1
|
||||
logger.info("cid[{}],payOrderId[{}]连接关闭!当前在线人数为{}", cid, payOrderId, onlineClientSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param session
|
||||
* @param error
|
||||
*/
|
||||
@OnError
|
||||
public void onError(Session session, Throwable error) {
|
||||
logger.error("ws发生错误", error);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现服务器主动推送
|
||||
*/
|
||||
public void sendMessage(String message) throws IOException {
|
||||
this.session.getBasicRemote().sendText(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单ID,推送消息
|
||||
* 捕捉所有的异常,避免影响业务。
|
||||
* @param payOrderId
|
||||
*/
|
||||
public static void sendMsgByOrderId(String payOrderId, String msg) {
|
||||
|
||||
try {
|
||||
logger.info("推送ws消息到浏览器, payOrderId={},msg={}", payOrderId, msg);
|
||||
|
||||
|
||||
Set<WsPayOrderServer> wsSet = wsOrderIdMap.get(payOrderId);
|
||||
if(wsSet == null || wsSet.isEmpty()){
|
||||
logger.info("payOrderId[{}] 无ws监听客户端", payOrderId);
|
||||
return ;
|
||||
}
|
||||
|
||||
for (WsPayOrderServer item : wsSet) {
|
||||
try {
|
||||
item.sendMessage(msg);
|
||||
} catch (Exception e) {
|
||||
logger.info("推送设备消息时异常,payOrderId={}, cid={}", payOrderId, item.cid, e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.info("推送消息时异常,payOrderId={}", payOrderId, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized int getOnlineClientSize() {
|
||||
return onlineClientSize;
|
||||
}
|
||||
|
||||
public static synchronized void addOnlineCount() {
|
||||
onlineClientSize++;
|
||||
}
|
||||
|
||||
public static synchronized void subOnlineCount() {
|
||||
onlineClientSize--;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue