支付宝支付之SpringBoot整合支付宝创建自定义支付二维码

news2024/11/23 15:22:18

文章目录

  • 自定义支付二维码
    • pom.xml
    • application.yml
    • 自定义二维码类
    • AlipayService.java
    • AlipayServiceImpl.java
    • AlipayController.java
    • qrCode.html

自定义支付二维码

继:SpringBoot支付入门

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
    <!--
        ZXing(Zebra Crossing)核心库,提供了二维码生成和解析的基本功能
    -->
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.4.1</version>
</dependency>
<!--
    ZXing 的 JavaSE 扩展库,提供了在 Java 环境中生成和解析二维码的更高级功能,
    例如将二维码保存为图像文件、从图像文件解析二维码等。
-->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.4.1</version>
</dependency>

application.yml

spring:
  thymeleaf:
    enabled: true  # 启用Thymeleaf
    cache: false    # 禁用Thymeleaf缓存,方便开发时查看修改的效果
    prefix: classpath:/static/html/  # Thymeleaf模板文件所在目录,默认classpath:/static/html/
    suffix: .html   # Thymeleaf模板文件的后缀,默认为.html

自定义二维码类

package com.sin.demo.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * @createTime 2024/4/17 10:07
 * @createAuthor SIN
 * @use 二维码创建工具类
 */
public class QRCodeUtil {


    private static final int WIDTH = 300; // 二维码宽度
    private static final int HEIGHT = 300; // 二维码高度
    private static final String FORMAT = "png"; // 二维码格式

    /**
     * 生成二维码
     * @param text 二维码内容,一定是互联网内容,本地是无法扫的到的
     * @param filePath 二维码生成地址
     */
    public static void generateQRCode(String text, String filePath) {
        try {
            
            // 创建一个存储编码参数的 HashMap 对象
            Map<EncodeHintType, Object> hints = new HashMap<>();
            // 设置字符集为 UTF-8
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // 设置容错级别为 M
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            // 设置边距为 2
            hints.put(EncodeHintType.MARGIN, 2);

            // 使用 MultiFormatWriter 类将指定文本 text 编码为二维码矩阵
            BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);

            // 将二维码矩阵转换为 BufferedImage 对象
            BufferedImage image = toBufferedImage(bitMatrix);

            // 创建一个表示目标文件的 File 对象
            File file = new File(filePath);
            // 将 BufferedImage 对象保存为图像文件
            ImageIO.write(image, FORMAT, file);

            System.out.println("二维码已生成,保存路径:" + filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将二维码矩阵转为可视化图像
     * @param matrix
     * @return 生成BufferdImage对象,获得二维码的可视化图像
     */
    private static BufferedImage toBufferedImage(BitMatrix matrix) {
        // 获取二维码的宽和高
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        // 创建一个新的BufferedImage对象,指定宽和高,已经颜色类型
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                // 获取当前坐标 (x, y) 的像素值(true 表示黑色,false 表示白色)
                boolean pixel = matrix.get(x, y);
                // 根据像素值设置对应位置的 RGB 值,将黑色或白色像素点绘制到 BufferedImage 对象中
                int rgb = pixel ? Color.BLACK.getRGB() : Color.WHITE.getRGB();
                // 设置x,y坐标和颜色
                image.setRGB(x, y, rgb);
            }
        }
        // 返回生成的 BufferedImage 对象
        return image;
    }
}

AlipayService.java

package com.sin.demo.service;

import com.alipay.api.AlipayApiException;

/**
 * @createTime 2024/4/17 8:20
 * @createAuthor SIN
 * @use
 */
public interface AlipayService {
    /**
     * 创建支付订单
     * @param outTradeNo 订单号
     * @param totalAmount 支付金额
     * @param subject 支付标题
     * @return 返回二维码信息
     * @throws AlipayApiException
     */
    public String getgenerateQrCode(String outTradeNo,double totalAmount,String subject) throws AlipayApiException;
}

AlipayServiceImpl.java

package com.sin.demo.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.sin.demo.service.AlipayService;
import com.sin.demo.utils.QRCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @createTime 2024/4/17 8:23
 * @createAuthor SIN
 * @use
 */
@Service
@Slf4j
public class AlipayServiceImpl implements AlipayService {

    // 从配置文件中获取参数值
    @Value("${alipay.appId}")
    private String appId; // 支付宝应用ID

    @Value("${alipay.privateKey}")
    private String privateKey; // 商户应用私钥

    @Value("${alipay.publicKey}")
    private String publicKey; // 支付宝公钥

    @Value("${alipay.gatewayUrl}")
    private String gatewayUrl; // 支付宝网关URL


