微信&支付宝小程序 技术要点

826 阅读3分钟

1. 地图导航

注意: (支付宝内部调用高德地图API, 微信内容调用腾讯地图API)

1.1 支付宝

Snipaste_2023-04-28_09-22-58.png 点击导航会引导用户打开高德地图;若未安装高德地图,会引导用户下载高德地图.

  • 代码:
my.openLocation({
  longitude: 121.47061,
  latitude: 31.26460,
  name: '申航大厦',
  address: '上海市静安区中山北路198号(西藏北路地铁站2号口步行250米)',
  success: res => {
    console.log(res);
  },
  fail: res => {
    console.log(res);
  },
});
  • 参数说明

Snipaste_2023-04-28_09-34-34.png

  • 注意:支付宝调用API的经纬度可以自己给上,微信调用API不可以,只能通过wx.getLocation方法返回来精确的经纬度
  • 支付宝文档:点我进入文档

1.2 微信

微信小程序和支付宝小程序大致相同,工作中没有直接使用到微信的地图导航,这里只做文档的说明

  • 代码
wx.getLocation({
 type: 'gcj02', //返回可以用于wx.openLocation的经纬度 (固定写法)
 success (res) {
   const latitude = res.latitude
   const longitude = res.longitude
   wx.openLocation({
     latitude,
     longitude,
     scale: 18
   })
 }
})
  • 阅读示例代码发现 和支付宝相比在外层多调用了一次wx.getLocation方法, 这个方法是为了获取精确的经纬度.
  • 微信文档点我进入文档

2. 微信&支付宝支付

2.1 支付宝支付

  • 支付宝支付是绝对的重头戏。支付宝有两种支付方式,一是直接支付(需要支付押金),二是签署连续包月服务(不需要支付押金)。
  • 先说签署协议
// 代码实现
// 一般会用一个变量来判断是哪种支付方式
if (this.confirmImage) {
    // 公司内部封装的发请求的轮子 可以忽略写法
    const [err, res] = await rentBatteryRequest({
            path: '/alipay/agreement/sign/nofreeze',
            method: 'POST',
            data: {
                    setmealId: this.setmealId
            }
    }, 1)
    console.log('连续包月回调', err, res);
    if (err) return
    await this.aliSesamePay(res.data.signStr) // 返回的res里有调用连续包月需要的 signStr
    return
}
//连续包月 方法 
async aliSesamePay(signStr) {
    my.paySignCenter({ //调起支付宝连续包月页面让用户点击 (下列主要对各种情况进行处理)
        signStr,
        success: async (result) => {
            console.log('连续包月回调', result);
            if (result.resultStatus == 7000) {
                uni.showToast({
                        title: '已完成支付',
                        icon: 'none'
                })
                uni.showLoading({
                        title: '跳转中'
                })
                setTimeout(async (restimeout) => {
                        uni.hideLoading()
                        this.$request.to('../devController/devController', 'r')
                }, 2500)
                return
            }

            if (result.resultStatus == 6001) {
                    uni.showModal({
                            content: '中途取消',
                            showCancel: false
                    })
                    return
            }
            if (result.resultStatus == 7002) {
                uni.showModal({
                    content: '协议签约失败',
                    showCancel: false
                })
                return
            }
        },
        fail: (err) => {
            console.log('连续包月回调', err);
            uni.showToast({
                title: '支付失败,请继续完成支付',
                icon: 'none'
            })
        },
    });
},		
  • 直接支付
    • 看着代码比较长,逻辑大概是这样:
    • 判断用户是否缴纳了押金. 如果是,那么去支付租金;如果否,调用峰云免押接口,如果成功,则冻结押金,如果失败,调用支付押金接口
