做了一个测试案例,用的沙箱测试账号
可以去支付宝官网注册一个开发者账号,获取沙箱账号,地址: https://openhome.alipay.com/platform/appDaily.htm?tab=info
注册完之后会看到以下画面:


上面两个图中,我们可以看到有这个几个有用的信息:
1.APPID
2.支付宝网关
3.商家账号 登录密码
4.买家账号 登录密码 支付密码
接下来,我们在沙箱应用里要设置一下RSA2公钥
首先下载生成公钥和私钥的工具,地址:https://opendocs.alipay.com/open/291/105971#LDsXr

如上图,只有windows版和macOs版,用linux的心疼一秒钟,还好我有windows虚拟机。

如上图,安装之后,点击生成秘钥即可生成公钥和私钥,复制保存好这个公钥和私钥
接下来更改沙箱应用中RSA2的公钥,把刚刚生成的公钥复制到在线网站上保存。

到现在为止,准备工作已经做完了。
在springboot上创建一个AlipayConfig类
package com.zhaohy.app.config;
import java.io.FileWriter;
import java.io.IOException;
public class AlipayConfig {
// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
public static String APP_ID = "";
// 商户私钥,您的PKCS8格式RSA2私钥,这些就是我们刚才设置的
public static String RSA_PRIVATE_KEY = "";
// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm
// 对应APPID下的支付宝公钥。,这些就是我们刚才设置的
public static String ALIPAY_PUBLIC_KEY = "";
// 异步通知,再这里我们设计自己的后台代码
public static String notify_url = "http://www.zhaohy.org.cn";
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String return_url = "http://www.zhaohy.org.cn";
// 签名方式
public static String SIGN_TYPE = "RSA2";
// 字符编码格式
public static String CHARSET = "utf-8";
// 支付宝网关 https://openapi.alipaydev.com/gateway.do https://openapi.alipay.com/gateway.do
public static String GATEWAYURL = "https://openapi.alipaydev.com/gateway.do";
// 支付宝网关
public static String LOG_PATH = "/home/zhaohy/alipayLog/";
public static String FORMAT = "json";
// ↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
*
* @param sWord 要写入日志里的文本内容
*/
public static void logResult(String sWord) {
FileWriter writer = null;
try {
writer = new FileWriter(LOG_PATH + "alipay_log_" + System.currentTimeMillis() + ".txt");
writer.write(sWord);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
把之前的appid,公钥,私钥和网关地址都填在上面代码里
新建AlipayService类
package com.zhaohy.app.service;
import com.alipay.api.AlipayApiException;
public interface AlipayService {
/**
* web端订单支付
*
* @param outTradeNo 订单编号(唯一)
* @param totalAmount 订单价格
* @param subject 商品名称
*/
String webPagePay(String outTradeNo, Integer totalAmount, String subject) throws Exception;
/**
* app端订单支付
*
* @param outTradeNo 订单编号
* @param totalAmount 订单价格
* @param subject 商品名称
*/
String appPagePay(String outTradeNo, Integer totalAmount, String subject) throws Exception;
/**
* 退款
*
* @param outTradeNo 订单编号
* @param refundReason 退款原因
* @param refundAmount 退款金额
* @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
*/
String refund(String outTradeNo, String refundReason, Integer refundAmount, String outRequestNo)
throws AlipayApiException;
/**
* 交易查询
*
* @param outTradeNo 订单编号(唯一)
*/
String query(String outTradeNo) throws AlipayApiException;
/**
* 交易关闭
*
* @param outTradeNo订单编号(唯一)
*/
String close(String outTradeNo) throws AlipayApiException;
/**
* 退款查询
*
* @param outTradeNo 订单编号(唯一)
* @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
*/
String refundQuery(String outTradeNo, String outRequestNo) throws AlipayApiException;
}
新建AlipayServiceImpl实现类
package com.zhaohy.app.service.impl;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.zhaohy.app.config.AlipayConfig;
import com.zhaohy.app.service.AlipayService;
import com.zhaohy.app.utils.AppFrameworkUtil;
@Service("AlipayService")
public class AlipayServiceImpl implements AlipayService {
/** 调取支付宝接口 web端支付 */
DefaultAlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAYURL, AlipayConfig.APP_ID,
AlipayConfig.RSA_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,
AlipayConfig.SIGN_TYPE);
/** 调取支付宝接口app端支付 */
AlipayClient alipayClients = new DefaultAlipayClient(AlipayConfig.GATEWAYURL, AlipayConfig.APP_ID,
AlipayConfig.RSA_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,
AlipayConfig.SIGN_TYPE);
/**
* web端订单支付
*
* @param outTradeNo 订单编号(唯一)
* @param totalAmount 订单价格
* @param subject 商品名称
*/
@Override
public String webPagePay(String outTradeNo, Integer totalAmount, String subject) throws Exception {
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
/** 同步通知,支付完成后,支付成功页面 */
alipayRequest.setReturnUrl(AlipayConfig.return_url);
/** 异步通知,支付完成后,需要进行的异步处理 */
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
Map<String, String> bizContentMap = new HashMap<String, String>();
bizContentMap.put("out_trade_no", outTradeNo);
bizContentMap.put("total_amount", totalAmount + "");
bizContentMap.put("subject", subject);
bizContentMap.put("body", "商品名称");
bizContentMap.put("timeout_express", "90m");
bizContentMap.put("product_code", "FAST_INSTANT_TRADE_PAY");
String bizContentJson = AppFrameworkUtil.structureConfigParamsGroupJSONDataWithOutSimpleResultBean(bizContentMap);
alipayRequest.setBizContent(bizContentJson);
/** 转换格式 */
String result = alipayClient.pageExecute(alipayRequest).getBody().replace('\"', '\'').replace('\n', ' ');
return result;
}
/**
* 退款
*
* @param outTradeNo 订单编号
* @param refundReason 退款原因
* @param refundAmount 退款金额
* @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
*/
@Override
public String refund(String outTradeNo, String refundReason, Integer refundAmount, String outRequestNo)
throws AlipayApiException {
AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
/** 调取接口 */
alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"," + "\"refund_amount\":\"" + refundAmount
+ "\"," + "\"refund_reason\":\"" + refundReason + "\"," + "\"out_request_no\":\"" + outRequestNo
+ "\"}");
String result = alipayClient.execute(alipayRequest).getBody();
return result;
}
/**
* 交易查询
*
* @param outTradeNo 订单编号(唯一)
*/
@Override
public String query(String outTradeNo) throws AlipayApiException {
AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();
/** 请求接口 */
alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"," + "\"trade_no\":\"" + "" + "\"}");
/** 转换格式 */
String result = alipayClient.execute(alipayRequest).getBody();
return result;
}
/**
* 交易关闭
*
* @param outTradeNo订单编号(唯一)
*/
@Override
public String close(String outTradeNo) throws AlipayApiException {
AlipayTradeCloseRequest alipayRequest = new AlipayTradeCloseRequest();
alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"," + "\"trade_no\":\"" + "" + "\"}");
String result = alipayClient.execute(alipayRequest).getBody();
return result;
}
/**
* 退款查询
*
* @param outTradeNo 订单编号(唯一)
* @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
*/
@Override
public String refundQuery(String outTradeNo, String outRequestNo) throws AlipayApiException {
AlipayTradeFastpayRefundQueryRequest alipayRequest = new AlipayTradeFastpayRefundQueryRequest();
/** 请求接口 */
alipayRequest.setBizContent(
"{\"out_trade_no\":\"" + outTradeNo + "\"," + "\"out_request_no\":\"" + outRequestNo + "\"}");
/** 格式转换 */
String result = alipayClient.execute(alipayRequest).getBody();
return result;
}
/**
* app端订单支付
*
* @param outTradeNo 订单编号
* @param totalAmount 订单价格
* @param subject 商品名称
*/
@Override
public String appPagePay(String outTradeNo, Integer totalAmount, String subject) throws Exception {
AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
/** 同步通知,支付完成后,支付成功页面 */
alipayRequest.setReturnUrl(AlipayConfig.return_url);
/** 异步通知,支付完成后,需要进行的异步处理 */
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
/** 销售产品码(固定) */
String productCode = "QUICK_WAP_WAY";
/** 进行赋值 */
AlipayTradeWapPayModel wapPayModel = new AlipayTradeWapPayModel();
wapPayModel.setOutTradeNo(outTradeNo);
wapPayModel.setSubject(subject);
wapPayModel.setTotalAmount(totalAmount.toString());
wapPayModel.setBody("商品名称");
wapPayModel.setTimeoutExpress("2m");
wapPayModel.setProductCode(productCode);
alipayRequest.setBizModel(wapPayModel);
/** 格式转换 */
String result = alipayClients.pageExecute(alipayRequest).getBody().replace('\"', '\'').replace('\n', ' ');
return result;
}
}
新建AlipayController
package com.zhaohy.app.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
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.RequestParam;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.zhaohy.app.service.AlipayService;
import com.zhaohy.app.utils.AppFrameworkUtil;
@Controller
public class AlipayController {
@Autowired
private AlipayService alipayService;
@RequestMapping("/alipayTest.do")
public String test(HttpServletRequest request) {
request.setAttribute("ctx", AppFrameworkUtil.getWebRootUrl(request, ""));
return "html/alipay";
}
/**
* web 订单支付
*/
@RequestMapping("/alipay/getPagePay")
public void getPagePay(HttpServletRequest request, HttpServletResponse response) throws Exception {
/** 模仿数据库,从后台调数据 */
String outTradeNo = "19960310621211";
Integer totalAmount = 1;
String subject = "苹果28";
String pay = alipayService.webPagePay(outTradeNo, totalAmount, subject);
System.out.println(pay);
Map<Object, Object> resultMap = new HashMap<>();
resultMap.put("data", pay);
AppFrameworkUtil.renderJSON(response, AppFrameworkUtil.structureConfigParamsGroupJSONData(resultMap));
}
/**
* app 订单支付
*/
@RequestMapping("/alipay/getAppPagePay")
public void getAppPagePay(HttpServletRequest request, HttpServletResponse response) throws Exception {
/** 模仿数据库,从后台调数据 */
String outTradeNo = "1312332";
Integer totalAmount = 1000;
String subject = "天猫超市014";
String pay = alipayService.appPagePay(outTradeNo, totalAmount, subject);
System.out.println(pay);
Map<Object, Object> resultMap = new HashMap<>();
resultMap.put("data", pay);
AppFrameworkUtil.renderJSON(response, AppFrameworkUtil.structureConfigParamsGroupJSONData(resultMap));
}
/**
* 交易查询
*/
@RequestMapping("/alipay/aipayQuery")
public void alipayQuery(HttpServletRequest request, HttpServletResponse response) throws Exception {
/** 调取支付订单号 */
String outTradeNo = "13123";
String query = alipayService.query(outTradeNo);
//Object json = JSONObject.toJSON(query);
/*
* JSONObject jObject = new JSONObject(); jObject.get(query);
*/
AppFrameworkUtil.renderJSON(response, query);
}
/**
* 退款
*
* @throws AlipayApiException
*/
@RequestMapping("/alipay/alipayRefund")
public void alipayRefund(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {
String outTradeNo = request.getParameter("outTradeNo");
String outRequestNo = request.getParameter("outRequestNo");
String refundAmount = request.getParameter("refundAmount");
/** 调取数据 */
// String outTradeNo = "15382028806591197";
String refundReason = "用户不想购买";
// refundAmount = 1;
// outRequestNo = "22";
String refund = alipayService.refund(outTradeNo, refundReason, Integer.parseInt(refundAmount), outRequestNo);
System.out.println(refund);
AppFrameworkUtil.renderJSON(response, refund);
}
/**
* 退款查询
*
* @throws AlipayApiException
*/
@RequestMapping("/alipay/refundQuery")
public void refundQuery(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {
/** 调取数据 */
String outTradeNo = "13123";
String outRequestNo = "2";
String refund = alipayService.refundQuery(outTradeNo, outRequestNo);
AppFrameworkUtil.renderJSON(response, refund);
}
/**
* 交易关闭
*
* @throws AlipayApiException
*/
@RequestMapping("/alipay/alipayclose")
public void alipaycolse(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {
/** 调取数据 */
String outTradeNo = "13123";
String close = alipayService.close(outTradeNo);
AppFrameworkUtil.renderJSON(response, close);
}
}
controller里getAppPagePay是app订单支付,里面写死的是测试数据,如果正式用,可以当参数传进来。
演示app 订单支付,因为app订单支付会跳转到支付宝进行登录支付,如果没有监测到支付宝应用,则用网页版的支付宝进行支付,会比较方便。
调用上面的/alipayTest.do接口会跳转到html/alipay.html页面
alipay.html代码如下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script th:src="@{${ctx} + '/js/jquery/jquery-3.2.1.min.js'}"></script>
<script th:src="@{${ctx} + '/js/common/common.js'}"></script>
<script>
$(function(){
let url = "http://127.0.0.1:8082/alipay/getAppPagePay";
let params = {}
let result = getData(params, url);
console.log(result)
$("#alipay").html(result.data);
})
function getData(dataArr, url){
let results = null;
$.ajax({
url:url,
data:JSON.stringify(dataArr),
contentType:'application/json',
dataType:'json',
async:false,
type:'post',
beforeSend: function(request) {
if(!booleanEmpty(localStorage.getItem("token"))){
request.setRequestHeader("token", localStorage.getItem("token"));
}
},
success:function(result){
if("403" == result.result_code){
alert(result.result_msg);
window.location.href = $("#rootPath").val() + "/user/loginPage.do"
} else{
results = result.data;
}
},
complete:function (){ //在数据加载完成之后,要删除掉 正在加载的dom
}
});
return results;
};
</script>
</head>
<body>
<div id="alipay"></div>
</body>
</html>
可以看到,一进来这个页面会请求app订单支付接口,那个接口会返回一个form表单,并提交给支付宝进行支付,那个form表单的html放到#alipay div中便会自动执行跳转.
启动项目,访问http://127.0.0.1:8082/alipayTest.do

如图,电脑访问跳转到了上图页面,点击继续浏览器付款,登录沙箱买家账号,输入支付密码即可

点击确认付款,输入密码

几秒钟后会跳转回AlipayConfig里面设置的http:www.zhaohy.org.cn

至此,整个支付过程已经完成~
网友评论