Uniapp识别微信二维码到付款

admin 104 0
Uniapp实现微信二维码识别到付款,需完成多环节配置与开发:首先在微信商户平台获取商户号、密钥等参数,并在Uniapp项目中配置微信支付相关插件(如uni.createPlugin)或调用微信JS-SDK;生成收款二维码时,通过后端接口生成包含订单信息的二维码(可使用uni.createQRCode);用户端通过uni.scanCode扫描二维码,获取订单号后调用uni.request发起支付请求,调起微信支付SDK(wx.chooseWXPay);支付完成后,接收微信异步通知并更新订单状态,同时前端处理支付结果回调(成功、失败、取消),实现完整闭环,需注意H5环境需配置授权域名,确保跨平台兼容性。

Uniapp实现微信二维码识别到支付:完整开发指南与应用场景

在移动互联网支付日益普及的今天,二维码支付已成为主流支付方式之一,对于开发者而言,如何在跨平台开发框架Uniapp中实现"识别微信二维码到完成支付"的功能,已成为电商、线下零售、服务类应用的核心需求,本文将从环境准备、代码实现、流程对接到场景应用,详细拆解这一功能的完整开发过程,帮助开发者快速落地并应用到实际项目中。

背景与需求:为什么选择Uniapp实现微信二维码支付?

Uniapp凭借"一次开发,多端发布"的核心优势,已成为跨平台开发的首选框架之一,其开发效率高、学习成本低、生态完善等特点,使其能够同时支持小程序、App、H5等多个平台,而微信支付作为国内使用最广泛的支付方式,其二维码支付场景主要分为两类:

  1. 主动生成支付二维码:商户系统生成包含支付信息的二维码,用户扫描后完成支付(如线下门店收款码、电商订单支付等);
  2. 识别用户付款码:用户出示微信付款码,商户扫码识别并完成扣款(如超市收银台扫码、外卖配送等)。

本文重点讲解第二种场景——即通过Uniapp调用设备摄像头识别微信付款码,并完成支付流程的实现,这是线下收银、O2O服务等高频场景的核心功能,对于提升商户收银效率、优化用户体验具有重要意义。

环境准备:开发前的必要配置

在开始编码前,需完成以下准备工作,确保后续开发顺利进行:

微信支付商户配置

  • 申请微信支付权限:登录微信支付商户平台,完成企业/个体工商户认证,开通"刷卡支付"功能(即付款码支付),注意:个人资质无法开通此功能。

  • 获取关键参数:在"账户中心 > API安全"中获取以下核心参数:

    • 商户号(mch_id):商户的唯一标识
    • API密钥(32位key):用于生成签名的密钥
    • 商户证书:部分接口需要,用于APIv3签名验证
  • 配置授权目录:在"产品中心 > 开发配置"中添加Uniapp应用的授权域名(如https://yourdomain.com),用于后端接口回调和支付结果通知。

Uniapp开发环境

  • 安装HBuilderX:推荐使用官方IDE,支持Uniapp项目创建、调试和发布,也可以使用VS Code配合uni-helper插件进行开发。

  • 配置微信相关能力

    • manifest.json中配置微信小程序/公众号AppID
    • 若涉及App端开发,需在微信开放平台绑定应用
    • 配置摄像头、网络等权限
  • 安装必要插件:如需要更高级的扫码功能,可考虑集成第三方扫码插件。

后端服务准备

微信付款码支付涉及敏感参数(如预支付订单、签名),必须由后端服务生成和处理,建议搭建以下后端接口(Node.js/Java/PHP/Python等):

  • 生成预支付订单:调用微信支付统一下单接口
  • 返回支付参数:返回timeStamp、nonceStr、package、signType、paySign等参数
  • 处理支付结果回调:接收并验证微信支付结果通知
  • 订单状态查询:提供订单状态查询接口

核心实现:从扫码到支付的完整流程

步骤1:调用摄像头识别微信二维码

Uniapp提供了uni.scanCode API,可调用设备摄像头扫描二维码/条形码,并返回扫描结果。

// 在页面中调用扫码功能
uni.scanCode({
  onlyFromCamera: true, // 只能从相机扫码,不允许相册选择
  scanType: ['barCode', 'qrCode'], // 支持条形码和二维码
  autoDecode: true, // 自动解码
  success: (res) => {
    console.log('扫码结果:', res.result);
    // 解析扫码结果,提取付款码信息
    handleWechatPayCode(res.result);
  },
  fail: (err) => {
    console.error('扫码失败:', err);
    if (err.errMsg.includes('permission')) {
      uni.showModal({
        title: '提示',
        content: '请允许使用摄像头权限',
        showCancel: false
      });
    } else {
      uni.showToast({ title: '扫码失败,请重试', icon: 'none' });
    }
  }
});

说明

  • onlyFromCamera: true 确保只能通过摄像头扫码,符合微信付款码的使用场景
  • scanType 包含barCode(条形码)和qrCode(二维码),微信付款码为18位条形码
  • 扫码结果res.result即为微信付款码的18位数字(如2821000420181234567890123456
  • 需要处理权限被拒绝的情况,引导用户开启摄像头权限

步骤2:解析付款码并调用统一下单接口

微信付款码的18位数字包含用户身份信息,需通过微信支付"统一下单"接口转换为支付订单。注意:付款码不能直接用于支付,必须通过后端接口处理

// 处理微信付款码
function handleWechatPayCode(code) {
  // 验证付款码格式
  if (!/^\d{18}$/.test(code)) {
    uni.showToast({ title: '付款码格式错误', icon: 'none' });
    return;
  }
  uni.showLoading({ title: '处理中...' });
  // 调用后端接口,将付款码转换为支付订单
  uni.request({
    url: 'https://yourdomain.com/api/pay/scan-pay',
    method: 'POST',
    header: {
      'content-type': 'application/json',
      'Authorization': 'Bearer ' + uni.getStorageSync('token') // 如果需要登录
    },
    data: {
      pay_code: code, // 微信付款码
      mch_id: 'your_mch_id', // 商户号(可后端配置)
      total_fee: 100, // 支付金额(单位:分,需前端传递)
      out_trade_no: 'ORDER' + Date.now(), // 商户订单号(需唯一)
      device_info: uni.getSystemInfoSync().deviceId, // 设备标识
      spbill_create_ip: uni.getNetworkTypeSync() // 获取网络信息
    },
    success: (res) => {
      uni.hideLoading();
      if (res.data.success) {
        // 调起微信支付
        requestWechatPayment(res.data.payment_params);
      } else {
        uni.showToast({ 
          title: res.data.message || '支付失败', 
          icon: 'none',
          duration: 2000
        });
      }
    },
    fail: (err) => {
      uni.hideLoading();
      uni.showToast({ 
        title: '网络错误,请重试', 
        icon: 'none' 
      });
      console.error('请求失败:', err);
    }
  });
}

步骤3:调起微信支付

后端返回支付参数后,使用uni.requestPayment调起微信支付:

// 调起微信支付
function requestWechatPayment(paymentParams) {
  uni.requestPayment({
    provider: 'wxpay',
    timeStamp: paymentParams.timeStamp,
    nonceStr: paymentParams.nonceStr,
    package: paymentParams.package,
    signType: paymentParams.signType,
    paySign: paymentParams.paySign,
    success: (res) => {
      // 支付成功
      uni.showModal({
        title: '支付成功',
        content: '订单支付完成,是否跳转到订单详情页?',
        success: (modalRes) => {
          if (modalRes.confirm) {
            uni.navigateTo({
              url: '/pages/order/detail?order

标签: #扫码 #支付