首先,參考官方api:
alipay.trade.wap.pay(手機網站支付接口2.0)
官方提供DEMO下載,不過是jsp的
準備工作:平臺入駐,簽約功能,應用上線,配置祕鑰等
使用Alipay SDK:
<!-- 支付寶支付sdk -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.9.124.ALL</version>
</dependency>
固定參數配置類:
// 由於部分數據來自數據庫,這裏用到了我自己寫的service,不需要查詢的話也可以直接在config中寫一個固定值
import com.tb.service.ShopDeviceService;
public class AlipayConfig {
private ShopDeviceService shopDeviceService;
// 爲了傳遞service,只能使用new的形式創建
public AlipayConfig(ShopDeviceService shopDeviceService) {
this.shopDeviceService = shopDeviceService;
}
// 商戶appid
public String getAppId() {
return shopDeviceService.getDictDetailByNameAndLabel("PAY-INFO", "AlipayAppid");
}
// 支付寶公鑰
public String getAliPayPublicKey() {
return shopDeviceService.getDictDetailByNameAndLabel("KEY", "支付寶公鑰");
}
// 私鑰 pkcs8格式的
public String getRSAPrivateKey() {
return shopDeviceService.getDictDetailByNameAndLabel("KEY", "支付寶應用私鑰");
}
// 服務器異步通知頁面路徑 需http://或者https://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
public String getNotifyUrl() {
return shopDeviceService.getDictDetailByNameAndLabel("URL", "AliPayNotify");
}
// 請求網關地址
public String getUrl() {
return "https://openapi.alipay.com/gateway.do";
}
// 編碼
public String getCharset() {
return "UTF-8";
}
// 返回格式
public String getFormat() {
return "json";
}
// RSA2
public String getSignType() {
return "RSA2";
}
public String getProductCode() {
return "QUICK_WAP_WAY";
}
// subject
public String getSubject() {
return "WASHER";
}
}
手機網站支付接口:
// ALIPay 下單 跳轉至付款界面
@PreAuthorize("@el.check('anonymous')")// 匿名訪問
@PostMapping("/aliPrePay")
public void alipayPlaceOrder(@RequestBody Map params, HttpServletResponse response) throws AlipayApiException {
// 創建訂單並返回訂單id
ShopOrderDTO shopOrderDTO = createOrder(params);
//new配置類,傳入需要的service
AlipayConfig alipayConfig = new AlipayConfig(shopDeviceService);
//支付固定寫法從這裏開始了!
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getAppId(),
alipayConfig.getRSAPrivateKey(), alipayConfig.getFormat(), alipayConfig.getCharset(),
alipayConfig.getAliPayPublicKey(), alipayConfig.getSignType());
AlipayTradeWapPayRequest req = new AlipayTradeWapPayRequest();
AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
model.setOutTradeNo(shopOrderDTO.getId().toString());
model.setSubject(alipayConfig.getSubject());
String amount = String.valueOf(shopOrderDTO.getAmount().floatValue() / 100);
model.setTotalAmount(amount);
model.setProductCode(alipayConfig.getProductCode());
req.setBizModel(model);
req.setNotifyUrl(alipayConfig.getNotifyUrl());
logger.info("發起AliPay下單請求");
String form = alipayClient.pageExecute(req).getBody();
response.setContentType("text/html;charset=" + alipayConfig.getCharset());
try {
//直接將完整的表單html輸出到頁面
response.getWriter().write(form);
response.getWriter().flush();
response.getWriter().close();
} catch (IOException e) {
logger.info("AliPay 界面跳轉失敗");
}
}
異步通知接口:
// AliPay 支付異步通知
@PreAuthorize("@el.check('anonymous')")
@PostMapping("/aliPayNotify")
public void alipayReturn(HttpServletRequest request) {
logger.info("AliPay 支付回調:");
Map<String,String> 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] + ",";
}
//亂碼解決,這段代碼在出現亂碼時使用。如果mysign和sign不相等也可以使用這段代碼轉化 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
String out_trade_no = request.getParameter("out_trade_no");
ShopOrderDTO orderDto = shopOrderService.findById(Long.valueOf(out_trade_no));
String trade_no = request.getParameter("trade_no");
String trade_status = request.getParameter("trade_status");
Float amount = Float.valueOf(request.getParameter("total_amount"));
AlipayConfig alipayConfig = new AlipayConfig(shopDeviceService);
try {
boolean verify_result = AlipaySignature.rsaCheckV1(params, alipayConfig.getAliPayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
if(verify_result) { // 簽名校驗
if (trade_status.equals("TRADE_SUCCESS") && !StringUtils.isBlank(trade_no) ) {// 支付成功
// 一些自己的判斷,比如金額,訂單支付狀態等等,自行修改
if (amount == Float.valueOf(orderDto.getAmount())/100 && orderDto.getState() == 1) {
onSuccess(orderDto, trade_no);
} else if (orderDto.getState() == 0) {
// 日誌保存
shopLogService.anonymousCreate(shopLogService.getShopLog(orderDto.getStoreId(), orderDto.getDeviceId(), "訂單支付狀態有誤","訂單支付狀態爲已支付 : " + orderDto.getId()));
} else if (amount != Float.valueOf(orderDto.getAmount())/100){
shopLogService.anonymousCreate(shopLogService.getShopLog(orderDto.getStoreId(), orderDto.getDeviceId(), "AliPay支付金額有誤","金額有誤 : " + orderDto.getId()));
}
} else {
shopLogService.anonymousCreate(shopLogService.getShopLog(orderDto.getStoreId(), orderDto.getDeviceId(), "AliPay支付失敗",orderDto.getId()+""));
}
} else {
logger.info("AliPay 簽名校驗失敗");
}
} catch (AlipayApiException e) {
logger.info("AliPay 簽名校驗失敗");
e.printStackTrace();
}
}
訂單查詢接口:
// AliPay 訂單查詢
@PreAuthorize("@el.check('anonymous')")
@GetMapping("/aliPayQuery")
public ResponseEntity AliPayQuery(String id) {
ShopOrderDTO orderDTO = shopOrderService.findById(Long.valueOf(id));
// 這裏可以加一層判斷,如果訂單是已支付且已有支付id直接返回成功就好,不必再調支付寶查詢接口
try {
AlipayConfig alipayConfig = new AlipayConfig(shopDeviceService);
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getAppId(),
alipayConfig.getRSAPrivateKey(), alipayConfig.getFormat(), alipayConfig.getCharset(),
alipayConfig.getAliPayPublicKey(), alipayConfig.getSignType());
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo(id);
request.setBizModel(model);
logger.info("發起 AliPay 查詢請求:");
AlipayTradeQueryResponse response = alipayClient.execute(request);
Map map = JSON.parseObject(response.getBody(), Map.class);
Map result = JSON.parseObject(map.get("alipay_trade_query_response").toString(), Map.class);
if (result.get("code").toString().equals("10000") && result.get("trade_status").toString().equals("TRADE_SUCCESS") // 支付成功
&& Float.valueOf(result.get("total_amount").toString()) == Float.valueOf(orderDTO.getAmount())) { // 金額與訂單金額相等
// TODO 支付成功後回調已經做了一些事 查詢的時候要做什麼有待思考
ShopOrder order = new ShopOrder();
order.setId(orderDTO.getId());
order.setState(0);
order.setPayId(result.get("trade_no").toString());
shopOrderService.update(order);
}
return new ResponseEntity<>(result, HttpStatus.OK);
} catch (AlipayApiException e) {
logger.info("AliPay 查詢失敗");
return new ResponseEntity(HttpStatus.OK);
}
}