Springboot整合支付宝支付(沙箱)
官方文档中心:
https://opendocs.alipay.com/apis/api_1/
前期准备
注册支付宝,登录,获取APPID等。
1.创建应用
官方创建应用提供方法:
/open/200/105310
开发者使用支付宝账号登录 开放平台控制台(需实名认证的支付宝账号)。
控制台–沙箱
2.获取到APPID
- APPID会配置到项目中使用
3.配置RSA2密钥
密钥生成地址:
/keytool/create
生成应用私钥与应用公钥
- 应用私钥会配置到项目中使用
配置应用公钥
选择自定义密钥
将生成好的公钥放入到配置中
保存之后,生成支付宝公钥。
- 支付宝公钥会配置到项目中使用
4.支付宝网关
/gateway.do
- 支付宝网关会配置到项目中使用
至此,项目中使用到的配置全拿到了。开始整合项目
开发
1.项目结构
主要是添加lombok,alipay-sdk-java,slf4j-api
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0" xmlns:xsi="http:///2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId></groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId></groupId>
<artifactId>alpay</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>alpay</name>
<description>Demo project for Spring Boot</description>
<properties>
<>1.8</>
</properties>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 支付SDK-->
<dependency>
<groupId></groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.9.9</version>
</dependency>
<!--日志记录-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.31</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId></groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId></groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
server.port=2080
# APPID 登录支付宝会生成
app.appId=登录支付宝会生成
# 应用私钥 生成密钥器生成
app.privateKey=使用生成器生成的
# 支付宝公钥 RSA2密钥(推荐) 配置好并启动会生成
app.publicKey=获取到公钥
app.notifyUrl=http://localhost:2080/ali/success
app.returnUrl=http://localhost:2080/ali/success
app.signType=RSA2
app.charset=utf-8
# 支付宝网关
app.gatewayUrl=https://openapi.alipaydev.com/gateway.do
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
package com.zjy.alpay.controller;
import com.alipay.api.AlipayApiException;
import com.zjy.alpay.bean.AliPayBean;
import com.zjy.alpay.service.PayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/ali")
public class OrderController {
/**日志对象*/
private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
@Autowired
private PayService payService;
@RequestMapping("/pay")
@ResponseBody
public String alipay(String outTradeNo, String subject, String totalAmount, String body) throws AlipayApiException {
logger.info("商户订单号为{},订单名称为{},付款金额为{},商品描述{}", outTradeNo, subject, totalAmount, body);
AliPayBean alipayBean = new AliPayBean();
alipayBean.setOut_trade_no(outTradeNo);
alipayBean.setSubject(subject);
alipayBean.setTotal_amount(totalAmount);
alipayBean.setBody(body);
return payService.aliPay(alipayBean);
}
@RequestMapping("/success")
@ResponseBody
public String success(){
return "交易成功!";
}
@RequestMapping(value = "/index")
public String payCoin(){
return "";
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
package com.zjy.alpay.service;
import com.alipay.api.AlipayApiException;
import com.zjy.alpay.bean.AliPayBean;
public interface PayService {
String aliPay(AliPayBean aliPayBean) throws AlipayApiException;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
package com.zjy.alpay.service;
import com.alipay.api.AlipayApiException;
import com.zjy.alpay.bean.AliPayBean;
import com.zjy.alpay.config.Alipay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 支付服务接口
*/
@Service
public class PayServiceImpl implements PayService{
/**日志对象*/
private static final Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);
@Autowired
private Alipay alipay;
@Override
public String aliPay(AliPayBean aliPayBean) throws AlipayApiException {
logger.info("调用支付服务接口...");
return alipay.pay(aliPayBean);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
package com.zjy.alpay.config;
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.zjy.alpay.bean.AliPayBean;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
public class Alipay {
/**日志对象*/
private static final Logger logger = LoggerFactory.getLogger(Alipay.class);
private final String format = "json";
/**
* appId
*/
@Value("${}")
private String appId;
/**
* 商户私钥
*/
@Value("${}")
private String privateKey;
/**
* 支付宝公钥
*/
@Value("${}")
private String publicKey;
/**
* 服务器异步通知页面路径,需要公网能访问到
*/
@Value("${}")
private String notifyUrl;
/**
* 服务器同步通知页面路径,需要公网能访问到
*/
@Value("${}")
private String returnUrl;
/**
* 签名方式
*/
@Value("${}")
private String signType;
/**
* 字符编码格式
*/
@Value("${}")
private String charset;
/**
* 支付宝网关
*/
@Value("${}")
private String gatewayUrl;
public String pay(AliPayBean aliPayBean) throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
gatewayUrl, appId, privateKey, format, charset, publicKey, signType);
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(returnUrl);
alipayRequest.setNotifyUrl(notifyUrl);
alipayRequest.setBizContent(JSON.toJSONString(aliPayBean));
logger.info("封装请求支付宝付款参数为:{}", JSON.toJSONString(alipayRequest));
String result = alipayClient.pageExecute(alipayRequest).getBody();
logger.info("请求支付宝付款返回参数为:{}", result);
return result;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
package com.zjy.alpay.bean;
import lombok.Data;
/**
* 支付宝支付实体
*/
@Data
public class AliPayBean {
/**
* 商户订单号
*/
private String out_trade_no;
/**
* 订单名称
*/
private String subject;
/**
* 付款金额
*/
private String total_amount;
/**
* 商品描述
*/
private String body;
/**
* 超时时间参数
*/
private String timeout_express = "60m";
/**
* 产品编号
*/
private String product_code = "FAST_INSTANT_TRADE_PAY";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/ali/pay" method="post">
订单号:<input type="text" name="outTradeNo" required><br/>
订单名称:<input type="text" name="subject" required><br/>
付款金额:<input type="text" name="totalAmount" required><br/>
商品描述:<input type="text" name="body"><br/>
<input type="submit" value="下单"> <input type="reset" value="重置">
</form>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
至此,代码贴完了。开始测试
测试
1.启动项目
启动项目,并访问:http://localhost:2080/
2.下单
输入一些个信息,点下单
直接返回提示:
支付存在钓鱼风险!
有2种处理方法:
- 关闭所有之前所登录的支付宝的页面,并且,清空浏览器缓存。
- 或者换一个没有登录过沙箱的浏览器
我的都是在谷歌浏览器制作的,所以会报这个错,但是又不想清空缓存。所以,选择第二种方法:换个浏览器!
换了个IE浏览器,再继续操作
会直接跳转到支付页面,由于是沙箱测试,所有自己手机的支付宝是扫不了的,得使用沙箱版本的支付宝APP扫描。这里直接用账号和密码来操作。得用买家的账号与密码
3.获取买家账号与密码和支付密码
4.支付
5.支付成功
6.跳转页面
金额扣除
控制台打印
注意坑
下单失败
如果点"下单"操作,返回提示:
订单信息无法识别,建议联系卖家。
错误码:INVALID_PARAMETER
引起原因:
目前只发现两个原因,就是AliPayBean里封装的实体字段写的有问题
1.去请求支付宝api就是要 _ 拼接的,不能使用驼峰拼接
- 正确写法:
/**
* 商户订单号
*/
private String out_trade_no;
/**
* 订单名称
*/
private String subject;
/**
* 付款金额
*/
private String total_amount;
/**
* 商品描述
*/
private String body;
/**
* 超时时间参数
*/
private String timeout_express = "60m";
/**
* 产品编号
*/
private String product_code = "FAST_INSTANT_TRADE_PAY";
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 错误写法:
/**
* 商户订单号
*/
private String outTradeNo;
/**
* 订单名称
*/
private String subject;
/**
* 付款金额
*/
private String totalAmount;
/**
* 商品描述
*/
private String body;
/**
* 超时时间参数
*/
private String timeoutExpress = "60m";
/**
* 产品编号
*/
private String productCode = "FAST_INSTANT_TRADE_PAY";
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
2.产品码。
商家和支付宝签约的产品码。 枚举值(点击查看签约情况):
FAST_INSTANT_TRADE_PAY:新快捷即时到账产品。
注:目前仅支持FAST_INSTANT_TRADE_PAY
测试OK!
欢迎大神指导,可以留言交流!
======================
本人原创文章,转载注明出入!
=================