12.支付宝支付、邮件发送

支付宝支付

前置准备

支付宝开放平台登录

image

image

利用支付宝秘钥工具,通过私钥生成公钥

image

image

再通过应用公钥去网站 生成支付宝公钥

image

1.加入支付宝支付依赖

<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-easysdk</artifactId>
  
   <version>2.0.2</version>
</dependency>

2.在配置文件中配置支付宝相关配置

alipay:
  appId: #换成你自己的APPID
  privateKey: #换成你自己的私钥
  publicKey: #支付宝公钥  通过公钥生成的支付宝公钥
  gateway: #支付网关配置,这一项是写死的,正式环境是openapi.alipay.com
  returnUrl: #支付成功之后的回调页面,只是一个友好页面。主要换成你自己映射的临时域名
  notifyUrl: #支付成功的接口回调,我们还没写,先空着

3.初始化支付宝相关配置

package com.wang.config;

import com.alipay.easysdk.factory.Factory;

import com.alipay.easysdk.kernel.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * @Classname AlipayConfig
 * @Description 初始化支付宝的相关配置
 * @Date 2024/10/18 13:51
 * @Created by pc
 */
@Component
public class AlipayConfig implements ApplicationRunner {

    @Value("${alipay.appId}")
    private String appId;
    @Value("${alipay.privateKey}")
    private String privateKey;
    @Value("${alipay.publicKey}")
    private String publicKey;
    @Value("${alipay.gateway}")
    private String gateway;
    @Value("${alipay.returnUrl}")
    private String returnUrl;
    @Value("${alipay.notifyUrl}")
    private String notifyUrl;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Factory.setOptions(getOptions());
        System.out.println("************支付宝SDK初始化完成********");
    }

    public Config getOptions(){
        Config config = new Config();
        config.protocol="https"; // 协议
        config.gatewayHost=this.gateway;// 网关
        config.signType="RSA2";// 加密算法类型
        config.appId=this.appId; // appId
        config.merchantPrivateKey = this.privateKey;// 私钥
        config.alipayPublicKey = this.publicKey;// 支付宝公钥
        config.notifyUrl = this.notifyUrl; // 支付宝回调接口
        return config;
    }
}

4.写一个根据时间戳生成订单的工具类

package com.wang.utils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

/**
 * @Classname OrderNo
 * @Description 根据时间戳生成一个订单号
 * @Date 2024/10/18 14:09
 * @Created by pc
 */
public class OrderNo {
    /**
     *  根据时间戳生成订单号
     * */
    public static String getOrderNo () {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        LocalDateTime localDateTime = Instant.ofEpochMilli(System.currentTimeMillis()).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
        return df.format(localDateTime);
    }
}

5.支付时相关参数

package com.wang.bo;

import lombok.*;

import java.math.BigDecimal;

/**
 * @Classname PayBo
 * @Description 发起支付的参数 -- 支付的项目  金额
 * @Date 2024/10/18 14:04
 * @Created by pc
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class PayBo {
    private String subject;

    private BigDecimal total = BigDecimal.ZERO;
}

6.支付宝支付的service

package com.wang.service;

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.wang.bo.PayBo;
import com.wang.utils.OrderNo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @Classname PayService
 * @Description TODO
 * @Date 2024/10/18 14:03
 * @Created by pc
 */
@Service
public class PayService {

    @Value("${alipay.returnUrl}")
    private String returnUrl;

    /*
    * 下单支付
    * */
    public Object pay(PayBo bo) throws Exception {
        // 生成订单号
        String orderNo = OrderNo.getOrderNo();
        //调用支付宝的SDK中支付方法 最终由支付宝生一个支付的页面 我们去这个页面付钱 AlipayTradePagePayResponse
        AlipayTradePagePayResponse response = Factory.Payment
                // 选择网页平台支付
                .Page()
                // 调用支付方法 传递参数
                //      产品名称       订单号      支付总金额              调用的回调页面
                .pay(bo.getSubject(),orderNo, bo.getTotal().toString(), returnUrl);
        // 生成一个支付页面片段
        return response.body;
    }
}