    @Override
    public String getgenerateQrCode(String outTradeNo, double totalAmount, String subject) throws AlipayApiException {

        // 创建支付宝客户端
        DefaultAlipayClient client = new DefaultAlipayClient(gatewayUrl, appId, privateKey, "json", "UTF-8", publicKey, "RSA2");

        // 创建预下单请求对象
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        // 设置测试业务参数
        request.setBizContent(
                "{\"out_trade_no\":\"" + outTradeNo + "\","
                        + "\"total_amount\":\"" + totalAmount + "\","
                        + "\"subject\":\"" + subject + "\"}"
        );

        // 执行预下单请求
        AlipayTradePrecreateResponse response = client.execute(request);

        // 判断预下单请求是否成功
        if (response.isSuccess()) {
            // 获取生成的支付二维码信息
            final String qrCode = response.getQrCode();
            // 打印二维码信息到控制台
            System.out.println("二维码信息:" + qrCode);
            // 记录生成支付二维码成功的日志
            log.info("生成支付二维码成功:{}", response.getBody());
            // 生成自定义二维码
            QRCodeUtil.generateQRCode(qrCode,"src/main/resources/static/image/qrcode.png");
            // 返回生成的支付二维码地址
            return "支付宝支付二维码地址:" + qrCode;
        } else {
            // 记录生成支付二维码失败的日志
            log.error("生成支付二维码失败:{}", response.getSubMsg());
            // 返回生成支付二维码失败的信息
            return "生成支付二维码失败:" + response.getSubMsg();
        }
    }
}

AlipayController.java

package com.sin.demo.controller;

import com.alipay.api.AlipayApiException;
import com.sin.demo.service.AlipayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @createTime 2024/4/17 8:28
 * @createAuthor SIN
 * @use
 */
@Controller
public class AlipayController {

    @Autowired
    private AlipayService alipayService;

    @ResponseBody
    @GetMapping("/generateQrCode/{outTradeNo}/{totalAmount}/{subject}")
    public String getGenerateQrCode(@PathVariable("outTradeNo") String outTradeNo,
                                    @PathVariable("totalAmount") double totalAmount,
                                    @PathVariable("subject")String subject) throws AlipayApiException {
        String s = alipayService.getgenerateQrCode(outTradeNo, totalAmount, subject);
        return s;
    }

    @GetMapping("/getQrCode")
    public String getQrCode(){
        return "qrCode";
    }

}

qrCode.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>支付页面</title>
</head>
<body>
<h1>支付页面</h1>
<div>
    <h2>扫描下方二维码进行支付:</h2>
    <img id="qrCode" src="../image/qrcode.png" alt="支付二维码">
</div>
</body>
</html>

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1605312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

批量人脸画口罩

网上参考的修改了一下&#xff0c;图片放在根目录&#xff0c;命名叫做1.png&#xff0c;批量人脸画口罩 这个程序的目的是为了解决人脸数据集中的特征点缺失的不足 # -*- coding: utf-8 -*- import os import numpy as np from PIL import Image, ImageFile__version__ 0.3…

前端请求404,后端保无此方法

1、微信小程序前端路径404 2、后端报无此路径 3、查看路径下对应的方法 发现忘了在list方法前加GetMapping(“/list”)&#xff0c;加上即可

中伟视界:智慧矿山智能化预警平台功能详解

矿山智能预警平台是一种高度集成化的安全监控系统&#xff0c;它能够提供实时的监控和报警功能&#xff0c;帮助企业和机构有效预防和响应潜在的安全威胁。以下是矿山智能预警平台的一些关键特性介绍&#xff1a; 报警短视频生成&#xff1a; 平台能够在检测到报警时自动生成短…

6.C++:继承

一、继承 //1.类中的保护和私有在当前类中没有差别&#xff1b; //2.在继承后的子类中有差别&#xff0c;private在子类中不可见&#xff0c;所以用protected&#xff1b; class person { public:void print(){cout << "name:" << _name << endl;c…

④【Shiro】Shiro框架进行敏感信息加密

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ ④【Shiro】Shiro框架进行敏感信息加密 实际系…

分布式调度器timer和spring task

1. Timer&#xff08;了解&#xff09; 一、Timer使用方式 Task1 public class Task1 extends TimerTask {Overridepublic void run(){System.out.println("com.aware.Task run");} } Task2 public class Task2 extends TimerTask {Overridepublic void run(){…

如何判断软件测试公司报告是否权威

在当今数字化浪潮中&#xff0c;软件测试报告已成为评估软件性能、确保用户体验、发掘潜在问题的关键所在。然而&#xff0c;面对众多软件测试公司及其纷繁复杂的报告&#xff0c;如何洞察其权威性成为一项亟待解决的任务。本文旨在探讨如何精准判别软件测试公司报告的权威性&a…

React Ant Design 简单实现如何选中图片

