前言
最近在做公司项目时使用websocket在支付回调接口中刷新页面状态时,忽然想起今年毕业做毕业设计的时候,做的是一个电商系统,那么支付是必不可少的,当时还没有听说过websocket,去网上查阅资料,申请支付宝或者微信授权肯定是不现实的,还搞了很久的沙箱支付,现在想想真是傻,没有早一点接触到websocket,至于websocket是一门怎样的技术我们在此不做过多介绍,大家可自行查阅资料,我们这里只是简单写一个demo来做模拟支付,没什么太大的技术含量,但对于在校的想实现一个模拟支付的你确是雪中送炭!
准备
首先新建一个简单的springboot项目,当然了,普通的web项目也是可以的,这里敏捷开发
引入jar包,不是用maven的就只能下载jar进行导入了
<!-- websocket包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
<!-- 二维码相关包 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
</dependency>
下面两个jar包是二维码相关的jar包,二维码的工具类此文就不再贴出了,在 【二维码】——生成二维码并转为base64中有代码贴出。
Websocket服务器
/**
* 开启WebSocket支持
* @author zhengkai
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
/** webSocket服务器
* @author WangZhiJun
*/
@ServerEndpoint("/ws/{sid}")
@Component
public class WebSocketServer {
private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class);
/**
* 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
*/
private static int onlineCount = 0;
/**
* concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
*/
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
/*
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
private Session session;
/**
* 接收sid
*/
private String sid="";
/**
* 连接建立成功调用的方法*/
@OnOpen
public void onOpen(Session session,@PathParam("sid") String sid) {
this.session = session;
//加入set中
webSocketSet.add(this);
//在线数加1
addOnlineCount();
logger.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount());
this.sid=sid;
try {
sendMessage("连接成功");
} catch (IOException e) {
logger.error("websocket IO异常");
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
//从set中删除
webSocketSet.remove(this);
//在线数减1
subOnlineCount();
logger.info("有一连接关闭!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session) {
logger.info("收到来自窗口"+sid+"的信息:"+message);
//群发消息
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
logger.error("发生错误");
error.printStackTrace();
}
/**
* 实现服务器主动推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 群发自定义消息
* */
public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {
logger.info("推送消息到窗口"+sid+",推送内容:"+message);
for (WebSocketServer item : webSocketSet) {
try {
//这里可以设定只推送给这个sid的,为null则全部推送
if(sid==null) {
item.sendMessage(message);
}else if(item.sid.equals(sid)){
item.sendMessage(message);
}
} catch (IOException e) {
continue;
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
实现
将订单的信息存储在二维码中,二维码生成请查看【二维码】——生成二维码并转为base64
/**
* @author: WangZhiJun
* @create: 2019-09-21 12:31
**/
@RestController
@RequestMapping("/api/v1/order")
public class OrderController {
/**
* 系统内生成支付二维码接口
*/
@GetMapping(value = "/payOrder")
public Result pay(@RequestParam String orderId) {
Result result = new Result();
String orderName = "XXSuperMarketPay";
BigDecimal orderMoney = new BigDecimal(100);
System.out.println("订单"+orderId+orderName+"需支付:"+orderMoney+"元");
String wxPayUrl = "http://192.168.1.101:8080/wx/pay/pay?orderId="+orderId+"&orderName="+orderName+"&orderMoney="+orderMoney;
System.out.println("生成支付二维码链接:"+wxPayUrl);
result.setData(BarCodeUtils.getImage2Base64String(BarCodeUtils.generateBarcodeWithoutWhite(wxPayUrl, Color.BLACK)));
return result;
}
/**
* 结果实体类,这里为简化开发写为内部类,且只有一个data属性
*/
class Result {
String data;
public void setData(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
}
演示
1.首先访问页面,生成二维码并连接上socket
2.用手机扫描二维码,这里要保证手机和电脑在同一个局域网内
注意:OrderController中的IP和pay.html中的IP要保持一致,且是电脑当前所在局域网的IP,电脑和手机连接同一WiFi或者手机给电脑开热点
最后放一下项目结构图:
可以在博主主页项目部分进行测试模拟支付
非技术的路过。
后悔就后悔在我Java学得太烂,目前之后hello world
哈哈,没事啊,慢慢来
java大佬@(真棒)
额,老哥太客气了
look look 回访
哈哈,欢迎光临