Java 微信当面付生成二维码支付实现

技术标签: 二维码支付  # 支付Demo  java  微信支付  

1. maven依赖

        <!-- 微信支付sdk -->
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.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>

2. 准备工作

a. WxPayConfig 配置类

在第一篇关于微信支付文章里有写到:
Java 微信支付统一下单、支付回调、订单查询实现
这里直接用了

b. 二维码图片本地存储位置

file.qrCode是在配置文件里写到的二维码图片本地存储位置,
在这里插入图片描述

c. 配置虚拟路径

需要在项目里配置虚拟路径
参考SpringBoot文件虚拟路径配置
以及图片开放访问,有权限限制的项目需要这一步,项目不同开放的方式也不同,举例:
在这里插入图片描述
如果是分布式项目的话,集成MinIO来存储图片会更好,参考
Java MinIO文件上传返回访问路径及访问配置

3. 代码

a. QrCodeUtil

(同支付宝二维码支付)

import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Hashtable;

public class QrCodeUtil {
    
    /**
     * 生成包含字符串信息的二维码图片
     * @param outputStream 文件输出流路径
     * @param content 二维码携带信息
     */
    public static boolean createQrCode(OutputStream outputStream, String content) throws WriterException, IOException{
    
        //设置二维码纠错级别MAP
        Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
        hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);  // 矫错级别
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        //创建比特矩阵(位矩阵)的QR码编码的字符串
        BitMatrix byteMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, 900, 900, hintMap);
        // 使BufferedImage勾画QRCode  (matrixWidth 是行二维码像素点)
        int matrixWidth = byteMatrix.getWidth();
        BufferedImage image = new BufferedImage(matrixWidth-200, matrixWidth-200, BufferedImage.TYPE_INT_RGB);
        image.createGraphics();
        Graphics2D graphics = (Graphics2D) image.getGraphics();
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, matrixWidth, matrixWidth);
        // 使用比特矩阵画并保存图像
        graphics.setColor(Color.BLACK);
        for (int i = 0; i < matrixWidth; i++){
    
            for (int j = 0; j < matrixWidth; j++){
    
                if (byteMatrix.get(i, j)){
    
                    graphics.fillRect(i-100, j-100, 1, 1);
                }
            }
        }
        return ImageIO.write(image, "JPEG", outputStream);
    }
}

