18、QR二维码的生成、微信支付第三方平台、统一下单思路说明、微信支付二维码实现思路、支付查询流程、对接订单生成逻辑&生成支付单完成支付、付款成功后修改订单状态&支付单状态

使用微信支付,需要新建两个模块,一个是interface,另一个是service。
在service中引入微信支付的依赖。

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

QR二维码的生成

使用生成二维码的qrious二维码插件来生成二维码。
在这里插入图片描述
经过删减之后的index中生成二维码的代码如下:(单单只生成一个二维码)

<!DOCTYPE html>
<html lang="zh">
<head>

</head>
<body>	
		    <img id="qrious">
	
	<script src="./dist/umd/qrious.js"></script>
	<script>
	  (function() {
	    var qr = window.qr = new QRious({
	      element: document.getElementById('qrious'),
	      size: 200,			//这里是二维码的大小
	      value: 'http://www.baidu.com',	   		//这里输入二维码
		  level:'H'				//容错度,最低是L,最高是H(一共四级别)
	    })
	  })()
	</script>
</body>
</html>

微信支付第三方平台

参考的是微信支付的第三方api。

统一下单思路说明

微信支付二维码实现思路

在cart-web模块中的controller中实现生成二维码的方法,传递需要的参数
在这里插入图片描述
在这里使用了定义的searchPayLogFromRedis方法来查找支付订单,获取订单中的金额
实现类如下:(在生成商品订单的同时生成了支付订单,同时存入了redis)
在这里插入图片描述

1、在interface中创建生成二维码的方法在这里插入图片描述
2、在impl中实现方法
需要将配置文件中的信息引入到当前类中
在这里插入图片描述
通过httpclient请求来发送获取支付链接的请求,请求中包括微信支付的api所有需要的参数数据,将所有参数封装到requestMap中通过httpclient发送。

注意:微信支付api需要的数据是xml格式。需要使用微信提供的工具类来将map转成xml。

然后再通过工具类获取微信支付的返回值,返回的数据是xml格式,需要手动转成map,使用的还是微信提供的工具类。

