首先配置沙箱应用环境沙箱环境 | 开放平台
进入页面后,使用支付宝进行登录(你也可以根据官方的说明进行操作,这个页面的数据会随版本变化而变化) 登录后来到支付宝开发平台
生成密钥,我是下载了软件,看你怎么操作生成密钥 | 开放平台,
如果是下载软件方式打开这个软件 ,点击生成密钥,点击复制公钥(注意是应用公钥,通过应用公钥获取支付宝公钥) 这个应用私钥下面也需要
选择自定义私钥 (我是弄过了的,你没有弄过就点击设置并查看)
把复制的公钥粘贴到上面对应的那个框,点击确定就生成了支付宝公钥,点击确定
点击左侧栏的沙箱账号,就可以看到买家和买家基本信息(下面会使用),这个金额都可以进行修改的
至此,沙箱模拟最主要的几个数据得到了
APPID 应用私钥 支付宝公钥
创建springboot工程,我这里采用thymeleaf作为模板引擎实现页面间的跳转,需要引入阿里提供的沙箱的依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.16.2.ALL</version>
</dependency>
开启内网穿透,双击start.bat (内网穿透我博客也有详细说明)
创建pojo,写四个变量
package com.alipay.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
@ConfigurationProperties("alipay")
public class Pay {
/*** APPID */
private String appId;
/** * 应用私钥 */
private String appPrivateKey;
/*** 支付宝公钥*/
private String alipayPublicKey;
/** * 支付宝异步通知路径 */
private String notifyUrl;
}
在配置文件yml中配置,这几个数据是按照你的数据来的,代表什么参照上一张图,因为值几个值可能会该变,尤其是公网,当关闭start.bat时网址会改变。所以不写死
server:
port: 9090 #端口号,要与在内网穿透中配置的端口号一致
alipay:
appId: 2021000121639754
appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHIur+5aCc6rmxlG/gSixVUgLzdoiJmmAdmRW06a9VWwHkSzicsSSmm9sWMgGJzMU1bKy/vf+i2HG2Xsb2otzqVomhwJCBD09zzFmil49fDDfRnjBmomxZHeTzgs5i+lJRU7NzIYoe9l2ZTtkaaWbRim9Cju9VLmqmKQyoMihTpi98RBRRlnTTz1XlgwLBzbvj9AX+gfgebEZLmohpej2L7EuDydiN1Pmw24b0A49IpIKwRUQP1Es6IUXl7JfH12nbZgU9FpKFFEi9Bv9brhXrODjk6HaggeJzsQ604q28S2cvJrcfmxXU0AG2sLPCcw5OQnEfQJRuEjDfPF/8YffrAgMBAAECggEAedc4y6OcIX7c+EheanpV6INuF7cque5PdMA+uwPrSukoFn7fxx9MbU+exC9IBcdzk4ytYJ/dKiU+uXBQsbT7u+lUZFurrkFwoHaB5sABy2/HsB6Rgyg0ylDSyd+JV+Jcb+kopch6sRnuIDjgNBkOVCUd1YPsNAAKtk/Skp/OjkO7jjQB5E+uYbIiYVEqgI8m1qe9V9alKseDRQKxfGY1G6vDXzGJZ+awpnfXE45KJm99SofN+KQzhDtOZwzLzBgrs7+raXNr93XIHHXMWU43q7d758cr5AxAOw7pz1+KYUEygRfERz/B3Gs0JWgTrr5fpoZfyH43+hB/XDPAL1V4GQKBgQC+/TObX0hrfrP23y0LMlzWP5U3sdPD0OAWFmBiDnQnOdRAFp3H12/nLPybIiTXfh1JcHLwzcJX7KE0VYuCIodouBd2gDQQMq62Po33ECgj65uc19Z13h8n4cGsyWtxCZZoW1bE0sgSfMCnVBw4xRgA63Rw/VfGIBn8hq4pG0xgdQKBgQC1IrYhwBJrQdNGTCnxBP6rmv4O14Jt4jZtY3M/1HfLXq9ATvmxkwmMBs7n9TeDQc5v8A1ZK4GIKwg2iRmQrvPNW1qoS1790ZyMbFihf6LCsVmJSCFCSn0nz7cVOb4vs51EhJRN7U1kJ/X61I6cDSWu+UQi6Nr6n9Drmv0hzBPq3wKBgQCnBQZ8eXb7inIXElRx1jkZo8D6U6i9NYzBxA/FsJ4jL49N/Hk+qkhSAiVmBRXy3Xb/IjdiHo42FdljyuuVglyoV1UtbDAbejcPaOT9ikOQJhqPrrD9oqHcXrDgScSLtbayzC21Mh+FC1PvAL8tZi73nvDVXrfDq48OJzlm+VhxgQKBgGVjxKcnqCe5dNWIlIGA1jygSU1tfGidkvGwFTbJazS/D0Hj8whe0Z07wl08eZJTJ4aozA/5tkvOKo68Nz8xbu6oEBrb9ZQF3KcNjp73ntd0BjY91cARifTa5BRReg+hboqH26uzBPrnE10P1bOr+Ef05xrTVJ+tDXiUDNT6MrvpAoGADureFLYwUwXXSP2JaO8njguIf7saYW/YvBl4C0C/veAYeH+PCSAkbURVi0IygGb0xshQ8BhSIp0eu1YUheLGKKyygu7CzO0Z8lnYLvGZeRTJwvwxO3MyQxbvdzy4M3/jrxUNb0xOyjB+92zjJOA4ux/E4rd7fgmL9I6n3cLvmCY=
alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhO+kUXPHJE2L5ZEnCPllcpD3hcjXF1+fsIDQxsgLDqQIpuX7+WvQGz4/4Qg5SRvd1g8Miy1uvmxrT4rzVM42QQYqgVH07E9Z6FCieTqYh1GWE0ceXKpD5k0fe8dez39Hph/njoMBiGGFpKMPg80r6LZd1NApm4Mfz5LETeH7AAiwexYBpRhs2x7+wtwfAcGop2a0hWP10PZJWdG0rViAyx2TbRCBAemqW8B3gmBueb3kVyi4XxgOE8hjyqxGWJRx4S+dWJDtDFr0lGyAdl2cSczQqY2Y9VIxPE4AKAUrnsOPIrZp7ko2iRIVgH/m10vHP8zZhWm6IZ5me9d+Gu6aWwIDAQAB
notifyUrl: http://t8529w.natappfree.cc/notifyUrl
创建controller,首先定义变量
/*APPID*/
@Value("${alipay.appId}")
private String appId;
/*应用私钥*/
@Value("${alipay.appPrivateKey}")
private String appPrivateKey;
/*支付宝公钥*/
@Value("${alipay.alipayPublicKey}")
private String alipayPublicKey;
/*支付宝异步通知路径*/
@Value("${alipay.notifyUrl}")
private String notifyUrl;
// 字符编码
private final String charSet = "UTF-8";
//沙箱接口路径
private final String gatewayUrl ="https://openapi.alipaydev.com/gateway.do";
//格式
private final String format = "JSON";
//签名方式
private final String signType = "RSA2";
//支付宝同步通知路径 这里要写你的
private final String returnUrl = "http://localhost:9090/returnUrl";
在index.js中写一个表单,注意是在templates下,并配置"/"的请求路径(因为使用到了thymeleaf作为模板引擎)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="get" th:action="@{/alipay}">
输入价格 <input type="text" name="money"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
参照上一步,写出下面代码,执行项目。通过输入数据后,响应(@ResponseBody)会加载支付宝登录界面,用户名就是沙箱账户中的买家账号,登录密码和支付密码与之对应。之后会进行页面跳转,但还没有写跳转的请求路径
@ResponseBody
@GetMapping("/alipay")
public String alipay(@RequestParam("money") float money) throws AlipayApiException {
// UUID生成订单号
String currenTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String orderNumber = UUID.randomUUID().toString().replace("-","").toUpperCase();
// 订单号
String Order = currenTime+orderNumber;
//调用封装好的方法(给支付宝接口发送请求)
return sendRequestToAlipay(Order,money,"请支付相关物品");
}
//支付宝官方提供的接口
private String sendRequestToAlipay(String outTradeNo,Float totalAmount,String subject) throws AlipayApiException {
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl,appId,appPrivateKey,format,charSet,alipayPublicKey,signType);
//设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(returnUrl);
alipayRequest.setNotifyUrl(notifyUrl);
//商品描述(可空)
String body="";
alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\","
+ "\"total_amount\":\"" + totalAmount + "\","
+ "\"subject\":\"" + subject + "\","
+ "\"body\":\"" + body + "\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//返回数据
return alipayClient.pageExecute(alipayRequest).getBody();
}
下面是同步回调的请求地址以及相关代码,复制到上一步下面就行了,现在重启系统,重新进行操作,操作完后就会跳转到对应的页面
@RequestMapping("/returnUrl")
public String returnUrlMethod(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
// 获取支付宝GET过来反馈信息
System.out.println("------------------------同步回调----------------------------------");
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);
}
System.out.println(params);//查看参数都有哪些
//验证签名(支付宝公钥)
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, charSet, signType); // 调用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");
// 付款金额
float money = Float.parseFloat(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));
System.out.println("商户订单号="+out_trade_no);
System.out.println("支付宝交易号="+trade_no);
System.out.println("付款金额="+money);
/**
* 这里可以对数据进行crud操作
*/
//跳转到提示页面(成功或者失败的提示页面)
return "success";
}else{
return "error";
}
}
至此,同步回调就完成了。还有异步回调,异步回调我还有点问题没有解决,就是通过手机或者另外的电脑登录公网时,最后页面加载不出来,但start.bat页面显示能加载这个post请求. 代码与同步回调基本一致,注意是post请求
@PostMapping("/notifyUrl")
public String notifyUrlethod(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
// 获取支付宝GET过来反馈信息
System.out.println("------------------------异步回调----------------------------------");
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);
}
System.out.println(params);//查看参数都有哪些
//验证签名(支付宝公钥)
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, charSet, signType); // 调用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");
// 付款金额
float money = Float.parseFloat(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));
System.out.println("商户订单号="+out_trade_no);
System.out.println("支付宝交易号="+trade_no);
System.out.println("付款金额="+money);
/**
* 这里可以对数据进行crud操作*/
//跳转到提示页面(成功或者失败的提示页面)
return "success";
}else
return "error";
}
}