SpringBoot中实现支付宝支付
本文只介绍当面付(扫码支付)和APP支付
一. 接入准备
#这里分两种情况,正式环境和沙箱环境,本文使用沙箱环境
1.进入支付宝开放平台,创建应用
登录 支付宝开放平台,创建应用并提交审核,审核通过后会生成应用唯一标识 APPID,并且可以申请开通开放产品使用权限。通过 APPID 应用才能调用开放产品的接口能力。详情请参考 创建应用。
2.配置应用
应用创建完成后,系统会自动跳转到应用详情页面。您可以在 能力列表 中点击 添加能力 来添加 当面付 功能。详情请参见 添加应用功能。 添加需要的能力
3.开发设置
进入开发设置中完成接口加签方式、IP白名单、应用网关、接口内容加密方式开发信息设置。详情请参见 配置应用环境
- 接口加签方式:必填。用于保障商户应用和支付宝交互的安全性,配置详情参见 接口加签方式配置说明。
IP白名单:选填。用于保障用户资金安全,说明详情参见 IP 白名单接入指南。
应用网关:选填。用于接收支付宝异步通知消息,说明详情参见 应用网关。
接口内容加密方式:选填。用于加/解密 OpenAPI bizContent 报文内容及加/解密部分用户隐私信息,说明详情参见 接口内容加密方式。
授权回调地址:选填。第三方应用授权 或 用户信息授权 后回调地址。授权链接中配置的 redirect_uri 的值必须与此值保持一致 (如:https://www.alipay.com) ,用户成功授权后将在该 url 后携带授权码等信息并跳转至该页。当填入该地址时,系统会自动进行安全检测,详情请参考 安全检测。
4.设置接口加签方式
支付宝开放平台的应用管理体系,使用了公私钥的机制,商户可通过设置接口加签方式为自身应用配置 公私钥/公私钥证书 来保障商户应用和支付宝交互的安全性。密钥的获取方式请参见 生成密钥。
公钥证书与公钥的区别请参见 普通公钥与公钥证书区别。
简单说一下公钥私钥
使用支付宝支付加密方式有两种:1. 公钥私钥 2. 证书
1. 可使用支付宝提供的开发助手生成证书,生成后,支付宝会提供给你三个证书,分别为:私钥证书、公钥证书、支付宝公钥证书,
将生成的公钥证书配置到支付宝平台中,剩下的私钥证书和支付宝公钥留在本地使用
2. 同上使用支付宝开发助手生成密钥,将生成的公钥配置到支付宝,将支付宝公钥复制到本地。
密钥的作用:私钥签名,公钥验签;公钥加密,私钥解密;私钥是不能公开的。
为什么有两套密钥:开发者生成的私钥公钥、支付宝公钥-支付宝私钥;开发者需要签名,支付宝平台也需要签名。
其他步骤参照支付宝开放平台接入流程。
二. 编码阶段
1. 下载支付宝sdk
java使用maven引入即可
2.编码
封装配置类
1 @Data
2 @Configuration
3 @ConfigurationProperties(prefix = "alipay")
4 public class AliPayConfig implements Serializable {
5
6 private static final long serialVersionUID = -4736760736935998953L;
7
8 public AliPayConfig(){}
9
10 public AlipayClient build(){
11 if(this.alipayClient == null){
12 return new DefaultAlipayClient(this.getGatewayUrl(),
13 this.getAppId(),
14 this.getPrivateKey(),
15 this.getFormat(),
16 this.getCharset(),
17 this.getAliPublicKey(),
18 this.getSignType());
19 }
20 return this.alipayClient;
21 }
22
23 /**
24 * 支付宝网关
25 */
26 private String gatewayUrl;
27
28 /**
29 * 新版本
30 */
31 private String newGatewayUrl;
32
33 /**
34 * AppId
35 */
36 private String appId;
37
38 /**
39 * 应用私钥
40 */
41 private String privateKey;
42
43 /**
44 * 请求使用的编码格式,如utf-8,gbk,gb2312等
45 */
46 private String charset;
47
48 /**
49 * 仅支持JSON
50 */
51 private String format;
52
53 /**
54 * 支付宝公钥
55 */
56 private String aliPublicKey;
57
58 /**
59 * 加密方式 目前支持RSA2和RSA,推荐使用RSA2
60 */
61 private String signType;
62
63 /**
64 * 回调地址
65 */
66 private String notifyUrl;
67
68 /**
69 * ali 客户端
70 */
71 private AlipayClient alipayClient;
72
73 /**
74 * 获取Config配置类
75 * @return Config
76 */
77 public Config getConfig(){
78 Config config = new Config();
79 config.protocol = "https";
80 config.gatewayHost = this.getNewGatewayUrl();
81 config.signType = this.getSignType();
82 config.appId = this.getAppId();
83 config.merchantPrivateKey = this.getPrivateKey();
84 config.alipayPublicKey = this.getAliPublicKey();
85 config.notifyUrl = this.getNotifyUrl();
86 return config;
87 }
88 }
老版支付宝sdk
1 @Slf4j
2 public class AliPayApi {
3
4 /**
5 * 统一收单线下交易预创建 (老版本sdk)
6 * 扫码支付
7 * @param model
8 * @param aliPayConfig
9 * @return
10 */
11 public static AlipayTradePrecreateResponse tradePayToScanCode(AlipayTradePrecreateModel model, AliPayConfig aliPayConfig){
12 log.info("扫码支付:"+model.getOutTradeNo());
13 // 1.实例化API对应的request类
14 AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
15 request.setBizModel(model);
16 // 2.发起请求
17 AlipayTradePrecreateResponse response = null;
18 try {
19 response = aliPayConfig.getAlipayClient().execute(request);
20 // 3.是否调用成功
21 if(response.isSuccess()){
22 log.info("扫码支付调用成功:" + response.getBody());
23 return response;
24 }
25 } catch (AlipayApiException e) {
26 log.info("扫码支付调用失败:" + e.getErrMsg());
27 throw new RuntimeException(e);
28 }
29 log.debug("扫码支付调用失败:" + response.getMsg());
30 return null;
31 }
32 }
新版支付宝sdk
1 /**
2 * 支付宝支付 新版sdk
3 * Create by Echo<php637.com> on 2021/1/22 0022
4 */
5 @Slf4j
6 public class AliPayNewApi {
7
8 /**
9 * 统一收单线下交易预创建
10 * 扫码支付
11 * @param model
12 * @param aliPayProperties
13 * @return
14 */
15 public static AlipayTradePrecreateResponse tradePayToScanCode(AlipayTradePrecreateModel model, AliPayConfig aliPayProperties){
16 log.info("扫码支付:" + model.getOutTradeNo());
17 // 1. 设置参数
18 Factory.setOptions(aliPayProperties.getConfig());
19 AlipayTradePrecreateResponse response = null;
20 try{
21 // 2. 发起Api调用
22 response = Factory.Payment.FaceToFace().preCreate(model.getSubject(), model.getOutTradeNo(), model.getTotalAmount());
23 dumpResponse(response);
24 // 3. 处理响应
25 if(ResponseChecker.success(response)){
26 log.info("扫码支付调用成功:" + response.getHttpBody());
27 return response;
28 }
29 } catch (Exception e) {
30 log.debug("扫码支付调用异常:" + e.getMessage());
31 throw new RuntimeException(e);
32 }
33 log.debug("扫码支付调用失败:" + response.getMsg());
34 return null;
35 }
36
37 /**
38 * App支付
39 * @param model
40 * @param aliPayConfig
41 * @return
42 */
43 public static AlipayTradeAppPayResponse tradePayToApp(AlipayTradeAppPayModel model, AliPayConfig aliPayConfig){
44 log.info("支付宝app支付:" + model.getOutTradeNo());
45 // 1. 设置参数
46 Factory.setOptions(aliPayConfig.getConfig());
47 AlipayTradeAppPayResponse response = null;
48 try{
49 // 2. 发起Api调用
50 response = Factory.Payment.App().pay(model.getSubject(), model.getOutTradeNo(), model.getTotalAmount());
51 // 3. 处理响应
52 if (ResponseChecker.success(response)){
53 return response;
54 }
55 } catch (Exception e) {
56 log.debug("支付宝app支付调用异常:" + e.getMessage());
57 throw new RuntimeException(e);
58 }
59 log.debug("支付宝app支付调用失败:" + response.getBody());
60 return null;
61 }
62
63 // 简单打印应答
64 private static void dumpResponse(AlipayTradePrecreateResponse response) {
65 if (response != null) {
66 log.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
67 if (StringUtils.isNotEmpty(response.getSubCode())) {
68 log.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
69 response.getSubMsg()));
70 }
71 log.info("body:" + response.getHttpBody());
72 }
73 }
74 }
测试和回调
1 @Autowired
2 private AliPayConfig aliPayProperties;
3
4 @Autowired
5 private SmsUtils smsUtils;
6
7 /**
8 * 扫码支付测试 老版本
9 * @return
10 */
11 @RequestMapping("/test1")
12 public Object test1(){
13 AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
14 model.setOutTradeNo("123456789");
15 model.setSubject("测试商品");
16 model.setTotalAmount("20");
17 System.out.println(AliPayApi.tradePayToScanCode(model, aliPayProperties));
18 return new Return().success();
19 }
20
21 /**
22 * 扫码支付测试 新版本
23 * @return
24 */
25 @RequestMapping("/test2")
26 public Object test2(){
27 AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
28 model.setOutTradeNo("12341234");
29 model.setSubject("新版支付");
30 model.setTotalAmount("10");
31 System.out.println(AliPayNewApi.tradePayToScanCode(model, aliPayProperties));
32 return new Return().success();
33 }
34
35 /**
36 * app支付测试 新版本
37 * @return
38 */
39 @RequestMapping("/test3")
40 public Object test3(){
41 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
42 model.setOutTradeNo("123412314");
43 model.setSubject("新版app支付");
44 model.setTotalAmount("10");
45 return new Return().success(AliPayNewApi.tradePayToApp(model, aliPayProperties));
46 }
47
48 /**
49 * 回调
50 * @param request
51 * @return
52 */
53 @RequestMapping("/notify")
54 public Object alinNotify(HttpServletRequest request){
55 // 1.获取回调参数
56 Map<String, String> params = new HashMap<>();
57 Map requestParams = request.getParameterMap();
58 for (Iterator iterable = requestParams.keySet().iterator(); iterable.hasNext();){
59 String name = (String) iterable.next();
60 String[] values = (String[]) requestParams.get(name);
61 StringBuffer valueStr = new StringBuffer();
62 for (int i = 0; i < values.length; i++){
63 if(i == values.length - 1){
64 valueStr.append(values[i]);
65 }else{
66 valueStr.append(values[i]);
67 valueStr.append(",");
68 }
69 params.put(name, valueStr.toString());
70 }
71 }
72 log.info("支付宝回调,sign:{},trade_status:{},参数:{}",params.get("sign"),params.get("trade_status"),params.toString());
73 // 2.验签
74 params.remove("sign");
75 params.remove("sign_type");
76 try {
77 boolean checkRes = AlipaySignature.rsaCheckV1(params, aliPayProperties.getAliPublicKey(), aliPayProperties.getCharset(), aliPayProperties.getSignType());
78 if (!checkRes){
79 return new Return().failed("非法请求,验证失败");
80 }
81 } catch (AlipayApiException e) {
82 log.debug("支付宝验签异常:{}", e.getErrMsg());
83 }
84 // 3.服务端订单参数验证及其他逻辑
85 // TODO
86 return "SUCCESS";
87 }
SpringBoot中实现支付宝支付的更多相关文章
- iOS中 最新支付宝支付(AliPay) 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 现在的支付方式一般有三种, 支付宝, 微信, 网银. 个人觉得最简单易用的还是支付宝, 微信虽然看起来币支付宝要简单 ...
- 在django中实现支付宝支付(支付宝接口调用)
支付宝支付 正式环境:用营业执照,申请商户号,appid 测试环境:沙箱环境:https://openhome.alipay.com/platform/appDaily.htm?tab=info 支付 ...
- 微信公众号中的支付宝支付与微信支付 && 支付宝支付问题(微信bug)
一般,在微信公众号中的商城都是需要支持微信支付和支付宝支付的,当然,较大的公司对于鹅厂和阿里的站队就不说了,所以这里简单记录一下支付宝支付和微信支付的主要流程.说是简单介绍,这是因为确实不难,因为前端 ...
- 【zhifu】web开发中的支付宝支付和微信支付
一.支付类型: 支付宝支付: 支付宝app内的网页支付: app外(即普通浏览器)网页支付: 微信支付: 微信app内的支付(在这里叫公众号支付) app外的支付(微信H5支付): 微信公众号的支付宝 ...
- TP5 中实现支付宝支付 利用model层调用支付宝类库
<?php /** * Created by PhpStorm. * User: admin * Date: 2017/8/16 * Time: 09:16 */ namespace app\a ...
- springboot项目对接支付宝支付
支付宝对接文档 一.准备工作 1. 首先要到 蚂蚁金服开发者中心 https://openhome.alipay.com/platform/home.htm 注册商家账户,并认证. 2.下载java版 ...
- web开发中的支付宝支付和微信支付
https://www.jianshu.com/p/155757d2b9eb <!-- wxPay --SDK--> <script src="https://res.wx ...
- iOS开发笔记14:微博/微信登录与分享、微信/支付宝支付
产品中接入了微博/微信的第三方登录分享功能.微信和支付宝的第三方支付功能,之前在开发过程中涉及到这些部分,于是抽空将接入过程梳理了一遍. 1.微博.微信.支付宝SDK相关接入设置 (1)微博SDK S ...
- laravel实现支付宝支付功能
起因 前段时间因为项目中需要实现支付宝手机网站支付功能,所以写下这篇文章以作记录,不足之处,欢迎指教. 后端框架:Laravel 5.5 业务功能 适用于商家在移动端网页应用中集成支付宝支付功能.商家 ...
随机推荐
- docker安装应用整理
nginx安装: docker run \ --name nginx \ --volume /var/data/nginx/nginx.conf:/etc/nginx/nginx.conf \ --v ...
- STM32笔记四
1.时钟振荡器:产生时钟信号送给单片机内部各电路,并且控制这些电路,使它们有节拍的工作. 2.ROM是一种具有存储功能的电路,断电后信息不回丢失.RAM也是一种存储电路,断电后信息丢失. 3.串行通信 ...
- 【重学Java】多线程基础(三种创建方式,线程安全,生产者消费者)
实现多线程 简单了解多线程[理解] 是指从软件或者硬件上实现多个线程并发执行的技术. 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能. 并发和并行[理解] 并行:在同一时刻, ...
- FreeRTOS+LVGL|Freertos+lvgl如何配置lvgl的心跳和任务管理器
目录 配置lvgl心跳(Tick) 配置lvgl任务管理器(Task Handler) LVGL中文手册 lvgl需要系统滴答声(心跳)才能知道动画和其他任务的经过时间,所以我们必须要配置好lvgl的 ...
- .Net Core微服务——服务发现:Consul(一)
先思考一些问题:它是做什么的.以及怎么使用它.带着这些问题往下走. consul是做什么的 consul用于微服务下的服务治理.服务治理是什么?它包含但不限于:服务发现.服务配置.健康检查.键值存储. ...
- python使用笔记23--面向对象编程
1.面向对象编程概念 面向对象是包含面向过程 面向过程编程 买车: 1.4s看车,买车 2.上保险 保险公司 3.交税 地税局 4.交管所 上牌 面向对象编程 卖车处: 1.4s 2.保险 3.交税 ...
- python 按行查找文本文件,找出答案,并提示置顶答案
1.整理好答案文件为文本文件:不能有空行:每个题干前有数字做为题号:每个题答案第一个字符为字母,答案占一行import time import time import sys import os im ...
- C语言变量 类型判断
变量三要素: 一个变量有三个基本的要素,变量的名称,变量的类型,变量的值.所以int a = 10; 变量名为a,变量的存储类型为int型,变量的值为10. 变量还有一些属性如作用范围和存储类型. 变 ...
- SLAM的数学基础(4):先验概率、后验概率、贝叶斯准则
假设有事件A和事件B,可以同时发生但不是完全同时发生,如以下韦恩图所示: 其中,A∩B表示A和B的并集,即A和B同时发生的概率. 如此,我们很容易得出,在事件B发生的情况下,事件A发生的概率为: 这个 ...
- Leetcode:面试题55 - II. 平衡二叉树
Leetcode:面试题55 - II. 平衡二叉树 Leetcode:面试题55 - II. 平衡二叉树 Talk is cheap . Show me the code . /** * Defin ...