Phonegap 之 iOS银联在线支付(js调用ios端银联支付控件)
Phonegap项目,做支付的时候,当把网站打包到ios或android端成app后,在app上通过wap调用银联在线存在一个问题:
就是当从银联支付成功后,再从服务器返回到app客户端就很难实现。
wap银联支付流程是这样:客户端---> 服务器(构建支付请求)--> 银联支付 ---> 返回到服务端(处理支付结果)。所以对于手机网站银联支付没有问题,但是对于ios端app和android端app, 再通过wap支付,发现支付成功后,很难在回到app客户端了。
所以这里就必须借助Phonegap的插件js脚本,通过js调用ios端或android端原生代码,然后再通过原生代码调用银联支付专门为移动客户端准备的sdk,去进行支付。支付成功后,银联会把支付结果一边通知到我们网站你的服务器,另一方面也会把给一个通知到ios或android客户端,这样就完美了!
------------------------------------------------------------------------------------------------------------------------------
先上Phonegap项目ios端app如何调用银联在线的支付流程截图:
1、客户端请求银联支付,网站服务端构建银联支付请求;并从银联获得银联生成的系统流水号

2、通过Phonegap脚本插件,调用OC代码,OC调用银联支付接口,弹出银联支付控件,输入你的银联卡号和手机验证码等信息,完成支付


3、支付成功后,点击“返回商户”, 银联一边会回传一个信息到网站服务端,一边也会通知ios端app的代理控制器支付结果。
然后ios端这边可以根据银联返回的支付信息,做自己的业务逻辑处理。