效果&#xff1a; 代码&#xff1a; 定义的初始值和方法 const [selected, setSelected] useState(0); // 表示当前选中的图片索引const handleClick (index) > {if (selected index) {setSelected(null); // 如果点击的是已选中的图片&#xff0c;则取消选中状态} else…

AI大模型日报#0418:Stable Diffusion 3开放API、Meta新研究让AI Agent理解物理世界

导读&#xff1a; 欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了每条资讯的摘要。标题: 微软刚发布了VASA-1 这个人工智能可以让单张图像具有生动的说话和歌唱能力 摘要: 微软发布了VASA-1人工智能&#xff0c;它能使单…

java算法day56 | 动态规划part15 ● 392.判断子序列 ● 115.不同的子序列

392.判断子序列 动规五部曲&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的字符串t&#xff0c;相同子序列的长度为dp[i][j]。确定递推公式 在确定递推公式的时候&#xff0c;…

显示msvcp140.dll丢失要如何解决?这5种方法高效修复msvcp140.dll

msvcp140.dll是Microsoft Visual C Redistributable软件包中的一个文件&#xff0c;主要用于支持使用C编程语言编写的软件的正常运行。如果你的电脑出现缺少msvcp140.dll的错误消息&#xff0c;可能会影响到某些程序的启动和运行。然而&#xff0c;不必过度担心&#xff0c;因为…

iText 5

依赖 implementation com.itextpdf:itextpdf:5.5.13.3implementation com.itextpdf:itext-asian:5.2.0implementation com.alibaba:fastjson:1.2.83compileOnly org.projectlombok:lombok:1.18.22annotationProcessor "org.projectlombok:lombok:1.18.22"测试 impor…

找不到api-ms-win-crt-runtime-l1-1-0.dll文件5种解决方法

在日常使用计算机的过程中&#xff0c;我们时常会遭遇各类意想不到的问题&#xff0c;其中之一就是“api-ms-win-crt-runtime-l1-1-0.dll丢失”。这个错误通常发生在Windows操作系统中&#xff0c;它表示一个动态链接库文件丢失或损坏。这个问题可能会导致某些应用程序无法正常…

【Vue脚手架】

初始化脚手架 如果下载缓慢请配置npm淘宝镜像&#xff1a; npm config set registry http://registry.npm.taobao.org 全局安装vue脚手架&#xff1a; vue/clinpm install -g vue/cli 1. 创建项目使用命令 vue create xxx 注&#xff1a;后面有选择安装版本&#xff0c;请注意选…

授权协议OAuth 2.0之除了授权码许可还有什么授权流程?

写在前面 源码 。 本文看下OAuth2.0的另外3中授权流程&#xff0c;资源拥有者凭据许可&#xff0c;客户端许可&#xff0c;隐式许可。分别看下具体的使用流程以及该使用场景。 1&#xff1a;资源拥有者凭据许可 资源拥有者凭据许可&#xff0c;这里资源拥有者的凭据是什么呢&…

Vue源码解读学习

Vue源码 观察者模式 & 发布订阅 观察者模式&#xff1a;中心一对多 系统单点间的灵活和拓展&#xff08;广播的方式&#xff09; 发布订阅&#xff1a;将注册列表遍历发布给订阅者 initInject initState initProvide他们挂载顺序为什么这样设计&#xff1f; initstate…

MySQL行格式(row format)

MySQL行格式&#xff08;row format&#xff09; 表的行格式决定了其行的物理存储方式&#xff0c;这反过来又会影响查询和 DML 操作的性能。随着单个磁盘页面容纳更多行&#xff0c;查询和索引查找可以更快地工作&#xff0c;缓冲池中需要的高速缓存内存更少&#xff0c;写出…

京西商城——前端项目的创建以及前后端联调

创建VUE项目 在jingxi_shop_project文件夹中再创建一个 frontend 文件夹用来存放前端项目 /jingxi_shop_project/backend/jingxi_shop_project....../frontend/jingxi_shop_web......首先要安装 node.js 和 VUE cli&#xff0c;进入到项目目录内创建项目 vue create jingxi_…

[Vision Board创客营]学习片上Flash移植FAL

文章目录 [Vision Board创客营]学习片上Flash移植FAL介绍环境搭建使用组件测试porbeerasewriteread 结语 [Vision Board创客营]学习片上Flash移植FAL 水平较菜&#xff0c;大佬轻喷。&#x1f630;&#x1f630;&#x1f630; 介绍 &#x1f680;&#x1f680;Vision-Board 开…

解锁流量密码:如何利用HubSpot打造高效的获客策略?(下)

在当今数字化时代&#xff0c;流量是企业成功的关键。HubSpot作为一款全面的营销自动化工具&#xff0c;为我们提供了强大的支持&#xff0c;帮助企业打造高效的流量获取策略。接下来&#xff0c;我们将从社交媒体与SEO优化、自动化营销流程、数据分析与效果评估以及流量获取策…