支付宝兼容
This commit is contained in:
+386
-6
@@ -36,6 +36,206 @@ const getPermissionText = (key) => {
|
||||
return texts[key] || permissionTexts[DEFAULT_LOCALE][key] || ''
|
||||
}
|
||||
|
||||
// 兼容多端:部分平台(如支付宝小程序)经纬度可能返回字符串
|
||||
// 统一先转为 Number 再做 toFixed,避免 "toFixed is not a function"
|
||||
const toFixedNumber = (value, digits = 5) => {
|
||||
const n = Number(value)
|
||||
if (!Number.isFinite(n)) return null
|
||||
return Number(n.toFixed(digits))
|
||||
}
|
||||
|
||||
// =============================
|
||||
// 支付宝小程序:高德地图 WebService(需要 key + 安全密钥签名)
|
||||
// 说明:支付宝小程序下仅使用高德 key(你提供的 key/secret),避免腾讯地图 key 不可用的问题
|
||||
// =============================
|
||||
// #ifdef MP-ALIPAY
|
||||
const AMAP_KEY = '1c6df40606891377b33576e7876af6ac'
|
||||
const AMAP_SECRET = '00ea790d0b24190174c598199b183750'
|
||||
const AMAP_BASE_URL = 'https://restapi.amap.com/v3/'
|
||||
|
||||
// 轻量 MD5(RFC1321)实现:用于高德 WebService 的 sig 参数
|
||||
// 仅在 MP-ALIPAY 编译进包,避免影响其它端体积
|
||||
function md5(str) {
|
||||
/* eslint-disable */
|
||||
function cmn(q, a, b, x, s, t) {
|
||||
a = add32(add32(a, q), add32(x, t));
|
||||
return add32((a << s) | (a >>> (32 - s)), b);
|
||||
}
|
||||
function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); }
|
||||
function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); }
|
||||
function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); }
|
||||
function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); }
|
||||
function md5cycle(x, k) {
|
||||
let a = x[0], b = x[1], c = x[2], d = x[3];
|
||||
|
||||
a = ff(a, b, c, d, k[0], 7, -680876936);
|
||||
d = ff(d, a, b, c, k[1], 12, -389564586);
|
||||
c = ff(c, d, a, b, k[2], 17, 606105819);
|
||||
b = ff(b, c, d, a, k[3], 22, -1044525330);
|
||||
a = ff(a, b, c, d, k[4], 7, -176418897);
|
||||
d = ff(d, a, b, c, k[5], 12, 1200080426);
|
||||
c = ff(c, d, a, b, k[6], 17, -1473231341);
|
||||
b = ff(b, c, d, a, k[7], 22, -45705983);
|
||||
a = ff(a, b, c, d, k[8], 7, 1770035416);
|
||||
d = ff(d, a, b, c, k[9], 12, -1958414417);
|
||||
c = ff(c, d, a, b, k[10], 17, -42063);
|
||||
b = ff(b, c, d, a, k[11], 22, -1990404162);
|
||||
a = ff(a, b, c, d, k[12], 7, 1804603682);
|
||||
d = ff(d, a, b, c, k[13], 12, -40341101);
|
||||
c = ff(c, d, a, b, k[14], 17, -1502002290);
|
||||
b = ff(b, c, d, a, k[15], 22, 1236535329);
|
||||
|
||||
a = gg(a, b, c, d, k[1], 5, -165796510);
|
||||
d = gg(d, a, b, c, k[6], 9, -1069501632);
|
||||
c = gg(c, d, a, b, k[11], 14, 643717713);
|
||||
b = gg(b, c, d, a, k[0], 20, -373897302);
|
||||
a = gg(a, b, c, d, k[5], 5, -701558691);
|
||||
d = gg(d, a, b, c, k[10], 9, 38016083);
|
||||
c = gg(c, d, a, b, k[15], 14, -660478335);
|
||||
b = gg(b, c, d, a, k[4], 20, -405537848);
|
||||
a = gg(a, b, c, d, k[9], 5, 568446438);
|
||||
d = gg(d, a, b, c, k[14], 9, -1019803690);
|
||||
c = gg(c, d, a, b, k[3], 14, -187363961);
|
||||
b = gg(b, c, d, a, k[8], 20, 1163531501);
|
||||
a = gg(a, b, c, d, k[13], 5, -1444681467);
|
||||
d = gg(d, a, b, c, k[2], 9, -51403784);
|
||||
c = gg(c, d, a, b, k[7], 14, 1735328473);
|
||||
b = gg(b, c, d, a, k[12], 20, -1926607734);
|
||||
|
||||
a = hh(a, b, c, d, k[5], 4, -378558);
|
||||
d = hh(d, a, b, c, k[8], 11, -2022574463);
|
||||
c = hh(c, d, a, b, k[11], 16, 1839030562);
|
||||
b = hh(b, c, d, a, k[14], 23, -35309556);
|
||||
a = hh(a, b, c, d, k[1], 4, -1530992060);
|
||||
d = hh(d, a, b, c, k[4], 11, 1272893353);
|
||||
c = hh(c, d, a, b, k[7], 16, -155497632);
|
||||
b = hh(b, c, d, a, k[10], 23, -1094730640);
|
||||
a = hh(a, b, c, d, k[13], 4, 681279174);
|
||||
d = hh(d, a, b, c, k[0], 11, -358537222);
|
||||
c = hh(c, d, a, b, k[3], 16, -722521979);
|
||||
b = hh(b, c, d, a, k[6], 23, 76029189);
|
||||
a = hh(a, b, c, d, k[9], 4, -640364487);
|
||||
d = hh(d, a, b, c, k[12], 11, -421815835);
|
||||
c = hh(c, d, a, b, k[15], 16, 530742520);
|
||||
b = hh(b, c, d, a, k[2], 23, -995338651);
|
||||
|
||||
a = ii(a, b, c, d, k[0], 6, -198630844);
|
||||
d = ii(d, a, b, c, k[7], 10, 1126891415);
|
||||
c = ii(c, d, a, b, k[14], 15, -1416354905);
|
||||
b = ii(b, c, d, a, k[5], 21, -57434055);
|
||||
a = ii(a, b, c, d, k[12], 6, 1700485571);
|
||||
d = ii(d, a, b, c, k[3], 10, -1894986606);
|
||||
c = ii(c, d, a, b, k[10], 15, -1051523);
|
||||
b = ii(b, c, d, a, k[1], 21, -2054922799);
|
||||
a = ii(a, b, c, d, k[8], 6, 1873313359);
|
||||
d = ii(d, a, b, c, k[15], 10, -30611744);
|
||||
c = ii(c, d, a, b, k[6], 15, -1560198380);
|
||||
b = ii(b, c, d, a, k[13], 21, 1309151649);
|
||||
a = ii(a, b, c, d, k[4], 6, -145523070);
|
||||
d = ii(d, a, b, c, k[11], 10, -1120210379);
|
||||
c = ii(c, d, a, b, k[2], 15, 718787259);
|
||||
b = ii(b, c, d, a, k[9], 21, -343485551);
|
||||
|
||||
x[0] = add32(a, x[0]);
|
||||
x[1] = add32(b, x[1]);
|
||||
x[2] = add32(c, x[2]);
|
||||
x[3] = add32(d, x[3]);
|
||||
}
|
||||
function md5blk(s) {
|
||||
const md5blks = [];
|
||||
for (let i = 0; i < 64; i += 4) {
|
||||
md5blks[i >> 2] = s.charCodeAt(i) +
|
||||
(s.charCodeAt(i + 1) << 8) +
|
||||
(s.charCodeAt(i + 2) << 16) +
|
||||
(s.charCodeAt(i + 3) << 24);
|
||||
}
|
||||
return md5blks;
|
||||
}
|
||||
function md5blk_array(a) {
|
||||
const md5blks = [];
|
||||
for (let i = 0; i < 64; i += 4) {
|
||||
md5blks[i >> 2] = a[i] +
|
||||
(a[i + 1] << 8) +
|
||||
(a[i + 2] << 16) +
|
||||
(a[i + 3] << 24);
|
||||
}
|
||||
return md5blks;
|
||||
}
|
||||
function md51(s) {
|
||||
let n = s.length;
|
||||
let state = [1732584193, -271733879, -1732584194, 271733878];
|
||||
let i;
|
||||
for (i = 64; i <= n; i += 64) {
|
||||
md5cycle(state, md5blk(s.substring(i - 64, i)));
|
||||
}
|
||||
s = s.substring(i - 64);
|
||||
const tail = new Array(64).fill(0);
|
||||
for (i = 0; i < s.length; i++) tail[i] = s.charCodeAt(i);
|
||||
tail[i] = 0x80;
|
||||
if (i > 55) {
|
||||
md5cycle(state, md5blk_array(tail));
|
||||
for (i = 0; i < 64; i++) tail[i] = 0;
|
||||
}
|
||||
const tmp = n * 8;
|
||||
tail[56] = tmp & 0xFF;
|
||||
tail[57] = (tmp >>> 8) & 0xFF;
|
||||
tail[58] = (tmp >>> 16) & 0xFF;
|
||||
tail[59] = (tmp >>> 24) & 0xFF;
|
||||
md5cycle(state, md5blk_array(tail));
|
||||
return state;
|
||||
}
|
||||
function rhex(n) {
|
||||
const s = '0123456789abcdef';
|
||||
let j, out = '';
|
||||
for (j = 0; j < 4; j++) {
|
||||
out += s.charAt((n >> (j * 8 + 4)) & 0x0F) + s.charAt((n >> (j * 8)) & 0x0F);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
function hex(x) { return x.map(rhex).join(''); }
|
||||
function add32(a, b) { return (a + b) & 0xFFFFFFFF; }
|
||||
return hex(md51(str));
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
function buildAmapQuery(params) {
|
||||
const clean = {}
|
||||
Object.keys(params || {}).forEach((k) => {
|
||||
const v = params[k]
|
||||
if (v === undefined || v === null || v === '') return
|
||||
clean[k] = String(v)
|
||||
})
|
||||
// 必须包含 key
|
||||
if (!clean.key) clean.key = AMAP_KEY
|
||||
|
||||
const keys = Object.keys(clean).sort()
|
||||
const query = keys.map((k) => `${k}=${encodeURIComponent(clean[k])}`).join('&')
|
||||
const sig = md5(query + AMAP_SECRET)
|
||||
return `${query}&sig=${sig}`
|
||||
}
|
||||
|
||||
function amapGet(path, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const query = buildAmapQuery(params)
|
||||
uni.request({
|
||||
url: `${AMAP_BASE_URL}${path}?${query}`,
|
||||
method: 'GET',
|
||||
header: { 'content-type': 'application/json' },
|
||||
success: (res) => {
|
||||
const data = res && res.data
|
||||
// 高德 WebService:status '1' 表示成功
|
||||
if (data && String(data.status) === '1') {
|
||||
resolve(data)
|
||||
} else {
|
||||
reject(data || { status: '0', info: '请求失败' })
|
||||
}
|
||||
},
|
||||
fail: (err) => reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 腾讯地图Key
|
||||
const QQMAP_KEY =
|
||||
// #ifdef H5
|
||||
@@ -566,8 +766,15 @@ function getUserLocation() {
|
||||
wx.getLocation({
|
||||
type: 'gcj02',
|
||||
success: (res) => {
|
||||
const longitude = parseFloat(res.longitude.toFixed(5));
|
||||
const latitude = parseFloat(res.latitude.toFixed(5));
|
||||
const longitude = toFixedNumber(res.longitude, 5)
|
||||
const latitude = toFixedNumber(res.latitude, 5)
|
||||
if (longitude === null || latitude === null) {
|
||||
reject({
|
||||
code: 'INVALID_COORD',
|
||||
errMsg: 'invalid longitude/latitude from getLocation'
|
||||
})
|
||||
return
|
||||
}
|
||||
console.log('地址获取成功');
|
||||
resolve({
|
||||
longitude,
|
||||
@@ -612,8 +819,15 @@ function getUserLocation() {
|
||||
wx.getLocation({
|
||||
type: 'gcj02',
|
||||
success: (res) => {
|
||||
const longitude = parseFloat(res.longitude.toFixed(5));
|
||||
const latitude = parseFloat(res.latitude.toFixed(5));
|
||||
const longitude = toFixedNumber(res.longitude, 5)
|
||||
const latitude = toFixedNumber(res.latitude, 5)
|
||||
if (longitude === null || latitude === null) {
|
||||
reject({
|
||||
code: 'INVALID_COORD',
|
||||
errMsg: 'invalid longitude/latitude from getLocation'
|
||||
})
|
||||
return
|
||||
}
|
||||
console.log('地址获取成功');
|
||||
resolve({
|
||||
longitude,
|
||||
@@ -635,8 +849,15 @@ function getUserLocation() {
|
||||
uni.getLocation({
|
||||
type: 'gcj02',
|
||||
success: (res) => {
|
||||
const longitude = parseFloat(res.longitude.toFixed(5));
|
||||
const latitude = parseFloat(res.latitude.toFixed(5));
|
||||
const longitude = toFixedNumber(res.longitude, 5)
|
||||
const latitude = toFixedNumber(res.latitude, 5)
|
||||
if (longitude === null || latitude === null) {
|
||||
reject({
|
||||
code: 'INVALID_COORD',
|
||||
errMsg: 'invalid longitude/latitude from getLocation'
|
||||
})
|
||||
return
|
||||
}
|
||||
console.log('地址获取成功');
|
||||
resolve({
|
||||
longitude,
|
||||
@@ -665,6 +886,41 @@ function getUserLocation() {
|
||||
// 逆地理编码 - 根据经纬度获取地址信息
|
||||
function getRegeo(longitude, latitude) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef MP-ALIPAY
|
||||
// 支付宝小程序:高德逆地理编码
|
||||
const lng = toFixedNumber(longitude, 6)
|
||||
const lat = toFixedNumber(latitude, 6)
|
||||
if (lng === null || lat === null) {
|
||||
reject({ success: false, message: '无效经纬度' })
|
||||
return
|
||||
}
|
||||
amapGet('geocode/regeo', {
|
||||
location: `${lng},${lat}`,
|
||||
radius: 1000,
|
||||
extensions: 'base'
|
||||
}).then((data) => {
|
||||
const regeocode = data.regeocode || {}
|
||||
const ac = regeocode.addressComponent || {}
|
||||
resolve({
|
||||
success: true,
|
||||
data: {
|
||||
formatted_address: regeocode.formatted_address || '',
|
||||
addressComponent: {
|
||||
city: Array.isArray(ac.city) ? '' : (ac.city || ''),
|
||||
district: ac.district || '',
|
||||
province: ac.province || '',
|
||||
street: (ac.streetNumber && ac.streetNumber.street) || '',
|
||||
street_number: (ac.streetNumber && ac.streetNumber.number) || ''
|
||||
}
|
||||
}
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.error('支付宝-高德逆地理编码失败:', err)
|
||||
reject({ success: false, message: err.info || err.message || '逆地理编码失败' })
|
||||
})
|
||||
return
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
// H5环境:使用JSONP方式调用腾讯地图API,避免跨域问题
|
||||
const callbackName = `qqmap_geocoder_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
@@ -756,6 +1012,50 @@ function getRegeo(longitude, latitude) {
|
||||
// 搜索周边POI
|
||||
function getPoiAround(longitude, latitude, keyword = '', radius = 1000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef MP-ALIPAY
|
||||
// 支付宝小程序:高德周边检索
|
||||
const lng = toFixedNumber(longitude, 6)
|
||||
const lat = toFixedNumber(latitude, 6)
|
||||
if (lng === null || lat === null) {
|
||||
reject({ success: false, message: '无效经纬度' })
|
||||
return
|
||||
}
|
||||
amapGet('place/around', {
|
||||
location: `${lng},${lat}`,
|
||||
keywords: keyword || '',
|
||||
radius: radius || 1000,
|
||||
sortrule: 'distance',
|
||||
offset: 10,
|
||||
page: 1,
|
||||
extensions: 'base'
|
||||
}).then((data) => {
|
||||
const pois = Array.isArray(data.pois) ? data.pois : []
|
||||
const list = pois.map((p) => {
|
||||
const loc = (p.location || '').split(',')
|
||||
const plng = toFixedNumber(loc[0], 6)
|
||||
const plat = toFixedNumber(loc[1], 6)
|
||||
return {
|
||||
id: p.id || null,
|
||||
title: p.name || null,
|
||||
latitude: plat,
|
||||
longitude: plng,
|
||||
address: p.address || null,
|
||||
category: p.type || null,
|
||||
tel: p.tel || null,
|
||||
adcode: p.adcode || null,
|
||||
city: p.cityname || null,
|
||||
district: p.adname || null,
|
||||
province: p.pname || null
|
||||
}
|
||||
})
|
||||
resolve({ success: true, data: list })
|
||||
}).catch((err) => {
|
||||
console.error('支付宝-高德搜索POI失败:', err)
|
||||
reject({ success: false, message: err.info || err.message || '搜索POI失败' })
|
||||
})
|
||||
return
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
// H5环境:使用JSONP方式调用腾讯地图API
|
||||
const callbackName = `qqmap_search_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
@@ -843,6 +1143,48 @@ function getPoiAround(longitude, latitude, keyword = '', radius = 1000) {
|
||||
// 计算距离(异步)
|
||||
function calculateDistance(from, to) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef MP-ALIPAY
|
||||
// 支付宝小程序:高德距离计算(支持多个目的地)
|
||||
if (!from || !to) {
|
||||
reject({ success: false, message: '参数缺失' })
|
||||
return
|
||||
}
|
||||
const fromLng = toFixedNumber((from && (from.longitude !== undefined ? from.longitude : from.lng)), 6)
|
||||
const fromLat = toFixedNumber((from && (from.latitude !== undefined ? from.latitude : from.lat)), 6)
|
||||
if (fromLng === null || fromLat === null) {
|
||||
reject({ success: false, message: '无效起点坐标' })
|
||||
return
|
||||
}
|
||||
|
||||
const toArr = Array.isArray(to) ? to : [to]
|
||||
const origins = toArr.map((p) => {
|
||||
const lng = toFixedNumber((p && (p.longitude !== undefined ? p.longitude : p.lng)), 6)
|
||||
const lat = toFixedNumber((p && (p.latitude !== undefined ? p.latitude : p.lat)), 6)
|
||||
return (lng === null || lat === null) ? null : `${lng},${lat}`
|
||||
}).filter(Boolean)
|
||||
|
||||
if (!origins.length) {
|
||||
reject({ success: false, message: '无效终点坐标' })
|
||||
return
|
||||
}
|
||||
|
||||
// 高德接口:origins(多个) + destination(单个)
|
||||
amapGet('distance', {
|
||||
origins: origins.join('|'),
|
||||
destination: `${fromLng},${fromLat}`,
|
||||
type: 0 // 0:驾车距离;步行/骑行需要其它接口,这里保持与原来“直线/近似”用途一致
|
||||
}).then((data) => {
|
||||
const results = Array.isArray(data.results) ? data.results : []
|
||||
const distances = results.map((r) => Number(r.distance)).filter((n) => Number.isFinite(n))
|
||||
// 保持与原实现一致:始终返回数组(即使只传了一个目的地)
|
||||
resolve({ success: true, data: distances })
|
||||
}).catch((err) => {
|
||||
console.error('支付宝-高德计算距离失败:', err)
|
||||
reject({ success: false, message: err.info || err.message || '计算距离失败' })
|
||||
})
|
||||
return
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
// H5环境:使用JSONP方式调用腾讯地图API
|
||||
const callbackName = `qqmap_distance_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
@@ -935,6 +1277,44 @@ function calculateDistanceSync(lat1, lng1, lat2, lng2) {
|
||||
// 关键词提示
|
||||
function getSuggestion(keyword, region = '全国') {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef MP-ALIPAY
|
||||
// 支付宝小程序:高德输入提示
|
||||
if (!keyword) {
|
||||
resolve({ success: true, data: [] })
|
||||
return
|
||||
}
|
||||
amapGet('assistant/inputtips', {
|
||||
keywords: keyword,
|
||||
city: region && region !== '全国' ? region : '',
|
||||
citylimit: region && region !== '全国' ? 1 : 0
|
||||
}).then((data) => {
|
||||
const tips = Array.isArray(data.tips) ? data.tips : []
|
||||
const list = tips.map((t) => {
|
||||
const loc = (t.location || '').split(',')
|
||||
const lng = toFixedNumber(loc[0], 6)
|
||||
const lat = toFixedNumber(loc[1], 6)
|
||||
return {
|
||||
adcode: t.adcode || null,
|
||||
address: t.address || null,
|
||||
category: t.type || null,
|
||||
city: t.cityname || null,
|
||||
district: t.district || null,
|
||||
id: t.id || null,
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
province: t.pname || null,
|
||||
title: t.name || null,
|
||||
type: t.type || null
|
||||
}
|
||||
})
|
||||
resolve({ success: true, data: list })
|
||||
}).catch((err) => {
|
||||
console.error('支付宝-高德关键词提示失败:', err)
|
||||
reject({ success: false, message: err.info || err.message || '关键词提示失败' })
|
||||
})
|
||||
return
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
// H5环境:使用JSONP方式调用腾讯地图API
|
||||
const callbackName = `qqmap_suggestion_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
|
||||
Reference in New Issue
Block a user