云闪付APP乘车码
云闪付
收单机构
商户
开发者
发卡机构
云闪付APP乘车码标准接入解决方案,旨在通过该解决方案为各地公交地铁行业方或者第三服务方接入云闪付APP乘车码业务,本方案提供了与合作方的相应接口对接,用户信息授权,无感支付等功能。
服务对象

公交地铁行业方或第三服务提供方。

应用场景

公交地铁出行场景

接入流程

编号

阶段

责任方

说明

1

合作洽谈

接入申请方(银联总公司各部门或分公司等)

 

银联总公司各部门或分公司与行业方进行商务洽谈,双方同意服务接入云闪付APP,为云闪付APP用户提供该服务。

2

协议签署

接入申请方

云闪付事业部

用户信息输出、收单垫资等协议的签署

3

全渠道商户入网

接入申请方(银联总公司各部门及各分公司等)

 

合作意向确定后,接入申请方通过UOSP工单向云闪付事业部相关人员提出业务接入申请。接入方完成全渠道商户入网,并在BOS工单中备注“申请开通云闪付APP无感支付(签约免密支付)权限”

4

技术对接

接入申请方

云闪付事业部

接入申请方根据云闪付APP乘车码标准接入解决方案对接文档进行改造,银联会指派人员进行技术支持与后续的测试。

5

业务上线

接入申请方

云闪付事业部

接入方测试通过后,向云闪付事业部提交测试报告,上线申请表等,审核通过后,云闪付安排时间上线。


步骤一:引入JS

在需要调用JS接口的页面引入如下JS文件,(仅支持https):https://open.95516.com/s/open/js/upsdk.js。
upsdk.js文件依赖Zepto或Jquery,Zepto的版本要求1.0及以上,Jquery的版本要求1.4及以上(建议用最新的Zepto及Jquery)。

步骤二:通过config接口注入权限验证配置

所有需要使用UPSDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次; 如果跳转的页面无需使用插件,则无需config, 否则需要重新执行config)。
Upsdk.config({
 appId: ‘’, // 必填,接入方的唯一标识
 timestamp: , // 必填,生成签名的时间戳,从1970年1月1日00:00:00至今的秒数
 nonceStr: ‘’, // 必填,生成签名的随机串
 signature: ‘’,// 必填,生成签名的摘要,采用sha256算法, 详见最后一章FAQ
 debug: true // 开发阶段可打开此标记,云闪付APP会将调试信息toast出来
});

建议接入方在开发联调时,打开debug: true 开关,UPSDK只有在开关打开时才会输出状态信息,帮助开发者定位错误。 请务必在最终生产版本关闭此开关。

步骤三:配置信息验证

(1)通过ready接口处理成功验证
upsdk.ready(function(){
 // config信息验证后会执行ready方法
});
(2)通过error接口处理失败验证
upsdk.error(function(err){
 // config信息验证失败会执行error方法
});

另:判断是否在云闪付APP内

var agent = navigator.userAgent.toLowerCase();
var isInsideWallet = ((new RegExp(/(com.unionpay.chsp)/).test(agent)) || (new RegExp(/(com.unionpay.mobilepay)/).test(agent)));
插件详情

a) 总体说明
参数基于如下字典格式传递,如果插件有成功回调的话,一定会调用success回调;有失败回调的话,会执行fail或者cancel回调。

b) 支付接口
upsdk.pay({
 tn: ‘支付流水号Ticket Number.’,
 success: function(){
  // 支付成功, 开发者执行后续操作。
 },
 fail: function(err){
  // 支付失败, err.msg 是失败原因描述, 比如TN号不合法, 或者用户取消了交易等等。
 }
});
前台支付对接,整个支付流程详解请参考第五章第二节FAQ。

c) 拍照或从手机相册中选图接口
upsdk.chooseImage({
 maxWidth: ‘目标图片宽度, 默认500’, 可选
 maxHeight: ‘目标图片高度, 默认1000’, 可选
 sourceType: ‘1|2|3, 仅允许拍照|仅允许从手机相册中选图|拍照或从手机相册中选图都支持, 默认为3’,可选
 success: function (data) {
  if (data.base64) {
   // 目标图片采用base64编码.
  }
 }
});
此接口还会返回选择的图片类型,比如jpg|png|gif

d) 设置页面标题接口
upsdk.setNavigationBarTitle({
 title: ‘设置云闪付标题’
});

