1、进入支付宝开发平台—沙箱环境
1.1、进入个人沙箱环境
点击进入沙箱环境并用支付宝登陆\
第一步:配置沙箱应用环境
沙箱管理界面如图所示
- appid,支付宝网关,自定义密钥等
appid,支付宝网关,自定义密钥等
这里是沙箱支付宝(虚拟)的账号和密码,可以用来支付
1.2、接下来进行几个密钥的生成
点击进入密钥工具 点击生成
这时我们拿到两个密钥,将它们保存,这两个密钥很重要
应用私钥 应用公钥
1.3、拿到两个密钥后,进行自定义密钥配置
进入最开始的沙箱管理界面,点击自定义密钥,点击设置(查看),我们选择的是RSA2密钥
选择“公钥”这一选项
将上一步骤生成的应用公钥填进来,会得到支付宝公钥这另一个密钥,记住并保存这个支付宝公钥
1.4、至此,我们沙箱环境的配置和基本参数都已经获取到。
2、项目端的代码配置
2.1 maven 依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.16.2.ALL</version>
</dependency>
2.2 创建Controller类后,首先设置如下私有属性
- APP_ID (appId,从沙箱管理页面获得)
- APP_PRIVATE_KEY (应用私钥,最开始在密钥工具生成而来)
- ALIPAY_PUBLIC_KEY (支付宝公钥,上一步骤获得)
- GATEWAY_URL (支付宝网关地址,在开发平台沙箱管理页面中获得)
- SIGN_TYPE (签名类型)
- NOTIFY_URL (异步回调地址,须是公网IP,后面再解释)
- RETURN_URL (同步回调地址,可以是私网IP)
package com.dm.sqlark.system.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 支付宝支付测试
* @author luhui
*/
@RestController
@ApiSort(value = 101)
@Api(tags = "101.支付宝支付测试控制器")
@Slf4j
public class AliPayTestController {
/**
* appid
*/
private final String APP_ID = "2021000122665251";
/**
* 应用私钥
*/
private final String APP_PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQChMDdq+vWT3c1GIbmQJVj4BM3OpnBc+HovRIVUpvnpgazcDLabX2UmN8UQAE35FmD6t8ApDRHsON8T7NfykUCjAqirUSVghXFPozOut0i3Lpdt1RiTjtMo4Jne8ZTlxSxSdfj7TGnK49+ESoK9VmYVQb8JF9mUdaMl/wa4vTv/N1Gqh+d5v5xF/oOlq89GP1SPQ7zwogbyaS69qNcKgep/5eJlrFHMyvvo5BSF5eKufJ6BkyaK6qfBQp+R4LnQy4hCcKnqXeqw9CGA2UCsz+ajueH900kgG+YOgwRlHSDFAyoKLGMS6v/H+o8TD6vmVmNmMGeB0kGecZltKxxX8icDAgMBAAECggEAKskVrLv4u8tAVcFV9EE1oIAF8TiU0tjR9gIGMjYwWB8ntzFYt11XCBH9qQWrrNaX33Uu+LaTb1SZQjy4BZcwxRRLmU3s0fYZ4b28VkAoeRdQ8sKBx4k927fioB8YGvV/klPmRy49VrGt/vuYQJHSfwn4n31JL/MZ31gWfKseZdvoGnkOkD1Bz4dz2p0Z/zYc/FDeOJGcnmFcN+3K1kZ6DJspir6+u+MzMWk7A5uhJEy323O5jsPyE94FyLLX4mt3wJvsEwN2aIWHPBu8NkjPov5USrzIyutYIPCztHTbIljRB9h203sLasqZ/9VDzB0c2vAielaV+alb/mscqQxXoQKBgQDtKDlBaTHDXLAR4L6oHh3NAR2NXv/WRw8L6K83VFAbo7LtZvrIOU/aRzM9ZtIxK8wHvLtAyms2L0LG7uZKJeTyyse+uMIa8jPihAMX1+H7VpsYxei3I90mSNKlg0sBzJl0vTNSg9IkbiZ5HuOOprz7litfztMlcCYdLKdTgzsL/wKBgQCt/smoz+yHjLHQ7A6UKyGk85qF168ufdIuO4uvEwEBQuYqpqDqfI3sLIuDo8bOS80TrRGCtLPwIYI0uArZx+4lNmJjtEs0o3Be/FJqutZnctK+fU0dnYffUbblIlPdDeYn9U1grIBqPvTrmDzHOkm/hPQObqO/lX5R0HNf/di0/QKBgQCSnFJBCMo1zyAd/UWAYxXjPXRKiFc63bUElLV1TA819w5PS2Fv1FZ0R536sIzyzvOUOO2+ESUUW0U5/EirwB94pTm0wz1kMSU4PIo4/EH9Aj5hoz/JsEcwOsbWgYMmOpkHnUuUEGAiG2J3cEwXTSb5lY187jyEIX++e3N54l/newKBgQCscIH9eyvo3whvjTOZpvFuIDu5gBvPEMWYKk1yknwBewLPrFp4aj7hnPgb29mxJLC3WmOrTVmzmBIKG4gtdBbR7IcwV0PdhEle6eTogAjzd3njbh1aR4CcU8jWZ+IDh73dRiCMugl+wqxLPZKmxF7In4SdOBIazvxRMzHo9Xc9zYJpap3c/43mr8lyOmJlRSl2/CYH1Nwex9gXIvtS5YENTplQa9T6FKD0H7md1R9MFjh+TejNDbg7CgME";
/**
* 编码
*/
private final String CHARSET = "UTF-8";
/**
* 支付宝公钥
*/
private final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu0pi+itnyNHGVHj6EmhyG4zOTfPgsBk5fMpFelBegRdXto5GThAMSmwAmvFnaaLypd+Uf5LHHhilnZ1U2ghGm+VApbzf//qezHvF+bNHY1AolFyKlET9QQNE5c0lpDSE3Mo0iJxdwZgPIvHKqnyL9NoqU4791ALZTmaNZ2EArrbkVSozZ6X64HU6dDdYpACE19xci17DZUFs8J3f4y78aSrG5zUcrh0EOSeoJMUb3MGM4MDMA+EQrcuOEvIjHYfcZKUDCmIK3/S9iT6VP8b6s6mWXtYR2sLPsqAzEX99mmrZZGJQeYhgEHn3otyZI2H9im8QmtR0aZPxedZdlwIDAQAB";
/**
* 这是沙箱接口路径,正式路径为https://openapi.alipay.com/gateway.do
*/
private final String GATEWAY_URL ="https://openapi-sandbox.dl.alipaydev.com/gateway.do";
/**
* 格式化
*/
private final String FORMAT = "JSON";
/**
* 签名方式
*/
private final String SIGN_TYPE = "RSA2";
/**
* 支付宝异步通知路径,付款完毕后会异步调用本项目的方法,必须为公网地址
*/
private final String NOTIFY_URL = "http://www.sqlark.com/website/testHook";
//
/**
* 支付宝同步通知路径,也就是当付款完毕后跳转本项目的页面,可以不是公网地址
*/
private final String RETURN_URL = "http://localhost:6767/returnUrl";
@ResponseBody
@RequestMapping("/pay/alipay")
public String alipay(HttpSession session,
@RequestParam("dona_money") float dona_money,
@RequestParam("dona_id") int dona_id) throws AlipayApiException {
//把dona_id项目id 放在session中
session.setAttribute("dona_id",dona_id);
//生成订单号(支付宝的要求?)
String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String user = UUID.randomUUID().toString().replace("-","").toUpperCase();
String OrderNum = time+user;
//调用封装好的方法(给支付宝接口发送请求)
return sendRequestToAlipay2(OrderNum,dona_money,"ghjk");
}
/**支付宝官方提供的接口,调整到支付宝页面,输入账号密码进行支付
* @param outTradeNo 订单号
* @param totalAmount 订单金额
* @param subject 订单名称
* @return
* @throws AlipayApiException
*/
private String sendRequestToAlipay(String outTradeNo,Float totalAmount,String subject) throws AlipayApiException {
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL,APP_ID,APP_PRIVATE_KEY,FORMAT,CHARSET,ALIPAY_PUBLIC_KEY,SIGN_TYPE);
//设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(RETURN_URL);
alipayRequest.setNotifyUrl(NOTIFY_URL);
//商品描述(可空)
String body="";
alipayRequest.setBizContent("{"out_trade_no":"" + outTradeNo + "","
+ ""total_amount":"" + totalAmount + "","
+ ""subject":"" + subject + "","
+ ""body":"" + body + "","
+ ""product_code":"FAST_INSTANT_TRADE_PAY"}");
//请求
String result = alipayClient.pageExecute(alipayRequest).getBody();
return result;
}
/**
* 支付宝生成一个地址,扫码支付
* @param outTradeNo
* @param totalAmount
* @param subject
* @return
* @throws AlipayApiException
*/
private String sendRequestToAlipay2(String outTradeNo,Float totalAmount,String subject) throws AlipayApiException {
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL,APP_ID,APP_PRIVATE_KEY,FORMAT,CHARSET,ALIPAY_PUBLIC_KEY,SIGN_TYPE);
AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();
alipayRequest.setReturnUrl(RETURN_URL);
alipayRequest.setNotifyUrl(NOTIFY_URL);
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(totalAmount.toString());
model.setSubject(subject);
alipayRequest.setBizModel(model);
AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest);
return response.getQrCode();
}
@RequestMapping("/returnUrl")
public String returnUrlMethod(HttpServletRequest request, HttpSession session, Model model)
throws AlipayApiException, UnsupportedEncodingException, UnsupportedEncodingException {
System.out.println("=================================同步回调=====================================");
// 获取支付宝GET过来反馈信息
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, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE); // 调用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);
//在这里编写自己的业务代码(对数据库的操作)
/*
################################
*/
//跳转到提示页面(成功或者失败的提示页面)
model.addAttribute("flag",1);
model.addAttribute("msg","支持");
return "common/payTips";
}else{
//跳转到提示页面(成功或者失败的提示页面)
model.addAttribute("flag",0);
model.addAttribute("msg","支持");
return "common/payTips";
}
}
}
2.3 下载支付沙箱App 登录沙箱账号
扫码下载,安装
2.4 扫码支付测试
1、访问 http://localhost:6767/pay/alipay?dona_money=10.2&dona_id=1
返回结果如下:
2、根据返回的Url 来生成二维码
访问 cli.im/url
3、登录沙箱 app 账号,进行扫码
支付成功后,可以看到回调地址
2.5 pc端支付
1、调整控制器代码,重启应用
//调用封装好的方法(给支付宝接口发送请求)
return sendRequestToAlipay(OrderNum,dona_money,"ghjk");
2、访问地址
http://localhost:6767/pay/alipay?dona_money=10.2&dona_id=1
跳转到页面
3、输入沙箱账号密码
4、支付成功后,回调到用户地址,当前地址可以不是公网地址
控制台输出如下:
\=================================同步回调=====================================
{charset=UTF-8, out\_trade\_no=2023060811310762338314203F4804A90B01C469BB351F, method=alipay.trade.page.pay.return, total\_amount=10.20, sign=T4VqLufnAUexj8i/rCuSGgR+VtzaleIj33hvSVCpn06OjUaX15W5HyL1UqOGK+SzRoDrx0MFZwCfF0tFX/CXQ3l2xLFOhLHzth2HSu2LqxjXXjWdCQg6udMh6J3pAn7FV3rqCd+pWA+eZFNMy1CovglEZ8RR2iRPh8z1k/oHUh/aKQ4VtkU45UXd6Gz0sL50Uv35r0UYNImAODORsq9HG4SyhinGlWKe3//TL7cW+ULzPkxHYuii4VhlCigsqmV2i5Dc4auHBlJEnkOHdgitARRBGjHjuuRs31mizacagQINwlNy63OZXh9BNHN0uI2gGLRmoEYKboCwFl0eJwlwOw==, auth\_app\_id=2021000122665251, trade\_no=2023060822001424540500151237, app\_id=2021000122665251, sign\_type=RSA2, version=1.0, seller\_id=2088721002424530, timestamp=2023-06-08 11:31:34}
商户订单号=2023060811310762338314203F4804A90B01C469BB351F
支付宝交易号=2023060822001424540500151237
付款金额=10.2