b. controller


    @Value("${file.qrCode}")
    private String qrCode;

    @PreAuthorize("@el.check('anonymous')")
    @PostMapping("/wxpayPrecreate")
    public ResponseEntity wxPrecreate(HttpServletRequest request, @RequestBody Map params) throws Exception {
    
        // 保存未支付订单
        ShopOrderDTO shopOrderDTO = createOrder(params, 0);

        // 处理请求参数
        WxPayConfig wxPayConfig = new WxPayConfig(shopDeviceService);
        WXPay wxPay = new WXPay(wxPayConfig);

        Map<String,String> data = new HashMap<>();
        data.put("out_trade_no", shopOrderDTO.getId()+"");   //订单编号
        data.put("total_fee",shopOrderDTO.getAmount().toString());   //金额(单位为分) int

        data.put("spbill_create_ip", IPUtil.getIPAddress(request));
        data.put("nonce_str", WXPayUtil.generateNonceStr());   // 随机字符串小于32位
        data.put("mch_id",wxPayConfig.getMchID());
        data.put("appid",wxPayConfig.getAppID());
		
		// 这里二维码支付是区别于手机网站支付的地方
        data.put("trade_type","NATIVE");	
        
        data.put("product_id", shopOrderDTO.getId().toString());

        data.put("device_info",wxPayConfig.getDeviceInfo());
        data.put("notify_url",wxPayConfig.getNotifyUrl());
        data.put("fee_type",wxPayConfig.getFeeType());
        data.put("body",wxPayConfig.getBody());
        data.put("scene_info", wxPayConfig.getSceneInfo());

        // 生成签名
        String s = WXPayUtil.generateSignature(data, wxPayConfig.getKey());
        data.put("sign",s);

        // 发起下单请求
        logger.info("发起 WxPay 下单请求");
        Map<String, String> respData = wxPay.unifiedOrder(data);

        // 处理下单结果
        if ("SUCCESS".equals(respData.get("return_code"))){
    
            if ("SUCCESS".equals(respData.get("result_code"))) {
    
                String path = qrCode + shopOrderDTO.getId() + "WXPay.jpg";
                String httpPath = "/qrCode/" + shopOrderDTO.getId() + "WXPay.jpg";
                File file = new File(path);
                if (!file.getParentFile().exists()) {
    
                    file.getParentFile().mkdirs();
                }
                QrCodeUtil.createQrCode(new FileOutputStream(file), respData.get("code_url"));
                respData.put("qrcode", httpPath);
                respData.put("out_trade_no", shopOrderDTO.getId()+"");

                shopLogService.anonymousCreate(shopLogService.getShopLog(shopOrderDTO.getStoreId(), shopOrderDTO.getDeviceId(), "生成WxPay订单","订单编号 : " + shopOrderDTO.getId()));
                return new ResponseEntity<>(respData, HttpStatus.OK);
            } else {
    
                shopLogService.anonymousCreate(shopLogService.getShopLog(shopOrderDTO.getStoreId(), shopOrderDTO.getDeviceId(), "WxPay下单失败","err_code_des : " + respData.get("err_code_des")));
                throw new Exception(respData.get("err_code_des"));
            }
        } else {
    
            shopLogService.anonymousCreate(shopLogService.getShopLog(shopOrderDTO.getStoreId(), shopOrderDTO.getDeviceId(), "WxPay下单失败","return_msg : " + respData.get("err_code_des")));
            throw new Exception(respData.get("return_msg"));
        }
    }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_39159076/article/details/107707098

智能推荐

Android报表库aChartEngine系列(line chart)_weixin_30299539的博客-程序员宅基地

前言:  这几天本来打算对achartengine进行一些比较全面的讲解,不过考虑到它并不复杂,而且非常方便应用,加之官网提供了很好的demo不需要我们自己慢慢摸索。所以这将是aChartEngine库介绍的最后一篇文章了。在cnblogs上的阅读量上来看这方面的文章园友们并不是特别需要(毕竟简单嘛),但是为了保证aChartEngine介绍的完整性,还是坚持写完这最后一篇相关的介绍。如...

用户故事与敏捷方法笔记---用户角色建模_愿做一颗朴实无华的螺丝钉的博客-程序员宅基地

如有错误或问题请留言文章目录前言文章概览1. 用户角色2. 角色建模的步骤3. 额外的技术4. 如果有真实的用户在讨论现场,那么用户角色建模依然是必要步骤。总结前言以用户为中心的设计和交互设计的规则使我们懂得,在编写前识别用户角色和虚构人物有很多好处。这篇文章记录了用户角色,角色建模,角色映射和虚构人物并学习用这些条件编写更好的故事。接下来的所有理论都会伴随一个实际的例子,而所有例子都基于一个假想的职位发布和搜索网站。文章概览1. 用户角色 a. 首先要明白用户角色并不是一个具体的用

团队项目——测量小助手个人一周详细计划表_weixin_30888027的博客-程序员宅基地

日期需完成项目项目估算、预计时间2018/11/15水准测量(二等、三等、四等)表格设计难度:一般;估时:1h2018/11/16计算界面设计难度:简单;估时:0.5h2018/11/17二等测量计算程序编写难度:一般;估时:6...

问题 J: Stone Game(模拟)_ZAX1的博客-程序员宅基地

原题地址#include&lt;cstdio&gt;#include&lt;cstring&gt;#include&lt;algorithm&gt;#include&lt;iostream&gt;#include&lt;string&gt;#include&lt;vector&gt;#include&lt;stack&gt;#include&lt;bitset&gt;#in...

充电书目推荐_1_Secrets_Of_Self_Made_Millionaires(待更新)_weixin_30571465的博客-程序员宅基地

