# uni.requestPayment(options)

请求支付

# requestPayment 兼容性

Web 微信小程序 Android iOS HarmonyOS
x 4.41 4.02 4.18 4.61

uni.requestPayment是一个统一各平台的客户端支付API,客户端均使用本API调用支付。

本API运行在各端时,会自动转换为各端的原生支付调用API。

注意支付不仅仅需要客户端的开发,还需要服务端开发。虽然客户端API统一了,但各平台的支付申请开通、配置回填仍然需要看各个平台本身的支付文档。

比如微信有App支付的申请入口和使用流程,对应到uni-app,在App端要申请微信的App支付。

如果服务端使用uniCloud,那么官方提供了uniPay云端统一支付服务,把App、微信小程序、支付宝小程序里的服务端支付开发进行了统一的封装。

前端统一的uni.requestPayment和云端统一的uniPay搭配,可以极大提升支付业务的开发效率,强烈推荐给开发者使用。uniPay的文档另见:https://doc.dcloud.net.cn/uniCloud/uni-pay/uni-app.html

# 参数

名称 类型 必填 默认值 兼容性 描述
options RequestPaymentOptions
名称 类型 必备 默认值 兼容性 描述
provider string
支付服务提供商,通过 uni.getProvider 获取,目前支持支付宝支付(alipay),微信支付(wxpay)
orderInfo string
订单数据
success (result: RequestPaymentSuccess) => void
接口调用成功的回调函数
fail (result: RequestPaymentFail) => void
接口调用失败的回调函数
complete (result: any) => void
接口调用结束的回调函数(调用成功、失败都会执行)
nonceStr string
随机字符串,长度为32个字符以下
package string
统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
paySign string
签名,具体见微信支付文档
timeStamp string
时间戳,从 1970 年 1 月 1 日 00:00:00 至今的秒数,即当前的时间
signType string
签名算法,应与后台下单时的值一致

可选值:
- 'MD5': 仅在 v2 版本接口适用;
- 'HMAC-SHA256': 仅在 v2 版本接口适用;
- 'RSA': 仅在 v3 版本接口适用;
合法值 兼容性 描述
MD5
HMAC-SHA256
RSA

# RequestPaymentSuccess 的属性值

名称 类型 必备 默认值 兼容性 描述
data any
返回数据

# RequestPaymentFail 的属性值

名称 类型 必备 默认值 兼容性 描述
errCode number
错误码
合法值 兼容性 描述
700000
其它支付错误。
700600
正在处理中,支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态
700601
用户中途取消。
700602
网络连接出错。
700603
支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态。
700604
微信没有安装。
700605
服务供应商获取失败。
700607
支付未完成。
700608
服务商返回参数错误。
700800
没有配置对应的URL Scheme。
700801
没有配置对应的Universal Link。
701100
订单支付失败。
701110
重复请求。
errSubject string
统一错误主题(模块)名称
data any
错误信息中包含的数据
cause Error 源错误信息,可以包含多个错误,详见SourceError
errMsg string

# orderInfo参数说明

  • 支付宝支付 App 支付请求参数字符串,主要包含商家的订单信息,key=value 形式,以 & 连接。示例
app_id=2015052600090779&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22seller_id%22%3A%22%22%2C%22product_code%
22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.02%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%
91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22
%2C%22out_trade_no%22%3A%22314VYGIAGG7ZOYY%22%7D&charset=utf-8&method=alipay.trade.app.pay&sign_type=R
SA2&timestamp=2016-08-15%2012%3A12%3A15&version=1.0&sign=MsbylYkCzlfYLy9PeRwUUIg9nZPeN9SfXPNavUCroGKR5Kqvx0nEnd3eRmKxJuthNUx4ERCXe552
EV9PfwexqW%2B1wbKOdYtDIb4%2B7PL3Pc94RZL0zKaWcaY3tSL89%2FuAVUsQuFqEJd
hIukuKygrXucvejOUgTCfoUdwTi7z%2BZzQ%3D<br>

[更多详情参考支付宝官方文档]

  • 微信支付 App 支付请求参数字符串,需要打自定义基座。示例
{
 "appid":"wxd569c7238830733b",
 "noncestr":"6N47VnR42bqIm4xq",
 "package":"Sign=WXPay",
 "partnerid":"1230636401",
 "prepayid":"wx26174750316675ac54b89c224eb3250000",
 "timestamp":1711446470,
 "sign":"EE987459B9CFF6462462147130110D31"
}

[更多详情参考微信官方文档]

# 参见

# 支付provider对象描述

UniPaymentAlipayProvider(支付宝支付)继承自 UniProvider

