SpringBoot+Vue整合支付宝沙箱支付
SpringBoot+Vue2整合实现支付宝沙箱支付原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!在进行电脑网站开发时我们常常需要用到支付宝支付,接下来我将带领大家使用springboot+vue整合支付宝沙箱支付1.支付宝开放平台注册沙箱账号登录 支付宝开放平台,创建应用并提交审核,审核通过后会生成应用唯一标识 APPID
SpringBoot+Vue2整合实现支付宝沙箱支付
原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!
在进行电脑网站开发时我们常常需要用到支付宝支付,接下来我将带领大家使用springboot+vue整合支付宝沙箱支付
1.支付宝开放平台注册沙箱账号
登录 支付宝开放平台,创建应用并提交审核,审核通过后会生成应用唯一标识 APPID,并且可以申请开通开放产品使用权限。通过 APPID 应用才能调用开放产品的接口能力
-
卖家账号
商家账号,支付成功后账户余额会相应增加
-
买家账号
用于后期功能开发完成即可使用该账号进行支付
接下来就是重要的一步–配置生成应用私钥、应用公钥
点击自定义密钥,选择证书
点击支付宝密钥生成器后
点击压缩包,解压、安装
安装完成后点击桌面应用
进入后首先支付宝扫码登录
点击后会出现这个界面
注:这个应用公钥和应用私钥非常重要,后期在写后台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触发事件,向后台发起请求
<button style="margin-left: 20px;background-color: white;border-radius:16px;" @click="submit">
注意:向后端传值时都必须为string类型
且订单编号和金额必须为**单引号内包含数字的形式 例如 **:
`//订单编号`
`order_number: '20025215241524',`
`//订单详情`
`order_detail: '商品支付',`
`//商品信息`
`goods_info: '支付宝支付',`
`//订单金额`
`order_price: '5215',`
点击支付后会自动跳转支付宝沙箱支付的支付界面
点击下一步,支付密码也是11111
点击确认付款后,不出意外会弹出支付成功的界面
支付成功后就会自动跳转到之前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整合支付包沙箱支付全部完毕!!!
原创不易,转载请注明!!
原创不易,转载请注明!!
更多推荐
所有评论(0)