springboot实现支付宝支付功能

article/2025/10/15 9:05:29

支付系统中容易出现的问题

1,用户在页面下订单后,价格被篡改;
解决方案:通过后端计算订单的总金额

2,订单重复处理。用户支付成功后,支付宝会短时间内多次调用我们的回调接口,如果出现网络波动等原因会导致多次回调请求同时到达,同时对订单做处理,导致用户充一次钱,服务续费了两个月。
解决方案:对订单数据加乐观锁,避免订单被多次修改。(之前接手一个老项目就发现了这种情况)

3,掉单情况。用户支付完成了,回到平台一看,订单状态还处于未支付。这是因为用户虽然支付成功了,但是支付宝回调我们接口的时候可能没有回调成功,或者回调成功了但是订单状态修改没有成功,就会导致订单状态没有变更。用户一看钱付了,购买的服务却没有成功,要炸毛了。
解决方案:用户支付成功回到平台后,前端要开启一个轮询,调用查询订单的状态接口,后端然后去支付宝查看该订单是否实际支付成功,如果支付成功,及时更改订单的状态。还有一种方式是后端可以开启一个定时任务,定时30秒查询订单表最近5分钟未支付的订单,然后去查看实际的支付状态,如果支付成功再修改订单的状态以及后续的业务处理,这种方式适合业务比较小的平台。
支付系统中最重要的就是要保证支付订单和业务处理只能被修改一次,以及可能出现订单状态修改不及时的情况。

开发测试过程中可能出现页面渲染不出来的情况
参考解决方案:https://blog.csdn.net/weixin_51324855/article/details/124098732
支付系统开发好后,在生产环境下可能会出现重复支付和掉单的问题
参考一:
参考二:
参考三:

一,实现支付宝支付功能步骤

1,创建一个springboot项目

2,注册入驻支付宝成为开发人员
地址给你准备好了:https://open.alipay.com/platform/home.htm?from=wwwalipay

3,进入沙箱应用,获取配置到项目中的配置信息 (重要!!!)

4,下载支付宝开放平台开发助手,生成应用公钥和应用私钥 (重要!!!私钥要配置到项目中)
开发助手下载地址:https://opendocs.alipay.com/common/02kipl

5,springboot中配置支付宝支付信息,编写代码。

6,测试支付功能。

创建springboot项目省略

二,入驻支付宝成为开发人员

搜索支付宝,进入支付宝首页—》我是开发者—》注册登录(第一次登录时要求你必须入驻,直接入驻就行了)

地址给你准备好了:https://open.alipay.com/platform/home.htm?from=wwwalipay
直接登录注册就可以了

在这里插入图片描述

三,进入沙箱应用

简单解释下沙箱,就是模拟的支付系统,支付的钱都是假的。

1,沙箱中操作说明

登录—》控制台—》沙箱—》沙箱应用

登录之后,页面是这个样子的
在这里插入图片描述
在这里插入图片描述

2,沙箱其他信息说明

下面分别是生成的买家和卖家的支付宝账号

支付宝客户端沙箱版,用来模拟扫码支付的,账号是上面的沙箱版买家账号(买家扫码向卖家支付),建议手机扫码下载一个,登录买家账号
在这里插入图片描述

在这里插入图片描述

四,下载支付宝开发助手生成秘钥

1,生成秘钥

开发助手下载地址:https://opendocs.alipay.com/common/02kipl

下载后直接安装,打开后直接生成秘钥,生成秘钥后电脑会有两个文件,分别保存有应用公钥和应用私钥
在这里插入图片描述
在这里插入图片描述

2,配置秘钥

将应用公钥复制下来,然后到沙箱应用中配置生成支付宝公钥

在这里插入图片描述

五,springboot中配置环境

1,引入jar包

		<!-- 支付宝支付jar包 --><dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>3.1.0</version></dependency>

2,application.properties

# 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,在沙箱应用中获取
appId:2021000119675024
# 商户私钥,您的PKCS8格式RSA2私钥,通过开发助手生成的应用私钥
privateKey:
# 支付宝公钥,在沙箱应用获取,通过应用公钥生成支付宝公钥
publicKey:
# 服务器异步通知页面路径需http://格式的完整路径,不能加?id=123这类自定义参数
notifyUrl:http://localhost:8081/alipay/success
# 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数
returnUrl: http://localhost:8081/alipay/success
# 签名方式
signType: RSA2
# 字符编码格式
charset: utf-8
# 支付宝网关,在沙箱应用中获取
gatewayUrl: https://openapi.alipaydev.com/gateway.do

