uni-app 支付集成

核心知识点

1. 支付基础

  • 支付概念:在线支付、移动支付、跨境支付等
  • 支付流程:下单、支付、回调、查询等
  • 支付安全:签名验证、加密传输、防篡改等
  • 支付状态:待支付、支付中、支付成功、支付失败等

2. 支付方式

  • 微信支付:APP支付、小程序支付、H5支付等
  • 支付宝支付:APP支付、小程序支付、H5支付等
  • 银联支付:云闪付、银联在线支付等
  • 其他支付:百度支付、京东支付、 PayPal 等
  • 聚合支付:集成多种支付方式

3. 支付API

  • **uni.requestPayment()**:uni-app 统一支付接口
  • 支付参数:不同支付方式的参数配置
  • 支付回调:处理支付结果
  • 支付查询:查询支付状态
  • 退款接口:处理退款请求

4. 支付配置

  • 商户资质:申请支付商户号
  • APPID配置:绑定应用
  • 密钥管理:API密钥、证书等
  • 支付授权:获取支付权限
  • 平台配置:不同平台的支付配置

5. 支付流程

  • 前端流程:发起支付请求、调用支付API、处理支付结果
  • 后端流程:生成订单、签名验证、调用支付接口、处理回调
  • 异常处理:支付超时、支付失败、重复支付等
  • 订单管理:订单状态更新、对账等

6. 支付安全

  • 签名验证:防止请求被篡改
  • 加密传输:保护敏感信息
  • 防重放攻击:防止重复支付
  • 数据校验:验证支付结果的真实性
  • 安全存储:保护商户密钥和证书

7. 跨平台支付处理

  • 平台差异:不同平台的支付方式支持
  • 条件编译:为不同平台提供不同的支付方案
  • 原生能力:使用平台原生的支付能力
  • 第三方服务:使用第三方支付服务

8. 支付优化

  • 支付体验:简化支付流程,减少支付步骤
  • 支付成功率:优化支付参数,减少支付失败
  • 支付速度:提高支付响应速度
  • 错误处理:友好的错误提示和处理

实用案例

案例 1:电商应用支付功能

需求分析

  • 支持微信支付和支付宝支付
  • 实现商品购买支付流程
  • 处理支付结果和订单状态
  • 支持支付记录查询

