微信支付的简单使用以及前端的显示

一、首先在项目中引入wxpay的依赖

     <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>

二、创建Wxpay的实例对象 并对参数进行设置

            HashMap<String, String> map = new HashMap<>();
           //商品描述
            map.put("body","商品名字");
            //交易号
            map.put("out_trade_no","交易号 可以是订单号 或者其他的");
            //交易币种
            map.put("fee_type","CNY");
            //交易金额  以分为单位  这里为了测试 用1分
            map.put("total_fee","1");
            //交易类型
            map.put("trade_type","NATIVE");
            //支付完成时的回调方法接口
            map.put("notify_url","/pay/success");

            WXPay wxPay = new WXPay(new WxPayConfig());
            //发送支付请求
            Map<String, String> resp = wxPay.unifiedOrder(map);

创建对象的过程中我们又被迫的需要创建交易成功后信息回调的接口以及微信支付中的商家信息配置

  • 商家信息配置
package com.llf.Config;

import com.github.wxpay.sdk.WXPayConfig;

import java.io.InputStream;

/**
创建wxpay config类实现wxpayconfig接口 重写其中的部分方法
其中用到的三个参数 都是在微信支付申请成功之后 微信官方给予的
**/
public class WxPayConfig implements WXPayConfig {
    @Override
    public String getAppID() {
        // 返回的是商家的appId
        return "wx632c8f211f8122c6";
    }

    @Override
    public String getMchID() {
        // 返回的是商家的id
        return "1497984412";
    }

    @Override
    public String getKey() {
        //返回的是商家的密钥
        return "sbNCm1JnevqI36LrEaxFwcaT0hkGxFnC";
    }

    @Override
    public InputStream getCertStream() {
        return null;
    }

    @Override
    public int getHttpConnectTimeoutMs() {
        return 0;
    }

    @Override
    public int getHttpReadTimeoutMs() {
        return 0;
    }
}

  • 信息回调的接口

    package com.llf.Controller;
    
    import io.swagger.annotations.Api;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/pay")
    @Api(value = "微信支付方法回调",tags = "微信支付成功的方法回调")
    public class PayController {
    
        /**
         * 微信支付成功的回调方法
         */
            @PostMapping("/success")
            public void success(){
    
            }
    }
    
    

    一切信息都设置好以后 当我们访问成功后 微信官方会给我们返回一个map信息集合

    Map<String, String> resp = wxPay.unifiedOrder(map);
/**
这个resp 就是返回的信息集合  其中有一个code_url的属性 就是进行支付的具体地址 可以将这个地址一起响应给前端  前端通过二维码生成 将链接生成二维码 完成支付
**/
				// 将支付的url传给前端
 			orderInfo.put("payUrl",resp.get("code_url"));
            resultVO=new ResultVO(ResStatus.OK,"提交订单成功",orderInfo);

三、前端接收到支付链接 将链接生成二维码

生成二维码 我们需要用到两个js文件的帮助 一个是jquary 一个是qrcode 其中qrcode就是生成二维码的工具,

前端通过localStorage.setItem("orderInfo",JSON.stringify(存储信息的对象));方法将参数传送到支付页面 ,支付页面使用let jsonstr = localStorage.getItem("orderInfo");方法 来获取支付需要的url

<!--引入js文件之后,首先设置一个div  用来作为显示二维码区域的盒子-->
	<div id="div1">
			<div id="payQrcodeDiv" style="width: 200px; height: 200px;"></div>
	</div>

// 接着对二维码进行模板渲染 由于我们使用vue进行数据渲染  因此需要创建mounted 钩子函数 实现渲染
mounted:function (){
    // 定位到我们设置的div
	let qrCode = new QRCode($("#payQrcodeDiv")[0],{
		height:200,
		width:200
					});
    //生成二维码 将支付的url放到这个方法中 
		qrCode.makeCode(this.orderInfo.payUrl);
				}