7.支付的Controller

package com.wang.controller.api;

import com.wang.bo.PayBo;
import com.wang.service.PayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @Classname ApiPayController
 * @Description TODO
 * @Date 2024/10/18 14:14
 * @Created by pc
 */
@RestController
@Slf4j
@RequestMapping("/api/pay")
public class ApiPayController {
    @Resource
    private PayService payService;

    @PostMapping(value = "/confirm",produces = {"text/html;charset=utf-8"})
    public Object pay(PayBo payBo) throws Exception {
        return payService.pay(payBo);
    }

    @PostMapping("/notify")
    // 支付成功之后 支付宝会调用这个回调接口 返回一些参数 这些参数会通过请求封装过来 我们可以在接口中获取
    public void notify(HttpServletRequest request){
        Map<String, String[]> map = request.getParameterMap();
        map.forEach((k,v)->{
            System.out.println("----------------"+k+"------------------");
            for (String s : v) {
                System.out.println(s);
            }
        });
    }
}

8.支付的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <form action="/api/pay/confirm" method="post">
        商品名称: <input type="text" name="subject"> <br>
        价格: <input type="text" name="total"> <br>
        <input type="submit" value="确认支付">
    </form>
</div>
</body>
</html>
<template>
  <el-form
      ref="ruleFormRef"
      style="max-width: 600px"
      :model="ruleForm"
      status-icon
      label-width="auto"
      class="demo-ruleForm"
  >
    <el-form-item label="商品名称" prop="pass">
      <el-text class="mx-1" size="large" v-model="ruleForm.subject">{{ ruleForm.subject }}</el-text>

    </el-form-item>
    <el-form-item label="金额" prop="checkPass">
      <el-text class="mx-1" size="large" v-model="ruleForm.total">{{ ruleForm.total }}</el-text>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="confirm">
        Submit
      </el-button>
    </el-form-item>
  </el-form>
<!-- 在页面中有一个可以提供渲染的元素 -->
  <div ref="alipayWap" v-html="alipay" />
</template>
<script setup>
import {ref,nextTick,getCurrentInstance} from "vue";
import {useRoute} from "vue-router";
import {pay} from "../api/payApi.js";

const {proxy} = getCurrentInstance()
const route = useRoute();
const ruleForm = ref({
  subject: route.query.subject,
  total :route.query.total
})
const alipay = ref()
async function confirm(){
  let {data:data} = await pay(ruleForm.value)
  console.log(data)
  alipay.value = data
  // 将数据渲染到元素内,通过触发表单的 提交事件,可以调起支付接口
  nextTick(() => {
    // 提交支付表单
    proxy.$refs.alipayWap.children[0].submit();
    setTimeout(() => {
      // this.toPayFlag = false;
    }, 500);
  });
}
</script>
<style scoped>

</style>

Mail邮件

一.邮件发送概述

1.概述

在Spring框架中提供了一个JavaMailSender接口,可以实现发送邮件功能。

而在Spring Boot中提供了一个对应的spring-boot-starter-mail依赖,添加该依赖后,Spring Boot将创建一个默认的JavaMailSender,该sender可以通过spring.mail命名空间下的配置项进一步自定义。

2.发送邮件的场景

(1)用户通过邮件注册激活;

(2)通过邮件找回密码;

(3)通过邮件发送系统情况;

(4)通过邮件发送报表信息等。

3.常用邮箱系统供应商

126邮箱SMTP服务器地址:smtp.126.com,端口号:465或者994

163邮箱SMTP服务器地址:smtp.163.com,端口号:465或者994

qq邮箱SMTP服务器地址:smtp.qq.com,端口号:465或587

yeah邮箱SMTP服务器地址:smtp.yeah.net,端口号:465或者994

4.QQ邮箱开启SMTP功能

为了保障用户邮箱的安全,QQ邮箱设置了POP3/SMTP/IMAP的开关。系统默认情况下相关设置是“关闭”状态的,在用户需要这些功能时请先“开启”,才可以用客户端软件收发邮件。

QQ邮箱开启SMTP功能步骤