3,接收请求参数的实体类

实体类总的属性只能是下划线连接,不能使用驼峰命名

@Data
public class AlipayBean implements Serializable {/*** 商户订单号*/private String out_trade_no;/*** 订单名称*/private String subject;/*** 付款金额*/private String total_amount;/*** 商品描述*/private String body;/*** 产品编号,支付方式不同,传的数据不同*///如果是PC网页支付,这个是必传参数private String product_code = "FAST_INSTANT_TRADE_PAY";//如果是扫码支付,这个是选传参数//private String product_code = "FACE_TO_FACE_PAYMENT";
}

4,支付接口

支付宝各种支付接口说明:https://opendocs.alipay.com/open/194/106078

我这里只说PC网页支付和扫码支付,详细的支付需要查看支付宝官方的文档

参数封装类不同,使用AlipayClient就要调用不同的方法,具体可以在支付宝AlipayTradePagePayRequest	pageExecute 	是PC网页支付,类似使用电脑在淘宝买东西的支付方式
AlipayClient.pageExecute(pagePayRequest)AlipayTradePrecreateRequest		execute  	扫码支付
AlipayClient.pageExecute(precreateRequest)
PC网页支付还是扫码支付,我们都需要传参,查看支付宝官方文档得知:
扫码支付必传3个参数:out_trade_no、subject、total_amount
而PC支付必传4个参数:out_trade_no、subject、total_amount、product_code 
根据支付方式不同对AlipayBean 中的属性进行改造项目代码写好后,调用支付接口,支付宝返回来的信息可能会出现参数不正确的错误信息,
这个时候就要检查你的传参是否符合支付宝文档的要求,参数是否使用下划线,是否漏了必传参数
@Controller
@RequestMapping("/alipay")
public class AlipayController {//获取配置文件中的配置信息//应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号@Value("${appId}")private String appId;//商户私钥 您的PKCS8格式RSA2私钥@Value("${privateKey}")private String privateKey;//支付宝公钥@Value("${publicKey}")private String publicKey;//服务器异步通知页面路径@Value("${notifyUrl}")private String notifyUrl;//页面跳转同步通知页面路径@Value("${returnUrl}")private String returnUrl;//签名方式@Value("${signType}")private String signType;//字符编码格式@Value("${charset}")private String charset;//支付宝网关@Value("${gatewayUrl}")private String gatewayUrl;private final String format = "json";//PC网页段支付,返回的是支付宝账号的登录页面@RequestMapping("/pay")@ResponseBodypublic String pay(AlipayBean alipayBean) throws AlipayApiException {//模拟数据alipayBean.setOut_trade_no(UUID.randomUUID().toString().replaceAll("-",""));alipayBean.setSubject("订单名称");alipayBean.setTotal_amount(String.valueOf(new Random().nextInt(100)));alipayBean.setBody("商品描述");AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, appId, privateKey, format, charset, publicKey, signType);//PC网页支付使用AlipayTradePagePayRequest传参,下面调用的是pageExecute方法AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();alipayRequest.setReturnUrl(returnUrl);alipayRequest.setNotifyUrl(notifyUrl);alipayRequest.setBizContent(JSON.toJSONString(alipayBean));log.info("封装请求支付宝付款参数为:{}", JSON.toJSONString(alipayRequest));// 调用SDK生成表单String result = alipayClient.pageExecute(alipayRequest).getBody();log.info("请求支付宝付款返回参数为:{}", result);return result;}/*** 手机扫码支付* @param alipayBean* @return* @throws Exception*/@RequestMapping("/pay2")@ResponseBodypublic Result pay2(AlipayBean alipayBean) throws Exception {//接口模拟数据alipayBean.setOut_trade_no("20210817010101003");alipayBean.setSubject("订单名称");alipayBean.setTotal_amount(String.valueOf(new Random().nextInt(100)));alipayBean.setBody("商品描述");AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, appId, privateKey, format, charset, publicKey, signType);//扫码支付使用AlipayTradePrecreateRequest传参,下面调用的是execute方法AlipayTradePrecreateRequest precreateRequest = new AlipayTradePrecreateRequest();precreateRequest.setReturnUrl(returnUrl);precreateRequest.setNotifyUrl(notifyUrl);precreateRequest.setBizContent(JSON.toJSONString(alipayBean));log.info("封装请求支付宝付款参数为:{}", JSON.toJSONString(precreateRequest));AlipayTradePrecreateResponse response = null;try {response = alipayClient.execute(precreateRequest);} catch (AlipayApiException e) {throw new Exception(String.format("下单失败 错误代码:[%s], 错误信息:[%s]", e.getErrCode(), e.getErrMsg()));}log.info("AlipayTradePrecreateResponse = {}", response.getBody());/*{"code": "10000","msg": "Success","out_trade_no": "815259610498863104","qr_code": "https://qr.alipay.com/bax09455sq1umiufbxf4503e"}*/if (!response.isSuccess()) {throw new Exception(String.format("下单失败 错误代码:[%s], 错误信息:[%s]", response.getCode(), response.getMsg()));}// TODO 下单记录保存入库// 返回结果,主要是返回 qr_code,前端根据 qr_code 进行重定向或者生成二维码引导用户支付JSONObject jsonObject = new JSONObject();//支付宝响应的订单号String outTradeNo = response.getOutTradeNo();jsonObject.put("outTradeNo",outTradeNo);//二维码地址,页面使用二维码工具显示出来就可以了jsonObject.put("qrCode",response.getQrCode());return Result.ok(jsonObject);}@RequestMapping("/success")@ResponseBodypublic String success(){return "交易成功!";}@RequestMapping(value = "/index")public String payCoin(){return "index.html";}
}

