車后市APP:Cordova項(xiàng)目轉(zhuǎn)換并兼容公眾號(hào)總結(jié)
2022年5月12日 7903 5Cordova與React Native一樣,是目前主流的Hybrid模式APP開發(fā)框架,而相對(duì)于H5代碼的銜接,Cordova在這方面的兼容性更好一些,因?yàn)樗鼪]有定義具體的語法,將具體的業(yè)務(wù)邏輯留給ionic或者AngularJS等單頁應(yīng)用的開發(fā)框架去實(shí)現(xiàn),自己負(fù)責(zé)與原生設(shè)備接口交互,包括相機(jī)(拍照)、相冊(cè)、GPS定位、掃碼、文件管理、支付等等。作為一款車后市APP,酷愛洗車APP是基于延譽(yù)寶會(huì)員管理系統(tǒng)深度定制合作的物聯(lián)網(wǎng)項(xiàng)目,隨著業(yè)務(wù)的不斷擴(kuò)展,APP端的已經(jīng)滿足自助洗車客戶對(duì)移動(dòng)端應(yīng)用入口的需求,因此,開發(fā)小程序和公眾號(hào)成為運(yùn)營(yíng)推廣的必然要求。但是考慮開發(fā)成本,特別是后期的運(yùn)營(yíng)維護(hù),如果兩套代碼,必然增加后續(xù)維護(hù)的負(fù)擔(dān),造成系統(tǒng)升級(jí)的項(xiàng)目投入增加,因此,最好的解決方案,就是實(shí)現(xiàn)Cordova項(xiàng)目可以兼容微信公眾號(hào),如此這樣,iPhone、安卓和公眾號(hào)三個(gè)入口使用一份代碼,便于BUG修復(fù),并提高系統(tǒng)運(yùn)維的效率,從而在服務(wù)器端大數(shù)據(jù)運(yùn)維投入不變的前提下,減輕客戶端的技術(shù)投入壓力。
Cordova與React Native一樣,是目前主流的Hybrid模式APP開發(fā)框架,而相對(duì)于H5代碼的銜接,Cordova在這方面的兼容性更好一些,因?yàn)樗鼪]有定義具體的語法,將具體的業(yè)務(wù)邏輯留給ionic或者AngularJS等單頁應(yīng)用的開發(fā)框架去實(shí)現(xiàn),自己負(fù)責(zé)與原生設(shè)備接口交互,包括相機(jī)(拍照)、相冊(cè)、GPS定位、掃碼、文件管理、支付等等。
作為一款車后市APP,酷愛洗車APP是基于延譽(yù)寶會(huì)員管理系統(tǒng)深度定制合作的物聯(lián)網(wǎng)項(xiàng)目,隨著業(yè)務(wù)的不斷擴(kuò)展,APP端的已經(jīng)滿足自助洗車客戶對(duì)移動(dòng)端應(yīng)用入口的需求,因此,開發(fā)小程序和公眾號(hào)成為運(yùn)營(yíng)推廣的必然要求。但是考慮開發(fā)成本,特別是后期的運(yùn)營(yíng)維護(hù),如果兩套代碼,必然增加后續(xù)維護(hù)的負(fù)擔(dān),造成系統(tǒng)升級(jí)的項(xiàng)目投入增加,因此,最好的解決方案,就是實(shí)現(xiàn)Cordova項(xiàng)目可以兼容微信公眾號(hào),如此這樣,iPhone、安卓和公眾號(hào)三個(gè)入口使用一份代碼,便于BUG修復(fù),并提高系統(tǒng)運(yùn)維的效率,從而在服務(wù)器端大數(shù)據(jù)運(yùn)維投入不變的前提下,減輕客戶端的技術(shù)投入壓力。
實(shí)現(xiàn)將Cordova APP轉(zhuǎn)公眾號(hào)項(xiàng)目,主要解決以下幾個(gè)接口的兼容:
1、微信粉絲身份的自動(dòng)獲取。
這個(gè)步驟在原生APP開發(fā)中是沒有的,也不需要的,因此需要服務(wù)器接口支持。對(duì)應(yīng)的AngularJS的代碼如下:
if(is_in_weixin_browser && !is_in_wxa_browser){
//公眾號(hào)更換頭像
console.log(is_in_weixin_browser);
console.log(is_in_wxa_browser);$scope.get_weixin_jssdk_params();
對(duì)應(yīng)的get_weixin_jssdk_params函數(shù)處理過程如下,除了獲取openid之外,還需要控制分享轉(zhuǎn)發(fā)的圖片、文字和鏈接。
//請(qǐng)求接口,獲取微信JSSDK參數(shù)
$scope.get_weixin_jssdk_params = function () {var current_url = document.location.href;
$http({
method: ‘post’,//請(qǐng)求方式
url: http_server + “/index.php?g=Yanyubao&m=Kuaicar&a=weixin_jssdk_params”,//請(qǐng)求地址
data: {‘sellerid’: 123, ‘userid’: 456, ‘checkstr’: 789, ‘current_url’:current_url}//請(qǐng)求參數(shù),如果使用JSON格式的對(duì)象則可為 data: JSON.stringify(obj),
//timeout: 8000//請(qǐng)求等待時(shí)間
})
.success(function (data) {
// console.log(1111111);
// console.log(data);
// console.log(1111111);
if (data.code == ‘1’) {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();
}wx.config({
debug: false, /* 開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來,若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會(huì)通過log打出,僅在pc端時(shí)才會(huì)打印。*/
appId: data.signPackage[‘appId’], /* 必填,公眾號(hào)的唯一標(biāo)識(shí)*/
timestamp: data.signPackage[‘timestamp’], /* 必填,生成簽名的時(shí)間戳*/
nonceStr: data.signPackage[‘nonceStr’], /* 必填,生成簽名的隨機(jī)串*/
signature: data.signPackage[‘signature’],/* 必填,簽名,見附錄1*/
jsApiList: [
‘checkJsApi’,
‘onMenuShareTimeline’,
‘onMenuShareAppMessage’,
‘onMenuShareQQ’,
‘onMenuShareWeibo’,
‘hideMenuItems’,
‘showMenuItems’,
‘hideAllNonBaseMenuItem’,
‘showAllNonBaseMenuItem’,
‘translateVoice’,
‘startRecord’,
‘stopRecord’,
‘onRecordEnd’,
‘playVoice’,
‘pauseVoice’,
‘stopVoice’,
‘uploadVoice’,
‘downloadVoice’,
‘chooseImage’,
‘previewImage’,
‘uploadImage’,
‘downloadImage’,
‘getNetworkType’,
‘openLocation’,
‘getLocation’,
‘hideOptionMenu’,
‘showOptionMenu’,
‘closeWindow’,
‘scanQRCode’,
‘chooseWXPay’,
‘openProductSpecificView’,
‘addCard’,
‘chooseCard’,
‘openCard’
] /* 必填,需要使用的JS接口列表,所有JS接口列表見附錄2*/
});}
})
.error(function (data, header, config, status) {//處理響應(yīng)失敗
// 當(dāng)ajax請(qǐng)求出現(xiàn)錯(cuò)誤時(shí),顯示一個(gè)提示信息
$ionicLoading.show({
animation: ‘fade-in’,
showBackdrop: false,
template: “網(wǎng)絡(luò)延遲,請(qǐng)重新嘗試”,
duration: 3000
});
});}
//請(qǐng)求接口,獲取微信JSSDK參數(shù)==end===
2、會(huì)員頭像的讀取和上傳。
這個(gè)地方對(duì)比兩個(gè)代碼就明白了,不是使用File控件,而是調(diào)用公眾號(hào)的文件讀取和上傳接口,調(diào)用這些接口的好處在于可以自動(dòng)壓縮上傳的圖片。
Cordova下的代碼:
buttonClicked: function (index) {
if (index == 0) {
//type = ‘camera’;
var srcType = Camera.PictureSourceType.CAMERA;
} else if (index == 1) {
//type = ‘gallery’;
var srcType = Camera.PictureSourceType.SAVEDPHOTOALBUM;
}
var options = setOptions(srcType);
//var func = createNewFileEntry;options.targetHeight = 1200;
options.targetWidth = 1200;
navigator.camera.getPicture(function cameraSuccess(imageUri) {
console.log(imageUri);
$scope.temp_image = imageUri;
$scope.head_logo = imageUri;
//$scope.uoload_img();//彈出緩沖提示
$scope.showLoadingToast();
//這里使用定時(shí)器是為了緩存一下加載過程,防止加載過快
$timeout(function () {
//停止緩沖提示
$scope.hideLoadingToast();
}, 1000);
}, function cameraError(error) {
console.debug(“Unable to obtain picture: ” + error, “app”);//顯示等待
//彈出緩沖提示
$scope.showLoadingToast();
//這里使用定時(shí)器是為了緩存一下加載過程,防止加載過快
$timeout(function () {
//停止緩沖提示
$scope.hideLoadingToast();
}, 2500);
}, options);}
});
$timeout(function () {
hideSheet();
}, 3000);
公眾號(hào)中的代碼:
$scope.choosePicMenu = function () {
wx.chooseImage({
count: 1, // 默認(rèn)9
sizeType: [‘original’, ‘compressed’], // 可以指定是原圖還是壓縮圖,默認(rèn)二者都有
sourceType: [‘album’, ‘camera’], // 可以指定來源是相冊(cè)還是相機(jī),默認(rèn)二者都有
success: function (res) {
var localIds = res.localIds; // 返回選定照片的本地ID列表,localId可以作為img標(biāo)簽的src屬性顯示圖片wx.uploadImage({
localId: localIds[0], // 需要上傳的圖片的本地ID,由chooseImage接口獲得
isShowProgressTips: 1, // 默認(rèn)為1,顯示進(jìn)度提示
success: function (res) {
var serverId = res.serverId; // 返回圖片的服務(wù)器端ID$http({
method: ‘post’,//請(qǐng)求方式
url: http_server + “/index.php?g=Yanyubao&m=Kuaicar&a=get_image_url_by_weixin_media_id”,//請(qǐng)求地址
data: {‘serverId’: serverId}//請(qǐng)求參數(shù),如果使用JSON格式的對(duì)象則可為 data: JSON.stringify(obj),
//timeout: 8000//請(qǐng)求等待時(shí)間
})
.success(function (data) {
if (data.code == ‘1’) {
console.log(2222222222);
console.log(data);
console.log(2222222222);
$scope.head_logo = data.url2;//$ionicLoading.hide();
}
})
.error(function (data, header, config, status) {
//處理響應(yīng)失敗
// 當(dāng)ajax請(qǐng)求出現(xiàn)錯(cuò)誤時(shí),顯示一個(gè)提示信息
$ionicLoading.show({
animation: ‘fade-in’,
showBackdrop: false,
template: “網(wǎng)絡(luò)延遲,請(qǐng)重新嘗試”,
duration: 3000
});
})}
});}
});}
3、用戶GPS坐標(biāo)(經(jīng)緯度)的讀取。
由于國(guó)內(nèi)的地圖中GPS坐標(biāo)是加密的,因此獲取微信信息,調(diào)用百度地圖的接口是穩(wěn)定的。
///讀取gps經(jīng)緯度信息
$scope.getGeolocation = function () {if(is_in_cordova_browser){
// 使用百度地圖插件進(jìn)行定位
baidumap_location.getCurrentPosition(function (result) {
console.log(JSON.stringify(result, null, 4));
//alert(JSON.stringify(result, null, 4));$scope.latitude = result.latitude;//緯度
$scope.longitude = result.longitude;//經(jīng)度
console.log(‘緯度:’ + $scope.latitude + ‘經(jīng)度:’ + $scope.longitude);$scope.get_machine_list();
}, function (error) {
console.log(‘調(diào)用百度地圖插件失敗:’+error);
alert(‘調(diào)用地圖失敗:’+error);
});}else if(is_in_weixin_browser && !is_in_wxa_browser ){
navigator.geolocation.getCurrentPosition(updataPosiyion);}
}function updataPosiyion(position){
var latitudeP = position.coords.latitude;
var longitudeP = position.coords.longitude;var point = new BMap.Point(longitudeP,latitudeP);
$scope.latitude = point.lat;//緯度
$scope.longitude = point.lng;//經(jīng)度
console.log(‘緯度:’ + $scope.latitude + ‘經(jīng)度:’ + $scope.longitude);$scope.get_machine_list();
}
});
4、二維碼掃描控件的調(diào)用。
使用公眾號(hào)的二維碼掃描接口,其實(shí)比使用Cordova插件的二維碼掃碼功能簡(jiǎn)單多了,而且用戶體驗(yàn)更好。
if(is_in_cordova_browser){
/////調(diào)掃碼插件
cordova.plugins.barcodeScanner.scan(
function (result) {
var machine_url = result.text;
console.log(‘洗車機(jī)機(jī)器url’ + machine_url);
var machineurl=encodeURI(machine_url);$scope.check_machine(machineurl);
},
function (error) {
console.log(“Scanning failed: ” + error);
}
);
}else if(is_in_weixin_browser && !is_in_wxa_browser){
//alert(11111111);
wx.scanQRCode({needResult: 1, // 默認(rèn)為0,掃描結(jié)果由微信處理,1則直接返回掃描結(jié)果,
scanType: [“qrCode”,”barCode”], // 可以指定掃二維碼還是一維碼,默認(rèn)二者都有
success: function (res) {
var result = res.resultStr; // 當(dāng)needResult 為 1 時(shí),掃碼返回的結(jié)果
//console.log(‘掃碼結(jié)果:’+result);
//alert(result);
var machineurl=encodeURI(result);$scope.check_machine(machineurl);
}
});
}
5、微信支付收款接口的調(diào)用。
這里調(diào)用的肯定是微信的公眾號(hào),而不是H5收款接口,首先參考第一點(diǎn),獲取當(dāng)前的用戶的openid,在調(diào)用微信支付APP接口的地方做判斷,調(diào)用對(duì)應(yīng)的公眾號(hào)內(nèi)支付接口。
首先需要隱藏支付寶收款,畢竟是在公眾號(hào)里面。
//在微信環(huán)境隱藏支付寶支付
$scope.is_in_weixin_browser = is_in_weixin_browser;
原生微信支付接口調(diào)用:
//微信APP支付
$scope.wechat_pay = function(payInfo,orderid,payment_type){
// console.table(payInfo);
//payInfo = JSON.parse(payInfo);
//console.log(payInfo.sub_mch_id);// alert(JSON.stringify(payInfo));
var params = {
partnerid: payInfo.partnerid, // merchant id
prepayid: payInfo.prepayid, // prepay id
noncestr: payInfo.noncestr, // nonce
timestamp: payInfo.timestamp, // timestamp
sign: payInfo.sign, // signed string
};
console.log(params.partnerid);
console.log(params.prepayid);
console.log(params.noncestr);
console.log(params.timestamp);
console.log(params.sign);// alert(JSON.stringify(params));
Wechat.sendPaymentRequest(params, function () {
// alert(“Success”);
$scope.order_buy_result(orderid,payment_type);
// alert(“回調(diào)成功”);
var alertPopup = $ionicPopup.alert({
title: ‘友情提示’,
template: “<p style=’text-align: center’>支付完成</p>”,
okText: ‘確定’, // String (默認(rèn): ‘OK’)。OK按鈕的文字。
okType: ‘button-assertive’, // String (默認(rèn): ‘button-positive’)。OK按鈕的類型。
});
alertPopup.then(function(res) {
//跳轉(zhuǎn)到支付成功頁面$state.go(“pay_success”, {‘orderid’:orderid}, {reload:true});
return false;
});}, function (reason) {
//alert(“reason=>”+reason);var alertPopup = $ionicPopup.alert({
title: ‘友情提示’,
template: “<p style=’text-align: center’>”+reason+”</p>”,
okText: ‘確定’, // String (默認(rèn): ‘OK’)。OK按鈕的文字。
okType: ‘button-assertive’, // String (默認(rèn): ‘button-positive’)。OK按鈕的類型。
});console.log(“Failed: ” + reason);
});}
公眾號(hào)支付的代碼:
//微信公眾號(hào)支付
$scope.wechat_pay_jsapi = function(payInfo,openid){
// console.log(2233244);
// console.log(payInfo);
// console.log(2233244);
//payInfo = JSON.parse(payInfo);
//console.log(payInfo.sub_mch_id);//var prepayid = payInfo.prepay_id; // prepay id
//var appid = payInfo.appid; //appid
var parameters = encodeURIComponent(payInfo.parameters); //appid//alert( weixin_payment_failure);
var jump_to_url = encodeURIComponent(weixin_payment_success);
var jump_url_failure = encodeURIComponent(weixin_payment_failure);var pay_url = weixin_payment_dir;
pay_url += ‘?parameters=’+ parameters + ‘&jump_to_url=’ + jump_to_url + ‘&jump_url_failure=’ + jump_url_failure ;
// console.log(123);
// console.log(pay_url);
// console.log(123);
//alert(pay_url);
window.location= pay_url;}
公眾號(hào)收款首先要獲取當(dāng)前粉絲的openid,對(duì)應(yīng)的接口調(diào)用代碼:
//
$scope.check_openid_cache = function (){
var o_weixin_openid = localStorage.getItem(“o_weixin_openid”);
//alert(‘o_weixin_openid:’+o_weixin_openid);
//alert(encodeURIComponent(document.location.href));if (!o_weixin_openid ) {
//alert(‘o_weixin_openid == undefined’);
location.href = http_server + “/index.php?g=Yanyubao&m=ShopApp&a=weixin_oauthor&sellerid=”+ sellerid +”&returl=”+encodeURIComponent(document.location.href);
return;
}
//alert(‘222222’);return o_weixin_openid;
}$scope.get_openid_from_server = function () {
//檢查是否要從服務(wù)器獲取openid
var weixin_openid_token = $location.search().weixin_openid_token;//alert(‘weixin_openid_token:’+weixin_openid_token);
//alert(window.location.href);
//alert(“get from url, openid token:”+weixin_openid_token);if (weixin_openid_token) {
alert(‘ready to get weixin_get_openid’);//同步ajax請(qǐng)求
$http({method: ‘post’,//請(qǐng)求方式
url:http_server + “/index.php?g=Yanyubao&m=ShopApp&a=weixin_get_openid”,//請(qǐng)求地址data: {“weixin_openid_token” : weixin_openid_token} //請(qǐng)求參數(shù),如果使用JSON格式的對(duì)象則可為 data: JSON.stringify(obj),
})
.success(function (res) {
//alert(‘success:’+res);window.localStorage.setItem(“o_weixin_openid”, res.openid);
})
.error(function (res, header, config, status) {//處理響應(yīng)失敗
// 當(dāng)ajax請(qǐng)求出現(xiàn)錯(cuò)誤時(shí),顯示一個(gè)提示信息
$ionicLoading.show({
animation: ‘fade-in’,
showBackdrop: false,
template: “網(wǎng)絡(luò)延遲,請(qǐng)重新嘗試”,
duration: 3000
});
});}
else{
console.log(‘$scope.check_openid_cache()’);
//alert(2888888);
$scope.check_openid_cache();}
}
通過對(duì)以上接口的兼容性改造,Cordova項(xiàng)目實(shí)現(xiàn)了對(duì)微信公眾號(hào)的兼容。最后再討論一個(gè)基礎(chǔ)的問題,即如何判斷公眾號(hào)環(huán)境還是Cordova環(huán)境。這個(gè)問題的解決方案來自對(duì)User Agent的判斷。Cordova環(huán)境的UA可以自己定義,這個(gè)可以在config.xml中指定,根據(jù)這個(gè)字符串可以判斷。在微信瀏覽器中,UA是帶有字符串“MicroMessenger”的,但是需要同時(shí)判斷是否在小程序的瀏覽器中,需要引用:
https://res.wx.qq.com/open/js/jweixin-1.3.2.js
這個(gè)判斷在小程序的官方文檔中也有說明,因?yàn)樾〕绦驗(yàn)g覽器中是不能調(diào)用公眾號(hào)的接口。
最近更新
- 物聯(lián)網(wǎng)的底層通信與應(yīng)用案例深度剖析
- 小程序和APP在線開發(fā)制作說明:超過100個(gè)設(shè)置選項(xiàng)自動(dòng)生成企業(yè)官網(wǎng)/商城網(wǎng)站/拼團(tuán)秒殺分銷/智能建站2.0
- 網(wǎng)站轉(zhuǎn)APP,WordPress轉(zhuǎn)小程序,安卓蘋果微信百度支付寶抖音全平臺(tái)小程序
- 延譽(yù)小工單軟件產(chǎn)品介紹和使用幫助
- 企業(yè)網(wǎng)站與商城 APP 開發(fā):AI 助力有限,程序員地位難撼
- 電腦端登錄忘記密碼怎么辦?
- 國(guó)際版進(jìn)銷存軟件:不容忽視的多重弊端
- 獨(dú)立站熱度不減,谷歌百度排名依然堅(jiān)挺
- 獨(dú)立站技術(shù)方案:WordPress三合一企業(yè)網(wǎng)站建設(shè)
- 商城APP和商城小程序運(yùn)營(yíng)推廣:智能建站2.0幫助手冊(cè)
猜你喜歡
- 掃描普通二維碼如何打開小程序?一定要小程序碼嗎?
- 浙江攀斯?fàn)柾赓Q(mào)采購(gòu)管理系統(tǒng)
- APP備案政策已出,企業(yè)及時(shí)申請(qǐng),個(gè)人勝算不大
- 延譽(yù)微餐飲:吸粉神器
- 上海延譽(yù)微信營(yíng)銷平臺(tái)“微讀客”上線
- 上海延譽(yù):軟件項(xiàng)目是怎么做出來的?
- 醒醒吧,小程序替代不了APP!
- 學(xué)而思培優(yōu):學(xué)而時(shí)習(xí)之,不亦樂乎!
- 會(huì)員營(yíng)銷運(yùn)營(yíng)方案1/9:新會(huì)員營(yíng)銷
- 搶占元宇宙新賽道:NFT卡包卡牌運(yùn)營(yíng)方案