默认情况下,SMTP服务器功能没有开启,所以需要在“设置”-->"账号"-->"POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务"中对SMTP进行开启。

开启成功后,会有一个授权码,这个授权码就是我们进行邮件发送时的邮箱密码,可以把它记住,不记也可以。因为这个授权码可以多次生成,只要用的时候发一次短信验证码,就可以得到一个新的授权码了。

1.引入依赖

<dependencies>
    <!-- web支持: 1、web mvc; 2、restful; 3、jackjson支持; 4、aop ........ -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>
    <!--简化bean代码-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

2.配置文件

server:
  port: 8080
  servlet:
    context-path: /
spring:
  freemarker:
    template-loader-path: classpath:/templates/
    suffix: .ftl
    cache: false
    charset: UTF-8
    check-template-location: true
    context-type: text/html
  #邮箱配置
  mail:
    host: smtp.qq.com
    from: 446470238@qq.com
    username: 446470238@qq.com
    password: djnxxmyhuzkwcbbb
    protocol: smtp
    default-encoding: UTF-8
    properties:
      mail:
        smtp:
          ssl:
            enable: true
          auth: true
        starttls:
          enable: true
          required: true

5.发送邮件接口

package com.wang.service;

import javax.mail.MessagingException;

public interface MailService {

    /**
     * 发送文本邮件
     *
     * @param to      收件人
     * @param subject 主题
     * @param content 内容
     */
    void sendSimpleMail(String to, String subject, String content);

    /**
     * 发送HTML邮件
     *
     * @param to      收件人
     * @param subject 主题
     * @param content 内容
     */
    void sendHtmlMail(String to, String subject, String content);

    /**
     * 发送带附件的邮件
     *
     * @param to       收件人
     * @param subject  主题
     * @param content  内容
     * @param filePath 附件
     */
    void sendAttachmentsMail(String to, String subject, String content, String filePath);

    /**
     * 发送模板文件
     *
     * @param to       收件人
     * @param subject  主题
     * @param fileName 邮件模板文件名称
     * @param model    邮件数据载体
     */
    void sendModelMail(String to, String subject, String fileName, Object model) throws MessagingException;
}

6.接口实现

package com.wang.service.impl;

import com.wang.service.MailService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Objects;

/**
 * @Classname MailServiceImpl
 * @Description TODO
 * @Date 2025/2/19 13:52
 * @Created by pc
 */
@Service
@Slf4j
public class MailServiceImpl implements MailService {

    @Resource
    private JavaMailSender mailSender;
    @Value("${spring.mail.from}")
    private String from;
    @Resource
    private Configuration configuration;

    @Override
    public void sendSimpleMail(String to, String subject, String content) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(content);
        mailSender.send(message);
    }

    @Override
    public void sendHtmlMail(String to, String subject, String content) {
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content,true);
            mailSender.send(message);
            log.info("邮件已发送");
        } catch (MessagingException e) {
            // throw new RuntimeException(e);
            e.printStackTrace();
            log.error("发送失败",e);
        }
    }

    @Override
    public void sendAttachmentsMail(String to, String subject, String content, String filePath) {
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content,true);
            // 带附件
            ClassPathResource resource = new ClassPathResource(filePath);
            FileSystemResource file = new FileSystemResource(resource.getFile());
            helper.addAttachment(Objects.requireNonNull(file.getFilename()),file);
            mailSender.send(message);
            log.info("邮件已发送");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("发送失败",e);
        }

    }

    @Override
    public void sendModelMail(String to, String subject, String fileName, Object model) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            Template template = configuration.getTemplate(fileName);
            String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
            helper.setText(html,true);
            mailSender.send(message);log.info("邮件已发送");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("发送失败",e);
        }
    }
}

7.控制器

package com.wang.controller;

import com.wang.entity.Employee;
import com.wang.service.MailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.mail.MessagingException;

/**
 * @Classname MailController
 * @Description TODO
 * @Date 2025/2/19 13:56
 * @Created by pc
 */
@RestController
@Slf4j
public class MailController {
    @Resource
    private MailService mailService;

