SpringBoot 集成支付宝支付,看这篇就够了
1网页操作步骤
1.进入支付宝开发平台—沙箱环境使用开发者账号登录开放平台控制平台
2.点击沙箱进入沙箱环境说明:沙箱环境支持的产品,可以在沙箱控制台 沙箱应用 > 产品列表 中查看。
3.进入沙箱,配置接口加签方式在沙箱进行调试前需要确保已经配置密钥/证书用于加签,支付宝提供了 系统默认密钥 及 自定义密钥 两种方式进行配置。这里我采取的是默认方式:
开发者如需使用系统默认密钥/证书,可在开发信息中选择系统默认密钥。注意:使用API在线调试工具调试OpenAPI必须使用系统默认密钥。
4.配置应用网关应用网关用于接收支付宝沙箱环境的异步通知(对接 From 蚂蚁消息),如创建门店的被动通知。
注意:仅 HTTP 订阅模式的 From 蚂蚁消息才需要配置应用网关,WebSocket 订阅模式的 From 蚂蚁消息无需配置应用网关。
5.生成自己的密钥至此,网页操作完成
2idea操作步骤
1.导入依赖<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.110.ALL</version>
</dependency>
2.在 application.yml 里面进行配置alipay:
appId:
appPrivateKey:
alipayPublicKey:
notifyUrl: (回调接口)
3.alipay的JAVA配置:AlipayConfig.java读取yml中的配置信息,自动填充到对应的属性
@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {
private String appId;
private String appPrivateKey;
private String alipayPublicKey;
private String notifyUrl;
}
4.支付接口 新建一个 AliPayController.java在Controller中配置gateway_url(调用支付宝url的一个网关地址)、format(JSON形式)、charset(UTF-8)、sign_type(签名方式-rsa2
编写一个Get请求,(方法参数是一个AliPay的配置类里面包括自己生成的订单号、总金额、支付的名称、支付宝交易凭证号和HttpServletResponse)
创建Client(他是由通用SDK提供的Client,负责调用支付宝的API,设置参数包含网关地址、appid、密钥、公钥、format、charset、签名方式)----------------------->创建Client,他是由通用SDK提供的Client,负责调用支付宝的API
创建 AlipayTradePagePayRequest,配置notifyUrl并设置Request参数(参数包含订单号、总金额、支付的名称)(格式:JSON格式)------------------------->创建 Request并设置Request参数
通过AlipayClient执行request调用SDK生成表单,用HttpServletResponse(浏览器响应的一个流)写表单的内容,创建一个html的网页)--------------------------->执行请求,拿到响应的结果,返回给浏览器
@Data
public class AliPay {
private String traceNo;
private double totalAmount;
private String subject;
private String alipayTraceNo;
}
private static final String GATEWAY_URL = "https://openapi.alipaydev.com/gateway.do";
private static final String FORMAT = "JSON";
private static final String CHARSET = "UTF-8";
private static final String SIGN_TYPE = "RSA2";
@Resource
private AliPayConfig aliPayConfig;
@Resource
private OrdersMapper ordersMapper;
@GetMapping("/pay")
public void pay(AliPay aliPay, HttpServletResponse httpResponse) throws Exception {
AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setNotifyUrl(aliPayConfig.getNotifyUrl());
JSONObject bizContent = new JSONObject();
bizContent.set("out_trade_no", aliPay.getTraceNo());
bizContent.set("total_amount", aliPay.getTotalAmount());
bizContent.set("subject", aliPay.getSubject());
bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY");
request.setBizContent(bizContent.toString());
String form = "";
try {
form = alipayClient.pageExecute(request).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
httpResponse.setContentType("text/html;charset=" + CHARSET);
httpResponse.getWriter().write(form);
httpResponse.getWriter().flush();
httpResponse.getWriter().close();
}
5.在拦截器里面加上 忽略alipay接口的配置遇到的坑:
url中有中文字符报错,更换依赖
官网提供有easy版和正式版
easy-sdk 好像不太支持中文的subject,否则 biz_content就会乱码,那我索性就用了 alipay-sdk 正式版的
6.回调接口使用的Post接口,首先验证交易状态是否成功,获取request里面的信息
支付宝验签(使用的是AlipaySignature(通用SDK提供的类)获取一个String字符串将其与sign签名验证),通过后,使用OrderMapper更新到数据库)
使用的Post接口,因为官方建议处理付款成功后的操作在异步调用方法中,异步调用为post请求,异步回调方法必须为公网IP,因为支付宝是基于公网访问,访问不了localhost,需要代理,设置公网IP有两种方案,1、内网穿透,2、将项目部署到服务器,我们项目使用的是内网穿透,使用的是natapp,配置一条免费的隧道,在idea中配置notifyurl接口
@PostMapping("/notify")
public String payNotify(HttpServletRequest request) throws Exception {
if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
System.out.println("=========支付宝异步回调========");
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
params.put(name, request.getParameter(name));
}
String tradeNo = params.get("out_trade_no");
String gmtPayment = params.get("gmt_payment");
String alipayTradeNo = params.get("trade_no");
String sign = params.get("sign");
String content = AlipaySignature.getSignCheckContentV1(params);
boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, aliPayConfig.getAlipayPublicKey(), "UTF-8");
if (checkSignature) {
System.out.println("交易名称: " + params.get("subject"));
System.out.println("交易状态: " + params.get("trade_status"));
System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
System.out.println("商户订单号: " + params.get("out_trade_no"));
System.out.println("交易金额: " + params.get("total_amount"));
System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
System.out.println("买家付款时间: " + params.get("gmt_payment"));
System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
ordersMapper.updateState(tradeNo, "已支付", gmtPayment, alipayTradeNo);
}
}
return "success";
}
3退款流程
创建Client(他是由通用SDK提供的Client,负责调用支付宝的API)(参数包含网关地址、appid、密钥、公钥、format、charset、签名方式)---------------------->创建Client,通用SDK提供的Client,负责调用支付宝的API
创建 AlipayTradePagePayRequest,设置Request参数(参数包含支付宝回调的订单流水号、总金额、我的订单编号)(格式:JSON格式)---------------------------->创建 Request,设置参数
通过AlipayClient执行request获取response,通过isSuccess判断是否成功,成功后更新数据库状态------------->执行请求,更新数据库
@GetMapping("/return")
public Result returnPay(AliPay aliPay) throws AlipayApiException {
String now = DateUtil.now();
Orders orders = ordersMapper.getByNo(aliPay.getTraceNo());
if (orders != null) {
long between = DateUtil.between(DateUtil.parseDateTime(orders.getPaymentTime()), DateUtil.parseDateTime(now), DateUnit.DAY);
if (between > 7) {
return Result.error("-1", "该订单已超过7天,不支持退款");
}
}
AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL,
aliPayConfig.getAppId(), aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET,
aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
JSONObject bizContent = new JSONObject();
bizContent.set("trade_no", aliPay.getAlipayTraceNo());
bizContent.set("refund_amount", aliPay.getTotalAmount());
bizContent.set("out_request_no", aliPay.getTraceNo());
request.setBizContent(bizContent.toString());
AlipayTradeRefundResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
System.out.println("调用成功");
ordersMapper.updatePayState(aliPay.getTraceNo(), "已退款", now);
return Result.success();
} else {
System.out.println(response.getBody());
return Result.error(response.getCode(), response.getBody());
}
}
订单三十分钟未支付自动取消使用消息队列
我们可以采用rabbitMQ的延时队列。RabbitMQ具有以下两个特性,可以实现延迟队列
RabbitMQ可以针对Queue和Message设置 x-message-tt,来控制消息的生存时间,如果超时,则消息变为dead letter
RabbitMQ的Queue可以配置x-dead-letter-exchange 和x-dead-letter-routing-key(可选)两个参数,用来控制队列内出现了deadletter,则按照这两个参数重新路由。结合以上两个特性,就可以模拟出延迟消息的功能
优缺点
优点: 高效,可以利用rabbitmq的分布式特性轻易的进行横向扩展,消息支持持久化增加了可靠性。
缺点: 本身的易用度要依赖于rabbitMq的运维.因为要引用rabbitMq,所以复杂度和成本变高。
用户下单之后,投递一个msg消息存放在msg服务器daunt,该消息msg消息过期时间为30分钟,一直未被订单消费者消费,消息会转移到死信交换机路由到死信队列中,被我们的死信消费者30分钟后消息。
死信消费者在根据订单号码查询支付订单状态,如果是未支付情况下,则将该订单设置未超时。
对筛选出来的订单号码进行核对校验:
订单中是否存在
携带订单号码调用支付宝查询订单支付状态是否为待支付
更新该订单号码状态
来源|juejin.cn/post/7269357836026904633
相关知识
全方位了解以色列农业,这篇就够了
养坏了几十盆花,才总结出来的避坑心得,养花新手看这篇就够了
兰花开花指南?8大要点,看看这篇就够了
全篇干货!动物饲养人的法律责任看这篇就够了!
支付宝如何修改花呗支付方式
支付宝取消美团会员,下一步用户是不是就不能自由选择支付方式?
支付宝中标铁路客票电子支付系统
结个婚一共要花多少钱? 时间和流程怎么安排? 收藏这篇就够了!
把佛山花海穿上身会有多美?拍花的正确姿势,看这篇就够了!
一文看“透”你所不知道在线支付
网址: SpringBoot 集成支付宝支付,看这篇就够了 https://www.huajiangbk.com/newsview849404.html
上一篇: Javen/IJPay |
下一篇: #支付宝 APP支付如何接入花呗 |
推荐分享

- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039