H5与原生交互那点事儿

聊一下关于H5、Android和iOS的交互。

支付宝支付需要参数的传递,问题的解决
首先是iOS需要建立一个UIWebView,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#import "webview.h"
#import <javascriptcore javascriptcore.h="">
@implementation webview

-(id)initWithFrame:(CGRect)frame
{
self=[super initWithFrame:frame];

if( self ){
self.webview=[[UIWebView alloc]initWithFrame:CGRectMake(0, 310, self.bounds.size.width, 300)];
self.webview.backgroundColor=[UIColor lightGrayColor];
NSString *htmlPath=[[NSBundle mainBundle] resourcePath];
htmlPath=[htmlPath stringByAppendingPathComponent:@"html/index.html"];
NSURL *localURL=[[NSURL alloc]initFileURLWithPath:htmlPath];
[self.webview loadRequest:[NSURLRequest requestWithURL:localURL]];
[self addSubview:self.webview];

JSContext *context = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 这个全是objective-c代码写的,下面会有详解
context[@"appointment"] = ^() {
NSLog(@"+++++++start Log+++++++");
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSLog(@"%@", jsVal);
}
JSValue *this = [JSContext currentThis];
NSLog(@"this: %@",this);
NSLog(@"-------finish Log-------");
};
}
return self;
}
@end</javascriptcore>

前端想把支付宝的参数传给iOS,问题就出在iOS怎么能拿到前端传递过来的数据,javascript直接调用oc代码而非通过改变url回调方式,最重要的地方是和H5约定好执行函数的名称。

1
2
3
4
5
6
7
8
9
context[@"appointment"] = ^() {
NSLog(@"-------Start Test-------");
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSLog(@"%@", jsVal);
}
JSValue *this = [JSContext currentThis];
NSLog(@"-------Finish Test-------");
};

前端的代码,看到下面的appointment没,一旦触发testClick()后,就会执行上面那段oc代码,iOS就能够拿到支付所需要的参数。

1
2
3
4
function testClick()
{
appointment('{"paramOne":"'+paramOne+'","paramTwo":"'+paramTwo+'","paramThree":"'+paramThree+'"}');
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@JavascriptInterface
public void get_payinfo(String paramOne, String paramTwo, String paramThree) {
payInforEntity=PayInforEntity.getInstance();
payInforEntity.paytype="支付宝";
payInforEntity.paramOne=paramOne;
payInforEntity.paramTwo=paramTwo;
payInforEntity.paramThree=paramThree;
······
String orderInfo = "paramOne=" + "\"" + paramOne + "\"";

orderInfo += "&paramTwo=" + "\"" + paramTwo + "\"";

orderInfo += "&paramThree=" + "\"" + paramThree.replace("T", " ") + "\"";

orderInfo += "&····=" + "\"" + ···· + "\"";

final String finalOrderInfo = orderInfo;
Runnable payRunnable = new Runnable() {
@Override
public void run() {
// 构造PayTask 对象
PayTask alipay = new PayTask(Resume_ToTopActivity.this);
// 调用支付接口,获取支付结果
String result = alipay.pay(finalOrderInfo, true);

Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
}

@JavascriptInterface
public void get_WXpayInfo(String paramOne, String paramTwo, String paramThree) throws Exception {
payInforEntity=PayInforEntity.getInstance();
payInforEntity.paytype="微信";
payInforEntity.paramOne=paramOne;
payInforEntity.paramTwo=paramTwo;
payInforEntity.paramThree=paramThree;
······
if (!isWeixinAvilible(Resume_ToTopActivity.this)) {
Weixin_Download = ViewUtils.Weixin_Download(Resume_ToTopActivity.this);
Weixin_Download.show();
Toast.makeText(Resume_ToTopActivity.this,"请安装微信",Toast.LENGTH_SHORT).show();
return;
}
api = WXAPIFactory.createWXAPI(Resume_ToTopActivity.this, "·····");
api.registerApp("·····");
String url = "http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=android";
PayReq req = new PayReq();
req.appId = "·····";
req.partnerId = partnerId;
req.prepayId = prepayId;
req.nonceStr = nonceStr;
req.timeStamp = timeStamp;
req.packageValue = "Sign=WXPay";
req.sign = sign;
Toast.makeText(Resume_ToTopActivity.this, "正常调起支付", Toast.LENGTH_SHORT).show();
// 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
api.sendReq(req);
}