网站建设常用模板下载,wordpress 虚机,营销策略国内外文献综述,网站如何注册域名前言 支付宝支付—沙箱环境使用支付宝支付-支付宝PC端扫码支付支付宝支付-手机浏览器H5支付支付宝支付-当面付之扫码支付「本文」 当面付包含两种支付方式#xff1a;商品条形码支付 扫码支付 经过前面两篇PC端扫码支付、手机H5支付#xff0c;我们可以看到一个共同的特点就… 前言 支付宝支付—沙箱环境使用支付宝支付-支付宝PC端扫码支付支付宝支付-手机浏览器H5支付支付宝支付-当面付之扫码支付「本文」 当面付包含两种支付方式商品条形码支付 扫码支付 经过前面两篇PC端扫码支付、手机H5支付我们可以看到一个共同的特点就是接口返回的都是一个Form表单然后交给提交执行然后调起支付。其中PC端提交Form表单后跳转至新的窗口进行支付而手机端H5支付则是唤起支付宝APP支付。 但是现在有这么个场景我不希望在PC端支付时跳转支付宝网页支付而是直接将二维码嵌入到系统当中用户直观看到的就是一个弹窗二维码然后用户拿支付宝扫码支付…这就是本文的当面付之扫码支付了。 废话不多说直接进入主题。 本文开发环境IDEA Tomcat8.5 支付宝沙箱环境 SpringBoot 补充调用沙箱环境接口需要安装沙箱环境下的支付宝APP不了解的小伙伴可以参考上方 支付宝支付—沙箱环境使用。 一、pom引入依赖 参数准备 引入支付宝支付依赖文件本文基于4.9.153.ALL版本及供参考 最新版本可去官方文档查阅。 !--alipay--dependency groupIdcom.alipay.sdk/groupId artifactIdalipay-sdk-java/artifactId version4.9.153.ALL/version/dependency 关于支付宝公钥、私钥、回调地址啥的就不再重复了不清楚的去看支付宝支付—沙箱环境使用。 配置可以单独创建一个类静态初始化参数AlipayConfig.java public class AlipayConfig { /** 商户appid **/ public static String APPID 201610170070; /** 私钥 pkcs8格式的 **/ public static String RSA_PRIVATE_KEY ; /** 服务器异步通知页面路径 需http://或者https://格式的完整路径不能加?id123这类自定义参数必须外网可以正常访问 **/ public static String notify_url http://ngrok.sscai.club/alipay_trade_wap_pay_java_utf_8_war_exploded/notify_url.jsp; /** 页面跳转同步通知页面路径 需http://或者https://格式的完整路径不能加?id123这类自定义参数必须外网可以正常访问 商户可以自定义同步跳转地址 **/ public static String return_url http://ngrok.sscai.club/alipay_trade_wap_pay_java_utf_8_war_exploded/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 /log; /** RSA2 **/ public static String SIGNTYPE RSA2; /** 商户门店编号「需要申请当面付」 **/ public static String STORE_ID 122211242;} 几个主要的参数 APPID 商户appidRSA_PRIVATE_KEY应用私钥ALIPAY_PUBLIC_KEY支付宝公钥「注意不是应用公钥」 这几个参数不清楚的可以看一下 沙箱环境使用或者看一下官方文档参数说明。 二、后端代码 还是之前的代码一个controller接口方法一个具体的实现方法「没有使用开源SDK」 Controller ApiOperation(value 获取支付宝支付二维码)public ResultAlipayResponse getAliPayQrCode(CurrentUser UserModel user, RequestBody AlipayOrderRequest alipayOrderRequest ) { /** 返回给前端的二维码内容 **/ String sHtmlText null; try { /** 判断是否已经存在订单根据自己业务的不同自行判断**/ if(!StringUtils.isNotBlank(alipayOrderRequest.getWidOutTradeNo())){ Orders ordersordersService.createOrder(user,alipayOrderRequest.getWidTotalFee(),alipayOrderRequest.getAppType()); alipayOrderRequest.setWidOutTradeNo(orders.getOrderId()); }else{ OrderResponse ordersordersService.searchOrderDetail(user,alipayOrderRequest.getWidOutTradeNo()); alipayOrderRequest.setWidTotalFee(orders.getAmount().toString()); } /** 这是主要的方法 **/ sHtmlText alipayService.alipayOrder(alipayOrderRequest); } catch (AlipayApiException e) { e.printStackTrace(); } AlipayResponse alipayResponse new AlipayResponse(); alipayResponse.setSHtmlText(sHtmlText); alipayResponse.setOrderId(alipayOrderRequest.getWidOutTradeNo()); return ResultUtil.success(alipayResponse);} ServerImpl Transactionalpublic String alipayOrder(AlipayOrderRequest alipayOrderRequest) throws AlipayApiException { /**获得初始化的AlipayClient**/ AlipayClient alipayClient new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, json, AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); /**当面付之「扫码支付」**/ AlipayTradePrecreateRequest alipayTradePrecreateRequest new AlipayTradePrecreateRequest(); /**回调地址异步通知**/ alipayTradePrecreateRequest.setNotifyUrl(AlipayConfig.notify_url); alipayTradePrecreateRequest.setReturnUrl(AlipayConfig.return_url); /**商户订单号商户网站订单系统中唯一订单号必填**/ String out_trade_no alipayOrderRequest.getWidOutTradeNo(); /**付款金额必填**/ String total_amount alipayOrderRequest.getWidTotalFee(); /**订单名称必填**/ String subject alipayOrderRequest.getWidSubject(); /**商户门店编号必填**/ String store_id AlipayConfig.STORE_ID; /**交易超时时间订单允许的最晚付款时间必填**/ String timeout_express 120m; /**拼接参数**/ alipayTradePrecreateRequest.setBizContent( {\out_trade_no\:\ out_trade_no \, \total_amount\:\ total_amount \, \subject\:\ subject \, \store_id\:\ store_id \, \timeout_express\:\timeout_express\}); return alipayClient.execute(alipayTradePrecreateRequest).getBody();} 三、返回结果测试 如上代码调用execute之后的返回结果 { alipay_trade_precreate_response:{ code:10000, msg:Success, out_trade_no:20200508160037744742, qr_code:https://qr.alipay.com/bax06173nktjyrrwupss00bf }, sign:sdk3Q6idlQCSRuuxc6xXv3g4BAkxEgpA9WYJoiE8oYH5mA6K8GMwAETNKOhOPh/SoYS4CECzswk/H7qw9A} 我们可以看到qr_code参数了剩下的就是交给前端生成二维码了然后用户扫码支付在这我就不展示了直接拿链接去草料二维码直接生成个二维码试试。 四、扫码支付回调地址 支付成功后支付宝会回调前边设置的回调地址由后端的的 return_url 参数控制。 再看看支付成功后的回调接口由后端的 notify_url 参数控制「没有使用开源的SDK演示」 public String alipaynotify(Model model, HttpServletRequest request) { log.info(支付宝异步回调 ------------beg-----------); String result fail; /**获取支付宝POST过来反馈信息**/ /* * * 功能支付宝服务器异步通知页面 * 说明 * 以下代码只是为了方便商户测试而提供的样例代码商户可以根据自己网站的需要按照技术文档编写,并非一定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用只是提供一个参考。 */ MapString, String paramsthis.getAlipayRequest(request); if(params null || params.size()0){ BufferedReader bufferReader null; StringBuilder sb new StringBuilder(); try { bufferReader new BufferedReader(request.getReader()); String line null; while ((line bufferReader.readLine()) ! null) { sb.append(new String(line.getBytes(ISO-8859-1), utf-8)); } } catch (IOException e) { e.printStackTrace(); } String body null; try { body URLDecoder.decode(sb.toString(),UTF-8); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } paramsUriComponentsBuilder.newInstance().query(body).build().getQueryParams().toSingleValueMap(); } boolean signVerified false; try { signVerified AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); } catch (AlipayApiException e1) { log.error(由于e1.getErrMsg()返回给支付宝系统的结果result:fail); model.addAttribute(result, fail); return result; } /**——请在这里编写您的程序以下代码仅作参考——**/ /* 实际验证过程建议商户务必添加以下校验 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号 2、判断total_amount是否确实为该订单的实际金额即商户订单创建时的金额 3、校验通知中的seller_id或者seller_email) 是否为out_trade_no这笔单据的对应的操作方有的时候一个商户可能有多个seller_id/seller_email 4、验证app_id是否为该商户本身。 */ log.error(支付宝验证签名---------------------------------signVerified); if(signVerified) {/**验证成功**/ /**商户订单号**/ /**交易状态**/ log.info(支付宝异步回调验签成功); String trade_status params.get(trade_status); if(TRADE_FINISHED.equals(trade_status)){ /**判断该笔订单是否在商户网站中已经做过处理**/ /**如果没有做过处理根据订单号out_trade_no在商户网站的订单系统中查到该笔订单的详细并执行商户的业务程序**/ /**如果有做过处理不执行商户的业务程序**/ /**注意**/ /**退款日期超过可退款期限后如三个月可退款支付宝系统发送该交易状态通知**/ try { /** 在这里处理支付成功后的操作比如修改订单状态等等**/ coding... result success; } catch (Exception e) { log.error(e.getMessage()); result fail; } }else if (TRADE_SUCCESS.equals(trade_status)){ /**判断该笔订单是否在商户网站中已经做过处理**/ /**如果没有做过处理根据订单号out_trade_no在商户网站的订单系统中查到该笔订单的详细并执行商户的业务程序**/ /**如果有做过处理不执行商户的业务程序**/ /**注意**/ /**付款完成后支付宝系统发送该交易状态通知**/ try { /** 在这里处理支付成功后的操作比如修改订单状态等等**/ coding... result success; } catch (Exception e) { log.error(e.getMessage()); result fail; } }else{ result fail; } }else {/**验证失败**/ result fail; /**调试用写文本函数记录程序运行情况是否正常**/ /**String sWord AlipaySignature.getSignCheckContentV1(params);**/ /**AlipayConfig.logResult(sWord);**/ log.debug(支付宝异步回调验签失败); } log.debug(异步回调返回给支付宝系统的结果result:result); model.addAttribute(result, result); log.info(支付宝异步回调 -------------end ------------); return result;} 该方法返回给支付宝的 result 就 success、fail 两个结果。从以上看来其实不难发现支付宝支付是非常简单的尽管我上边贴了大量的代码其实采用开源SDK的话可以更加缩减、美化一些。 ok这篇文章就到这结束了上边并没有详细介绍接口调用、参数说明等详细介绍请查看官方文档 https://opendocs.alipay.com/open/194/106078/https://opendocs.alipay.com/open/194/103296 文章最后 博客地址https://www.cgblog.com/niceyoo 如果觉得这篇文章有丶东西不妨关注一下我关注是对我最大的鼓励~