ok首先说明一下,下面说的使用 即时到账方式,服务端获取到了一个订单的支付地址,而app端我们做的就是使用WebView来显示二维码的操作,涉及到二维码地址的请求,这一部分有服务端来做。
一、主要涉及的问题
- WebView 不能显示二维码,出现网站已迁移的问题
- 退出了Activity,但是网页还在不停的请求
- https需要证书
- 如何判断支付成功
二、问题解决的方式
(1) 第一个问题可能由以下两种原因引起
-
WebView木有加代理
解决方式
加代理/** * 加这个代理的原因是: 以前是不需要加这个的,现在必须加这个,现在不加这个会出现(无法连接网络)这个错误,加上用户代理 */ payWv.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36
-
木有接受网站的证书(就是第三个问题)
解决方式
创建一个 WebViewClient 的子类MyWebViewClient,重写这个类中的onReceivedSslError方法,接受网站的证书/** * 处理https请求的时候,需要加上下面这个代码(接受证书),不然有的手机无法请求https(例如:ml) */ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed();// 接受所有网站的证书 Log.i("MyWebViewClient", "接受证书"); }
(2)第二个问题的解决方式
重写onKeyDown方法,退出时,把WebView 销毁掉
/**
* 按下返回键的时候 退出Activity 并且destroy掉 webView
* 不destory 掉的话,webview会一直请求网路 除非整个应用关闭,
* 所以添加上了 webView.destroy操作。
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK){
payWv.destroy();
finish();
}
return false;
}
(3)第三个问题的解决方式
这个问题的解决方式和第一个问题中的第二个解决方式一样
创建一个 WebViewClient 的子类,重写这个类中的onReceivedSslError方法,接受网站的证书
/**
* 处理https请求的时候,需要加上下面这个代码(接受证书),不然有的手机无法请求https(例如:ml)
*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
handler.proceed();// 接受所有网站的证书
Log.i("MyWebViewClient", "接受证书");
}
(4)第四个问题的解决方式
支付成功,我们的网页地址会调到一个支付成功的界面(地址是:https://tradeexprod.alipay.com/cashiergw/cashierReturnMiddlePage.htm?,后面带一些参数),这时候,我们可以在MyWebViewClient中的shouldOverrideUrlLoading方法中判断,url是不是的开始部分是不是上面这个网址。
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.startsWith("https://tradeexprod.alipay.com/cashiergw/cashierReturnMiddlePage.htm?")){
//这里面就是支付成功,以后的操作 ,这里面我们是调到支付成界面
startActivity(new Intent(MainActivity.this,PayOk.class));
}
view.loadUrl(url);
return true;
}
三、代码示例
这里主要说明一哈,我们获取到的二维码,有好几种格式,这里我们选择的是 2
类型(长度范围) 是否可为空 样例
参数 | 参数名称 | 参数说明 |
---|---|---|
qr_pay_mode | 扫码支付方式 | 扫码支付的方式,支持前置模式和跳转模式。前置模式是将二维码前置到商户的订单确认页的模式。需要商户在自己的页面中以iframe方式请求支付宝页面。具体分为以下3种:1、订单码-简约前置模式,对应iframe宽度不能小于600px,高度不能小于300px;2、订单码-前置模式,对应iframe宽度不能小于300px,高度不能小于600px;3、订单码-迷你前置模式,对应iframe宽度不能小于75px,高度不能小于75px。跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。4、订单码-跳转模式 |
具体可以看 支付宝开放平台api–即时到账
根据生成的二位的大小,我们来定义WebView的宽和高,ok也许你也想到了,我们的这个WebView应该不能滑动放大之类的,so easy 我们写一个WebView的子类,屏蔽掉它的触摸事件就ok了。
(1)NoScorWbView
package com.xm.alipayxmdemo1;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.webkit.WebView;
/**
* @author:qiwenming
* @date:2015/8/28 0028 下午 5:14
* @instruction
*/
public class NoScorWbView extends WebView {
public NoScorWbView(Context context) {
super(context);
}
public NoScorWbView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NoScorWbView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
*让这个webview 无法响应触摸事件
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}
}
(2)activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.xm.alipayxmdemo1.NoScorWbView
android:layout_centerInParent="true"
android:id="@+id/sdwv_apy"
android:layout_width="290dp"
android:layout_height="290dp" />
</RelativeLayout>
(3)MainActivity
package com.xm.alipayxmdemo1;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.http.SslError;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends Activity {
private WebView payWv;
private ProgressDialog dialog;
Runnable runnable;
Handler handler;
private String payUrl = "你获取到二维码的支付地址";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
payWv = (WebView)findViewById(R.id.sdwv_apy);
payWv.getSettings().setJavaScriptEnabled(true);
payWv.setWebViewClient(new MyWebViewClient());
/**
* 加这个代理的原因是: 以前是不需要加这个的,现在必须加这个,现在不加这个会出现(无法连接网络)这个错误,加上用户代理
*/
payWv.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36");
payWv.loadUrl(payUrl);
//这是用于控制我们的进度框显示的
runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
// webView.loadUrl("javascript:window.local_obj.dimissDialog()");
if(dialog != null && dialog.isShowing())
dialog.dismiss();
}
};
handler = new Handler();
dialog = ProgressDialog.show(this, null, "正在加载中。。。", true, true);
}
class MyWebViewClient extends WebViewClient{
/**
* 处理https请求的时候,需要加上下面这个代码(接受证书),不然有的手机无法请求https(例如:ml)
*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
handler.proceed();// 接受所有网站的证书
Log.i("MyWebViewClient", "接受证书");
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.startsWith("https://tradeexprod.alipay.com/cashiergw/cashierReturnMiddlePage.htm?")){
//这里面就是支付成功,以后的操作 ,这里面我们是调到支付成界面
startActivity(new Intent(MainActivity.this,PayOk.class));
}
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(final WebView view, String url) {
Log.d("MyWebViewClient","onPageFinished---url="+url);
//加载完成以后,需要把我么的dialog关了
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, 2000);
super.onPageFinished(view, url);
}
}
/**
* 按下返回键的时候 退出Activity 并且destroy掉 webView
* 不destory 掉的话,webview会一直请求网路 除非整个应用关闭,
* 所以添加上了 webView.destroy操作。
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode== KeyEvent.KEYCODE_BACK){
payWv.destroy();
finish();
}
return false;
}
}