//支付押金
async goPayCash() {
  //判断是否缴纳押金
  if (this.isPayCash) {
    //已缴纳押金需要支付租金
    await this.goPayCRent(); // 支付租金方法
    return;
  }
  //免押金
  if (this.showView) {
    //调用峰云免押
    const option = {
      path: "/fengyun/preFreeze",
      method: "POST",
      data: {
        setmeal_id: this.setmealId,
      },
    };
    const [err, res] = await myRequest(option, 1);
    if (err) {
      console.log(err, "失败");
      return;
    }
    this.rentOrderId = res.data.rent_order_id;
    my.tradePay({
      orderStr: res.data.orderStr, // 完整的支付参数拼接成的字符串,从服务端获取
      success: async (tradeRes) => {
        if (tradeRes.resultCode == 9000) {
          //押金已经缴纳更改状态
          this.isPayCash = true;
          uni.showModal({
            content:"已缴纳押金,请点击下方支付租金。支付完成后在“我的设备”绑定电池即可使用。",
            showCancel: false,
            success: async () => {
              await this.goPayCRent();
            },
          });
          return;
        }
        if (tradeRes.resultCode == 6001) {
          uni.showToast({
            title: "已取消支付",
            icon: "none",
          });
          return;
        }
        this.showView = false;
      },
      fail: (res) => {
        console.log(res, "失败");
        uni.alert({
          content: JSON.stringify(res),
        });
      },
    });
  }
  //免押失败的情况,支付押金
  if (!this.showView) {
    const [error, success] = await myRequest({
        path: "/alipay/preFreeze",
        method: "POST",
        data: {setmeal_id: this.setmealId,},
      },1)
    this.rentOrderId = success.data.rent_order_id;
    my.tradePay({
      orderStr: success.data.orderStr, // 完整的支付参数拼接成的字符串,从服务端获取
      success: async (payRes) => {
        console.log(payRes, "调起支付宝支付接口后");
        if (payRes.resultCode == 9000) {
          //押金已经缴纳更改状态
          this.isPayCash = true;
          uni.showModal({
            content:"已缴纳押金,请支付租金。支付完成后在“我的设备”绑定电池即可使用。",
            showCancel: false,
            success: async () => {
              await this.goPayCRent(); // 支付租金方法
            },
          });
        }
      },
    });
  }
},
//支付租金
async goPayCRent() {
  ...
  await this.affirmPay();
},
//直接购买  支付租金
async affirmPay() {
  //发起支付
  const [rentErr, rentRes] = await rentBatteryRequest({
      path: "/alipay/rentalPreCreate",
      method: "POST",
      data: {
        rent_order_id: this.rentOrderId,
        months: `${this.productCount}`,
        coupons: this.confirmList,
        discount_id: this.discount_id,
     },
  },1);
  // 这个是调用支付内部的支付接口  我们后端会返回需要的orderInfo参数
  uni.requestPayment({
    provider: "alipay",
    orderInfo: rentRes.data.trade_no,
    success: async (payRes) => {
      if (payRes.resultCode == 9000) {
        uni.showToast({
           title: "已完成支付",
        });
        setTimeout(() => {
          uni.redirectTo({
            url: "../devController/devController",
          });
        }, 1000);
        return;
      }
      if (payRes.resultCode == 6001) {
        uni.showModal({
          content: "支付未完成,请在'我的设备'继续对此订单完成支付",
          showCancel: false,
          success: (res) => {
            uni.redirectTo({
              url: "../devController/devController",
            });
          },
        });
      }
    },
  });
},

2.2 微信支付

  • 微信只有一种支付方式
// 微信端支付 点击确定 
async rentConfirm(){
    const option = {
        path:'/weixin/createOrder',
        method:'POST',
        data: {
            setmeal_id:this.setmealId,
            setmeal_num:`${this.productCount}`,
            isNeedPremium:false,
            coupons:this.confirmList,
            discount_id: this.discount_id
        }
    }
    const [err,res] = await rentBatteryRequest(option,1)
    const result = mypay(res.data).then(result => {
            //处理result,提示,然后跳转
            if(!result) {
                    return
            }
     this.$request.to('../devController/devController','r')
    }).catch(err=>{
            //处理err
            console.error(err.errMsg,'错误')
    })//前提:外部方法是async的
    await mypay(res.data).then((res)=>{
            console.log('支付成功',res)
            uni.showToast({
                    title: '已完成支付,正在跳转',
                    icon: 'none'
            })
            setTimeout(()=>{
                    this.$request.to('../devController/devController','r')
            },3000)
    }).catch(()=>{
            console.log('支付失败')
    })	
},

// 封装的轮子 支付方法(微信支付宝都兼容)

export async function mypay(data) {
    const { timeStamp, nonceStr, signType, paySign, provider, trade_no } = data
    return await new Promise(async (resolve, reject) => {
    console.log('执行支付内部 ,支付宝需要的trade_no = ', trade_no);
    console.log('执行支付内部,微信支付需要的', timeStamp, nonceStr, data.package, signType, paySign);
    await uni.requestPayment({
        // #ifdef MP-ALIPAY
        provider: 'alipay',
        orderInfo: trade_no,
        // #endif
        // #ifdef MP-WEIXIN
        provider: 'wxpay',
        timeStamp,
        nonceStr,
        package: data.package,
        signType,
        paySign,
        // #endif
        success: (res) => {
                console.log('支付成功', res);
                // #ifdef MP-ALIPAY
                if (res.resultCode == 9000) {
                        console.log('支付成功');
                        uni.showToast({
                                title: '支付成功',
                                icon: 'none'
                        })
                        resolve(true)
                        return
                }
                uni.showModal({
                        content: res.memo ? res.memo : '支付未完成',
                        showCancel: false
                })
                reject(false)
                // #endif
                // #ifdef MP-WEIXIN
                uni.showToast({
                        title: '支付成功',
                        icon: 'none'
                })
                resolve(true)
                // #endif
        },
        fail: err => {
                console.log('失败', err);
                uni.showModal({
                        content: '支付未完成',
                        showCancel: false
                })
                reject(false)
        }
    })
    console.log('支付方法 已经走完');
    })
}