    @GetMapping("/simple")
    public String sendSimpleMail() {
        mailService.sendSimpleMail("446470238@qq.com", "你打开看看", "什么也没有");
        return "success";
    }

    @GetMapping("/html")
    public String sendHtmlMail() {
        mailService.sendHtmlMail("446470238@qq.com", "你打开看看", "<h1>邮件主题</h1><br/><p><font color='red'>什么也没有</font></p>");
        return "success";
    }
    @GetMapping("/attachment")
    public String sendAttachmentMail() {
        mailService.sendAttachmentsMail("446470238@qq.com", "主题:带附件的邮件", "有附件的邮件,不要错过哦...", "static/lock.png");
        return "success";
    }

    @PostMapping("/model")
    public String sendModelMail(@RequestBody Employee employee) throws MessagingException {
        mailService.sendModelMail("446470238@qq.com", "主题:新员工入职欢迎邮件--模板邮件", "mail.ftl", employee);
        return "success";
    }
}

8.模版文件

<p>${username}--你好,欢迎加入XXX大家庭!您的入职信息如下:</p>
<table border="1" cellspacing="0">
    <tr><td><strong style="color: #F00">工号</strong></td><td>${id}</td></tr>
    <tr><td><strong style="color: #F00">合同期限</strong></td><td>${contractTerm}年</td></tr>
    <tr><td><strong style="color: #F00">员工薪资</strong></td><td>${salary}/月(美元)</td></tr>
    <tr><td><strong style="color: #F00">合同起始日期</strong></td><td>${beginContact?string("yyyy-MM-dd")}</td></tr>
    <tr><td><strong style="color: #F00">合同截至日期</strong></td><td>${endContact?string("yyyy-MM-dd")}</td></tr>
    <tr><td><strong style="color: #F00">所属部门</strong></td><td>${departmentName}</td></tr>
    <tr><td><strong style="color: #F00">职位</strong></td><td>${posName}</td></tr>
</table>
<p><strong style="color: #F00; font-size: 24px;">希望在未来的日子里,携手共进!</strong></p>

9.实体类

package com.wang.entity;

import lombok.Data;

import java.util.Date;

@Data
public class Employee {

    private Long        id;
    private String      username;
    private Integer     contractTerm;
    private Double      salary;
    private Date        beginContact;
    private Date        endContact;
    private String      departmentName;
    private String      posName;
}

二.邮件注册激活功能

1.引入依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--MySQL-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--Druid数据库连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--邮件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

2.配置文件

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db66?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    username: root
    password: wang
    driverClassName: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  #页面模板配置
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
  mail:
    host: smtp.qq.com
    from: 446470238@qq.com
    username: 446470238@qq.com
    password: djnxxmyhuzkwcbbb
    protocol: smtp
    default-encoding: UTF-8
    properties:
      mail:
        smtp:
          ssl:
            enable: true
          auth: true
        starttls:
          enable: true
          required: true
server:
  tomcat:
    uri-encoding: UTF-8

3.实体类

@Data
public class User implements Serializable {

private Integer id;

private String username;

private String password;

    @Column(name = "usermail")
private String userMail;

    /**
     * 状态:0代表未激活,1代表激活
     */
private Integer status;

    /**
     * 用UUID生成一段数字,发送到用户邮箱,当用户点击链接时,再做一个校验,
     * 如果用户传来的code跟我们发送的code一致,则更改状态为"1"来激活用户。
     */
    private String code;
}

4.工具类

public class UUIDUtil {
    public static String getUUID(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }

    public static void main(String[] args) {
        System.out.println(UUID.randomUUID().toString().replaceAll("-",""));
    }
}

5.mapper接口

    User findUserByCode(String code);
    User findByUsernameAndPassword(String username, String password);
public interface UserService {
    // 注册
    void reg(User user);

    // 根据激活码查找用户
    User checkedCode(String code);

    // 激活 修改用户状态
    void updateUserStatus(User user);

    // 登录
    User login(User user);
}

发送短信

posted @ 2025-06-04 14:24  icui4cu  阅读(15)  评论(0)    收藏  举报