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 业务功能 适用于商家在移动端网页应用中集成支付宝支付功能.商家 ...
随机推荐
- Acunetix引入了Docker支持,扫描统计信息以及将漏洞发送到AWS WAF的功能
已针对Windows,Linux和macOS发布了新的Acunetix更新:14.2.210503151. 此Acunetix更新引入了Docker支持,针对每次扫描显示的新"扫描统计信息& ...
- ESP32引脚参考(转)
ESP32芯片配有48个具有多种功能的引脚.并非所有的引脚都暴露在所有的ESP32开发板中,有些引脚不能使用. 关于如何使用ESP32 GPIO有很多问题.你应该用什么pin?在项目中应该避免使用哪 ...
- yum的卸载和安装
安装精髓:报错就查,少包就按. 一.如果yum没有注册则需要卸载再安装第三方yum 1.卸载redhat的默认安装yum包 [root@dsl ~]#rpm –qa | grep yum [root@ ...
- 从源码分析Hystrix工作机制
一.Hystrix解决了什么问题? 在复杂的分布式应用中有着许多的依赖,各个依赖都有难免在某个时刻失败,如果应用不隔离各个依赖,降低外部的风险,那容易拖垮整个应用. 举个电商场景中常见的例子,比如订单 ...
- C语言:赋值语句
赋值语句 1.赋值号:= 2.赋值号具有方向性,只能将右边的常数 变量的值 表达式的值赋值给左边的变量 3.赋值号左边只能是变量,不能是表达式.常数.符号常量.常量 如下列是非法的语句:a+b=3; ...
- python 读注册表 检测NET版本
from winreg import * import re def subRegKey(key, pattern, patchlist): # 个数 count = QueryInfoKey(key ...
- Rust安装-运行第一个程序-hello_world
Rust官网:https://rust-lang.org/ 安装 点击install,选择版本 选择相对应的版本进行下载 我这里下载的是windows系统,运行下载好的exe文件,根据需要选择选对应的 ...
- dataX windows10安装
按照视频课程,从Github上下载文件:https://github.com/alibaba/DataX 然后将下载的压缩包解压即可,不过需要的前提Python环境是要求python2,于是在pyth ...
- [刘阳Java]_MySQL数据优化总结_查询备忘录
数据库优化是在后端开发中必备技能,今天写一篇MySQL数据优化的总结,供大家看看 一.MySQL数据库优化分类 我们通过一个图片形式来看看数据优化一些策略问题 不难看出,优化有两条路可以选择:硬件与技 ...
- 无需kubectl!快速使用Prometheus监控Etcd
在本文中,我们将安装一个Etcd集群并使用Prometheus和Grafana配置监控,以上这些操作我们都通过Rancher进行. 我们将看到在不需要依赖的情况下充分利用Rancher的应用商店实现这 ...