聚合支付

第三章 支付宝(即时到账交易接口)


文章目录

  • 聚合支付
  • 前言
  • 一、开发前准备
  • 二、java实现
    • 1.pom中引入相关jar包
    • 2.支付相关工具类
    • 3.支付相关参数
    • 4.支付实现
    • 5.查询实现
    • 6.支付回调

前言

支付宝支付接口分两种,一种是“统一下单接口”在第一章已经介绍过了,第二种就是本章要介绍的内容“即时到账交易接口”,相关文档参考:https://opendocs.alipay.com/open/65/104807。相较于“统一下单接口”方式来说,“即时到账接口”目前应用相对来说较少,一般都是之前旧系统使用的,新开发的系统大都使用“统一下单接口”,另外由于支付宝开展“MD5密钥专项治理”,新用户申请不到MD5秘钥需要使用rsa或者rsa2秘钥进行相关数据交互签名和验签。


提示:以下是本篇文章正文内容,下面案例可供参考

一、开发前准备

对接支付接口前商户需要项支付宝申请获取一些必要的商户接入参数:支付宝账号、合作者id、MD5秘钥、接入地址等参数。

二、java实现

1.pom中引入相关jar包

        <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.12</version></dependency><dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.1</version></dependency>

2.支付相关工具类

代码如下(示例):