在这里插入图片描述

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">

		<title>购物车页面</title>

		<link href="static/css/amazeui.css" rel="stylesheet" type="text/css" />
		<link href="static/css/demo.css" rel="stylesheet" type="text/css" />
		<link href="static/css/cartstyle.css" rel="stylesheet" type="text/css" />
		<link href="static/css/optstyle.css" rel="stylesheet" type="text/css" />

		<script type="text/javascript" src="static/js/jquery.js"></script>

	</head>

	<body>
		<div id="container">
			<!--顶部导航条 -->
			<div class="am-container header">
			<ul class="message-l">
				<div class="topMessage">
					<div class="menu-hd">
						<a href="#" target="_top" class="h">亲,请登录</a>
						<a href="#" target="_top">免费注册</a>
					</div>
				</div>
			</ul>
			<ul class="message-r">
				<div class="topMessage home">
					<div class="menu-hd"><a href="index.html" target="_top" class="h">商城首页</a></div>
				</div>
				<div class="topMessage my-shangcheng">
					<div class="menu-hd MyShangcheng"><a href="#" target="_top"><i class="am-icon-user am-icon-fw"></i>个人中心</a></div>
				</div>
				<div class="topMessage mini-cart">
					<div class="menu-hd"><a id="mc-menu-hd" href="shopcart.html" target="_top"><i class="am-icon-shopping-cart  am-icon-fw"></i><span>购物车</span><strong id="J_MiniCartNum" class="h">0</strong></a></div>
				</div>
				<div class="topMessage favorite">
					<div class="menu-hd"><a href="#" target="_top"><i class="am-icon-heart am-icon-fw"></i><span>收藏夹</span></a></div>
			</ul>
			</div>

			<!--悬浮搜索框-->

			<div class="nav white">
				<div class="logo"><img src="static/images/logo.png" /></div>
				<div class="logoBig">
					<li><img src="static/images/logobig.png" /></li>
				</div>

				<div class="search-bar pr">
					<a name="index_none_header_sysc" href="#"></a>
					<form>
						<input id="searchInput" name="index_none_header_sysc" type="text" placeholder="搜索" autocomplete="off">
						<input id="ai-topsearch" class="submit am-btn" value="搜索" index="1" type="submit">
					</form>
				</div>
			</div>

			<div class="clear"></div>

		
			<div style="background: lightgrey; height: 600px; margin-top: 40px; padding: 15px;">
				<div style="width:65%; background: white; height: 540px; margin: auto; padding-left: 50px;">
 ========================================================================================                   关键渲染区域
				<p>&nbsp;</p>
				<p>&nbsp;</p>
				<h3>订单编号:{{orderInfo.orderId}}</h3>
				<p>&nbsp;</p>
				<h3>订单金额:¥ {{orderInfo.totalPrice}}</h3>
				<hr/>
					<!--存放二维码的div-->
				<div id="div1">
					<div id="payQrcodeDiv" style="width: 200px; height: 200px;"></div>
				</div>
 ================================================================================                   
				</div>
			</div>
		
		
			
		<!--操作页面-->
			<div class="theme-popover-mask"></div>
			<div class="theme-popover">
				<div class="theme-span"></div>
				<div class="theme-poptit h-title">
					<a href="javascript:;" title="关闭" class="close">×</a>
				</div>
				<div class="theme-popbod dform">
					<form class="theme-signin" name="loginform" action="" method="post">

						<div class="theme-signin-left">

							<li class="theme-options">
								<div class="cart-title">颜色:</div>
								<ul>
									<li class="sku-line selected">12#川南玛瑙<i></i></li>
									<li class="sku-line">10#蜜橘色+17#樱花粉<i></i></li>
								</ul>
							</li>
							<li class="theme-options">
								<div class="cart-title">包装:</div>
								<ul>
									<li class="sku-line selected">包装:裸装<i></i></li>
									<li class="sku-line">两支手袋装(送彩带)<i></i></li>
								</ul>
							</li>
							<div class="theme-options">
								<div class="cart-title number">数量</div>
								<dd>
									<input class="min am-btn am-btn-default" name="" type="button" value="-" />
									<input class="text_box" name="" type="text" value="1" style="width:30px;" />
									<input class="add am-btn am-btn-default" name="" type="button" value="+" />
									<span  class="tb-hidden">库存<span class="stock">1000</span></span>
								</dd>

							</div>
							<div class="clear"></div>
							<div class="btn-op">
								<div class="btn am-btn am-btn-warning">确认</div>
								<div class="btn close am-btn am-btn-warning">取消</div>
							</div>

						</div>
						<div class="theme-signin-right">
							<div class="img-info">
								<img src="static/images/kouhong.jpg_80x80.jpg" />
							</div>
							<div class="text-info">
								<span class="J_Price price-now">¥39.00</span>
								<span id="Stock" class="tb-hidden">库存<span class="stock">1000</span></span>
							</div>
						</div>

					</form>
				</div>
			</div>
		<!--引导 -->
		<div class="navCir">
			<li><a href="home.html"><i class="am-icon-home "></i>首页</a></li>
			<li><a href="sort.html"><i class="am-icon-list"></i>分类</a></li>
			<li class="active"><a href="shopcart.html"><i class="am-icon-shopping-basket"></i>购物车</a></li>	
			<li><a href="person/index.html"><i class="am-icon-user"></i>我的</a></li>					
		</div>
		</div>
		<script type="text/javascript" src="static/js/jquery-1.9.min.js" ></script>
		<script type="text/javascript" src="static/js/Cookie_Utils.js" ></script>
		<script type="text/javascript" src="static/js/vue.js" ></script>
		<script type="text/javascript" src="static/js/axios.min.js" ></script>
		<script type="text/javascript" src="static/js/qrcode.min.js" ></script>
		<script type="text/javascript">

			let vm = new Vue({
				el:"#container",
				data:{
					orderInfo:{}
				},
				created:function(){
					let jsonstr = localStorage.getItem("orderInfo");
					if(jsonstr!=null){
						localStorage.removeItem("orderInfo");
					}
					this.orderInfo = eval("("+jsonstr+")");
				},
				//二维码渲染要在模板渲染之后 因此需要用到mounted 钩子函数
				mounted:function (){
					let qrCode = new QRCode($("#payQrcodeDiv")[0],{
						height:200,
						width:200
					});
					qrCode.makeCode(this.orderInfo.payUrl);
				}

			});
		</script>
		
		
	</body>

