引言
Spring Boot 是一个广受欢迎的 Java 框架,它极大地简化了基于 Java 的 Web 应用程序的开发流程。支付宝,作为中国领先的第三方支付平台,提供了丰富的 API 以支持多种支付方式。在本文中,我将概述如何在 Spring Boot 应用中集成支付宝支付,包括手机网站支付、电脑网站支付、移动支付、扫码支付和 APP 支付等场景。
一、手机网站支付
手机网站支付指的是通过手机浏览器完成的支付方式,具体实现方式如下:
1.引入支付宝SDK依赖
在pom.xml文件中添加以下依赖:
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.22.ALL</version>
</dependency>
2.配置支付宝信息
在SpringBoot的配置文件中,添加支付宝相关的配置,
alipay:
alipayPublicKey: ALIPAY_PUBLIC_KEY
appId: YOUR_APP_ID
gateway: https://openapi.alipay.com/gateway.do
appPrivateKey: YOUR_PRIVATE_KEY
@RestController
public class PayController {
@Value("${alipay.appId}")
private String appId;
@Value("${alipay.gateway}")
private String gateway;
@Value("${alipay.appPrivateKey}")
private String appPrivateKey;
@Value("${alipay.alipayPublicKey}")
private String alipayPublicKey;
@RequestMapping("/pay")
public String pay(HttpServletRequest request) throws AlipayApiException {
// 实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(gateway, appId, appPrivateKey, "json", "utf-8", alipayPublicKey, "RSA2");
// 实例化请求对象
AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
// 设置回调地址
alipayRequest.setReturnUrl(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/return_url");
alipayRequest.setNotifyUrl(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/notify_url");
// 设置订单信息
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo("20150320010101001");
model.setSubject("Iphone6 16G");
model.setTotalAmount("0.01");
model.setBody("Iphone6 16G");
model.setTimeoutExpress("30m");
model.setProductCode("QUICK_WAP_WAY");
alipayRequest.setBizModel(model);
// 调用SDK生成表单
String form = alipayClient.pageExecute(alipayRequest).getBody();
return form;
}
@RequestMapping("/return_url")
public String returnUrl(HttpServletRequest request) throws AlipayApiException {
// 获取支付宝GET过来反馈信息
Map<String, String> params = new HashMap<String, String>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 解码
params.put(name, URLDecoder.decode(valueStr, "UTF-8"));
}
// 验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
if (signVerified) {
return "success";
} else {
return "fail";
}
}
@RequestMapping("/notify_url")
public String notifyUrl(HttpServletRequest request) throws AlipayApiException {
// 获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<String, String>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 解码
params.put(name, URLDecoder.decode(valueStr, "UTF-8"));
}
// 验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
if (signVerified) {
// 商户订单号
String outTradeNo = params.get("out_trade_no");
// 支付宝交易号
String tradeNo = params.get("trade_no");
// 交易状态
String tradeStatus = params.get("trade_status");
if (tradeStatus.equals("TRADE_SUCCESS")) {
// TODO: 处理业务逻辑
return "success";
}
}
return "fail";
}
}
二、电脑网站支付
脑网站支付是指在电脑浏览器中完成支付的一种方式。下面是集成步骤:
依赖和参数配置如上:(手机网站支付方式)
编写支付请求接口
@RestController
public class PayController {
@Value("${alipay.appId}")
private String appId;
@Value("${alipay.gateway}")
private String gateway;
@Value("${alipay.appPrivateKey}")
private String appPrivateKey;
@Value("${alipay.alipayPublicKey}")
private String alipayPublicKey;
@RequestMapping("/pay")
public String pay(HttpServletRequest request) throws AlipayApiException {
// 实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(gateway, appId, appPrivateKey, "json", "utf-8", alipayPublicKey, "RSA2");
// 实例化请求
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
// 设置异步通知地址
alipayRequest.setNotifyUrl("http://localhost:8080/notify_url");
// 设置同步通知地址
alipayRequest.setReturnUrl("http://localhost:8080/return_url");
// 设置订单号
String outTradeNo = "20220326112000001";
// 设置订单总金额
String totalAmount = "100.00";
// 设置订单标题
String subject = "测试电脑网站支付";
// 组装请求参数
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(totalAmount);
model.setSubject(subject);
model.setBody("测试电脑网站支付");
model.setProductCode("FAST_INSTANT_TRADE_PAY");
alipayRequest.setBizModel(model);
// 请求支付宝进行支付
String form = alipayClient.pageExecute(alipayRequest).getBody();
return form;
}
@RequestMapping("/return_url")
public String returnUrl(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
// 获取支付宝GET过来反馈信息
Map<String, String> params = new HashMap<String, String>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 解码
params.put(name, URLDecoder.decode(valueStr, "UTF-8"));
}
// 验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
if (signVerified) {
// 获取订单号
String outTradeNo = params.get("out_trade_no");
// 获取支付宝交易号
String tradeNo = params.get("trade_no");
// 获取交易状态
String tradeStatus = params.get("trade_status");
if (tradeStatus.equals("TRADE_SUCCESS")) {
// TODO: 处理业务逻辑
return "success";
}
}
return "fail";
}
@RequestMapping("/notify_url")
public String notifyUrl(HttpServletRequest request) throws AlipayApiException {
// 获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<String, String>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 解码
params.put(name, URLDecoder.decode(valueStr, "UTF-8"));
}
// 验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
if (signVerified) {
// 获取订单号
String outTradeNo = params.get("out_trade_no");
// 获取支付宝交易号
String tradeNo = params.get("trade_no");
// 获取交易状态
String tradeStatus = params.get("trade_status");
if (tradeStatus.equals("TRADE_SUCCESS")) {
// TODO: 处理业务逻辑
return "success";
}
}
return "fail";
}
}
解读:
三. 移动支付
支付宝还提供了更加便捷的移动支付的功能,让用户可以在手机端完成支付。移动支付实现过程如下:
在使用支付宝移动支付服务之前,首要步骤是注册并登录支付宝开发者平台,以便创建并管理您的应用。以下是详细的操作流程:
1.准备操作
1.1. 访问支付宝开发者中心官网:https://openhome.alipay.com/platform/appManage.htm
1.2. 使用您的支付宝开发者账号登录,若尚未拥有账号,请先完成注册流程。
1.3. 在开发者中心界面,寻找并点击“创建应用”的按钮,以启动新应用的创建流程。
1.4. 在创建应用页面,认真填写应用名称,并选择应用类型为“移动应用”。完成信息填写后,提交以继续。
1.5. 应用创建成功后,系统会自动生成一系列关键信息,包括AppID(应用ID)和私钥等。
2.引入支付宝SDK依赖和相关参数 与上述操作相同(这里不做重复描述)
3.编写支付接口
重新修改下 PayController 接口:
@Controller
public class PayController {
@Autowired
private AliPayConfig aliPayConfig;
@PostMapping("/pay")
@ResponseBody
public String pay(@RequestParam("outTradeNo") String outTradeNo,
@RequestParam("totalAmount") String totalAmount,
@RequestParam("subject") String subject) throws AlipayApiException {
// 创建 AlipayClient 对象,用于调用支付宝接口
AlipayClient alipayClient = new DefaultAlipayClient(
aliPayConfig.getServerUrl(),
aliPayConfig.getAppId(),
aliPayConfig.getPrivateKey(),
"json",
"utf-8",
aliPayConfig.getPublicKey(),
"RSA2");
// 创建 AlipayTradeAppPayRequest 对象,用于设置支付参数
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
// 设置异步回调地址
request.setNotifyUrl(aliPayConfig.getNotifyUrl());
// 设置订单信息
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(totalAmount);
model.setSubject(subject);
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
// 调用支付接口,获取支付参数
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
// 返回客户端支付参数
return response.getBody();
}
}
4. 处理支付结果回调
在客户端支付完成后,支付宝的服务器就会将支付结果通知到客户端的服务器上的回调接口,所以我们还需要编写一个回调接口来处理支付结果:
@Controller
public class NotifyController {
@PostMapping("/notify")
@ResponseBody
public String notify(HttpServletRequest request) throws AlipayApiException {
// 获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<>();
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String paramName = parameterNames.nextElement();
String paramValue = request.getParameter(paramName);
params.put(paramName, paramValue);
}
// 验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params,
aliPayConfig.getPublicKey(),
"utf-8",
"RSA2");
if (signVerified) {
// 处理支付结果
String tradeStatus = params.get("trade_status");
String outTradeNo = params.get("out_trade_no");
String tradeNo = params.get("trade_no");
String totalAmount = params.get("total_amount");
// TODO: 处理支付结果
return "success";
} else {
return "failure";
}
}
}
5.发起支付请求
客户端在发起支付请求时,需要调用我们编写的支付接口,并将支付参数传递给支付宝SDK。具体代码如下:
public class PayActivity extends AppCompatActivity {
private static final String TAG = "PayActivity";
private static final String SERVER_URL = "http://www.example.com/pay";
private static final int SDK_PAY_FLAG = 1;
private Button mBtnPay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pay);
mBtnPay = findViewById(R.id.btn_pay);
mBtnPay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pay();
}
});
}
private void pay() {
String outTradeNo = UUID.randomUUID().toString();
String totalAmount = "0.01";
String subject = "测试商品";
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new FormBody.Builder()
.add("out_trade_no", outTradeNo)
.add("total_amount", totalAmount)
.add("subject", subject)
.build();
Request request = new Request.Builder()
.url(SERVER_URL)
.post(requestBody)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "请求支付接口失败", e);
showToast("请求支付接口失败");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
// 获取支付参数成功,打印日志,并将支付参数传递给支付宝SDK
String body = response.body().string();
Log.d(TAG, "获取支付参数成功: " + body);
PayTask task = new PayTask(PayActivity.this);
Map<String, String> result = task.payV2(body, true);
// 将支付结果通过 Handler 对象传递回主线程
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
} else {
// 获取支付参数失败,打印日志,并提示用户
Log.e(TAG, "获取支付参数失败: " + response.code());
showToast("获取支付参数失败");
}
}
});
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what) {
case SDK_PAY_FLAG:
Map<String, String> result = (Map<String, String>) msg.obj;
String resultStatus = result.get("resultStatus");
if (TextUtils.equals(resultStatus, "9000")) {
showToast("支付成功");
} else if (TextUtils.equals(resultStatus, "6001")) {
showToast("支付取消");
} else {
showToast("支付失败");
}
break;
}
}
};
private void showToast(String message) {
runOnUiThread(() -> Toast.makeText(PayActivity.this, message, Toast.LENGTH_SHORT).show());
}
}
四. 扫码支付
1.注册支付宝开发者账号
需要注册一个支付宝开发者账号。进入开发者中心,在“应用管理”中创建一个新的应用,选择“PC网站支付”作为接口类型。
在创建完应用后,我们需要获取一些必要的配置信息,包括应用ID、商户私钥、支付宝公钥、异步通知地址、同步跳转地址等。
2.引入支付宝SDK依赖和相关参数 与上述操作相同(这里不做重复描述)
3.实现支付接口
实现一个支付接口,用于生成支付二维码并返回给前端。
具体代码如下:
@RestController
public class AlipayController {
@Resource
private AlipayConfig alipayConfig;
/**
* 支付宝扫码支付
*/
@GetMapping("/scan/pay")
public String scanPay(String orderNo, String amount, String subject) throws AlipayApiException {
// 创建AlipayClient对象
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(), alipayConfig.getAppId(), alipayConfig.getPrivateKey(), "json", "UTF-8", alipayConfig.getAlipayPublicKey(), "RSA2");
// 创建AlipayTradePrecreateRequest对象
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
// 设置异步通知地址
request.setNotifyUrl("异步通知地址");
// 设置订单信息
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(orderNo);
model.setTotalAmount(amount);
model.setSubject(subject);
request.setBizModel(model);
// 发起支付请求
AlipayTradePrecreateResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
// 返回二维码链接给前端
return response.getQrCode();
} else {
// 处理支付失败的情况
throw new AlipayApiException(response.getMsg());
}
}
/**
* 处理支付结果
*/
@PostMapping("/notify")
public String notify(HttpServletRequest request) throws AlipayApiException {
// 获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
String[] values = requestParams.get(name);
StringBuilder valueStr = new StringBuilder();
for (int i = 0; i < values.length; i++) {
valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");
}
params.put(name, valueStr.toString());
}
// 验证签名
boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), "UTF-8", "RSA2");
if (verifyResult) {
// 处理支付成功的情况
String orderNo = params.get("out_trade_no");
String tradeNo = params.get("trade_no");
String amount = params.get("total_amount");
// TODO: 处理订单状态
return "success";
} else {
// 处理验签失败的情况
return "failure";
}
}
}
在上面的代码中,我们定义了一个AlipayController,其中包含了两个接口:scanPay和notify。
在scanPay接口中,我们首先创建了一个AlipayClient对象,然后创建了一个AlipayTradePrecreateRequest对象,并设置了异步通知地址和订单信息。最后,我们通过AlipayClient对象的execute方法发送支付请求,获取二维码链接,并将其返回给前端。
在notify接口中,我们首先从request中获取支付结果参数,并使用AlipaySignature.rsaCheckV1方法验证签名。如果验签成功,则处理支付成功的情况,否则处理验签失败的情况。在处理支付成功的情况时,我们可以根据订单号、交易号和金额等参数来更新订单状态。
五. APP支付
1.引入支付宝SDK依赖
在pom.xml文件中添加以下依赖:
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.22.ALL</version>
</dependency>
2.引入支付宝SDK依赖和相关参数 与上述操作相同(这里不做重复描述)
3.创建支付接口
在项目中创建一个控制器类,命名为AlipayController,用于处理支付相关的请求:
@RestController
@RequestMapping("/alipay")
public class AlipayController {
@Autowired
private AlipayConfig alipayConfig;
/**
* 处理支付请求
*/
@PostMapping("/app-pay")
public String appPay(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException, IOException {
// 实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(),
alipayConfig.getAppId(),
alipayConfig.getPrivateKey(),
"json",
"UTF-8",
alipayConfig.getAlipayPublicKey(),
"RSA2");
// 实例化请求对象
AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
// 设置异步通知地址
alipayRequest.setNotifyUrl("http://localhost:8080/alipay/notify");
// 设置订单信息
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setOutTradeNo("订单号");
model.setSubject("订单标题");
model.setBody("订单描述");
model.setTotalAmount("订单金额");
alipayRequest.setBizModel(model);
// 请求支付宝生成支付结果
String form = alipayClient.sdkExecute(alipayRequest).getBody();
// 将支付结果返回给客户端
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(form);
response.getWriter().flush();
response.getWriter().close();
return null;
}
/**
* 处理支付结果
*/
@PostMapping("/notify")
public String notify(HttpServletRequest request) throws AlipayApiException {
// 获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
String[] values = requestParams.get(name);
StringBuilder valueStr = new StringBuilder();
for (int i = 0; i < values.length; i++) {
valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");
}
params.put(name, valueStr.toString());
}
// 验证签名
boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), "UTF-8", "RSA2");
if (verifyResult) {
// 处理支付结果
String tradeStatus = params.get("trade_status");
if ("TRADE_SUCCESS".equals(tradeStatus)) {
String outTradeNo = params.get("out_trade_no");
String tradeNo = params.get("trade_no");
// TODO: 处理支付结果
}
return "success";
} else {
return "failure";
}
}
}
4.调用支付接口
客户端在调用支付接口时,要向服务端发送支付请求,并需要获取服务端返回的支付结果。具体代码如下:
public class AlipayClient {
private static final String APP_PAY_URL = "http://localhost:8080/alipay/app-pay";
/**
* 调用支付接口
*/
public String pay() {
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.build();
Request request = new Request.Builder()
.url(APP_PAY_URL)
.post(formBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
上述内容概述了集成支付宝APP支付的核心流程。重要的是,在利用支付宝SDK进行支付应用开发时,务必严格遵守支付宝制定的各项规定与安全准则,这是保障支付流程安全无误的基石。此外,根据实际应用场景与业务需求,灵活调整与优化支付流程也是必不可少的环节。例如,针对多样化的支付场景,可以灵活选择最适宜的支付方式;同时,对于支付结果的确认与处理,可采用定时查询等策略以确保交易的准确无误。总而言之,持续的实践与迭代是提升支付宝SDK应用效率、安全性及稳定性的关键路径,唯有不断精进,方能在实际项目中实现更加卓越的支付体验。
原文始发于微信公众号(Java技术前沿):SpringBoot 集成支付宝的各种应用场景
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/299599.html