Java SpringMVC 支付寶-即時支付介面-ping++支付
一. 前言介紹:
前幾天突然要做支付寶的支付功能,因為以前一直沒有做過支付功能,所以比較茫然,但是後來經過不斷摸索和前輩指導,終於做了出來;後來發現,其實做支付寶的支付功能也並不難。
二.正文:
首先你要搞到商家的支付寶賬號,合作者ID
(1).第一步要先能夠跳轉到支付寶的支付介面(可以本地測試)。
(2).第二部完成支付跳轉回商家介面(必須線上測試,因為返回回來,支付寶找不到你的localhost:8080;所以必須要有域名(地址))。
首先在支付寶官網下載java的即時支付包,然後根據自己所需要,拷貝進它的原始碼,也可以全部拷入,但是不一定全部能用。
對於:資料互動方式可以用jsp,也可以用控制器。支付寶給的demo是用的jsp實現。
而我們用的是控制器實現;線面就用控制器介紹:
程式碼:
package com...web.alipay;
@Controller
@RequestMapping(value = "/alipay")
public class alipayController {
@Autowired
private AlipayService alipayService;
@Autowired
private ProjectService projectService;
@Autowired
private ProjectAcceleratorService projectAcceleratorService;
//跳轉支付寶網站的方法
@RequestMapping(value = "/deposit", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity deposit(HttpServletRequest request,HttpServletResponse response,Model model){
//防釣魚時間戳
防釣魚時間戳這裡沒寫,貌似要先去支付寶申請,要稽核一個星期左右,通過了才能用
Date date = new Date();
// 支付型別
// 必填,不能修改
String payment_type = "1";
// 伺服器非同步通知頁面路徑
// 需http://格式的完整路徑,不能加?id=123這類自定義引數
String notify_url = "http://“自己網站的域名”/alipay/async";
// 頁面跳轉同步通知頁面路徑
// 需http://格式的完整路徑,不能加?id=123這類自定義引數,不能寫成http://localhost/
String return_url = "http://“自己網站的域名”/alipay/return_url";
// 商戶訂單號.
// 商戶網站訂單系統中唯一訂單號,必填
//String out_trade_no = date.getTime() + "";
// 訂單名稱
// 必填
String projectId = request.getParameter("projectId");
if(projectId != null){
ProjectEntity project = projectService.getProject(projectId);
if(project != null){
//從支付頁面獲取值
//商品名稱
String subject = project.getName();
//String WIDout_trade_no = request.getParameter("WIDout_trade_no");
// 防釣魚時間戳
// 若要使用請呼叫類檔案submit中的query_timestamp函式
//String anti_phishing_key = "";
// 客戶端的IP地址
// 非區域網的外網IP地址,如:
String exter_invoke_ip = ""; 可不填
String total_fee = project.getReward();
String body = project.getSummary();
//商品展示地址
String show_url = "";可不填
//需以http://開頭的完整路徑,例如:http://www.xxx.com/myorder.html
Map sParaTemp = new HashMap();
sParaTemp.put("service", "create_direct_pay_by_user");//介面服務----即時到賬
sParaTemp.put("partner", AlipayConfig.partner);//支付寶PID
sParaTemp.put("_input_charset", AlipayConfig.input_charset);//統一編碼
sParaTemp.put("payment_type", payment_type);//支付型別
sParaTemp.put("notify_url", notify_url);//非同步通知頁面
sParaTemp.put("return_url", return_url);//頁面跳轉同步通知頁面
sParaTemp.put("seller_email", "");//賣家支付寶賬號
sParaTemp.put("out_trade_no", date.getTime()+payment_type);//商品訂單編號
sParaTemp.put("subject", subject);//商品名稱
sParaTemp.put("total_fee", total_fee);//價格
sParaTemp.put("body", body);
sParaTemp.put("extra_common_param", extra_common_param);
sParaTemp.put("show_url", show_url);
//sParaTemp.put("anti_phishing_key", anti_phishing_key);
sParaTemp.put("exter_invoke_ip", exter_invoke_ip);
String sHtmlText = AlipaySubmit.buildRequest(sParaTemp,"get","確認");
try {
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setContentType("text/html; charset=utf-8");
response.getWriter().write(sHtmlText);
response.getWriter().close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
@SuppressWarnings("rawtypes")
@RequestMapping(value="/async",method = RequestMethod.POST)
public String async(HttpServletRequest request,HttpServletResponse response){
Map params = new HashMap();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]: valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
//獲取返回資料
String orderTitle = request.getParameter("subject");//訂單名稱
String payType = request.getParameter("payment_type");//支付型別
String outTradeNo = request.getParameter("out_trade_no");//訂單號
String tradeNo = request.getParameter("trade_no");//支付寶交易號
String notifyId = request.getParameter("notify_id");//支付校驗id
String amount = request.getParameter("total_fee");//交易金額
String notifyTime = request.getParameter("notify_time");//通知時間
String tradeStatus = request.getParameter("trade_status");//交易狀態
String returnId = request.getParameter("extra_common_param");//專案id
String payer = request.getParameter("buyer_email");//支付者賬號
//
if(AlipayNotify.verify(params)){//驗證成功
if(tradeStatus.equals("TRADE_FINISHED") || tradeStatus.equals("TRADE_SUCCESS")) {
//要寫的邏輯。自己按自己的要求寫
//封裝交易資訊實體,存入資料庫之類的
System.out.println(">>>>>非同步返回:" + tradeNo);
}
return "success/alipay-success";
}else{//驗證失敗
return "success/alipay-fail";
}
}
@RequestMapping(value="/return_url",method = RequestMethod.GET)
public String Return_url(HttpServletRequest request,HttpServletResponse response){
Map params = new HashMap();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]: valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
String tradeNo = request.getParameter("trade_no");//支付寶交易號
String tradeStatus = request.getParameter("trade_status");//交易狀態
if(AlipayNotify.verify(params)){//驗證成功
if(tradeStatus.equals("TRADE_FINISHED") || tradeStatus.equals("TRADE_SUCCESS")) {
//要寫的邏輯。自己按自己的要求寫
System.out.println(">>>>>充值成功" + tradeNo);
}
return "...";
}else{//驗證失敗
return "success/fail";
}
}
}
支付流程:
先訪問 /deposit 對映下面的方法 ---> 跳轉到支付寶的支付介面 ---> 核對支付資訊進行支付 (測試一般用1分錢)--->支付成功 --->支付寶同時呼叫同步和非同步方法;
但是非同步方法一般要快於同步方法,因為中間還有一個跳轉流程。所以這裡特別注意的是:如果你要講支付寶返回來的資訊存入資料庫,邏輯一般是寫在非同步方法裡面,同步方法作為頁面跳轉(跳你自己的網站頁面)。如果把邏輯寫在同步方法裡面,客戶在支付成功直接關閉視窗,沒返回你的網站的話,它是訪問不到你的控制器的。
而且對於非同步方法訪問的方法是要在瀏覽器上直接訪問到的!但是一般我們網站都做了許可權過濾的,直接方法方法,要先去判斷是否登入,沒登入一般跳轉登入介面。但是不論你是用的過濾器還是 shiro,還是其它的,總之你要暴露出這個方法要讓支付寶能訪問(不能夠跳登入介面)!
並且這個非同步方法返回的jsp不能有其它程式碼:
我就只寫了: <%=%>