2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Spring-Boot整合微信登陆 微信支付 邮箱发送 支付宝支付和阿里云短信

Spring-Boot整合微信登陆 微信支付 邮箱发送 支付宝支付和阿里云短信

时间:2022-07-20 04:22:43

相关推荐

Spring-Boot整合微信登陆 微信支付 邮箱发送 支付宝支付和阿里云短信

Spring-Boot整合

1. 发送邮件2. 支付宝支付3. 阿里云短信4. 微信登陆5. 微信支付6. Swargger2 前后端API接口信息文档7. ehcache缓存缓存8. Spring-Boot注解详解9. 自定义配置文件类

1. 发送邮件

添加依赖

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

创建mail.properties配置文件

mail.host=#邮箱地址mail.username=*****@#邮箱授权码mail.password=********#是否启用加密mail.smtpAuth=true#mail.smtpStarttlsEnable=truemail.smtpStarttlsRequired=truemail.defaultEncoding=UTF-8

创建配置类

package com.example.demo1.config;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.PropertySource;import org.ponent;/*** 邮箱类*/@Component//配置属性文件@PropertySource("classpath:mail.properties")//说明配置文件属性的头部@ConfigurationProperties(prefix = "mail")public class MailConfig {private String host;private String username;private String password;private String smtpAuth;private String smtpStarttlsEnable;private String smtpStarttlsRequired;private String defaultEncoding;//getter and setter }

创建工具类

