支付宝支付整体流程,包括验签【同步】【异步】

2023-11-14

一、前期准备

1、支付宝开放平台沙箱账号,用于测试

在这里插入图片描述
应用公钥需要使用支付宝第三方工具生成,最好在本地备份好,公钥以及配对的密钥

在这里插入图片描述

2、javasdk的maven仓库

javasdk

3、内网穿透,使内网能够被 支付宝的服务器访问

支付成功后支付宝需要回调咱们服务器的端口,必须保证自己的服务器能被外网访问
穿透教程

二、流程图

主要流程:

  1. 用户下单请求商户系统
  2. 商户系统构造支付请求,发送给支付宝
  3. 支付宝展示支付信息,用户支付
  4. 支付结果由支付宝回调给商户创建好的接口
  5. 商户根据支付结果业务操作,并在最后将订单信息返回给用户

在这里插入图片描述

三、代码编写

1、依赖导入
springboot thymeleaf alipa-sdk-java

![在这里插入图片描述](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2p3LXN0YXIvbXlGaWd1cmViZWQvbWFzdGVyL2ltZy8yMDE5MTIxMTE0NDc1OS5wbmc?x-oss-process=image/format,png)

2、创建请求公共参数的类 AlipayConfig


public class AlipayConfig {
    // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,开发时使用沙箱提供的APPID,生产环境改成自己的APPID
    public static String APP_ID = "2016101600700789";  //沙箱的
    //public static String APP_ID = "2019120669659570";
    // 商户私钥,您的PKCS8格式RSA2私钥
    public static String APP_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCFOj7P1DzSVD2j/DxZrLg3i9siUn47m6xL2yaZZprDNb3UjyNEt31B/q4hdhZ7StJVBx9AEfSsceXzOizbRJgdAboR6XSz66bE9pI3k/Ef2TmSc4v+cEysCKF/Mg4t8Y+uCWpOak+r/K4ZNBla2u45gU1vPcvOzf/uvJiTXmSYbBndKUMCICkF0RbHLOjhMFN8a0Nu0IiCSuGFl8iMSnL9czKnGWT6k5luwHsvxh0ei+lW2V9NZyP56reSylhO8RmOihsDKep7Y4JdNRyGNGzjkiaqGKzbcGU2a/Zx9ztSmo7tzOLVK3eDZEiOX4nBqa0HqczpYEg7S+kYwkIAXT7nAgMBAAECggEANufPNRWRz1i6Ype0Q3zEGtg/gkCfF2/LrSNvH+9CPssqJayr60j3jTgpiU7CayNl1Xbu8Re1T1BNZVUHYYI+ck3g4jrlRrUKcMfxcIg+6lI6wNlvy3d6kbeo3uPBJjwUa7QjpJd5qDalhWuMO35YiUh5oivEj8EkBb6h3rIbIRlrrsjFXN60RJXbQlulj6Cm1xNvzehhr34pSIrEZr1wbyy0bRq/YOpZ0XhnCrpWktZoIXirIQ3DUNu2NQ9PSUoJAaEYdk3DkKc+r+ARM99U1ZLRii1WWDDECZXmf66lKtPun09+obUe8Ly34+7DUsg0xZhpXcBWg0wR/WeWX7vz8QKBgQC+rB2ZsJGfoL4SkMtXJw7atG+ZiGQEILkoBH+CVhgj6ZYdEIy6Dc4NS7o5n/Am14hGmbCdMYSJZkCsypmDjhX7sDzeHQUl0E06aSN0qyotLzWuIDfl90SJL42/lyX4CniBFWJFXv6nPOQmR6JEDB07FjN1/gOgrZSrXagr2ookyQKBgQCy36Q0QVa3sZUFyKbH3VmlN9f1wHiO9crtrP94VAkpbvCCWof2O7z2az9F2EZmhwpbK1PhAFx0IHlSqvH6HuWT89Xi0DCPfbALbuQyaQoIm6K0QvPyVb1SNW0W9tMTGVZtUXaHpmwL+w5qoK6zojLGYMOzs31yblizniPhNVGOLwKBgDmFfQyPeu8YNB8vtVhefRm3k29S+TFRmeobqUftpyy2XEX6Zyn93iqerNiTioR9QyxhUymo9Z3pzhsSp8tLQxCB82rigFoPBC1Z6Ita08d71YrpR1PGC9QDF5U0CQ1SQ1ZV2CaraNGVChMOS0KSEQNxSCcRcZC4rQAhqglIzaIZAoGAJEacu4hAuPJHwauGv2PRqWMg5hMJoByS8g6ypMmOLhv0pMsNZc+JrAPmChkpdeOPIxwvX6M+HML1N+G5PzuC3bWGu//yyTb5O+haWSraQRKnNZ2acZwX0BNLs2uNNQNfdr4dprcGlItuygsaQw3y9C5togUVvN5KGOtKZYL1rjsCgYEAtNwjD9q963DUKDpoAZFCZClCtd8cxUsv8yPAZndWpgujtkOblYn8tQvxx/9yWPJC8NUahnMLrPI36YgAwB5Gs0csU0p2s80otTk3++oInrzTxCYuNlF+HT1RKzJ+JDOxVjJpBu91DJ4OnIhfDIPG8GGr+mtf2bg0sidz7HoL6ng=";
   // public static String APP_PRIVATE_KEY ="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCai3umtojYHJNn3ZbvUivIarG8kGHzWoGbJkuB8Ppo4nKhBmDHXCeO712jrEx4frQMUpoOx85NTmrZS8w96b3JDyt10KYEFNhm/W5CoNcxqAy8tDExiQRlxEoU0rSLNrTzgIRgfZW+uRC34T270itjh59St6U/9fd6y0oThV+PPRcKuZMZg8Qv3LKHYdHxwMyaoo+GT15N76/WYxSOZy4c7njaDo5C62okFdwHK8TzeTJ9y+OqeSuW/YevLxSfnTt1yOtQiIfx2oOOBsFqsqQ+uNvCSpDMl6r8F9LyeVm5lvxGTrzdz+odmyRGUkIfxVZAeSoqrwUSXsmceLvdurcjAgMBAAECggEASY/ZNLqwGoZHl+n+/T2Uv5ohrgrfxPEwvgQVbu2glCotu/4INPzli4Dehpjt8XEGDNOIpz5uMZgA/hu5RUMsZjbFThgZ3dl6RFOflzFuHSHLpkrzG4wHvtUXGiBNdfJ9YWasHC3LCHSYw54AP5XDt2WH7dyiWPagbR+0y+PxX4FMRiVVpjqloRKQqSW/gV+Y1ka8nHvUgU0IyJbi9ZZGbjEz409hWmTExmCuVwCdV/Tdq5q1PDiQHOtkgSf6UVCjMB4Ey5Y1Zn2E9/l7h2fDvZgYXCIwkFnPyNf+3cMnydvS22bks1M9PFp33bPVrV1F3DVltY9d7o8AXxqnFSlp0QKBgQDJbMA+AmpAvn2fUSptVwth39srxFuIY2Cqwx7jApLBeMlfqfw5aY7B6jbMhoIRtKVCy3b6KR7URT9sVqFYrKG2er99WARmHRnMh5vNxQBzrq+hqz5v5WxH9xjh4mHKSPBx4ti6ODGiQjv+wugntpBif45wHubgTUlaowp3uDT4mwKBgQDEawoukIcpMNFigTpmPp+R033xZAz9CyJCVuX8vfgfTMHsQNfngh5FNtCWMpIcrVei6cvCWD+cJqeVuV6LEbUxvqK+OY1bNoZnhnN1K6OjcyziYK//TSf0lHzBy7Uiy3l06youlRt/in3LualY3EDdtx/fUe4Lj244Nj2Cm3pQGQKBgQCiZFg1ZjMN0cZr/L8s+gGGPjlwdtWpBx33bmpncTqqWtxXkS91hiH/OvpFOKiC59ZZHLrmguKFFvNEQC/C0yNpgFsEDkM1pH6ZRDeb1RlBKvQUboBfLGN5PcFE1AQtV1LrLo22zPlPLQE7qx4KbojHsLlAsdlHu2fJeCtHTC8AwwKBgAWnBu38HseirgPlsCaNGs55haBSvsTxcxTxp0C0vtU3wkToQM5awkA/qZUI84d7vY/kpoZ7P6lgu2XlpcDey5YY5FoREe5UDV4hUmVG0ji78ci5+5afQ80YENcK47WSoXYp5lbc16O9+ozIVQVHoV5ADNzCYNVYVVWsyexeSRDRAoGBAJEa+g3rfVEKDzCXA+EgkTDphwEJyVH2csV9cGFLUnPv7fJgsTCj1QSE6PYHddCChKDBuJ5Yw1VhmqBch3Y4bcyV36hybO+vqzUP3AW1LVeu/NAhd3qRULoaiG5dhKJ28RWMZWr7IP1+xA58y/TbUpHdBhvOmvzopiXKe0SgWeSc";

    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public static String ALIPAY_PUBLIC_KEY="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkE5K/L+l166zCpgLZ5EQRf9f32lNII8xtIJzTiBJaRgYAb2HnW3ZAEnpLNeWl8s5PxWsa6tNtqlrjSG8smNHDmbgF9pF1pLjhbCoe1tMizeuUvX6wypnPH3k2dM5Z4ffyLyvXw8rqO28CUegNLnDtc7U6dq5YhSlntTph3DB5EKL6iNSCs8PtblKwAA108I5beV8lvV75QkkXMU1jdpbA013swBAptyLxTsb/NoUB4eUmjr+uwrhavHoWbolFID2v9MuZ0GYb7TpiBEQSns+VaHi7pJpYXsL+bwSoteKAD+cG2vH8NI5HggMn3eXH6hOFtZ5jsm4NOZ0WgKOjo38UwIDAQAB";
    //public static String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhvCnEvUMjsa7N1CybrtIdMY74o1JVyspZqv5Q5yj/8uyaE5LSG+7hFhQZpkJgHFNdKJsICfEKpK95MoKAm9uOV4+p7R7i7FMjVKh8yX6bf4auQXQLa3KeTJ/GSQpw1Z+5cSivyzBb2v+d4dt9MgJj04j6cCo2g9wjYsQ/wpRn/BMdDtA7nUaKfa15gJLz4q/1MYlIjALjnMeXIJXqZdDvBLuQ3JMEAgv6jfFxbU6U71L6ayA1OFdc1RFUrz4SXryOk9Ogoz77/DWCF4fcCZenx/zsBhTUXbl5GDy6/KFeMoU2WkVhFC9N/kG5aAiUTihjHQI3w3APAGAbJZkFJg/iwIDAQAB";

