实现SpringMVC + Vue 前后端分离 支付宝API付款

项目场景:

需求:VUE + SpringMVC前后端分离项目使用支付宝API接口实现付款。


问题描述

提示为:验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配
在这里输入图片描述

解决方案:

1.密钥真的不匹配,检查是否输出错误或者出现了空格。
2.确认密钥无误,可能是数据传输回前端的时候出现了问题,编码格式不对,出现了中文,解析出现问题,导致失败!!建议在填写订单信息的时候不要出现中文。
3.如果真的需要中文信息,可将返回的结果转换为 utf-8的编码格式,如下:

@PostMapping(value = "pay/alipay" , produces = "text/html;charset=utf-8")

实现过程

获取私钥、公钥、APPID

打开支付宝开放平台:https://open.alipay.com/develop/sandbox/tool
在这里插入图片描述
打开沙箱工具,后使用自定义密钥:
在这里插入图片描述
建议使用密钥生成器来生成密钥:
在这里插入图片描述

按照要求安装下载:
在这里插入图片描述
默认即可,点击生成密钥,生成后这个程序先不要关闭,记录下生成的密钥,之后会用到。
在这里插入图片描述

SpringMVC后端代码编写

如果你是使用SSM或SpringBoot + Mybatis plus写的后端,那么可以直接复制到你的项目,代码进行少量修改即可。

引入支付宝Api的Maven依赖

    <!--支付宝Api-->
    <!-- fastjson -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.48</version>
    </dependency>
    <!-- 支付宝支付jar包 -->
    <dependency>
      <groupId>com.alipay.sdk</groupId>
      <artifactId>alipay-sdk-java</artifactId>
      <version>4.22.57.ALL</version>
    </dependency>
    <!--支付宝Api end-->

需要的文件如下,其他内容不相关可以不看,只需要关注红框内的文件

在这里插入图片描述
在这里插入图片描述

支付宝订单实体类

package cn.edu.nchu.bookstore.entity;

/**
 * 支付实体对象
 * 根据支付宝接口协议,其中的属性名,必须使用下划线,不能修改
 */
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 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;
    }

}

支付宝订单工具类:

package cn.edu.nchu.bookstore.utils.alipay.config;


import cn.edu.nchu.bookstore.dao.OrderDao;
import cn.edu.nchu.bookstore.entity.AlipayBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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;


@Component
public class Alipay {

    @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();
        System.out.println(result);
        // 返回付款信息
        return result;
    }
}

支付宝参数类

注意在这个页面内填入你的APPID,商户私钥,支付宝公钥:

package cn.edu.nchu.bookstore.utils.alipay.config;

import org.springframework.context.annotation.Configuration;

import org.springframework.stereotype.Component;

@Configuration
@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://localhost:8081/#/success";

    /**
     * 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数
     */
    private String returnUrl = "http://localhost:8081/#/success";

    /**
     * 签名方式
     */
    private String signType = "RSA2";

    /**
     * 字符编码格式
     */
    private String charset = "utf-8";

    /**
     * 支付宝网关
     */
    private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

    /**
     * 支付宝网关
     */
    private String logPath = "C:\\";


    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;
    }
}

支付服务接口:

package cn.edu.nchu.bookstore.service;

import cn.edu.nchu.bookstore.entity.AlipayBean;
import com.alipay.api.AlipayApiException;

public interface PayService {

    /**
     * 支付宝支付接口
     * @param alipayBean
     * @return
     * @throws AlipayApiException
     */
    String aliPay(AlipayBean alipayBean) throws AlipayApiException;

}

支付实体服务类实现类

package cn.edu.nchu.bookstore.service.impl;

import cn.edu.nchu.bookstore.entity.AlipayBean;
import cn.edu.nchu.bookstore.service.PayService;
import cn.edu.nchu.bookstore.utils.alipay.config.Alipay;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alipay.api.AlipayApiException;

@Service("payService")
public class PayServiceImpl implements PayService {

    @Autowired
    private Alipay alipay;

    @Override
    public String aliPay(AlipayBean alipayBean) throws AlipayApiException {
        return alipay.pay(alipayBean);
    }
}

支付控制器类

package cn.edu.nchu.bookstore.controller;

import cn.edu.nchu.bookstore.entity.AlipayBean;
import cn.edu.nchu.bookstore.service.PayService;
import cn.edu.nchu.bookstore.utils.JsonResult;
import com.alipay.api.AlipayApiException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;


@RestController
//可修改为Controller
public class PayController {

    @Autowired
    private PayService payService;

    /**
     * 阿里支付
     * @param outTradeNo
     * @param subject
     * @param totalAmount
     * @param body
     * @return
     * @throws AlipayApiException
     */
    @PostMapping(value = "pay/alipay" , produces = "text/html;charset=utf-8")
    /*可替换为:
    @RequestMapping(value = "pay/alipay" , produces = "text/html;charset=utf-8")
    @ResponseBody
    */
    public String alipay(String outTradeNo, String subject, String totalAmount, String body) throws AlipayApiException, UnsupportedEncodingException {
        AlipayBean alipayBean = new AlipayBean();
        alipayBean.setOut_trade_no(outTradeNo);
        alipayBean.setSubject(subject);
        alipayBean.setTotal_amount(totalAmount);
        alipayBean.setBody(body);
        System.out.println(outTradeNo);
        System.out.println(subject);
        System.out.println(totalAmount);
        System.out.println(body);
        return payService.aliPay(alipayBean);

    }
}