e) 设置标题栏右边按钮接口
文字,图片均支持。
Upsdk.setNavigationBarRightButton({
 // title和image可任选其一, 同时有的话, title优先
 title: ‘标题栏文字’,
 image: ‘按钮图片绝对路径’,
 handler: function(){
  // 用户点击标题按钮以后回调函数
 }
});

f) 调用云闪付的扫码功能接口
upsdk.scanQRCode({
 scanType: [“qrCode”,”barCode”],
 success: function(result){
  alert(‘Scan result = ‘ + result);
 }
});

g) 绑定银行卡接口
upsdk.addBankCard({
 success: function(){
  // 绑卡成功
 },
 fail: function(){
  // 绑卡失败或者用户取消
 }
 sence: ‘场景号’ //可选参数,用来控制添加特定类型的银行卡,例如只添加信用卡
});

h) Toast文言显示接口
upsdk.showFlashInfo({
 msg: ‘绑定银行卡成功’
});

i)关闭当前WEB窗口接口
upsdk.closeWebApp();
无需传递参数,也没有回调函数返回。

j) 返回用户在首页选取的城市
upsdk.getLocationCity({
 success: function(cityCd){
   //插件返回的城市代码cityCd 符合全国行政区划代码表标准,比如广州市为440100
 }
});

k) 用户通过输入支付密码授权
此插件会引导用户进入支付密码输入页面,验证支付密码正确与否
upsdk.verifyPayPwd({
 transNo: ‘后台获取的支付密码验证流水号’,
 bizType:’业务类型编号 ‘,
 success: function() {
  // 支付密码验证通过
 }
});
请参考FAQ获取更多信息。

l) 获取用户当前位置经纬度
upsdk.getLocationGps({
 success: success,
 fail: fail
});
成功返回latitude 和longitude, 基于高德地图坐标系

m) 云闪付分享插件
upsdk.showSharePopup({
 title: ‘银联云闪付随机立减大优惠~!’,
 desc: ‘我刚刚使用银联云闪付, 省了30元,大家快来使用吧.’,
 shareUrl: ‘https://youhui.95516.com’,
 picUrl: ‘https://youhui.95516.com/web/image/mchnt/coupon/Z00000000138804_logo_list_web.jpg’
});
picUrl 选填,默认显示银联云闪付图标

n) 获取本地音视频(或图片)
分两个步骤:
步骤一:选择本地音视频(或图片),获取到文件基本信息
upsdk.chooseFileFromAlbum({
 maxSize: ‘1024’,// 最大上传的文件大小(单位byte),若选择的文件大于该值进入失败回调。建议值不要超过100m(即100*1024*1024)
 sourceType: ‘00’, // 00:仅支持视频文件,例如mp4、mov等。01:仅支持图片文件,例如png、jpg等。02:支持视频+图片文件。
 success:function(data){
  // 成功返回{url:’视频地址’,size:’视频大小’,filename:’视频文件名,例如123.mp4’}
 },
 fail: function(err){
  // 失败回调{code:’失败码’,msg:’失败原因描述’}
  // {code:’00’,msg:’参数错误’}
  // {code:’01’,msg:’内部错误’}
  // {code:’02’,msg:’权限失败’}
  // {code:’03’,msg:’用户选择的文件超过最大值’}
  // {code:’04’,msg:’其他错误’}
 }
});
步骤二:将选取的文件分块,通过以下插件分块获取文件流的base64
upsdk.readAlbumData({
 url: ‘url’,// 即步骤一成功回调获取视频地址url
 bufferSize: ‘1024’, //分块大小,单位byte,最大不可以超过512kb(即512*1024)
 fromOffset: ‘0’, //每块的开始位置,第一块为0,第二块为1*bufferSize,依次类推
 success:function(data){
  // 成功返回{data:’文件块的base64’,isFinished:’1’}
  // isFinished:0代表文件还有块未获取,1代表文件所有块已获取完毕
 },
 fail: function(err){
  // 失败回调{code:’失败码’,msg:’失败原因描述’}
  // {code:’00’,msg:’参数错误’}
  // {code:’01’,msg:’内部错误’}
  // {code:’02’,msg:’权限失败’}
  // {code:’03’,msg:’用户选择的文件超过最大值’}
  // {code:’04’,msg:’其他错误’}
 }
});

