需要实现支付宝支付功能,首先需要到支付宝开放平台(https://open.alipay.com/dev/workspace),去开通自己的沙箱账号。
然后配置秘钥和私钥,具体操作步骤参照支付宝沙箱支付开发文档,文档很详细,按照文档操作就行。
2.1 引入依赖
com.alipay.sdk
alipay-sdk-java
3.0.0
2.2 配置类
需要根据自己的沙箱,更改配置类相关属性。
public class AlipayConfig {
// 应用ID,APPID,收款账号既是的APPID对应支付宝账号,开发时使用沙箱提供的APPID,生产环境改成自己的APPID
public static String APP_ID = ""; //测试
// 商户私钥,PKCS8格式RSA2私钥
public static String APP_PRIVATE_KEY = "";
// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
public static String ALIPAY_PUBLIC_KEY = "";
// 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "http://localhost:8188/notifyUrl";
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问(其实就是支付成功后返回的页面)
public static String return_url = "http://localhost:8188/returnUrl";
// 签名方式
public static String sign_type = "RSA2";
// 字符编码格式
public static String CHARSET = "UTF-8";
// 支付宝网关,这是沙箱的网关
public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do"; //测试
// 支付宝网关
public static String log_path = "D:\\";
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
* @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();
}
}
}
}
}
支付业务代码
public class PayController {
@ResponseBody
@RequestMapping("/payOrder")
public String payController(HttpServletRequest request, HttpServletResponse response, String id) throws IOException {
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.APP_ID,
AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);
//设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(AlipayConfig.return_url);
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
//商户订单号,商户网站订单系统中唯一订单号,必填
String out_trade_no = ;
//付款金额,必填
String total_amount = ;
//订单名称,必填
String subject =;
//商品描述,可空
String body = "测试";
// 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天
// (1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
String timeout_express = "1c";
alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
+ "\"total_amount\":\"" + total_amount + "\","
+ "\"subject\":\"" + subject + "\","
+ "\"body\":\"" + body + "\","
+ "\"timeout_express\":\"" + timeout_express + "\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//请求
String url = "";
try {
url = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
response.getWriter().write(url); // 直接将完整的表单html输出到页面
response.getWriter().flush();
response.getWriter().close();
} catch (AlipayApiException e) {
e.printStackTrace();
}
System.out.println(url);
return url;
}
/**
* 同步跳转
*
* @param request
* @throws Exception
*/
@ResponseBody
@RequestMapping("/returnUrl")
public ModelAndView returnUrl(HttpServletRequest request) throws Exception {
ModelAndView mav = new ModelAndView();
// 获取支付宝GET过来反馈信息(官方固定代码)
Map params = new HashMap();
Map requestParams = request.getParameterMap();
for (Iterator 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] + ",";
}
params.put(name, valueStr);
}
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.sign_type); // 调用SDK验证签名
// 返回界面
if (signVerified) {
System.out.println("前往支付成功页面");
mav.setViewName("redirect:/myOrder");
} else {
System.out.println("前往支付失败页面");
mav.setViewName("redirect:/myOrder");
}
return mav;
}
public ModelAndView toRefund(HttpServletResponse response, String id) throws IOException {
ModelAndView mv=new ModelAndView();
// 设置编码格式
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.APP_ID,
AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);
//设置请求参数
AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
//商户订单号,必填
String out_trade_no = ;
//需要退款的金额,该金额不能大于订单金额,必填
String refund_amount = ;
//标识一次退款请求,同一笔交易多次退款需要保证唯一。如需部分退款,则此参数必传;不传该参数则代表全额退款
String out_request_no = new String(UUID.randomUUID().toString());
// 字符转义很重要
alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
+ "\"refund_amount\":\"" + refund_amount + "\","
+ "\"out_request_no\":\"" + out_request_no + "\"}");
//请求
AlipayTradeRefundResponse result = null;
try {
result = alipayClient.execute(alipayRequest);
} catch (AlipayApiException e) {
e.printStackTrace();
}
//输出
out.println(result);
if (result.isSuccess()) {
System.out.println("退款成功");
mv.setViewName("redirect:/myOrder");
}else {
System.out.println("退款失败");
mv.setViewName("error");
}
return mv;
}
注意:
配置文件需要改成自己的沙箱相关内容,本人实测,只要公钥和私钥配置没有问题,基本都不会有错,如有问题,请评论区提出供大家一起学习探讨。