本文只介绍当面付(扫码支付)和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中实现支付宝支付的更多相关文章

  1. iOS中 最新支付宝支付(AliPay) 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 现在的支付方式一般有三种, 支付宝, 微信, 网银. 个人觉得最简单易用的还是支付宝, 微信虽然看起来币支付宝要简单 ...

  2. 在django中实现支付宝支付(支付宝接口调用)

    支付宝支付 正式环境:用营业执照,申请商户号,appid 测试环境:沙箱环境:https://openhome.alipay.com/platform/appDaily.htm?tab=info 支付 ...

  3. 微信公众号中的支付宝支付与微信支付 && 支付宝支付问题(微信bug)

    一般,在微信公众号中的商城都是需要支持微信支付和支付宝支付的,当然,较大的公司对于鹅厂和阿里的站队就不说了,所以这里简单记录一下支付宝支付和微信支付的主要流程.说是简单介绍,这是因为确实不难,因为前端 ...

  4. 【zhifu】web开发中的支付宝支付和微信支付

    一.支付类型: 支付宝支付: 支付宝app内的网页支付: app外(即普通浏览器)网页支付: 微信支付: 微信app内的支付(在这里叫公众号支付) app外的支付(微信H5支付): 微信公众号的支付宝 ...

  5. TP5 中实现支付宝支付 利用model层调用支付宝类库

    <?php /** * Created by PhpStorm. * User: admin * Date: 2017/8/16 * Time: 09:16 */ namespace app\a ...

  6. springboot项目对接支付宝支付

    支付宝对接文档 一.准备工作 1. 首先要到 蚂蚁金服开发者中心 https://openhome.alipay.com/platform/home.htm 注册商家账户,并认证. 2.下载java版 ...

  7. web开发中的支付宝支付和微信支付

    https://www.jianshu.com/p/155757d2b9eb <!-- wxPay --SDK--> <script src="https://res.wx ...

  8. iOS开发笔记14:微博/微信登录与分享、微信/支付宝支付

    产品中接入了微博/微信的第三方登录分享功能.微信和支付宝的第三方支付功能,之前在开发过程中涉及到这些部分,于是抽空将接入过程梳理了一遍. 1.微博.微信.支付宝SDK相关接入设置 (1)微博SDK S ...

  9. laravel实现支付宝支付功能

    起因 前段时间因为项目中需要实现支付宝手机网站支付功能,所以写下这篇文章以作记录,不足之处,欢迎指教. 后端框架:Laravel 5.5 业务功能 适用于商家在移动端网页应用中集成支付宝支付功能.商家 ...

随机推荐

  1. Java | 字符串的使用 & 分析

    字符串 字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,在程序中所有的双引号字符串,都是String类的对象. 字符串的特点 1.字符串的内容永不可变. 2.正在是因为字符串的不 ...

  2. fasthttp:比net/http快十倍的Go框架(server 篇)

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/574 我们在上一篇文章中讲解了 Go HTTP 标准库的实现原理,这 ...

  3. Maven多模块Spring的注入

    第一次做多模块项目,Unit Test的时候发现Biz模块没法注入Dal模块的Mappper,提示找不到Bean. POM文件是正确引入了dependency的,扫描的package也没错,所以卡了好 ...

  4. python + pytest基本使用方法(断言)

    #pytest 的基本用法# 安装: pip install pytest#在当前目录下运行 : 输入 pytest# 1.断言#功能:用于计算a与b相加的和def add(a,b): return ...

  5. React中组件之间通信的方式

    一.是什么 我们将组件间通信可以拆分为两个词: 组件 通信 回顾Vue系列的文章,组件是vue中最强大的功能之一,同样组件化是React的核心思想 相比vue,React的组件更加灵活和多样,按照不同 ...

  6. YsoSerial 工具常用Payload分析之CC3(二)

    这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...

  7. kubernetes 降本增效标准指南|ProphetPilot:容器智能成本管理引擎

    作者 田奇,腾讯云高级工程师,专注大规模离在线混部,弹性伸缩,云原生成本优化,熟悉Kubernetes,关注云原生大数据.AI. 王孝威,腾讯云容器产品经理,热衷于为客户提供高效的 Kubernete ...

  8. English Study!

    As you konw, education is a top priority for us !  When the times abandon you, they don't even call ...

  9. 版本号是通过import合并而来的,不是继承来的

  10. linux系统下操作mysql数据库常见命令

    一. 备份数据库(如: test): ①可直接进入后台即可.(MySQL的默认目录:/var/lib/mysql ) ②输入命令: [root@obj mysql]# mysqldump -u roo ...