1.alipay 双功能支付简介
2.alipay 提交支付订单
3.alipay 整合双功能支付及发货信息同步
4.alipay 页面跳转同步通知处理
5.alipay 服务器异步通知处理
====================== 华丽丽的分割线 ======================
1.alipay 双功能支付简介
1.0 L.z的唠叨
网上copy的东西那么多,查个东西在百度上google一下都搜不到个完整,我恨!代码还是看自己整理的比较好。
1.1 使用流程
在网站中生成订单信息,并记录到数据库中,将订单信息及其他必要信息按照alipayto指定的形式,发给支付宝,也就是生成完了调 AlipayService.BuildForm() 方法,改方法会返回一串字符串,里面记录着表单信息,无需更改返回的字符串,并使之打印到页面上(该字符串有js写的自动提交表单)。
此时进入支付宝付款页面,当支付成功时,支付宝会根据我们设置的returnURL来访问我们指定的页面(action),我们可以根据他回馈的状态及订单号,钱等信息进行对数据库相应处理(得判断状态是否一致)。
但是,上述的情况只是在用户每关闭我们网站的时候才会出现,事实上,有可能用户在没付款结束时就关闭了网站。支付宝为解决这个问题,使用了 notifyURL,即每次用户的交易状态发生更改,都会主动向notifyURL中设置的页面(action)发出通知,以便我们能设置商业逻辑。
为此,需要编写或更改的,有如下:aAlipayConfig(设置alipay账户,及跳转通知页面等基本信息),alipayto(生成表单并提交),returnURL(页面跳转同步通知处理文件),notifyURL(服务器异步通知处理文件)。
由于可能存在重复通知,所以必须忠实的判断订单的状态,以免重复操作。
1.2 支付宝双功能支付所需要的类
所需要的类如下:
AlipayConfig.java
这个类里面需要我去修改一些信息,如:身份ID,key等
AlipayService.java
请求处理类,可整合进发货信息同步(当然,也可以独立出来,不过我感觉没那个必要)
AlipayNotify.java
该类无需更改。
Md5Encrpt.java
支付宝传输参数加密用,无需更改
AlipayFunction.java
公用函数,alipay 请求、通知时调用,无需更改
SetCharacterEncodingFilter.java
字符串格式,无需更改(搞笑的是,里面的注释是英文的,与上面的类注释不同,不协调~~)
UtilDate.java
自定义订单类,用于生成订单号,该类可要可不要(能确保自己生成的订单号唯一就行)
(建议以上放在同一包中)
AlipayAction.java
用于编写alipayTo(),notifyURL(),returnURL() 等处理alipay相关方法
另外,还需要如下jsp页面:
alipayto.jsp
用于跳转到打印AlipayService.BuildForm()返回的字符串,跳转到 alipay 的支付页面(当然,也可以改造成直接从Action中提交)
return_url.jsp
用于展示用户订单支付成功的页面。
====================== 华丽丽的分割线 ======================
2.alipay 提交支付订单
2.1 设置AlipayConfig信息
如前所述,签约支付的卖家帐号,服务器通知的页面,字符编码格式等,都在这里设置,如下:
1 /* * 2 *功能:设置帐户有关信息及返回路径(基础配置页面) 3 *版本:3.1 4 *日期:2010-11-25 5 *说明: 6 *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 7 *该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 8 9 *提示:如何获取安全校验码和合作身份者ID 10 *1.访问支付宝首页(www.alipay.com),然后用您的签约支付宝账号登陆. 11 *2.点击导航栏中的“商家服务”,即可查看 12 13 *安全校验码查看时,输入支付密码后,页面呈灰色的现象,怎么办? 14 *解决方法: 15 *1、检查浏览器配置,不让浏览器做弹框屏蔽设置 16 *2、更换浏览器或电脑,重新登录查询。 17 * */ 18 package com.blank.alipay; 19 20 import java.util.*; 21 22 public class AlipayConfig { 23 // 如何获取安全校验码和合作身份者ID 24 // 1.访问支付宝商户服务中心(b.alipay.com),然后用您的签约支付宝账号登陆. 25 // 2.访问“技术服务”→“下载技术集成文档”(https://b.alipay.com/support/helperApply.htm?action=selfIntegration) 26 // 3.在“自助集成帮助”中,点击“合作者身份(Partner ID)查询”、“安全校验码(Key)查询” 27 28 //↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 29 // 合作身份者ID,以2088开头由16位纯数字组成的字符串30 public static String partner = ""; 31 32 // 交易安全检验码,由数字和字母组成的32位字符串33 public static String key = ""; 34 35 // 签约支付宝账号或卖家收款支付宝帐户36 public static String seller_email = ""; 37 38 // notify_url 交易过程中服务器通知的页面 要用 http://格式的完整路径,不允许加?id=123这类自定义参数39 public static String notify_url = ""; 40 41 // 付完款后跳转的页面 要用 http://格式的完整路径,不允许加?id=123这类自定义参数42 public static String return_url = ""; 43 44 // 网站商品的展示地址,不允许加?id=123这类自定义参数45 public static String show_url = ""; 46 47 //收款方名称,如:公司名称、网站名称、收款人姓名等48 public static String mainname = ""; 49 //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 50 51 52 // 字符编码格式 目前支持 gbk 或 utf-8 53 // 这里注意要小写,我的alipay双功能支付文件中居然是大写(拿到手就这样),结果出现异常,如果你莫名奇妙的异常,请检查这里。很无语...54 public static String input_charset = "utf-8"; 55 56 // 签名方式 不需修改57 public static String sign_type = "MD5"; 58 59 //访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http60 public static String transport = "http"; 61 }
附注:我拿到alipay双功能支付的时候,里面AlipayConfig.java文件中,input_charset="UTF-8"。这让人很无语,只支持小写,可默认的却又大写。导致出现奇怪的异常...
2.2 提交支付订单的Action (AlipayAction.java)
1 /** 2 * 要充值的金额 3 */ 4 private String alimoney; 5 6 /** 7 * 要支付的订单编号 8 */ 9 private String tradeNumber; 10 11 /** 12 * 生成的HTML-URL,需到JSP打印出来 13 */ 14 private String sHtmlText; 15 16 // Getter/Setter 方法略,若还需要其他信息同理。 17 18 public String payTo() { 19 boolean flag = true; 20 // 商业逻辑判断,判断各种信息是否正确,如:金钱,用户信息等 21 // ...略 22 23 if(flag) { 24 // 如若无误,写入数据库,并记录状态,生成订单,获取订单ID等信息。 25 // ...略 26 27 // 调用入口页方法 28 alipayTo(); 29 30 // 跳转到打印sHtmlText页面 31 return SUCCESS; 32 }else { 33 // 信息部正确,跳转到提示错误页面 34 return INPUT; 35 } 36 } 37 38 39 /** 40 * 功能:设置商品有关信息(入口页) 详细:该页面是接口入口页面,生成支付时的URL 41 */ 42 private void alipayTo() { 43 String input_charset = AlipayConfig.input_charset; 44 String sign_type = AlipayConfig.sign_type; 45 String seller_email = AlipayConfig.seller_email; 46 String partner = AlipayConfig.partner; 47 String key = AlipayConfig.key; 48 49 String show_url = AlipayConfig.show_url; 50 String notify_url = AlipayConfig.notify_url; 51 String return_url = AlipayConfig.return_url; 52 53 /////////////////////////////////////////////////////////////////////////////////// 54 55 // 以下参数是需要通过下单时的订单数据传入进来获得 56 // 必填参数 57 58 /////////////////////////////////////////////////////////////////////////////////// 59 // 这里是需要修改的,暂且注释掉 60 // UtilDate date = new UtilDate();//调取支付宝工具类生成订单号 61 // String out_trade_no = date.getOrderNum();//请与贵网站订单系统中的唯一订单号匹配 62 String out_trade_no = tradeNumber; 63 64 // 订单名称,显示在支付宝收银台里的“商品名称”里,显示在支付宝的交易管理的“商品名称”的列表里。 65 // String subject = new String(request.getParameter("aliorder").getBytes("ISO-8859-1"),"utf-8"); 66 String subject = "XX网站充值" + alimoney + "元货币"; 67 68 // 订单描述、订单详细、订单备注,显示在支付宝收银台里的“商品描述”里 69 // String body = new String(request.getParameter("alibody").getBytes("ISO-8859-1"),"utf-8"); 70 String body = "default"; 71 72 // 订单总金额,显示在支付宝收银台里的“应付总额”里 73 // String price = new String(request.getParameter("alimoney").getBytes("ISO-8859-1"),"utf-8"); 74 String price = alimoney; 75 76 String logistics_fee = "0.00"; // 物流费用,即运费。 77 String logistics_type = "EXPRESS"; // 物流类型,三个值可选:EXPRESS(快递)、POST(平邮)、EMS(EMS) 78 String logistics_payment = "SELLER_PAY"; // 物流支付方式,两个值可选:SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费) 79 80 String quantity = "1"; // 商品数量,建议默认为1,不改变值,把一次交易看成是一次下订单而非购买一件商品。 81 82 // 扩展参数——买家收货信息(推荐作为必填) 83 // 该功能作用在于买家已经在商户网站的下单流程中填过一次收货信息,而不需要买家在支付宝的付款流程中再次填写收货信息。 84 // 若要使用该功能,请至少保证receive_name、receive_address有值 85 String receive_name = "收货人姓名"; // 收货人姓名,如:张三 86 String receive_address = "收货人地址"; // 收货人地址,如:XX省XXX市XXX区XXX路XXX小区XXX栋XXX单元XXX号 87 String receive_zip = "123456"; // 收货人邮编,如:123456 88 String receive_phone = "0571-81234567"; // 收货人电话号码,如:0571-81234567 89 String receive_mobile = "13312341234"; // 收货人手机号码,如:13312341234 90 91 //扩展参数——第二组物流方式 92 //物流方式是三个为一组成组出现。若要使用,三个参数都需要填上数据;若不使用,三个参数都需要为空 93 //有了第一组物流方式,才能有第二组物流方式,且不能与第一个物流方式中的物流类型相同, 94 //即logistics_type="EXPRESS",那么logistics_type_1就必须在剩下的两个值(POST、EMS)中选择 95 String logistics_fee_1 = ""; // 物流费用,即运费。 96 String logistics_type_1 = ""; // 物流类型,三个值可选:EXPRESS(快递)、POST(平邮)、EMS(EMS) 97 String logistics_payment_1 = ""; // 物流支付方式,两个值可选:SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费) 98 99 //扩展参数——第三组物流方式 100 //物流方式是三个为一组成组出现。若要使用,三个参数都需要填上数据;若不使用,三个参数都需要为空 101 //有了第一组物流方式和第二组物流方式,才能有第三组物流方式,且不能与第一组物流方式和第二组物流方式中的物流类型相同, 102 //即logistics_type="EXPRESS"、logistics_type_1="EMS",那么logistics_type_2就只能选择"POST"103 String logistics_fee_2 = ""; // 物流费用,即运费。104 String logistics_type_2 = ""; // 物流类型,三个值可选:EXPRESS(快递)、POST(平邮)、EMS(EMS)105 String logistics_payment_2 = ""; // 物流支付方式,两个值可选:SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费) 106 107 //扩展功能参数——其他108 String buyer_email = ""; // 默认买家支付宝账号109 String discount = ""; // 折扣,是具体的金额,而不是百分比。若要使用打折,请使用负数,并保证小数点最多两位数110 111 /////////////////////////////////////////////////////////////////////////////////////////////////////112 113 ////构造函数,生成请求URL114 sHtmlText = AlipayService.BuildForm(partner,seller_email,return_url,notify_url,show_url,out_trade_no, 115 subject,body,price,logistics_fee,logistics_type,logistics_payment,quantity,receive_name,receive_address, 116 receive_zip,receive_phone,receive_mobile,logistics_fee_1,logistics_type_1,logistics_payment_1, 117 logistics_fee_2,logistics_type_2,logistics_payment_2,buyer_email,discount,input_charset,key,sign_type); 118 }
2.3 跳转到alipay支付页面(alipayto.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>数据传输中...</title> </head> <body> <div> <!-- escape 用于设置是否编码,若为true会将内容(如:空格会被转成 )进行转换,建议设置成false,事实上,设置成true麻烦事更多 --> <s:property value="sHtmlText" escape="false"/> </div> </body> </html>
2.4 设置struts配置文件 (struts.xml)
<!-- 上部分,略 --> <action name="payTo" class="AlipayAction" method="payTo"> <result name="success">alipayto.jsp</result> <result name="input">exception.jsp</result> </action>
====================== 华丽丽的分割线 ======================
3.alipay 整合双功能支付及发货信息同步
3.1 交易通知
在担保交易中,有如下的通知状态:WAIT_BUYER_PAY(等待买家付款)→WAIT_SELLER_SEND_GOODS(买家已付款,等待卖家发货)→WAIT_BUYER_CONFIRM_GOODS(卖家已发货,等待买家收货)→TRADE_FINISHED(买家已收货,交易完成)
(在使用alipay做本次项目时,没涉及到退货环节,故不写上)
由于alipay有这个WAIT_BUYER_CONFIRM_GOODS(卖家已发货,等待买家收货)状态存在,故在买家已付款的时候,我们需通知alipay,告知我们已发货,故需要在双功能支付的基础上整合进发货信息同步(其实也就2个方法),放在AlipayService.java中。
3.2 整合发货信息同步
1 import java.io.BufferedReader; 2 import java.io.InputStreamReader; 3 import java.io.OutputStream; 4 import java.io.UnsupportedEncodingException; 5 import java.net.HttpURLConnection; 6 import java.net.URL; 7 import java.net.URLEncoder; 8 import java.util.ArrayList; 9 import java.util.Collections; 10 import java.util.HashMap; 11 import java.util.List; 12 import java.util.Map; 13 14 15 /** 16 *类名:alipay_service 17 *功能:支付宝外部服务接口控制 18 *详细:该页面是请求参数核心处理文件,不需要修改 19 *版本:3.1 20 *修改日期:2010-11-24 21 *说明: 22 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 23 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 24 */ 25 26 public class AlipayService { 27 /** 28 * 功能:构造表单提交HTML 29 * @param partner 合作身份者ID 30 * @param seller_email 签约支付宝账号或卖家支付宝帐户 31 * @param return_url 付完款后跳转的页面 要用 以http开头格式的完整路径,不允许加?id=123这类自定义参数 32 * @param notify_url 交易过程中服务器通知的页面 要用 以http开格式的完整路径,不允许加?id=123这类自定义参数 33 * @param show_url 网站商品的展示地址,不允许加?id=123这类自定义参数 34 * @param out_trade_no 请与贵网站订单系统中的唯一订单号匹配 35 * @param subject 订单名称,显示在支付宝收银台里的“商品名称”里,显示在支付宝的交易管理的“商品名称”的列表里。 36 * @param body 订单描述、订单详细、订单备注,显示在支付宝收银台里的“商品描述”里 37 * @param price 订单总金额,显示在支付宝收银台里的“商品单价”里 38 * @param logistics_fee 物流费用,即运费。 39 * @param logistics_type 物流类型,三个值可选:EXPRESS(快递)、POST(平邮)、EMS(EMS) 40 * @param logistics_payment 物流支付方式,两个值可选:SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费) 41 * @param quantity 商品数量,建议默认为1,不改变值,把一次交易看成是一次下订单而非购买一件商品。 42 * @param receive_name 收货人姓名,如:张三 43 * @param receive_address 收货人地址,如:XX省XXX市XXX区XXX路XXX小区XXX栋XXX单元XXX号 44 * @param receive_zip 收货人邮编,如:123456 45 * @param receive_phone 收货人电话号码,如:0571-81234567 46 * @param receive_mobile 收货人手机号码,如:13312341234 47 * @param logistics_fee_1 第二组物流费用,即运费。 48 * @param logistics_type_1 第二组物流类型,三个值可选:EXPRESS(快递)、POST(平邮)、EMS(EMS) 49 * @param logistics_payment_1 第二组物流支付方式,两个值可选:SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费) 50 * @param logistics_fee_2 第三组物流费用,即运费。 51 * @param logistics_type_2 第三组物流类型,三个值可选:EXPRESS(快递)、POST(平邮)、EMS(EMS) 52 * @param logistics_payment_2 第三组物流支付方式,两个值可选:SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费) 53 * @param buyer_email 默认买家支付宝账号 54 * @param discount 折扣,是具体的金额,而不是百分比。若要使用打折,请使用负数,并保证小数点最多两位数 55 * @param input_charset 字符编码格式 目前支持 GBK 或 utf-8 56 * @param key 安全校验码 57 * @param sign_type 签名方式 不需修改 58 * @return 表单提交HTML文本 59 */ 60 public static String BuildForm(String partner, 61 String seller_email, 62 String return_url, 63 String notify_url, 64 String show_url, 65 String out_trade_no, 66 String subject, 67 String body, 68 String price, 69 String logistics_fee, 70 String logistics_type, 71 String logistics_payment, 72 String quantity, 73 String receive_name, 74 String receive_address, 75 String receive_zip, 76 String receive_phone, 77 String receive_mobile, 78 String logistics_fee_1, 79 String logistics_type_1, 80 String logistics_payment_1, 81 String logistics_fee_2, 82 String logistics_type_2, 83 String logistics_payment_2, 84 String buyer_email, 85 String discount, 86 String input_charset, 87 String key, 88 String sign_type){ 89 Map sPara = new HashMap(); 90 sPara.put("service","trade_create_by_buyer"); 91 sPara.put("payment_type","1"); 92 sPara.put("partner", partner); 93 sPara.put("seller_email", seller_email); 94 sPara.put("return_url", return_url); 95 sPara.put("notify_url", notify_url); 96 sPara.put("_input_charset", input_charset); 97 sPara.put("show_url", show_url); 98 sPara.put("out_trade_no", out_trade_no); 99 sPara.put("subject", subject); 100 sPara.put("body", body); 101 sPara.put("price", price); 102 sPara.put("logistics_fee", logistics_fee); 103 sPara.put("logistics_type", logistics_type); 104 sPara.put("logistics_payment", logistics_payment); 105 sPara.put("quantity", quantity); 106 sPara.put("receive_name", receive_name); 107 sPara.put("receive_address", receive_address); 108 sPara.put("receive_zip", receive_zip); 109 sPara.put("receive_phone", receive_phone); 110 sPara.put("receive_mobile", receive_mobile); 111 sPara.put("logistics_fee_1", logistics_fee_1); 112 sPara.put("logistics_type_1", logistics_type_1); 113 sPara.put("logistics_payment_1", logistics_payment_1); 114 sPara.put("logistics_fee_2", logistics_fee_2); 115 sPara.put("logistics_type_2", logistics_type_2); 116 sPara.put("logistics_payment_2", logistics_payment_2); 117 sPara.put("buyer_email", buyer_email); 118 sPara.put("discount", discount); 119 120 Map sParaNew = AlipayFunction.ParaFilter(sPara); //除去数组中的空值和签名参数121 String mysign = AlipayFunction.BuildMysign(sParaNew, key);//生成签名结果122 123 StringBuffer sbHtml = new StringBuffer(); 124 List keys = new ArrayList(sParaNew.keySet()); 125 String gateway = "https://www.alipay.com/cooperate/gateway.do?"; 126 127 //GET方式传递128 sbHtml.append("<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"" + gateway + "_input_charset=" + input_charset + "\" method=\"get\">"); 129 //POST方式传递(GET与POST二必选一) 130 //sbHtml.append("<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"" + gateway + "_input_charset=" + input_charset + "\" method=\"post\">");131 132 for (int i = 0; i < keys.size(); i++) { 133 String name = (String) keys.get(i); 134 String value = (String) sParaNew.get(name); 135 136 sbHtml.append("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\"/>"); 137 } 138 sbHtml.append("<input type=\"hidden\" name=\"sign\" value=\"" + mysign + "\"/>"); 139 sbHtml.append("<input type=\"hidden\" name=\"sign_type\" value=\"" + sign_type + "\"/>"); 140 141 //submit按钮控件请不要含有name属性 142 //sbHtml.append("<input type=\"submit\" value=\"支付宝确认付款\"></form>");143 144 sbHtml.append("<script>document.forms['alipaysubmit'].submit();</script>"); 145 return sbHtml.toString(); 146 } 147 148 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 整合Alipay发货信息同步 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓149 /**150 * 功能:把数组所有元素按照“参数=参数值”的模式用“&”字符拼接成字符串 151 * @param params 需要排序并参与字符拼接的参数组 152 * @param input_charset 编码格式 153 * @return 拼接后字符串 154 */ 155 public static String CreateLinkString_urlencode(Map params, String input_charset){ 156 List keys = new ArrayList(params.keySet()); 157 Collections.sort(keys); 158 159 String prestr = ""; 160 161 for (int i = 0; i < keys.size(); i++) { 162 String key = (String) keys.get(i); 163 String value = (String) params.get(key); 164 165 try { 166 prestr = prestr + key + "=" + URLEncoder.encode(value,input_charset) + "&"; 167 } catch (UnsupportedEncodingException e) { 168 169 e.printStackTrace(); 170 } 171 } 172 173 return prestr; 174 } 175 176 /**177 * 功能:远程xml解析 178 * @param partner 合作身份者ID 179 * @param trade_no 支付宝交易号。它是登陆支付宝网站在交易管理中查询得到,一般以8位日期开头的纯数字(如:20100419XXXXXXXXXX) 180 * @param logistics_name 物流公司名称 181 * @param invoice_no 物流发货单号 182 * @param transport_type 物流发货时的运输类型,三个值可选:POST(平邮)、EXPRESS(快递)、EMS(EMS) 183 * @param seller_ip 卖家本地电脑IP地址 184 * @param input_charset 字符编码格式 目前支持 GBK 或 utf-8 185 * @param key 安全校验码 186 * @param sign_type 签名方式 不需修改 187 * @return 获得解析结果 188 */ 189 public static String PostXml(String partner, 190 String trade_no, 191 String logistics_name, 192 String invoice_no, 193 String transport_type, 194 String seller_ip, 195 String input_charset, 196 String key, 197 String sign_type) throws Exception{ 198 Map sPara = new HashMap(); 199 sPara.put("service","send_goods_confirm_by_platform"); 200 sPara.put("partner", partner); 201 sPara.put("trade_no", trade_no); 202 sPara.put("logistics_name", logistics_name); 203 sPara.put("invoice_no", invoice_no); 204 sPara.put("transport_type", transport_type); 205 sPara.put("seller_ip", seller_ip); 206 sPara.put("_input_charset", input_charset); 207 208 Map sParaNew = AlipayFunction.ParaFilter(sPara); //除去数组中的空值和签名参数209 String mysign = AlipayFunction.BuildMysign(sParaNew, key);//生成签名结果210 211 sParaNew.put("sign", mysign); 212 sParaNew.put("sign_type", "MD5"); 213 214 String strUrl = "https://www.alipay.com/cooperate/gateway.do?_input_charset=utf-8"; 215 URL url = new URL(strUrl); 216 HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 217 conn.setRequestMethod("POST"); 218 conn.setDoInput(true); 219 conn.setDoOutput(true); 220 OutputStream os = conn.getOutputStream(); 221 os.write(CreateLinkString_urlencode(sParaNew,input_charset).getBytes("utf-8")); 222 os.close(); 223 224 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 225 String line; 226 String xmlResult =""; 227 while( (line =br.readLine()) != null ){ 228 xmlResult += "\n"+line; 229 } 230 br.close(); 231 232 return xmlResult; 233 } 234 }
====================== 华丽丽的分割线 ======================
4.alipay 页面跳转同步通知处理
4.1 页面跳转同步通知
当买家完成了支付流程后,会出现成功支付的页面,该页面做短暂停留后,会跳转到我们AlipayConfig.xml中的 return_url 属性所指定的页面,这称为页面跳转同步通知。
我们需要在该页面请求中,做相应的商业逻辑处理,如判断并更改订单状态,增加数据库中表示money的字段,注意:判断状态是十分必要的,避免重复进行操作。
4.2 returnURL
1 /** 2 * 功能:付完款后跳转的页面(页面跳转同步通知页面) 3 * WAIT_SELLER_SEND_GOODS(表示买家已在支付宝交易管理中产生了交易记录且付款成功,但卖家没有发货); 4 * TRADE_FINISHED(表示买家已经确认收货,这笔交易完成); 5 * 6 * @return 7 */ 8 public String returnURL() { 9 String key = AlipayConfig.key; 10 // 获取支付宝GET过来反馈信息 11 Map params = new HashMap(); 12 13 // MyServletContext 为自定义的类,可无视,换成如下写法: 14 // HttpServletRequet request = ServletActionContext.getRequest(); 15 HttpServletRequest request = MyServletContext.getRequest(); 16 17 Map requestParams = request.getParameterMap(); 18 for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { 19 String name = (String) iter.next(); 20 String[] values = (String[]) requestParams.get(name); 21 String valueStr = ""; 22 for (int i = 0; i < values.length; i++) { 23 valueStr = (i == values.length - 1) ? valueStr + values[i] 24 : valueStr + values[i] + ","; 25 } 26 // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 27 try { 28 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"); 29 } catch (UnsupportedEncodingException e) { 30 e.printStackTrace(); 31 } 32 params.put(name, valueStr); 33 } 34 35 // 判断responsetTxt是否为ture,生成的签名结果mysign与获得的签名结果sign是否一致 36 // responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 37 // mysign与sign不等,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 38 String mysign = AlipayNotify.GetMysign(params, key); 39 String responseTxt = AlipayNotify.Verify(request 40 .getParameter("notify_id")); 41 String sign = request.getParameter("sign"); 42 43 // 写日志记录(若要调试,请取消下面两行注释) 44 // String sWord = "responseTxt=" + responseTxt + 45 // "\n return_url_log:sign=" + sign + "&mysign=" + mysign + 46 // "\n return回来的参数:" + AlipayFunction.CreateLinkString(params); 47 // AlipayFunction.LogResult(sWord); 48 49 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)// 50 String trade_no = request.getParameter("trade_no"); // 支付宝交易号 51 String order_no = request.getParameter("out_trade_no"); // 获取订单号 52 String total_fee = request.getParameter("price"); // 获取总金额 53 String subject = ""; 54 try { 55 subject = new String(request.getParameter("subject").getBytes( 56 "ISO-8859-1"), "UTF-8"); 57 } catch (UnsupportedEncodingException e1) { 58 // TODO Auto-generated catch block 59 e1.printStackTrace(); 60 }// 商品名称、订单名称 61 62 String body = ""; 63 if (request.getParameter("body") != null) { 64 try { 65 body = new String(request.getParameter("body").getBytes( 66 "ISO-8859-1"), "UTF-8"); 67 } catch (UnsupportedEncodingException e) { 68 e.printStackTrace(); 69 }// 商品描述、订单备注、描述 70 } 71 String buyer_email = request.getParameter("buyer_email"); // 买家支付宝账号 72 String receive_name = "";// 收货人姓名 73 if (request.getParameter("receive_name") != null) { 74 try { 75 receive_name = new String(request.getParameter("receive_name") 76 .getBytes("ISO-8859-1"), "UTF-8"); 77 } catch (UnsupportedEncodingException e) { 78 e.printStackTrace(); 79 } 80 } 81 String receive_address = "";// 收货人地址 82 if (request.getParameter("receive_address") != null) { 83 try { 84 receive_address = new String(request.getParameter( 85 "receive_address").getBytes("ISO-8859-1"), "UTF-8"); 86 } catch (UnsupportedEncodingException e) { 87 e.printStackTrace(); 88 } 89 } 90 String receive_zip = "";// 收货人邮编 91 if (request.getParameter("receive_zip") != null) { 92 try { 93 receive_zip = new String(request.getParameter("receive_zip") 94 .getBytes("ISO-8859-1"), "UTF-8"); 95 } catch (UnsupportedEncodingException e) { 96 e.printStackTrace(); 97 } 98 } 99 String receive_phone = "";// 收货人电话100 if (request.getParameter("receive_phone") != null) { 101 try { 102 receive_phone = new String(request 103 .getParameter("receive_phone").getBytes("ISO-8859-1"), 104 "UTF-8"); 105 } catch (UnsupportedEncodingException e) { 106 // TODO Auto-generated catch block107 e.printStackTrace(); 108 } 109 } 110 String receive_mobile = "";// 收货人手机111 if (request.getParameter("receive_mobile") != null) { 112 try { 113 receive_mobile = new String(request.getParameter( 114 "receive_mobile").getBytes("ISO-8859-1"), "UTF-8"); 115 } catch (UnsupportedEncodingException e) { 116 e.printStackTrace(); 117 } 118 } 119 String trade_status = request.getParameter("trade_status"); // 交易状态 120 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// 121 122 String verifyStatus = ""; 123 if (mysign.equals(sign) && responseTxt.equals("true")) { 124 //////////////////////////////////////////////////////////////////////////////////////////125 // 请在这里加上商户的业务逻辑程序代码 126 127 // ——请根据您的业务逻辑来编写程序(以下代码仅作参考)——128 if (trade_status.equals("WAIT_SELLER_SEND_GOODS")) { 129 // 判断该笔订单是否在商户网站中已经做过处理(可参考“集成教程”中“3.4返回数据处理”) 130 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 131 // 如果有做过处理,不执行商户的业务程序 132 133 // if ("WAIT_BUYER_PAY".equals(memberMoney.getRemark()) 134 // && mMoney == Double.parseDouble(total_fee)) { 135 // memberMoney.setRemark("WAIT_BUYER_CONFIRM_GOODS"); 136 // memberMoneyService.saveOrUpdate(memberMoney); 137 // Members member = memberService.get(mid); 138 // if(member.getIdealMoney()==null){ // 这里是前人的数据库设置不合理,没给金钱这字段默认值,故判断其是否为空 139 // member.setIdealMoney(mMoney); 140 // }else{ 141 // member.setIdealMoney(member.getIdealMoney() + mMoney); 142 // } 143 // memberService.saveOrUpdate(member); // 如果订单状态为默认状态,则添加金钱 144 // } 145 // try { 146 //// 这里是发货信息同步 147 // String xmlResult = AlipayService.PostXml( 148 // AlipayConfig.partner, trade_no, "直接充值", 149 // "请到个人中心-我的钱包查看充值货币", "EXPRESS", "", 150 // AlipayConfig.input_charset, AlipayConfig.key, 151 // AlipayConfig.sign_type); 152 // } catch (Exception e) { 153 // e.printStackTrace(); 154 // }155 156 } 157 158 // ——请根据您的业务逻辑来编写程序(以下代码仅作参考)——159 if (trade_status.equals("TRADE_FINISHED")) { 160 // 判断该笔订单是否在商户网站中已经做过处理(可参考“集成教程”中“3.4返回数据处理”) 161 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 162 // 如果有做过处理,不执行商户的业务程序 163 164 // if ("WAIT_BUYER_PAY".equals(memberMoney.getRemark()) 165 // && mMoney == Double.parseDouble(total_fee)) { 166 // memberMoney.setRemark("TRADE_FINISHED"); 167 // memberMoneyService.saveOrUpdate(memberMoney); 168 // Members member = memberService.get(mid); 169 // if(member.getIdealMoney()==null){ 170 // member.setIdealMoney(mMoney); 171 // }else{ 172 // member.setIdealMoney(member.getIdealMoney() + mMoney); 173 // } 174 // memberService.saveOrUpdate(member); // 如果订单状态为默认状态,则添加金钱 175 //176 // try { 177 //// 这里是发货信息同步 178 179 // String xmlResult = AlipayService.PostXml( 180 // AlipayConfig.partner, trade_no, "直接充值", 181 // "个人中心请查看充值货币", "EXPRESS", "", 182 // AlipayConfig.input_charset, AlipayConfig.key, 183 // AlipayConfig.sign_type); 184 // } catch (Exception e) { 185 // e.printStackTrace(); 186 // } 187 // } else if ("WAIT_BUYER_CONFIRM_GOODS".equals(memberMoney 188 // .getRemark()) 189 // && mMoney == Double.parseDouble(total_fee)) { 190 // memberMoney.setRemark("TRADE_FINISHED"); 191 // memberMoneyService.saveOrUpdate(memberMoney); 192 // } 193 // 194 } 195 196 verifyStatus = "验证成功"; 197 // ——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— 198 199 ////////////////////////////////////////////////////////////////////////////////////////// 200 } else { 201 verifyStatus = "验证失败"; 202 } 203 return SUCCESS; 204 }
4.3 struts.xml
1 <!-- 上面略,该action用于页面跳转同步通知 --> 2 <action name="payMoney" class="AlipayAction" method="payMoney"> 3 <result name="success">alipayto.jsp</result> 4 <result name="input">exception.jsp</result> 5 </action>
====================== 华丽丽的分割线 ======================
5.alipay 服务器异步通知处理
5.1 服务器异步通知
买家在支付宝中完成交易,付了款后,会出现如下页面:
该页面做数秒停留后,会跳转到 AlipayConfig.xml 中的 return_url 属性所指定的页面,这称为页面跳转同步通知(如前所述),而商业网站便在被调用的页面中,做业务逻辑处理。
但是,买家可能在 Alipay 尚未跳转前,便把上面那页面关闭,这时怎么办?
为解决这问题 ,支付宝便有了服务器异步通知。即每当交易状态发生变化,Alipay 都会主动通知AlipayConfig.xml 中的 notify_url 属性所指定的页面(该action不能有返回值,也不能跳转)。这样做确实解决了该问题,但也带来了可能重复调用,故,我们需要判断alipay传过来的状态是否被处理过,若处理过,则不重复执行。
5.2 notifyURL
逻辑处理语句略!!!
1 /** 2 * 功能:支付宝主动通知调用的页面(服务器异步通知页面) 3 * 4 * @return 5 */ 6 public void notifyURL() { 7 String key = AlipayConfig.key; 8 // 获取支付宝POST过来反馈信息 9 Map params = new HashMap(); 10 //HttpServletRequest request = ServletActionContext.getRequest(); 11 HttpServletRequest request = MyServletContext.getRequest(); 12 PrintWriter out = null; 13 try { 14 // out = ServletActionContext.getResponse().getWriter(); 15 out = MyServletContext.getResponse().getWriter(); 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } 19 Map requestParams = request.getParameterMap(); 20 for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { 21 String name = (String) iter.next(); 22 String[] values = (String[]) requestParams.get(name); 23 String valueStr = ""; 24 for (int i = 0; i < values.length; i++) { 25 valueStr = (i == values.length - 1) ? valueStr + values[i] 26 : valueStr + values[i] + ","; 27 } 28 // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 29 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"); 30 params.put(name, valueStr); 31 } 32 33 // 判断responsetTxt是否为ture,生成的签名结果mysign与获得的签名结果sign是否一致 34 // responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 35 // mysign与sign不等,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 36 String mysign = AlipayNotify.GetMysign(params, key); 37 String responseTxt = AlipayNotify.Verify(request 38 .getParameter("notify_id")); 39 String sign = request.getParameter("sign"); 40 41 // 写日志记录(若要调试,请取消下面两行注释) 42 String sWord = "responseTxt=" + responseTxt + "\n notify_url_log:sign=" 43 + sign + "&mysign=" + mysign + "\n notify回来的参数:" 44 + AlipayFunction.CreateLinkString(params); 45 AlipayFunction.LogResult(sWord); 46 47 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)// 48 String trade_no = request.getParameter("trade_no"); // 支付宝交易号 49 String order_no = request.getParameter("out_trade_no"); // 获取订单号 50 String total_fee = request.getParameter("price"); // 获取总金额 51 String subject = ""; 52 try { 53 subject = new String(request.getParameter("subject").getBytes( 54 "ISO-8859-1"), "UTF-8"); 55 } catch (UnsupportedEncodingException e) { 56 e.printStackTrace(); 57 }// 商品名称、订单名称 58 String body = ""; 59 if (request.getParameter("body") != null) { 60 try { 61 body = new String(request.getParameter("body").getBytes( 62 "ISO-8859-1"), "UTF-8"); 63 } catch (UnsupportedEncodingException e) { 64 e.printStackTrace(); 65 }// 商品描述、订单备注、描述 66 } 67 String buyer_email = request.getParameter("buyer_email"); // 买家支付宝账号 68 String receive_name = "";// 收货人姓名 69 if (request.getParameter("receive_name") != null) { 70 try { 71 receive_name = new String(request.getParameter("receive_name") 72 .getBytes("ISO-8859-1"), "UTF-8"); 73 } catch (UnsupportedEncodingException e) { 74 e.printStackTrace(); 75 } 76 } 77 String receive_address = "";// 收货人地址 78 if (request.getParameter("receive_address") != null) { 79 try { 80 receive_address = new String(request.getParameter( 81 "receive_address").getBytes("ISO-8859-1"), "UTF-8"); 82 } catch (UnsupportedEncodingException e) { 83 e.printStackTrace(); 84 } 85 } 86 String receive_zip = "";// 收货人邮编 87 if (request.getParameter("receive_zip") != null) { 88 try { 89 receive_zip = new String(request.getParameter("receive_zip") 90 .getBytes("ISO-8859-1"), "UTF-8"); 91 } catch (UnsupportedEncodingException e) { 92 e.printStackTrace(); 93 } 94 } 95 String receive_phone = "";// 收货人电话 96 if (request.getParameter("receive_phone") != null) { 97 try { 98 receive_phone = new String(request 99 .getParameter("receive_phone").getBytes("ISO-8859-1"), 100 "UTF-8"); 101 } catch (UnsupportedEncodingException e) { 102 e.printStackTrace(); 103 } 104 } 105 String receive_mobile = "";// 收货人手机106 if (request.getParameter("receive_mobile") != null) { 107 try { 108 receive_mobile = new String(request.getParameter( 109 "receive_mobile").getBytes("ISO-8859-1"), "UTF-8"); 110 } catch (UnsupportedEncodingException e) { 111 e.printStackTrace(); 112 } 113 } 114 String trade_status = request.getParameter("trade_status"); // 交易状态 115 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// 116 117 if (mysign.equals(sign) && responseTxt.equals("true")) {// 验证成功 118 //////////////////////////////////////////////////////////////////////////////////////////119 // 请在这里加上商户的业务逻辑程序代码 120 121 122 // —— 请根据您的业务逻辑来编写程序(以下代码仅作参考)——123 if (trade_status.equals("WAIT_BUYER_PAY")) { 124 // 该判断表示买家已在支付宝交易管理中产生了交易记录,但没有付款 125 126 // 判断该笔订单是否在商户网站中已经做过处理(可参考“集成教程”中“3.4返回数据处理”) 127 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 128 // 如果有做过处理,不执行商户的业务程序 129 // 不做处理130 out.println("success"); // 请不要修改或删除131 } else if (trade_status.equals("WAIT_SELLER_SEND_GOODS")) { 132 // 该判断表示买家已在支付宝交易管理中产生了交易记录且付款成功,但卖家没有发货 133 134 // 判断该笔订单是否在商户网站中已经做过处理(可参考“集成教程”中“3.4返回数据处理”) 135 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 136 // 如果有做过处理,不执行商户的业务程序137 138 139 out.println("success"); // 请不要修改或删除140 } else if (trade_status.equals("WAIT_BUYER_CONFIRM_GOODS")) { 141 // 该判断表示卖家已经发了货,但买家还没有做确认收货的操作 142 143 // 判断该笔订单是否在商户网站中已经做过处理(可参考“集成教程”中“3.4返回数据处理”) 144 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 145 // 如果有做过处理,不执行商户的业务程序146 147 out.println("success"); // 请不要修改或删除148 } else if (trade_status.equals("TRADE_FINISHED")) { 149 // 该判断表示买家已经确认收货,这笔交易完成 150 151 // 判断该笔订单是否在商户网站中已经做过处理(可参考“集成教程”中“3.4返回数据处理”) 152 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 153 // 如果有做过处理,不执行商户的业务程序154 155 156 out.println("success"); // 请不要修改或删除157 } else { 158 out.println("success"); // 请不要修改或删除159 } 160 // ——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— 161 162 ////////////////////////////////////////////////////////////////////////////////////////// 163 }else {// 验证失败164 out.println("fail"); 165 } 166 }
5.3 struts.xml
1 <!-- 上面略,该action不能执行任何跳转 --> 2 <action name="notifyURL" class="AlipayAction" method="notifyURL"/>
相关推荐
支付宝即时转账接口是支付宝提供的一种在线支付服务,...以上就是关于“alipay转账接口java版”的主要知识点。在具体实践中,还需要遵循支付宝的开发文档,确保所有步骤都符合其规定,以保证接口调用的成功和安全性。
在这个“alipay所有支付接口java版及说明文档”中,我们主要会探讨以下几个关键知识点: 1. **Java SDK**: Alipay提供了Java版本的SDK,它包含了一系列的类和方法,用于与支付宝服务器进行通信。这些类通常封装了...
支付宝SDK是支付宝提供的工具Jar包,封装了大量的基础功能,使我们可以快速开发支付宝接口。下载解压后的SDK,得到alipay-sdk-java20180122110032.jar、commons-logging-1.1.1.jar等文件,然后将其导入到项目里。...
首先,“alipay-sdk-java”是一个Java版本的SDK,它包含了支付宝接口调用所需的类库和方法。这些类库涵盖了支付、退款、查询订单状态、用户授权等众多功能。使用这个SDK,开发者可以快速地在自己的Java应用中集成...
提供支付宝开放平台的单笔转账到支付宝账户接口JAVA版本demo 望大家共同进步
在进行支付宝接口开发时,开发者需要熟悉Alipay SDK,它提供了与支付宝服务器通信的类库和方法。SDK中包括了签名算法、请求构建、响应解析等关键功能,确保了交易的安全性和正确性。此外,开发者还需要了解支付宝的...
以上就是关于Java支付宝接口程序的主要知识点,涵盖了接口的原理、使用流程、核心组件和注意事项。理解并熟练掌握这些内容,开发者就能在自己的Java项目中顺利集成支付宝支付功能,提升用户体验。
"alipay-sdk-java20170307171631.jar"是支付宝专门为Java开发者提供的SDK,它包含了实现支付宝接口调用所需的类库和配置文件,使得开发者能够便捷地在Java环境中集成支付宝的各种服务,如在线支付、退款、查询订单...
"alipay_sdk_java" 是一个专门针对Java平台的支付宝SDK(Software Development Kit),它提供了与支付宝接口进行交互的工具和库。这个SDK主要用于帮助开发者在Java应用中集成支付宝的各项服务,比如支付、退款、查询...
2. **签名机制**: 支付宝接口使用了非对称加密的RSA算法进行签名,确保数据传输过程中的安全性。商户使用自己的私钥对请求参数进行签名,而支付宝会用商户的公钥来验证签名的有效性。 3. **请求接口**: 使用SDK中的...
1. **支付宝接口介绍**: 支付宝提供了一系列的API接口,让开发者能够在自己的应用或网站上实现支付功能。这些接口通常包括但不限于订单创建、支付请求、支付结果查询、退款处理等关键步骤。 2. **iOS集成**: ...
- **alipay-sdk-java20180104135026.jar**:这是核心SDK库文件,包含了所有与支付宝接口交互所需的类和方法。 - **alipay-sdk-java20180104135026-source.jar**:源代码文件,对于开发者来说,查看源码有助于理解...
2. 配置参数:创建一个配置文件,包含支付宝接口所需的商户ID、私钥、公钥、签名方式等信息。 3. 创建客户端:使用SDK提供的`AlipayClient`类,根据配置文件初始化客户端实例。 4. 调用接口:通过客户端实例,调用...
总结来说,“alipay支付Demo-springboot整合版”是一个帮助开发者快速上手支付宝接口的示例项目,它展示了如何在SpringBoot应用中集成支付宝接口,以及在沙箱环境中进行测试的基本流程。通过这个Demo,开发者可以...
这个库包含了加密算法、请求和响应处理、异常处理等核心组件,是所有支付宝接口调用的基石。开发者可以通过这个库中的类和方法,构建请求参数,进行签名验证,以及解析支付宝返回的结果。 `alipay-trade-sdk-1.0.0....
7. **错误处理和重试机制**:在调用支付宝接口时,可能会遇到网络问题、服务器错误等,需要有适当的错误处理机制和重试逻辑,保证支付流程的健壮性。 总的来说,使用这个定制的ASP支付宝支付接口,开发者可以在其...
支付宝APP支付Java版是支付宝为开发者提供的一种便捷的在线支付接口,主要应用于移动应用中的商品购买、服务费用收取等场景。在Java环境下实现支付宝APP支付,开发者需要掌握以下几个关键知识点: 1. **集成SDK**: ...
根据给定的信息,“支付宝支付Java版”主要涉及的是利用Java编程语言实现的支付宝支付系统开发。下面将围绕这个主题展开详细介绍。 ### Java支付系统的基本概念 在电子商务领域中,支付系统是连接商家与消费者的...
支付宝接口测试Demo主要展示了如何...以上就是关于"支付宝接口测试Demo"的主要知识点,涵盖了JAVA和PHP两个版本的接口调用流程和注意事项。通过这个Demo,开发者可以快速理解并实现在自己的应用中接入支付宝支付功能。