</html>

四、后端接收微信支付中心反馈的信息

前端付款成功后 微信会向我们设置的信息回调接口发送反馈信息 ,我们要接收这些信息 进行处理

微信如何访问我们?

​ 因为我们的程序在本地部署,因此微信是不能直接访问的,所以我们需要借助Ngrok来进行内网穿透,只有这样我们才能接收到微信反馈给我们的信息。

​ Ngrok的具体使用方法 可以参考Ngrok内网穿透这篇博客,里面介绍了使用方法

Ngrok配置完成后 把我们设置的信息回调地址转换成 Ngrok生成的地址

 map.put("notify_url","/pay/success"); 换成
 map.put("notify_url","http://0565-2408-8220-201b-ca00-488f-47a9-9a54-6964.ngrok.io/pay/success");

地址设置完成之后,对我们的回调接口进行设置

接收微信信息 并进行处理

package com.llf.Controller;

import com.github.wxpay.sdk.WXPayUtil;
import com.llf.Service.ServiceImpl.OrdersServiceImpl;
import com.llf.WebStocket.WebSocketServer;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/pay")
@Api(value = "微信支付方法回调",tags = "微信支付成功的方法回调")
public class PayController {
    @Autowired
    private OrdersServiceImpl ordersService;

    /**
     * 微信支付成功的回调方法
     */
        @RequestMapping("/success")
        public String success(HttpServletRequest request) throws  Exception{
            //获得响应流
            ServletInputStream inputStream = request.getInputStream();
            //将响应的流文件转换成byte类型
            byte[] bs = new byte[1024];
            int len=-1;
            StringBuilder stringBuilder = new StringBuilder();
            while((len=inputStream.read(bs))!=-1){
                stringBuilder.append(new String(bs,0,len));
            }
            //得到xml类型的响应流
            String s = stringBuilder.toString();
            //使用帮助类将xml文件还原为map文件
            Map<String, String> map = WXPayUtil.xmlToMap(s);
            //如果支付成功
            if(map!=null&&"success".equalsIgnoreCase(map.get("result_code"))){
                //修改订单状态为2 已支付
                String orderId=map.get("out_trade_no");
                int i = ordersService.updateStatusByOrderId(map.get("out_trade_no"), 2);

               

               //如果i<0  表示支付状态改变失败 微信则会继续通知 如果改变成功 即告诉微信平台 已接收回调信息
                if (i>0){
                    Map<String, String> resp = new HashMap<>();
                    //响应微信平台 响应码
                    resp.put("return_code","success");
                    //响应信息
                    resp.put("return_msg","OK");
                    //响应的商家id
                    resp.put("appid",map.get("appid"));
                    //结果信息
                    resp.put("result_code","success");
                    return WXPayUtil.mapToXml(resp);
                }

            }
            return  null;

        }
}

五、前端付款成功进行提示