UniPaymentWxpayProvider(微信支付)继承自 UniProvider,特有字段说明:

名称 类型 必备 默认值 描述
isWeChatInstalled boolean - 判断微信是否安装

# 支付SDK错误码

支付失败时可通过错误回调参数IRequestPaymentFail中的cause属性获取支付SDK的源错误信息,类型为SourceError,其包含 code 属性存储了支付SDK的原始错误码。

# 支付宝支付

支付宝错误码 错误信息
9000 订单支付成功
8000 正在处理中,支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态
4000 订单支付失败
5000 重复请求
6001 用户中途取消
6002 网络连接出错
6004 支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态
其它 其它支付错误

# 微信支付

微信支付错误码 错误信息
0 成功
-1 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常原因等
-2 无需处理。发生场景:用户不支付了,点击取消,返回APP
-3 发送失败
-4 授权被拒绝
-5 不支持
-6 禁止
其它 其它支付错误

# 注意

  • App平台开发支付宝支付,无需自定义基座,真机运行可直接开发
  • App平台判断微信是否安装可以通过uni.getProvider的方式,详见uni.getProvider
  • 在4.25版本前使用微信支付,Android需要在隐私协议弹框后调用微信sdk
   uni.getProvider({
      service: "payment",
      success: (e) => {
         const provider = e.providers.find((item): boolean => {
            return item.id == 'wxpay'
         })

          // #ifdef APP-ANDROID
          if (provider != null && provider instanceof UniPaymentWxpayProvider && !((provider as UniPaymentWxpayProvider).isWeChatInstalled)) {
            console.log('WeChat 没有安装')
          } else {
             console.log('WeChat 已安装')
          }
          // #endif
          // #ifdef APP-IOS
          if (provider != null && ((provider as UniPaymentWxpayProvider).isWeChatInstalled == undefined || ((provider as UniPaymentWxpayProvider).isWeChatInstalled != null && (provider as UniPaymentWxpayProvider).isWeChatInstalled == false))) {
            console.log('WeChat 没有安装')
          } else {
            console.log('WeChat 已安装')
          }
          // #endif
      },
      fail: (e) => {
         console.log("获取支付通道失败:", e);
      }
   })

# 示例

示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见

该 API 不支持 Web,请运行 hello uni-app x 到 App 平台体验

扫码体验(手机浏览器跳转到App直达页)
<template>
  <page-head title="发起支付"></page-head>
  <view class="uni-common-mt payment-content">
    <text>如对当前页面的支付示例功能有任何疑问,通过电子邮件:service@dcloud.io 联系我们</text>
  </view>
  <view class="payment-content">
    <template v-if="providerList.length > 0">
      <button class="payment-button" type="primary" v-for="(item, index) in providerList" :key="index" @click="requestPayment(item)">{{ item.name }}</button>
    </template>
    <template v-else>
      <button class="payment-button" type="primary">请先在 manifest.json 配置勾选微信支付、支付宝</button>
    </template>
  </view>
</template>

