下面是详细讲解“SpringBoot集成支付宝沙箱支付的实现示例”的完整攻略:
一、前置准备
- 注册并开通阿里云账号。
- 创建一个支付宝沙箱应用,获取支付宝沙箱应用 ID 和秘钥。
- 了解支付宝接口文档和SDK相关内容。
- 选择合适的开发语言和开发框架。本教程采用 SpringBoot 框架。
二、添加依赖
在 pom.xml 文件中添加 Alibaba maven repository 中央仓库和支付宝沙箱支付的 SDK 依赖。
<repositories>
<repository>
<id>alibaba-nexus</id>
<name>Alibaba Nexus Repository</name>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java-all</artifactId>
<version>3.3.0.RELEASE</version>
</dependency>
</dependencies>
三、配置支付宝客户端
在 SpringBoot 的配置文件中,添加以下关于支付宝客户端相关的配置信息。
# 支付宝沙箱环境公共参数
alipay.sandbox.gateway.url=https://openapi.alipaydev.com/gateway.do
alipay.sandbox.app.id=沙箱应用 ID
alipay.sandbox.private.key=沙箱应用私钥
alipay.sandbox.public.key=沙箱应用公钥
alipay.sandbox.notify.url=回调 URL
四、实现支付
在代码实现支付前,需要为客户端读取支付宝沙箱公钥、自己的私钥、支付宝公钥。为了完成这些操作,可以将公钥和私钥放在 resources 目录下,使用密钥工具类 IORUtils 进行加载。
1、IOUtils 工具类
public class IOUtils {
/**
* 获取文件内容
*
* @param resource 资源信息
* @return 文件内容
*/
public static String getResource(String resource) {
try (InputStream inputStream = new ClassPathResource(resource).getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
byte[] bytes = new byte[bufferedInputStream.available()];
bufferedInputStream.read(bytes);
return new String(bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 获取私钥
*
* @param resource 私钥文件路径
* @return 私钥
*/
public static String getPrivateKey(String resource) {
try {
return getResource(resource);
} catch (Exception e) {
throw new RuntimeException("获取私钥失败!", e);
}
}
/**
* 获取公钥证书
*
* @param resource 公钥证书路径
* @return 公钥证书
*/
public static String getCertPublicKey(String resource) {
try {
InputStream inputStream = new ClassPathResource(resource).getInputStream();
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream);
inputStream.close();
return Base64Utils.encodeToString(x509Certificate.getPublicKey().getEncoded());
} catch (Exception e) {
throw new RuntimeException("获取公钥证书失败!", e);
}
}
/**
* 获取PKCS8格式私钥对象
*
* @param resource 私钥文件路径
* @return AlibabaRSA2PrivateKey PKCS8格式私钥对象
*/
public static AlibabaRSA2PrivateKey getCFGPrivateKey(String resource) {
try {
byte[] privateKeyBytes = getPemPrivateKey(readContent(resource));
if (privateKeyBytes == null) {
throw new RuntimeException("私钥内容为空,请检查私钥文件!");
}
RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(privateKeyBytes));
if (asn1PrivKey == null) {
throw new RuntimeException("ASN1解析私钥失败,请检查私钥文件!");
}
RSAPrivateCrtKey rsaKey = new RSAPrivateCrtKey(
asn1PrivKey.getModulus(),
asn1PrivKey.getPublicExponent(),
asn1PrivKey.getPrivateExponent(),
asn1PrivKey.getPrime1(),
asn1PrivKey.getPrime2(),
asn1PrivKey.getExponent1(),
asn1PrivKey.getExponent2(),
asn1PrivKey.getCoefficient());
return new AlibabaRSA2PrivateKey(rsaKey.getEncoded());
} catch (Exception e) {
throw new RuntimeException("获取PKCS8格式私钥对象失败!", e);
}
}
/**
* 获取pem格式的报文
*
* @param pemContent pem格式的私钥报文
* @return byte[] 二进制格式的报文
*/
public static byte[] getPemPrivateKey(String pemContent) {
if (pemContent == null) {
return null;
}
String[] strings = pemContent.split("\n");
StringBuilder pkcs8Lines = new StringBuilder();
for (String str : strings) {
if (!str.startsWith("--")) {
pkcs8Lines.append(str);
}
}
return Base64Utils.decodeFromString(pkcs8Lines.toString());
}
/**
* 读取文件内容
*
* @param filePath
* @return 文件内容
* @throws Exception
*/
public static String readContent(String filePath) throws Exception {
String res = null;
File file = new File(filePath);
if (file != null && file.exists()) {
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
String line = null;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
}
res = stringBuilder.toString();
} else {
throw new RuntimeException("文件不存在!");
}
return res;
}
}
2、支付宝支付服务启动类
在 SpringBootApplication 启动类下创建 PayService 类,创建拼装支付请求的方法aliPay,订单查询方法queryOrder,退款申请方法refundOrder等。这里只展示aliPay函数的实现。
@Service
@Slf4j
public class PayService {
@Value("${alipay.sandbox.app.id}")
private String appId;
@Value("${alipay.sandbox.private.key}")
private String privateKey;
@Value("${alipay.sandbox.public.key}")
private String publicKey;
@Value("${alipay.sandbox.gateway.url}")
private String gatewayUrl;
@Value("${alipay.sandbox.notify.url}")
private String notifyUrl;
@Autowired
private OrderService orderService;
/**
* 支付宝支付
*
* @param order
* @return
*/
public String aliPay(Order order) {
try {
log.info(">>> 支付宝支付开始:{}", order);
// 1、构建AlipayClient实例
AlipayClient alipayClient = buildAlipayClient();
// 2、构建AlipayTradeAppPayRequest实例
AlipayTradeAppPayRequest payRequest = buildTradePayRequest(order);
// 3、调用SDK生成支付串
AlipayTradeAppPayResponse payResponse = alipayClient.sdkExecute(payRequest);
// 4、处理支付结果
String resultString = payResponse.getBody();
log.info(">>> 支付宝支付结果:{}", resultString);
return resultString;
} catch (AlipayApiException e) {
throw new RuntimeException("支付宝支付失败!", e);
}
}
/**
* 构建AlipayClient实例
*
* @return
*/
private AlipayClient buildAlipayClient() {
return new DefaultAlipayClient(
gatewayUrl, appId, privateKey, "json", "utf-8", publicKey, "RSA2");
}
/**
* 构建AlipayTradeAppPayRequest实例
*
* @param order
* @return
*/
private AlipayTradeAppPayRequest buildTradePayRequest(Order order) {
// 1、构建生成支付串请求对象
AlipayTradeAppPayRequest payRequest = new AlipayTradeAppPayRequest();
payRequest.setNotifyUrl(notifyUrl);
payRequest.setBizContent(buildTradePayBizContent(order));
return payRequest;
}
/**
* 构建生成支付串请求BizContent
*
* @param order
* @return
*/
private String buildTradePayBizContent(Order order) {
AlipayTradeAppPayModel payModel = new AlipayTradeAppPayModel();
payModel.setSubject("测试商品");
payModel.setOutTradeNo(order.getOrderNo());
payModel.setTotalAmount(order.getOrderAmount().toString());
payModel.setBody("测试商品描述");
payModel.setProductCode("QUICK_MSECURITY_PAY");
return JSON.toJSONString(payModel);
}
}
五、测试支付
添加测试类进行支付调用,并在阿里云管理后台查看支付宝账单确认支付已经成功。
@SpringBootTest
public class PayServiceTest {
@Autowired
private PayService payService;
@Test
public void testAliPay() {
Order order = new Order();
order.setOrderNo(UUID.randomUUID().toString());
order.setOrderAmount(new BigDecimal("0.01"));
String result = payService.aliPay(order);
log.info(">>> 支付结果:{}", result);
}
}
六、遇到问题处理
如果支付请求失败,可以通过以下方式查看日志,找到错误原因。
# 打开支付宝验签日志开关
log4j.logger.com.alipay.api=com.alipay.api.log4j.AlipayLog4jLogger
# 查看支付宝验签日志
tail -f /path/to/your/tomcat/logs/catalina.out|egrep "com.alipay.api.log"
# 自定义消息处理类
@ControllerAdvice
public class AlipayExceptionHandler {
@ExceptionHandler(AlipayApiException.class)
public void handleAlipayException(AlipayApiException e) {
// 处理支付宝请求异常
log.error("支付宝请求异常!", e);
}
@ExceptionHandler(AopInvocationException.class)
public void handleInvocationException(AopInvocationException e) {
// 处理支付宝请求接口调用异常
log.error("支付宝请求接口调用异常!", e);
}
}
以上就是SpringBoot集成支付宝沙箱支付的实现示例攻略的完整解释。另外,还可以通过“SpringBoot集成微信支付”的方式实现微信支付功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot集成支付宝沙箱支付的实现示例 - Python技术站