目录
第三方支付宝支付介绍
第二步配置秘钥
配置搭建环境和SDK介绍
支付宝支付编码实现解析
获取订单信息
统一下单API的实现
异步通知
同步通知
测试
第三方支付宝支付介绍
第三方支付平台
选择服务商
- 支付宝
- 财付通
- 银联商务
- 块钱
- ... ...
沙箱环境
又称沙盘,为了开放与调试所提供的环境,它与生产环境互相隔离,但具有生产环境几乎完全相同的功能。
蚂蚁金服开放平台——开发者中心
提供的调试产品
- APP支付
- 当面支付
- 电脑网站支付。
接入流程
- 创建应用并获取APPID
- 配置秘钥
- 搭建和配置开发环境
- 使用SDK(支付宝提供的)
- 线上验收
第二步配置秘钥
第一步:创建应用并获取APPID
准备工作
- 支付宝账号
- 必须在开放平台完成实名认证才能使用开放平台服务
生成应用唯一标识(APPID)
- 创建登录应用
- 提交审核
开发阶段可使用默认的沙箱应用
- 开发者中心——研发服务——沙箱应用
- 每个应用对应一个APPID
第一次使用需要完善信息。
完善后,再打开
“第三方应用”是服务商,所以选择“自用型应用”。点击“创建”后出现页面
这个时候应用不能用。需要提交审核,上线后才能用。所以要使用“沙箱应用”,不需要这些步骤。
“功能列表”默认有三条,可以删除添加。添加后不一定能用。后面有个选项“是否需要签约”,如果是“需签约”,就必须签约后才能使用。
基础环境中
应用网关:
授权回调地址:支付成功后,会回调一个地址,第三方商户网站提供的一个地址,支付宝会把一些状态返回给改地址。
那么要使用沙箱应用该怎么打开那?
进入页面
沙箱账号里面有个商家信息,买家信息。
第二步:配置密钥
1.生成RSA密钥对
- 应用私钥
- 应用公钥
2.上传应用公钥
3.平台自动生成支付宝公钥
3.填写内容
这个密钥怎么产生。是支付宝提供一键生成工具便于开发者生成一对RSA密钥,可通过下方链接下载密钥生成工具
点击“查看密钥生成”下载完后,打开“RSA签名验签工具.bat”
把“商户应用公钥”填到上面那个“应用公钥”里面。确定后,出现以下界面
这个支付宝公钥也是后面所需要的。
配置搭建环境和SDK介绍
第三步:搭建和配置开发环境
下载SDK
- https://docs.open.alipay.com/54/103419
- 接口调用属性配置
接口属性配置查看
第四步:SDK的使用
SDK包说明:
- alipay-sdk-java*.jar:支付宝SDK编译文件jar
- alipay-sdk-java*-source.jar:支付宝SDK源码文件.jar
- commons-logging-1.1.1.jar:SDK依赖的日志jar
- commons-logging-1.1.1-sources.jar:SDK依赖的日志源码jar
核心API:
- AlipayClient:封装签名与验证
- AlipayTradePagePayRequest:支付请求类
- AlipayTradePagePayModel:封装请求支付信息
服务器异步通知
- notify_url
- 支付宝使用POST方式,保证99.999999%的通知到达率
页面跳转同步通知
- return_url
- 支付宝使用GET方式,是由客户浏览器触发的一个通知,不保证其到达率。
支付宝支付编码实现解析
看文档“电脑网站支付”>“快速接入”
https://docs.open.alipay.com/270/105899/
获取订单信息
显示所有订单信息
/**
* 确认订单信息
*
* @param orderNo
* 订单ID
* @return
*/
@RequestMapping(value = "/prepay/{orderNo}", method = RequestMethod.GET)
@ResponseBody
public Dto prePay(@PathVariable String orderNo,HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "*");
try {
QgOrder order = qgAlipayService.loadQgOrderByOrderNo(orderNo);
if (!EmptyUtils.isEmpty(order)) {
Map<String,Object> result=new HashMap<String, Object>();
result.put("orderNo", orderNo);
result.put("goodsId", order.getGoodsId());
result.put("count", order.getNum());
result.put("payAmount", order.getAmount());
return DtoUtil.returnSuccess("获取订单信息成功", result);
}else
return DtoUtil.returnFail("订单不存在","fail");
} catch (Exception e) {
e.printStackTrace();
return DtoUtil.returnFail("获取订单信息失败","fail");
}
}
统一下单API的实现
/**
* 客户端提交订单支付请求,对该API的返回结果不用处理,浏览器将自动跳转至支付宝。即例子中的alipay.trade.page.pay.jsp
*
* @param WIDout_trade_no
* 商户订单号,商户网站订单系统中唯一订单号,必填
* @param WIDsubject
* 订单名称,必填
* @param WIDtotal_amount
* 付款金额,必填
*/
@RequestMapping(value = "/pay", method = RequestMethod.POST)
public void pay(
@RequestParam String WIDout_trade_no,
@RequestParam String WIDsubject,
@RequestParam String WIDtotal_amount, HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "*");
String product_code = "FAST_INSTANT_TRADE_PAY";
// SDK 公共请求类,包含公共请求参数,以及封装了签名与验签,开发者无需关注签名与验签
// 调用RSA签名方式
AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(),
alipayConfig.getAppID(), alipayConfig.getRsaPrivateKey(),
alipayConfig.getFormat(), alipayConfig.getCharset(),
alipayConfig.getAlipayPublicKey(), alipayConfig.getSignType());
AlipayTradePagePayRequest alipay_request = new AlipayTradePagePayRequest();
// 封装请求支付信息
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo(WIDout_trade_no);
model.setSubject(WIDsubject);
model.setTotalAmount(WIDtotal_amount);
model.setProductCode(product_code);
alipay_request.setBizModel(model);
// 设置异步通知地址
alipay_request.setNotifyUrl(alipayConfig.getNotifyUrl());
// 设置同步地址
alipay_request.setReturnUrl(alipayConfig.getReturnUrl());
// form表单生产
String form = "";
try {
// 调用SDK生成表单
form = client.pageExecute(alipay_request).getBody();
response.setContentType("text/html;charset="
+ alipayConfig.getCharset());
response.getWriter().write(form);// 直接将完整的表单html输出到页面
response.getWriter().flush();
response.getWriter().close();
} catch (AlipayApiException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
异步通知
/**
* 导步通知,跟踪支付状态变更,即例子中的notify_url.jsp
* @param request
* @param response
*/
@RequestMapping(value = "/notify", method = RequestMethod.POST)
public void trackPaymentStatus(HttpServletRequest request,
HttpServletResponse response) {
try {
Map<String, Object> params = new HashMap<String, Object>();
// 获取支付宝POST过来反馈信息
Map requestParams = request.getParameterMap();
request.setCharacterEncoding("UTF-8");
// 商户订单号
String out_trade_no = request.getParameter("out_trade_no");
// 支付宝交易号
String trade_no = request.getParameter("trade_no");
// 交易状态
String trade_status = request.getParameter("trade_status");
boolean verify_result = qgAlipayService.asyncVerifyResult(requestParams);
if (verify_result) {// 验证成功
response.getWriter().println("success"); // 请不要修改或删除
} else {// 验证失败
response.getWriter().println("fail");
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error(e.getMessage());
} catch (AlipayApiException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error(e.getMessage());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error(e.getMessage());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error(e.getMessage());
}
}
同步通知
/**
* 支付宝页面跳转同步通知页面
*/
@RequestMapping(value = "/return", method = RequestMethod.GET)
public void callback(HttpServletRequest request,
HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "*");
try {
//获取支付宝GET过来反馈信息
Map<String,String> params = new HashMap<String,String>();
request.setCharacterEncoding("UTF-8");
Map requestParams = request.getParameterMap();
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
//商户订单号
String out_trade_no = request.getParameter("out_trade_no");
//支付宝交易号
String trade_no = request.getParameter("trade_no");
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
//计算得出通知验证结果
//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
boolean verify_result = qgAlipayService.syncVerifyResult(requestParams);
if(verify_result){//验证成功
if(!qgAlipayService.processed(out_trade_no)){
qgAlipayService.insertTrade(out_trade_no, trade_no);
}
String id=qgAlipayService.loadQgOrderByOrderNo(out_trade_no).getId().toString();
//提示支付成功
response.sendRedirect(String.format(alipayConfig.getPaymentSuccessUrl(), out_trade_no,id));
}else{
//提示支付失败
response.sendRedirect(alipayConfig.getPaymentFailureUrl());
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error(e.getMessage());
} catch (AlipayApiException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error(e.getMessage());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error(e.getMessage());
}
}
测试
依赖项目shop-common,shop-goods,shop-order,shop-order,shop-pre。
- 访问toPay.html,注意同一个订单编号只能操作一次。点击按钮“去结算”,
- 所在页面choosePay.html,确认订单信息(/api/prepay/{orderNo}),选择“支付宝”点击“立即支付”。执行方法提交订单信息(/api/pay)
- 跳转到支付宝支付页面(支付宝官方提供的页面),可以用扫一扫进行支付,也可以用账户支付,这个账户可以用蚂蚁金服沙箱账号来支付。
- 支付成功后,跳转到我们设置的一个支付成功的页面
alipay.paymentSuccessUrl=http://www.qg.com/success.html?orderNo=%s&id=%sd
第五步:线上验收
在沙箱环境完成功能调试后,必须将支付宝网关,appid,应用私钥,支付宝公钥修改成正式环境的配置,并在蚂蚁正式环境进行完整的功能验收测试。
完善应用基本信息
- 应用名称
- 图标
- 签约支付产品
- 开发配置
等待审核