場景
最近在做支付寶的接口對接染坯,之前做過一個版本稽揭,但是由于申請了新的賬號以前舊的的接口對接就不能使用了
所以就開始對接新的版本接口對接翔忽,在這里也記錄一下讓那些還沒有對接的兄弟少走點彎路呼渣。
準備
先申請一個企業(yè)賬戶
https://memberprod.alipay.com/account/reg/enterpriseIndex.htm
創(chuàng)建應(yīng)用
去支付寶的開放平臺
https://open.alipay.com/platform/home.htm
添加應(yīng)用:
https://docs.open.alipay.com/200/105310
按照這個鏈接的文檔一步一步操作蔑祟;
賬號準備好之后早敬,就可以了解相關(guān)的接口了忌傻,以(即時到賬)支付接口為例。
閱讀接口文檔
https://docs.open.alipay.com/270/alipay.trade.page.pay/
下載SDK
https://docs.open.alipay.com/54/103419
選擇java版本
將sdk集成進入項目中
sdk中有一個jar包
將這個jar包上傳到私服上去搞监。
參考這個:
http://blog.csdn.net/huchunlinnk/article/details/17789175
項目引入sdk中的關(guān)鍵jar包
這里的gav的寫法取決于你上傳私服的時候的填寫
com.alipay
alipay-api
1.0.0
處理AlipayConfig對象
取消AlipayConfig配置文件中的部分常量
打開下載sdk應(yīng)該可以找到
將這個類中的前幾個靜態(tài)常量變成非靜態(tài)的水孩,以便可以支持多個配置對象。
/*?*
*類名:AlipayConfig
*功能:基礎(chǔ)配置類
*詳細:設(shè)置帳戶有關(guān)信息及返回路徑
*修改日期:2017-04-05
*說明:
*以下代碼只是為了方便商戶測試而提供的樣例代碼琐驴,商戶可以根據(jù)自己網(wǎng)站的需要俘种,按照技術(shù)文檔編寫,并非一定要使用該代碼。
*該代碼僅供學習和研究支付寶接口使用绝淡,只是提供一個參考宙刘。
*/
@Data
publicclassAlipayConfig{
//↓↓↓↓↓↓↓↓↓↓請在這里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//?應(yīng)用ID,您的APPID,收款賬號既是您的APPID對應(yīng)支付寶賬號
publicString?app_id?="";
//?商戶私鑰牢酵,您的PKCS8格式RSA2私鑰
publicString?merchant_private_key?="";
//?支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm?對應(yīng)APPID下的支付寶公鑰悬包。
publicString?alipay_public_key?="";
//?服務(wù)器異步通知頁面路徑??需http://格式的完整路徑,不能加?id=123這類自定義參數(shù)馍乙,必須外網(wǎng)可以正常訪問
publicString?notify_url?="";
//?頁面跳轉(zhuǎn)同步通知頁面路徑?需http://格式的完整路徑布近,不能加?id=123這類自定義參數(shù),必須外網(wǎng)可以正常訪問
publicString?return_url?="";
//?簽名方式
publicstaticString?sign_type?="RSA2";
//?字符編碼格式
publicstaticString?charset?="utf-8";
//?支付寶網(wǎng)關(guān)
publicstaticString?gatewayUrl?="https://openapi.alipay.com/gateway.do";
//日志路徑
publicstaticString?log_path?="C:\\";
}
公眾號注:文中代碼看不全可左右滑動
編寫請求支付的接口
后端向支付寶發(fā)起支付的請求潘拨,在這個同時需要傳遞必要參數(shù)吊输,下面我們就來編寫如何向支付寶發(fā)起支付。
編寫conroller層
/**
*?阿里支付控制器
*
*@authorWangSen(wangsenhehe@126.com)
*@Date2017年8月16日
*/
@Controller
@RequestMapping("/alipay")
publicclassAliPayController{
@Autowired
privateAlipayViewService?alipayViewService;
/**
*?跳轉(zhuǎn)到去支付的jsp頁面
*
*@paramorderId?訂單號
*
*@parampayAccountType?支付賬號類型
*
*@parammodel?模型
*
*@throwsException
*/
@RequestMapping
publicvoidgotopay(longorderId,?Model?model)throwsException{
alipayViewService.setGoToPayInfo(orderId,?model);
}
}
編寫viewService層
/**
*?阿里支付頁面服務(wù)類
*
*@authorWangSen(wangsenhehe@126.com)
*@Date2017年8月16日
*/
@Service
publicclassAlipayViewService{
@Autowired
privateNewAlipayBusinessService?newAlipayBusinessService;
/**
*?設(shè)置去支付信息
*
*@paramorderId?訂單id
*@parammodel?模型
*@parampayAccountType?支付賬號類型
*
*@return構(gòu)建的字符串
*/
publicvoidsetGoToPayInfo(longorderId,?Model?model)throwsException{
model.addAttribute("htmlStr",?newAlipayBusinessService.buildPayRequest(orderId,?payPrice,"報名費","略"));
}
}
編寫service層
/**
*?新的阿里支付頁面服務(wù)類
*?
*?阿里升級接口之后使用這個服務(wù)類
*
*@authorWangSen(wangsenhehe@126.com)
*@Date2017年8月16日
*/
@Data
publicclassNewAlipayBusinessService{
/**
*?阿里的配置文件對象
*/
privateAlipayConfig?alipayConfig;
/**
*?構(gòu)建支付請求
*
*@paramorderId?訂單號
*@parampayPrice?付款金額
*@paramorderName?訂單名稱
*@parambody?商品描述
*
*@returnhtml字符串
*/
publicStringbuildPayRequest(longorderId,longpayPrice,?String?orderName,?String?body)throwsException{
//獲得初始化的AlipayClient
AlipayClient?alipayClient?=?getAlipayClient();
//設(shè)置請求參數(shù)
String?bizContent?=?getBizContent(ConvertUtil.obj2str(orderId),?AmountUtils.changeF2Y(payPrice),?orderName,
body);
returnalipayClient.pageExecute(setAlipayRequestParameters(bizContent)).getBody();
}
/**
*?設(shè)置阿里支付請求參數(shù)
*
*@parambizContent?包含關(guān)鍵參數(shù)的json字符串
*
*@returnAlipayTradePagePayRequest對象
*/
privateAlipayTradePagePayRequestsetAlipayRequestParameters(String?bizContent){
AlipayTradePagePayRequest?alipayRequest?=newAlipayTradePagePayRequest();
alipayRequest.setReturnUrl(alipayConfig.getReturn_url());
alipayRequest.setNotifyUrl(alipayConfig.getNotify_url());
alipayRequest.setBizContent(bizContent);
returnalipayRequest;
}
privateAlipayClientgetAlipayClient(){
AlipayClient?alipayClient?=newDefaultAlipayClient(AlipayConfig.gatewayUrl,?alipayConfig.getApp_id(),
alipayConfig.getMerchant_private_key(),"json",?AlipayConfig.charset,
alipayConfig.getAlipay_public_key(),?AlipayConfig.sign_type);
returnalipayClient;
}
/**
*?獲取業(yè)務(wù)的關(guān)鍵內(nèi)容
*
*@paramout_trade_no?訂單號
*@paramtotal_amount?付款金額
*@paramsubject?訂單名稱
*@parambody?商品描述
*
*@return拼接之后的json字符串
*/
privateStringgetBizContent(String?out_trade_no,?String?total_amount,?String?subject,?String?body){
ExceptionUtil.checkEmpty(out_trade_no,"訂單號不能為空");
ExceptionUtil.checkEmpty(total_amount,"價格不能為空");
ExceptionUtil.checkEmpty(subject,"訂單名稱不能為空");
ExceptionUtil.checkEmpty(body,"商品描述不能為空");
StringBuffer?sb?=newStringBuffer();
sb.append("{");
sb.append("\"out_trade_no\":\"").append(out_trade_no).append("\",");
sb.append("\"total_amount\":\"").append(total_amount).append("\",");
sb.append("\"subject\":\"").append(subject).append("\",");
sb.append("\"body\":\"").append(body).append("\",");
sb.append("\"product_code\":\"FAST_INSTANT_TRADE_PAY\"");
sb.append("}");
returnsb.toString();
}
}
通過xml文件配置支付對象
<?xml?version="1.0"?encoding="UTF-8"?>
xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context?http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc?http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"
>
<!--?數(shù)理化支付配置對象?-->
<!--?阿里支付業(yè)務(wù)服務(wù)類?-->
編寫jsp頁面
<%@pageimport="com.we.core.common.util.DateTimeUtil"%>
<%@pagelanguage="java"contentType="text/html;?charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE?HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN">
支付寶即時到賬交易接口
${htmlStr?}
測試
頁面訪問:
localhost:8091/alipay/gotopay.json?orderId=232323
就可以看到支付頁面了铁追;
編寫支付的異步通知接口
用戶支付完成之后支付寶會通過你配置的的notify_url的值進行回調(diào)季蚂,
我需要編寫這個邏輯,以完成整個的支付流程。
編寫controller層
/**
*?阿里支付控制器
*
*@authorWangSen(wangsenhehe@126.com)
*@Date2017年8月16日
*/
@Controller
@RequestMapping("/alipay")
publicclassAliPayController{
@Autowired
privateAlipayViewService?alipayViewService;
/**
*?支付完成
*/
@Void
@NotSso
@ResponseBody
@RequestMapping
publicvoidpayFinish()throwsException{
alipayViewService.payFinish();
}
}
編寫viewService層
/**
*?阿里支付頁面服務(wù)類
*
*@authorWangSen(wangsenhehe@126.com)
*@Date2017年8月16日
*/
@Service
publicclassAlipayViewService{
@Autowired
privateNewAlipayBusinessService?newAlipayBusinessService;
/**
*?支付完成
*
*@throwsIOException?io異常
*/
publicvoidpayFinish()throwsException{
newAlipayBusinessService.payFinish();
}
}
編寫處理支付完成的servie
/**
*?新的阿里支付頁面服務(wù)類
*?
*?阿里升級接口之后使用這個服務(wù)類
*
*?@author???WangSen(wangsenhehe@126.com)
*?@Date?????2017年8月16日
*/
@Data
publicclassNewAlipayBusinessService{
/**
*?阿里的配置文件對象
*/
privateAlipayConfig?alipayConfig;
/**
*?支付完成
*
*?@throws?Exception?異常對象
*/
publicvoidpayFinish()?throws?Exception{
HttpServletRequest?request?=?MvcUtil.getRequest();
PrintWriterout=?MvcUtil.getResponse().getWriter();
//獲取支付寶POST過來反饋信息
Mapparams=?getParames(request);
if(!isSuccess(params))?{
fail(out);
return;
}
longorderId?=?getOrderId(params);
longpayPrice?=?getTotalFee(params);
try{
//編輯你支付完成之后的邏輯
success(out);
}catch(Exception?e)?{
fail(out);
}
}
/**
*?獲取訂單id
*
*?@param?params?請求參數(shù)
*?@return?訂單id
*/
privatelonggetOrderId(Mapparams){
String?order_no?=params.get("out_trade_no");
returnConvertUtil.obj2long(order_no);
}
/**
*?獲取總金額
*
*?@param?params?請求參數(shù)
*?@return?總金額
*/
privatelonggetTotalFee(Mapparams){
String?total_fee?=params.get("total_amount");
returnConvertUtil.obj2long(AmountUtils.changeY2F(total_fee));
}
/**
*?校驗支付寶支付是否成功
*
*?@param?params?http請求
*?@return?成功即為真
*?@throws?AlipayApiException
*/
privatebooleanisSuccess(final?Mapparams)?throws?AlipayApiException{
boolean?signVerified?=?AlipaySignature.rsaCheckV1(params,?alipayConfig.getAlipay_public_key(),
AlipayConfig.charset,?AlipayConfig.sign_type);//調(diào)用SDK驗證簽名
if(!signVerified)?{
returnfalse;
}
//交易狀態(tài)
String?trade_status?=params.get("trade_status");
if(!trade_status.equals("TRADE_FINISHED")?&&?!trade_status.equals("TRADE_SUCCESS"))?{
returnfalse;
}
returntrue;
}
/**
*?成功
*
*?TODO?重構(gòu)方法名
*?@param?out?輸出流
*/
privatevoidsuccess(PrintWriterout){
out.println("success");
}
/**
*?失敗
*
*?TODO?重構(gòu)方法名
*?@param?out?輸出流
*/
privatevoidfail(PrintWriterout){
out.println("fail");
}
/**
*?獲取參數(shù)
*
*?@param?request?HttpServletRequest對象
*
*?@return?返回支付寶攜帶的參數(shù)
*/
privateMapgetParames(HttpServletRequest?request){
Mapparams=newHashMap();
@SuppressWarnings("unchecked")
Map?requestParams?=?request.getParameterMap();
for(Iterator?iter?=?requestParams.keySet().iterator();?iter.hasNext();)?{
String?name?=?ConvertUtil.obj2str(iter.next());
@SuppressWarnings("cast")
String[]?values?=?(String[])?requestParams.get(name);
String?valueStr?="";
for(inti?=0;?i?<?values.length;?i++)?{
valueStr?=?(i?==?values.length?-1)???valueStr?+?values[i]?:?valueStr?+?values[i]?+",";
}
//亂碼解決扭屁,這段代碼在出現(xiàn)亂碼時使用
//valueStr?=?new?String(valueStr.getBytes("ISO-8859-1"),?"utf-8");
params.put(name,?valueStr);
}
returnparams;
}
}
做的過程可能用到的資源
支付接口以及異步通知接口的參數(shù)詳解:
https://docs.open.alipay.com/270/105902/
生成公鑰私鑰的步驟:
https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1
服務(wù)端的sdk:
https://docs.open.alipay.com/203/105910
即時到賬新老版本接口對比:
https://docs.open.alipay.com/270/106759
擴展閱讀
互聯(lián)網(wǎng)支付系統(tǒng)整體架構(gòu)詳解
支付系統(tǒng)設(shè)計:支付系統(tǒng)的賬戶模型
最強解析:支付寶系統(tǒng)架構(gòu)內(nèi)部剖析
Spring MVC+Spring+Mybatis實現(xiàn)支付寶支付功能(圖文詳解)
來源:https://www.cnblogs.com/wangsen/p/7512391.html