Secrets_Of_Self_Made_Millionaires_Notes《自己成为百万富翁的秘密》 ·为什么选择读这本书:   首先这是一本英文读物,本人英语水平有限,但兴趣使然。其次,这是一本我在B站关注的UP主(来自马来西亚的清华学生李瑾唐,在年仅19岁的时候已经月入5位数,大概是2W RMB一个月)推荐的,感觉有着深深的价值感,也加入一同打天下的队列吧! ·想要收获的东...

渲染流程_小伏羲的博客-程序员宅基地

(注:【D3D11游戏编程】学习笔记系列由CSDN作者BonChoix所写,转载请注明出处:http://blog.csdn.net/BonChoix,谢谢~)        3D图形学研究的基本内容,即给定场景的描述,包括各个物体的材质、纹理、坐标等,照相机的位置及朝向,光源等信息,计算其最终在二维的光栅化显示器上对应的显示结果。从最初的场景描述到最终的显示结果,这整个过程就是在

随便推点

android 上传图片给js,安卓中HTML5图片上传实例详解_weixin_39975900的博客-程序员宅基地

应用的平台环境:安卓webview;涉及的技术点:(1) :在开发中,安卓webview默认点击无法调用文件选择与相机拍照(其他的设备ios等浏览器没有此问题),需要让安卓开发同学在代码调整即可;(2) 点击选择图片后如何展示在页面上呢?很多开发人员估计是直接获取 this.value,这是错误的,不可行。有2个API可以现实,new FileReader与window.URL.createOb...

linux命令忘了,Linux考试易忘命令_weixin_39863616的博客-程序员宅基地

这是为了考试而做的笔记mv命令可以移动可以改名mv a /test //移动a到test文件夹下mv a b //把a改名为b软链接和硬链接的创建ln -s profile a //profile文件创建一个软链接aln profile b //profile文件创建一个硬链接b查找文件find newfile //查找名字为newfile的文件对c...

vue项目解决打包后index.html里面的引入文件没有引号问题总结_木屋x的博客-程序员宅基地

vue项目解决打包后index.html里面的引入文件没有引号问题总结1.业务需求:vue项目打包后,index.html里面的引入文件没有引号,导致打包后的项目不能正常运行。2.解决方案:在项目找到vue.config.js文件,然后添加如下代码: chainWebpack: config =&gt; { config.plugin('html').tap(args =&gt; { args[0].minify=false return ar

在 angular6 中自定义 webpack 配置_程树上的程序猿的博客-程序员宅基地_angular6 webpack

在 angular6 中自定义 webpack 配置我们已经使用 angular6 开发了一套后台管理系统,且体量日益增大,为了优化打包速度,想从 webpack 着手。但是Angular Cli 6 禁用了webpack的自定义配置,官方似乎并未提供自定义配置webpack的方法;在此之前,可以使用ng eject把默认的webpack提取到代码中,进行自定义,但是 angular6 不支持了,只能使用 第三方库来实现。1. 探索阶段–成功在 angular6 中使用 自定义 webpack 配置

2020.11.27 比赛总结&题解合集_C20190406Panda_hu的博客-程序员宅基地

题目终于又回归正常了…没有像之前一样卡常卡空间背模板了…

python爬虫,爬取猫眼电影2(xpath和bs4)_JECK_ケーキ的博客-程序员宅基地

接着上面的。使用xpath提取信息,虽然python很多库,比如beautifulsoup,也有很多功能,比如查找节点,添加删除节点。但是个人感觉对爬虫来说,最重要的还是提取信息,当然,顺利的提取信息的前提是你得掌握好这些库的用法,不过有些功能确实一辈子也不会用到。对爬虫来说,就是提取文本,获取属性,这两个。还是打开页面,这里我直接读入本地的文件,知识为了简单起见。不在requests了。我们自己做网页爬虫的时候,还是需要借助一些工具的。比如xpath。我经常用的就是 浏览器的xpath hel

推荐文章

热门文章

相关标签