public class MD5Util {/*** 支付宝消息验证地址*/private static final String HTTPS_VERIFY_URL = "https://mapi.alipay.com/gateway.do?service=notify_verify&";/*** 生成签名结果* @param sPara 要签名的数组* @return 签名结果字符串*/public static String buildRequestMysign(Map<String, Object> sPara,String md5Key) {String prestr = createLinkString(sPara); //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串String mysign = "";mysign = sign(prestr, md5Key, "UTF-8");return mysign;}/*** 签名字符串*/public static String sign(String text, String key, String input_charset) {text = text + key;return DigestUtils.md5Hex(getContentBytes(text, input_charset));}/*** 签名字符串*/public static boolean verify(String text, String sign, String key, String input_charset) {text = text + key;String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));if(mysign.equals(sign)) {return true;}else {return false;}}private static byte[] getContentBytes(String content, String charset) {if (charset == null || "".equals(charset)) {return content.getBytes();}try {return content.getBytes(charset);} catch (UnsupportedEncodingException e) {throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);}}/*** 除去数组中的空值和签名参数*/public static Map<String, Object> paraFilter(Map<String, Object> sArray) {Map<String, Object> result = new HashMap<String, Object>();if (sArray == null || sArray.size() <= 0) {return result;}for (String key : sArray.keySet()) {String value = (String) sArray.get(key);if (value == null || value.equals("") || key.equalsIgnoreCase("sign")|| key.equalsIgnoreCase("sign_type")) {continue;}result.put(key, value);}return result;}/*** 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串*/public static String createLinkString(Map<String, Object> params) {//去除空值params = paraFilter(params);List<String> keys = new ArrayList<String>(params.keySet());Collections.sort(keys);String prestr = "";for (int i = 0; i < keys.size(); i++) {String key = keys.get(i);String value = (String) params.get(key);if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符prestr = prestr + key + "=" + value;} else {prestr = prestr + key + "=" + value + "&";}}return prestr;}/*** 根据反馈回来的信息,生成签名结果*/public static boolean getSignVeryfy(Map<String, Object> Params, String sign,String md5Key) {//过滤空值、sign与sign_type参数Map<String, Object> sParaNew = paraFilter(Params);//获取待签名字符串String preSignStr = createLinkString(sParaNew);//获得签名验证结果boolean isSign = false;isSign = verify(preSignStr, sign, md5Key, "UTF-8");return isSign;}/*** 获取远程服务器ATN结果,验证返回URL*/private static String verifyResponse(String notify_id,String partner) {//获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求String veryfy_url = HTTPS_VERIFY_URL + "partner=" + partner + "&notify_id=" + notify_id;return checkUrl(veryfy_url);}/*** 获取远程服务器ATN结果*/private static String checkUrl(String urlvalue) {String inputLine = "";try {URL url = new URL(urlvalue);HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));inputLine = in.readLine().toString();} catch (Exception e) {e.printStackTrace();inputLine = "";}return inputLine;}/*** 验证消息是否是支付宝发出的合法消息*/public static boolean verify(Map<String, Object> params,String partner,String md5Key) {//判断responsetTxt是否为true,isSign是否为true//responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关//isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关String responseTxt = "true";if(params.get("notify_id") != null) {String notify_id = (String) params.get("notify_id");responseTxt = verifyResponse(notify_id,partner);}String sign = "";if(params.get("sign") != null) {sign = (String) params.get("sign");}boolean isSign = getSignVeryfy(params, sign,md5Key);if (isSign && responseTxt.equals("true")) {return true;} else {return false;}}
}public class AlipayHttpUtil {/*** 支付宝提供给商户的服务接入网关URL(新)*/private static final String ALIPAY_GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";/*** 生成要请求给支付宝的参数数*/private static Map<String, Object> buildRequestPara(Map<String, Object> sParaTemp,String md5Key) {//除去数组中的空值和签名参数Map<String, Object> sPara = MD5Util.paraFilter(sParaTemp);//生成签名结果String mysign = MD5Util.buildRequestMysign(sPara,md5Key);//签名结果与签名方式加入请求提交参数组中sPara.put("sign", mysign);sPara.put("sign_type", "MD5");return sPara;}/*** 建立请求,以表单HTML形式构造(默认)*/public static String buildRequest(Map<String, Object> sParaTemp, String strMethod, String strButtonName,String md5Key) {//待请求参数数组Map<String, Object> sPara = buildRequestPara(sParaTemp,md5Key);List<String> keys = new ArrayList<String>(sPara.keySet());StringBuffer sbHtml = new StringBuffer();sbHtml.append("<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"" + ALIPAY_GATEWAY_NEW+ "_input_charset=" + "UTF-8" + "\" method=\"" + strMethod+ "\">");for (int i = 0; i < keys.size(); i++) {String name = (String) keys.get(i);String value = (String) sPara.get(name);sbHtml.append("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\"/>");}//submit按钮控件请不要含有name属性sbHtml.append("<input type=\"submit\" value=\"" + strButtonName + "\" style=\"display:none;\"></form>");sbHtml.append("<script>document.forms['alipaysubmit'].submit();</script>");return sbHtml.toString();}/*** 建立请求,以表单HTML形式构造,带文件上传功能*/public static String buildRequest(Map<String, Object> sParaTemp, String strMethod, String strButtonName, String strParaFileName,String md5Key) {//待请求参数数组Map<String, Object> sPara = buildRequestPara(sParaTemp,md5Key);List<String> keys = new ArrayList<String>(sPara.keySet());StringBuffer sbHtml = new StringBuffer();sbHtml.append("<form id=\"alipaysubmit\" name=\"alipaysubmit\"  enctype=\"multipart/form-data\" action=\"" + ALIPAY_GATEWAY_NEW+ "_input_charset=" + "UTF-8" + "\" method=\"" + strMethod+ "\">");for (int i = 0; i < keys.size(); i++) {String name = (String) keys.get(i);String value = (String) sPara.get(name);sbHtml.append("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\"/>");}sbHtml.append("<input type=\"file\" name=\"" + strParaFileName + "\" />");//submit按钮控件请不要含有name属性sbHtml.append("<input type=\"submit\" value=\"" + strButtonName + "\" style=\"display:none;\"></form>");return sbHtml.toString();}/*** 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果* 如果接口中没有上传文件参数,那么strParaFileName与strFilePath设置为空值*/public static String buildRequest(Map<String,Object> sParaTemp,String md5Key) throws Exception {//待请求参数数组Map<String, Object> sPara = buildRequestPara(sParaTemp,md5Key);HttpProtocolHandler httpProtocolHandler = HttpProtocolHandler.getInstance();HttpRequest request = new HttpRequest(HttpResultType.BYTES);//设置编码集request.setCharset("UTF-8");request.setParameters(generatNameValuePair(sPara));request.setUrl(ALIPAY_GATEWAY_NEW+"_input_charset="+"UTF-8");HttpResponse response = httpProtocolHandler.execute(request);if (response == null) {return null;}String strResult = response.getStringResult();return strResult;}/*** MAP类型数组转换成NameValuePair类型*/private static NameValuePair[] generatNameValuePair(Map<String, Object> properties) {NameValuePair[] nameValuePair = new NameValuePair[properties.size()];int i = 0;for (Map.Entry<String, Object> entry : properties.entrySet()) {nameValuePair[i++] = new NameValuePair(entry.getKey(), String.valueOf(entry.getValue()));}return nameValuePair;}
}

3.支付相关参数

public class  AliPayConfig {//这里用natapp内外网穿透,主要用于支付回调(用外网服务器更好)public static final String natUrl = "http://xiaotiancai.natapp1.cc";// 合作者身份IDpublic static partner="245625.......";// 支付宝账号public static seller_email="test.....@163.com";// md5秘钥public static String mchID="sdahsjdskjf....." ;// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问public static String notifyUrl = natUrl + "/aliPay/AliPayNotify";public static String returnUrl = natUrl + "/aliPay/AliPayReturn";// 签名方式public static String signType = "MD5";// 字符编码格式public static String charset = "UTF-8";//支付请求地址public static String payUrl = "https://mapi.alipay.com/gateway.do";//支付接口名称public static String payService = "create_direct_pay_by_user";//查询接口名称public static String queryService = "single_trade_query";
}

