SpringBoot+Vue整合支付宝沙箱支付

SpringBoot+Vue2整合实现支付宝沙箱支付

原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!原创不易,转载请注明!!
在进行电脑网站开发时我们常常需要用到支付宝支付,接下来我将带领大家使用springboot+vue整合支付宝沙箱支付

1.支付宝开放平台注册沙箱账号

登录 支付宝开放平台,创建应用并提交审核,审核通过后会生成应用唯一标识 APPID,并且可以申请开通开放产品使用权限。通过 APPID 应用才能调用开放产品的接口能力
  • 卖家账号

    商家账号,支付成功后账户余额会相应增加
    在这里插入图片描述

  • 买家账号

    用于后期功能开发完成即可使用该账号进行支付

在这里插入图片描述

接下来就是重要的一步–配置生成应用私钥、应用公钥

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OaojsvzM-1649656872189)(C:UsersdellAppDataRoamingTypora	ypora-user-imagesimage-20220411103355245.png)]

点击自定义密钥,选择证书

在这里插入图片描述

点击支付宝密钥生成器后

点击压缩包,解压、安装

安装完成后点击桌面应用

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

在这里插入图片描述

点击后会出现这个界面

注:这个应用公钥和应用私钥非常重要,后期在写后台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整合支付包沙箱支付全部完毕!!!

原创不易,转载请注明!!
原创不易,转载请注明!!

  • 9
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的Spring BootVue.js应用程序中的支付宝沙箱支付代码示例: 在Spring Boot项目中: 1. 添加以下依赖: ``` <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.3.0.ALL</version> </dependency> ``` 2. 创建一个包含支付宝配置信息的类,例如: ``` @Configuration public class AlipayConfig { private String appId; private String privateKey; private String publicKey; private String notifyUrl; private String returnUrl; private String gatewayUrl; // getters and setters } ``` 3. 创建一个返回AlipayClient的方法: ``` @Bean public AlipayClient getAlipayClient() { return new DefaultAlipayClient( alipayConfig.getGatewayUrl(), alipayConfig.getAppId(), alipayConfig.getPrivateKey(), "json", "UTF-8", alipayConfig.getPublicKey(), "RSA2" ); } ``` 4. 在控制器中创建支付接口,例如: ``` @Autowired private AlipayClient alipayClient; @Autowired private AlipayConfig alipayConfig; @PostMapping("/pay") public String pay(@RequestParam String orderNo, @RequestParam String amount) throws AlipayApiException { AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); alipayRequest.setReturnUrl(alipayConfig.getReturnUrl()); alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl()); alipayRequest.setBizContent("{\"out_trade_no\":\"" + orderNo + "\"," + "\"total_amount\":\"" + amount + "\"," + "\"subject\":\"" + "测试订单" + "\"," + "\"body\":\"" + "测试订单" + "\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); String form = alipayClient.pageExecute(alipayRequest).getBody(); return form; } ``` 在Vue.js中: 1. 创建一个按钮来启动支付流程: ``` <template> <div> <button @click="pay">Pay Now</button> </div> </template> ``` 2. 在脚本部分中创建一个调用支付接口的方法: ``` <script> export default { methods: { pay() { axios.post('/api/pay', { orderNo: '123456', amount: '0.01' }) .then(response => { let form = response.data; document.write(form); // 打开支付页面 }) .catch(error => { console.log(error); }); } } } </script> ``` 请注意,以上示例只适用于测试环境,如果您想在生产环境中使用支付宝支付,您需要进行更多的测试和配置。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值