package com.example.demo1.utils;import com.example.demo1.config.MailConfig;import org.springframework.mail.SimpleMailMessage;import org.springframework.mail.javamail.JavaMailSenderImpl;import org.ponent;import javax.annotation.Resource;import java.util.Properties;@Componentpublic class MailUtils {@Resourceprivate MailConfig mailConfig;/*** 邮箱发送方法** @param to收信人* @param title 邮箱标题* @param content 邮箱内容*/public boolean sendMail(String to, String title, String content) {try {//邮箱消息对象SimpleMailMessage simpleMailMessage = new SimpleMailMessage();simpleMailMessage.setFrom(mailConfig.getUsername());//发送人simpleMailMessage.setTo(to);//收件人simpleMailMessage.setSubject(title);//邮箱标题simpleMailMessage.setText(content);//邮箱内容//邮箱发送对象JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();javaMailSender.setUsername(mailConfig.getUsername());javaMailSender.setHost(mailConfig.getHost());javaMailSender.setPassword(mailConfig.getPassword());javaMailSender.setDefaultEncoding(mailConfig.getDefaultEncoding());Properties properties = new Properties();properties.setProperty("mail.smtp.auth", mailConfig.getSmtpAuth());properties.setProperty("mail.smtp.starttls.enable", mailConfig.getSmtpStarttlsEnable());properties.setProperty("mail.smtp.starttls.required", mailConfig.getSmtpStarttlsRequired());javaMailSender.setJavaMailProperties(properties);//实现发送邮箱javaMailSender.send(simpleMailMessage);return true;} catch (Exception e) {e.printStackTrace();return false;}}}

创建MailController

package com.example.demo1.controller;import com.alibaba.fastjson.JSONObject;import com.example.demo1.pojo.Test;import com.example.demo1.service.TestService;import com.example.demo1.utils.MailUtils;import com.example.demo1.utils.RandomUtils;import com.example.demo1.utils.RedisUtils;import com.example.demo1.utils.TokenUtils;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiParam;import org.springframework.web.bind.annotation.GetMapping;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.HashMap;import java.util.Map;import java.util.concurrent.TimeUnit;@Api(tags = "邮箱登陆")@RestController@RequestMapping("test")public class MailController {@Resourceprivate MailUtils mailUtils;@Resourceprivate RedisUtils redisUtils;@Resourceprivate TestService testService;@Resourceprivate TokenUtils tokenUtils;/* 发送验证码 */@ApiOperation("发送验证码")@GetMapping("/sendmail")public Object sendMail(@ApiParam(value = "请求头", required = true) HttpServletRequest request) {Map<String, Object> dto = new HashMap<>();String to = request.getHeader("to");//判断是否已经发送过验证码String code = redisUtils.get(to);if (code != null) {dto.put("msg", "验证码10分钟内有效");dto.put("code", 6000);return dto;}//生产随机数Integer ran = RandomUtils.genNumByLen(6);String title = "登陆";String content = "验证码" + ran + ",5分钟内有效";//发送验证码if (mailUtils.sendMail(to, title, content)) {// 把验证码保存到redis中redisUtils.set(to, ran.toString(), 300, TimeUnit.SECONDS);dto.put("msg", "发送成功");dto.put("code", 2);return dto;}dto.put("msg", "发送失败");dto.put("code", -2);return dto;}/* 邮箱登陆 */@ApiOperation("邮箱登陆")@GetMapping("/maillogin")public Object mailLogin(HttpServletRequest request) {String to = request.getHeader("to");String code = request.getHeader("code");Map<String, Object> dto = new HashMap<>();//从redis中获取验证吗String rCode = redisUtils.get(to);if (!rCode.equals(code)) {dto.put("msg", "验证码错误");dto.put("code", 0);return dto;}//判断用户是否存在Test test = testService.getUserByEmail(to);if (test == null) {//新用户test = new Test();test.setCode(to);//添加用户到数据库/* ---------------------添加并获取id------------- */if (!testService.addUser(test)) {dto.put("msg", "登陆失败");dto.put("code", -1);return dto;}}//生成tokenString token = tokenUtils.getToken("Mail-", test.getId(), RandomUtils.genNumByLen(6));//把token存入redis中 30分钟有效redisUtils.set(token, JSONObject.toJSONString(test), 30 * 60, TimeUnit.SECONDS);dto.put("msg", "登陆成功");dto.put("code", 1);dto.put("token", token);return dto;}/*** 用于测试token的替换** @param request 请求对象* @return*/@ApiOperation("用于测试token的替换")@GetMapping("getUser")public Object getUser(@ApiParam(value = "请求对象") HttpServletRequest request) {Map<String, Object> dto = new HashMap<>();String token = request.getHeader("token");//判断token存在if (!redisUtils.hasKey(token)) {dto.put("msg", "token失效");dto.put("code", -3);return dto;}//把redis转换成对象Test test = JSONObject.parseObject(redisUtils.get(token), Test.class);token = tokenUtils.replaceToken(token, "Mail-", test);dto.put("msg", "token有效");dto.put("code", 3);dto.put("token", token);return dto;}}

2. 支付宝支付

引入依赖

<!-- 支付宝支付 --><dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-easysdk</artifactId><version>2.0.1</version></dependency>

创建AliPayConfig配置类

package com.example.demo1.config;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.PropertySource;import org.ponent;@Component@PropertySource("classpath:alipay.properties")@ConfigurationProperties("alipay")public class AliPayConfig {private String protocol;private String gatewayHost;private String signType;private String appId;private String merchantPrivateKey;private String notifyUrl;private String returnUrl;private String encryptKey;private String alipayPublicKey;private String successUrl;// getter and setter}

创建AliPayUtils工具类

package com.example.demo1.utils;import com.alipay.easysdk.factory.Factory;import com.alipay.easysdk.factory.Factory.Payment;import com.alipay.easysdk.kernel.Config;import com.alipay.easysdk.kernel.util.ResponseChecker;import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;import com.example.demo1.config.AliPayConfig;import org.ponent;import javax.annotation.Resource;import java.util.Map;/*** 阿里支付工具类*/@Componentpublic class AliPayUtils {@Resourceprivate AliPayConfig aliPayConfig;public AliPayConfig getAliPayConfig() {return aliPayConfig;}/*** 支付** @param sunject 项目名称* @param payNo 订单号* @param amount 支付金额* @return*/public String toPcPay(String sunject, String payNo, String amount) {String result = "";// 1. 设置参数(全局只需设置一次)Factory.setOptions(getOptions());try {// 2. 发起API调用AlipayTradePagePayResponse response = Payment.Page().pay(sunject, payNo, amount, aliPayConfig.getReturnUrl());// 3. 处理响应或异常if (ResponseChecker.success(response)) {result = response.body;System.out.println("调用成功");} else {System.err.println("调用失败,原因:" + response.body);}} catch (Exception e) {System.err.println("调用遭遇异常,原因:" + e.getMessage());throw new RuntimeException(e.getMessage(), e);}return result;}private Config getOptions() {Config config = new Config();config.protocol = aliPayConfig.getProtocol();config.gatewayHost = aliPayConfig.getGatewayHost();config.signType = aliPayConfig.getSignType();config.appId = aliPayConfig.getAppId();config.merchantPrivateKey = aliPayConfig.getMerchantPrivateKey();config.encryptKey = aliPayConfig.getEncryptKey();config.notifyUrl = aliPayConfig.getNotifyUrl();config.alipayPublicKey = aliPayConfig.getAlipayPublicKey();return config;}/*** 验签** @param parameters* @return* @throws Exception*/public Boolean verify(Map<String, String> parameters) throws Exception {return mon().verifyNotify(parameters);}}

新增测试页面

<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>支付测试页</title></head><body><form action="/test/alipay" method="POST"><label for="subject">项目名:</label><input type="text" name="subject"><br><label for="payno">订单号:</label><input type="text" name="payno"><br><label for="amount">订单金额:</label><input type="text" name="amount"><br><input type="submit" value="支付"></form></body></html>

3. 阿里云短信

引入依赖

<!-- 发送短信 --><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.5.3</version></dependency>

2.创建ssm.properties配置文件

#此处替填写'AccessKey ID'sms.accessKeyId=**************#此处填写'AccessKey Secret'sms.secret=**************# 最近服务器地点sms.RegionId=cn-hangzhousms.domain=sms.version=-05-25sms.action=SendSms#此处替换为'签名名称'sms.signName=**#此处替换为'模版CODE'sms.templateCode=***

创建配置类

package com.example.demo1.config;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.PropertySource;import org.ponent;@Component@PropertySource("classpath:ssm.properties")@ConfigurationProperties(prefix = "sms")public class AliyunSSMConfig {private String accessKeyId;private String secret;private String RegionId;private String domain;private String version;private String action;private String signName;private String templateCode;//getter and setter}

创建工具类

package com.example.demo1.utils;import com.alibaba.fastjson.JSONObject;import monRequest;import monResponse;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.IAcsClient;import com.aliyuncs.exceptions.ClientException;import com.aliyuncs.exceptions.ServerException;import com.aliyuncs.http.MethodType;import com.aliyuncs.profile.DefaultProfile;import com.example.demo1.config.AliyunSSMConfig;import org.ponent;import javax.annotation.Resource;@Componentpublic class AliyunSMSUtils {@Resourceprivate AliyunSSMConfig aliyunSSMConfig;/*** 发送短信** @param phone 手机号* @param code 验证码*/public boolean sendMessage(String phone, String code) {DefaultProfile profile = DefaultProfile.getProfile(aliyunSSMConfig.getRegionId(),aliyunSSMConfig.getAccessKeyId(), aliyunSSMConfig.getSecret());//客服端对象IAcsClient client = new DefaultAcsClient(profile);//请求对象CommonRequest request = new CommonRequest();//请求方式request.setSysMethod(MethodType.POST);request.setSysDomain(aliyunSSMConfig.getDomain());request.setSysVersion(aliyunSSMConfig.getVersion());//具体操作request.setSysAction(aliyunSSMConfig.getAction());request.putQueryParameter("RegionId", aliyunSSMConfig.getRegionId());request.putQueryParameter("PhoneNumbers", phone);request.putQueryParameter("SignName", aliyunSSMConfig.getSignName());request.putQueryParameter("TemplateCode", aliyunSSMConfig.getTemplateCode());// 参数 和模板里的格式一样request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");try {//响应对象CommonResponse response = client.getCommonResponse(request);System.out.println(response.getData());// 获取状态码 (固定)String status = JSONObject.parseObject(response.getData()).get("Code").toString();return "OK".equals(status);} catch (ServerException e) {e.printStackTrace();} catch (ClientException e) {e.printStackTrace();}return false;}}

创建AliyunController

package com.example.demo1.controller;import com.alibaba.fastjson.JSONObject;import com.example.demo1.pojo.Test;import com.example.demo1.service.TestService;import com.example.demo1.utils.MailUtils;import com.example.demo1.utils.RandomUtils;import com.example.demo1.utils.RedisUtils;import com.example.demo1.utils.TokenUtils;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiParam;import org.springframework.web.bind.annotation.GetMapping;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.HashMap;import java.util.Map;import java.util.concurrent.TimeUnit;@Api(tags = "邮箱登陆")@RestController@RequestMapping("test")public class MailController {@Resourceprivate MailUtils mailUtils;@Resourceprivate RedisUtils redisUtils;@Resourceprivate TestService testService;@Resourceprivate TokenUtils tokenUtils;/* 发送验证码 */@ApiOperation("发送验证码")@GetMapping("/sendmail")public Object sendMail(@ApiParam(value = "请求头", required = true) HttpServletRequest request) {Map<String, Object> dto = new HashMap<>();String to = request.getHeader("to");//判断是否已经发送过验证码String code = redisUtils.get(to);if (code != null) {dto.put("msg", "验证码10分钟内有效");dto.put("code", 6000);return dto;}//生产随机数Integer ran = RandomUtils.genNumByLen(6);String title = "登陆";String content = "验证码" + ran + ",5分钟内有效";//发送验证码if (mailUtils.sendMail(to, title, content)) {// 把验证码保存到redis中redisUtils.set(to, ran.toString(), 300, TimeUnit.SECONDS);dto.put("msg", "发送成功");dto.put("code", 2);return dto;}dto.put("msg", "发送失败");dto.put("code", -2);return dto;}/* 邮箱登陆 */@ApiOperation("邮箱登陆")@GetMapping("/maillogin")public Object mailLogin(HttpServletRequest request) {String to = request.getHeader("to");String code = request.getHeader("code");Map<String, Object> dto = new HashMap<>();//从redis中获取验证吗String rCode = redisUtils.get(to);if (!rCode.equals(code)) {dto.put("msg", "验证码错误");dto.put("code", 0);return dto;}//判断用户是否存在Test test = testService.getUserByEmail(to);if (test == null) {//新用户test = new Test();test.setCode(to);//添加用户到数据库/* ---------------------添加并获取id------------- */if (!testService.addUser(test)) {dto.put("msg", "登陆失败");dto.put("code", -1);return dto;}}//生成tokenString token = tokenUtils.getToken("Mail-", test.getId(), RandomUtils.genNumByLen(6));//把token存入redis中 30分钟有效redisUtils.set(token, JSONObject.toJSONString(test), 30 * 60, TimeUnit.SECONDS);dto.put("msg", "登陆成功");dto.put("code", 1);dto.put("token", token);return dto;}/*** 用于测试token的替换** @param request 请求对象* @return*/@ApiOperation("用于测试token的替换")@GetMapping("getUser")public Object getUser(@ApiParam(value = "请求对象") HttpServletRequest request) {Map<String, Object> dto = new HashMap<>();String token = request.getHeader("token");//判断token存在if (!redisUtils.hasKey(token)) {dto.put("msg", "token失效");dto.put("code", -3);return dto;}//把redis转换成对象Test test = JSONObject.parseObject(redisUtils.get(token), Test.class);token = tokenUtils.replaceToken(token, "Mail-", test);dto.put("msg", "token有效");dto.put("code", 3);dto.put("token", token);return dto;}}

4. 微信登陆

引入依赖

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.31</version></dependency>

创建wxlogin.properties配置文件

wxlogin.openUrl=https://open./connect/qrconnectwxlogin.appid=*********# 回调地址 接收用户信息的Urlwxlogin.redirectUri=http://localhost:8080/test/wechat/callbackwxlogin.responseType=codewxlogin.scope=snsapi_loginwxlogin.state=STATE#wechat_redirect# 再去微信服务器拿token的urlwxlogin.accessTokenUrl=https://api./sns/oauth2/access_tokenwxlogin.secret=********wxlogin.grantType=authorization_code# 获取微信用户的信息wxlogin.userInfoUrl=https://api./sns/userinfo

创建WxLoginConfig配置类

import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.PropertySource;import org.ponent;/*** 微信登陆配置文件类*/@Component@ConfigurationProperties(prefix = "wxlogin")@PropertySource("classpath:wxlogin.properties")public class WxLoginConfig {private String appid;private String redirectUri;private String responseType;private String scope;private String state;private String openUrl;private String accessTokenUrl;private String secret;private String grantType;private String userInfoUrl;//getter and serter}

创建UrlUtils工具类

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import .HttpURLConnection;import .URL;/*** 微信登陆Url工具类*/public class UrlUtils {/*** 获取url网址返回的数据内容** @param urlStr* @return*/public static String loadURL(String urlStr) {try {URL url = new URL(urlStr);//连接网址对象HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();// 连接方式urlConnection.setRequestMethod("GET");urlConnection.connect();//获取返回的输入流InputStream inputStream = urlConnection.getInputStream();//把输入流转换成字符串String responseStr = ConvertToString(inputStream);return responseStr;} catch (IOException e) {e.printStackTrace();return null;}}/*** 输入流转换成字符串* @param inputStream* @return*/private static String ConvertToString(InputStream inputStream) {InputStreamReader inputStreamReader = new InputStreamReader(inputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);StringBuilder result = new StringBuilder();String line = null;try {while ((line = bufferedReader.readLine()) != null) {result.append(line + "\n");}} catch (IOException e) {e.printStackTrace();} finally {try {inputStreamReader.close();inputStream.close();bufferedReader.close();} catch (IOException e) {e.printStackTrace();}}return result.toString();}}

创建WxLoginControllerAPI接口

import com.alibaba.fastjson.JSONObject;import com.example.demo1.config.WxLoginConfig;import com.example.demo1.utils.RandomUtils;import com.example.demo1.utils.RedisUtils;import com.example.demo1.utils.TokenUtils;import com.example.demo1.utils.UrlUtils;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import javax.servlet.http.HttpServletResponse;import java.util.HashMap;import java.util.Map;import java.util.concurrent.TimeUnit;@RestController@RequestMapping("/test")public class WxLoginController {@Resourceprivate WxLoginConfig wxLoginConfig;@Resourceprivate RedisUtils redisUtils;@Resourceprivate TokenUtils tokenUtils;/*** 显示微信登陆扫码界面** @param response* @throws Exception*/@RequestMapping("/wechat/login")public void wechat(HttpServletResponse response) throws Exception {// 构建获取二维码的URLStringBuffer wxsb = new StringBuffer(wxLoginConfig.getOpenUrl());wxsb.append("?appid=" + wxLoginConfig.getAppid());wxsb.append("&redirect_uri=" + wxLoginConfig.getRedirectUri());wxsb.append("&response_type=" + wxLoginConfig.getResponseType());wxsb.append("&scope=" + wxLoginConfig.getScope());wxsb.append("&state=" + wxLoginConfig.getState());response.sendRedirect(wxsb.toString());}/*** 用户手机确认后回调函数** @param code* @throws Exception*/@RequestMapping("/wechat/callback")public Object callback(String code) throws Exception {Map<String, Object> dto = new HashMap<>();// 构造请求URLStringBuffer wxsb = new StringBuffer(wxLoginConfig.getAccessTokenUrl());wxsb.append("?appid=" + wxLoginConfig.getAppid());wxsb.append("&secret=" + wxLoginConfig.getSecret());wxsb.append("&code=" + code);wxsb.append("&grant_type=" + wxLoginConfig.getGrantType());// 发送请求并获取accessToken和opendIdString resp = UrlUtils.loadURL(wxsb.toString());JSONObject jsonObject = JSONObject.parseObject(resp);String accessToken = jsonObject.getString("access_token");String openId = jsonObject.getString("openid");// 构造获取用户信息的URLStringBuffer usb = new StringBuffer(wxLoginConfig.getUserInfoUrl());usb.append("?access_token=" + accessToken);usb.append("&openid=" + openId);// 发送请求并获取用户信息String userInfo = UrlUtils.loadURL(usb.toString());JSONObject userObject = JSONObject.parseObject(userInfo);if (userObject == null) {dto.put("msg", "微信登陆失败");dto.put("code", -4);return dto;}//生产tokenString token = tokenUtils.getToken("WX-", 1, RandomUtils.genNumByLen(6));redisUtils.set(token, JSONObject.toJSONString(userObject), 30 * 60, TimeUnit.SECONDS);dto.put("msg", "微信登陆成功");dto.put("code", 4);dto.put("token", token);return dto;}}

5. 微信支付

添加依赖

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

微信app支付参数配置

#服务器域名地址server.service-domain = http://127.0.0.1:8080#微信app支付pay.wxpay.app.appID = "你的appid"pay.wxpay.app.mchID = "你的商户id"pay.wxpay.app.key = "你的api秘钥,不是appSecret"#从微信商户平台下载的安全证书存放的路径、我放在resources下面,切记一定要看看target目录下的class文件下有没有打包apiclient_cert.p12文件pay.wxpay.app.certPath = static/cert/wxpay/apiclient_cert.p12#微信支付成功的异步通知接口pay.wxpay.app.payNotifyUrl=${server.service-domain}/api/wxPay/notify

创建配置类

import com.github.wxpay.sdk.WXPayConfig;import org.springframework.boot.context.properties.ConfigurationProperties;import org.ponent;import java.io.InputStream;/*** 配置我们自己的信息*/@Component@ConfigurationProperties(prefix = "pay.wxpay.app")public class WxPayAppConfig implements WXPayConfig {/*** appID*/private String appID;/*** 商户号*/private String mchID;/*** API 密钥*/private String key;/*** API证书绝对路径 (本项目放在了 resources/cert/wxpay/apiclient_cert.p12")*/private String certPath;/*** HTTP(S) 连接超时时间,单位毫秒*/private int httpConnectTimeoutMs = 8000;/*** HTTP(S) 读数据超时时间,单位毫秒*/private int httpReadTimeoutMs = 10000;/*** 微信支付异步通知地址*/private String payNotifyUrl;/*** 微信退款异步通知地址*/private String refundNotifyUrl;/*** 获取商户证书内容(这里证书需要到微信商户平台进行下载)** @return 商户证书内容*/@Overridepublic InputStream getCertStream() {InputStream certStream =getClass().getClassLoader().getResourceAsStream(certPath);return certStream;}public String getAppID() {return appID;}public void setAppID(String appID) {this.appID = appID;}public String getMchID() {return mchID;}public void setMchID(String mchID) {this.mchID = mchID;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getCertPath() {return certPath;}public void setCertPath(String certPath) {this.certPath = certPath;}public int getHttpConnectTimeoutMs() {return httpConnectTimeoutMs;}public void setHttpConnectTimeoutMs(int httpConnectTimeoutMs) {this.httpConnectTimeoutMs = httpConnectTimeoutMs;}public int getHttpReadTimeoutMs() {return httpReadTimeoutMs;}public void setHttpReadTimeoutMs(int httpReadTimeoutMs) {this.httpReadTimeoutMs = httpReadTimeoutMs;}public String getPayNotifyUrl() {return payNotifyUrl;}public void setPayNotifyUrl(String payNotifyUrl) {this.payNotifyUrl = payNotifyUrl;}public String getRefundNotifyUrl() {return refundNotifyUrl;}public void setRefundNotifyUrl(String refundNotifyUrl) {this.refundNotifyUrl = refundNotifyUrl;}}

定义controller

在调用微信服务接口进行统一下单之前,

1、为保证安全性,建议验证数据库是否存在订单号对应的订单。

package com.annaru.upms.payment.controller;import mon.result.ResultMap;import com.annaru.upms.payment.service.WxPayService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiParam;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;@Api(tags = "微信支付接口管理")@RestController@RequestMapping("/wxPay")public class WxPayController{@Autowiredprivate WxPayService wxPayService;/*** 统一下单接口*/@ApiOperation(value = "统一下单", notes = "统一下单")@GetMapping("/unifiedOrder")public ResultMap unifiedOrder(@ApiParam(value = "订单号") @RequestParam String orderNo,@ApiParam(value = "订单金额") @RequestParam double amount,@ApiParam(value = "商品名称") @RequestParam String body,HttpServletRequest request) {try {// 1、验证订单是否存在// 2、开始微信支付统一下单ResultMap resultMap = wxPayService.unifiedOrder(orderNo, orderNo, body);return resultMap;//系统通用的返回结果集,见文章末尾} catch (Exception e) {logger.error(e.getMessage());return ResultMap.error("运行异常,请联系管理员");}}/*** 微信支付异步通知*/@RequestMapping(value = "/notify")public String payNotify(HttpServletRequest request) {InputStream is = null;String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";try {is = request.getInputStream();// 将InputStream转换成StringBufferedReader reader = new BufferedReader(new InputStreamReader(is));StringBuilder sb = new StringBuilder();String line = null;while ((line = reader.readLine()) != null) {sb.append(line + "\n");}xmlBack = wxPayService.notify(sb.toString());} catch (Exception e) {logger.error("微信手机支付回调通知失败:", e);} finally {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}return xmlBack;}@ApiOperation(value = "退款", notes = "退款")@PostMapping("/refund")public ResultMap refund(@ApiParam(value = "订单号") @RequestParam String orderNo,@ApiParam(value = "退款金额") @RequestParam double amount,@ApiParam(value = "退款原因") @RequestParam(required = false) String refundReason){return wxPayService.refund(orderNo, amount, refundReason);}}

定义service接口

package com.annaru.upms.payment.service;import mon.result.ResultMap;/*** 微信支付服务接口*/public interface WxPayService {/*** @Description: 微信支付统一下单* @param orderNo: 订单编号* @param amount: 实际支付金额* @param body: 订单描述* @Author: * @Date: /8/1* @return*/ResultMap unifiedOrder(String orderNo, double amount, String body) ;/*** @Description: 订单支付异步通知* @param notifyStr: 微信异步通知消息字符串* @Author: * @Date: /8/1* @return */String notify(String notifyStr) throws Exception;/*** @Description: 退款* @param orderNo: 订单编号* @param amount: 实际支付金额* @param refundReason: 退款原因* @Author: XCK* @Date: /8/6* @return*/ResultMap refund(String orderNo, double amount, String refundReason);}

service实现类

package com.annaru.upms.payment.service.impl;import com.alibaba.dubbo.config.annotation.Reference;import mon.result.ResultMap;import mon.util.HttpContextUtils;import com.annaru.upms.payment.config.WxPayAppConfig;import com.annaru.upms.payment.service.WxPayService;import com.annaru.upms.service.IOrderPaymentService;import com.github.wxpay.sdk.WXPay;import com.github.wxpay.sdk.WXPayUtil;import mons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.HashMap;import java.util.Map;@Servicepublic class WxPayServiceImpl implements WxPayService {private final Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);@Referenceprivate IOrderPaymentService orderPaymentService;@Autowiredprivate WxPayAppConfig wxPayAppConfig;@Overridepublic ResultMap unifiedOrder(String orderNo, double amount, String body) {Map<String, String> returnMap = new HashMap<>();Map<String, String> responseMap = new HashMap<>();Map<String, String> requestMap = new HashMap<>();try {WXPay wxpay = new WXPay(wxPayAppConfig);requestMap.put("body", body); // 商品描述requestMap.put("out_trade_no", orderNo);// 商户订单号requestMap.put("total_fee", String.valueOf((int)(amount*100))); // 总金额requestMap.put("spbill_create_ip", HttpContextUtils.getIpAddr()); // 终端IPrequestMap.put("trade_type", "APP");// App支付类型requestMap.put("notify_url", wxPayAppConfig.getPayNotifyUrl()); // 接收微信支付异步通知回调地址Map<String, String> resultMap = wxpay.unifiedOrder(requestMap);//获取返回码String returnCode = resultMap.get("return_code");String returnMsg = resultMap.get("return_msg");//若返回码为SUCCESS,则会返回一个result_code,再对该result_code进行判断if ("SUCCESS".equals(returnCode)) {String resultCode = resultMap.get("result_code");String errCodeDes = resultMap.get("err_code_des");if ("SUCCESS".equals(resultCode)) {responseMap = resultMap;}}if (responseMap == null || responseMap.isEmpty()) {return ResultMap.error("获取预支付交易会话标识失败");}// 3、签名生成算法Long time = System.currentTimeMillis() / 1000;String timestamp = time.toString();returnMap.put("appid", wxPayAppConfig.getAppID());returnMap.put("partnerid", wxPayAppConfig.getMchID());returnMap.put("prepayid", responseMap.get("prepay_id"));returnMap.put("noncestr", responseMap.get("nonce_str"));returnMap.put("timestamp", timestamp);returnMap.put("package", "Sign=WXPay");returnMap.put("sign", WXPayUtil.generateSignature(returnMap, wxPayAppConfig.getKey()));//微信支付签名return ResultMap.ok().put("data", returnMap);} catch (Exception e) {logger.error("订单号:{},错误信息:{}", orderNo, e.getMessage());return ResultMap.error("微信支付统一下单失败");}}@Overridepublic String notify(String notifyStr) {String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";try {// 转换成mapMap<String, String> resultMap = WXPayUtil.xmlToMap(notifyStr);WXPay wxpayApp = new WXPay(wxPayAppConfig);if (wxpayApp.isPayResultNotifySignatureValid(resultMap)) {String returnCode = resultMap.get("return_code"); //状态String outTradeNo = resultMap.get("out_trade_no");//商户订单号String transactionId = resultMap.get("transaction_id");if (returnCode.equals("SUCCESS")) {if (StringUtils.isNotBlank(outTradeNo)) {/*** 注意!!!* 请根据业务流程,修改数据库订单支付状态,和其他数据的相应状态**/logger.info("微信手机支付回调成功,订单号:{}", outTradeNo);xmlBack = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";}}}} catch (Exception e) {e.printStackTrace();}return xmlBack;}@Overridepublic ResultMap refund(String orderNo, double amount, String refundReason){if(StringUtils.isBlank(orderNo)){return ResultMap.error("订单编号不能为空");}if(amount <= 0){return ResultMap.error("退款金额必须大于0");}Map<String, String> responseMap = new HashMap<>();Map<String, String> requestMap = new HashMap<>();WXPay wxpay = new WXPay(wxPayAppConfig);requestMap.put("out_trade_no", orderNo);requestMap.put("out_refund_no", UUIDGenerator.getOrderNo());requestMap.put("total_fee", "订单支付时的总金额,需要从数据库查");requestMap.put("refund_fee", String.valueOf((int)(amount*100)));//所需退款金额requestMap.put("refund_desc", refundReason);try {responseMap = wxpay.refund(requestMap);} catch (Exception e) {e.printStackTrace();}String return_code = responseMap.get("return_code"); //返回状态码String return_msg = responseMap.get("return_msg");//返回信息if ("SUCCESS".equals(return_code)) {String result_code = responseMap.get("result_code"); //业务结果String err_code_des = responseMap.get("err_code_des");//错误代码描述if ("SUCCESS".equals(result_code)) {//表示退款申请接受成功,结果通过退款查询接口查询//修改用户订单状态为退款申请中或已退款。退款异步通知根据需求,可选//return ResultMap.ok("退款申请成功");} else {logger.info("订单号:{}错误信息:{}", orderNo, err_code_des);return ResultMap.error(err_code_des);}} else {logger.info("订单号:{}错误信息:{}", orderNo, return_msg);return ResultMap.error(return_msg);}}}

定义通用返回结果集 ResultMap

package mon.result;import org.apache.http.HttpStatus;import java.util.HashMap;import java.util.Map;/*** @Description 通用返回结果集* @Author * @Date /6/12 15:13*/public class ResultMap extends HashMap<String, Object> {public ResultMap() {put("state", true);put("code", 0);put("msg", "success");}public static ResultMap error(int code, String msg) {ResultMap r = new ResultMap();r.put("state", false);r.put("code", code);r.put("msg", msg);return r;}public static ResultMap error(String msg) {return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);}public static ResultMap error() {return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");}public static ResultMap ok(String msg) {ResultMap r = new ResultMap();r.put("msg", msg);return r;}public static ResultMap ok(Map<String, Object> par) {ResultMap r = new ResultMap();r.putAll(par);return r;}public static ResultMap ok() {return new ResultMap();}public ResultMap put(String key, Object value) {super.put(key, value);return this;}}

6. Swargger2 前后端API接口信息文档

添加依赖

<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-uiartifactId><version>2.9.2</version></dependency>

创建swagger.properties配置文件

# swagger测试项目swagger.title=各种登陆# swagger测试案例swagger.description=邮箱登陆,短信登陆,微信扫码登陆# 版本swagger.version=1.0.0

创建配置类

package com.example.demo1.config;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.service.ApiInfo;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration//配置类@PropertySource("classpath:swagger.properties")@ConfigurationProperties("swagger")@EnableSwagger2public class SwaggerConfig {private String title;private String description;private String version;//getter and setter@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build();}public ApiInfo apiInfo() {return new ApiInfoBuilder().title(this.title).description(this.description).version(this.version).build();}}

API类

@Api(tags = "类说明")public class TestController {@ApiOperation("方法说明")public String test(@ApiParam(value = "参数说明", required = true)//required 说明是否必需@RequestParam String text) {return text;}}

访问网页查看文档

访问:http://localhost:8080/swagger-ui.html

7. ehcache缓存缓存

添加依赖

<!-- cache缓存依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId></dependency>

resources文件下添加ehcache.xml配置文件

<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="/ehcache.xsd" updateCheck="false"><!--磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存path:指定在硬盘上存储对象的路径path可以配置的目录有:user.home(用户的家目录)user.dir(用户当前的工作目录)java.io.tmpdir(默认的临时目录)ehcache.disk.store.dir(ehcache的配置目录)绝对路径(如:d:\\ehcache)查看路径方法:String tmpDir = System.getProperty("java.io.tmpdir");--><diskStore path="java.io.tmpdir"/><!--defaultCache:默认的缓存配置信息,如果不加特殊说明,则所有对象按照此配置项处理maxElementsInMemory:设置了缓存的上限,最多存储多少个记录对象eternal:代表对象是否永不过期 (指定true则下面两项配置需为0无限期)timeToIdleSeconds:最大的发呆时间 /秒timeToLiveSeconds:最大的存活时间 /秒overflowToDisk:是否允许对象被写入到磁盘说明:下列配置自缓存建立起600秒(10分钟)有效 。在有效的600秒(10分钟)内,如果连续120秒(2分钟)未访问缓存,则缓存失效。就算有访问,也只会存活600秒。--><defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="600"timeToLiveSeconds="600" overflowToDisk="true"/><cache name="cache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"timeToLiveSeconds="600" overflowToDisk="true"/></ehcache>

在程序入口MyAppRun类中添加注解@EnableCaching

@EnableCaching@SpringBootApplicationpublic class MyAppRun {public static void main(String[] args) {SpringApplication.run(MyAppRun.class, args);}}

给需要缓存的方法加注解 (一般在service实现类上)@Cacheable(value=”accountCache”)

当调用这个方法的时候,会先从一个名叫 accountCache的缓存中查询,如果没有,则执行实际的方法(即查询数库),并将执行的结果存入缓存中,否则返回缓存中的象。这里的缓存中的 key 就是参数 userName,value 是ehcache.xml 文件里定义的<cache>的name属性值,不设置就是默认

@CachePut 作用和配置方法:

@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用,多数用于数据的更新。@CachePut 注释,这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中,实现缓存与数据库的同步更新。

@CacheEvict 作用和配置方法

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空,多用于删除数据

@CacheConfig

所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了, 所以,有了@CacheConfig这个配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的方法写别的名字,那么依然以方法的名字为准。

@CacheConfig("books")public class BookRepositoryImpl implements BookRepository {@Cacheablepublic Book findBook(ISBN isbn) {...}}

@Caching

有时候我们可能组合多个Cache注解使用;比如用户新增成功后,我们要添加id–>user;username—>user;email—>user的缓存;此时就需要@Caching组合多个注解标签了。

@Caching(put = {@CachePut(value = "user", key = "#user.id"),@CachePut(value = "user", key = "#user.username"),@CachePut(value = "user", key = "#user.email")})public User save(User user) {

8. Spring-Boot注解详解

@SpringBootApplication

这个注解是Spring Boot最核心的注解,用在 Spring Boot的主类上,标识这是一个 Spring Boot 应用,用来开启 Spring Boot 的各项能力。实际上这个注解是@Configuration,@EnableAutoConfiguration,@ComponentScan三个注解的组合。由于这些注解一般都是一起使用,所以Spring Boot提供了一个统一的注解@SpringBootApplication。

@EnableAutoConfiguration

允许 Spring Boot 自动配置注解,开启这个注解之后,Spring Boot 就能根据当前类路径下的包或者类来配置 Spring Bean。

如:当前类路径下有 Mybatis 这个 JAR 包,MybatisAutoConfiguration 注解就能根据相关参数来配置 Mybatis 的各个 Spring Bean。

@EnableAutoConfiguration实现的关键在于引入了AutoConfigurationImportSelector,其核心逻辑为selectImports方法,逻辑大致如下:

●从配置文件META-INF/spring.factories加载所有可能用到的自动配置类;

●去重,并将exclude和excludeName属性携带的类排除;

●过滤,将满足条件(@Conditional)的自动配置类返回;

@Configuration

用于定义配置类,指出该类是 Bean 配置的信息源,相当于传统的xml配置文件,一般加在主类上。如果有些第三方库需要用到xml文件,建议仍然通过@Configuration类作为项目的配置主类——可以使用@ImportResource注解加载xml配置文件。

@ComponentScan

组件扫描。让spring Boot扫描到Configuration类并把它加入到程序上下文。

@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中。

@Repository

用于标注数据访问组件,即DAO组件。

使用@Repository注解可以确保DAO或者repositories提供异常转译,这个注解修饰的DAO或者repositories类会被ComponetScan发现并配置,同时也不需要为它们提供XML配置项。

@Service

一般用于修饰service层的组件,修饰服务层

@RestController

用于标注控制层组件(如struts中的action),表示这是个控制器bean,并且是将函数的返回JSON值直接填入HTTP响应体中,是REST风格的控制器;它是@Controller和@ResponseBody的合集。

@Component

泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注,一般用于实体类。

@Bean

相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。

@AutoWired

byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。

当加上(required=false)时,就算找不到bean也不报错

@Qualifier

当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用

@Resource(name=“name”,type=“type”)

没有括号内内容的话,默认byName。与@Autowired干类似的事。

@RequestMapping

RequestMapping是一个用来处理请求地址映射的注解;提供路由信息,负责URL到Controller中的具体函数的映射,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

@RequestParam

用于注解Controller里面的方法参数

@RequestParam(defaultValue = “默认值”,required = true) --ture表示参数是必须要的

@PathVariable

前端访问以http://localhost:8080/demo/id方式访问,后端方法参数前面必须加上此注解 public String demo(@PathVariable Integer id)

@Profiles

Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。

任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。

@ConfigurationProperties

Spring Boot可使用注解的方式将自定义的properties文件映射到实体bean中,比如config.properties文件。

9. 自定义配置文件类

创建新的maven项目

父包名必须和使用它的项目的父包名一样

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3yFTmBRg-1600694977271)(demo.jpg)]

导入依赖

<dependencies><dependency><groupId>org.springframework.boot<groupId><artifactId>spring-boot-autoconfigure<artifactId><version>2.1.6.RELEASE</version></dependency></dependencies>

创建SayHelloProperties配置文件属性类

package com.ddz.config;import org.springframework.boot.context.properties.ConfigurationProperties;import org.ponent;/*** 属性类、从配置文件中读取属性并赋值*/@Component@ConfigurationProperties(prefix = "myhello")public class SayHelloProperties {private String msg;public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}}

创建SayHello核心事件类 所有的具体功能都在这里完成

package com.ddz.config;/*** 核心事件类完成具体功能* 返回信息*/public class SayHello {private String inMsg;public String sayHello() {return "信息:" + inMsg;}public String getInMsg() {return inMsg;}public void setInMsg(String inMsg) {this.inMsg = inMsg;}}

创建SayHelloAutoConfiguation整合类 负责整合属性类和核心事件类

package com.ddz.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;/*** 整合类*/@Configuration@EnableConfigurationProperties({SayHelloProperties.class})@ConditionalOnClass(SayHello.class)@ConditionalOnProperty(prefix = "myhello", value = "enabled", matchIfMissing = true)public class SayHelloAutoConfiguation {@Autowiredprivate SayHelloProperties sayHelloProperties;@Bean@ConditionalOnMissingBean(SayHello.class)public SayHello creatSayHello() {SayHello sayHello = new SayHello();sayHello.setInMsg(sayHelloProperties.getMsg());return sayHello;}}

使用install上传到本地

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UApmpn37-1600694977272)(install.jpg)]

在需要使用的项目里导入依赖

<dependency><groupId>com.ddz</groupId><artifactId>myconfig</artifactId><version>1.0-SNAPSHOT</version></dependency>

application.yml里面添加属性

myhello:msg: ddz

Controller里面使用注解就能使用

package com.ddz.controller;import com.ddz.config.SayHello;import com.ddz.config.SayHelloAutoConfiguation;import com.ddz.entity.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController@CrossOrigin //解决跨域public class UserController {@Resourceprivate User user;@Autowired private SayHello sayHello; //自定义配置文件事件处理类@GetMapping("/show")public User show() {System.out.println(sayHello.sayHello());return user;}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。