前端开发

该部分使用vue实现,通过点击支付按钮点击实现跳转到支付界面吗,将订单填写在params里面
			submitOrder() {
			//	修改为你自己的地址
				var url = "/pay/alipay";
				this.axios({
					method: 'post',
					url: url,
					params: {
					
						outTradeNo: ,//订单的唯一ID
						subject: ,//订单名称
						totalAmount: ,//订单总价,即付款的钱
						body: ,//订单主题内容
					},
					
				}).then(response => {
					// 添加之前先删除一下,如果单页面,页面不刷新,添加进去的内容会一直保留在页面中,二次调用form表单会出错
					const divForm = document.getElementsByTagName('div')
					if (divForm.length) {
						document.body.removeChild(divForm[0])
					}
					const div = document.createElement('div')
					console.log(response.data);
					div.innerHTML = response.data // data就是接口返回的form 表单字符串
					document.body.appendChild(div)
					document.forms[0].setAttribute('target', '_blank') // 新开窗口跳转
					document.forms[0].submit()
				}).catch(err => {
					console.log(err)
				})

支付成功后的操作——success.vue

这个success界面需要在前面的AlipayConfig 类里面定义,你也可以设置为跳转到其他页面。
我是在这个页面实现了支付后的对数据更新的操作,你也可以直接在后端实现业务,而不必在前端再发一次请求。
以下代码仅供参考,你需要自己写post/get请求的方式,界面自行美化
<template>
	<div>
		支付成功!!
	</div>
</template>

<script>
	export default {
		mounted() {
			console.log(this.$route.query.out_trade_no);
			// 获取订单号
			//你也可以通过this.$route.query.xxx 获取订单价格,等信息,
			//在支付之前,通过F12查看“network” ,支付后,你会看到带有订单信息的请求,找到请求的内容
			// 以下代码是支付成功之后的操作,请在这修改你自己的处理方式
			// 以下代码是经过封装的请求,不能直接使用
			// 我这里的意思是支付后,根据订单ID对订单状态进行修改
			this.$post("order/payForOrderByGen", {
				orderGeneratedId: this.$route.query.out_trade_no,
			}).then(res => {
				this.$message({
					message: res.data ? '支付成功!' : "支付失败",
					type: res.data ? 'success' : 'error'
				});
				// 跳转到订单页面
				this.$router.push("/customer/order");
			}).catch(err => {
				console.log(err);
			});
		}
	}
</script>

<style>
</style>

参考文章

https://blog.csdn.net/weixin_51324855/article/details/124097792


如文章中有侵权,请及时联系删除。
本文用于记录作者本人的学习,其中遇到的问题,欢迎大家在讨论区交流。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
本文将介绍如何利用SpringMVCVue实现前后端分离的大学生社团管理系统。 1. 系统需求分析 该系统需要实现以下功能: - 用户登录和注册 - 社团管理:创建、修改、删除社团 - 活动管理:创建、修改、删除活动 - 成员管理:加入、退出社团 2. 系统设计 该系统采用前后端分离的架构,前端使用Vue框架,后端采用SpringMVC框架。 2.1 后端设计 后端使用SpringMVC框架,实现了以下功能: - 用户登录和注册 - 社团管理:创建、修改、删除社团 - 活动管理:创建、修改、删除活动 - 成员管理:加入、退出社团 2.2 前端设计 前端使用Vue框架,实现了以下功能: - 用户登录和注册 - 社团管理:创建、修改、删除社团 - 活动管理:创建、修改、删除活动 - 成员管理:加入、退出社团 3. 系统实现 3.1 后端实现 后端使用SpringMVC框架,实现了以下功能: - 用户登录和注册 用户登录和注册功能使用Spring Security框架实现。用户信息存储在数据库中,密码经过加密存储。 - 社团管理 社团管理功能使用SpringMVC框架实现。社团信息存储在数据库中,包括社团名称、社团介绍、社团成员等信息。用户可以创建、修改、删除社团。 - 活动管理 活动管理功能使用SpringMVC框架实现。活动信息存储在数据库中,包括活动名称、活动介绍、活动时间、活动地点等信息。用户可以创建、修改、删除活动。 - 成员管理 成员管理功能使用SpringMVC框架实现。成员信息存储在数据库中,包括成员姓名、成员学号等信息。用户可以加入、退出社团。 3.2 前端实现 前端使用Vue框架,实现了以下功能: - 用户登录和注册 使用Vue Router实现登录和注册页面的路由。用户输入用户名和密码后,使用axios发送请求到后端验证用户信息。 - 社团管理 使用Vue Router实现社团管理页面的路由。用户可以查看所有社团的信息,并且可以创建、修改、删除自己的社团。 - 活动管理 使用Vue Router实现活动管理页面的路由。用户可以查看所有活动的信息,并且可以创建、修改、删除自己的活动。 - 成员管理 使用Vue Router实现成员管理页面的路由。用户可以加入、退出社团。 4. 总结 本文介绍了如何利用SpringMVCVue实现前后端分离的大学生社团管理系统。该系统采用前后端分离的架构,实现了用户登录和注册、社团管理、活动管理和成员管理等功能。该系统可以作为大学生社团管理的参考实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ASHkenazi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值