当前位置: 首页 > news >正文

SpringBoot 整合支付宝沙箱支付——从接入到回调

支付是电商系统的核心功能。接入支付宝需要企业资质,但支付宝提供了沙箱环境——模拟真实支付流程,不需要真实商户号,适合开发测试和学习。

一、沙箱环境准备

1. 登录开放平台

打开 open.alipay.com → 控制台 → 沙箱应用

2. 获取配置参数

APP_ID: 9021000122691234(沙箱专用) 应用私钥: 生成的 RSA2 私钥 支付宝公钥: 生成的 RSA2 公钥 服务器异步通知地址: http://你的地址/pay/notify

3. 沙箱账号

沙箱环境提供测试买家账号:

买家账号: rixwby5818@sandbox.com 登录密码: 111111 支付密码: 111111

二、SpringBoot 集成

1. 引入依赖

<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.38.200.ALL</version></dependency>

2. 配置

alipay:app-id:9021000122691234app-private-key:|-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQ... (你的应用私钥,不要写在配置里!建议用Jasypt加密) -----END RSA PRIVATE KEY-----alipay-public-key:|-----BEGIN PUBLIC KEY----- MIIBIjANBgk... (支付宝公钥) -----END PUBLIC KEY-----notify-url:http://你的公网IP/pay/notifyreturn-url:http://localhost:9090/pay/returngateway-url:https://openapi-sandbox.dl.alipaydev.com/gateway.do

3. 配置类

@Configuration@ConfigurationProperties(prefix="alipay")@DatapublicclassAlipayConfig{privateStringappId;privateStringappPrivateKey;privateStringalipayPublicKey;privateStringnotifyUrl;privateStringreturnUrl;privateStringgatewayUrl;@BeanpublicAlipayClientalipayClient(){returnnewDefaultAlipayClient(gatewayUrl,appId,appPrivateKey,"json","utf-8",alipayPublicKey,"RSA2");}}

三、统一下单接口