5,写一个简单的页面index.html

不要页面,直接接口工具请求也可以

<!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>

六,测试

启动springboot项目,地址栏输入localhost:8081,下单后自动跳到登录页面,需要登录买方的账号,就是沙箱应用生成的账号,支付密码111111,有没有支付成功,可以到沙箱应用查看账号的金额是否发生变动。

1,测试PC网页支付

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2,测试扫码支付

1,首先手机上先下载沙盒版支付宝,安装到手机上,怎么下载看上面沙箱应用的说明
2,下载后登录沙箱版生成的买方账号。
3,调用扫码支付的接口
4,网上搜一个二维码在线生成器
5,用沙箱版扫码支付
在这里插入图片描述

七,可能出现的问题

1,问题1:付款时显示订单已付款

原因: 向支付宝提交的订单号重复,且之前的订单号已支付过

解决办法: 换个订单号就行

2,问题2: 触发点击事件时界面显示404NotFound

原因1:支付宝网关填写有错误或者支付宝沙箱环境不稳定造成的

解决办法1:查看郁闷了配置文件中gatewayUrl是不是支付宝沙箱支付的网关 如下:

gatewayUrl: https://openapi.alipaydev.com/gateway.do

原因2:支付宝沙箱环境不稳定造成的

解决办法2:在404NotFound界面一直点击刷新,重复提交几次就行了

3,问题3:输入支付密码后显示,抱歉网络系统繁忙,请稍后再试

在这里插入图片描述
原因:沙箱支付环境不稳定或者沙箱环境正在维护中

解决办法:等一天,尽量避开周日到周一一点,这个问题就自动解决了

4,问题4:付款时跳转到504

原因:网速过慢

解决办法:切换到更快的网络付款就行

5,问题5:付款时显示支付存在钓鱼风险!

在这里插入图片描述
原因:浏览器环境的问题

解决办法1:换一个未登录支付宝开放平台以及未调用过沙箱支付接口的浏览器,重新提交付款

解决办法2:把浏览器上打开的所有沙箱支付、支付宝官方等的页面全部关闭,然后Crtl+Shift+delete,清空浏览器缓存

6,问题6:付款时显示订单信息无法识别,请联系卖家

在这里插入图片描述
原因1:AliPayBean里封装的实体字段写的有问题

请求支付宝api就是要 _ 拼接的,不能使用驼峰拼接

解决办法1:AliPayBean文件与以下保持一致,字段名用_连接

package com.htu.domain;/*** 支付实体对象* 根据支付宝接口协议,其中的属性名,必须使用下划线,不能修改*/
public class AlipayBean {/*** 商户订单号,必填**/private String out_trade_no;/*** 订单名称,必填*/private String subject;/*** 付款金额,必填* 根据支付宝接口协议,必须使用下划线*/private String total_amount;/*** 商品描述,可空*/private String body;/*** 超时时间参数*/private String timeout_express= "10m";/*** 产品编号*/private String product_code= "FAST_INSTANT_TRADE_PAY";public AlipayBean(){}public AlipayBean(String out_trade_no, String subject, String total_amount, String body, String timeout_express, String product_code){this.out_trade_no = out_trade_no;this.subject = subject;this.total_amount = total_amount;this.body = body;this.timeout_express = timeout_express;this.product_code = product_code;}public String getOut_trade_no() {return out_trade_no;}public void setOut_trade_no(String out_trade_no) {this.out_trade_no = out_trade_no;}public String getSubject() {return subject;}public void setSubject(String subject) {this.subject = subject;}public String getTotal_amount() {return total_amount;}public void setTotal_amount(String total_amount) {this.total_amount = total_amount;}public String getBody() {return body;}public void setBody(String body) {this.body = body;}public String getTimeout_express() {return timeout_express;}public void setTimeout_express(String timeout_express) {this.timeout_express = timeout_express;}public String getProduct_code() {return product_code;}public void setProduct_code(String product_code) {this.product_code = product_code;}@Overridepublic String toString(){return "AlipayBean{" +"out_trade_no='" + out_trade_no + '\'' +", subject='" + subject + '\'' +", total_amount='" + total_amount + '\'' +", body='" + body + '\'' +", timeout_express='" + timeout_express + '\'' +", product_code='" + product_code + '\'' +'}';}
}