前端付款成功后,我们需要进行支付结果提示,当付款成功后 我们应该显示付款成功的提示。那应该如何实现呢?

方法一、因为付款成功后 该订单的状态会变成2,那么我们设置一个定时任务 每隔1秒钟访问一次后端接口 知道得到该订单的状态为2时 再清除这个定时任务

优点:实现简单 前端设置定时任务 后端写接口 就可以完成

缺点:当并发量足够大的时候,每个用户每一秒钟都对该接口进行访问 加大服务器的访问量 容易使服务器崩溃

方法二、使用webSocket 让前端进入支付页面之后 就与后端建立一个长连接 当前端付款成功后 后端通过webSocket向前端发送消息 告诉前端支付成功 前端进行支付页面内容的改变

优点:对服务器的访问压力小 一次支付只需要访问一次就行

缺点:相较于方法一 实施起来较麻烦

方法一实现

<div id="div1">
    // 通过v-if 判断状态的值 进行不同效果的显示
	<div id="payQrcodeDiv" style="width: 200px; height: 200px;" v-if="status==1"></div>
	<div v-else><span>支付成功</span></div>
</div>	


//设置定时任务 一秒钟访问一次后端接口 直到支付状态为已支付 弊端是当并发量够多时,对后端接口访问量会很大
				let i=setInterval(function (){
						axios({
							url:baseUrl+"orders/status/"+orderId,
							method:"get",
							headers:{
								token:getCookieValue("token")
							}
						}).then((res)=>{
							if (res.data.data==1){
								//表示未支付
								vm.status=1
							}else if (res.data.data==2){
								vm.status=2
								//状态为二 表示以完成支付 清除定时任务
								clearInterval(i);
							}
						})
					},1000)
//controller
    @GetMapping("status/{orderId}")
	public ResultVO  quarryStatusByOrderId(@PathVariable String orderId,@RequestHeader String token){
      return   ordersService.quarryStatusByOrderId(orderId);
    }

//service
   /**
     * 根据订单编号 查询订单状态
     * @param orderId
     * @return
     */
    ResultVO  quarryStatusByOrderId(String orderId);

//serviceImpl
   public ResultVO quarryStatusByOrderId(String orderId) {
        Orders orders = ordersMapper.selectById(orderId);
        if (orders!=null){
            return new ResultVO(ResStatus.OK,"success",orders.getStatus());
        }else {
            return new ResultVO(ResStatus.NO,"ERROr",null);
        }

    }

方法二实现

使用webSocket首先需要导入websocket依赖

     <!--webSocket 长连接-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
由于已经被springboot托管 因此这个依赖不需要导入版本号

配置WebSocket的conig类和服务器端

config配置类
    @Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter getServerEndpointExporter(){
        return new ServerEndpointExporter();
    }
}
Server服务端
    package com.llf.WebStocket;

import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;

@Component
//前端进行访问的地址 类似于controller的地址
@ServerEndpoint("/webSocket/{orderId}")
public class WebSocketServer {

    private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**前端发送请求建立websocket连接,就会执行@OnOpen方法**/
    @OnOpen
    public void open(@PathParam("orderId") String orderId, Session session){
        System.out.println("------------建立连接:"+orderId);
        sessionMap.put(orderId,session);
    }

    /**前端关闭页面或者主动关闭websocket连接,都会执行close**/
    @OnClose
    public void close(@PathParam("orderId") String orderId){
        sessionMap.remove(orderId);
    }

