UniApp支付接口:打造统一支付能力
在移动应用开发中,支付功能是一个不可或缺的重要模块。本文将详细介绍如何在UniApp中实现微信支付和支付宝支付接口,并针对鸿蒙系统进行特别优化。
技术方案设计
1. 核心功能规划
- 统一支付接口封装
- 多平台支付适配
- 支付状态管理
- 订单信息处理
- 支付结果验证
- 错误处理机制
2. 技术架构选型
- 支付SDK:微信支付、支付宝SDK
- 状态管理:Vuex/Pinia
- 网络请求:uni.request
- 数据加密:CryptoJS
- 错误处理:统一异常处理
实现详解
1. 支付服务封装
首先,我们需要封装一个统一的支付服务:
// services/payment.ts
import { encrypt } from '@/utils/crypto'
import { generateOrderNo } from '@/utils/order'
interface PaymentConfig {
appId: string
mchId: string // 商户号
apiKey: string // API密钥
notifyUrl: string // 支付结果通知地址
}
interface PaymentParams {
amount: number
subject: string
body: string
orderId?: string
extraData?: Record<string, any>
}
class PaymentService {
private config: PaymentConfig
private platform: string
constructor(config: PaymentConfig) {
this.config = config
// 获取当前运行平台
this.platform = uni.getSystemInfoSync().platform
}
/**
* 统一支付入口
*/
async pay(params: PaymentParams): Promise<any> {
try {
// 生成订单号
const orderId = params.orderId || generateOrderNo()
// 构建支付参数
const payParams = await this.buildPayParams(params, orderId)
// 根据平台调用对应的支付方法
if (this.isWechat()) {
return this.wechatPay(payParams)
} else if (this.isAlipay()) {
return this.alipayPay(payParams)
} else if (this.isHarmonyOS()) {
return this.harmonyPay(payParams)
} else {
throw new Error('不支持的支付平台')
}
} catch (error) {
console.error('支付失败:', error)
throw error
}
}
/**
* 构建统一支付参数
*/
private async buildPayParams(params: PaymentParams, orderId: string) {
const timestamp = Date.now().toString()
const nonceStr = Math.random().toString(36).substr(2)
const baseParams = {
appId: this.config.appId,
mchId: this.config.mchId,
nonceStr,
timestamp,
orderId,
amount: params.amount,
subject: params.subject,
body: params.body,
notifyUrl: this.config.notifyUrl
}
// 生成签名
const sign = this.generateSign(baseParams)
return {
...baseParams,
sign
}
}
/**
* 微信支付实现
*/
private async wechatPay(params: any): Promise<any> {
try {
// 调用统一下单接口
const orderResult = await this.createWechatOrder(params)
// 调起微信支付
return new Promise((resolve, reject) => {
uni.requestPayment({
provider: 'wxpay',
timeStamp: params.timestamp,
nonceStr: params.nonceStr,
package: `prepay_id=${orderResult.prepayId}`,
signType: 'MD5',
paySign: orderResult.paySign,
success: (res) => {
resolve(res)
},
fail: (err) => {
reject(err)
}
})
})
} catch (error) {
throw error
}
}
/**
* 支付宝支付实现
*/
private async alipayPay(params: any): Promise<any> {
try {
// 调用支付宝统一收单接口
const orderInfo = await this.createAlipayOrder(params)
// 调起支付宝支付
return new Promise((resolve, reject) => {
uni.requestPayment({
provider: 'alipay',
orderInfo: orderInfo,
success: (res) => {
resolve(res)
},
fail: (err) => {
reject(err)
}
})
})
} catch (error) {
throw error
}
}
/**
* 鸿蒙支付实现
*/
private async harmonyPay(params: any): Promise<any> {
try {
// 获取鸿蒙支付能力
const harmonyPayApi = await this.getHarmonyPayApi()
// 构建鸿蒙支付参数
const harmonyParams = this.buildHarmonyPayParams(params)
// 调用鸿蒙支付接口
return new Promise((resolve, reject) => {
harmonyPayApi.pay({
...harmonyParams,
success: (res) => {
resolve(res)
},
fail: (err) => {
reject(err)
}
})
})
} catch (error) {
throw error
}
}
/**
* 生成签名
*/
private generateSign(params: Record<string, any>): string {
// 按字典序排序参数
const sortedParams = Object.keys(params)
.sort()
.reduce((result, key) => {
result[key] = params[key]
return result
}, {} as Record<string, any>)
// 构建签名字符串
const signStr = Object.entries(sortedParams)
.map(([key, value]) => `${key}=${value}`)
.join('&')
// 添加密钥
const signStrWithKey = `${signStr}&key=${this.config.apiKey}`
// 计算签名
return encrypt(signStrWithKey)
}
/**
* 平台判断方法
*/
private isWechat(): boolean {
return this.platform === 'mp-weixin'
}
private isAlipay(): boolean {
return this.platform === 'mp-alipay'
}
private isHarmonyOS(): boolean {
const systemInfo = uni.getSystemInfoSync()
return systemInfo.osName === 'HarmonyOS'
}
/**
* 创建微信订单
*/
private async createWechatOrder(params: any): Promise<any> {
return this.request('/api/pay/wechat/create', params)
}
/**
* 创建支付宝订单
*/
private async createAlipayOrder(params: any): Promise<any> {
return this.request('/api/pay/alipay/create', params)
}
/**
* 获取鸿蒙支付API
*/
private async getHarmonyPayApi(): Promise<any> {
// 这里实现鸿蒙支付API的获取逻辑
return new Promise((resolve) => {
// 模拟获取鸿蒙支付API
resolve({
pay: (options: any) => {
// 实现鸿蒙支付逻辑
}
})
})
}
/**
* 构建鸿蒙支付参数
*/
private buildHarmonyPayParams(params: any): any {
return {
...params,
// 添加鸿蒙特有的支付参数
platform: 'harmony',
version: '1.0.0'
}
}
/**
* 统一请求方法
*/
private async request(url: string, data: any): Promise<any> {
return new Promise((resolve, reject) => {
uni.request({
url: url,
method: 'POST',
data: data,
success: (res) => {
if (res.statusCode === 200 && res.data.code === 0) {
resolve(res.data.data)
} else {
reject(new Error(res.data.message || '请求失败'))
}
},
fail: (err) => {
reject(err)
}
})
})
}
}
export default PaymentService
2. 使用示例
<!-- pages/payment/index.vue -->
<template>
<view class="payment-container">
<view class="payment-header">
<text class="payment-amount">¥{{ amount }}</text>
<text class="payment-desc">{{ subject }}</text>
</view>
<view class="payment-methods">
<view
class="payment-method"
v-for="method in paymentMethods"
:key="method.id"
@tap="handlePayment(method)"
>
<image :src="method.icon" class="method-icon" />
<view class="method-info">
<text class="method-name">{{ method.name }}</text>
<text class="method-desc">{{ method.description }}</text>
</view>
<text class="iconfont icon-arrow-right"></text>
</view>
</view>
<button
class="payment-btn"
:class="{ 'payment-btn--harmony': isHarmonyOS }"
@tap="handleConfirmPayment"
>
确认支付
</button>
</view>
</template>
<script>
import { ref, onMounted } from 'vue'
import PaymentService from '@/services/payment'
export default {
setup() {
const amount = ref(99.99)
const subject = ref('商品订单')
const selectedMethod = ref(null)
const isHarmonyOS = ref(false)
const paymentMethods = [
{
id: 'wxpay',
name: '微信支付',
description: '推荐使用微信支付',
icon: '/static/images/wxpay.png'
},
{
id: 'alipay',
name: '支付宝',
description: '推荐使用支付宝',
icon: '/static/images/alipay.png'
}
]
// 检测系统类型
onMounted(() => {
const systemInfo = uni.getSystemInfoSync()
isHarmonyOS.value = systemInfo.osName === 'HarmonyOS'
// 如果是鸿蒙系统,添加鸿蒙支付方式
if (isHarmonyOS.value) {
paymentMethods.push({
id: 'harmony',
name: '鸿蒙支付',
description: '推荐使用鸿蒙支付',
icon: '/static/images/harmony.png'
})
}
})
// 选择支付方式
const handlePayment = (method) => {
selectedMethod.value = method
}
// 确认支付
const handleConfirmPayment = async () => {
if (!selectedMethod.value) {
uni.showToast({
title: '请选择支付方式',
icon: 'none'
})
return
}
try {
const paymentService = new PaymentService({
appId: 'your_app_id',
mchId: 'your_mch_id',
apiKey: 'your_api_key',
notifyUrl: 'your_notify_url'
})
const result = await paymentService.pay({
amount: amount.value,
subject: subject.value,
body: '商品描述',
extraData: {
paymentMethod: selectedMethod.value.id
}
})
// 处理支付结果
if (result.success) {
uni.showToast({
title: '支付成功',
icon: 'success'
})
// 跳转到支付成功页面
setTimeout(() => {
uni.navigateTo({
url: '/pages/payment/success'
})
}, 1500)
}
} catch (error) {
uni.showToast({
title: error.message || '支付失败',
icon: 'none'
})
}
}
return {
amount,
subject,
paymentMethods,
isHarmonyOS,
handlePayment,
handleConfirmPayment
}
}
}
</script>
<style>
.payment-container {
padding: 20px;
}
.payment-header {
text-align: center;
margin-bottom: 30px;
}
.payment-amount {
font-size: 36px;
font-weight: bold;
color: #333;
}
.payment-desc {
font-size: 14px;
color: #666;
margin-top: 8px;
}
.payment-methods {
background-color: #fff;
border-radius: 8px;
margin-bottom: 20px;
}
.payment-method {
display: flex;
align-items: center;
padding: 16px;
border-bottom: 1px solid #eee;
}
.method-icon {
width: 32px;
height: 32px;
margin-right: 12px;
}
.method-info {
flex: 1;
}
.method-name {
font-size: 16px;
color: #333;
}
.method-desc {
font-size: 12px;
color: #999;
margin-top: 4px;
}
.payment-btn {
width: 100%;
height: 44px;
background-color: #007AFF;
color: #fff;
border-radius: 22px;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
}
.payment-btn--harmony {
background-color: #0A59F7;
}
</style>
性能优化
-
请求优化
- 接口缓存
- 请求合并
- 错误重试
-
支付体验
- 预加载资源
- 状态缓存
- 动画过渡
-
鸿蒙适配
- 原生API调用
- 性能优化
- 界面适配
最佳实践建议
-
安全性
- 参数加密
- 签名验证
- 敏感信息保护
-
用户体验
- 清晰的支付流程
- 友好的错误提示
- 完整的结果展示
-
代码质量
- TypeScript类型
- 异常处理
- 代码复用
总结
通过本文的介绍,我们实现了一个功能完整的支付服务,支持微信支付、支付宝支付,并对鸿蒙系统进行了特别优化。该实现不仅保证了支付功能的可靠性,还提供了良好的用户体验。
希望这个实现能够帮助开发者快速集成支付功能。同时,也欢迎大家在实践中不断改进和完善这些功能。
参考资料
- UniApp官方文档
- 微信支付开发文档
- 支付宝开放平台文档
- HarmonyOS开发指南