原因2:向后端穿的订单号与金额不规范,如订单编号或者金额中出现了字母或符号

解决办法2:订单编号和订单金额只能有数字组成


http://chatgpt.dhexx.cn/article/AmdcUuGL.shtml

相关文章

2021年,Flutter 与 React Native该如何选择?,安卓app开发教程

一、Flutter 应用的优势 =========================================================================== 1. 热重载 = 快速编码 Flutter 允许开发人员使用一种更复杂、更快速的方式来创建应用程序。这是 Flutter 的最大优势之一,也是所有顶级移动应用开发公司都颇为看重的…

一大波开发者福利来了,一份微软官方Github上发布的开源项目清单等你签收

目录 微软Github开源项目入口微软开源项目受欢迎程度排名 Visual Studio CodeTypeScriptRxJS.NET Core 基础类库CNTKMicrosoft calculatorMonaco editorMS-DOSRedis windows版.NET Core CLR (公共语言运行时)ASP.NET CoreEntity Framework CorePowerShell如何在其中搜索自己需要…

.Net资讯 | 一大波开发者福利来了, 一份微软官方Github上发布的开源项目清单等你签收...

目录 微软Github开源项目入口微软开源项目受欢迎程度排名 Visual Studio CodeTypeScriptRxJS.NET Core 基础类库CNTKMicrosoft calculatorMonaco editorMS-DOSRedis windows版.NET Core CLR (公共语言运行时)ASP.NET CoreEntity Framework CorePowerShell如何在其中搜索自己需要…

FullCalendar:eventColor,eventBackgroundColor, eventBorderColor, and eventTextColor

<!DOCTYPE html><html><head><meta charsetutf-8 /><title>背景色設定</title><link href../fullcalendar.min.css relstylesheet /><link href../fullcalendar.print.min.css relstylesheet mediaprint /><script src../l…

Flutter 与 React Native 该如何选择

跨平台程序员之间关于 React Native 和 Flutter 的旷日持久的争论越来越白热化了。前几年&#xff0c;React Native 还是开发人员的首选框架&#xff0c;但是自 2017 年 Flutter 发布以来&#xff0c;其已经发展成为 React Native 的一个强有力竞争对手。 最近&#xff0c;随着…

2021年,Flutter 与 React Native该如何选择?

????????关注后回复 “进群” &#xff0c;拉你进程序员交流群???????? 作者 | Wasim Charoliya 译者 | 王强 策划 | 田晓旭 2021 年&#xff0c;跨平台程序员之间关于 React Native 和 Flutter 的旷日持久的争论越来越白热化了。前几年&#xff0c;React Nati…

React Native 三端同构实践

⚠️ 博客中涉及的代码内容可查看 Github: react-native-isomorphism React Native三端同构皆在&#x1f22f;️在不改动 React Native 代码下&#xff0c;公用一套代码架构, 在浏览器中实现同样的展示、交互、功能。 在实际开发过程中, 尤其创业公司, 需求的迭代周期是非常快…

吐血推荐|2万字总结Mac所有应用程序、软件工具和相关资料

现在随着互联网的发展&#xff0c;越来越多的公司都鼓励Mac办公&#xff0c;属实MacOS系统对于我们的工作开发效率有很大提升&#xff0c;所以我们需要收集各种类别非常好用的 Mac 应用程序、软件以及工具。作为一个资深 Mac 用户&#xff0c;我需要它们帮助我快乐、高效的工作…

网易云音乐React Native体系建设与发展

