1. 程式人生 > >支付寶支付Java程式碼

支付寶支付Java程式碼

支付寶呼叫流程

開發前的準備工作

配置應用閘道器
應用閘道器裡面填寫的值就是商戶後臺的非同步回撥地址.也就是在支付寶付完款之後,由支付寶呼叫商戶,便於商戶驗證訂單各資訊和更新訂單狀態
授權回撥地址
授權回撥地址的值是指使用者在使用支付寶付款成功後從支付寶跳轉到商戶自己的頁面.
介面加密方式
這個用於商戶的簽名加密,有RSA2和RSA兩種演算法型別,預設是RSA2.開發人員可以使用支付寶提供的生成方式自己生成,然後將公鑰上傳到支付寶開放平臺.這裡提供支付寶生成金鑰的教程和下載地址
現在提供一張的截圖,顯示配置的位置.到達方式:螞蟻金服開放文件—> 右上角賬戶中的賬號管理—>開發者中心—>我的應用(應用) —> 選擇自己將要配置的應用名稱點選右邊的檢視—>應用資訊(就是截圖看到的頁面了)

 


支付寶支付流程:

前端呼叫商戶後臺支付介面
商戶後臺支付介面進行一些必要的業務邏輯上的處理之後呼叫支付寶的支付介面(原始支付API).需要的引數詳見支付寶支付介面的引數說明.支付寶會返回一個form表單.商戶後臺支付介面將表單返回給前臺.
前臺將表單提交給支付寶,喚起支付寶客戶端進行支付.
支付成功後支付寶會根據原始支付API中傳入的非同步通知地址notify_url,通過POST請求的方式將支付結果作為引數通知到商戶後臺系統.
商戶後臺系統在接到支付寶的非同步通知後要在驗證自己本身業務邏輯之外嚴格驗證通知資料的正確性.
商戶需要驗證該通知資料中的out_trade_no是否為商戶系統中建立的訂單號
判斷total_amount是否確實為該訂單的實際金額(即商戶訂單建立時的金額)
校驗通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)
驗證app_id是否為該商戶本身
上述1、2、3、4有任何一個驗證不通過,則表明本次通知是異常通知,務必忽略.詳情參見https://docs.open.alipay.com/203/105286/ 非同步返回的驗籤
判斷沒有任何錯誤,列印success.否則支付寶伺服器會不斷重發通知,直至超過24小時22分鐘.


開發需要準備的物料
pom.xml新增支付寶依賴

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.alipay</groupId>
<artifactId>alipay-sdk</artifactId>
<version>java20170307171631</version>
</dependency>


支付寶方面的引數

 

 

程式碼展示
商戶後臺支付介面

/**
* 支付寶支付
* @param req
* @param response
* @throws OperationFailedException
*/
@RequestMapping("alipay/Prepay")
@ResponseBody
public void aliPrepay(@RequestBody AliPrepayReq req, HttpServletResponse response) throws OperationFailedException {
Set<ConstraintViolation<AliPrepayReq>> constraintViolationSet = validator.validate(req);
if (constraintViolationSet.size() > 0) {
throw new OperationFailedException(constraintViolationSet.iterator().next().getMessage());
}

LibraOrder libraOrder = libraService.findLibraOrderByHashCode(req.getOutTradeNo());

Product product = productRepository.findOne(Long.valueOf(libraOrder.getProduct().getId()));
if(product == null) { throw new OperationFailedException("該商品不存在"); }

try{
String form = aliPayService.generateAliPay(req);

if(!"err".equals(form)){
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(form);// 直接將完整的表單html輸出到頁面
response.getWriter().flush();
}
}catch (Exception e){
throw new OperationFailedException("支付失敗");
}

}

 


/**
* 支付寶方面訂單號獲取
* @param aliPrepayReq
* @return
* @throws OperationFailedException
*/
public String generateAliPay(AliPrepayReq aliPrepayReq) throws OperationFailedException {
AlipayClient alipayClient = new DefaultAlipayClient(aliPayUrl,
appId, rsaPrivateKey, "json", "UTF-8", rsaPublicKey, "RSA2"); //獲得初始化的AlipayClient
Map<String, String> param = new HashMap<>();

AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

// 封裝請求支付資訊
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(aliPrepayReq.getOutTradeNo());
model.setSubject(aliPrepayReq.getSubject());
Integer totalAmount = aliPrepayReq.getTotalAmount();
model.setTotalAmount(String.valueOf(totalAmount / 100.0));
// model.setBody(aliPrepayReq.getBody());
model.setProductCode(aliPrepayReq.getProductCode());
alipay_request.setBizModel(model);
// 設定非同步通知地址
alipay_request.setNotifyUrl(notifyUrl);
// 設定同步地址
alipay_request.setReturnUrl(returnUrl);

String form = "";
try {
LOGGER.info("alipay_request = "+jsonService.toJson(alipay_request));
// 呼叫SDK生成表單
form = alipayClient.pageExecute(alipay_request).getBody();
LOGGER.info("form = "+form);
} catch (Exception e) {
throw new OperationFailedException("支付出錯");
}
return form;
}

 


非同步回撥介面

/**
* 支付寶方面非同步回撥
* @param request
* @return
* @throws OperationFailedException
*/
@RequestMapping("alipay/notifyCallback")
public String AlipayCallBack(HttpServletRequest request) throws OperationFailedException {
//獲取支付寶POST過來反饋資訊
Map<String,String> params = new HashMap<String,String>();

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] + ",";
}
//亂碼解決,這段程式碼在出現亂碼時使用。如果mysign和sign不相等也可以使用這段程式碼轉化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
LOGGER.info("params = "+jsonService.toJson(params));
boolean verify_result = aliPayService.rsaCheck(params);
if(verify_result && aliPayService.dealWithAliPayChargeOrder(params)){
return "success";
}
return "false";
}

 

 

/**
* 訂單驗證
* @param params
* @return
*/
@Transactional
public boolean dealWithAliPayChargeOrder(Map<String, String> params) {
String outTradeNo = params.get("out_trade_no");
LibraOrder libraOrder = libraOrderRepository.findByHashCode(outTradeNo);
if (libraOrder == null) {
LOGGER.info("訂單" + outTradeNo + "不存在");
return false;
}

boolean locked = distributeLocker.lock(USER_ALIPAY_DEAL_LOCK_KEY);
try {
if (locked) {
String totalAmount = params.get("total_amount");
double totalPrice = Double.parseDouble(totalAmount) * 100;
if(libraOrder.getTotalPrice() != Math.round(totalPrice)){
LOGGER.info("alipay和訂單金額不一致");
return false;
}

if(totalPrice < 0 || libraOrder.getTotalPrice() < 0){
LOGGER.info("alipay或訂單金額為負");
return false;
}
//set done
libraOrder.setPayAt(new Date());
libraOrder.setUpdateAt(new Date());
libraOrder.setStatus(ClientOrderStatus.PAYED);

//後臺訂單狀態初始化為 等待接待
libraOrder.setServiceStatus(ServiceStatus.SERVICE_WAIT);
libraOrderRepository.save(libraOrder);
}
} finally {
if (locked) {
//TODO + order.getUserId()
distributeLocker.unlock(USER_ALIPAY_DEAL_LOCK_KEY);
}
}
return false;
}

 

 

/**
* 驗證RSA簽名
* @param params
* @return
* @throws OperationFailedException
*/
public boolean rsaCheck(Map<String, String> params) throws OperationFailedException {
try {
boolean verify_result = AlipaySignature.rsaCheckV1(params, rsaPublicKey, charset, signType);
LOGGER.info("verify_result = "+verify_result);
return verify_result;
} catch (AlipayApiException e) {
throw new OperationFailedException("驗證簽名失敗");
}
}
---------------------