    // 异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    public static String notify_url = "http://gojw.xyz/notify";

    // 同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问(其实就是支付成功后返回的页面)
    public static String return_url = "http://gojw.xyz/return";

    // 签名方式
    public static String sign_type = "RSA2";

    // 字符编码格式
    public static String CHARSET = "utf-8";

    // 支付宝网关,
    public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

    // 日志输出地方
    public static String log_path = "C:\\";


//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

    /**
     * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
     * @param sWord 要写入日志里的文本内容
     */
    public static void logResult(String sWord) {
        FileWriter writer = null;
        try {
            writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis()+".txt");
            writer.write(sWord);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3、支付控制层PayController


@Controller
public class PayController {
    //获得初始化的AlipayClient
    AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);
    @RequestMapping("/pay")
    @ResponseBody
    public String payController(String WIDout_trade_no,String WIDsubject,String WIDtotal_amount,String WIDbody) {//创建支付请求
        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
        //商户订单号,商户网站订单系统中唯一订单号,必填
        String out_trade_no = WIDout_trade_no;
        //付款金额,必填
        String total_amount =WIDtotal_amount;
        //订单名称,必填
        String subject = WIDsubject;
        //商品描述,可空
        String body = WIDbody;

        alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                + "\"total_amount\":\"" + total_amount + "\","
                + "\"subject\":\"" + subject + "\","
                + "\"body\":\"" + body + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        //请求
        String form = "";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return  form;

    }
    @ResponseBody
    @RequestMapping("/dingdanLook")
    public String dingdanChaxun(){//查看订单信息
        //设置请求参数
        AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
        alipayTradeQueryRequest.setBizContent("{" +
                "    \"out_trade_no\":\"201503s240440010101002\"  " +//商户订单号
                "}"  );
        String body="";
        try {
            body = alipayClient.execute(alipayTradeQueryRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return body;
    }
    @ResponseBody
    @PostMapping("/notify")                   //异步验签接口
    public String notifyer(HttpServletRequest request) throws AlipayApiException {
        boolean b = mysignVerified(request);
        if (b){
        System.out.println("异步验签成功");
        //修改数据库订单状态
        return "success";
    }else {
        System.out.println("异步验签失败");
        return "failure";
    }
}
    @GetMapping(value = "/return")            //同步验签接口
    public String returner(HttpServletRequest request) throws AlipayApiException {
        boolean b = mysignVerified(request);
        if (b){
            System.out.println("同步验签成功-跳转到成功后页面");
            //修改数据库订单状态
            return "/success";
        }else {
            System.out.println("同步验签失败-跳转到充值页面让用户重新充值");
            return "/error";
        }
    }
    /*
    *   验签方法
    * */
    public boolean mysignVerified(HttpServletRequest request) throws AlipayApiException {
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }
        //String out_trade_no = request.getParameter("out_trade_no");// 商户订单号
        return AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.sign_type); //调用SDK验证签名
    }


    @RequestMapping("/")
    public String toTest(){
        return "index";
    }
}

4、前台页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/pay" method="post">
    订单号:<input type="text" name="WIDout_trade_no" required><br/>
    订单名称:<input type="text" name="WIDsubject" required><br/>
    付款金额:<input type="text" name="WIDtotal_amount" required><br/>
    WIDbody:<input type="text" name="WIDbody"><br/>
    <input type="submit" value="下单"> <input type="reset" value="重置">
</form>
</body>
</html>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

支付宝支付整体流程,包括验签【同步】【异步】 的相关文章

随机推荐

  • Docker-容器

    容器 容器的状态用 docker contaier ls 启动容器 启动一个容器的终端 并允许交互 docker run it ubuntu 16 04 bin bash 当利用 docker run 来创建容器时 Docker 在后台运行
  • uvm message printing mechnism

    原文链接 http www sunburst design com papers CummingsSNUG2014AUS UVM Messages pdf 本文主要介绍了如何控制消息打印的等级 以及禁止消息打印等
  • 使用nginx+uwsgi+flask实现python服务的负载均衡---(2)uwsgi的安装

    0 安装uwsgi 转自官网 使用pip install uwsgi就可以 当然了也可以下载源码自己make 1 配置uwsgi uwsgi 有多种配置可用 1 ini 2 xml 3 json 4 yaml 这里我使用的ini 当然也可以
  • selenium-server-standalone selenium-server 和 selenium-java 的区别

    selenium1 0还是 seleniumRC的时候 需要启动selenium server standalone包 用来做server selenium RC通过server来给code和broswer建立通道 同时 该jar包包括我们
  • BATJ面试必会之Java IO 篇

    一 概览 二 磁盘操作 三 字节操作 实现文件复制 装饰者模式 四 字符操作 编码与解码 String 的编码方式 Reader 与 Writer 实现逐行输出文本文件的内容 五 对象操作 序列化 Serializable transien
  • DDL和DML常用语句总结