<script setup lang="uts">
  export type PayItem = { id: string; name: string; provider?: UniProvider };

  type DataType = {
    btnText: string;
    btnType: string;
    orderInfo: string;
    errorCode: number;
    errorMsg: string;
    complete: boolean;
    fail: boolean;
    outTradeNo: string;
    openid: string;
  };

  type PaymentOptions = {
    provider: string;
    orderInfo: string;
    errorTitle?: string;
    duration?: number;
  };

  // 支付订单请求地址
  const ALIPAY_ORDER_URL = 'https://demo.dcloud.net.cn/payment/alipay/?total=0.01';
  const WXPAY_ORDER_URL = 'https://demo.dcloud.net.cn/payment/wxpayv3.__UNI__uniappx/?total=0.01';
  const WXPAY_HELLO_UNI_APP_X_ORDER_URL = 'https://demo.dcloud.net.cn/payment/wxpayv3.__UNI__HelloUniAppX/?total=0.01';
  const UNI_PAY_API_URL = 'https://env-00jxt67zj8kj.dev-hz.cloudbasefunction.cn/uni-pay-api';

  const providerList = ref([] as PayItem[]);

  const data = reactive({
    btnText: '支付宝支付',
    btnType: 'primary',
    orderInfo: '',
    errorCode: 0,
    errorMsg: '',
    complete: false,
    fail: false,
    outTradeNo: '',
    openid: '',
  } as DataType);

  const getPaymentBundleId = (): string => {
    let bundleId: string | null = '';
    // #ifdef APP-ANDROID
    bundleId = uni.getAppBaseInfo().packageName;
    // #endif
    // #ifdef APP-IOS
    bundleId = uni.getAppBaseInfo().bundleId;
    // #endif
    // #ifdef APP-HARMONY
    bundleId = uni.getAppBaseInfo().bundleName;
    // #endif
    // #ifdef MP-WEIXIN
    bundleId = uni.getAccountInfoSync().miniProgram.appId;
    // #endif
    return bundleId ?? '';
  };

  const getWxpayOrderUrl = (): string => {
    if (getPaymentBundleId() == 'io.dcloud.hellouniappx') {
      return WXPAY_HELLO_UNI_APP_X_ORDER_URL;
    }
    return WXPAY_ORDER_URL;
  };

  const requestPaymentByOrderInfo = (options: PaymentOptions) => {
    let duration = 3000;
    if (options.duration != null) {
      duration = options.duration as number;
    }
    uni.requestPayment({
      provider: options.provider,
      orderInfo: options.orderInfo,
      // #ifdef MP-WEIXIN
      // 微信小程序支持...结构语法
      ...JSON.parse(options.orderInfo),
      // #endif
      // #ifdef APP-HARMONY
      dataType: 'text',
      // #endif
      success: (res: RequestPaymentSuccess) => {
        console.log(JSON.stringify(res));
        uni.showToast({ duration, icon: 'success', title: '支付成功' });
      },
      fail: (res: RequestPaymentFail) => {
        console.log(JSON.stringify(res));
        data.errorCode = res.errCode;
        const title = options.errorTitle == null ? 'errorCode:' + data.errorCode : options.errorTitle;
        uni.showToast({ duration, icon: 'error', title });
      },
    } as RequestPaymentOptions);
  };

  // #ifdef APP
  const appPay = (provider: string) => {
    uni.showLoading({ title: '请求中...' });
    const isWxpay = provider == 'wxpay';
    uni.request({
      url: isWxpay ? getWxpayOrderUrl() : ALIPAY_ORDER_URL,
      method: 'GET',
      timeout: 6000,
      success: (res) => {
        console.log(res.data);
        const orderInfo = isWxpay ? JSON.stringify(res.data) : (res.data as string);
        data.orderInfo = JSON.stringify(res.data);
        uni.hideLoading();
        requestPaymentByOrderInfo({
          provider,
          orderInfo,
          duration: isWxpay ? 5000 : 3000,
        });
      },
      fail: (res) => {
        uni.hideLoading();
        console.log(res);
      },
    });
  };
  // #endif

  // #ifdef MP-WEIXIN
  // 发起微信小程序支付
  const mpWeixinPay = async (): Promise<void> => {
    uni.showLoading({ title: '请求中...', mask: true });
    try {
      if (data.openid == '') {
        await getOpenId();
      }
    } catch (err) {
      uni.hideLoading();
      console.error('get-openid-err', err);
      return;
    }
    let bundleId = getPaymentBundleId();
    let random = Math.floor(Math.random() * 9000) + 1000;
    data.outTradeNo = `test${Date.now()}${random}`;
    console.log('outTradeNo: ', data.outTradeNo);
    uni.request({
      url: `${UNI_PAY_API_URL}/getOrderInfo`,
      method: 'GET',
      data: {
        outTradeNo: data.outTradeNo,
        bundleId,
        openid: data.openid,
        totalFee: 1,
      },
      success: (res) => {
        uni.hideLoading();
        let responseData = res.data as UTSJSONObject;
        let errCode = responseData['errCode'] as number;
        if (errCode != 0) {
          uni.showModal({
            title: '提示',
            content: responseData['errMsg'] as string,
            showCancel: false,
          });
          return;
        }
        let orderInfo = responseData['orderInfo'] as string;
        console.log('orderInfo: ', orderInfo);
        requestPaymentByOrderInfo({
          provider: 'wxpay',
          orderInfo,
          errorTitle: '支付失败',
        });
      },
      fail: (err) => {
        uni.hideLoading();
        console.error('request-err', err);
      },
    });
  };
  // #endif

  const requestPayment = (e: PayItem) => {
    // #ifdef APP
    const provider = e.id;
    if (provider == 'wxpay') {
      const wxProvider = e.provider as UniPaymentWxpayProvider;
      if (wxProvider != null && wxProvider.isWeChatInstalled != null && wxProvider.isWeChatInstalled == false) {
        uni.showToast({
          title: '微信没有安装',
          icon: 'error',
        });
        return;
      }
    }
    appPay(provider);
    // #endif

    // #ifdef MP-WEIXIN
    mpWeixinPay();
    // #endif
  };

  // #ifdef MP-WEIXIN
  // 获取微信小程序openid,用于发起支付
  const getOpenId = async (): Promise<void> => {
    let bundleId = getPaymentBundleId();
    let code = '';
    await new Promise<void>((resolve, reject) => {
      uni.login({
        provider: 'weixin',
        success: (res) => {
          code = res.code;
          resolve();
        },
        fail: (err) => {
          reject(err);
        },
      });
    });
    await new Promise<void>((resolve, reject) => {
      uni.request({
        url: `${UNI_PAY_API_URL}/getOpenId`,
        method: 'GET',
        data: {
          code,
          bundleId,
        },
        success: (res) => {
          data.openid = res.data.openid;
          console.log('openid: ', data.openid);
          resolve();
        },
        fail: (err) => {
          console.error('request-err', err);
          reject(err);
        },
      });
    });
  };
  // #endif

  onLoad(() => {
    // #ifdef APP
    let provider = uni.getProviderSync({
      service: 'payment',
    } as GetProviderSyncOptions);
    console.log(provider);
    provider.providerObjects.forEach((value: UniProvider) => {
      if (value.id == 'alipay' || value.id == 'wxpay') {
        console.log(value.id, value);
        providerList.value.push({
          name: value.description,
          id: value.id,
          provider: value,
        } as PayItem);
      }
    });
    // #endif

    // #ifdef MP-WEIXIN
    providerList.value.push({
      name: '微信支付',
      id: 'wxpay',
    } as PayItem);
    // #endif
  });

  // 自动化测试使用
  const jest_pay = () => {
    uni.requestPayment({
      provider: 'alipay',
      orderInfo: data.orderInfo,
      fail: (res: RequestPaymentFail) => {
        data.errorCode = res.errCode;
        data.complete = true;
        data.fail = true;
      },
      success: (res: RequestPaymentSuccess) => {
        console.log(JSON.stringify(res));
        data.complete = true;
        data.fail = false;
      },
    } as RequestPaymentOptions);
  };

  defineExpose({
    data,
    jest_pay,
  });
