一、生成秘钥
1.1 登录平台
登录支付宝开放平台:https://open.alipay.com/
完善账户信息后;
1)点击控制台:

2)找到开发工具推荐,控制台下方的沙箱:

3)进入如下页面;

1.2 生成秘钥
注意:生成秘钥方式只要选择一种即可,“系统默认秘钥”比较简单,自定义秘钥需要使用工具生成;
1.2.1 系统默认秘钥
(这是第一种方式)

点击“查看”,可以看到如下界面;
这个 “应用私钥” 和 “支付宝公钥” 在之后的步骤中需要配置到Java程序

1.2.2 自定义秘钥
这是第二种方式:这个步骤需要生成工具!!!
二选一即可,此种方式暂时可以不用

点击“自定义秘钥”

下载秘钥生成工具


安装成功之后,点击生成秘钥



回到沙箱应用,填入公钥并确定完成;

注意:↑ 这个页面的网关地址和授权回调地址填入:https://www.alipay.com
点击上图的”设置并查看” 填入自己本地的“应用公钥”,就可以得到”支付宝公钥“;
这个”支付宝公钥“ 和 保存在我们本地的“应用私钥” 就是我们要配置到Java程序中的。

在沙箱账号中支付宝给我们提供了商家和买家账号:在支付环节需要用到

1.3 开发文档
可以参考官方文档进行调试(此步非必须,可以直接跳到 二、配置环境)



二、配置环境
2.1 沙箱环境准备
登录沙箱地址
保证接口加签方式已经启用:

官方文档
账号准备

2.2 内网穿透工具
注册一个账号,后期会要求实名认证,照做即可。

购买穿透隧道,可以选择免费一个月的。


购买成功后看下面的列表,点击配置:

会有生成认证令牌:复制并保存
注意:端口改为此时正在启动服务的端口,比如现在IDEA的Springboot项目中 tomcat使用的是9999端
口,则此时这里本地端口要改为9999

在官网右上角点击下载客户端工具: 根据你电脑情况选择合适的版本下载,这里我选用Windows64位

客户端启动需要一个config.ini文件,放到和下载的客户端natapp.exe文件同一个文件夹下,authtoken
的值粘贴为之前这里复制的令牌:


启动客户端:windows下,直接双击natapp.exe 即可。红框内就是我们的隧道通信地址。

注意:每次启动客户端都会分配一个新的隧道地址:要注意后期更换程序中配置 的地址。
测试:此时 这个穿透地址是临时域名就是代表了本地应用程序的访问地址http://localhost:9999
可以直接使用此域名来访问应用程序下的任意一个接口,如能访问,则环境OK。
比如: 我现在springboot应用启动了,那么输入这个临时域名 + 访问资源路径:
http://f55v9f.natappfree.cc/user/findAll 查询所有用户,能正常访问,就是测试成功!

三、Java程序配置
3.1 添加依赖
刷新maven,直到把资源下载下来为止。 也可以选择其他版本
1 2 3 4 5
| <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.9.13.ALL</version> </dependency>
|
3.2 配置 application.yml
增加如下信息:
1 2 3 4 5 6
| alipay: appId: 这里配置的是“沙箱应用”中的APPID号,如下图 appPrivateKey: 配置应用私钥,之前有获得过 alipayPublicKey: 配置“支付宝公钥”,之前有获得过,注意:不是“应用公钥” notifyUrl: 你自己的隧道通信地址/alipay/notify # 比如我这里配置为: http://muaqx9.natappfree.cc/alipay/notify
|

配置成这样:

3.3 编写Java程序
1)新Alipay类,用于前后端交互,注意加上@Data注解(或者自行加上 gettersetter 也可以)
1 2 3 4 5 6 7 8 9 10 11 12
|
@Data public class AliPay { private String traceNo; private Double totalAmount; private String subject; private String alipayTraceNo; }
|
2)新增AlipayConfig配置类,增加如下注解,读取yaml中关于alipay的配置信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
@Data @Component @ConfigurationProperties(prefix = "alipay") public class AlipayConfig { private String appId;
private String appPrivateKey;
private String alipayPublicKey;
private String notifyUrl; }
|
如果这个类的上方有警告关于注解处理器配置问题,则增加依赖并刷新maven:
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency>
|
3)编写控制器类AlipayController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| package com.cykj.controll; import com.alibaba.fastjson.JSONObject; 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 org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map;
@RestController @RequestMapping("/alipay") public class AliPayController {
private static final String GATEWAY_URL = "https://openapi.alipaydev.com/gateway.do";
private static final String FORMAT = "JSON";
private static final String CHARSET = "UTF-8";
private static final String SIGN_TYPE = "RSA2"; @Resource private AlipayConfig alipayConfig;
@GetMapping("/pay") public void pay(AliPay aliPay, HttpServletResponse response) throws IOException { System.out.println(aliPay); System.out.println("alipayConfig:" + alipayConfig);
AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, alipayConfig.getAppId(), alipayConfig.getAppPrivateKey(), FORMAT, CHARSET, alipayConfig.getAlipayPublicKey(), SIGN_TYPE);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); request.setNotifyUrl(alipayConfig.getNotifyUrl()); JSONObject bizContent = new JSONObject(); bizContent.put("out_trade_no", aliPay.getTraceNo()); bizContent.put("total_amount", aliPay.getTotalAmount()); bizContent.put("subject", aliPay.getSubject()); bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); request.setBizContent(bizContent.toString());
String form = ""; try { form = alipayClient.pageExecute(request).getBody(); } catch (AlipayApiException e) { e.printStackTrace(); }
response.setContentType("text/html;charset=" + CHARSET); response.getWriter().write(form); response.getWriter().flush(); response.getWriter().close(); }
@PostMapping("/notify") public String payNotify(HttpServletRequest request) throws AlipayApiException { System.out.println("异步回调了。" + request); if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) { System.out.println("-------------支付宝异步回调----"); Map<String, String> params = new HashMap<>(); Map<String, String[]> requestParams = request.getParameterMap(); System.out.println("-----params-----------"); for (String name : requestParams.keySet()) { params.put(name, request.getParameter(name)); System.out.println(name + " " + request.getParameter(name)); } String outTradeNo = params.get("out_trade_no"); String gmtPayment = params.get("gmt_payment"); String alipayTradeNo = params.get("trade_no"); String sign = params.get("sign"); String content = AlipaySignature.getSignCheckContentV1(params); boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, alipayConfig.getAlipayPublicKey(), "UTF-8");
if (checkSignature) {
System.out.println("交易名称: " + params.get("subject")); System.out.println("交易状态: " + params.get("trade_status")); System.out.println("支付宝交易凭证号: " + params.get("trade_no")); System.out.println("商户订单号: " + params.get("out_trade_no")); System.out.println("交易金额: " + params.get("total_amount")); System.out.println("买家在支付宝唯一id: " + params.get("buyer_id")); System.out.println("买家付款时间: " + params.get("gmt_payment")); System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
} } return "success"; } }
|
四、前端程序编写
新建Alipay.vue,并且给他配置对应的路由。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <template> <div> <h3>测试支付宝支付</h3> <el-form label-width="80px" :model="aliPay"> <el-form-item label="订单id"> <el-input v-model="aliPay.traceNo" ></el-input> </el-form-item> <el-form-item label="订单价格"> <el-input v-model="aliPay.totalAmount" ></el-input> </el-form-item> </el-form> <a :href="payURL">确定支付</a> </div> </template> <script> export default { data() { return { aliPay: { traceNo: "", totalAmount: 0.0 }, }; }, computed:{ payURL:function(){ return "http://localhost:9999/alipay/pay?subject=收购阿里&traceNo=" + this.aliPay.traceNo + "&totalAmount=" + this.aliPay.totalAmount } } }; </script>
|
点击支付:


五、沙箱支付宝付款
沙箱环境是模拟环境,所以要使用沙箱版支付宝进行支付,下载安装:
此时回到
\


回到沙箱账号充钱!!

打开沙箱支付宝客户端,输入买家账号和密码,
打开“沙箱支付宝”, 登录方式选择“ 其他方式登录”


然后扫支付二维码:


