對接「支付寶」支付接口

作者:王森;
鏈接:https://www.cnblogs.com/wangsen/p/7512391.html

對接「支付寶」支付接口



場景

最近在做支付寶的接口對接,之前做過一個版本,但是由於申請了新的賬號以前舊的的接口對接就不能使用了

所以就開始對接新的版本接口對接,在這裡也記錄一下讓那些還沒有對接的兄弟少走點彎路。

準備

先申請一個企業賬戶

https://memberprod.alipay.com/account/reg/enterpriseIndex.htm

創建應用

去支付寶的開放平臺

https://open.alipay.com/platform/home.htm

添加應用:

https://docs.open.alipay.com/200/105310

按照這個鏈接的文檔一步一步操作;

賬號準備好之後,就可以瞭解相關的接口了,以(即時到賬)支付接口為例。

閱讀接口文檔

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中的關鍵jar包

這裡的gav的寫法取決於你上傳私服的時候的填寫

對接「支付寶」支付接口



com.alipay
alipay-api
1.0.0

處理AlipayConfig對象

取消AlipayConfig配置文件中的部分常量

打開下載sdk應該可以找到

對接「支付寶」支付接口


將這個類中的前幾個靜態常量變成非靜態的,以便可以支持多個配置對象。

/* *
*類名:AlipayConfig
*功能:基礎配置類
*詳細:設置帳戶有關信息及返回路徑
*修改日期:2017-04-05
*說明:
*以下代碼只是為了方便商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。
*該代碼僅供學習和研究支付寶接口使用,只是提供一個參考。
*/
@Data
public class AlipayConfig {
//↓↓↓↓↓↓↓↓↓↓請在這裡配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 應用ID,您的APPID,收款賬號既是您的APPID對應支付寶賬號
public String app_id = "";
// 商戶私鑰,您的PKCS8格式RSA2私鑰
public String merchant_private_key = "";
// 支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。
public String alipay_public_key = "";
// 服務器異步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問

public String notify_url = "";
// 頁面跳轉同步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
public String return_url = "";
// 簽名方式
public static String sign_type = "RSA2";
// 字符編碼格式
public static String charset = "utf-8";
// 支付寶網關
public static String gatewayUrl = "https://openapi.alipay.com/gateway.do";
//日誌路徑
public static String log_path = "C:\";
}

編寫請求支付的接口

後端向支付寶發起支付的請求,在這個同時需要傳遞必要參數,下面我們就來編寫如何向支付寶發起支付。

編寫conroller層

/**
* 阿里支付控制器
*
* @author WangSen([email protected])
* @Date 2017年8月16日
*/
@Controller
@RequestMapping("/alipay")
public class AliPayController {
@Autowired
private AlipayViewService alipayViewService;
/**
* 跳轉到去支付的jsp頁面

*
* @param orderId 訂單號
*
* @param payAccountType 支付賬號類型
*
* @param model 模型
*
* @throws Exception
*/
@RequestMapping
public void gotopay(long orderId, Model model) throws Exception {
alipayViewService.setGoToPayInfo(orderId, model);
}
}

編寫viewService層

/**
* 阿里支付頁面服務類
*
* @author WangSen([email protected])
* @Date 2017年8月16日
*/
@Service
public class AlipayViewService {
@Autowired
private NewAlipayBusinessService newAlipayBusinessService;
/**
* 設置去支付信息
*
* @param orderId 訂單id
* @param model 模型
* @param payAccountType 支付賬號類型
*
* @return 構建的字符串
*/
public void setGoToPayInfo(long orderId, Model model) throws Exception {
model.addAttribute("htmlStr", newAlipayBusinessService.buildPayRequest(orderId, payPrice, "報名費", "略"));
}
}

編寫service層

/**
* 新的阿里支付頁面服務類
*


* 阿里升級接口之後使用這個服務類
*
* @author WangSen([email protected])
* @Date 2017年8月16日
*/
@Data
public class NewAlipayBusinessService {
/**
* 阿里的配置文件對象
*/
private AlipayConfig alipayConfig;
/**
* 構建支付請求
*
* @param orderId 訂單號
* @param payPrice 付款金額
* @param orderName 訂單名稱
* @param body 商品描述
*
* @return html字符串
*/
public String buildPayRequest(long orderId, long payPrice, String orderName, String body) throws Exception {
//獲得初始化的AlipayClient
AlipayClient alipayClient = getAlipayClient();
//設置請求參數
String bizContent = getBizContent(ConvertUtil.obj2str(orderId), AmountUtils.changeF2Y(payPrice), orderName,
body);
return alipayClient.pageExecute(setAlipayRequestParameters(bizContent)).getBody();
}
/**
* 設置阿里支付請求參數
*
* @param bizContent 包含關鍵參數的json字符串


*
* @return AlipayTradePagePayRequest對象
*/
private AlipayTradePagePayRequest setAlipayRequestParameters(String bizContent) {
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(alipayConfig.getReturn_url());
alipayRequest.setNotifyUrl(alipayConfig.getNotify_url());
alipayRequest.setBizContent(bizContent);
return alipayRequest;
}
private AlipayClient getAlipayClient() {
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, alipayConfig.getApp_id(),
alipayConfig.getMerchant_private_key(), "json", AlipayConfig.charset,
alipayConfig.getAlipay_public_key(), AlipayConfig.sign_type);
return alipayClient;
}
/**
* 獲取業務的關鍵內容
*
* @param out_trade_no 訂單號
* @param total_amount 付款金額
* @param subject 訂單名稱
* @param body 商品描述
*
* @return 拼接之後的json字符串
*/
private String getBizContent(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 = new StringBuffer();
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("}");
return sb.toString();
}
}

通過xml文件配置支付對象


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">













編寫jsp頁面







支付寶即時到賬交易接口

${htmlStr }



測試

頁面訪問:

localhost:8091/alipay/gotopay.json?orderId=232323

就可以看到支付頁面了;

對接「支付寶」支付接口


編寫支付的異步通知接口

用戶支付完成之後支付寶會通過你配置的的notify_url的值進行回調,

我需要編寫這個邏輯,以完成整個的支付流程。

編寫controller層

/**
* 阿里支付控制器
*
* @author WangSen([email protected])
* @Date 2017年8月16日
*/
@Controller
@RequestMapping("/alipay")
public class AliPayController {
@Autowired
private AlipayViewService alipayViewService;
/**
* 支付完成
*/
@Void
@NotSso
@ResponseBody
@RequestMapping
public void payFinish() throws Exception {
alipayViewService.payFinish();
}
}

編寫viewService層

/**
* 阿里支付頁面服務類
*
* @author WangSen([email protected])
* @Date 2017年8月16日
*/
@Service
public class AlipayViewService {
@Autowired
private NewAlipayBusinessService newAlipayBusinessService;
/**
* 支付完成
*
* @throws IOException io異常
*/
public void payFinish() throws Exception {
newAlipayBusinessService.payFinish();
}
}

編寫處理支付完成的servie

/**
* 新的阿里支付頁面服務類
*


* 阿里升級接口之後使用這個服務類
*
* @author WangSen([email protected])
* @Date 2017年8月16日
*/
@Data
public class NewAlipayBusinessService {
/**
* 阿里的配置文件對象
*/
private AlipayConfig alipayConfig;
/**
* 支付完成


*
* @throws Exception 異常對象
*/
public void payFinish() throws Exception {
HttpServletRequest request = MvcUtil.getRequest();
PrintWriter out = MvcUtil.getResponse().getWriter();
//獲取支付寶POST過來反饋信息
Map params = getParames(request);
if (!isSuccess(params)) {
fail(out);
return;
}
long orderId = getOrderId(params);
long payPrice = getTotalFee(params);
try {
//編輯你支付完成之後的邏輯
success(out);
} catch (Exception e) {
fail(out);
}
}
/**
* 獲取訂單id
*
* @param params 請求參數
* @return 訂單id
*/
private long getOrderId(Map params) {
String order_no = params.get("out_trade_no");
return ConvertUtil.obj2long(order_no);
}
/**
* 獲取總金額
*
* @param params 請求參數
* @return 總金額
*/
private long getTotalFee(Map params) {
String total_fee = params.get("total_amount");
return ConvertUtil.obj2long(AmountUtils.changeY2F(total_fee));
}
/**
* 校驗支付寶支付是否成功

*
* @param params http請求
* @return 成功即為真
* @throws AlipayApiException
*/
private boolean isSuccess(final Map params) throws AlipayApiException {
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipay_public_key(),
AlipayConfig.charset, AlipayConfig.sign_type); //調用SDK驗證簽名
if (!signVerified) {
return false;
}
//交易狀態
String trade_status = params.get("trade_status");
if (!trade_status.equals("TRADE_FINISHED") && !trade_status.equals("TRADE_SUCCESS")) {
return false;
}
return true;
}
/**
* 成功
*
* TODO 重構方法名
* @param out 輸出流
*/
private void success(PrintWriter out) {
out.println("success");
}
/**
* 失敗
*
* TODO 重構方法名
* @param out 輸出流
*/
private void fail(PrintWriter out) {
out.println("fail");
}
/**
* 獲取參數
*
* @param request HttpServletRequest對象
*
* @return 返回支付寶攜帶的參數
*/
private Map
getParames(HttpServletRequest request) {
Map params = new HashMap();
@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 (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
//亂碼解決,這段代碼在出現亂碼時使用
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
return params;
}
}

做的過程可能用到的資源

支付接口以及異步通知接口的參數詳解:https://docs.open.alipay.com/270/105902/生成公鑰私鑰的步驟:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1服務端的sdk:https://docs.open.alipay.com/203/105910即時到賬新老版本接口對比:https://docs.open.alipay.com/270/106759


分享到:


相關文章: