手把手教你如何对接支付宝支付接口(奶爸级别)

news2025/1/25 4:30:19

支付宝支付接口

  • 步骤:
  • 第一步:
  • 第二步:
  • 如何让支付宝将付款成功的通知,回调到你本机,我使用的是内网穿透:Natapp

步骤:

第一步:准备支付宝相关的参数,如appId、公私钥

第二步:写代码,搞起

第一步:

1.你需要登录支付宝https://open.alipay.com/platform/developerIndex.htm。

2.点击控制台—>研发服务
在这里插入图片描述
3.到这个地址上生成一对公私钥:https://miniu.alipay.com/keytool/create

在这里插入图片描述
4.私钥保存下来,是要放在项目配置里面的,公钥是下面的步骤要用到的。
5.复制上面的公钥,放到这个输入框里面
在这里插入图片描述
6.保存设置后,打开就可以看到这样的窗口,下面的【敲黑板了!!!支付宝公钥】是放在代码里面的,自己保存下来。
在这里插入图片描述
7.点击左边的【沙箱账号】,把账号密码保存下来,支付的时候要用到。
在这里插入图片描述
8.到了这一步,咱们所需要的配置基本上就准备齐了

# 应用ID,您的APPID
alipay.appId=2021xxxx
# 支付宝公私钥生成地址:https://miniu.alipay.com/keytool/create
# 商户私钥,您的PKCS8格式RSA2私钥
alipay.merchantPrivateKey=第一次生成的私钥
# 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm
alipay.alipayPublicKey=支付宝公钥
# 页面跳转异步通知页面路径,需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
alipay.notifyUrl=http://5ktbak.natappfree.cc/payment/alipay
# 页面跳转同步通知页面路径,需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
alipay.returnUrl=http://5ktbak.natappfree.cc/alipayResult

# 签名方式
alipay.signType=RSA2
# 字符编码格式
alipay.charset=utf-8
# 支付宝网关
alipay.gatewayUrl=https://openapi.alipaydev.com/gateway.do

第二步:

alipay.properties

# 应用ID,您的APPID
alipay.appId=2021xxxx
# 支付宝公私钥生成地址:https://miniu.alipay.com/keytool/create
# 商户私钥,您的PKCS8格式RSA2私钥
alipay.merchantPrivateKey=第一次生成的私钥
# 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm
alipay.alipayPublicKey=支付宝公钥
# 页面跳转异步通知页面路径,需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
alipay.notifyUrl=http://5ktbak.natappfree.cc/payment/alipay
# 页面跳转同步通知页面路径,需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
alipay.returnUrl=http://5ktbak.natappfree.cc/alipayResult

# 签名方式
alipay.signType=RSA2
# 字符编码格式
alipay.charset=utf-8
# 支付宝网关
alipay.gatewayUrl=https://openapi.alipaydev.com/gateway.do

AliPayResource.java

package com.alipay.resource;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix="alipay")
@PropertySource("classpath:alipay.properties")
public class AliPayResource {

    private String appId;
    private String merchantPrivateKey;
    private String alipayPublicKey;

    private String notifyUrl;
    private String returnUrl;

    private String signType;
    private String charset;
    private String gatewayUrl;
}

AlipayController.java

package com.alipay.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.resource.AliPayResource;
import com.alipay.utils.DateUtil;
import com.alipay.utils.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author: HuGoldWater
 * @description:
 */
@Slf4j
@RestController
@RequestMapping("payment")
public class AlipayController {

    @Autowired
    private AliPayResource aliPayResource;

    /**
     * 前往支付宝进行支付
     */
    @GetMapping(value="/goAlipay")
    public JsonResult goAlipay(String merchantUserId, String merchantOrderId) throws Exception{
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayResource.getGatewayUrl(),
                aliPayResource.getAppId(),
                aliPayResource.getMerchantPrivateKey(),
                "json",
                aliPayResource.getCharset(),
                aliPayResource.getAlipayPublicKey(),
                aliPayResource.getSignType());

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(aliPayResource.getReturnUrl());
        alipayRequest.setNotifyUrl(aliPayResource.getNotifyUrl());

        // 商户订单号, 商户网站订单系统中唯一订单号, 必填
        String out_trade_no = merchantOrderId;
        // 付款金额, 必填 单位元
       String total_amount = "0.01";  // 测试用 1分钱
        // 订单名称, 必填
        String subject = "胡金水-付款用户[" + merchantUserId + "]";
        // 商品描述, 可空, 目前先用订单名称
        String body = subject;

        // 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
        String timeout_express = "1h";
        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"timeout_express\":\""+ timeout_express +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        //请求
        String alipayForm = "";
        try {
            alipayForm = alipayClient.pageExecute(alipayRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        log.info("支付宝支付 - 前往支付页面, alipayForm: \n{}", alipayForm);
        return JsonResult.ok(alipayForm);
    }


    /**
     * 支付成功后的支付宝异步通知
     */
    @RequestMapping(value="/alipay")
    public String alipay(HttpServletRequest request, HttpServletResponse response) throws Exception {

        log.info("支付成功后的支付宝异步通知");

        //获取支付宝POST过来反馈信息
        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 = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用
//       valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params,
                aliPayResource.getAlipayPublicKey(),
                aliPayResource.getCharset(),
                aliPayResource.getSignType()); //调用SDK验证签名

        if(signVerified) {//验证成功
            // 商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
            // 交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
            // 付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");

            if (trade_status.equals("TRADE_SUCCESS")){
//                String merchantReturnUrl = paymentOrderService.updateOrderPaid(out_trade_no, CurrencyUtils.getYuan2Fen(total_amount));
//                notifyFoodieShop(out_trade_no,merchantReturnUrl);
            }

            log.info("************* 支付成功(支付宝异步通知) - 时间: {} *************", DateUtil.getCurrentDateString(DateUtil.DATETIME_PATTERN));
            log.info("* 订单号: {}", out_trade_no);
            log.info("* 支付宝交易号: {}", trade_no);
            log.info("* 实付金额: {}", total_amount);
            log.info("* 交易状态: {}", trade_status);
            log.info("*****************************************************************************");

            return "success";
        }else {
            //验证失败
            log.info("验签失败, 时间: {}", DateUtil.getCurrentDateString(DateUtil.DATETIME_PATTERN));
            return "fail";
        }
    }

}

Application.java

package com.alipay;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
   public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
   }

}

运行Application,在页面输入localhost:9090/payment/goAlipay?merchantUserId=123456&merchantOrderId=654321
结果如下:

五月 08, 2021 11:30:51 下午 org.apache.catalina.core.ApplicationContext log
信息: Initializing Spring DispatcherServlet 'dispatcherServlet'
INFO  DispatcherServlet:525 - Initializing Servlet 'dispatcherServlet'
INFO  DispatcherServlet:547 - Completed initialization in 3 ms
INFO  AlipayController:80 - 支付宝支付 - 前往支付页面, alipayForm: 
<form name="punchout_form" method="post" action="https://openapi.alipaydev.com/gateway.do?charset=utf-8&method=alipay.trade.page.pay&sign=0G7TbOfYZn8BS1dYY%2FITfZLBHgz%2F0uBz3XU4ndiw%2Fpd%2BADurlNMtYNugvZpGTjrL4JBJb%2Fgzl6vG%2B9urFCbeLiVDXhnGMIvqzXOY67YVGIMfIDxR%2BOytOzZ3zctPeEVHDZBAjRNy4aOqW1elJ491Q%2BptPNT2X3vy8Qts0Ago1HaOyoCRlFag5nB3fwD5t3NQz4ZCEG8slwERixJnN2sIQLj4NGI2bM2T6x8ayDtehRC89hwXJ1ZY9IyLVkwhby%2BW4HU2LiQ%2BqD%2FOKLmxsC65M5pWNF7vw9uswmEuN5qBswJ5rqlTl6iyYd5EKK2Xqhj6hCQYz0IMR1cymRhqDoPG1Q%3D%3D&return_url=http%3A%2F%2F5ktbak.natappfree.cc%2FalipayResult&notify_url=http%3A%2F%2F5ktbak.natappfree.cc%2Fpayment%2Falipay&version=1.0&app_id=2021000117651511&sign_type=RSA2&timestamp=2021-05-08+23%3A30%3A51&alipay_sdk=alipay-sdk-java-3.7.110.ALL&format=json">
<input type="hidden" name="biz_content" value="{&quot;out_trade_no&quot;:&quot;654321&quot;,&quot;total_amount&quot;:&quot;0.01&quot;,&quot;subject&quot;:&quot;胡金水-付款用户[123456]&quot;,&quot;body&quot;:&quot;胡金水-付款用户[123456]&quot;,&quot;timeout_express&quot;:&quot;1h&quot;,&quot;product_code&quot;:&quot;FAST_INSTANT_TRADE_PAY&quot;}">
<input type="submit" value="立即支付" style="display:none" >
</form>
<script>document.forms[0].submit();</script>

把上面的html代码放到html文件中:

<form name="punchout_form" method="post" action="https://openapi.alipaydev.com/gateway.do?charset=utf-8&method=alipay.trade.page.pay&sign=0G7TbOfYZn8BS1dYY%2FITfZLBHgz%2F0uBz3XU4ndiw%2Fpd%2BADurlNMtYNugvZpGTjrL4JBJb%2Fgzl6vG%2B9urFCbeLiVDXhnGMIvqzXOY67YVGIMfIDxR%2BOytOzZ3zctPeEVHDZBAjRNy4aOqW1elJ491Q%2BptPNT2X3vy8Qts0Ago1HaOyoCRlFag5nB3fwD5t3NQz4ZCEG8slwERixJnN2sIQLj4NGI2bM2T6x8ayDtehRC89hwXJ1ZY9IyLVkwhby%2BW4HU2LiQ%2BqD%2FOKLmxsC65M5pWNF7vw9uswmEuN5qBswJ5rqlTl6iyYd5EKK2Xqhj6hCQYz0IMR1cymRhqDoPG1Q%3D%3D&return_url=http%3A%2F%2F5ktbak.natappfree.cc%2FalipayResult&notify_url=http%3A%2F%2F5ktbak.natappfree.cc%2Fpayment%2Falipay&version=1.0&app_id=2021000117651511&sign_type=RSA2&timestamp=2021-05-08+23%3A30%3A51&alipay_sdk=alipay-sdk-java-3.7.110.ALL&format=json">
    <input type="hidden" name="biz_content" value="{&quot;out_trade_no&quot;:&quot;654321&quot;,&quot;total_amount&quot;:&quot;0.01&quot;,&quot;subject&quot;:&quot;胡金水-付款用户[123456]&quot;,&quot;body&quot;:&quot;胡金水-付款用户[123456]&quot;,&quot;timeout_express&quot;:&quot;1h&quot;,&quot;product_code&quot;:&quot;FAST_INSTANT_TRADE_PAY&quot;}">
    <input type="submit" value="立即支付" style="display:none" >
</form>
<script>document.forms[0].submit();</script>

打开html文件后,会进入这个页面:
在这里插入图片描述
输入沙箱的账号密码:
在这里插入图片描述
在这里插入图片描述

输入密码后,就已经付款完成了,控制台会打印支付成功的回调通知。

INFO  AlipayController:91 - 支付成功后的支付宝异步通知
INFO  AlipayController:129 - ************* 支付成功(支付宝异步通知) - 时间: 2021-05-09 00:09:32 *************
INFO  AlipayController:130 - * 订单号: 123123123123
INFO  AlipayController:131 - * 支付宝交易号: 2021050922001489970501658602
INFO  AlipayController:132 - * 实付金额: 0.01
INFO  AlipayController:133 - * 交易状态: TRADE_SUCCESS
INFO  AlipayController:134 - *****************************************************************************

如何让支付宝将付款成功的通知,回调到你本机,我使用的是内网穿透:Natapp

首先,先到官网下载:https://natapp.cn/#download

然后,你会得到一个natapp_darwin_amd64_2_3_9.zip,解压之后,你会得到natapp(这个文件不能直接运行,需要通过命令去执行)【注意!!!!打开这个需要在(系统偏好设置 --> 安全性隐私 --> 通用)这里点击仍然打开】

最后,在natapp路径下执行命令:chmod 777 natapp、./natapp -authtoken=到官网免费申请【,authtoken申请是非常简单的】

最最后,就可以愉快的玩耍了,祝你玩得愉快!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/407825.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vite中静态资源(css、img、svg等)的加载机制及其相关配置

什么是静态资源&#xff1f; 简单来说&#xff0c;我们开发完一个项目后&#xff0c;需要把它打包&#xff08;一般是dist文件夹&#xff09;&#xff0c;并部署在服务器上。那么&#xff0c;这个打包后的dist文件夹都是静态资源&#xff1b;在我们写项目时&#xff0c;图片、…

JS类型转换

JS中的类型转换方式一般分为三类&#xff1a;转为String型&#xff0c;转为数字型&#xff0c;转为布尔型。 一.转为String型 1.toString() 通过变量.toString()可以将其他类型的变量转换为字符串型&#xff08;null和undefined没有toString()方法&#xff09; let age 18;…

如何运行vue项目

一、 1、下载node.js 安装完成后分别在cmd中执行node -v查看是否安装成功&#xff0c;出现版本号就安装成功了 2、安装 webpack npm install webpack -g 安装完成后分别在cmd中执行npm -v查看是否安装成功&#xff0c;出现版本号就安装成功了 3、安装vue-cli脚手架 cnpm i…

【vue3】使用canvas

canvas是什么&#xff1f; 一个html5支持的新标签&#xff0c;见名知意&#xff0c;canvas就是画板的意思&#xff0c;可以在canvas上画画。css画三角形很简单&#xff0c;但是要画五角星呢&#xff0c;不妨试试canvas。 在html中使用canvas 1、canvas是html5中的一个标签。…

前端之CSS

目录 一.CSS是什么 二.CSS的基本语法规范 三.CSS的引入方式 1.内部样式 2.内联样式 3.外部样式 四.CSS的基本用法 1.基础选择器 1.1 标签选择器 1.2 类选择器 1.3 id选择器 1.4 通配符选择器 2.复合选择器 2.1 后代选择器 2.2 子选择器 2.3 并集选择器 2.4 伪类…

【实战篇】最详细的Rollup打包项目教程

介绍 本文带你一起使用 Rollup 打包项目&#xff0c;实现以下功能&#xff1a; 自动将 dependencies 依赖声明为 externals支持处理外部 npm 依赖支持基于 CommonJS 模块引入支持 typescript&#xff0c;并导出声明文件支持 scss&#xff0c;并添加前缀支持自动清除调试代码打…

怒肝最新保姆级前端学习路线,速成贴心全面!

这份学习路线并不完美&#xff0c;也不会有最终形态&#xff0c;正如前端不可预见、永无止境的未来。 大家好&#xff0c;我是鱼皮&#xff0c;肝了几天终于完成了这份保姆级前端学习路线。 &#x1f482; &#x1f4bb; &#x1f474;&#x1f3fd; 先放一张图&#xff1a…

JS原型与原型链详细解释

文章目录一、JS原型链简要解释二、JS原型链详细解释1.构造函数2.原型对象3.__proto__4.原型链总结一、JS原型链简要解释 原型是function对象上的一个属性, 它表示构造函数构造出来的对象的共有祖先, 被通过构造函数构造出来的对象上有一个__proto__属性指向该函数的prototype,…

JSON.parse和JSON.stringify的用法

平时我们在接收后端返回的json对象通常是一个字符串类型的object&#xff0c;所以一般我们要对这个object进行类型转化后&#xff0c;我们才能使用object里面的数据&#xff0c;而这其中涉及到两个必不可少的方法就是JSON.parse和JSON.stringify JSON.parse()JSON.parse()方法将…

vue 控制元素的显示和隐藏

方法&#xff1a; 使用 v-if 指令&#xff0c;通过动态的向DOM树内添加或者删除DOM元素的方式来显示或隐藏元素&#xff1b;使用 v-show 指令&#xff0c;通过设置DOM元素的display样式属性来控制显隐。v-if 指令与 v-show 指令都可以根据值动态控制DOM元素显示隐藏&#xff0…