@ServicepublicclassAlipayService{@AutowiredprivateAlipayClientalipayClient;@AutowiredprivateAlipayConfigalipayConfig;/** * 创建支付订单,返回支付页面表单 */publicStringcreatePay(StringorderNo,BigDecimalamount,Stringsubject){AlipayTradePagePayRequestrequest=newAlipayTradePagePayRequest();// 同步回调地址(用户支付完成后跳转)request.setReturnUrl(alipayConfig.getReturnUrl());// 异步回调地址(支付宝服务器通知)request.setNotifyUrl(alipayConfig.getNotifyUrl());JSONObjectbiz=newJSONObject();biz.put("out_trade_no",orderNo);// 商户订单号biz.put("total_amount",amount.toString());// 支付金额biz.put("subject",subject);// 订单标题biz.put("product_code","FAST_INSTANT_TRADE_PAY");// 电脑网站支付request.setBizContent(biz.toJSONString());try{AlipayTradePagePayResponseresponse=alipayClient.pageExecute(request);if(response.isSuccess()){returnresponse.getBody();// 返回 HTML 表单}}catch(AlipayApiExceptione){thrownewRuntimeException("支付宝下单失败",e);}returnnull;}}

四、Controller

@RestController@RequestMapping("/pay")publicclassPayController{@AutowiredprivateAlipayServicealipayService;/** * 发起支付 */@PostMapping("/create")publicResultVO<String>createPay(@RequestBodyPayDTOdto){// 生成订单号StringorderNo="ORD"+IdUtil.simpleUUID().toUpperCase();Stringform=alipayService.createPay(orderNo,dto.getAmount(),dto.getSubject());returnResultVO.success(form);}/** * 同步回调(用户支付完成后跳转到此页面) */@GetMapping("/return")publicStringreturnUrl(HttpServletRequestrequest){// 获取支付宝返回的参数Map<String,String>params=getParamsFromRequest(request);try{// 验签AlipaySignature.rsaCheckV1(params,alipayConfig.getAlipayPublicKey(),"utf-8","RSA2");StringorderNo=params.get("out_trade_no");StringtradeNo=params.get("trade_no");return"支付成功!订单号: "+orderNo;}catch(AlipayApiExceptione){return"验签失败";}}/** * 异步回调(支付宝服务器通知,必须返回 success) */@PostMapping("/notify")publicStringnotifyUrl(HttpServletRequestrequest){Map<String,String>params=getParamsFromRequest(request);try{booleansignVerified=AlipaySignature.rsaCheckV1(params,alipayConfig.getAlipayPublicKey(),"utf-8","RSA2");if(signVerified){StringorderNo=params.get("out_trade_no");StringtradeNo=params.get("trade_no");StringtradeStatus=params.get("trade_status");// 支付成功if("TRADE_SUCCESS".equals(tradeStatus)){// 更新订单状态、归还库存等业务逻辑updateOrderStatus(orderNo,tradeNo);}return"success";// 必须返回 success,否则支付宝会重复通知}}catch(AlipayApiExceptione){e.printStackTrace();}return"fail";}privateMap<String,String>getParamsFromRequest(HttpServletRequestrequest){Map<String,String>params=newHashMap<>();Map<String,String[]>requestParams=request.getParameterMap();for(Stringname:requestParams.keySet()){params.put(name,request.getParameter(name));}returnparams;}}

五、秒杀系统集成支付

支付完成后更新订单状态并归还库存:

@ServicepublicclassPayService{@AutowiredprivateOrderServiceorderService;@AutowiredprivateProductServiceproductService;/** * 支付成功回调处理 */@TransactionalpublicvoidhandlePaySuccess(StringorderNo,StringtradeNo){// 1. 查询订单SeckillOrderorder=orderService.lambdaQuery().eq(SeckillOrder::getOrderNo,orderNo).one();if(order==null||order.getStatus()!=0){return;// 订单不存在或已处理}// 2. 更新订单状态为已支付order.setStatus(1);order.setPayTime(LocalDateTime.now());order.setTradeNo(tradeNo);orderService.updateById(order);// 3. 记录支付日志log.info("支付成功: 订单={}, 支付宝交易号={}",orderNo,tradeNo);}}

六、前端调用

<buttononclick="pay()">支付宝支付</button><script>asyncfunctionpay(){constresp=awaitfetch('/pay/create',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({amount:99.99,subject:'秒杀商品 - iPhone 15'})});constresult=awaitresp.json();if(result.code===200){// 把返回的 HTML 表单写到页面并自动提交document.body.innerHTML=result.data;document.forms[0].submit();// 自动跳转到支付宝}}</script>

七、注意事项

  1. 异步通知必须返回 “success”(全小写),否则支付宝会重复通知 8 次
  2. 验签必不可少,防止伪造回调
  3. 幂等处理——支付宝通知可能重复,判断订单状态防止重复更新
  4. 沙箱金额随便填,不会真实扣款
  5. 上生产环境只需把gateway-url换成生产地址,其他代码不变

💡 觉得有用的话,点赞 + 关注【张老师技术栈】吧!每周更新 Java/Python/爬虫 实战干货,不让你白来。

http://www.jsqmd.com/news/1134888/

相关文章:

  • STM32与CS2200-CP构建高精度计时系统设计
  • 推荐系统 5 大评价指标实战:从 Recall@20 到 NDCG@10 的 Python 实现与对比
  • 警惕!找综合律所打离婚家事与财产纠纷官司,容易踩的3个专业坑
  • 终极指南:3步解锁中兴光猫工厂模式,获取完整设备控制权限
  • DC-DC降压电源设计:171010550与PIC18F4680方案详解
  • Spring Boot项目JUnit 5与Spring-test版本冲突诊断与解决方案
  • B站缓存视频格式转换完全指南:解锁跨平台播放的终极方案
  • B站视频下载器终极指南:3个技巧解锁大会员4K和充电专属内容
  • 基于YOLOv8的斗地主手牌检测实战指南
  • STM32与TPAFE0808实现多通道信号采集方案解析
  • Innovus 23.1 电源规划实战:5步完成多电压域 Power Mesh 设计(附 IR Drop 分析)
  • 《地下偶像》 动漫|在线观看|樱花|全集|sana
  • 从零掌握曝光铁三角:光圈、快门、ISO的实战平衡术
  • 【Java毕业设计】基于 SpringBoot 的疾病 - 靶标 - 药物关联知识库采集平台的设计与实现(源码+文档+远程调试,全bao定制等)
  • 用Python开发一个简单的Web应用:步骤详解
  • 锂电池保护板设计实战:基于DW01A的过流保护电路与MOS选型3要点
  • 从Gh0stt木马攻击实战,解析Windows Defender瘫痪与应急清除
  • Blender贝塞尔曲线插件终极指南:10个技巧让你的3D设计效率翻倍
  • 【vibe coding 第六部分】练手项目地图
  • RGB-D 抓取检测实战:基于 YOLOv8 与 FastSAM 的 3D 物体分割 Pipeline 实现
  • 哔咔漫画批量下载器终极指南:三步打造个人数字漫画库
  • OpenCV 4.8 图像处理实战:Canny边缘检测与轮廓提取的3个关键参数调优
  • DevEco 构建环境排障:JBR、Node、SDK 与 hvigor daemon 的正确组合
  • 携程酒店价格实时监控脚本---接口逆向分析
  • 浏览器即API:零依赖调用Gemini网页版的实战方案
  • WorkshopDL终极指南:跨平台畅玩Steam创意工坊模组的完整解决方案
  • 从零搭建SpringBoot项目,这些配置细节值得留意
  • 测试转大模型:AI 测试工程师的能力跃迁,把学习路线落到项目证据
  • 六、HSV颜色空间实战进阶——动态阈值调优与多目标分割
  • 【Java课程设计/毕业设计】基于 SpringBoot 的冠状病毒研究数据标准化采集系统的设计与实现【附源码、数据库、万字文档】