教你用Java在个人电脑上实现微信扫码支付
作者:记或往 发布时间:2023-07-22 20:52:15
标签:Java,微信,扫码支付
Java实现PC微信扫码支付
做一个电商网站支付功能必不可少,那我们今天就来盘一盘微信支付。
微信支付官方网站
业务流程:
支付服务开发前提准备:
1.SDK下载:SDK
2.利用外网穿透,获得一个外网域名:natapp
3.APPID,商户ID,密钥注:上面三个参数需要自己申请
开发阶段:
导入依赖:
<!--eureka的客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- http客户端 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</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>
<!--websocket 服务器主动发送请求给websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
微信支付配置类
/**
* 微信支付配置
*/
public class MyWXConfig extends WXPayConfig {
//账户的APPID
@Override
public String getAppID() {
return "wx307113892f15a42e";
}
//商户ID
@Override
public String getMchID() {
return "1508236581";
}
//秘钥
@Override
public String getKey() {
return "HJd7sHGHd6djgdgFG5778GFfhghghgfg";
}
@Override
public InputStream getCertStream() {
return null;
}
@Override
public IWXPayDomain getWXPayDomain() {
return new WXPayDomain();
}
class WXPayDomain implements IWXPayDomain{
@Override
public void report(String domain, long elapsedTimeMillis, Exception ex) {
}
@Override
public DomainInfo getDomain(WXPayConfig config) {
return new DomainInfo("api.mch.weixin.qq.com",true);
}
}
}
websocket配置类:
package com.cloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
wensocket工具类:
package com.cloud.config;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
/**
* WebSocket工具类
* ServerEndpoint配置websocket的名称,和前台页面对应
*/
@ServerEndpoint(value = "/eshop")
@Component
public class WebSocketUtils {
//WebSocket的对话对象
private static Session session = null;
//建立和前台页面连接后的回调方法
@OnOpen
public void onOpen(Session session){
System.out.println("建立连接"+session);
//给连接赋值
WebSocketUtils.session = session;
}
@OnMessage
public void onMessage(String message, Session session){
System.out.println("收到前台消息:" + message);
}
@OnClose
public void onClose(Session session) throws IOException {
System.out.println("连接关闭");
session.close();
}
/**
* 向前台发消息
* @param message
* @throws IOException
*/
public static void sendMessage(String message) throws IOException {
System.out.println("发送消息:" + message);
if( WebSocketUtils.session != null) {
WebSocketUtils.session.getBasicRemote().sendText(message);
}
}
}
service:
package com.cloud.service;
import com.cloud.utils.MyWXConfig;
import com.cloud.utils.WXPay;
import com.cloud.utils.WXPayUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 微信支付Service
*/
@Service
public class PayService {
/**
* 下单
* @param goodsId 商品id
* @param price 价格
* @return 二维码的URL
*/
public Map<String, String> makeOrder(String goodsId, Long price) throws Exception {
//创建支付对象
MyWXConfig config = new MyWXConfig();
WXPay wxPay = new WXPay(config);
Map<String,String> map = new HashMap<>();
map.put("appid",config.getAppID());
map.put("mch_id",config.getMchID());
map.put("device_info","WEB");
map.put("nonce_str", UUID.randomUUID().toString().replace("-",""));
map.put("body","商城购物");
String tradeNo = UUID.randomUUID().toString().replace("-", "");
map.put("out_trade_no", tradeNo);
map.put("fee_type","CNY");
map.put("total_fee",String.valueOf(price));
map.put("notify_url","http://68dhbz.natappfree.cc/pay/rollback"); //微信对商户后台的回调接口
map.put("trade_type","NATIVE");
map.put("product_id",goodsId);
//执行统一下单
Map<String, String> result = wxPay.unifiedOrder(map);
System.out.println("result:"+result);
//保存订单号
result.put("trade_no",tradeNo);
return result;
}
/**
* 生成二维码
* @param url
* @param response
*/
public void makeQRCode(String url, HttpServletResponse response){
//通过支付链接生成二维码
HashMap<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
hints.put(EncodeHintType.MARGIN, 2);
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 200, 200, hints);
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", response.getOutputStream());
System.out.println("创建二维码完成");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 检查订单状态
* @param tradeNo
* @return
* @throws Exception
*/
public String checkOrder(String tradeNo) throws Exception {
MyWXConfig config = new MyWXConfig();
String str =
"<xml>"+
"<appid>"+config.getAppID()+"</appid>"+
"<mch_id>"+config.getMchID()+"</mch_id>"+
"<nonce_str>"+UUID.randomUUID().toString().replace("-","")+"</nonce_str>"+
"<out_trade_no>"+tradeNo+"</out_trade_no>"+
"<sign>5E00F9F72173C9449F802411E36208734B8138870ED3F66D8E2821D55B317078</sign>"+
"</xml>";
WXPay pay = new WXPay(config);
Map<String,String> map = WXPayUtil.xmlToMap(str);
Map<String, String> map2 = pay.orderQuery(map);
String state = map2.get("trade_state");
System.out.println("订单"+tradeNo+",状态"+state);
return state;
}
}
controller:
package com.cloud.controller;
import com.cloud.config.WebSocketUtils;
import com.cloud.service.PayService;
import com.cloud.utils.WXPayUtil;
import org.apache.tomcat.util.http.fileupload.util.Streams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* @author yanglihu
*/
@RestController
@RequestMapping("/pay")
public class PayController {
@Autowired
private PayService payService;
private String tradeNo;
/**
* 二维码生成
*/
@GetMapping("/code")
public void qrcode(@RequestParam("goodsId")String goodsId,
@RequestParam("price")Long price,
HttpServletResponse response){
try {
Map<String,String> map = payService.makeOrder(goodsId, price);
payService.makeQRCode(map.get("code_url"),response);
System.out.println("生成订单号:" + map.get("trade_no"));
tradeNo = map.get("trade_no");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 支付后通知
*/
@PostMapping("/rollback")
public void notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
//获得微信传来的xml字符串
String str = Streams.asString(request.getInputStream());
//将字符串xml转换为Map
Map<String, String> map = WXPayUtil.xmlToMap(str);
//读取订单号
String no = map.get("out_trade_no");
//模拟修改商户后台数据库订单状态
System.out.println("更新订单状态:"+no);
//给微信发送消息
response.getWriter().println("<xml>\n" +
" <return_code><![CDATA[SUCCESS]]></return_code>\n" +
" <return_msg><![CDATA[OK]]></return_msg>\n" +
" <appid><![CDATA["+map.get("appid")+"]]></appid>\n" +
" <mch_id><![CDATA["+map.get("mch_id")+"]]></mch_id>\n" +
" <nonce_str><![CDATA["+map.get("nonce_str")+"]]></nonce_str>\n" +
" <openid><![CDATA["+map.get("openid")+"]]></openid>\n" +
" <sign><![CDATA["+map.get("sign")+"]]></sign>\n" +
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
" <prepay_id><![CDATA["+map.get("prepay_id")+"]]></prepay_id>\n" +
" <trade_type><![CDATA[NATIVE]]></trade_type>\n" +
"</xml>");
WebSocketUtils.sendMessage("ok");
}
/**
* 检查订单状态
*/
@PostMapping("checkOrder")
public String checkOrder() throws Exception {
System.out.println("trade_no:" + tradeNo);
if(StringUtils.isEmpty(tradeNo)){
return null;
}
String success = payService.checkOrder(tradeNo);
System.out.println("check:" + success);
return success;
}
}
支付页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<title>乐优商城--微信支付页</title>
<link rel="icon" href="/assets/img/favicon.ico" rel="external nofollow" rel="external nofollow" >
<link rel="stylesheet" type="text/css" href="css/webbase.css" rel="external nofollow" rel="external nofollow" />
<link rel="stylesheet" type="text/css" href="css/pages-weixinpay.css" rel="external nofollow" />
</head>
<body>
<!--页面顶部白条条,由js动态加载-->
<script type="text/javascript" src="plugins/jquery/jquery.min.js"></script>
<div class="top"></div>
<script type="text/javascript">$(".top").load("shortcut.html");</script>
<div class="checkout py-container pay">
<div class="checkout-steps">
<div class="fl weixin">微信支付</div>
<div class="fl sao">
<p class="red">二维码已过期,刷新页面重新获取二维码。</p>
<div class="fl code">
<img src="http://api.eshop.com/pay/code?goodsId=11&price=1" alt="">
<div class="saosao">
<p>请使用微信扫一扫</p>
<p>扫描二维码支付</p>
</div>
</div>
<div class="fl phone">
</div>
</div>
<div class="clearfix"></div>
<p><a href="pay.html" rel="external nofollow" target="_blank">> 其他支付方式</a></p>
</div>
</div>
</div>
<script type="text/javascript" src="js/plugins/jquery/jquery.min.js"></script>
<script type="text/javascript" src="js/plugins/jquery.easing/jquery.easing.min.js"></script>
<script type="text/javascript" src="js/plugins/sui/sui.min.js"></script>
<script type="text/javascript" src="js/widget/nav.js"></script>
<script type="text/javascript">
$(function(){
$("ul.payType li").click(function(){
$(this).css("border","2px solid #E4393C").siblings().css("border-color","#ddd");
})
})
</script>
<script>
var websocket = null;
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
websocket = new WebSocket("ws://localhost:8888/eshop");
}
else{
alert('Not support websocket')
}
//接收到消息的回调方法
websocket.onmessage = function(event){
console.log(event.data);
if(event.data == "ok"){
location.href = "paysuccess.html";
}
}
</script>
</body>
</html>
成功页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<title>乐优商城--支付页-成功</title>
<link rel="icon" href="/assets/img/favicon.ico" rel="external nofollow" rel="external nofollow" >
<link rel="stylesheet" type="text/css" href="css/webbase.css" rel="external nofollow" rel="external nofollow" />
<link rel="stylesheet" type="text/css" href="css/pages-paysuccess.css" rel="external nofollow" />
</head>
<body>
<!--head-->
<!--页面顶部白条条,由js动态加载-->
<script type="text/javascript" src="plugins/jquery/jquery.min.js"></script>
<div class="top"></div>
<script type="text/javascript">$(".top").load("shortcut.html");</script>
<div class="cart py-container">
<!--主内容-->
<div class="paysuccess">
<div class="success">
<h3><img src="img/_/right.png" width="48" height="48">恭喜您,支付成功啦!</h3>
<div class="paydetail">
<p>支付方式:微信支付</p>
<p>支付金额:¥1006.00元</p>
<p class="button"><a href="home-index.html" rel="external nofollow" class="sui-btn btn-xlarge btn-danger">查看订单</a> <a href="index.html" rel="external nofollow" class="sui-btn btn-xlarge ">继续购物</a></p>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="js/plugins/jquery/jquery.min.js"></script>
<script type="text/javascript" src="js/plugins/jquery.easing/jquery.easing.min.js"></script>
<script type="text/javascript" src="js/plugins/sui/sui.min.js"></script>
<script type="text/javascript" src="components/ui-modules/nav/nav-portal-top.js"></script>
</body>
</html>
java后台显示
来源:https://blog.csdn.net/xiaozhuzhuyang/article/details/117789776


