赞
踩
文章主要记录uniapp开发公众号H5、APP、小程序过程中支付相关的微信支付、支付宝支付调用,支付失败处理,多端兼容性如状态栏背景色处理、H5页面参数传递转义处理,H5跨域处理,页面使用拖拽功能,并且拖拽不影响页面其它按钮点击等的操作。
uni-app微信支付、支付宝支付
首先要在微信支付商户平台申请接入对应的平台(APP,H5,小程序);支付宝支付也需要在支付宝开放平台申请对应的平台支付
1. 微信公众号中(H5)调用微信支付: 获取openid,引入微信公众平台API的微信H5支付JSSDK插件 或者 使用微信浏览器内置的onBrideReady(这种方式不需要引入JSSDK,但是只能在微信浏览器中使用)
// 引入微信JSSDK var jweixin = require('@/js_sdk/jweixin-module@1.6.0.js') export function toWxPay(res) { // res为下单后端接口返回的数据,微信支付需要的参数(appId,timeStamp,nonceStr,package,signType,paySign)是后端接口返回的,下单时需要传当前用户的openid jweixin.config({ // debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: res.third_data.appId, // 必填,公众号的唯一标识 timestamp: res.third_data.timeStamp, // 必填,生成签名的时间戳 nonceStr: res.third_data.nonceStr, // 必填,生成签名的随机串 signature: res.third_data.authSign, // 必填,签名,见附录1 jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); jweixin.ready(function() { // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 jweixin.chooseWXPay({ appId: res.third_data.appId, //公众号名称,由商户传入 timestamp: res.third_data.timeStamp, //时间戳,自1970年以来的秒数 nonceStr: res.third_data.nonceStr, //随机串 package: res.third_data.package, signType: res.third_data.signType, //微信签名方式: paySign: res.third_data.paySign, //微信签名 success: function(res) { // console.log('支付成功' + res) uni.showToast({ title: '支付成功' }) setTimeout(function() { uni.navigateBack({ delta: 1 }) }, 1000) }, cancel: function(res) { // console.log('取消支付' + res) uni.showToast({ title: '取消支付', icon: 'none' }) }, fail: function(res) { // console.log('支付失败' + res) uni.showToast({ title: '支付失败', icon: 'none' }) } }) }); jweixin.error(function(res) { console.log('身份验证失效' + res) }); } // 微信浏览器内置支付方式,appid,timeStamp,nonceStr,package,signType,paySign参数值从接口获取 function onBridgeReady(res) { WeixinJSBridge.invoke( "getBrandWCPayRequest", { appId: "wx2421b1c4370ec43b", //公众号名称,由商户传入 timeStamp: "1395712654", //时间戳,自1970年以来的秒数 nonceStr: "e61463f8efa94090b1f366cccfbbb444", //随机串 package: "prepay_id=u802345jgfjsdfgsdg888", signType: "RSA", //微信签名方式: paySign: "70EA570631E4BB79628FBCA90534C63FF7FADD89", //微信签名 }, function (res) { if (res.err_msg == "get_brand_wcpay_request:ok") { // 支付成功处理 } } ); } export function wxBridegePay(res){ if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener("WeixinJSBridgeReady", onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent("WeixinJSBridgeReady", onBridgeReady); document.attachEvent("onWeixinJSBridgeReady", onBridgeReady); } } else { onBridgeReady(res); } }
2. 支付宝H5支付:通过支付宝扫码调起支付宝支付,后端配合获取用户buyer_id;下载或引入Alipay JSSDK,页面下单后接口返回对应的参数,再调用ap.tradePay唤起支付,有2种唤起方式,根据接口返回的参数类型调用
// 1.交易号唤起支付——tradeNO参数为页面下单后接口返回的交易号 function aliPay(tradeNO){ ap.tradePay({ tradeNO: tradeNO }, function(res){ if(res.resultCode == '9000'){ console.log("支付成功") }else{ ap.alert('支付失败,'+res.resultCode); } }); } // 2.订单字符串唤起支付——orderStr参数为页面下单后接口返回的交易字符串 function aliPay(orderStr){ ap.tradePay({ orderStr: orderStr}, function(res){ if(res.resultCode == '9000'){ console.log("支付成功") }else{ ap.alert('支付失败,'+res.resultCode); } }); }
3. APP中调用微信支付、支付宝支付
export function appPay(orderInfo, provider) { // orderInfo包含的key值 // orderInfo = { // "appid": objData.appid, // "noncestr": objData.noncestr, // "package": objData.package, // "partnerid": objData.partnerid, // "prepayid": objData.prepayid, // "timestamp": objData.timestamp, // "sign": resObj.sign, // } // orderInfo为下单后端接口返回的数据,微信支付时provider为wxpay,支付宝支付时provider为alipay uni.requestPayment({ provider: provider, orderInfo: orderInfo, success: function(res) { uni.showToast({ title: '支付成功' }) }, fail: function(err) { console.log(err) showTishi('支付失败') } }); }
微信支付调用出现错误 requestPayment:fail [payment微信:-1]General errors",“errCode”:-100,“code”:-100} 时问题排查:
uni-app请求封装
6. H5端跨域处理 —— 在manifest.json中新增跨域处理
"h5" : { "devServer" : { "port" : 9000, "proxy" : { "/api" : { "target" : url, // url为接口地址 "secure" : false, "changeOrigin" : true, "pathRewrite" : { "^/api" : "/api" // web-admin是接口前面统一的参数,在这里统一处理下,没有的不用"" } } } } } // 使用方法:假如接口地址为 "http://abc.com/api/login", 配置后直接写 "/api/login",在封装好的request.js文件中写法参考下面一条的H5情况
const BASE_URL = url // url是接口地址 export const request = (options) => { return new Promise((resolve, reject) => { // #ifdef MP-WEIXIN options.url= BASE_URL + options.url // #endif // #ifdef H5 // '/api' 在上面一条里面跨域那里处理的 options.url= '/api' + options.url // #endif if(options.url !='/user/login'){ const token = uni.getStorageSync('token') if(token){ options.header = { 'authorization':token } } } uni.request({ url: options.url, method: options.method || 'GET', data: options.data || {}, header: options.header , success: (response) => { const res = response // 请求携带authorization的时候就更新authorization的值,没有就不处理 if(res.header.authorization){ uni.setStorageSync('token',res.header.authorization) } if(res.statusCode !== 200){ uni.showToast({ title: res.data.message, }) // 根据实际返回的code处理,我的403和440为需要登录的状态,自动跳转登录页面 if(res.statusCode == 403 || res.statusCode == 440){ uni.removeStorageSync('token') uni.reLaunch({ url: '../login/login' }) } } resolve(res) }, fail: (error) => { uni.showToast({ title: error.message }) reject(error) } }) }) }
H5特殊处理
{
"path": "pages/home/index",
"style": {
"navigationBarTitleText": "首页",
"h5": {
"titleNView": false
}
}
}
padding-top: var(--window-top);
padding-bottom: var(--window-bottom);
uni.navigateTo({ url: '/pages/news/list?item='+encodeURIComponent(JSON.stringify((this.infoData))) }) // 接收页面: onLoad(option){ this.info= JSON.parse(decodeURIComponent(option.item)) console.log(this.info,'000') } // 有时url参数被转义:decodeURIComponent() 进行反转义 function GetRequest() { var url = location.search; //获取url中"?"符后的字串 var params= new Object(); if (url.indexOf("?") != -1) { var str = url.substr(1); strs = str.split("&"); for(var i = 0; i < strs.length; i ++) { params[strs[i].split("=")[0]]= decodeURIComponent(strs[i].split("=")[1]); } } return params; }
tabbar菜单使用了不显示title属性,页面顶部使用了fixed,滚动时状态栏能看到滚动上去的内容处理:给状态栏也设置fixed,并添加个背景色。
<template> <!-- #ifdef APP-PLUS --> <view class="status-bar"></view> <!-- #endif --> <view class="nav">内容</view> </template> <style lang="scss" scoped> .status-bar{ height: var(--status-bar-height); position: fixed; width: 100%; top: 0; z-index: 9; background: #ffffff; } </style>
页面使用拖拽功能,并且拖拽不影响页面其它按钮点击等的操作
uniapp封装好了内置的拖拽组件movable-area**,要不影响页面其他操作可以使用 pointer-events 这个css属性,设置可拖动区域movable-area的pointer-events为none,可移动的视图容器movable-view的pointer-events为auto,既可以实现拖拽功能,又不影响页面其他操作,因为可拖动区域可能会覆盖页面其它内容:
<template> <view class="container"> <button type="primary">点击</button> <movable-area> <movable-view direction="all" >text</movable-view> </movable-area> </view> </template> <style lang="scss" scoped> uni-movable-area{ width: 100vw; height: calc(100vh - var(--status-bar-height)); position: fixed !important; left: 0; top: var(--status-bar-height) ; pointer-events: none; } uni-movable-view{ margin-left: calc(100vw - 380rpx); top: calc(100vh - var(--status-bar-height) - 260rpx); width: 380rpx; height: 260rpx; background: #a4a2a287; pointer-events: auto; } </style>
其它知识累积
import package from 'packageName'
const package = require('packageName')
// npm安装方式引入
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
// 下载安装方式引入
"^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
@tab 在小程序不起作用;
navigator需要在同级目录下跳转,不同级的目录需添加 open-type=“switchTab” 属性;
uniapp微信小程序v-show不能和display:flex用在同一个元素上,flex的层级比v-show的display高,导致v-show无效,可以使用v-if
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。