</script>

<style>
  .payment-content {
    padding: 0 10px;
  }

  .payment-button {
    margin-top: 20px;
  }
</style>

# 通用类型

# GeneralCallbackResult

名称 类型 必备 默认值 兼容性 描述
errMsg string
错误信息

# API源码和更多SDK功能

App平台,微信和支付宝的SDK,除了requestPayment API封装的功能,还有一些其他功能。如开发者需要调用这些SDK的其他API,可以使用uts直接调用(注意打包时勾选相应的模块)

可以参考uni.requestPayment的源码,也是通过uts调用这2个原生SDK:

# 自定义支付provider接入到uni API

背景:目前uni-app x引擎已经内置了支付宝支付、微信支付。但支付SDK还有很多,比如银联SDK。

以往这些SDK可以通过独立插件的方式集成到uni-app x中,但需要提供单独的API给开发者使用。

uni-app x从4.25起,开放了provider自接入机制,让三方SDK可以以provider方式被开发者集成。

开发一个UTS插件,对接uni规范化的API、错误信息描述等实现自己的支付插件,这样插件使用者就可以通过uni的标准API使用三方SDK。

举个例子,开发者想使用uni.requestPayment()的方式调用XX支付,但是内置支付api不支持,

那只需要按照下面四个步骤实现即可:

第一步,新建一个UTS插件,在interface.uts 中定义接口,继承UniPaymentProvider,代码如下

export interface UniPaymentAlipayProvider extends UniPaymentProvider{}

第二步,在app-android或者app-ios的index.uts中实现接口,代码如下

import { UniPaymentAlipayProvider } from '../interface.uts'
export class UniPaymentAlipayProviderImpl implements UniPaymentAlipayProvider{
	override id : String = "XX" // id必须有插件作者前缀,避免冲突,避免不同插件作者的插件id重名
	override description : String = "XX的描述"
	override isAppExist : boolean | null = null

	constructor(){}

	override requestPayment(options : RequestPaymentOptions) {
		//todo 具体逻辑,接收uni规范的入参,进行业务处理,返回uni规范的返回值。如遇到错误,按uni的规范返回错误码
	}
}

第三步,在manifest.json中配置

  "app": {
    "distribute": {
      /* android打包配置 */
      "modules": {
        "uni-payment":{
          "XX":{}
        }
      }
    }
  }

第四步,打包自定义基座然后运行

由于uni-app x内置的支付API也是基于这套规范实现的,所以推荐参考 uni-app x支付宝支付插件的实现源码