返回的数据中包含很多信息。我们只需要三个:一个是商户订单号(我们传入的),一个是支付金额(我们传入的),还有一个是返回的支付链接。所以再次封装一个responseMap,存放这三个数据,返回。


    @Override                       //商户订单号,支付金额
    public Map createNative(String out_trade_no, String total_fee) {
        try {
            //通过我们的common模块发送http请求,请求地址是微信支付提供的支付链接请求的接口地址
            HttpClientUtil clientUtil = new HttpClientUtil("https://api.mch.weixin.qq.com/pay/unifiedorder");
            Map requestMap = new HashMap<>();
            requestMap.put("appid", appid);
            requestMap.put("mch_id", mch_id);
            requestMap.put("nonce_str", WXPayUtil.generateNonceStr());
            requestMap.put("body", "商城中的商品");
            requestMap.put("out_trade_no", out_trade_no);
            requestMap.put("total_fee", total_fee);
            requestMap.put("spbill_create_ip","127.0.0.1");
            requestMap.put("notify_url", notifyurl);
            requestMap.put("trade_type", "NATIVE");
            //微信工具类可以将map转xml的String,采用api:generateSignedXml
            String requestXml = WXPayUtil.generateSignedXml(requestMap, partnerkey);
            clientUtil.setXmlParam(requestXml);
            //需要设置请求的协议
            clientUtil.setHttps(true);

            //发送请求
            clientUtil.post();

            //接收参数
            String content = clientUtil.getContent();

            System.out.println("========================收到的xml"+content);

            Map<String, String> map = WXPayUtil.xmlToMap(content);

            //map中的数据太多,我们暂时不需要,并且我们需要返回订单号和支付金额,所以再封装一个新的map。
            Map responseMap = new HashMap<>();
            responseMap.put("out_trade_no", out_trade_no);
            responseMap.put("total_fee", total_fee);
            responseMap.put("code_url", map.get("code_url"));

            return responseMap;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

返回到前端页面上(cart-web),在js文件中完成二维码的生成,在页面绑定名字为“qrious”的id。

在这里插入图片描述

在这里插入图片描述

支付查询状态(查询是否支付了)

前端在生成二维码的方法下调用查询状态的方法。
在这里插入图片描述
前端js文件controller中的查询状态的方法中,通过返回值判断状态,并做处理。
在这里插入图片描述
在后端(pay_service)模块中创建对应方法

还是使用微信支付的查询状态的api。
使用的依然是httpclientutil工具类。
将需要的参数封装到map中,转成xml格式发送请求。
接收到的xml转成map直接返回即可。

 @Override
    public Map queryPayStatus(String out_trade_no) {
        try {
            HttpClientUtil clientUtil = new HttpClientUtil("https://api.mch.weixin.qq.com/pay/orderquery");
            Map requestMap = new HashMap<>();
            requestMap.put("appid", appid);
            requestMap.put("mch_id", mch_id);
            requestMap.put("nonce_str", WXPayUtil.generateNonceStr());
            requestMap.put("out_trade_no", out_trade_no);

            //微信工具类可以将map转xml的String,采用api:generateSignedXml
            String requestXml = WXPayUtil.generateSignedXml(requestMap, partnerkey);
            clientUtil.setXmlParam(requestXml);
            //需要设置请求的协议
            clientUtil.setHttps(true);
            //发送请求
            clientUtil.post();
            //接收参数
            String content = clientUtil.getContent();
            Map<String, String> responseMap = WXPayUtil.xmlToMap(content);
            //直接将微信返回的内容往前端返
            return responseMap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

在调用这个方法的controller(cart-web)中,使用死循环的方式,间断查询订单状态。

    @RequestMapping("/queryPayStatus")
    public Result queryPayStatus(String out_trade_no){

        int timer = 1;  //定义一个记录次数

        while(true){
            Map map = weixinPayService.queryPayStatus(out_trade_no);
            if (map== null){
                return  new Result(false,"付款失败!");
            }
            //这里是微信支付的状态,参考微信支付api
            if("SUCCESS".equals(map.get("trade_state"))){
                weixinPayService.updateOrderStatus(out_trade_no, map.get("transaction_id").toString());
                return new Result(true,"付款成功!");
            }


            //设置支付超出时间
            if(timer > 6){  //判断30秒内需要完成支付动作,否则超时
                System.out.println("=支付超时=");//如果关闭了客户端页面,显示完支付超时后,就不再执行查询订单状态操作,不会一直死循环
                return  new Result(false,"timeout");
            }

            timer ++;

            try {
                Thread.sleep(5000);//5秒查询一个订单状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

测试支付结果的演示

对接订单生成逻辑&生成支付单完成支付

思路说明:在生成商品订单时,要同时生成支付订单。(在order_service模块中的OrderServiceImpl类中的add方法中)

  //生成支付单
        TbPayLog payLog = new TbPayLog();
        payLog.setTradeState("0");  //0未支付  1已支付
        payLog.setUserId(order.getUserId());
        payLog.setTotalFee((long) (payMoney * 100));  //支付总金额
        payLog.setPayType("1");   //1.微信支付,2.货到付款
        payLog.setCreateTime(new Date());
        //去掉左括号和右括号,最好也去掉中间的空格
        payLog.setOrderList(ordersIds.toString().replace("[", "").replace("]", "").replaceAll(" ", ""));
        payLog.setOutTradeNo(idWorker.nextId() + ""); //支付单号采用uuid
        //保存数据库
        payLogMapper.insert(payLog);

        //将payLog对象存到redis中
        redisTemplate.boundHashOps("payLog").put(payLog.getUserId(), payLog);

付款成功后修改订单状态&支付单状态

在这里插入图片描述
传入两个参数,一个是订单id,一个是微信流水号,修改支付单的状态,再修改订单的状态(注意修改每一个商品的状态)。最后清空redis中的缓存。

   @Override
    public void updateOrderStatus(String out_trade_no, String transaction_id) {
        //1.修改支付日志状态
        TbPayLog payLog = payLogMapper.selectByPrimaryKey(out_trade_no);
        payLog.setPayTime(new Date());
        payLog.setTradeState("1");//已支付
        payLog.setTransactionId(transaction_id);//微信内部交易号
        payLogMapper.updateByPrimaryKey(payLog);

        //2.修改本次支付所关联订单状态为"2"已付款
        String orderList = payLog.getOrderList();//获取订单号列表
        String[] orderIds = orderList.split(",");//获取订单号数组
        //状态:1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭,7、待评价
        for(String orderId:orderIds){
            TbOrder order = orderMapper.selectByPrimaryKey( Long.parseLong(orderId) );
            if(order!=null){
                order.setStatus("2");//已付款
                order.setPaymentTime(new Date());//订单更新付款时间
                orderMapper.updateByPrimaryKey(order);
            }
        }
        //3.清除redis中保存的支付缓存数据
        redisTemplate.boundHashOps("payLog").delete(payLog.getUserId());
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生成微信支付二维码,可以使用微信支付官方提供的接口,以下是基于 Spring Boot 的简实现步骤: 1. 引入相关依赖 ```xml <dependency> <groupId>com.github.wxpay</groupId> <artifactId>wxpay-sdk</artifactId> <version>3.0.9</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> ``` 2. 配置微信支付相关参数 ```java @Configuration public class WxPayConfig { // 微信支付分配的商户号 @Value("${wxpay.mchId}") private String mchId; // 微信支付分配的终端设备号 @Value("${wxpay.deviceInfo}") private String deviceInfo; // 微信支付分配的公众账号ID @Value("${wxpay.appId}") private String appId; // 微信支付分配的商户密钥 @Value("${wxpay.key}") private String key; // 微信支付异步通知地址 @Value("${wxpay.notifyUrl}") private String notifyUrl; // 微信支付统一下单接口地址 @Value("${wxpay.unifiedOrderUrl}") private String unifiedOrderUrl; // 微信支付查询订单接口地址 @Value("${wxpay.orderQueryUrl}") private String orderQueryUrl; // 微信支付关闭订单接口地址 @Value("${wxpay.closeOrderUrl}") private String closeOrderUrl; // 微信支付申请退款接口地址 @Value("${wxpay.refundUrl}") private String refundUrl; // 微信支付查询退款接口地址 @Value("${wxpay.refundQueryUrl}") private String refundQueryUrl; // 微信支付下载对账接口地址 @Value("${wxpay.downloadBillUrl}") private String downloadBillUrl; // 微信支付交易保障接口地址 @Value("${wxpay.reportUrl}") private String reportUrl; // 签名类型 private final String SIGN_TYPE = "MD5"; // 连接超时时间 private final int CONNECT_TIMEOUT = 5000; // 读取超时时间 private final int READ_TIMEOUT = 10000; // 微信支付API证书路径 @Value("${wxpay.certPath}") private String certPath; // 微信支付API证书密码 @Value("${wxpay.certPassword}") private String certPassword; /** * 初始化微信支付配置 */ @Bean public WXPay wxPay() throws Exception { WXPayConfigImpl config = new WXPayConfigImpl(); config.setAppID(appId); config.setMchID(mchId); config.setKey(key); config.setDeviceInfo(deviceInfo); config.setSignType(SIGN_TYPE); config.setUnifiedOrderUrl(unifiedOrderUrl); config.setOrderQueryUrl(orderQueryUrl); config.setCloseOrderUrl(closeOrderUrl); config.setRefundUrl(refundUrl); config.setRefundQueryUrl(refundQueryUrl); config.setDownloadBillUrl(downloadBillUrl); config.setReportUrl(reportUrl); return new WXPay(config, notifyUrl, true, true); } /** * 微信支付配置类 */ class WXPayConfigImpl extends WXPayConfig { private String appId; private String mchId; private String key; private String deviceInfo; private String signType; private String unifiedOrderUrl; private String orderQueryUrl; private String closeOrderUrl; private String refundUrl; private String refundQueryUrl; private String downloadBillUrl; private String reportUrl; public void setAppID(String appId) { this.appId = appId; } public void setMchID(String mchId) { this.mchId = mchId; } public void setKey(String key) { this.key = key; } public void setDeviceInfo(String deviceInfo) { this.deviceInfo = deviceInfo; } public void setSignType(String signType) { this.signType = signType; } public void setUnifiedOrderUrl(String unifiedOrderUrl) { this.unifiedOrderUrl = unifiedOrderUrl; } public void setOrderQueryUrl(String orderQueryUrl) { this.orderQueryUrl = orderQueryUrl; } public void setCloseOrderUrl(String closeOrderUrl) { this.closeOrderUrl = closeOrderUrl; } public void setRefundUrl(String refundUrl) { this.refundUrl = refundUrl; } public void setRefundQueryUrl(String refundQueryUrl) { this.refundQueryUrl = refundQueryUrl; } public void setDownloadBillUrl(String downloadBillUrl) { this.downloadBillUrl = downloadBillUrl; } public void setReportUrl(String reportUrl) { this.reportUrl = reportUrl; } @Override public String getAppID() { return appId; } @Override public String getMchID() { return mchId; } @Override public String getKey() { return key; } @Override public InputStream getCertStream() { try { return new FileInputStream(new File(certPath)); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } @Override public int getHttpConnectTimeoutMs() { return CONNECT_TIMEOUT; } @Override public int getHttpReadTimeoutMs() { return READ_TIMEOUT; } @Override public String getDeviceInfo() { return deviceInfo; } @Override public String getSignType() { return signType; } @Override public String getUnifiedOrderUrl() { return unifiedOrderUrl; } @Override public String getOrderQueryUrl() { return orderQueryUrl; } @Override public String getCloseOrderUrl() { return closeOrderUrl; } @Override public String getRefundUrl() { return refundUrl; } @Override public String getRefundQueryUrl() { return refundQueryUrl; } @Override public String getDownloadBillUrl() { return downloadBillUrl; } @Override public String getReportUrl() { return reportUrl; } } } ``` 3. 调用微信支付统一下单接口,获取支付二维码 ```java @RestController @RequestMapping("/wxpay") public class WxPayController { @Autowired private WXPay wxPay; /** * 生成微信支付二维码 * * @param orderId 订单ID * @param amount 支付金额 * @return 二维码图片Base64编码字符串 */ @GetMapping("/qrcode") public String generateQrCode(@RequestParam("order_id") String orderId, @RequestParam("amount") int amount) { try { Map<String, String> data = new HashMap<>(); data.put("body", "xxxx"); // 商品描述 data.put("out_trade_no", orderId); // 订单号 data.put("total_fee", String.valueOf(amount)); // 支付金额,位为分 data.put("spbill_create_ip", "127.0.0.1"); // 发起支付的客户端IP data.put("notify_url", "http://localhost/wxpay/notify"); // 支付成功的回调地址 data.put("trade_type", "NATIVE"); // 交易类型,JSAPI:公众号支付;NATIVE:扫码支付;APP:APP支付 data.put("product_id", orderId); // 商品ID,trade_type=NATIVE时必填 // 调用微信支付统一下单接口 Map<String, String> result = wxPay.unifiedOrder(data); String return_code = result.get("return_code"); String result_code = result.get("result_code"); if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) { String codeUrl = result.get("code_url"); // 生成二维码 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); BitMatrix bitMatrix = new MultiFormatWriter().encode(codeUrl, BarcodeFormat.QR_CODE, 300, 300); MatrixToImageWriter.writeToStream(bitMatrix, "png", outputStream); byte[] bytes = outputStream.toByteArray(); return Base64.getEncoder().encodeToString(bytes); } else { String err_code_des = result.get("err_code_des"); throw new RuntimeException(err_code_des); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } } } ``` 以上就是基于 Spring Boot 的微信支付二维码生成的简实现了。需要注意的是,微信支付二维码的有效期为2小时,超过时间后需要重新生成

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值