实现方案

  1. 支付集成
    <template>
      <view class="payment-app">
        <view class="order-info">
          <text class="order-title">订单信息</text>
          <text class="order-price">总价:¥{{ orderPrice }}</text>
          <text class="order-id">订单号:{{ orderId }}</text>
        </view>
        
        <view class="payment-methods">
          <text class="method-title">选择支付方式</text>
          <view 
            v-for="(method, index) in paymentMethods" 
            :key="index"
            @click="selectPaymentMethod(method)"
            :class="{ active: selectedMethod === method.id }"
            class="payment-method"
          >
            <view class="method-icon">{{ method.icon }}</view>
            <view class="method-info">
              <text class="method-name">{{ method.name }}</text>
              <text class="method-desc">{{ method.description }}</text>
            </view>
            <view class="method-check" v-if="selectedMethod === method.id">✓</view>
          </view>
        </view>
        
        <button @click="submitPayment" type="primary" class="pay-btn">
          确认支付 ¥{{ orderPrice }}
        </button>
      </view>
    </template>
    
    <script>
    export default {
      data() {
        return {
          orderId: 'ORD' + Date.now(),
          orderPrice: 99.99,
          selectedMethod: 'wechat',
          paymentMethods: [
            {
              id: 'wechat',
              name: '微信支付',

description: '推荐使用微信支付',
icon: '💳'
},
{
id: 'alipay',
name: '支付宝',
description: '支付宝快捷支付',
icon: '💰'
}
]
}
},
methods: {
selectPaymentMethod(method) {
this.selectedMethod = method.id
},
submitPayment() {
// 1. 后端生成订单
this.createOrder()
},
createOrder() {
// 调用后端API生成订单
uni.request({
url: 'https://example.com/api/order/create',
method: 'POST',
data: {
orderId: this.orderId,
price: this.orderPrice,
paymentMethod: this.selectedMethod
},
success: (res) => {
if (res.data.code === 0) {
// 2. 发起支付
this.requestPayment(res.data.paymentParams)
} else {
uni.showToast({
title: '订单创建失败',
icon: 'none'
})
}
},
fail: (err) => {
console.error('创建订单失败', err)
uni.showToast({
title: '网络错误,请重试',
icon: 'none'
})
}
})
},
requestPayment(paymentParams) {
uni.requestPayment({
provider: this.selectedMethod === 'wechat' ? 'wxpay' : 'alipay',
timeStamp: paymentParams.timeStamp,
nonceStr: paymentParams.nonceStr,
package: paymentParams.package,
signType: paymentParams.signType,
paySign: paymentParams.paySign,
success: (res) => {
console.log('支付成功', res)
this.handlePaymentSuccess()
},
fail: (err) => {
console.error('支付失败', err)
this.handlePaymentFail(err)
},
complete: (res) => {
console.log('支付完成', res)
}
})
},
handlePaymentSuccess() {
uni.showToast({
title: '支付成功',
icon: 'success'
})

     // 更新订单状态
     this.updateOrderStatus('success')
     
     // 跳转到支付成功页面
     setTimeout(() => {
       uni.navigateTo({
         url: `/pages/payment/success?orderId=${this.orderId}&price=${this.orderPrice}`
       })
     }, 1500)
   },
   handlePaymentFail(err) {
     uni.showToast({
       title: '支付失败,请重试',
       icon: 'none'
     })
     
     // 更新订单状态
     this.updateOrderStatus('fail')
   },
   updateOrderStatus(status) {
     // 调用后端API更新订单状态
     uni.request({
       url: 'https://example.com/api/order/updateStatus',
       method: 'POST',
       data: {
         orderId: this.orderId,
         status: status
       },
       success: (res) => {
         console.log('订单状态更新成功', res)
       },
       fail: (err) => {
         console.error('订单状态更新失败', err)
       }
     })
   }
 }

}


2. **支付回调处理**
- 处理支付结果通知
- 验证支付结果的真实性
- 更新订单状态
- 发送支付成功通知

### 案例 2:会员订阅支付功能

#### 需求分析
- 支持多种订阅套餐
- 实现周期性支付(月付、年付等)
- 处理订阅状态和续费
- 支持订阅管理(暂停、取消等)

#### 实现方案