o) 录音并获取录音文件【录音文件格式为mp3,采用覆盖模式,只会存储最后一次的录音】
分两个步骤:
步骤一:开始录音,获得成功回调后,可以选择主动停止录音,或者等待最大录音时间后自动停止。
/**
* 开始录音插件
*/
upsdk.startAudioRecording({
 maxTime: ‘10’,// 单位为秒,必选参数,允许用户录制的最大时间
 success:function(){
  // 成功回调,此处可选择主动停止录音,或者等待maxTime
 },
 fail: function(err){
  // 失败回调{code:’失败码’,msg:’失败原因描述’}
  // {code:’00’,msg:’参数错误’}
  // {code:’01’,msg:’内部错误’}
  // {code:’02’,msg:’权限失败’}
  // {code:’03’,msg:’用户选择的文件超过最大值’}
  // {code:’04’,msg:’其他错误’}
 }
});
/**
* 停止录音插件
*/
upsdk.stopAudioRecording({
 success:function(){
  // 成功回调,此处可获取已录好的本地音频文件
 },
 fail: function(err){
  // 失败回调{code:’失败码’,msg:’失败原因描述’}
  // {code:’00’,msg:’参数错误’}
  // {code:’01’,msg:’内部错误’}
  // {code:’02’,msg:’权限失败’}
  // {code:’03’,msg:’用户选择的文件超过最大值’}
  // {code:’04’,msg:’其他错误’}
 }
});
步骤二:将录好的本地音频文件分块,通过以下插件分块获取文件流的base64。【注意,该插件应该在停止录音插件成功回调中使用,或者等待最大录音时间maxTime后才能使用】
upsdk.readAudioRecordingData({
 bufferSize: ‘1024’, //分块大小,单位byte,最大不可以超过512kb(即512*1024)
 fromOffset: ‘0’, //每块的开始位置,第一块为0,第二块为1*bufferSize,依次类推
 success:function(data){
  // 成功返回{data:’文件块的base64’,isFinished:’1’}
  // isFinished:0代表文件还有块未获取,1代表文件所有块已获取完毕
 },
 fail: function(err){
  // 失败回调{code:’失败码’,msg:’失败原因描述’}
  // {code:’00’,msg:’参数错误’}
  // {code:’01’,msg:’内部错误’}
  // {code:’02’,msg:’权限失败’}
  // {code:’03’,msg:’用户选择的文件超过最大值’}
  // {code:’04’,msg:’其他错误’}
 }
});
备注:始终保存最后一次录音的文件,仅在卸载APP后才会清除。

p) 录视频并获取视频文件【录频文件格式为mp4,采用覆盖模式,只会存储最后一次录的视频】
分两个步骤:
步骤一:开始录视频,到达最大录制时间,视频自动录制结束。用户录制完视频后调用成功回调。
/**
* 开始录视频插件
*/
upsdk.startVideoRecording({
 maxTime: ‘10’,// 单位为秒,必选参数,允许用户录制的最大时间
 success:function(){
  // 成功回调,此时用户已完成录制视频,可获取录制的视频文件
 },
 fail: function(err){
  // 失败回调{code:’失败码’,msg:’失败原因描述’}
  // {code:’00’,msg:’参数错误’}
  // {code:’01’,msg:’内部错误’}
  // {code:’02’,msg:’权限失败’}
  // {code:’03’,msg:’用户选择的文件超过最大值’}
  // {code:’04’,msg:’其他错误’}
 }
});
步骤二:将录好的本地视频文件分块,通过以下插件分块获取文件流的base64。【注意,该插件应该在开始录视频插件成功回调中使用。】
upsdk.readVideoRecordingData({
 bufferSize: ‘1024’, //分块大小,单位byte,最大不可以超过512kb(即512*1024)
 fromOffset: ‘0’, //每块的开始位置,第一块为0,第二块为1*bufferSize,依次类推
 success:function(data){
  // 成功返回{data:’文件块的base64’,isFinished:’1’}
  // isFinished:0代表文件还有块未获取,1代表文件所有块已获取完毕
 },
 fail: function(err){
  // 失败回调{code:’失败码’,msg:’失败原因描述’}
  // {code:’00’,msg:’参数错误’}
  // {code:’01’,msg:’内部错误’}
  // {code:’02’,msg:’权限失败’}
  // {code:’03’,msg:’用户选择的文件超过最大值’}
  // {code:’04’,msg:’其他错误’}
 }
});
备注:始终保存最后一次录音的文件,仅在卸载APP后才会清除。

