沙箱支付宝支付 SpringBoot+Vue前后端分离项目 实战
沙箱支付宝支付 SpringBoot+Vue前后端分离项目 实战
·
一、教学讲解视频
对应教程视频:B站视频教程
二、支付宝有关的配置代码
pom.xml依赖:
<!-- 支付宝支付jar包 -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.1.0</version>
</dependency>
AliPayUtil.java代码:
package com.yjq.programmer.util;
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.yjq.programmer.config.AliPayConfig;
import com.yjq.programmer.domain.AliPayBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author 杨杨吖
* @QQ 823208782
* @WX yjqi12345678
* @create 2021-11-07 10:23
*/
/**
* 支付宝支付工具类
*/
@Component
public class AliPayUtil {
@Autowired
private AliPayConfig alipayConfig;
/**
* 支付接口
* @param alipayBean
* @return
* @throws AlipayApiException
*/
public String pay(AliPayBean alipayBean) throws AlipayApiException {
// 1、获得初始化的AlipayClient
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;
}
}
AliPayConfig.java代码:
package com.yjq.programmer.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* @author 杨杨吖
* @QQ 823208782
* @WX yjqi12345678
* @create 2021-11-07 10:25
*/
@Configuration
@Component
public class AliPayConfig {
/**
* 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
*/
private String appId = "2016110300790563";
/**
* 商户私钥,您的PKCS8格式RSA2私钥 填上你的私钥
*/
private String privateKey = "";
/**
* 支付宝公钥, 填上你的公钥
*/
private String publicKey = "";
/**
* 服务器异步通知页面路径需http://格式的完整路径,不能加?id=123这类自定义参数
*/
private String notifyUrl = "http://localhost:8080/user/order";
/**
* 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数
*/
private String returnUrl = "http://localhost:8080/user/order";
/**
* 签名方式
*/
private String signType = "RSA2";
/**
* 字符编码格式
*/
private String charset = "UTF-8";
/**
* 支付宝网关
*/
private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
/**
* 支付宝网关
*/
private String 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;
}
}
AliPayBean.java代码:
package com.yjq.programmer.domain;
/**
* @author 杨杨吖
* @QQ 823208782
* @WX yjqi12345678
* @create 2021-11-07 10:34
*/
/**
* 支付实体对象
* 根据支付宝接口协议,其中的属性名,必须使用下划线,不能修改
*/
public class AliPayBean {
/**
* 商户订单号,必填
*
*/
private String out_trade_no;
/**
* 订单名称,必填
*/
private String subject;
/**
* 付款金额,必填
* 根据支付宝接口协议,必须使用下划线
*/
private String total_amount;
/**
* 商品描述,可空
*/
private String body;
/**
* 超时时间参数
*/
private String timeout_express= "5m";
/**
* 产品编号
*/
private String product_code= "FAST_INSTANT_TRADE_PAY";
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;
}
}
三、控制层接口代码
控制层StoreController.java文件代码:
package com.yjq.programmer.controller;
import com.yjq.programmer.dto.*;
import com.yjq.programmer.service.IStoreService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
/**
* @author 杨杨吖
* @QQ 823208782
* @WX yjqi12345678
* @create 2022-07-06 15:44
*/
@RestController
@RequestMapping("/store")
public class StoreController {
@Resource
private IStoreService storeService;
/**
* 使用沙箱支付宝支付订单
* @param orderDTO
* @return
*/
@PostMapping("/order/aliPay")
public ResponseDTO<String> aliPayOrder(@RequestBody OrderDTO orderDTO){
return storeService.aliPayOrder(orderDTO);
}
/**
* 沙箱支付宝成功支付回调接口
* @param orderDTO
* @return
*/
@PostMapping("/order/aliPay/success")
public ResponseDTO<Boolean> aliPayOrderSuccess(@RequestBody OrderDTO orderDTO){
return storeService.aliPayOrderSuccess(orderDTO);
}
}
四、实体文件返回文件代码
CodeMsg.java返回码文件代码:
public class CodeMsg {
private Integer code;//错误码
private String msg;//错误信息
/**
* 构造函数私有化即单例模式
* 该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
* @param code
* @param msg
*/
private CodeMsg(Integer code, String msg){
this.code = code;
this.msg = msg;
}
public CodeMsg() {
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
//通用错误码定义
//处理成功消息码
public static CodeMsg SUCCESS = new CodeMsg(0, "success");
}
OrderDTO.java实体文件代码:
package com.yjq.programmer.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @author 杨杨吖
* @QQ 823208782
* @WX yjqi12345678
* @create 2022-07-16 20:35
*/
public class OrderDTO {
private String id;
private String no;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
private Integer state;
private String userId;
private String address;
private String remark;
private BigDecimal totalPrice;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
ResponseDTO.java返回文件代码:
package com.yjq.programmer.dto;
import com.yjq.programmer.bean.CodeMsg;
/**
* @author 杨杨吖
* @QQ 823208782
* @WX yjqi12345678
* @create 2020-09-20 10:34
*/
/**
* 返回类数据传输对象 作用于service和controller
* @param <T>
*/
public class ResponseDTO<T> {
private Integer code;
private String msg;
private T data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public ResponseDTO() {
}
private ResponseDTO(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
private ResponseDTO(Integer code, T data) {
this.code = code;
this.data = data;
}
private ResponseDTO(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public static <T> ResponseDTO<T> success(T data) {
return new ResponseDTO<>(CodeMsg.SUCCESS.getCode(), data);
}
public static <T> ResponseDTO<T> successByMsg(T data, String msg) {
return new ResponseDTO<>(CodeMsg.SUCCESS.getCode(), msg, data);
}
public static <T> ResponseDTO<T> errorByMsg(CodeMsg codeMsg) {
return new ResponseDTO<>(codeMsg.getCode(),codeMsg.getMsg());
}
}
五、业务逻辑层Service代码
IStoreService.java文件代码
package com.yjq.programmer.service;
import com.yjq.programmer.dto.*;
import java.math.BigDecimal;
import java.util.List;
/**
* @author 杨杨吖
* @QQ 823208782
* @WX yjqi12345678
* @create 2022-07-06 15:25
*/
public interface IStoreService {
// 使用沙箱支付宝支付订单
ResponseDTO<String> aliPayOrder(OrderDTO orderDTO);
// 沙箱支付宝成功支付回调接口
ResponseDTO<Boolean> aliPayOrderSuccess(OrderDTO orderDTO);
}
里面有一些业务逻辑处理的代码我就不贴了,这个根据自己的业务需求去写就好了,这里我帮大家把支付的最核心代码抽出来
StoreServiceImpl.java文件代码:
package com.yjq.programmer.service.impl;
import com.alipay.api.AlipayApiException;
import com.yjq.programmer.dto.*;
import com.yjq.programmer.service.IStoreService;
import com.yjq.programmer.util.AliPayUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
* @author 杨杨吖
* @QQ 823208782
* @WX yjqi12345678
* @create 2022-07-06 15:25
*/
@Service
@Transactional
public class StoreServiceImpl implements IStoreService {
@Resource
private AliPayUtil aliPayUtil;
/**
* 使用沙箱支付宝支付订单
* @param orderDTO
* @return
*/
@Override
public ResponseDTO<String> aliPayOrder(OrderDTO orderDTO) {
BigDecimal totalPrice = new BigDecimal("0.00");
String orderNo = "111111111";
return initAliPay(orderNo, totalPrice);
}
/**
* 初始化支付信息
* @param orderNo
* @param totalPrice
* @return
*/
public ResponseDTO<String> initAliPay(String orderNo, BigDecimal totalPrice) {
// 封装沙箱支付宝支付信息
AliPayBean alipayBean = new AliPayBean();
alipayBean.setOut_trade_no(orderNo);
alipayBean.setSubject("校园二手市场沙箱支付宝支付");
alipayBean.setTotal_amount(String.valueOf(totalPrice));
alipayBean.setBody("欢迎您在校园二手市场上下单!!");
String pay = null;
try {
pay = aliPayUtil.pay(alipayBean);
} catch (AlipayApiException e) {
e.printStackTrace();
}
return ResponseDTO.success(pay);
}
/**
* 沙箱支付宝成功支付回调接口
* @param orderDTO
* @return
*/
@Override
public ResponseDTO<Boolean> aliPayOrderSuccess(OrderDTO orderDTO) {
// 这里可以写一些回调的接口逻辑,比如更新订单状态
// 因为我们这有一个OrderDTO的入参,我们可以使用这个实体里面的订单号字段来获取详细订单信息
return ResponseDTO.successByMsg(true, "支付成功!");
}
}
六、前端Vue支付页面展示代码
点击支付按钮时候,调用这个payOrder函数
process.env.VUE_APP_SERVER是代表向后端接口请求的地址
payOrder() {
let _this = this;
this.$ajax.post(process.env.VUE_APP_SERVER + "/store/order/aliPay", {}).then((response)=>{
let resp = response.data;
if(resp.code === 0){
// 添加之前先删除一下,如果单页面,页面不刷新,添加进去的内容会一直保留在页面中,二次调用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();
} else {
_this.$message.error(resp.msg);
}
});
},
在个人订单页面的mounted生命周期中调用这个payReturn函数,为了判断如果是支付的回调的话,就调用后端的接口进行订单状态修改的一些操作。
process.env.VUE_APP_SERVER是代表向后端接口请求的地址
payReturn() {
let _this = this;
if (this.$route.query && this.$route.query.out_trade_no){
// 支付回调
console.log("进入回调...");
console.log("交易号:"+ this.$route.query.out_trade_no);
this.$ajax.post(process.env.VUE_APP_SERVER + "/store/order/aliPay/success", {no: this.$route.query.out_trade_no}).then((response)=>{
let resp = response.data;
if(resp.code === 0){
_this.$message.success(resp.msg);
}else{
_this.$message.error(resp.msg);
}
});
}
}
更多推荐
已为社区贡献6条内容
所有评论(0)