    /**当微信支付成功调用该方法 向前端通知**/
    public static void sendMsg(String orderId,String msg){
        try {
            Session session = sessionMap.get(orderId);
            session.getBasicRemote().sendText(msg);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

在回调信息接口类中引用server类 向前端进行消息推送

package com.llf.Controller;

import com.github.wxpay.sdk.WXPayUtil;
import com.llf.Service.ServiceImpl.OrdersServiceImpl;
import com.llf.WebStocket.WebSocketServer;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/pay")
@Api(value = "微信支付方法回调",tags = "微信支付成功的方法回调")
public class PayController {
    @Autowired
    private OrdersServiceImpl ordersService;

    /**
     * 微信支付成功的回调方法
     */
        @RequestMapping("/success")
        public String success(HttpServletRequest request) throws  Exception{
            //1、获得响应流
            ServletInputStream inputStream = request.getInputStream();
            //将响应的流文件转换成byte类型
            byte[] bs = new byte[1024];
            int len=-1;
            StringBuilder stringBuilder = new StringBuilder();
            while((len=inputStream.read(bs))!=-1){
                stringBuilder.append(new String(bs,0,len));
            }
            //得到xml类型的响应流
            String s = stringBuilder.toString();
            //使用帮助类将xml文件还原为map文件
            Map<String, String> map = WXPayUtil.xmlToMap(s);
            //如果支付成功
            if(map!=null&&"success".equalsIgnoreCase(map.get("result_code"))){
                //2、修改订单状态为已支付
                String orderId=map.get("out_trade_no");
                int i = ordersService.updateStatusByOrderId(map.get("out_trade_no"), 2);

                //3、向前端websocket发送信息 1表示支付成功
            		 添加这句话
                 WebSocketServer.sendMsg(orderId,"1");

               //4、如果i<0  表示支付状态改变失败 微信则会继续通知 如果改变成功 即告诉微信平台 已接收回调信息
                if (i>0){
                    Map<String, String> resp = new HashMap<>();
                    //响应微信平台 响应码
                    resp.put("return_code","success");
                    //响应信息
                    resp.put("return_msg","OK");
                    //响应的商家id
                    resp.put("appid",map.get("appid"));
                    //结果信息
                    resp.put("result_code","success");
                    return WXPayUtil.mapToXml(resp);
                }

            }
            //支付失败 状态改变失败 都返回null
            return  null;

        }
}

后端设置完成后 在前端也要进行简单设置

	//方法二、 向后端建立webSocket链接
					let socket = new WebSocket("ws://localhost:8080/webSocket/"+orderId);
					//只要后端向前端发送消息 前端就接收它
					socket.onmessage=function (event){
						let msg = event.data;
						if (msg=="1"){
							vm.status=2
						}
					}

接收到信息 进行判断 如果为1 表示支付成功 则在div中显示状态为2的效果

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: H5微信支付是指在移动端网页上集成微信支付功能,使用户可以直接在手机浏览器中完成支付操作。下面是一个H5微信支付简单示例: 首先,我们需要在页面中引入微信支付的相关JavaScript文件和CSS样式,以便使用微信支付的功能和界面。 然后,用户在填写订单信息后,点击支付按钮触发支付事件。在支付事件中,我们需要通过调用微信支付的API来获取预支付交易会话标识。 接着,我们将获取到的预支付交易会话标识发送给服务器进行签名,以确保支付请求的安全性。服务器返回签名后的数据给前端。 最后,前端使用微信支付SDK中的接口,调起微信支付界面。用户在微信支付界面中完成支付操作后,支付结果会通过回调函数返回到前端,我们可以根据支付结果进行相应的处理,如展示支付成功或失败的页面。 需要注意的是,H5微信支付接口的使用需要满足一定的条件,如商户需要先进行微信支付的相关注册及配置,获取到相应的商户号、密钥等信息。 以上就是H5微信支付简单 demo。通过集成H5微信支付功能,我们可以在移动端网页上方便地实现微信支付,为用户提供更加便捷的支付方式。 ### 回答2: H5 微信支付 Demo 是一个可以在移动端网页上使用微信支付功能的示例项目。通过该示例项目,开发者可以学习和了解如何在自己的移动网页中集成微信支付功能,并快速上线自己的移动网页应用。 在 H5 微信支付 Demo 中,主要包含以下几个步骤: 1. 创建订单:用户在移动网页上选择商品并确认购买后,网页应用将生成一个唯一的订单号,并将相关订单信息发送给服务端。 2. 统一下单:服务端通过调用微信支付接口,将上一步生成的订单信息传递给微信支付平台。平台根据接收到的信息,生成一个预支付会话标识(prepay_id)并返回给服务端。 3. 调起支付:服务端将预支付会话标识返回给移动网页,网页通过 JavaScript API 调用微信支付 SDK,发起支付请求。移动网页上将出现微信支付的界面,用户可以使用微信钱包完成支付。 4. 支付结果查询:支付完成后,微信支付平台会将支付结果通知给服务端。服务端通过查询支付结果接口,获取支付结果并返回给移动网页。移动网页根据支付结果显示支付成功或失败的页面。 在 H5 微信支付 Demo 中,开发者需要了解的主要是如何生成订单、调用微信支付接口以及处理支付结果的逻辑。通过参考该示例项目,开发者可以快速集成微信支付功能,提升移动网页应用的付款体验,以及更好地满足用户需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值