SpringBoot+Vue2整合实现支付宝沙箱支付
原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!
在进行电脑网站开发时我们常常需要用到支付宝支付,接下来我将带领大家使用springboot+vue整合支付宝沙箱支付
1.支付宝开放平台注册沙箱账号
登录支付宝开放平台,创建应用并提交审核,审核通过后会生成应用唯一标识 APPID,并且可以申请开通开放产品使用权限。通过 APPID 应用才能调用开放产品的接口能力
- 卖家账号
- 买家账号
用于后期功能开发完成即可使用该账号进行支付

接下来就是重要的一步–配置生成应用私钥、应用公钥
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OaojsvzM-1649656872189)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20220411103355245.png)]](https://javaforall.net/wp-content/uploads/2020/11/2020110817443450.jpg)
点击自定义密钥,选择证书

点击支付宝密钥生成器后

点击压缩包,解压、安装
安装完成后点击桌面应用

进入后首先支付宝扫码登录

点击后会出现这个界面
注:这个应用公钥和应用私钥非常重要,后期在写后台Java代码时会用到

保存后会出现这个界面,至此我们的沙箱账号的公钥私钥就配置完成了

2.SpringBoot整合沙箱支付
首先是项目目录结构,由于我的整合是在一个大项目中,大家在学习沙箱支付时只需看我提到的部分就行
箭头所指就是需要用到的Java代码(其他的不用管)


目录结构创建好后,接下来就是Java代码的部分
1.首先在pom文件中添加项目所需要的相应依赖
<dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.22.57.ALL</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.48</version> </dependency>
2.在resource目录下创建application.yml文件
注:下面这个图片是我自己的支付宝配置,大家可根据自己的账号进行配置

- appId:#支付宝开放平台中沙箱应用

- privateKey: #应用私钥
- publicKey: #应用公钥

- notifyUrl:#异步通知url设置成 http://locallhost:8080 就可
- returnUrl:#支付成功后返回的url
剩下的就与我的保持一致就行

以下是我所提供的代码模板,缺少的部分大家根据自己的配置自行添加
alipay: appId: privateKey: publicKey: notifyUrl: returnUrl: signType: RSA2 charset: utf-8 gatewayUrl: https://openapi.alipaydev.com/gateway.do logPath: "D:\\"
我的项目采用的是五层架构
首先在是config目录下的AlipayConfig
保持一致就行
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; / * 读取配置文件 */ @Configuration @ConfigurationProperties(prefix = "alipay") @PropertySource("classpath:/application.yml") @Data @Component public class AlipayConfig {
/ * 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号 */ private String appId; / * 商户私钥,您的PKCS8格式RSA2私钥 */ private String privateKey; / * 支付宝公钥, */ private String publicKey; / * 服务器异步通知页面路径需http://格式的完整路径,不能加?id=123这类自定义参数 */ private String notifyUrl; / * 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数 */ private String returnUrl; / * 签名方式 */ private String signType; / * 字符编码格式 */ private String charset; / * 支付宝网关 */ private String gatewayUrl; / * 支付宝网关 */ private String logPath; public AlipayConfig() {
} public AlipayConfig(String appId, String privateKey, String publicKey, String notifyUrl, String returnUrl, String signType, String charset, String gatewayUrl, String logPath) {
this.appId = appId; this.privateKey = privateKey; this.publicKey = publicKey; this.notifyUrl = notifyUrl; this.returnUrl = returnUrl; this.signType = signType; this.charset = charset; this.gatewayUrl = gatewayUrl; this.logPath = logPath; } public String getAppId() {
return appId; } public void setAppId(String appId) {
this.appId = appId; } public String getPrivateKey() {
return privateKey; } public void setPrivateKey(String privateKey) {
this.privateKey = privateKey; } public String getPublicKey() {
return publicKey; } public void setPublicKey(String publicKey) {
this.publicKey = publicKey; } public String getNotifyUrl() {
return notifyUrl; } public void setNotifyUrl(String notifyUrl) {
this.notifyUrl = notifyUrl; } public String getReturnUrl() {
return returnUrl; } public void setReturnUrl(String returnUrl) {
this.returnUrl = returnUrl; } public String getSignType() {
return signType; } public void setSignType(String signType) {
this.signType = signType; } public String getCharset() {
return charset; } public void setCharset(String charset) {
this.charset = charset; } public String getGatewayUrl() {
return gatewayUrl; } public void setGatewayUrl(String gatewayUrl) {
this.gatewayUrl = gatewayUrl; } public String getLogPath() {
return logPath; } public void setLogPath(String logPath) {
this.logPath = logPath; } @Override public String toString() {
return "AlipayConfig{" + "appId='" + appId + '\'' + ", privateKey='" + privateKey + '\'' + ", publicKey='" + publicKey + '\'' + ", notifyUrl='" + notifyUrl + '\'' + ", returnUrl='" + returnUrl + '\'' + ", signType='" + signType + '\'' + ", charset='" + charset + '\'' + ", gatewayUrl='" + gatewayUrl + '\'' + ", logPath='" + logPath + '\'' + '}'; } }
接下来是domin目录下的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; } @Override public 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 + '\'' + '}'; } }
Controller层的AliPayController
import com.alipay.api.AlipayApiException; import com.htu.domain.AlipayBean; import com.htu.model.alipay.IPayModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @CrossOrigin public class AliPayController {
@Autowired private IPayModel model; @PostMapping(value = "/order/alipay") public String alipay(String outTradeNo, String subject, String totalAmount, String body) throws AlipayApiException {
AlipayBean alipayBean = new AlipayBean(); alipayBean.setOut_trade_no(outTradeNo); alipayBean.setSubject(subject); alipayBean.setTotal_amount(totalAmount); alipayBean.setBody(body); return model.aliPay(alipayBean); } }
model层的IPayModel
import com.alipay.api.AlipayApiException; import com.htu.domain.AlipayBean; public interface IPayModel {
/ * 支付宝支付接口 * @param alipayBean * @return * @throws AlipayApiException */ String aliPay(AlipayBean alipayBean) throws AlipayApiException; }
其对应的实现类PayModelImpl
import com.alipay.api.AlipayApiException; import com.htu.domain.AlipayBean; import com.htu.model.alipay.IPayModel; import com.htu.service.alipay.IPayService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class PayModelImpl implements IPayModel {
@Autowired private IPayService service; @Override public String aliPay(AlipayBean alipayBean) throws AlipayApiException {
return service.aliPay(alipayBean); } }
service层下的IPayService
import com.alipay.api.AlipayApiException; import com.htu.domain.AlipayBean; public interface IPayService {
/ * 支付宝支付接口 * @param alipayBean * @return * @throws AlipayApiException */ String aliPay(AlipayBean alipayBean) throws AlipayApiException; }
对应的实现类PayServiceImpl
import com.alipay.api.AlipayApiException; import com.htu.domain.AlipayBean; import com.htu.service.alipay.IPayService; import com.htu.utils.AlipayUtile; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class PayServiceImpl implements IPayService {
@Autowired private AlipayUtile alipayUtile; @Override public String aliPay(AlipayBean alipayBean) throws AlipayApiException {
return alipayUtile.pay(alipayBean); } }
utile包下的AlipayUtile
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.htu.config.AlipayConfig; import com.htu.domain.AlipayBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class AlipayUtile { @Autowired private AlipayConfig alipayConfig; / * 支付接口 * * @param alipayBean * @return * @throws AlipayApiException */ public String pay(AlipayBean alipayBean) throws AlipayApiException { String serverUrl = alipayConfig.getGatewayUrl(); String appId = alipayConfig.getAppId(); String privateKey = alipayConfig.getPrivateKey(); String format = "json"; String charset = alipayConfig.getCharset(); String alipayPublicKey = alipayConfig.getPublicKey(); String signType = alipayConfig.getSignType(); String returnUrl = alipayConfig.getReturnUrl(); String notifyUrl = alipayConfig.getNotifyUrl(); AlipayClient alipayClient = new DefaultAlipayClient(serverUrl, appId, privateKey, format, charset, alipayPublicKey, signType); // 2、设置请求参数 AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); // 页面跳转同步通知页面路径 alipayRequest.setReturnUrl(returnUrl); // 服务器异步通知页面路径 alipayRequest.setNotifyUrl(notifyUrl); // 封装参数 alipayRequest.setBizContent(JSON.toJSONString(alipayBean)); // 3、请求支付宝进行付款,并获取支付结果 String result = alipayClient.pageExecute(alipayRequest).getBody(); // 返回付款信息 return result; } }
至此我们的Java代码全部完毕
接下来是vue前端部分
3.vue对接支付宝支付
首先对接支付宝的沙箱支付需要为后端传4个必要的参数
//订单编号 order_number: '', //订单详情 order_detail: '', //商品信息 goods_info: '', //订单金额 order_price: '',
前端将参数通过axios的方式提交给后端
submit() {
axios.post( "http://localhost:8080/order/alipay?outTradeNo=" + this.ruleForm.order_number + "&subject=" + this.ruleForm.order_detail + "&totalAmount=" + this.ruleForm.order_price + "&body=" + this.ruleForm.goods_info ) .then((resp) => {
// 添加之前先删除一下,如果单页面,页面不刷新,添加进去的内容会一直保留在页面中,二次调用form表单会出错 const divForm = document.getElementsByTagName("div"); if (divForm.length) {
document.body.removeChild(divForm[0]); } const div = document.createElement("div"); div.innerHTML = resp.data; // data就是接口返回的form 表单字符串 document.body.appendChild(div); document.forms[0].setAttribute("target", "_blank"); // 新开窗口跳转 document.forms[0].submit(); }); } }
通过按钮的@click触发事件,向后台发起请求
注意:向后端传值时都必须为string类型
且订单编号和金额必须为单引号内包含数字的形式 例如 :
`//订单编号` `order_number: '524',` `//订单详情` `order_detail: '商品支付',` `//商品信息` `goods_info: '支付宝支付',` `//订单金额` `order_price: '5215',`
点击确认付款后,不出意外会弹出支付成功的界面

支付成功后就会自动跳转到之前returnUrl中设置的界面
我的项目跳转的是订单界面
至此,springboot+vue整合支付宝沙箱支付就完全完毕了
但还有几个问题需要注意一下!!
4.可能遇到的问题
问题1:付款时显示订单已付款
原因: 向支付宝提交的订单号重复,且之前的订单号已支付过
解决办法: 换个订单号就行
问题2: 触发点击事件时界面显示404NotFound

原因1:支付宝网关填写有错误或者支付宝沙箱环境不稳定造成的
解决办法1:查看郁闷了配置文件中gatewayUrl是不是支付宝沙箱支付的网关 如下:
gatewayUrl: https://openapi.alipaydev.com/gateway.do
原因2:支付宝沙箱环境不稳定造成的

解决办法2:在404NotFound界面一直点击刷新,重复提交几次就行了
问题3:输入支付密码后显示,抱歉网络系统繁忙,请稍后再试

原因:沙箱支付环境不稳定或者沙箱环境正在维护中
解决办法:等一天,尽量避开周日到周一一点,这个问题就自动解决了
问题4:付款时跳转到504
原因:网速过慢
解决办法:切换到更快的网络付款就行
问题5:付款时显示支付存在钓鱼风险!

原因:浏览器环境的问题
解决办法1:换一个未登录支付宝开放平台以及未调用过沙箱支付接口的浏览器,重新提交付款
解决办法2:把浏览器上打开的所有沙箱支付、支付宝官方等的页面全部关闭,然后Crtl+Shift+delete,清空浏览器缓存
问题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; } @Override public 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:订单编号和订单金额只能有数字组成
原因2:向后端传的订单号与金额不规范,如订单编号或者金额中出现了字母或符号
解决办法2:订单编号和订单金额只能有数字组成
至此springboot+vue2整合支付包沙箱支付全部完毕!!!
原创不易,转载请注明!!
原创不易,转载请注明!!
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/215060.html原文链接:https://javaforall.net
