支付宝支付---服务端
第一次做支付宝支付,辛辛苦苦,打了N多日志
首先,下载sdk
package com.util; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.Map; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alipay.api.AlipayApiException; import com.alipay.api.internal.util.AlipaySignature; /* * *类名:AlipayNotify *功能:支付宝通知处理类 *详细:处理支付宝各接口通知返回 *版本:3.3 *日期:2012-08-17 *说明: *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 *该代码仅供学习和研究支付宝接口使用,只是提供一个参考 *************************注意************************* *调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常 */ public class AlipayNotify { private static final Logger logger = LoggerFactory.getLogger(AlipayNotify.class); /** * 支付宝消息验证地址 */ private static final String HTTPS_VERIFY_URL = "https://mapi.alipay.com/gateway.do?service=notify_verify&"; /** * 验证消息是否是支付宝发出的合法消息 * @param params 通知返回来的参数数组 * @return 验证结果 */ public static boolean verify(Map<String, String> params) { //判断responsetTxt是否为true,isSign是否为true //responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 //isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 String responseTxt = "true"; logger.info("--------------------------------------------verity notify_id:"+params.get("notify_id")); if(params.get("notify_id") != null) { String notify_id = params.get("notify_id"); responseTxt = verifyResponse(notify_id); logger.info("---------------------------------------------verity responseTxt:"+responseTxt); } String sign = ""; logger.info("--------------------------------------------verity sign:"+params.get("sign")); if(params.get("sign") != null) {sign = params.get("sign");} boolean isSign = getSignVeryfy(params, sign); logger.info("--------------------------------------------verity isSign:"+isSign); //写日志记录(若要调试,请取消下面两行注释) //String sWord = "responseTxt=" + responseTxt + "\n isSign=" + isSign + "\n 返回回来的参数:" + AlipayCore.createLinkString(params); //AlipayCore.logResult(sWord); if (isSign && responseTxt.equals("true")) { return true; } else { return false; } } /** * 根据反馈回来的信息,生成签名结果 * @param Params 通知返回来的参数数组 * @param sign 比对的签名结果 * @return 生成的签名结果 */ private static boolean getSignVeryfy(Map<String, String> Params, String sign) { //过滤空值、sign与sign_type参数 Map<String, String> sParaNew = AlipayCore.paraFilter(Params); logger.info("++++++++++++++++++++++++++++++++++++++sParaNew:"+sParaNew); //获取待签名字符串 String preSignStr = AlipayCore.createLinkString(sParaNew); logger.info("++++++++++++++++++++++++++++++++++++++ preSignStr:"+preSignStr); //获得签名验证结果 boolean isSign = false; if(AlipayConfig.sign_type.equals("RSA")){ isSign = RSA.verify(preSignStr, sign, AlipayConfig.ali_public_key, AlipayConfig.input_charset); } return isSign; } /** * 获取远程服务器ATN结果,验证返回URL * @param notify_id 通知校验ID * @return 服务器ATN结果 * 验证结果集: * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空 * true 返回正确信息 * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟 */ private static String verifyResponse(String notify_id) { //获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求 String partner = AlipayConfig.partner; String veryfy_url = HTTPS_VERIFY_URL + "partner=" + partner + "¬ify_id=" + notify_id; return checkUrl(veryfy_url); } /** * 获取远程服务器ATN结果 * @param urlvalue 指定URL路径地址 * @return 服务器ATN结果 * 验证结果集: * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空 * true 返回正确信息 * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟 */ 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; } }
配置,
package com.util; /* * *类名:AlipayConfig *功能:基础配置类 *详细:设置帐户有关信息及返回路径 *版本:3.3 *日期:2012-08-10 *说明: *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 *该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 *提示:如何获取安全校验码和合作身份者ID *1.用您的签约支付宝账号登录支付宝网站(www.alipay.com) *2.点击“商家服务”(https://b.alipay.com/order/myOrder.htm) *3.点击“查询合作者身份(PID)”、“查询安全校验码(Key)” *安全校验码查看时,输入支付密码后,页面呈灰色的现象,怎么办? *解决方法: *1、检查浏览器配置,不让浏览器做弹框屏蔽设置 *2、更换浏览器或电脑,重新登录查询。 */ public class AlipayConfig { // 合作身份者ID,以2088开头由16位纯数字组成的字符串 public static String partner = "2088xxxxxxxxxxxx"; // 商户的私钥 public static String private_key = ""; // 支付宝的公钥(固定) public static String ali_public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB"; // 支付宝的公钥(页面) // public static String ali_public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB"; //支付宝网关 public static String alipay_url = "https://openapi.alipay.com/gateway.do"; // 支付宝分配给开发者的应用ID public static String app_id = "100000000000000"; public static String content_type = "JSON"; // 调试用,创建TXT日志文件夹路径 public static String log_path = "D:\\"; // 字符编码格式 目前支持 gbk 或 utf-8 public static String input_charset = "utf-8"; // 签名方式 不需修改 public static String sign_type = "RSA"; }
其次,
/** * @Title: alipayNotify * @Description: 支付宝钱包支付回调 * @param @param request 设定文件 * @return void 返回类型 * @throws */ @RequestMapping("/alipayNotify") public void alipayNotify(HttpServletRequest request,HttpServletResponse response) {// 获取支付宝POST过来反馈信息 logger.info("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa进入了回调函数!"); 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] + ","; } // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); params.put(name, valueStr); } // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)// // 交易创建时间 String gmtCreate = request.getParameter("gmt_create"); // log.info("支付宝交易创建时间戳:"+gmtCreate); // 交易付款时间 String gmtPayment = request.getParameter("gmt_payment"); // log.info("支付宝交易付款时间:"+gmtPayment); // 支付宝交易号 String trade_no = new // String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 交易状态 String trade_status = null; // 商户订单号 String out_trade_no = null; //交易编号 String trade_no = null; try { trade_status = new String(request.getParameter("trade_status") .getBytes("ISO-8859-1"), "UTF-8");// log.info("支付宝交易状态:"+trade_status); out_trade_no = new String(request.getParameter("out_trade_no") .getBytes("ISO-8859-1"), "UTF-8"); logger.info("trade_status:"+trade_status+" ccccccccccccccccccccccccc " +"out_trade_no:"+out_trade_no); // log.info("支付宝交易单号:"+out_trade_no); trade_no = new String(request.getParameter("trade_no") .getBytes("ISO-8859-1"), "UTF-8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// logger.info("ccccccccccccccccccccccccc notify_id:"+params.get("notify_id")); logger.info("ccccccccccccccccccccccccc sign:"+params.get("sign")); if (AlipayNotify.verify(params)) {// 验证成功 logger.info("dddddddddddddddddddddddddddddddddd 验证通过"); // //////////////////////////////////////////////////////////////////////////////////////// // 请在这里加上商户的业务逻辑程序代码 // ——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— if (trade_status.equals("TRADE_FINISHED")) { // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 如果有做过处理,不执行商户的业务程序 // 注意: // 退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 } else if (trade_status.equals("TRADE_SUCCESS")) { logger.info("进入TRADE_SUCCESS状态"); // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 如果有做过处理,不执行商户的业务程序 // 注意: // 付款完成后,支付宝系统发送该交易状态通知 // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 } } // ——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— try { response.getOutputStream().write("success".getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //请不要修改或删除 } else {// 验证失败 try { response.getOutputStream().write("fail".getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //请不要修改或删除 } }