微信和支付寶的H5支付下單成功后都會返回一個跳轉支付的url連接,通過這個連接可以拉起微信或支付寶進行支付操作。
如果直接訪問,支付寶會有一個中間的頁面,而微信有個麻煩的refresh驗證問題;那么是否可以跳過這個步驟直接將微信支付寶拉起進行支付呢?
網上大部分的教程都是讓做安卓和IOS的自己去攔截微信和支付寶的地址進行處理。但是對這種內嵌網頁,前端的同學就非常不好操作了;那么這個活就需要后端的同學辛苦哈來解決了(ง •_•)ง。
首先需要知道的是每一個手機APP都有一個唯一的URL Scheme地址,訪問這個地址即可將對應的APP打開。
基於這個原理,那么微信和支付寶的支付最終肯定也是基於此來實現將其APP拉起然后讓用戶進行支付的。
因此讓后端對支付地址處理下,直接返回可以拉起微信和支付寶的支付URL Scheme;這樣就可以直接用了,微信的refresh驗證也可以跳過了。
首先是微信H5支付
通過程序直接請求微信H5支付下單返回的支付鏈接,返回如下(下面是返回的部分html代碼):
在Html代碼中有以weixin://
開頭的鏈接;而weixin://
正好是微信的URL Scheme,這個就是之后調用微信支付的鏈接,在手機瀏覽器上打開這個鏈接正好可以調起微信支付進行支付。
說明微信在這個頁面上並沒有做其他的騷操作,那些Referer攔截只是一些簡單的前台攔截。那么我們通過后端程序直接去請求微信返回H5支付鏈接,然后將返回的HTML中的微信支付URL Scheme提取出來直接返回給前端即可。
下面是Java示例代碼
HttpHeaders headers = new HttpHeaders();
headers.add("Host", "wx.tenpay.com");
headers.add("Accept-Language", "en, zh-CN; q=0.8,zh; q=0.6,en-US; q=0.4");
headers.add("Accept", "text/html,application/xhtml+xml, application/xml ; g=0. 9 ,image/webp,*/* ; q=0.8");
headers.add("Upgrade-Insecure-Requests", "1");
// 這個地方寫你自己在微信支付后台配置的安全域名
headers.add("Referer", "https://www.baidu.com");
HttpEntity<String> httpEntity = new HttpEntity<>(headers);
try{
// 使用spring的 RestTemplate; mweb_url是微信的H5支付鏈接
ResponseEntity<String> exchange = this.restTemplate.exchange(mweb_url, HttpMethod.GET, httpEntity, String.class);
String body = exchange.getBody();
if(StringUtils.isBlank(body)){
System.out.println("請求無響應");
return url;
}
// 通過正則表達式提取需要的字符串
String pattern= "\"weixin(.*?)\"";
Pattern p = Pattern.compile(pattern);
Matcher matcher = p.matcher(body);
if(matcher.find()){
String pullUrl = matcher.group();
return pullUrl.substring(1, pullUrl.length()-1);
}
}catch (Exception e){
System.out.println("請求異常");
}
return url;
需要注意的是使用這種方式就不要再將會回跳地址傳入了,同時需要自己做個是否支付成功的判斷。
支付寶H5支付
基於剛才微信的思路,使用同樣的方式來處理支付寶的。支付寶返回的HTML內容中沒有現成的支付寶支付的URL Scheme。通過調試和HTML代碼分析,提取出其支付URL Scheme如下:
# 安卓的(實際測試中,蘋果手機使用這個也可以拉起支付寶)
alipays://platformapi/startApp?appId=102564&orderSuffix=' + o.android + '#Intent;scheme=alipays;package=com.eg.android.AlipayGphone;end
# 蘋果的
alipay://alipayclient/?o.ios
其中o.ios和o.android的內容是使用url encoder編碼了的;其中蘋果的內容是如下的JSON串:
{
"requestType": "SafePay",
"fromAppUrlScheme": "alipays",
"dataString": "h5_route_token=\"FPwoiehfPAWuiofw\"&is_h5_route=\"true\"&need_invoke_app=\"true\""
}
安卓的只有一個dataString的值。通過字段的值對比h5_route_token
其值就是HTML中的session的值;在返回的HTML代碼中有如下代碼:
var inData = { "requestType": "SafePay", "fromAppUrlScheme": "alipays", "dataString": "h5_route_token=\"FPwoiehfPAWuiofw\"&is_h5_route=\"true\"&need_invoke_app=\"true\"" };
這個就是上面需要的內容,同樣通過正則表達式將內容提取出來。
下面是Java示例代碼:
HttpGet httpGet = new HttpGet(h5Url);
httpGet.setConfig(RequestConfig.custom()
.setConnectTimeout(HttpConstants.CONNECT_TIMEOUT)
.setConnectionRequestTimeout(HttpConstants.CONNECTION_REQUEST_TIMEOUT)
.setSocketTimeout(HttpConstants.SOCKET_TIMEOUT).build());
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
if(response.getEntity()!=null){
String body = EntityUtils.toString(response.getEntity(), "UTF-8");
// 通過正則表達式提取需要的字符串;也可以直接提取session的值 `pattern = "'session':(.*)'";`
String pattern= "inData =(.*)";
Pattern p = Pattern.compile(pattern);
Matcher matcher = p.matcher(body);
if(matcher.find()){
String pullUrl = matcher.group();
if(pullUrl.length()>9){
pullUrl = pullUrl.substring(9, pullUrl.length()-1);
if(isAndroid){
JSONObject params = JSONObject.parseObject(pullUrl);
if(params.getString("dataString")!=null){
pullUrl = params.getString("dataString");
// 安卓
return String.format("alipays://platformapi/startApp?appId=549984&orderSuffix=%s#Intent;scheme=alipays;package=com.eg.android.AlipayGphone;end", URLEncoder.encode(pullUrl, "utf-8"));
}
}else {
// iso
return String.format("alipay://alipayclient/?%s", URLEncoder.encode(pullUrl.trim(), "utf-8"));
}
}
}
System.out.println("請求返回內容:"+ body);
}else {
System.out.println("無請求內容返回");
}
} catch (IOException e) {
System.out.println("處理異常");
}finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
這種方式對原生的APP開發應該也適用,即不使用微信支付寶的APP支付方式,直接使用H5的支付方式,這樣就無需再去對接其APP支付的SDK了。
關注微信訂閱號‘起岸星辰’獲取最新資訊