支付寶開發文檔:https://b.alipay.com/order/techService.htmhtml
1.alipay 雙功能支付簡介java
2.alipay 提交支付訂單數據庫
3.alipay 整合雙功能支付及發貨信息同步數組
4.alipay 頁面跳轉同步通知處理瀏覽器
5.alipay 服務器異步通知處理安全
====================== 華麗麗的分割線 ======================服務器
1.alipay 雙功能支付簡介app
1.0 L.z的嘮叨異步
網上copy的東西那麼多,查個東西在百度上google一下都搜不到個完整,我恨!代碼仍是看本身整理的比較好。jsp
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 一、檢查瀏覽器配置,不讓瀏覽器作彈框屏蔽設置
16 二、更換瀏覽器或電腦,從新登陸查詢。
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">
<body> <div> <!-- escape 用於設置是否編碼,若爲true會將內容(如:空格會被轉成 )進行轉換,建議設置成false,事實上,設置成true麻煩事更多 --> <s:property value="sHtmlText" escape="false"/> </div> </body>
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("");
143
144 sbHtml.append("");
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
2
3
4
5
====================== 華麗麗的分割線 ======================
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 2