    DDL语句 常用来操作数据库 数据库表 用到的语句 create show alter drop 1 操作数据库 CRUD 1 C Create 创建 创建数据库 create database 数据库名称 创建数据库 判断不存在 再创建
  • 前端页面性能优化 - 字体加载优化

    相比于英文的字库来说 中文字库的体积非常之大 小则1M 动辄几十 M 的体积非常常见 所以在前端页面性能优化中 字体加载的优化就显得尤为重要 阅读了相关的知识和文章 在研究了市面上字体加载方案之后 我总结出了目前可行的方案 1 font s
  • 实对称矩阵的特征值求法_机器学习与线性代数 - 特殊矩阵

    在线性代数中 有一些特殊的矩阵具有易于分析和操作的特性 它们的特征向量可能具有特定的特征值或特殊关系 还有一些方法可以将一个矩阵分解成这些 更简单 的矩阵 操作复杂性的降低提高了可伸缩性 然而 即使这些矩阵都是特殊的 它们也不是罕见的 在机
  • linux创建文件软连接和硬链接详解

    前言 linux系统中链接文件仔细区分可以分为软连接 符号链接 和硬链接 软链接比硬链接应用更广泛 所以也可以认为linux链接文件就是指软链接文件 本文将会在第2部分介绍创建软链接和硬链接的基本命令 在第3部分从linux文件系统的角度出
  • 联合体union在立体几何中的妙用

    联合体union在立体几何中的妙用 为了更好地理解三维游戏编程 我开始研究了立体几何 注意 是立体解析几何 里面涉及到了很多元组 向量和矩阵的知识 虽然还有
  • 编写一个密码类,其中包含一个 str 密码字符串私有成员数据,一个“==”运算 符重载成员函数,用于比较用户输入的密码是否正确。并用数据测试该类。

    define CRT SECURE NO WARNINGS 编写一个密码类 其中包含一个 str 密码字符串私有成员数据 一个 运算 符重载成员函数 用于比较用户输入的密码是否正确 并用数据测试该类 include
  • [Python人工智能] 七.加速神经网络、激励函数和过拟合

    从本系列文章开始 作者正式开始研究Python深度学习 神经网络及人工智能相关知识 前六篇文章讲解了神经网络基础概念 Theano库的安装过程及基础用法 theano实现回归神经网络 theano实现分类神经网络 theano正规化处理 这
  • PTA L1-058 6翻了(详解)

    前言 内容包括 题目 代码实现 大致思路 代码解读 题目 666 是一种网络用语 大概是表示某人很厉害 我们很佩服的意思 最近又衍生出另一个数字 9 意思是 6翻了 实在太厉害的意思 如果你以为这就是厉害的最高境界 那就错啦 目前的最高境界
  • 【运维知识基础篇】Linux定时任务

    今天给大家介绍下linux定时任务 定时任务无非就是在什么时间干什么命令 首先大家要知道文件怎么配置 定时任务一般用root执行 这里介绍crond crontab crontab e 用户定时任务 var spool cron root
  • 2021-06-18 mysql8.0数据库常用操作语句总结

    net start mysql启动MySQL的服务了 net stop mysql停止服务 sc delete MySQL mysqld remove卸载 MySQL 服务 创建新用户 CREATE USER 用户名 host名称 IDEN
  • STL中迭代器的问题

    STL中的容器迭代器 在容器的学习过程中 使用迭代器跳转插入 做了个简单测试 void test 指定位置插入 index使用迭代器 list
  • c++中如何只保留float型的小数点后两位

    float spd 22 518744 char buf 10 sprintf buf 2f spd sscanf buf f spd 记录一下 有时候我们需要float类型只保留两个有效小数 但是在实际应用中会发现一些现象 如 1 5 在
  • 这个 17 岁的黑客天才,破解了第一代 iPhone!

    关注 星标公众号 直达精彩内容 时间来到2007年 第一代的ipone问世惊艳了世人 重新定义了智能手机 但第一代的iPhone也有让人恼火的地方 当时的iPhone和AT T 当时美国最大的移动运营商 签了五年的独家运营协议 使得网络只局
  • redmine Email delivery error: Net::ReadTimeout

    好吧 创建一个redmine 在配置邮件的时候sendmail 可以通过 smtp 25端口可以通过 但使用SSL465 端口说什么也过不去 报错Email delivery error Net ReadTimeout 找样例找不到 有关于
  • 支付宝支付整体流程,包括验签【同步】【异步】

    一 前期准备 1 支付宝开放平台沙箱账号 用于测试 应用公钥需要使用支付宝第三方工具生成 最好在本地备份好 公钥以及配对的密钥 2 javasdk的maven仓库 javasdk 3 内网穿透 使内网能够被 支付宝的服务器访问 支付成功后支