4.支付实现

代码如下(示例):

public void oldAliPayUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");//商户订单号,商户网站订单系统中唯一订单号,必填(可以用一些重要的数加上时间戳组装,回调时可通过订单号截取使用)String orderNo = sdf.format(new Date());Map sParaTemp = new HashMap();sParaTemp.put("service", AliPayConfig.payService);sParaTemp.put("partner", AliPayConfig.partner);//合作者身份IdsParaTemp.put("seller_email", AliPayConfig.seller_email);//sParaTemp.put("_input_charset", "UTF-8");sParaTemp.put("payment_type", "1");//支付类型,只支持值为1sParaTemp.put("notify_url", AliPayConfig.notifyUrl);sParaTemp.put("return_url", AliPayConfig.returnUrl);sParaTemp.put("out_trade_no", orderNo);sParaTemp.put("subject", "乌龙茶");sParaTemp.put("total_fee", payAmount);sParaTemp.put("body","商品");sParaTemp.put("paymethod", "bankPay");sign = MD5Util.buildRequestMysign(sParaTemp,AliPayConfig.md5Key);String subject = URLEncoder.encode("商品","UTF-8");String body = URLEncoder.encode("乌龙茶","UTF-8");String notifyUrl = URLEncoder.encode(notify_url,"UTF-8");String returnUrl = URLEncoder.encode(return_url,"UTF-8");String seller_email = URLEncoder.encode(seller_email,"UTF-8");payData = rdcNetpayPbank.getNetpayUrl();payData += "?service="+AliPayConfig.payService+"&partner="+AliPayConfig.partner+"&seller_email="+seller_email+"&_input_charset="+"UTF-8"+"&payment_type="+"1"+"&notify_url="+notifyUrl+"&return_url="+returnUrl+"&out_trade_no="+orderNo+"&subject="+subject+"&sign="+sign+"&sign_type="+AliPayConfig.signType+"&total_fee="+payAmount+"&body="+body+"&paymethod="+"bankPay";}

5.查询实现

代码如下(示例):

public String aliPayOrderQuery(String orderNo) throws Exception {Map sParaTemp = new HashMap();sParaTemp.put("service", AliPayConfig.queryService);sParaTemp.put("partner", AliPayConfig.partner);sParaTemp.put("_input_charset", AliPayConfig.charset);sParaTemp.put("out_trade_no", orderNo);String resultStr = AlipayHttpUtil.buildRequest(sParaTemp, AliPayConfig.md5Key);System.out.println("result++++++:" + resultStr);Alipay alipay = AlipayXmlUtil.xmlToObject(resultStr, Alipay.class);if ("T".equals(alipay.getIsSuccess())){AlipayRequest alipayRequest = alipay.getRequest();String alipaySign = alipay.getSign();AlipayResponse alipayResponse = alipay.getResponse();AlipayTrade alipayTrade = alipayResponse.getTrade();JSONObject tradeJson = (JSONObject) JSON.toJSON(alipayTrade);Map<String, Object> tradeMap = (Map<String, Object>) tradeJson;boolean issign = MD5Util.getSignVeryfy(tradeMap, alipaySign, AliPayConfig.md5Key);if(issign){if ("TRADE_SUCCESS".equals(alipayTrade.getTrade_status()) || "TRADE_FINISHED".equals(alipayTrade.getTrade_status())){/**支付成功*/}else{/**支付失败,或未支付*/}}}}

6.支付回调