------------------------------------ 大概代码如下: -------------------------------
1、客户端选择银联支付,js端代码:
//模拟去服务器端构建银联请求, myApp是使用Framework7框架创建的一个js对象
function toPay() {
var ServerDomain = "http://192.168.1.189"; //网站服务端地址
var isApp = ServerDomain.indexOf(location.hostname) > 0 ? "0" : "1"; //是否来自app的请求 $$.ajax({
url: ServerDomain + "Payment/CreateOrderInfo",
method: "post",
dataType: "json",
data: { "isApp": isApp },
success: function (data) {
if (data.success == "0") {
myApp.alert(data.info); //弹窗提示信息
return false;
} //data.info 信息,如果是通过手机网站访问,则data.info是一个form表单html页面代码;
//如果是移动客户端(ios或android),则data.info是来自银联的系统流水号:tn
if (isApp == "0") { //来自wap的请求
//针对手机网站的银联支付请求,直接构建get请求表单,跳转到银联那边
document.write(data.info);
}
else if (myApp.device.ios) { //来自ios app的请求
Cordova.exec(function (successInfo) { /*成功通知方法*/ }, function (errorInfo) { /*失败回调通知方法*/ }, "PluginName", "uppay", [data.info]);
}
else if (myApp.device.android) { //来自android app的请求
UnionPayFunc(data.info);
}
}
});
}
2、服务端构建银联支付请求代码,服务端使用C#的MVC
public class PaymentController : Controller
{
/// <summary>测试构建银联支付请求:如果是wap请求,则构建form表单;若是app请求,则获取银联系统流水号
/// </summary>
/// <param name="isApp">是否来自app的请求【0表示来自wap, 1表示来自android】</param>
/// <returns></returns>
public JsonResult CreateOrderInfo(int isApp)
{
//以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己需要,按照技术文档编写。该代码仅供参考
// **************演示前台交易的请求***********************
Dictionary<string, string> param = new Dictionary<string, string>();
//生成订单编号
Random rnd = new Random();
string orderID = DateTime.Now.ToString("yyyyMMddHHmmss") + (rnd.Next() + ).ToString().Trim(); param["version"] = "5.0.0";//版本号
param["encoding"] = "UTF-8";//编码方式
param["certId"] = CertUtil.GetSignCertId(); //证书ID(签名私钥证书的Serial Number)
param["txnType"] = "";//交易类型:00=查询交易,01=消费,04=退货,12=代付,21=批量交易,22=批量查询
param["txnSubType"] = "";//交易子类,依据实际交易类型填写
param["bizType"] = "";//产品类型:000201=B2C网关支付,000401=代付,000501=代收,000601=账单支付,000901=绑定支付,000202=B2B param["frontUrl"] = "http://192.168.1.189/Payment/UppayFront"; //前台通知地址(前台返回商户结果时使用,前台类交易需上送)
param["backUrl"] = "http://192.168.1.189/Payment/UnppayBack"; //后台通知地址,改自己的外网地址(后台返回商户结果时使用,如上送,则发送商户后台交易结果通知)
//param["frontFailUrl"] = "http://192.168.1.189/Payment/UnppayFail";//失败交易前台跳转地址(可选:支付失败时,页面跳转至商户该URL,不带交易信息,仅跳转)
param["signMethod"] = "";//签名方法(01:表示采用RSA)
param["channelType"] = "";//渠道类型: 05=语音,07=互联网(PC),08=移动(手机)
param["accessType"] = "";//接入类型:0=商户直连接入,1=收单机构接入,2=平台商户接入
param["merId"] = "";//商户代码(请填入已被批准加入银联互联网系统的商户代码)
param["orderId"] = orderID;//商户订单号(不能含”-“或”_")
param["txnTime"] = DateTime.Now.ToString("yyyyMMddHHmmss");//订单发送时间
param["txnAmt"] = "";//交易金额,单位分
param["currencyCode"] = "";//交易币种(币种格式必须为3位代码,默认取值:156(人民币))
//param["orderDesc"] = "订单描述";//订单描述,暂时不会起作用
param["reqReserved"] = "";//请求方保留域,透传字段,查询、通知、对账文件中均会原样出现 //将参数进行签名
SDKUtil.Sign(param, Encoding.UTF8); string returnInfo = ""; //返回信息
string isSuccess = ""; // if (isApp == )//wap请求,则返回form表单请求请求
{
// 将SDKUtil产生的Html文档写入页面,从而引导用户浏览器重定向
returnInfo = SDKUtil.CreateAutoSubmitForm(SDKConfig.FrontTransUrl, param, Encoding.UTF8) + "<script type='text/javascript'>OnLoadSubmit();</script>";
}
else if (isApp == )//app请求,则返回银联生成的系统流水号
{
// 初始化通信处理类
HttpClient hc = new HttpClient(SDKConfig.AppRequestUrl);
//// 发送请求获取通信应答
int status = hc.Send(param, Encoding.UTF8);
// 返回结果
string result = hc.Result; if (status != )
{
isSuccess = "";
returnInfo = "请求银联失败";
return Json(new { success = isSuccess, info = returnInfo }, JsonRequestBehavior.AllowGet);
} Dictionary<string, string> resData = SDKUtil.CoverstringToDictionary(result); if (!SDKUtil.Validate(resData, Encoding.UTF8))
{
returnInfo = "验证失败";
isSuccess = "";
return Json(new { success = isSuccess, info = returnInfo }, JsonRequestBehavior.AllowGet);
} string respCode = resData["respCode"];
string respMsg = resData["respMsg"];
returnInfo = resData["tn"]; //银受理订单号:商户推送订单后银联移动支付系统返回该流水号,商户调用支付控件时使用
} return Json(new { success = isSuccess, info = returnInfo }, JsonRequestBehavior.AllowGet);
} ///........
}
3、ios端代码,js脚本调用OC代码需要Phonegap提供的一个脚本插件支持: cordova.js (下载链接)
创建一个类Plugin, 继承Phonegap插件类:CDVPlugin,
还需要在配置文件config.xml中配置一下,才能使用js调用Plugin类里面的方法