猜你喜欢
- Android自定义控件属性详细介绍1. reference:参考某一资源ID。
- 本文实例为大家分享了Java实现聊天室界面的具体代码,供大家参考,具体内容如下服务器端:package Server; impor
- 上篇文章给大家介绍了在idea中将创建的java web项目部署到Tomcat中的过程图文详解,可以参考下,本文给大家继续介绍如何在IDEA
- 本文需要解决的问题笔者最近正在做一个项目,里面需要用到 Android Notification 机制来实现某些特定需求。我正好通过这个机会
- pom.xml<dependency> <groupId>org.springframework.bo
- java.math包提供了java中的数学类。包括基本的浮点库、复杂运算以及任意精度的数据运算提供用于执行任意精度整数算法 (BigInte
- 通常我们遇到的图片缩放需求,都是图片基于屏幕自适应后,进行缩放和移动,且图片最小只能是自适应的大小。最近遇到一个需求,要求图片只能在屏幕内缩
- 一、前言若使用本机存储来存放文件资源核心实现过程:上传文件,保存文件(本地磁盘)返回文件HTTP访问服务器路径给前端,进行效果展示二、储备服
- 本文实例为大家分享了C#实现航班预订的具体代码,供大家参考,具体内容如下连接数据库using System;using System.Col
- 前言在一个高并发系统中对流量的把控是非常重要的,当巨大的流量直接请求到我们的服务器上没多久就可能造成接口不可用,不处理的话甚至会造成整个应用
- 先从本地把图片上传到服务器,然后根据URL把头像处理成圆形头像。因为上传图片用到bmob的平台,所以要到bmob(http://www.bm
- 本文实例为大家分享了android序列化过程Parcelable的具体代码,供大家参考,具体内容如下直接上代码:注释都写的很清楚了。publ
- 一、配置文件内容mybatis.xml就是Mybatis的全局配置文件。全局配置文件需要在头部使用约束文件。<?xml version
- 一、什么是Java事务通常的观念认为,事务仅与数据库相关。  
- 经常遇到的问题在实际得开发过程中,我们经常会遇到以下场景,我们后端请求某个接口后获取到得数据,不希望将所有字段都返回给前端,那么我们需要封装
- 本实例使用用户和订单的例子做说明: 一个用户可以有多个订单, 一个订单只对应一个用户。(其中应用到注释)1.代码的结构2. 建表语
- 一、简单介绍Unity 游戏实例开发集合,使用简单易懂的方式,讲解常见游戏的开发实现过程,方便后期类似游戏开发的借鉴和复用。本节介绍,Fly
- cin的返回值今天在用STL时用到while(cin>>s1>>a>>s2>>b)这样的语句
- 在Android中,线程内部或者线程之间进行信息交互时经常会使用消息,这些基础的东西如果我们熟悉其内部的原理,将会使我们容易、更好地架构系统
- 1、cs代码public void DownFile(string filePath ,string fileName ){ // file