前言
这篇博客主要介绍如何在Java web项目中集成支付宝的电脑支付接口(会稍微介绍一下服务器集成APP支付接口)。目前支付宝接口更新很快,在博主查找资料的时候,很多都是即时到账接口,APP支付则是移动支付接口等,所以想结合现在的电脑支付接口写一篇博文。如果项目要正式接入支付宝接口的话,是要企业与支付宝创建应用以及签约获取APPID等等的,如果我们只是个人想要学习或者测试的话,可以使用沙箱环境,不需要创建应用和签约,默认有很多应用!!正式环境的开发顺序是:创建应用—签约(电脑支付、APP支付、当面付、手机网站支付等等都需要单独签约!!)
配置沙箱环境
一、如果你是一个新手小白想要在项目中接入支付宝接口,首先你要做的是,进入支付宝官网开放平台。点击“快速开发”下的“开发接入”,跳转到新页面后点击“开发服务”下的“沙箱”。
二、新页面就是支付宝配置沙箱环境的文档以及使用说明,这里告诉我们沙箱环境默认给了我们一个APPID,需要我们自己配置RSA2(SHA256)的应用公钥,需要先下载支付宝生成秘钥的工具,如果是RSA2签名格式的话,记住要生成2048位的!!不要被示例图给迷惑了,当初博主就是这里弄错了!生成之后,进入沙箱应用,上传刚刚生成的应用公钥,上传成功后会生成支付宝公钥,应用私钥以及支付宝公钥会在代码配置中用到。如需要更改秘钥,使用下载的工具重新生成再上传即可!上传应用公钥并获取支付宝公钥,沙箱环境与链接中的示例图略有不同!
导入支付宝电脑支付的demo
一、在沙箱应用的链接中,点击最下面的功能中的电脑网站支付,选择左侧SDK&DEMO的菜单项,下载Java版的demo。
二、解压刚刚下载的demo,导入到eclipse中,目录结构如下图
三、修改AlipayConfig.java文件,记住是商户私钥和支付宝公钥!不要写成应用公钥!应用私钥即商户私钥!
这里的notify_url和return_url改成自己项目要返回页面的地址,由于是沙箱环境,所以支付宝网关也有修改。return_url是指付款成功之后返回给用户查看的界面,如付款成功之后返回到商品详情或者网站首页等等。notify_url则是支付包与服务器交互的页面,用户看不到,支付成功以notify_url返回的参数或者查询订单返回的参数为准。电脑网站支付快速接入。
四、修改配置成功之后,运行项目。
页面如下:
1.
2.
3.使用沙箱应用下面的沙箱账号里的买家账号登录,付款!钱会直接打到卖家账户中!这里面的钱可以自己手动添加,很有满足感 !!!!瞬间变富婆啊!!如果想用二维码支付,则到沙箱应用中扫描二维码下载沙箱版的支付宝,再用沙箱的买家账号登录就可以付款了!目前支持安卓版。
4.由于博主并没有写页面,使用的是支付宝默认的,所以返回的是一串json数据。
5.沙箱调试常见的错误如下图,如果报的错误不在这里面,请自行百度!
到这里如果能够成功付款或者查询订单等等,就可以看出我们的配置是没有问题的!接下来就要与我们的Java web项目整合并且存订单数据到数据库中!
整合接口到Java web项目
一、博主的框架是公司同事搭的SSM框架,但是与我在网上看的也有点不太一样,不过没关系,整合起来就那么几个文件。首先把上面那个demo里的Alipayconfig.java放在项目中(目录随项目而定),然后导入alipay-sdk-javaXXX.jar、commons-logging-1.1.1.jar这两个jar包到WebContent\WEB-INF\lib中,(具体路径随项目不同而改变)。
二、写支付接口。这里面可以对自己项目中的订单表进行操作,先增加一条订单,但是状态为未付款。然后调用支付宝付款接口。
/**
* 获取订单数据接口
* @param request
* @param response
* @throws AlipayApiException
* @throws IOException
*/
@RequestMapping("viewOrder")
public void viewOrder(HttpServletRequest req, Model mod, HttpServletResponse rep,
@RequestParam(value = "goodId", required = true)Integer goodId) throws AlipayApiException, IOException{
CommonResponse cr = new CommonResponse();
User cu = ViewSessionManager.getUserSession();
if(cu == null){
cr.setMessage("未登录");
cr.setData(null);
cr.setCode(3109);
}
OrderInfo param = new OrderInfo();
param.setGoodId(goodId);
payService.alipayOrder(cu, param);
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_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 = param.getTradeCode();
String total_amount = param.getMoney().toString();
String subject = param.getSubject();
String body = param.getRemark();
alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
+ "\"total_amount\":\""+ total_amount +"\","
+ "\"subject\":\""+ subject +"\","
+ "\"body\":\""+ body +"\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
String result = alipayClient.pageExecute(alipayRequest).getBody();
rep.setContentType("text/html;charset=" + AlipayConfig.charset);
rep.getWriter().write(result);
rep.getWriter().flush();
rep.getWriter().close();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
三、写同步通知return_url接口。这里面可以更改订单状态,但是不以这个为准(若网速太卡或者用户付完款关掉页面,则不会跳到这个接口,所以订单状态可能就不会更改)
/**
* 回调路径return_url
* @param request
* @param response
* @throws AlipayApiException
* @throws UnsupportedEncodingException
*/
@RequestMapping("return_url.view")
public String returnUrl(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException, UnsupportedEncodingException{
Map<String,String> params = new HashMap<String,String>();
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);
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");
String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
request.setAttribute("out_trade_no", out_trade_no);
request.setAttribute("trade_no", trade_no);
request.setAttribute("total_amount", total_amount);
log.info("订单处理:系统订单号" + out_trade_no + "支付宝交易号:" + trade_no);
OrderInfo order = payService.findOneByTradeCode(out_trade_no);
if(order == null){
signVerified = false;
request.setAttribute("signVerified", signVerified);
request.setAttribute("reason", "商户订单号不存在");
log.error("系统订单:"+ out_trade_no + "不存在。");
}else{
if(!order.getMoney().toString().equals(total_amount)){
signVerified = false;
request.setAttribute("signVerified", signVerified);
request.setAttribute("reason", "付款金额不对");
return "notify_url";
}
if(order.getTradeStatus() == 1){
log.info("系统订单:"+ out_trade_no + "无需重复处理。");
}else{
order.setTradeStatus(1);
Date payedAt = new Date();
order.setTransactionId(trade_no);
order.setPayedAt(payedAt);
payService.payOrder(order);
log.info("系统订单:"+ out_trade_no + "成功支付。");
}
}
}else{
request.setAttribute("reason", "验签失败");
}
request.setAttribute("signVerified", signVerified);
return "return_url";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
四、异步通知notify_url接口,与上面return_url的几乎相同,只是最后返回的页面改为notify_url,还有一点需要注意的是:必须保证服务器异步通知页面(notify_url)上无任何字符,如空格、HTML标签、开发系统自带抛出的异常提示信息等
电脑网站支付结果异步通知
数据库中订单状态的更新以这个接口中的为准!
五、查询订单接口。这里的返回类型CommonResponse 是我们公司自己的,你们改成自己的返回类型就好.我们这个是ajax调用接口,然后将orderString的数据返回,实际上是json数据。
/**
* 支付宝交易查询接口
* @param request
* @param response
* @throws UnsupportedEncodingException
* @throws AlipayApiException
*/
@RequestMapping("queryOrder")
@ResponseBody
public CommonResponse queryOrder(HttpServletRequest req, Model mod, HttpServletResponse rep,
@RequestParam(value = "tradeCode", required = true)String tradeCode,
@RequestParam(value = "tradeNo", required = true)String tradeNo) throws UnsupportedEncodingException, AlipayApiException{
CommonResponse cr = new CommonResponse();
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("{" +
" \"out_trade_no\":\""+tradeCode+"\"," +
" \"trade_no\":\""+tradeNo+"\"" +
" }");
String orderString = null;
try {
AlipayTradeQueryResponse response = alipayClient.execute(request);
orderString = response.getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
cr.setData(orderString);
return cr;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
服务器端添加APP支付接口
与电脑支付接口类似,可以直接使用同一个jar包,不过在付款接口的入参里需要添加token。下面是部分代码。我相信你们足够聪明能够改成自己的!
CommonResponse cr = new CommonResponse()
Cache<String, User> apiAccessTokenCache = cacheManager.getCache("apiAccessTokenCache")
User cu = apiAccessTokenCache.get(token)
if(cu == null){
cr.setMessage("token值不对或已失效")
cr.setData(null)
cr.setCode(3109)
return cr
}
//系统下单
OrderInfo param = new OrderInfo()
param.setGoodId(goodId)
payService.order(cu, param)
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type)
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest()
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel()
String time = Long.toString(System.currentTimeMillis()/1000)
model.setBody(param.getRemark())
model.setSubject(param.getSubject())
model.setOutTradeNo(param.getTradeCode())
model.setTimeoutExpress(time)
model.setTotalAmount(param.getMoney()+"")
model.setProductCode("QUICK_MSECURITY_PAY")
request.setBizModel(model)
request.setReturnUrl(AlipayConfig.return_url)
request.setNotifyUrl(AlipayConfig.notify_url)
String orderString = null
try {
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request)
orderString = response.getBody()
} catch (AlipayApiException e) {
e.printStackTrace()
}
cr.setData(orderString)
return cr
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
转换成正式环境
需要修改配置文件中的APPID,支付宝公钥,应用私钥,以及支付宝网关!有时改了网关之后跳转的还是沙箱环境的网关,需要clean一下服务器(我的是Tomcat)
结语
上面就是博主总结的Java web项目集成支付宝电脑支付接口!希望这一篇博文能够解决你的问题,祝好运!如果有疑问可以给我留言,看到了如果我会的问题就会回答!☺☺
注:此篇文章转自一位女前辈
地址:http://blog.csdn.net/Amo_lt/article/details/77435545
文章稍有改动。