q) 获取活体检测后保存在本地的视频和图片
1. 获取活体检测的视频(一次获取,视频格式为mp4)
upsdk.readFaceVideoData({
 success:function(data){
  // 成功返回{data:’文件块的base64’}
 },
 fail: function(err){
  // 失败回调{code:’失败码’, msg:’失败原因描述’}
  // {code:’00’, msg:’参数错误’}
  // {code:’01’, msg:’内部错误’}
  // {code:’07’, msg:’文件不存在’}
 }
});
2. 获取活体检测的图片(一次获取,图片格式为jpg)
upsdk.readFaceImageData({
 success:function(data){
  // 成功返回{data:’文件块的base64’}
 },
 fail: function(err){
  // 失败回调{code:’失败码’, msg:’失败原因描述’}
  // {code:’00’, msg:’参数错误’}
  // {code:’01’, msg:’内部错误’}
  // {code:’07’, msg:’文件不存在’}
 }
});

r) 通知客户端刷新卡管家中的虚拟卡列表
upsdk.noteInfoChange()
无需传递参数,也没有回调函数返回。

s) 打开客户端中特定React Native页面
upsdk.openRNPage({
 dest: "rntransfer", // 必传,目标RN页面,示例中表示打开 转账页面(RN实现)
 isFinished: "1", // 可选,默认为‘0’,为‘1’则关闭当前webview
 extraData: {// 可选,具体参数内容与对接业务强相关,以下示例为农村转账业务:
  KTransferRouteType: "3", //固定值 转账类型”3" 表示进入农村转账场景
  kTransferUserMsg: {
   transferName: "name", //name 姓名 不加掩码
   transferCardNum: "card", //card 卡号 全卡号
   transferAmount: "amount" //金额 单位分 整数不能有小数
  },
  kTransferThirdMsg: { //生活后台接口新增字段 后续获取tn 支付使用
   thirdOrderId: "", // 第三方订单流水号
   thirdName: "", //第三方抬头
   thirdType: "appId" //接入方的唯一标识
  }
 },
 success:function(){ // 成功跳转 },
 fail: function(msg){ // 失败回调}
});
注意:属性extraData为可选参数,是否传该参数以及具体该参数的值的具体内容需与对接业务沟通并确认好,以上示例仅为农村转账业务。

t) 地图导航插件
通过提供起始经纬度等信息调用插件可打开地图并显示导航路线
upsdk.navi({
 sLat:'31.23958', // 起点维度
 sLon:'121.499763', // 起点经度
 sName:'上海东方明珠', // 起点名称
 dLat:'39.917854', // 终点维度
 dLon:'116.397006', // 终点经度
 dName:'北京故宫', // 终点名称
 success:function(){ // 成功回调 },
 fail: function(msg){ // 失败回调}
});

u) 设置屏幕亮度
upsdk.setScreenBrightness({
 brightness:'0.2', // 屏幕亮度值,范围取值0-1。精确到小数点后一位
 success:function(data){
  // 成功回调 {data.brightness}
 },
 fail: function(msg){ // 失败回调}
});

v) 获取当前屏幕亮度
upsdk.getScreenBrightness({
 success:function(data){
  // 成功回调 {data.brightness}
 },
 fail: function(msg){ // 失败回调}
});

w) 打开屏幕截图权限(仅限android使用)
upsdk.changeScreenShot({
 switch:true, // true表示禁止截屏,false表示允许截屏
 success:function(){ // 成功回调 },
 fail: function(msg){ // 失败回调}
});

x) 监听屏幕截屏(仅限ios使用)
upsdk.monitorScreenShot({
 success:function(){
  // 成功回调,表明用户已经进行了截屏
 }
});
备注:通常只在需要监听的页面调用该插件打开监听。

y) 移除监听屏幕截屏(仅限ios使用)
upsdk.removeScreenShot({
 success:function(){
  // 成功回调,表明用户已经移除了截屏
 }
});
备注:打开监听后,只有当该webview关闭后才会停止监听。若其它页面不需要监听可调用该插件移除监听。


应答码参照
应答码 描述 解决方案
联系我们

业务咨询: 400-77-95516

曹晓雯

caoxiaowen@unionpay.com

咨询与服务