#import <UIKit/UIKit.h>
#import <Cordova/CDVPlugin.h> @interface Plugin : CDVPlugin @property (nonatomic, copy) NSString* callbackID; //支付
- (void)uppay:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options; @end
#import "Plugin.h"
#import "MainViewController.h"
#import "UPPayPlugin.h" @interface Plugin () @end @implementation Plugin @synthesize callbackID; - (void)uppay:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options{
// 这是classid,在下面的PluginResult进行数据的返回时,将会用到它
self.callbackID = [arguments pop]; NSString *tn = [arguments objectAtIndex:]; //获取银联生成返回的系统流水号
MainViewController *controller = (MainViewController *)self.viewController; //调用银联支付接口
[UPPayPlugin startPay:tn mode:@"" viewController:controller delegate:controller];
} @end
代理控制器设置银联支付结束后的代理方法:
#import <Cordova/CDVViewController.h>
#import <Cordova/CDVCommandDelegateImpl.h>
#import <Cordova/CDVCommandQueue.h>
#import "UPPayPluginDelegate.h" @interface MainViewController : CDVViewController <UPPayPluginDelegate> //.......... @end
#import "MainViewController.h"
#import "AppDelegate.h" @implementation MainViewController #pragma mark - 支付结束后代理方法
//success、fail、cancel,分别代表:支付成功、支付失败、用户取消支付
-(void)UPPayPluginResult:(NSString*)result
{
NSLog(@"支付结果:%@", result); //调用脚本方法,处理支付完成后的逻辑
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"unipayPayResult('%@');", result]];
} //....... @end
4、支付成功后,ios 控制器收到银联的支付结果,调用js脚本方法,处理后面逻辑:
// ios支付成功后,收到银联通知跳转到其他页面去, info参数有三种状态:success, fail, cancl
function unipayPayResult(info) {
var textTip = "";
if (info == "success") {
textTip = "支付成功";
}
else if (info == "fail") {
textTip = "支付失败";
}
else {
textTip = "取消支付";
} myApp.alert(textTip);
//弹窗提示后,跳到主页面去
mainView.loadPage("index.html");
}
原文链接地址:http://www.cnblogs.com/tandaxia/p/4964753.html
cordova for iOS 通过js调用OC原生代码demo:
github地址:https://github.com/xiaotanit/Tan_CordovaPlugin
csdn地址: http://download.csdn.net/detail/tandaxia/9524576
Phonegap 之 iOS银联在线支付(js调用ios端银联支付控件)的更多相关文章
- JS调用Delphi编写的OCX控件
原文:http://www.mamicode.com/info-detail-471283.html 一.使用Delphi XE2编写OCX控件 生成OCX工程: 1.File-New-Other,在 ...
- js 调用IE内置打印控件
转自学网(http://www.xue5.com/itedu/200802/102909.html) WebBrowser是IE内置的浏览器控件,无需用户下载. 一.WebBrowser控件 < ...
- 转载 OS js oc相互调用(JavaScriptCore) ---js调用iOS ---js里面直接调用方法
OS js oc相互调用(JavaScriptCore) 接着上节我们讲到的iOS调用js 下来我们使用js调用iOS js调用iOS分两种情况 一,js里面直接调用方法 二,js里面通过对象调用 ...
- [iOS]通过JS调用iOS函数时的URL编码问题
在前面的文章:[iOS]在WebApp中怎样使用JS调用iOS的函数 中,提到了怎样使用JS通过改动URL调用iOS的内部函数. 当中会遇到一个问题,就是编码问题.比方通过URL调用弹窗,在里面写上内 ...
- js如何获取asp.net服务器端控件的值(label,textbox,dropdownlist,radiobuttonlist等)
js如何获取asp.net服务器端控件的值(label,textbox,dropdownlist,radiobuttonlist等) 欢迎访问原稿:http://hi.baidu.com/2wixia ...
- js组件开发-移动端地区选择控件mobile-select-area
移动端地区选择控件mobile-select-area 由于之前的[js开源组件开发]js手机联动选择地区仿ios 开源git 很受欢迎,于是我又对其进行了一些优化,包括可选的范围变大了,添加了默认空 ...
- iOS系列 基础篇 09 开关、滑块和分段控件
iOS系列 基础篇 09 开关.滑块和分段控件 目录: 案例说明 开关控件Switch 滑块控件Slider 分段控件Segmented Control 1. 案例说明 开关控件(Switch).滑块 ...
- ASP.NET开发中主要的字符验证方法-JS验证、正则表达式、验证控件、后台验证
ASP.NET开发中主要的字符验证方法-JS验证.正则表达式.验证控件.后台验证 2012年03月19日 星期一 下午 8:53 在ASP.NET开发中主要的验证方法收藏 <1>使用JS验 ...
- 【高德地图API】从零开始学高德JS API(二)地图控件与插件——测距、圆形编辑器、鼠标工具、地图类型切换、鹰眼鱼骨
原文:[高德地图API]从零开始学高德JS API(二)地图控件与插件——测距.圆形编辑器.鼠标工具.地图类型切换.鹰眼鱼骨 摘要:无论是控件还是插件,都是在一级API接口的基础上,进行二次开发,封装 ...
随机推荐
- [SDK2.2]Windows Azure Virtual Network (1) 概念
<Windows Azure Platform 系列文章目录> Windows Azure Virtual Network是非常重要的概念,其主要作用有以下两点: 1.将多台Azure V ...
- 浏览器退出之后php还会继续执行么?
浏览器退出之后php还会继续执行么? 前提:这里说的是典型的lnmp结构,nginx+php-fpm的模式 如果我有个php程序执行地非常慢,甚至于在代码中sleep(),然后浏览器连接上服务的时候, ...
- 【Swift学习】Swift编程之旅---扩展(二十四)
扩展就是向一个已有的类.结构体或枚举类型添加新功能,包含属性和方法,如果你定义了一个扩展向一个已有类型添加新功能,那么这个新功能对该类型的所有已有实例中都是可用的,即使它们是在你的这个扩展的前面定义的 ...
- Android Studio添加PNG图片报错原因
今天在网上看到一个关于Splash Activity的Android帖子,博主在一通讲解之后也给出了代码.于是果断下载下来了看看怎么实现的.一步步照着流程把这个功能实现了一遍.一切都没有大问题,但是在 ...
- Python语言特性之3:@staticmethod和@classmethod
问题:Python中@staticmethod和@classmethod两种装饰器装饰的函数有什么不同? 原地址:http://stackoverflow.com/questions/136097/w ...
- XML基础学习02<linq to xml>
Linq to XML的理解 1:这是一种比较好的操作Xml的工具. àXDocument 文档 àXElement 元素 àXAttribute 属性 àXText 文本 2:这里还是和我们之前创建 ...
- C# 3DES加密
最近一个项目中,因为服务端是用的java开发的,客户端是用的C#,由于通信部分采用到了3DES加密,所以做个记录,以备以后需要的时候直接用. 这是对方(java)的加密算法,和网上流传的代码也差不多( ...
- 【iOS】配置和使用静态库
上一篇 我们演示了了如何创建自己的静态库,最终生成多个.a文件,根据需要引用工程就可以直接使用静态库了,但是有个很麻烦的问题,模拟器用的库和真机的不是同一个,当我们切换的时候需要更换静态库,有两种方式 ...
- 学习“迷你ASP.NET MVC框架”后的小结
看蒋老师MVC的书第二个大收获可以是算是看了这个迷你ASP.NET MVC框架了,虽然它远不如真正ASP.NET MVC(下文简称“MVC”)那么复杂庞大,但在迷你版中绕来绕去也够呛的.这部分我看了几 ...
- 让 ListView 在 Android 可回弹
说明:让 ListView 在 Android 可回弹. 适用:Delphi XE5 修改:找出 FMX.Platform.Android.pas 档案,并复制到自己的 Project 路径里,找到 ...