线上支付
线上支付
1. 基本概念
Passport的「经济系统」提供接入线上支付的相关接口,玩家可以通过线上真实货币支付后购买Passport经济系统中的商品,并保存相关交易记录。
可参考下方流程集成线上支付:
创建订单:
- 自行生成自定义唯一订单号outTradeNo,调用外部线上支付的生成订单方法
- 调用passport经济系统「创建交易记录」完成订单的创建
处理支付回调:
- 自行解析外部线上支付回调的内容,判断是否支付成功
- 调用passport经济系统「支付回调」更新交易状态,若支付成功则完成购买流程
具体可参考 支付宝接入示例 中的完整示例代码。
2. 准备工作
开通 UOS Passport
开通 UOS Passport 服务,进入 Passport 服务侧边栏「经济系统」模块。
资源商品配置
- 在 「资源」 栏下配置一个资源,此资源为购买商品可以获得的「物品」或「虚拟货币」
- 在 「商品」 栏下配置一个商品(首次配置商品前需要先创建一个目录),设置消耗资源为人民币CNY,数量单位为分(假设消耗0.01元则此处数量应配置为1,1元则此处应为100,图中以0.01元为例),获得物品为上一步中的资源

- 完成商品配置后,更改发布状态,发布此商品,并记录商品 SlugName 和商品名称供后续函数调用使用。此时此商品即为一个需要人民币才可以购买的商品,使用人民币线上购买后角色背包内会增加对应的资源。
3. 相关函数
详细函数说明及请求示例参见 「Passport 服务端API接入指南 / 线上支付」 。
3.1 创建交易记录
请求方式:POST
URL: https://p.unity.cn/v1/payments
参数说明:
| 名称 | 描述 | 类型 |
|---|---|---|
| personaId | 购买者的角色ID,不可为空 | string |
| outTradeNo | 自定义唯一订单号,不可为空,不可重复 | string |
| paymentMethod | 交易渠道,可自定义渠道名称,不可为空 | string |
| totalAmount | 订单总金额,单位为分,取值范围为 [1,10000000000]。金额不能为0。需要与购买的uos passport经济系统中的商品价格一致 | int |
| productSlug | uos passport经济系统中的商品slugName,不可为空 | string |
| expiredAt | 可选参数。订单的失效时间,遵循标准时间格式,格式为yyyy-MM-DDTHH:mm:ss+,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒 | string |
3.2 支付回调
请求方式:POST
URL: https://p.unity.cn/v1/payments/notify
参数说明:
| 名称 | 描述 | 类型 |
|---|---|---|
| outTradeNo | 支付完成的自定义唯一订单号,不可为空 | string |
| tradeState | 交易状态,保存支付方返回的交易状态,不可为空 | string |
| totalAmount | 支付总金额,单位为分,需和订单金额保持一致 | int |
| paymentSuccess | 交易是否成功 | bool |
4. 支付宝接入示例
我们提供一套完整的支付宝线上支付接入示例,使用了 Func Stateless 云函数作为服务端进行支付相关操作的处理。建议使用前先了解支付宝官方文档中的支付相关内容。
代码包中包括了五个云函数,其中 alipayPagePay、alipayWapPay 和 alipayAppPay 分别对应了电脑网站支付、手机网站支付和跳转支付宝APP支付。 在客户端发起支付时,可以根据需要调用生成的对应云函数。
alipayCallback 和 alipayNotify 处理了支付宝端的同步回调和异步回调,供支付宝方调用,用于接收并处理支付宝返回的信息。
4.1. Func Stateless 相关配置
开通 Func Stateless
开通 Func Stateless 服务,脚本语言选择为 Nodejs.
上传云函数
上传支付相关函数 uosPassportAlipay.zip 包,进入在线编辑,进行配置:
将 utils/common.js 中的 appId 填入 支付宝 的应用APPID,可在支付宝的应用信息页面获得:

将 utils/common.js 中的 gateway 填入网关地址,可在支付宝应用信息中获得:
- 正式上线地址为
https://openapi.alipay.com/gateway.do - 沙盒测试地址为
https://openapi-sandbox.dl.alipaydev.com/gateway.do
- 正式上线地址为
private-key.pem 文件中填入应用私钥,沙箱环境可在支付宝应用信息中的开发信息处,点击「查看」后可获取,注意应用私钥需要选择 非JAVA语言 !

正式环境获取方式可参考如何生成及配置 RSA2 密钥:
alipay-public-key.pem 文件中填入支付宝公钥,注意不是应用公钥,沙箱环境中获取方式同上,正式环境获取方式可參考 如何获取支付宝公钥:

确认上传
编辑完成后,点击右上方「上传云函数」,等待云函数上传完毕(约1-2分钟)。上传完成后列表中应有五个函数,并且状态均为已启用。
记录函数地址
记录下 alipayNotify、alipayCallback 两个函数的地址:
重新编辑云函数
点击「在线编辑」,重新编辑云函数。将上述的两个地址分别填入 utils/common.js 中的 exports.returnUrl(对应alipayCallback地址),exports.notifyUrl(对应alipayNotify地址)。
注意:当 Func Stateless 转成正式用户时,alipayNotify、alipayCallback 两个函数的地址会改变。此时需要重复此步骤,重新填写exports.returnUrl和exports.notifyUrl的地址。

完成配置
再次点击右上方「上传云函数」,等待云函数更新完毕。此时已完成了所有支付宝支付的相关配置,对于每个函数,可以在后续调用结束后,点击函数右侧对应的「...」选择「查看日志」监控函数的调用情况。
4.2. 调用流程示例
此处以 电脑网站支付alipayPagePay 为例,模拟实现玩家使用支付宝购买 SlugName 为 testProduct 的商品:
首先我们需要准备一个玩家的角色ID(personaID):
- 在「账号 -> 角色管理」下可以查看当前 UOS App 下已有的角色列表。
- 如果想快速创建一个测试角色,可以点击 Passport 功能列表下方的「在线体验」,使用手机号登录Demo并创建角色进入主页面后,回到「账号 -> 角色管理」下就可以看到新创建的角色了。
此时,调用 alipayPagePay 在 Func Stateless 上对应的URL:
body为:
{
// 需要支付的总金额,单位为分,此处表示玩家需要支付0.01元
"totalAmount": 1,
// 订单标题
"subject": "testpagepay",
// 玩家需要购买的经济系统商品slugName
"productSlug": "testProduct",
// 玩家需要购买的经济系统商品名称
"productName": "测试商品",
// 玩家的personaID
"personaId": "1000390001",
// 可选,支付的超时时间,建议不晚于当前时间的12小时后
"expiredAt": "2024-11-26T17:51:00+08:00"
}调用成功后会返回一个URL。此时这个支付交易订单已经创建,在「Passport -> 经济系统 -> 交易记录」中可以看到创建了一个交易订单,状态为“待支付”,表示玩家已经下单但是还未支付。
返回的URL就是玩家需要进行支付操作的页面。模拟玩家操作打开这个URL之后,会看到如图所示的网页内容,会显示需要支付的金额、交易关闭时间、订单标题等信息。测试时可以使用支付宝的沙盒账号和密码进行模拟支付。
支付宝支付完成后,支付宝会调用alipayCallback同步返回,可以根据游戏逻辑需要修改alipayCallback云函数中的内容。此时,在「Passport -> 经济系统 -> 交易记录」中可以看到这个交易订单的状态变为“交易完成”,表示本次支付宝交易成功。
在「passport -> 经济系统 -> 背包」中,也可以看到角色背包中增加了购买商品可以获得的对应资源。
4.3. 云函数调用说明
电脑网站支付(alipayPagePay)
请求方式:POST
URL:见Func Stateless页面上显示的函数名对应的地址:
参数:
| 名称 | 描述 | 类型 |
|---|---|---|
| totalAmount | 订单总金额,单位为分,取值范围为 [1,10000000000]。金额不能为0。需要与购买的uos passport经济系统中的商品价格一致。 | int |
| subject | 订单标题。注意:不可使用特殊字符,如 /,=,& 等。 | string |
| productSlug | uos passport经济系统中的商品slugName | string |
| productName | uos passport经济系统中的商品名称 | string |
| personaId | 进行购买行为的uos passport角色ID | string |
| expiredAt | 可选参数。超时时间范围:1m~15d。订单的失效时间,遵循标准时间格式,格式为yyyy-MM-DDTHH:mm:ss+,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。 | string |
body示例:
{
"totalAmount": 1,
"subject": "testpagepay",
"productSlug": "testProduct",
"productName": "测试商品",
"personaId": "1000390001",
"expiredAt": "2024-11-26T17:51:00+08:00"
}返回值:
- 正常情况:
statusCode: 200
body: 支付宝URL,需要打开或重定向到该URL进入支付流程 - 异常情况:
statusCode: 400
body: 错误内容
手机网站支付(alipayWapPay)
请求方式:POST
URL:见Func Stateless页面上显示的函数名对应的地址:
参数:
| 名称 | 描述 | 类型 |
|---|---|---|
| totalAmount | 订单总金额,单位为分,取值范围为 [1,10000000000]。金额不能为0。需要与购买的uos passport经济系统中的商品价格一致。 | int |
| subject | 订单标题。注意:不可使用特殊字符,如 /,=,& 等。 | string |
| productSlug | uos passport经济系统中的商品slugName | string |
| productName | uos passport经济系统中的商品名称 | string |
| personaId | 进行购买行为的uos passport角色ID | string |
| expiredAt | 可选参数。超时时间范围:1m~15d。订单的失效时间,遵循标准时间格式,格式为yyyy-MM-DDTHH:mm:ss+,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。 | string |
body示例:
{
"totalAmount": 1,
"subject": "testpagepay",
"productSlug": "testProduct",
"productName": "测试商品",
"personaId": "1000390001",
"expiredAt": "2024-11-26T17:51:00+08:00"
}返回值:
- 正常情况:
statusCode: 200
body: 支付宝URL,需要打开或重定向到该URL进入支付流程 - 异常情况:
statusCode: 400
body: 错误内容
APP支付(alipayAppPay)
请求方式:POST
URL:见Func Stateless页面上显示的函数名对应的地址:
参数:
| 名称 | 描述 | 类型 |
|---|---|---|
| totalAmount | 订单总金额,单位为分,取值范围为 [1,10000000000]。金额不能为0。需要与购买的uos passport经济系统中的商品价格一致。 | int |
| subject | 订单标题。注意:不可使用特殊字符,如 /,=,& 等。 | string |
| productSlug | uos passport经济系统中的商品slugName | string |
| productName | uos passport经济系统中的商品名称 | string |
| personaId | 进行购买行为的uos passport角色ID | string |
| expiredAt | 可选参数。超时时间范围:1m~15d。订单的失效时间,遵循标准时间格式,格式为yyyy-MM-DDTHH:mm:ss+,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。 | string |
body示例:
{
"totalAmount": 1,
"subject": "testpagepay",
"productSlug": "testProduct",
"productName": "测试商品",
"personaId": "1000390001",
"expiredAt": "2024-11-26T17:51:00+08:00"
}返回值:
- 正常情况:
statusCode: 200
| 名称 | 描述 | 类型 |
|---|---|---|
| orderStr | 签名字符串,用于客户端调用支付宝支付接口发起支付 | string |
- 异常情况:
statusCode: 400
body: 错误内容
同步返回(alipayCallback)
支付宝的同步返回,目前是uos经济系统的交易信息,可自行更改。
异步通知(alipayNotify)
支付宝的异步通知调用,用于接受支付订单状态,不可更改。
5. 微信支付接入示例
我们提供一套完整的支付宝线上支付接入示例,使用了 Func Stateless 云函数作为服务端进行支付相关操作的处理。建议使用前先了解微信支付官方文档中的支付相关内容。
在开始接入前,请确保已完成:
- 注册微信支付商户号
- 获取 AppID 和商户号(mchId)
- 配置支付回调地址
5.1 Func Stateless 相关配置
开通 Func Stateless 服务,脚本语言选择为 Nodejs.
上传云函数
上传支付相关函数 uosPassportWxpay.zip 包,进入在线编辑,进行配置:
- 将 utils/common.js 中的 appId 填入直连商户申请的公众号或移动应用AppId
- 将 utils/common.js 中的 mchId 填入商户号
- 将 utils/common.js 中的 apiKey 填入商户平台上设置的APIv3密钥【微信商户平台 (opens new window)—>账户设置—>API安全—>设置APIv3密钥】
- apiclient_cert.pem 文件中填入公钥
- apiclient_key.pem 文件中填入私钥
确认上传
编辑完成后,点击右上方「上传云函数」,等待云函数上传完毕(约1-2分钟)。上传完成后列表中应有五个函数,并且状态均为已启用。
记录函数地址
记录下 wxpayNotify 函数的地址:
重新编辑云函数
点击「在线编辑」,重新编辑云函数。将上述地址填入 utils/common.jsexports.notifyUrl。
注意:当 Func Stateless 转成正式用户时,wxpayNotify函数的地址会改变。此时需要重复此步骤,重新填写exports.notifyUrl的地址。

完成配置
再次点击右上方「上传云函数」,等待云函数更新完毕。此时已完成了所有支付宝支付的相关配置,对于每个函数,可以在后续调用结束后,点击函数右侧对应的「...」选择「查看日志」监控函数的调用情况。
5.2 参数说明
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| totalAmount | Number | 是 | 订单总金额,单位为分 |
| subject | String | 是 | 商品描述 |
| clientIP | String | 是 | 用户的客户端IP |
| productSlug | String | 是 | 商品标识符 |
| personaId | String | 是 | 用户ID |
| expiredAt | String | 否 | 订单过期时间,格式:YYYY-MM-DDTHH:mm:ss+08:00 |
5.3 返回说明
成功时返回预支付交易会话标识(prepay_id),用于后续接口调用,有效期为2小时。示例:
{
"prepay_id": "wx201410272009395522657a690389285100"
}