- 浏览: 17981 次
- 性别:
- 来自: 长沙
最新评论
关于Alipay支付宝接口(Java版)
2013-03-26 15:53:37| 分类: java |举报 |字号 订阅
1.alipay 双功能支付简介
2.alipay 提交支付订单
3.alipay 整合双功能支付及发货信息同步
4.alipay 页面跳转同步通知处理
5.alipay 服务器异步通知处理
====================== 华丽丽的分割线 ======================
1.alipay 双功能支付简介
1.1 使用流程
在网站中生成订单信息,并记录到数据库中,将订单信息及其他必要信息按照alipayto指定的形式,发给支付宝,也就是生成完了调AlipayService.BuildForm() 方法,改方法会返回一串字符串,里面记录着表单信息,无需更改返回的字符串,并使之打印到页面上(该字符串有js写的自动提交表单)。
但是,上述的情况只是在用户每关闭我们网站的时候才会出现,事实上,有可能用户在没付款结束时就关闭了网站。支付宝为解决这个问题,使用了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;若不支持请选择http
60 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 ////构造函数,生成请求URL
114 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 block
107 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" />
2013-03-26 15:53:37| 分类: java |举报 |字号 订阅
1.alipay 双功能支付简介
2.alipay 提交支付订单
3.alipay 整合双功能支付及发货信息同步
4.alipay 页面跳转同步通知处理
5.alipay 服务器异步通知处理
====================== 华丽丽的分割线 ======================
1.alipay 双功能支付简介
1.1 使用流程
在网站中生成订单信息,并记录到数据库中,将订单信息及其他必要信息按照alipayto指定的形式,发给支付宝,也就是生成完了调AlipayService.BuildForm() 方法,改方法会返回一串字符串,里面记录着表单信息,无需更改返回的字符串,并使之打印到页面上(该字符串有js写的自动提交表单)。
但是,上述的情况只是在用户每关闭我们网站的时候才会出现,事实上,有可能用户在没付款结束时就关闭了网站。支付宝为解决这个问题,使用了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;若不支持请选择http
60 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 ////构造函数,生成请求URL
114 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 block
107 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" />
发表评论
-
Java开发中遇到的小问题总结
2014-12-11 17:49 628昨天有人在群里问说JSP页面发送请求后获取参数属性值乱码,re ... -
Java实现之网络爬虫
2014-12-08 20:52 809最近公司闲来无事,看到了Apache nutch项目,记得前段 ... -
Java实现判断电话号码运行商
2014-12-04 12:05 1805项目需求描述: 后台统计电话号码发送短信统计,要求选择运行商选 ... -
Java编程之代码优化
2014-12-02 15:47 691可供程序利用的资源(内存、CPU时间、网络带宽等)是有限的,优 ... -
JAVA的Random类
2014-11-27 17:28 382Random类 (java.util) ... -
Java开发ui工具对比
2014-11-26 09:47 462最近由于项目需要,对js UI作了一些简单的了解和使用,有自己 ... -
汉字按拼音首字母查询
2014-11-17 15:16 1599按汉字首字母搜索的功能,即:输入“bj”得到“北京”; 注 ...
相关推荐
网上支付与电子银行是现代信息技术在金融领域的重要应用,它们极大地改变了人们的交易方式,使得资金流动更为便捷、高效。这个课件"网上支付与电子银行"涵盖了这一领域的核心概念、技术原理以及实际操作。 首先,...
### 网上支付接口的实现 随着电子商务的迅速发展,网上支付已成为现代网络交易中不可或缺的一部分。本文将深入探讨网上支付接口的实现方法及其在购物模块中的应用,旨在帮助开发者更好地理解并掌握这一关键技能。 ...
《农行网上支付平台-商户接口编程指南-Java Edition-V3.1.7》是一份由农业银行开发的针对开发者和商户的编程指南,用于指导如何通过Java语言接入并使用农行的网上支付平台进行交易处理。这份指南覆盖了接口的详细...
《帅青红网上支付与电子银行课件》是一份详尽的教育资源,涵盖了网上支付与电子银行领域的核心概念和实践应用。这份由帅青红和夏军飞编著的课件,出自东北财经大学出版社,旨在帮助学习者深入理解这个在信息化时代日...
这份农行网上支付平台商户接口编程指南主要针对使用***技术的开发人员,旨在详细说明如何通过编程实现与中国农业银行网上支付平台的对接。指南从发布至2019年的V3.1.6版本经历了多次更新,每次更新都对功能进行了...
网上支付的ppt
《农行网上支付平台-商户接口编程指南-Java_Edition-V3.1.6》是农业银行为开发者提供的一份详尽的参考资料,旨在帮助商户快速理解和接入其网上支付系统。这份指南专为Java开发人员设计,涵盖了从基础概念到实际操作...
### 网上支付两种接入方式详解 #### 直接与银行对接 **优点:** - **资金安全性高:**由于直接与银行进行财务结算,因此资金的安全性相对较高,适合那些对资金流转安全性有较高要求的企业。 - **适用范围广:**...
实现网上支付需要可靠的支付网关和安全协议,如SSL、SET等,以确保交易信息的安全性和用户隐私的保护。 【网上银行】 网上银行是传统银行服务的数字化延伸,让用户能够通过互联网进行账户查询、转账、支付等操作。...
韩顺平老师是知名的IT教育专家,他的“php 网上支付讲座”深入浅出地讲解了如何使用PHP实现安全、可靠的在线支付系统。 首先,我们来探讨PHP在构建网上支付系统中的核心知识点。支付接口是连接商家网站与支付网关的...
RA审核操作员负责收集并保存网上支付跨行清算系统业务主管部门审核后提交的网上支付跨行清算系统参与者的证书申请表、审核网上支付跨行清算系统参与者的证书申请和证书管理操作申请、查询和统计所有网上支付跨行清算...
《农行网上支付平台-商户接口编程指南-ASP.NET_Edition-V3.1.6》是一份详尽的文档,旨在指导开发者如何利用ASP.NET技术与农业银行的网上支付平台进行有效集成,以便商户能够接收和处理在线支付。这份指南在2019年...
**知识点详解:B2B电子商务网上支付技术方案(公共类支付)** ### 一、背景与目标 在当今数字化时代,随着中国互联网技术的迅速发展,电子政务已成为推动政府管理创新的重要驱动力,特别是在提高公共服务质量和扩大...
首先,网上支付平台的基础是处理交易和安全。在PHP中,你需要理解HTTP协议和POST请求,这是用户提交支付信息的方式。同时,你将学习如何使用PHP的$_POST全局变量来接收这些数据。 其次,支付平台的核心是支付接口的...
**电子商务网上支付系统探析** 电子商务(e-commerce)是指通过互联网进行的商品和服务交易。随着互联网技术的飞速发展,电子商务已成为全球经济的重要组成部分。其中,网上支付系统是电子商务中不可或缺的一环,它...
随着互联网技术的飞速发展,网上支付已成为现代社会生活中不可或缺的一部分。网上支付不仅为消费者和商家提供了一种便捷、高效的交易方式,还为金融机构拓展业务范围带来了新的机遇。本文将深入分析网上支付模式,并...
【Web服务 - 网上支付系统】 网上支付系统是一种基于Web技术的电子商务基础设施,它使得用户能够在互联网上安全地进行购物、转账等金融交易。本项目是开发一个基于JSP(JavaServer Pages)、Servlet和JavaBean技术...