1. **订阅支付**
```vue
<template>
  <view class="subscription-app">
    <view class="subscription-plans">
      <text class="plans-title">选择订阅套餐</text>
      <view 
        v-for="(plan, index) in subscriptionPlans" 
        :key="index"
        @click="selectPlan(plan)"
        :class="{ active: selectedPlan.id === plan.id }"
        class="plan-item"
      >
        <text class="plan-name">{{ plan.name }}</text>
        <text class="plan-price">{{ plan.price }}</text>
        <text class="plan-period">{{ plan.period }}</text>
        <text class="plan-features" v-for="(feature, idx) in plan.features" :key="idx">
          • {{ feature }}
        </text>
      </view>
    </view>
    
    <button @click="submitSubscription" type="primary" class="subscribe-btn">
      立即订阅
    </button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      selectedPlan: null,
      subscriptionPlans: [
        {
          id: 'monthly',
          name: '月度会员',
          price: '¥19.99/月',
          period: '30天',
          features: [
            '无限访问所有内容',
            '高清视频观看',
            '无广告体验',
            '基础客服支持'
          ]
        },
        {
          id: 'yearly',
          name: '年度会员',
          price: '¥199.99/年',
          period: '365天',
          features: [
            '无限访问所有内容',
            '4K视频观看',
            '无广告体验',
            '优先客服支持',
            '专属内容'              ]
        },
        {
          id: 'lifetime',
          name: '终身会员',
          price: '¥999.99',
          period: '永久',
          features: [
            '无限访问所有内容',
            '8K视频观看',
            '无广告体验',
            '24小时客服支持',
            '专属内容',
            '终身免费升级'
          ]
        }
      ]
    }
  },
  onLoad() {
    // 默认选择月度会员
    this.selectedPlan = this.subscriptionPlans[0]
  },
  methods: {
    selectPlan(plan) {
      this.selectedPlan = plan
    },
    submitSubscription() {
      if (!this.selectedPlan) {
        uni.showToast({
          title: '请选择订阅套餐',
          icon: 'none'
        })
        return
      }
      
      // 生成订阅订单
      this.createSubscriptionOrder()
    },
    createSubscriptionOrder() {
      uni.request({
        url: 'https://example.com/api/subscription/create',
        method: 'POST',
        data: {
          planId: this.selectedPlan.id,
          planName: this.selectedPlan.name,
          price: this.selectedPlan.price,
          period: this.selectedPlan.period
        },
        success: (res) => {
          if (res.data.code === 0) {
            // 发起支付
            this.requestPayment(res.data.paymentParams)
          } else {
            uni.showToast({
              title: '订单创建失败',
              icon: 'none'
            })
          }
        },
        fail: (err) => {
          console.error('创建订单失败', err)
          uni.showToast({
            title: '网络错误,请重试',
            icon: 'none'
          })
        }
      })
    },
    requestPayment(paymentParams) {
      uni.requestPayment({
        provider: 'wxpay', // 或 'alipay'
        timeStamp: paymentParams.timeStamp,
        nonceStr: paymentParams.nonceStr,
        package: paymentParams.package,
        signType: paymentParams.signType,
        paySign: paymentParams.paySign,
        success: (res) => {
          console.log('支付成功', res)
          this.handleSubscriptionSuccess()
        },
        fail: (err) => {
          console.error('支付失败', err)
          this.handleSubscriptionFail(err)
        }
      })
    },
    handleSubscriptionSuccess() {
      uni.showToast({
        title: '订阅成功',
        icon: 'success'
      })
      
      // 更新用户订阅状态
      this.updateSubscriptionStatus('active')
      
      // 跳转到会员中心
      setTimeout(() => {
        uni.navigateTo({
          url: '/pages/member/center'
        })
      }, 1500)
    },
    handleSubscriptionFail(err) {
      uni.showToast({
        title: '订阅失败,请重试',
        icon: 'none'
      })
    },
    updateSubscriptionStatus(status) {
      uni.request({
        url: 'https://example.com/api/subscription/updateStatus',
        method: 'POST',
        data: {
          status: status,
          planId: this.selectedPlan.id
        },
        success: (res) => {
          console.log('订阅状态更新成功', res)
        },
        fail: (err) => {
          console.error('订阅状态更新失败', err)
        }
      })
    }
  }
}
</script>
  1. 订阅管理
    • 处理订阅续费
    • 管理订阅状态
    • 处理订阅取消和退款
    • 提供订阅历史记录

案例 3:虚拟商品支付功能

需求分析

  • 支持虚拟商品购买(如游戏币、会员点数等)
  • 实现快速支付流程
  • 处理商品发放和库存管理
  • 支持购买历史查询

实现方案

  1. 虚拟商品支付
    <template>
      <view class="virtual-goods-app">
        <view class="goods-list">
          <text class="list-title">虚拟商品</text>
          <view 
            v-for="(goods, index) in virtualGoods" 
            :key="index"
            @click="selectGoods(goods)"
            :class="{ active: selectedGoods.id === goods.id }"
            class="goods-item"
          >
            <text class="goods-name">{{ goods.name }}</text>
            <text class="goods-price">{{ goods.price }}</text>
            <text class="goods-desc">{{ goods.description }}</text>
          </view>
        </view>
        
        <button @click="purchaseGoods" type="primary" class="purchase-btn">
          立即购买
        </button>
      </view>
    </template>
    
    <script>
    export default {
      data() {
        return {
          selectedGoods: null,
          virtualGoods: [
            {
              id: 'coin_100',
              name: '100游戏币',
              price: '¥10.00',

description: '可用于游戏内购买道具'
},
{
id: 'coin_500',
name: '500游戏币',
price: '¥45.00',
description: '可用于游戏内购买道具'
},
{
id: 'coin_1000',
name: '1000游戏币',
price: '¥80.00',
description: '可用于游戏内购买道具'
},
{
id: 'vip_30',
name: '30天VIP',
price: '¥29.99',
description: '享受VIP特权'
}
]
}
},
onLoad() {
// 默认选择第一个商品
this.selectedGoods = this.virtualGoods[0]
},
methods: {
selectGoods(goods) {
this.selectedGoods = goods
},
purchaseGoods() {
if (!this.selectedGoods) {
uni.showToast({
title: '请选择商品',
icon: 'none'
})
return
}

     // 生成购买订单
     this.createOrder()
   },
   createOrder() {
     uni.request({
       url: 'https://example.com/api/goods/createOrder',
       method: 'POST',
       data: {
         goodsId: this.selectedGoods.id,
         goodsName: this.selectedGoods.name,
         price: this.selectedGoods.price
       },
       success: (res) => {
         if (res.data.code === 0) {
           // 发起支付
           this.requestPayment(res.data.paymentParams)
         } else {
           uni.showToast({
             title: '订单创建失败',
             icon: 'none'
           })
         }
       },
       fail: (err) => {
         console.error('创建订单失败', err)
         uni.showToast({
           title: '网络错误,请重试',
           icon: 'none'
         })
       }
     })
   },
   requestPayment(paymentParams) {
     uni.requestPayment({
       provider: 'wxpay', // 或 'alipay'
       timeStamp: paymentParams.timeStamp,
       nonceStr: paymentParams.nonceStr,
       package: paymentParams.package,
       signType: paymentParams.signType,
       paySign: paymentParams.paySign,
       success: (res) => {
         console.log('支付成功', res)
         this.handlePurchaseSuccess()
       },
       fail: (err) => {
         console.error('支付失败', err)
         this.handlePurchaseFail(err)
       }
     })
   },
   handlePurchaseSuccess() {
     uni.showToast({
       title: '购买成功',
       icon: 'success'
     })
     
     // 发放虚拟商品
     this.deliverGoods()
     
     // 跳转到购买成功页面
     setTimeout(() => {
       uni.navigateTo({
         url: '/pages/purchase/success?goodsId=' + this.selectedGoods.id
       })
     }, 1500)
   },
   handlePurchaseFail(err) {
     uni.showToast({
       title: '购买失败,请重试',
       icon: 'none'
     })
   },
   deliverGoods() {
     uni.request({
       url: 'https://example.com/api/goods/deliver',
       method: 'POST',
       data: {
         goodsId: this.selectedGoods.id,
         userId: 'current_user_id' // 实际项目中使用真实用户ID
       },
       success: (res) => {
         console.log('商品发放成功', res)
       },
       fail: (err) => {
         console.error('商品发放失败', err)
         // 记录发放失败,后续处理
       }
     })
   }
 }

}


2. **商品管理**
- 处理虚拟商品库存
- 管理商品发放记录
- 提供商品购买历史
- 处理商品退换货

## 学习目标

1. 掌握 uni-app 中支付功能的集成方法
2. 学会实现微信支付、支付宝支付等多种支付方式
3. 了解支付流程和安全处理
4. 能够开发电商、订阅、虚拟商品等不同场景的支付功能
5. 掌握支付异常处理和订单管理
6. 提升支付体验和成功率

## 总结

支付集成是 uni-app 应用开发中的重要组成部分,通过合理使用 uni.requestPayment() API、配置不同支付方式的参数、处理支付结果和订单状态,可以实现安全、可靠的支付功能。在实际开发中,开发者应该根据具体场景选择合适的支付方式,优化支付流程,提升支付体验和成功率。

同时,开发者还需要注意支付安全,保护商户密钥和用户信息,防止支付欺诈和安全漏洞。对于不同平台的支付差异,需要使用条件编译或平台特定的配置来处理,确保应用在所有平台上都能正常运行支付功能。

通过本教程的学习,开发者将能够掌握 uni-app 中支付功能的集成方法,为应用添加安全、便捷的支付能力,提升用户体验和商业价值。
« 上一篇 uni-app 定位服务 下一篇 » uni-app 推送系统