代码如下(示例):

    @RequestMapping(value = "/aliPay/AliPayNotify")public void AliPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {//获取支付宝POST过来反馈信息Map<String, String> params = new HashMap<String, String>();Map<String, String[]> requestParams = request.getParameterMap();for (Iterator<String> 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] + ",";}//乱码解决,这段代码在出现乱码时使用//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");params.put(name, valueStr);}//验证签名boolean signVerified = MD5Util.verify(params,AliPayConfig.partner,AliPayConfig.md5Key);//验证签名if (signVerified) {//验证成功//商户订单号String out_trade_no = params.get("out_trade_no");//支付宝交易号String trade_no = params.get("trade_no");//付款金额String total_amount = params.get("total_amount");//交易状态String total_amount = params.get("trade_status");if (trade_status.equals("TRADE_FINISHED") || trade_status.equals("TRADE_SUCCESS")) {/** 支付成功* 业务规则实现*///回复支付公司try {response.getWriter().print("SUCCESS");} catch (IOException e) {e.printStackTrace();}}} else {//验证失败/** 支付失败*/}}

聚合支付PC端-支付宝(即时到账交易接口)相关推荐

  1. 聚合支付PC端-支付宝

    聚合支付 第一章 支付宝 文章目录 聚合支付 前言 一.开发前准备 1.1 获得沙箱账号 1.2 选择沙箱环境 1.3 配置商户参数 1.4 支付接入文档 二.java实现过程 1.pom中引入支付宝 ...

  2. 支付宝即时到账交易接口和即时到账有密退款接口demo

    https://pan.baidu.com/s/1-bb33MZ26-o0M4sAd5meaw

  3. 支付宝接口 - 即时到账交易接口 对接 整理 1

    支付宝官方开放平台接口说明: https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.Gp6DiG&treeId=62&a ...

  4. php支付宝红包接口,支付宝支付接口(即时到账交易接口)

    付宝红包分享 小伙伴们,给大家发红包喽!人人可领,领完就能用.祝大家领取的红包金额大大大!#吱口令#长按复制此消息,打开支付宝就能领取!SJIJ3r58z8 步骤:1. 按照官方文档,编写此接口所需要 ...

  5. 聚合支付PC端-微信扫码

    聚合支付 第二章 微信扫码 文章目录 聚合支付 前言 一.开发前准备 二.java实现 1.pom中引入相关jar包 2.支付相关工具类 3.支付相关商户参数 4.微信支付统一下单-生成二维码 5.微 ...

  6. 支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc

    一.场景:公司需要在网站上进行支付宝支付. 二.API:使用支付宝开放平台的支付能力-即时到账接口.支付宝开放平台链接 三.分析: 1.支付宝的文档比较容易看,主要是有相应的DEMO,我这里看的DEM ...

  7. PHP实现支付宝即时到账功能

    本文实例为大家分享了PHP支付宝即时到账功能的实现代码,供大家参考,具体内容如下 首先需要下载即时到账交易接口,传送门https://doc.open.alipay.com/doc2/detail?t ...

  8. 支付宝即时到账接口开发 - DEMO讲解

    支付宝即时到账接口开发 - DEMO讲解 环境要求 PHP5.0以上,且需要开启curl.openssl. 文档地址: https://doc.open.alipay.com/doc2/detail? ...

  9. Payment:支付宝即时到账接口接入教程

    记住,如果觉得文档写得不清楚,一定要告诉我.励志写好文档为大家服务! Payment 3.0 支付宝的配置设置文档请 点击这里 项目GitHub地址:https://github.com/helei1 ...

最新文章

  1. [转]自定义hadoop map/reduce输入文件切割InputFormat
  2. php灰度化,PHP Imagick – 将图像转换为灰度(非常糟糕的结果)
  3. JAVA数组及数组的应用
  4. 【OpenCV 例程200篇】18. 图像的掩模加法
  5. 计组之总线:2、总线仲裁(链式查询、计数器查询、独立请求、分布式查询)
  6. 第一个flash游戏--配对游戏
  7. Spark编译报错:missing or invalid depency detected while loading class file RDDOperationScope.class
  8. 二叉树中两个节点的第一个祖先父节点
  9. 【Unity Shader】(九) ------ 高级纹理之渲染纹理及镜子与玻璃效果的实现
  10. GEF:应用示例列表
  11. 清华大学829考研 初试436经验谈
  12. 刷机!刷机!!刷机!!!
  13. 393高校毕业设计选题
  14. 虚拟化与元宇宙:人类文明演化的奇点与治理
  15. CentOS 7下的软件安装方法及策略
  16. 走方格跳格子(dp,递归,排列组合三种方法)
  17. 判断ua字段中是否含有html5plus,浏览器UA,浏览器标识检测
  18. Tracer 记录 Controller 日志
  19. JS中常见的字符串拼接处理
  20. Arena仿真-基于超市排队的建模分析

热门文章

  1. mac+修改+ssh文件夹权限_MAC创建SSH客户端配置文件
  2. 【论文笔记】A Learned Sketch for Subgraph Counting
  3. 【智能工厂】精工智能工厂规划;透明化车间典型案例呈现
  4. 基于DSP的视频采集系统设计
  5. MATLAB在力学上应用,Matlab在力学中的应用
  6. 简约淡雅花卉年终总结PPT模板
  7. 淡雅个人简历自我介绍PPT模板
  8. 推箱子游戏(C语言版)
  9. List集合遍历的五种方法
  10. 简洁,漂亮实用的万年历