本文作者&#xff1a;章伟东 &#xff08;网易云音乐大前端团队&#xff09; 0.33 历史 17 年 3 月份&#xff0c;为了解决商城性能和用户体验问题&#xff0c;云音乐技术团队组建了一只 4 人 ReactNative 开发小分队&#xff1a;我负责 RN 前端开发&#xff0c;安卓和 iOS 两…

每周分享第 26 期

这里记录过去一周&#xff0c;我看到的值得分享的东西&#xff0c;每周五发布。 Basecamp 是 IT 行业很有名的一家公司&#xff0c;提供团队协作工具&#xff0c;同时也是 Rails on Ruby 框架的创造者。这家公司的特别之处在于&#xff0c;它不仅写软件&#xff0c;还写畅销书&…

爱开源的微软是如何击败 Facebook、Google 成为 GitHub No.1 的?

拥抱开源的微软这几年究竟都做了些什么&#xff1f; 去年今月&#xff0c;我在微软开发者峰会上见到了《设计模式&#xff1a;可复用面向对象软件的基础》联合作者、现任微软技术院士&#xff08;Technical Fellow at Microsoft&#xff09;Erich Gamma&#xff0c;那是我第一次…

跨端与同构开发技术一览

关键词&#xff1a;React Native, uni-app, Flutter ,Tauri, Ionic 和 weex 文章目录 前言跨端技术简史几种常见跨端技术对比小程序的繁荣跨端同构技术uni-appTaroreact-native-webreactxpWeex阿里的RaxRemax去哪儿网的qrn-remax-unir去哪儿网的anuKbone腾讯新一代跨端开发框架…

@开发者,一份微软官方Github上发布的开源项目清单等你签收

最近在倒腾WPF的项目&#xff0c;试着搜一下微软官方提供的WPF Smaples, 结果找到了https://github.com/Microsoft/WPF-Samples. 当然还发现了Cortana相关的开源资料http://microsoft.github.io/UWPQuickStart/docs/challenges/cortana-integration.html和UWP资源http://micros…

React Native 三端同构实战

WeiboGoogle用电子邮件发送本页面 0 React Native 三端&#xff08;Web、iOS、Android&#xff09;同构是指在不改动原 React Native 的代码下&#xff0c;让其在浏览器中运行出和在 React Native 环境下一样的页面。对于使用 React Native 开发的页面&#xff0c;如果又单独为…

reactxp搭建,start:windows运行不起来

1、官网 reactxp 2、VSCode和Visual Studio2019 安装VSCode Visual Studio 下载地址 先不用勾选工作负荷&#xff0c;直接安装 3、安装nvm 访问下载地址下载安装nvm&#xff1a; 百度云分享 官网直装链接 nvm的github发行界面下载nvm-setup.exe GitCode镜像下载nvm-setup…

微软发布ReactXP:方便开发者构建跨平台应用

说起跨平台开发工具&#xff0c;开发者们最先想到的无外乎是 Cordova 和 Xamarin。但是前者无法提供足够令人满意的性能表现&#xff0c;而后者在 Web 开发上心有余而力不足。所以&#xff0c;微软 Skype 团队基于 React JS 和 React Native 开发了一款全新的跨平台开发工具 —…

跨平台技术实践案例: 用 reactxp 重写墨刀的移动端

重新编写&#xff0c;又一次&#xff0c;我们又一次重新编写了移动端应用和移动端网站。要重新编写是一个风险很大的决定&#xff0c;但是其必要性以及它所带来的收益是我们无法拒绝的。这篇文章会分享我们为什么这么做&#xff0c;我们是怎么做的&#xff0c;以及这次重写后为…

ReactXP入门指南

ReactXP入门指南 1.ReactXP介绍 ReactXP使用了React框架&#xff0c;使得开发人员可以使用React开发他们的跨平台任务。 React的理念是“学习一次&#xff0c;写在任何地方”。使用React和React Native&#xff0c;应用程序可以与iOS和Android应用程序共享大部分逻辑&#x…

SfM、VO和SLAM介绍

一家之言&#xff0c;仅作分享&#xff0c;如有不合理或需要改进的地方&#xff0c;欢迎各位讨论。 前言 在自动驾驶地图定位模块的功能开发中&#xff0c;主要研究方向分为三种&#xff1a;建图、里程计、定位。SfM&#xff08;Structure From Motion&#xff09;即 传统三维…

SfM: Structure from motion

SfM Structure from motion (SfM) is the process of estimating the 3-D structure of a scene from a set of 2-D images. 运动结构&#xff08;SfM&#xff09;是根据一组二维图像估计场景的 3-D **结构的过程。 注意Motion是指相机在移动 SFM通常用来建立image structu…