Springboot整合支付宝支付(沙箱)
官方文档中心:
https://opendocs.alipay.com/apis/api_1/alipay.trade.page.pay
前期准备
注册支付宝,登录,获取APPID等。
1.创建应用
官方创建应用提供方法:
https://opendocs.alipay.com/open/200/105310
开发者使用支付宝账号登录 开放平台控制台(需实名认证的支付宝账号)。
控制台–沙箱
2.获取到APPID
- APPID会配置到项目中使用
3.配置RSA2密钥
密钥生成地址:
https://miniu.alipay.com/keytool/create
生成应用私钥与应用公钥
- 应用私钥会配置到项目中使用
配置应用公钥
选择自定义密钥
将生成好的公钥放入到配置中
保存之后,生成支付宝公钥。
- 支付宝公钥会配置到项目中使用
4.支付宝网关
https://openapi.alipaydev.com/gateway.do
- 支付宝网关会配置到项目中使用
至此,项目中使用到的配置全拿到了。开始整合项目
开发
1.项目结构
2.pom.xml
主要是添加lombok,alipay-sdk-java,slf4j-api
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zjy</groupId>
<artifactId>alpay</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>alpay</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
<!-- 支付SDK-->
<dependency>
<groupId>com.alipay.sdk</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>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.application.properties
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
4.OrderController
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 "index.html";
}
}
5.PayService
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;
}
6.PayServiceImpl
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);
}
}
7.Alipay
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("${app.appId}")
private String appId;
/**
* 商户私钥
*/
@Value("${app.privateKey}")
private String privateKey;
/**
* 支付宝公钥
*/
@Value("${app.publicKey}")
private String publicKey;
/**
* 服务器异步通知页面路径,需要公网能访问到
*/
@Value("${app.notifyUrl}")
private String notifyUrl;
/**
* 服务器同步通知页面路径,需要公网能访问到
*/
@Value("${app.returnUrl}")
private String returnUrl;
/**
* 签名方式
*/
@Value("${app.signType}")
private String signType;
/**
* 字符编码格式
*/
@Value("${app.charset}")
private String charset;
/**
* 支付宝网关
*/
@Value("${app.gatewayUrl}")
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;
}
}
8.AliPayBean
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";
}
9.index.html
<!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.启动项目
启动项目,并访问: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";
- 错误写法:
/**
* 商户订单号
*/
private String outTradeNo;
/**
* 订单名称
*/
private String subject;
/**
* 付款金额
*/
private String totalAmount;
/**
* 商品描述
*/
private String body;
/**
* 超时时间参数
*/
private String timeoutExpress = "60m";
/**
* 产品编号
*/
private String productCode = "FAST_INSTANT_TRADE_PAY";
2.产品码。
商家和支付宝签约的产品码。 枚举值(点击查看签约情况):
FAST_INSTANT_TRADE_PAY:新快捷即时到账产品。
注:目前仅支持FAST_INSTANT_TRADE_PAY
测试OK!
欢迎大神指导,可以留言交流!
======================
本人原创文章,转载注明出入!
=================