Springboot整合支付宝alipay-实现沙箱支付功能-详细
一、官网介绍和参考文档
提供一个官网的API接口文档,重点在于参数!
官网API接口参数文档:https://opendocs.alipay.com/apis/api_1/alipay.trade.page.pay?scene=common
如果报错,可看官网这个链接文档!官网包含各种接口文档,供大家学习使用!
报错信息:订单信息无法识别,建议联系卖家,错误码:INVALID_PARAMETER
网址:https://opendocs.alipay.com/support/01rfv4
二、创建-支付宝开放平台用户
1、百度搜索:支付宝开放平台
2、登录账号
使用手机支付宝,登录即可!!
注意:如果弹窗说要同意协议、支持等,点击“同意”、“确定”、“支持”,即可!
3、进入:控制台 ,–>再进入下面的沙箱:沙箱
进入:控制台
进入:沙箱(在最下面)
3、启用(产生密钥)—>查看:生产的密钥 –>修改:地址
启用 和 查看:之后需要用到密钥!!!!
修改地址:对接的是我们的 application-alipay.properties配置文件
三、代码实现-沙箱支付
3.1、创建项目、项目结构展示
第一步:创建springboot项目,选择 Spring Initializr项目!
第二步:选择 springboot 2.x的版本,并勾选依赖!
首先给大家展示一下,整个项目的,项目结构:
3.2、依赖配置文件 pom.xml
<dependencies>
<!--
个人版本踩坑:
不加这个依赖的话,当在配置类中
使用@ConfigurationProperties(prefix = "aliyun")注解时,
我这个版本的spring boot会提示有问题-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.31</version>
</dependency>
</dependencies>
3.3、application.yml 和 application-alipay.properties 文件编写
第一步:application.yml
server:
port: 8081
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/?characterEncoding=utf-8&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
# 项目名称
application:
name: aliyun-alipay
# 模板引擎配置
thymeleaf:
encoding: UTF-8
cache: false
suffix: .html
prefix: classpath:templates/
#mybatis:
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# map-underscore-to-camel-case: true
# type-aliases-package: com.it.pojo
# mapper-locations: classpath:/mapper/*.xml
第二步:application-alipay.properties
沙箱支付的配置:
# ----------阿里云-支付宝相关配置-----------
# 应用ID
alipay.appId=2021.....
# 应用公钥 -- 选择最长的复制粘贴
alipay.alipayPublicKey=MIIEvwIBADANBgkqhki.....
# 应用私钥 -- 较短的复制粘贴
alipay.privateKey=MIIBIjANBgkqhkiG9w0B.....
# 异步通知回调地址 - 用户回调地址# https://www.baidu.com/
alipay.notifyUrl=http://127.0.0.1:8081/paySuccess
# 同步回调地址 - 成功回调地址
alipay.returnUrl=http://127.0.0.1:8081/paySuccess
# 编码格式
alipay.charset=UTF-8
# 签名类型 - 密钥凭证
alipay.signType=RSA2
# 支付宝的网关地址
alipay.gatewayUrl=https://openapi.alipaydev.com/gateway.do
#生成日志文件
alipay.logPath="F:\\alipay\\log"
查看 公钥 和私钥:
复制公钥 和 私钥到配置文件:
3.4、pojo、bean、config、service、service.impl、controller 包名(实体、alipay的bean、配置类、业务层、业务实现层、控制层)
1、pojo实体类:订单参数实体类:Order
package com.it.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true) //链式
public class Order {
/**
* 商户订单号
*/
private String out_trade_no;
/**
* 订单名称
*/
private String subject;
/**
* 付款金额
*/
private String total_amount;
/**
* 超时时间参数
*/
private String timeout_express = "10m";
/**
* 产品编号
*/
private String product_code = "FAST_INSTANT_TRADE_PAY";
}
2、bean沙箱的组件:Alipay
package com.it.bean;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.it.config.AliPayConfig;
import com.it.pojo.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AliPay {
@Autowired
private AliPayConfig aliPayConfig;
public String pay(Order order) throws AlipayApiException {
//支付网关
String serverUrl = aliPayConfig.getGatewayUrl();
// AppId
String appId = aliPayConfig.getAppId();
// 用户密钥(私钥),即PKCS8格式RSA2私钥
String privateKey = aliPayConfig.getPrivateKey();
//格式化为json格式
String format = "json";
//编码
String charset = aliPayConfig.getCharset();
//支付宝公钥,即对应Appid下的支付宝公钥
String alipayPublicKey = aliPayConfig.getAlipayPublicKey();
//签名方式
String signType = aliPayConfig.getSignType();
//页面跳转同步通知页面路径
String returnUrl = aliPayConfig.getReturnUrl();
//服务器异步通知页面路径
String notifyUrl = aliPayConfig.getNotifyUrl();
//1、获取初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(
serverUrl, appId, privateKey, format, charset, alipayPublicKey, signType);
//2、设置请求参数
AlipayTradePagePayRequest alipayTradePagePayRequest = new AlipayTradePagePayRequest();
// 页面跳转同步通知页面路径
alipayTradePagePayRequest.setReturnUrl(returnUrl);
alipayTradePagePayRequest.setNotifyUrl(notifyUrl);
//封装参数(json格式)
alipayTradePagePayRequest.setBizContent(JSON.toJSONString(order));
// 3、请求支付宝进行付款,并获取支付结果
String body = alipayClient.pageExecute(alipayTradePagePayRequest).getBody();
//放回信息
return body;
}
}
3、config配置类:AliPayConfig
用于读取 application-alipay.properties文件的数据(属性)!!
package com.it.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(value = "classpath:application-alipay.properties")
@ConfigurationProperties(prefix = "alipay") //前缀
@Data
public class AliPayConfig {
private String appId;
private String privateKey;
private String alipayPublicKey;
private String notifyUrl;
private String returnUrl;
private String charset;
private String signType;
private String gatewayUrl;
}
4、service业务层:AliPayService
package com.it.service;
import com.alipay.api.AlipayApiException;
import com.it.pojo.Order;
public interface AliPayService {
/**
* 支付宝支付接口
*/
String aliPay(Order order) throws AlipayApiException;
}
5、service.impl业务实现层:AliPayServiceImpl
package com.it.service.impl;
import com.alipay.api.AlipayApiException;
import com.it.bean.AliPay;
import com.it.pojo.Order;
import com.it.service.AliPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @date 2023/3/23 10:47
*/
@Service
public class AliPayServiceImpl implements AliPayService {
@Autowired
private AliPay aliPay;
@Override
public String aliPay(Order order) throws AlipayApiException {
System.out.println("order----service--:"+order);
return aliPay.pay(order);
}
}
6、controller控制层(web层):AliPayController
package com.it.controller;
import com.alipay.api.AlipayApiException;
import com.it.pojo.Order;
import com.it.service.AliPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@RestController
public class AliPayController {
@Autowired
private AliPayService aliPayService;
/**
* 进入支付主页
* @return
*/
@GetMapping("/")
public ModelAndView index(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("testAliPay");
return modelAndView;
}
/**
* 提交订单
* @param outTradeNo
* @param subject
* @param totalAmount
* @param description
* @return
* @throws AlipayApiException
*/
@PostMapping("/order/alipay")
public String aliPay(String outTradeNo,String subject,
String totalAmount) throws AlipayApiException {
System.out.println("--------进入提交支付----------");
Order order = new Order();
order.setOut_trade_no(outTradeNo);
order.setSubject(subject);
order.setTotal_amount(totalAmount);
System.out.println("order-----:"+order);
return aliPayService.aliPay(order);
}
/**
* 支付成功
* @return
*/
@GetMapping("/paySuccess")
public ModelAndView paySuccess(){
System.out.println("--------支付成功----------");
//如果支付成功,订单就要新增到数据库
//如果取消支付,也要新增订单到数据库,取消订单-状态
//订单查询能够查出订单状态 信息
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("success");
System.out.println("支付成功");
return modelAndView;
}
}
3.5、templates模板-编写,html页面
支付成功页面:编写页面:success.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>支付成功</title>
</head>
<body>
<h2>支付成功</h2>
</body>
</html>
支付成功页面:编写页面:testAliPay.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>订单支付</title>
</head>
<body>
<table border="1" style="margin: auto;">
<form th:action="@{/order/alipay}" th:method="post" style="margin: auto;">
<tr>
<td>订单号:</td>
<td>
<input type="text" name="outTradeNo" value="25852">
</td>
</tr>
<tr>
<td>商品名称:</td>
<td>
<input type="text" name="subject" value="银河">
</td>
</tr>
<tr>
<td>商品价格:</td>
<td>
<input type="text" name="totalAmount" value="520.00">
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;">
<input type="submit" value="立即支付">
</td>
</tr>
</form>
</table>
</body>
</html>
四、运行测试
注意:支付宝沙箱支付时,可能会遇到各种坑:如我在开头说的那种!
处理方式有几种:我这里说几种我用过的:
第一种:清理浏览器缓存,或者换一个浏览器
第二种:有时支付宝开放平台可能在做系统维护,或者升级时,是无法使用的!
第三种:要输入“支付宝开放平台”提供的账号密码。当然,这里可以是他人的,但一定也要是”支付宝开放平台“的哦!!!
遇到报错可看:https://blog.csdn.net/dayonglove2018/article/details/122061298
4.1、平台账号、密码
4.2、点击“立即支付” —》进入支付页面,输入账号密码—-》点击:“下一步”
4.3、到确认支付页面:
4.4、等待支付成功,并返回页面!!—》success.html
这个页面:
不管你什么时候开始,都不迟!!都还来得及!! --Jesse.超