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-8gatewayUrl: https://openapi.alipaydev.com/gateway.do
logPath:"D:\\"
我的项目采用的是五层架构
首先在是config目录下的AlipayConfig
保持一致就行
importlombok.Data;importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.PropertySource;importorg.springframework.stereotype.Component;/**
* 读取配置文件
*/@Configuration@ConfigurationProperties(prefix ="alipay")@PropertySource("classpath:/application.yml")@Data@ComponentpublicclassAlipayConfig{/**
* 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
*/privateString appId;/**
* 商户私钥,您的PKCS8格式RSA2私钥
*/privateString privateKey;/**
* 支付宝公钥,
*/privateString publicKey;/**
* 服务器异步通知页面路径需http://格式的完整路径,不能加?id=123这类自定义参数
*/privateString notifyUrl;/**
* 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数
*/privateString returnUrl;/**
* 签名方式
*/privateString signType;/**
* 字符编码格式
*/privateString charset;/**
* 支付宝网关
*/privateString gatewayUrl;/**
* 支付宝网关
*/privateString logPath;publicAlipayConfig(){}publicAlipayConfig(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;}publicStringgetAppId(){return appId;}publicvoidsetAppId(String appId){this.appId = appId;}publicStringgetPrivateKey(){return privateKey;}publicvoidsetPrivateKey(String privateKey){this.privateKey = privateKey;}publicStringgetPublicKey(){return publicKey;}publicvoidsetPublicKey(String publicKey){this.publicKey = publicKey;}publicStringgetNotifyUrl(){return notifyUrl;}publicvoidsetNotifyUrl(String notifyUrl){this.notifyUrl = notifyUrl;}publicStringgetReturnUrl(){return returnUrl;}publicvoidsetReturnUrl(String returnUrl){this.returnUrl = returnUrl;}publicStringgetSignType(){return signType;}publicvoidsetSignType(String signType){this.signType = signType;}publicStringgetCharset(){return charset;}publicvoidsetCharset(String charset){this.charset = charset;}publicStringgetGatewayUrl(){return gatewayUrl;}publicvoidsetGatewayUrl(String gatewayUrl){this.gatewayUrl = gatewayUrl;}publicStringgetLogPath(){return logPath;}publicvoidsetLogPath(String logPath){this.logPath = logPath;}@OverridepublicStringtoString(){return"AlipayConfig{"+"appId='"+ appId +'\''+", privateKey='"+ privateKey +'\''+", publicKey='"+ publicKey +'\''+", notifyUrl='"+ notifyUrl +'\''+", returnUrl='"+ returnUrl +'\''+", signType='"+ signType +'\''+", charset='"+ charset +'\''+", gatewayUrl='"+ gatewayUrl +'\''+", logPath='"+ logPath +'\''+'}';}}
接下来是domin目录下的AlipayBean文件,也保持一致
packagecom.htu.domain;/**
* 支付实体对象
* 根据支付宝接口协议,其中的属性名,必须使用下划线,不能修改
*/publicclassAlipayBean{/**
* 商户订单号,必填
*
*/privateString out_trade_no;/**
* 订单名称,必填
*/privateString subject;/**
* 付款金额,必填
* 根据支付宝接口协议,必须使用下划线
*/privateString total_amount;/**
* 商品描述,可空
*/privateString body;/**
* 超时时间参数
*/privateString timeout_express="10m";/**
* 产品编号
*/privateString product_code="FAST_INSTANT_TRADE_PAY";publicAlipayBean(){}publicAlipayBean(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;}publicStringgetOut_trade_no(){return out_trade_no;}publicvoidsetOut_trade_no(String out_trade_no){this.out_trade_no = out_trade_no;}publicStringgetSubject(){return subject;}publicvoidsetSubject(String subject){this.subject = subject;}publicStringgetTotal_amount(){return total_amount;}publicvoidsetTotal_amount(String total_amount){this.total_amount = total_amount;}publicStringgetBody(){return body;}publicvoidsetBody(String body){this.body = body;}publicStringgetTimeout_express(){return timeout_express;}publicvoidsetTimeout_express(String timeout_express){this.timeout_express = timeout_express;}publicStringgetProduct_code(){return product_code;}publicvoidsetProduct_code(String product_code){this.product_code = product_code;}@OverridepublicStringtoString(){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
importcom.alipay.api.AlipayApiException;importcom.htu.domain.AlipayBean;importcom.htu.model.alipay.IPayModel;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;@RestController@CrossOriginpublicclassAliPayController{@AutowiredprivateIPayModel model;@PostMapping(value ="/order/alipay")publicStringalipay(String outTradeNo,String subject,String totalAmount,String body)throwsAlipayApiException{AlipayBean alipayBean =newAlipayBean();
alipayBean.setOut_trade_no(outTradeNo);
alipayBean.setSubject(subject);
alipayBean.setTotal_amount(totalAmount);
alipayBean.setBody(body);return model.aliPay(alipayBean);}}
model层的IPayModel
importcom.alipay.api.AlipayApiException;importcom.htu.domain.AlipayBean;publicinterfaceIPayModel{/**
* 支付宝支付接口
* @param alipayBean
* @return
* @throws AlipayApiException
*/StringaliPay(AlipayBean alipayBean)throwsAlipayApiException;}
其对应的实现类PayModelImpl
importcom.alipay.api.AlipayApiException;importcom.htu.domain.AlipayBean;importcom.htu.model.alipay.IPayModel;importcom.htu.service.alipay.IPayService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;@ComponentpublicclassPayModelImplimplementsIPayModel{@AutowiredprivateIPayService service;@OverridepublicStringaliPay(AlipayBean alipayBean)throwsAlipayApiException{return service.aliPay(alipayBean);}}
service层下的IPayService
importcom.alipay.api.AlipayApiException;importcom.htu.domain.AlipayBean;publicinterfaceIPayService{/**
* 支付宝支付接口
* @param alipayBean
* @return
* @throws AlipayApiException
*/StringaliPay(AlipayBean alipayBean)throwsAlipayApiException;}
对应的实现类PayServiceImpl
importcom.alipay.api.AlipayApiException;importcom.htu.domain.AlipayBean;importcom.htu.service.alipay.IPayService;importcom.htu.utils.AlipayUtile;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;@ServicepublicclassPayServiceImplimplementsIPayService{@AutowiredprivateAlipayUtile alipayUtile;@OverridepublicStringaliPay(AlipayBean alipayBean)throwsAlipayApiException{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文件与以下保持一致,字段名用_连接
packagecom.htu.domain;/**
* 支付实体对象
* 根据支付宝接口协议,其中的属性名,必须使用下划线,不能修改
*/publicclassAlipayBean{/**
* 商户订单号,必填
*
*/privateString out_trade_no;/**
* 订单名称,必填
*/privateString subject;/**
* 付款金额,必填
* 根据支付宝接口协议,必须使用下划线
*/privateString total_amount;/**
* 商品描述,可空
*/privateString body;/**
* 超时时间参数
*/privateString timeout_express="10m";/**
* 产品编号
*/privateString product_code="FAST_INSTANT_TRADE_PAY";publicAlipayBean(){}publicAlipayBean(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;}publicStringgetOut_trade_no(){return out_trade_no;}publicvoidsetOut_trade_no(String out_trade_no){this.out_trade_no = out_trade_no;}publicStringgetSubject(){return subject;}publicvoidsetSubject(String subject){this.subject = subject;}publicStringgetTotal_amount(){return total_amount;}publicvoidsetTotal_amount(String total_amount){this.total_amount = total_amount;}publicStringgetBody(){return body;}publicvoidsetBody(String body){this.body = body;}publicStringgetTimeout_express(){return timeout_express;}publicvoidsetTimeout_express(String timeout_express){this.timeout_express = timeout_express;}publicStringgetProduct_code(){return product_code;}publicvoidsetProduct_code(String product_code){this.product_code = product_code;}@OverridepublicStringtoString(){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整合支付包沙箱支付全部完毕!!!
原创不易,转载请注明!!
原创不易,转载请注明!!
版权归原作者 金州扣篮王拉文 所有, 如有侵权,请联系我们删除。