支付宝沙箱环境+SpringBoot+内网穿透整合开发
目录
1.查看沙箱账号
2.内网穿透
3.沙箱环境整合SpringBoot开发
下面我将以实际案例详细介绍如何使用沙箱环境进行支付宝支付对接的开发
1.查看沙箱账号
首先什么是沙箱账号?
沙箱账号是指在支付宝沙箱环境中创建的测试账户,用于模拟真实的支付流程。在开发和测试过程中,使用沙箱账号可以避免真实账户数据的泄露和风险,同时可以进行多种测试场景和交易模拟,以保证应用程序的稳定性和可靠性。
支付宝沙箱环境中的测试账户和真实账户一样,可以进行支付、退款、查询等操作。开发人员可以通过创建和使用沙箱账号,进行多种测试和调试,以保证应用程序的正确性和稳定性。同时,沙箱账号的创建和使用是免费的,不需要任何费用。
需要注意的是,沙箱账号只能在支付宝沙箱环境中使用,不能在生产环境中使用。在将应用程序上线之前,需要使用真实账户进行测试和验证。
1.登录支付宝开放平台:https://open.alipay.com/platform/home.htm
2.点击登录,系统会弹出一个二维码进行扫描登录,当然也可以使用账号密码进行登录
3.点击进入控制台
4.开发工具推荐中选择使用沙箱环境
5.自此完成沙箱账号信息的查看
2.内网穿透
获取方式:电脑应用商店搜索花生壳
网页端申请配置:
1.需要进行实名认证否则用不了
2.需要花6元买个域名映射
3.将ip和端口换成刚刚申请的域名,填入回调地址处,用于后续的支付宝系统回调接口
客户端:开启自定义映射
下面将进入主题,如何整合SpringBoot进行支付开发
3.沙箱环境整合SpringBoot开发
1.1.创建Spring Boot项目
可以使用Spring Initializr快速创建一个新项目也可以在maven创建的基础上加上相关的依赖。
如果您是maven创建的项目请加如下依赖:
<dependencies><!-- Spring Boot starter dependencies --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.5.4</version></dependency></dependencies>
如果是基于Spring Initializr快速创建一个SpringBoot项目则导入如下依赖:
2.导入依赖
<dependencies><!-- Other dependencies --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency><dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>3.0.0</version></dependency><!-- Fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.78</version></dependency><!-- slf4j --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.32</version></dependency><!-- JSON --><dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20210307</version></dependency></dependencies>
3.配置应用程序
在application.yml文件中,我们需要添加支付宝支付的相关配置。
# 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,在沙箱应用中获取
appId:
# 商户私钥,您的PKCS8格式RSA2私钥,通过开发助手生成的应用私钥
privateKey:
# 支付宝公钥,在沙箱应用获取,通过应用公钥生成支付宝公钥
publicKey:
# 服务器异步通知页面路径需http://格式的完整路径,不能加?id=123这类自定义参数
notifyUrl: https://7*****.zicp.fun/alipay/notify
# 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数
returnUrl: https://7*****.zicp.fun/alipay/success
# 支付宝网关,在沙箱应用中获取
gatewayUrl:
下面就上面的参数进行说明
所以应用ID、应用私钥和支付宝公钥可以在支付宝开放平台上获取。gateway-url是支付宝支付接口的地址,return-url和notify-url是支付完成后跳转的地址和支付结果通知地址。
4.创建支付服务
接下来,创建一个支付服务类,用于处理支付请求和支付结果通知。在创建支付服务之前,我要先创建一个AlipayClient对象,用于调用支付宝支付接口。
@Configuration
public class AlipayConfig {//获取配置文件中的配置信息//应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号@Value("${appId}")private String appId;//商户私钥 您的PKCS8格式RSA2私钥@Value("${privateKey}")private String privateKey;//支付宝公钥@Value("${publicKey}")private String publicKey;//支付宝网关@Value("${gatewayUrl}")private String gatewayUrl;@Beanpublic AlipayClient alipayClient() {return new DefaultAlipayClient(gatewayUrl, appId, privateKey, "json", "UTF-8", publicKey, "RSA2");}
}
再创建一个支付服务,用于处理支付请求和支付结果通知。
@Service
public class AlipayService {@Autowiredprivate AlipayClient alipayClient;//服务器异步通知页面路径@Value("${notifyUrl}")private String notifyUrl;//页面跳转同步通知页面路径@Value("${returnUrl}")private String returnUrl;/*** 发起支付请求* @param order 订单信息* @return 支付页面HTML代码*/public String pay(Order order) {AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();request.setReturnUrl(returnUrl);request.setNotifyUrl(notifyUrl);Map<String, Object> params = new HashMap<>();params.put("out_trade_no", order.getOrderId());params.put("total_amount", order.getTotalAmount());params.put("subject", order.getSubject());params.put("body", order.getBody());params.put("product_code", "FAST_INSTANT_TRADE_PAY");request.setBizContent(JSON.toJSONString(params));try {AlipayTradePagePayResponse response = alipayClient.pageExecute(request);return response.getBody();} catch (AlipayApiException e) {throw new RuntimeException("支付宝支付失败", e);}}/*** 处理支付结果通知** @param request 支付结果通知参数* @return 处理结果*/public String notify(HttpServletRequest request) throws AlipayApiException {log.info("异步回调");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);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());}log.info("请求参数的传入:" + params);String tradeStatus = params.get("trade_status");log.info("tradeStatus:" + tradeStatus);String outTradeNo = params.get("out_trade_no");log.info("outTradeNo:" + outTradeNo);String totalAmount = params.get("total_amount");log.info("totalAmount:" + totalAmount);
//
// // 从数据库中查询订单信息
// Order order = orderService.findByOutTradeNo(outTradeNo);// 验证通知是否来自支付宝服务器if (!AlipaySignature.rsaCheckV1(params, publicKey, charset, signType)) {return "fail";}// 验证交易状态和订单金额等信息
// if (!"TRADE_SUCCESS".equals(tradeStatus) || !totalAmount.equals(order.getTotalAmount().toString())) {if (!"TRADE_SUCCESS".equals(tradeStatus)) {return "fail";}// 根据交易状态进行业务处理switch (tradeStatus) {case "TRADE_SUCCESS":// 更新订单状态、发货等操作break;case "TRADE_CLOSED":// 订单关闭处理break;default:// 其他状态处理break;}return "success";}public String success(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {log.info("=================同步回调======================");// 获取支付宝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 = (String) iter.next();String[] values = (String[]) requestParams.get(name);String valueStr = "";for (int i = 0; i < values.length; i++) {valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";}// 乱码解决,这段代码在出现乱码时使用valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");params.put(name, valueStr);}log.info("支付宝平台同步回调传入的参数:" + params);//验证签名(支付宝公钥)boolean signVerified = AlipaySignature.rsaCheckV1(params, publicKey, charset, signType); // 调用SDK验证签名//验证签名通过if (signVerified) {// 商户订单号String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");// 支付宝交易流水号String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");// 付款金额float money = Float.parseFloat(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));log.info("商户订单号=" + out_trade_no);log.info("支付宝交易号=" + trade_no);log.info("付款金额=" + money);//在这里编写自己的业务代码(对数据库的操作)/*################################*///跳转到提示页面(成功或者失败的提示页面)return "交易成功!";} else {//跳转到提示页面(成功或者失败的提示页面)return "交易失败!";}}
}
在AlipayService类中,我们使用@Autowired注解注入AlipayClient对象,并使用@Value注解注入支付宝支付的相关配置。
pay方法用于发起支付请求,首先创建一个AlipayTradePagePayRequest对象,设置returnUrl和notifyUrl,然后将订单信息封装成一个Map对象,调用alipayClient的pageExecute方法发起支付请求,并返回支付页面的HTML代码。
notify方法用于处理支付结果通知,首先使用AlipaySignature.rsaCheckV1方法验证支付结果通知的签名,然后根据支付结果更新订单状态。
success方法也是如此,但是开发中用notify异步处理效率更高一些。
5.5.创建支付控制器
创建一个支付控制器,用于处理支付请求和支付结果通知。
@Controller
@RequestMapping("/alipay")
public class AlipayController {@Autowiredprivate AlipayService alipayService;/*** 发起支付请求* @param order 订单信息* @return 支付页面HTML代码*/@RequestMapping("/pay")@ResponseBodypublic String pay(Order order) {return alipayService.pay(order);}/*** 处理支付结果通知* @param request 支付结果通知参数* @return 处理结果*/@PostMapping("/notify")@ResponseBodypublic String notify(@RequestParam HttpServletRequest request) throws AlipayApiException {return alipayService.notify(request);}/*** 支付完成后跳转回商户网站的地址** @return 跳转页面*/@RequestMapping("/success")@ResponseBodypublic String success(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException {return alipayService.success(request);}
//根据自己的实际业务选择是同步处理还是异步处理
}
在AlipayController类中,我们使用@Autowired注解注入AlipayService对象,并创建pay、notify和returnUrl三个方法,分别用于处理支付请求、支付结果通知和支付完成后跳转回商户网站的地址。
这里需要注意的是,只有当方法的返回值类型为
void
或String
时,才需要使用@ResponseBody
注解。如果方法的返回值类型为其他类型(如对象、集合等),Spring MVC会自动将其转换为JSON或XML格式的数据并返回给客户端,无需使用@ResponseBody
注解。
6.测试支付功能
现在,我们已经完成了支付宝支付的整合,可以通过调用支付控制器中的pay方法发起支付请求,并在支付完成后处理支付结果通知和支付完成后跳转回商户网站的地址。
可以通过Postman等工具模拟支付请求,或者在网站上添加一个支付按钮,点击按钮后跳转到支付页面完成支付。
在网站上面添加一个支付按钮
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="/alipay/pay" method="post">订单号:<input type="text" name="out_trade_no" required><br/>订单名称:<input type="text" name="subject" required><br/>付款金额:<input type="text" name="total_amount" required><br/>商品描述:<input type="text" name="body"><br/><input type="submit" value="下单"> <input type="reset" value="重置">
</form></body>
</html>
浏览器地址栏输入:http://localhost:8081/
输入支付账号和支付密码即可完成支付
支付宝沙箱环境+SpringBoot+内网穿透整合开发完美收官!
有任何问题随时私信我!