Java支付宝扫码支付[新]
Java支付宝扫码支付[新]
支付宝老版本的 Web 端扫码支付产品为即时到账,更新到新版后现在的产品为电脑网站支付
更多精彩
- 更多技术博客,请移步 asing1elife’s blog
官网
准备数据
- 电脑网站支付 应用需要在开发者页面端进行申请和签约
- 应用签约成功之后需要获取以下信息
- app_id: 签约成功的应用唯一标识
- app_private_key: 通过 RSA 密钥生成的应用私钥,由开发者自己通过签名软件生成[支付宝提供]
- alipay_public_key: 通过应用私钥和公钥生成的支付宝公钥,由支付宝自动生成
下载 Java 版 SDK
- 前往 电脑网站支付 SDK 获取 下载 Java 的 SDK
- 该 SDK 目前不支持 Maven 方式引入,只能通过本地引入
- 正常开发模式只需要引入 alipay-sdk-java-3.0.0.jar 即可
获取支付宝客户端
- 支付宝客户端是调用所有接口的前置条件,所以应该放置在顶层父类做一次初始化
-
SOPConstants.ALI_PAY_SEND_URL
是该支付方式的统一请求接口,值为https://openapi.alipay.com/gateway.do
public class AliCoreServiceImpl extends OrderCoreServiceImpl { // 参数返回格式 private static final String ALI_PAY_FORMAT = "json"; // 编码集,支持 GBK/UTF-8 protected static final String ALI_PAY_CHARSET = "utf-8"; // 商户生成签名字符串所使用的签名算法类型,目前支持 RSA2/RSA ,推荐使用 RSA2 protected static final String ALI_PAY_SIGN_TYPE = "RSA2"; // 订单支付成功状态 protected static final String TRADE_STATUS_SUCCESS = "TRADE_SUCCESS"; // 订单支付结束状态 protected static final String TRADE_STATUS_FINISHED = "TRADE_FINISHED"; // 支付宝客户端 protected static AlipayClient alipayClient; static { // 初始化支付宝客户端 alipayClient = new DefaultAlipayClient( SOPConstants.ALI_PAY_SEND_URL, SOPConstants.ALI_PAY_APP_ID, SOPConstants.ALI_PAY_PRIVATE_KEY, ALI_PAY_FORMAT, ALI_PAY_CHARSET, SOPConstants.ALI_PAY_PUBLIC_KEY, ALI_PAY_SIGN_TYPE); } }
发起支付宝付款页面请求
- 新版的扫码支付对请求参数和响应参数都做了封装,只需要传入对应参数值即可
-
SOPConstants.ALI_PAY_RETURN_URL
是支付宝付款成功需要的同步回执地址 -
SOPConstants.ALI_PAY_NOTIFY_URL
是支付宝付款成功需要的异步回执地址 - 以上两个地址都需要能够外网访问
- 该请求方式是通过拼接请求使用 iframe 获取支付宝的付款二维码
- 通过客户端发起请求时不使用一般的
pageExecute()
而使用sdkExecute()
-
sdkExecute()
获取的是请求之后的参数值,所以还需要拼接请求地址 -
SOPConstants.ALI_PAY_SEND_URL
是支付请求地址
- 通过客户端发起请求时不使用一般的
public class AliPayServiceImpl extends AliCoreServiceImpl { public String aliPay(Long orderId) { // 创建统一下单请求 AlipayTradePagePayRequest payRequest = new AlipayTradePagePayRequest(); payRequest.setReturnUrl(SOPConstants.ALI_PAY_RETURN_URL); payRequest.setNotifyUrl(SOPConstants.ALI_PAY_NOTIFY_URL); // 将订单详情传入业务请求参数中 payRequest.setBizModel(generateOrderInfo(orderId)); String body = null; try { body = alipayClient.sdkExecute(payRequest).getBody(); } catch (AlipayApiException e) { logger.error("订单" + orderId + "获取支付宝付款界面失败!"); } if (body == null) { logger.error("订单" + orderId + "未成功获取支付宝付款界面!"); } return SOPConstants.ALI_PAY_SEND_URL + "?" + body; } private AlipayTradePagePayModel generateOrderInfo(Long orderId) { // 获取订单信息 OrderDTO order = orderManageService.getOrder(orderId); AlipayTradePagePayModel model = new AlipayTradePagePayModel(); model.setOutTradeNo(order.getCode()); model.setProductCode("FAST_INSTANT_TRADE_PAY"); model.setTotalAmount(String.valueOf(order.getPrice())); model.setSubject("实训在线-" + order.getName()); model.setBody("实训在线-" + order.getName()); // 二维码获取方式为模式4,最简洁模式,只有二维码 model.setQrPayMode("4"); model.setQrcodeWidth(240L); return model; } }
- 控制层调用请求接口获取完整请求地址
@RequestMapping("/ali/{orderId}") public String ali(Model model, @PathVariable String orderId) { model.addAttribute("order", orderManageService.getOrder(IdEncoder.decodeId(orderId))); model.addAttribute("orderType", OrderPay.aliPay.getCode()); model.addAttribute("aliPayUrl", aliPayService.aliPay(IdEncoder.decodeId(orderId))); return "/order/pay/ali"; }
- 上述方法中拼接完整的二维码请求地址可以直接放置到 iframe 的 src 属性中
- 如果页面没有成功获取,可根据报错信息前往 验签失败错误排查 进行解决
<iframe id="aliPayFrame" src="${aliPayUrl}" frameborder="0"></iframe>
接收同步回执
- 该地址需要与之前初始化客户端时提交给支付宝的同步回执地址保持一致
- 回执地址不能有任何多余参数
@RequestMapping("/ali/return") public String aliReturn(HttpServletRequest request) { aliNotifyService.aliReturn(request); return null; }
- 新版的同步回执中不会携带订单的状态信息,所以只能用做一般的信息接收,不能做为交易成功的依据
- 同步回执需要验签,但验签的方法支付宝已提供,即
AlipaySignature.rsaCheckV2()
- 同步回执需要验签,但验签的方法支付宝已提供,即
public void aliReturn(HttpServletRequest request) { // 订单号 String orderCode = request.getParameter("out_trade_no"); Boolean result = false; try { // 回执验签 result = AlipaySignature.rsaCheckV2(parameterToMap(request, false), SOPConstants.ALI_PAY_PUBLIC_KEY, ALI_PAY_CHARSET, ALI_PAY_SIGN_TYPE); } catch (AlipayApiException e) { logger.error("支付宝订单" + orderCode + "同步回执验签失败!", e); } if (result) { logger.info("支付宝订单" + orderCode + "同步回执接收成功!"); } else { logger.error("支付宝订单" + orderCode + "同步回执无效!"); } }
- 对同步回执中的响应参数验签之前,需要先将参数转化为 map 形式
private Map<String, String> parameterToMap(HttpServletRequest request, Boolean isNotify) { // 获取回执内容 Map requestParams = request.getParameterMap(); // 过滤回执内容 Map<String, String> params = Maps.newHashMap(); for (Object o : requestParams.keySet()) { String name = (String) o; 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] + ","; } if (isNotify) { params.put(name, valueStr); } else { try { params.put(name, new String(valueStr.getBytes("ISO-8859-1"), "utf-8")); } catch (UnsupportedEncodingException e) { logger.error("支付宝订单同步回执转码失败!", e); } } } return params; }
接收异步回执
- 该地址需要与之前初始化客户端时提交给支付宝的异步回执地址保持一致
- 回执地址不能携带任何参数
@RequestMapping(value = "/ali", method = RequestMethod.POST) @ResponseBody public String aliNotify(HttpServletRequest request) { return aliNotifyService.aliNotify(request); }
- 异步回执作为支付成功的依据,支付宝成功通知到本地后,需要明确告知支付宝交易已成功
- 交易成功后返回
success
即可 - 当订单支付成功后订单可以展现两种状态,TRADE_SUCCESS 或 TRADE_FINISHED
- 交易成功后返回
public String aliNotify(HttpServletRequest request) { // 订单号 String orderCode = request.getParameter("out_trade_no"); // 订单状态 String orderStatus = request.getParameter("trade_status"); boolean result = false; try { result = AlipaySignature.rsaCheckV2(parameterToMap(request, true), SOPConstants.ALI_PAY_PUBLIC_KEY, ALI_PAY_CHARSET, ALI_PAY_SIGN_TYPE); } catch (AlipayApiException e) { logger.error("支付宝订单" + orderCode + "异步回执验签失败,订单状态为:" + orderStatus + "!", e); } // 验签成功 if (result) { // 订单已支付 if (orderStatus.equals(TRADE_STATUS_SUCCESS) || orderStatus.equals(TRADE_STATUS_FINISHED)) { // 更新订单状态 updateOrderInfo(orderCode, OrderPay.aliPay.getCode()); return "success"; } else { logger.error("支付宝订单" + orderCode + "未支付,订单状态为:" + orderStatus + "!"); return "fail"; } } else { logger.error("支付宝订单" + orderCode + "异步回执接收失败,订单状态为:" + orderStatus + "!"); return "fail"; } }
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java支付宝扫码支付[旧]
版权声明:本文首发 http://asing1elife.com ,转载请注明出处。 https://blog.csdn.net/asing1elife/article/details/82619972 Java支付宝扫码支付[旧] 在实际开发过程中,首先采用当面付模式进行开发,但没有成功,个人认为当面付更适合线下模式 之后改用即时到账模式才成功接入支付宝扫码支付功能 以下内容是基于即时到账模式开发 要使用支付宝即时到账接口,首先需要签约即时到账产品, 申请地址 审核进度通常需要1个工作日,但实际几小时即可 之后需要获取和设置如下关键信息 pid:2088621150311111 合作伙伴身份ID key:zrqyf6dfli7dvji4mmi4sw1111111111 MD5密钥 notify_url:http://127.0.0.1:8080/sop/order/notify/ali 异步通知回调地址 return_url:http://127.0.0.1:8080/sop/order/notify/ali/return 同步通知回调地址 更多精彩 更多技术博客,请移步 asing...
- 下一篇
Java支付宝订单查询
版权声明:本文首发 http://asing1elife.com ,转载请注明出处。 https://blog.csdn.net/asing1elife/article/details/82620005 Java支付宝订单查询 电脑网站支付成功后可通过支付宝接口主动查询订单结果 更多精彩 更多技术博客,请移步 asing1elife’s blog 前置条件 该方法基于 Java 支付宝扫码支付 (新) 实现 调用查询接口进行订单查询 public class AliQueryServiceImpl extends AliCoreServiceImpl { public Boolean getPayResult(Long orderId) { AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest(); queryRequest.setBizModel(generateOrderInfo(orderId)); AlipayTradeQueryResponse response = null; try { res...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果