想在项目里测试一下第三方支付,结果文档查起来东拼西凑的,教程也很多已经过时了,
这里把我的实现过程总结一下,方便各位查阅
以下操作基于的开发环境是windows10+tomcat8+jdk1.8
登陆进入蚂蚁金服开放平台
服务类型选择为自研开发者
蚂蚁沙箱环境(Beta)是协助开发者进行接口功能开发及主要功能联调的模拟环境,在沙箱完成接口开发及主要功能调试后,请务必在蚂蚁正式环境进行完整的功能验收测试。所有返回码及业务逻辑以正式环境为准。
开发中心——>研发服务——>沙箱应用
系统已经自动为你创建一个应用,在基础信息中可以看到应用信息。
应用私钥需填写到代码中供签名时使用,应用公钥需提供给支付宝账号管理者上传到支付宝开放平台
支付宝提供生成工具
下载
解压运行“RSA签名验签工具.bat”
根据开发语言选择密钥格式和密钥长度,新建应用请务必使用2048位
点击“生成密钥”——>复制公钥
设置应用公钥——>复制——>保存
下载手机网站支付demo
下载
解压后将jar包放入自己的项目lib中并build path
将相关类和jsp页面导入项目
修改AlipayConfig
package com.alipay.config;
public class AlipayConfig {
// 商户appid
public static String APPID = "你的沙箱APPID";
// 私钥 pkcs8格式的
public static String RSA_PRIVATE_KEY = "第三步中生成的私钥";
// 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "http://localhost:8080/alipay.trade.wap.pay-JAVA-UTF-8/notify_url.jsp";
// 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
public static String return_url = "http://localhost:8080/alipay.trade.wap.pay-JAVA-UTF-8/return_url.jsp";
// 请求网关地址
public static String URL = "https://openapi.alipaydev.com/gateway.do";
// 编码
public static String CHARSET = "UTF-8";
// 返回格式
public static String FORMAT = "json";
// 支付宝公钥
public static String ALIPAY_PUBLIC_KEY = "第三步中生成的公钥";
// 日志记录目录
public static String log_path = "F:\\log";
// RSA2
public static String SIGNTYPE = "RSA2";
}
请求网关地址修改为https://openapi.alipaydev.com/gateway.do
log_path修改为本地的已存在的文件夹
参数列表
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.config.AlipayConfig;
public class PayServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//初始化
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL,
AlipayConfig.APPID,
AlipayConfig.RSA_PRIVATE_KEY,
AlipayConfig.FORMAT,
AlipayConfig.CHARSET,
AlipayConfig.ALIPAY_PUBLIC_KEY,
AlipayConfig.SIGNTYPE);
//创建API对应的request
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
//在公共参数中设置回跳和通知地址
alipayRequest.setReturnUrl(AlipayConfig.return_url);
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
//填充业务参数
//必填
//商户订单号,需保证在商户端不重复
String out_trade_no = "20181037";
//销售产品码,与支付宝签约的产品码名称。目前仅支持FAST_INSTANT_TRADE_PAY
String product_code = "FAST_INSTANT_TRADE_PAY";
//订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]。
String total_amount = "1.23";
//订单标题
String subject = "支付宝测试";
//选填
//商品描述,可空
String body = "商品描述";
alipayRequest.setBizContent("{" +
"\"out_trade_no\":\"" + out_trade_no + "\"," +
"\"product_code\":\"" + product_code + "\"," +
"\"total_amount\":\"" + total_amount + "\"," +
"\"subject\":\"" + subject + "\"," +
"\"body\":\"" + body + "\"}" );
//请求
String form = "";
try {
form = alipayClient.pageExecute(alipayRequest).getBody();//调用SDK生成表单
} catch (AlipayApiException e) {
e.printStackTrace();
response.getWriter().write("捕获异常出错");
response.getWriter().flush();
response.getWriter().close();
}
response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
response.getWriter().write(form);//直接将完整的表单html输出到页面
response.getWriter().flush();
response.getWriter().close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
访问http://localhost:8080/你的项目名/PayServlet
下载
将下载的apk在手机上安装,这是一个沙箱版的支付宝app,用来对第六步的二维码进行扫码付款
使用沙箱账号登陆,这是一个模拟账号。
// 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "";
// 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
public static String return_url = "";
在AlipayConfig.java中的这两个路径,return_url是第六步支付成功之后,在五秒后跳转的地址
notify_url是支付宝异步通知的地址,这两个地址都要求外网可访问,由于是本地测试,这里可以免费内网穿透
使用赠送域名代替localhost:8080并按照你项目的地址填入两个url即可
notify_url的简单示例
package servlet;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.blowbb.bookstore.order.service.OrderService;
import com.alipay.api.internal.util.AlipaySignature;
public class NotifyServlet extends HttpServlet {
private OrderService service=new OrderService();
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Map map = 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] + ",";
}
map.put(name, valueStr);
}
//调用SDK验证签名
boolean signVerified = false;
try {
signVerified = AlipaySignature.rsaCheckV1(
map,
AlipayConfig.ALIPAY_PUBLIC_KEY,
AlipayConfig.CHARSET,
AlipayConfig.SIGNTYPE);
}
catch (Exception e)
{
e.printStackTrace();
}
if (signVerified)
{
System.out.println(map.toString());
String out_trade_no=map.get("out_trade_no");
if ("TRADE_SUCCESS".equals(map.get("trade_status"))) {
//交易成功
System.out.println("交易成功");
//交易逻辑
service.buy(out_trade_no);
}
}
}
}
return_url随便写个jsp就行