文档库开发之-vite打包优化

背景 首次进行组件库文档打包&#xff0c;遇到了一些ts打包报错和css打包警告&#xff0c;记录下处理过程。并且发现打包后的主包的体积过大&#xff0c;有一定优化空间 ts报错处理 当时有好奇为什么开发环境下都不报错&#xff0c;构建才产生这么多ts错误。大致猜想可能vite…

英雄联盟轮播图自动轮播

六月过去了&#xff0c;七月还会远吗&#xff1f;不知不觉到了六月底的最后一天。你好&#xff0c;七月&#xff01; 大家好&#xff0c;我是小陈陈呀&#xff0c;上次写了一篇英雄联盟轮播图手动轮播&#xff0c;当天晚上有很多大朋友小朋友私信小陈陈&#xff1a;可以在上次…

【微信小程序】一文读懂页面导航

&#x1f381;写在前面&#xff1a; 观众老爷们好呀&#xff0c;这里是前端小刘不怕牛牛频道&#xff0c;小程序系列又更新了呀&#xff0c;今天的内容是微信小程序的页面导航&#xff0c;非常重要&#xff0c;赶紧拿起小本本记起来呀&#xff01; 文章目录一&#xff0c;页面导…

【项目问题定位】前端请求不到资源报错ERR_CONTENT_LENGTH_MISMATCH的解决

文章目录问题简述问题背景问题定位初始报错定位好像是网络问题ERR_CONTENT_LENGTH_MISMATCH 200 是什么原因&#xff1f;原来是Nginx报错了为何没有权限&#xff1f;nobody的原因问题解决原因总结知识点问题简述 前端页面加载资源时&#xff0c;出现ERR_CONTENT_LENGTH_MISMAT…

前端异常:“Uncaught SyntaxError: missing ) after argument list“真的只是参数列表后面缺少 “)”?

案发现场 我们在写JS的时候&#xff0c;有时候报错"Uncaught SyntaxError: missing ) after argument list"&#xff0c;字面翻译过来的意思&#xff1a;语法错误: 参数列表后面缺少 )。 这真的就是缺少括号的意思吗&#xff1f;然而只是真的缺少括号才会出现这样的…

HTML的常见标签及用法

一、注释标签 形如&#xff1a;<!-- -->的格式就叫做注释标签&#xff0c;在代码中起到解释说明的作用。 二、标题标签 在HTML中有六种格式的标题标签类型&#xff0c;分别是h1,h2,h3,h4,h5,h6。对应的形式为&#xff1a; 三、段落标签 当文章需要分段时&#xff0c;使…

js除法取整(js除法向上取整)

Javascript取整问题。要求只要有小数存在就进一位。例如&#xff1a;2.1取3&#xff0c;3.1取4 var a 2.0; function parseNumber(number, splitChar) { var n number ; var s splitChar nullvar a 2.1; var b parseInt(a) 1; // b will be 3 parseInt是截掉尾数&#…

vxe-table表格合并单元格和编辑

//这是在vue上面引用vxe-table插件实现的&#xff0c;主要方法都设置在table中&#xff0c;mergeCells&#xff0c;tableData都是在vue页面的data初使化数据&#xff0c; :footer-method“footerMethod”&#xff1a;尾部数据&#xff0c;:merge-footer-items“mergeCells”&am…

vue通过url方式展示PDF方法总结

最近vue项目中遇到预览pdf出现乱码问题&#xff0c;尝试了各种办法受尽折磨&#xff0c;以此记录一下使用的几种方法 1.使用pdfjs-dist 插件&#xff0c;通过iframe标签显示 首先 npm install pdfjs-dist --save npm直接下载插件 npm install --save pdfjs-dist2.0.943&…

【vue 项目】有关cascader任选一级、字段名不同、同时获取value和label值、回显(推父节点)等问题解决

文章目录选择任意一级选项字段名转换最后一级数据为空显示暂无数据问题同时获取cascader的value和label值选择时双击两次才显示被选中&#xff08;单选选择任意一级组件&#xff09;Error in callback for watcher “options“: “TypeError: Cannot read property ‘level‘ o…