0.1.3 • Published 3 years ago
waft-payment v0.1.3
Waft 收银台
为 Waft 应用提供收银台能力。
功能特性
- 支持 支付宝 扫码支付
- 支持两种展示形式
- 内嵌:极简的二维码样式
- 浮窗:内置统一的浮窗样式,除了二维码,同时展示更多的订单信息(订单金额、商户名称等)
接入说明
- 接入收银台之前,需完成天猫精灵应用商业化入驻流程。
- Waft 容器版本要求:>= 1.3。如何判断当前容器版本?
安装
npm install --save waft-payment
API
参数说明
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
sellerId | i64 | 是 | 商户淘宝 ID |
content | string | 是 | 支付内容(内容的字段说明见下方),以 JSON 字符串表示 |
sign | string | 是 | 根据商户 RSA 私钥对 content 的签名,平台会根据商户提交的公钥进行验签(加签、验签方式见下方) |
size | i64 | 否 | (仅内嵌形式下可用)二维码的宽高,默认为 200 |
onStatus | Function | 否 | 订单支付状态回调(状态枚举值见下方) |
requestNewOrder | Function | 是 | (仅浮窗形式下可用)请求订单刷新时,该回调会执行 |
content
支付内容字段说明:
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
sellerId | i64 | 是 | 商户淘宝 ID |
amount | i64 | 是 | 订单金额 (单位:分) |
outItemId | string | 是 | 商户的商品 ID |
outItemName | string | 是 | 商户售卖的商品名称 |
outOrderId | string | 是 | 商户订单号 |
payExpireTime | string | 是 | 订单的超时时间(如:2049-12-30 23:59:59) |
订单状态(status
)说明:
- 等待未超时:
状态值 | 说明 |
---|---|
100 | 天猫精灵侧订单创建成功 |
200 | 交易创单成功 |
250 | 交易创单失败 |
300 | 支付创单成功 |
350 | 支付创单失败 |
400 | 用户支付成功 |
450 | 用户支付失败 |
470 | 用户待支付 |
this.addEventListener('onStatus', (e: Event) => {
const current = (e as MessageEvent).data
// { "status": 300 }
// { "status": 350, "failMsg": "订单创建失败的原因" }
console.log(current)
})
- 等待超时:
超时指的是订单创建成功后,长时间处于未支付状态。目前的等待时长约 3-4 分钟,超过这个时间,需创建新的订单。
this.addEventListener('onStatus', (e: Event) => {
const current = (e as MessageEvent).data
// { "isTimeout": true }
console.log(current)
})
如何使用
在需要使用支付组件的页面(比如 pages/index.json
)中,声明以下组件:
x-payment-qrcode
以内嵌形式展示支付二维码x-payment-drawer
以浮窗形式展示支付二维码
{
"usingComponents": {
"x-payment-qrcode": "waft-payment/assembly/qrcode/qrcode",
"x-payment-drawer": "waft-payment/assembly/drawer/drawer"
}
}
在 pages/index.json
中添加相关业务逻辑处理:
import { Page, Props, Event, MessageEvent, console } from 'waft'
import { JSONObject } from 'waft-json'
import { PaymentDrawer } from 'waft-payment'
export class Demo extends Page {
constructor(props: Props) {
super(props)
const state = new JSONObject()
state.set('sellerId', 0)
state.set('content', '')
state.set('sign', '')
this.setState(state)
// 创建订单,并渲染内嵌支付二维码
this.addEventListener('createEmbeddedPayment', (e: Event, target) => {
const _this = target as Demo
_this.createEmbeddedQrCode()
})
// 创建订单,并打开浮窗展示支付二维码
this.addEventListener('createPopupPayment', (e: Event, target) => {
const _this = target as Demo
_this.createPopupQrCode()
})
// (仅在浮窗形式下用到)点击刷新当前订单
this.addEventListener('requestNewOrder', (e: Event, target) => {
const _this = target as Demo
_this.refreshPopupQrCode()
})
// 这里可获取当前订单的状态
this.addEventListener('onStatus', (e: Event) => {
const current = (e as MessageEvent).data
// { "status": 300 }
// { "status": 350, "failMsg": "订单创建失败的原因" }
// { "isTimeout": true } 等待超时,订单仍未支付
console.log(current)
})
}
createEmbeddedQrCode(): void {
/**
* 注意:内嵌二维码 `didMount` 后不会响应后续 `props` 的更新
* 如果你想更新订单,需先将组件卸载(比如,本例子中可将订单参数重置为空)
* 然后根据新的参数 (content / sign) 再渲染新的组件
*/
if (this.state.getString(sign) != '') {
const nextState = new JSONObject()
nextState.set('sellerId', 0)
nextState.set('content', '')
nextState.set('sign', '')
this.setState(nextState)
}
setTimeout((_, target) => {
const _this = target as Demo
const orderParams = _this.generateOrderParams()
_this.setState(orderParams)
}, 0, this)
}
createPopupQrCode(): void {
const orderParams = this.generateOrderParams()
const sellerId = orderParams.getInteger('sellerId')
const content = orderParams.getString('content')
const sign = orderParams.getString('sign')
PaymentDrawer.open(sellerId, content, sign)
}
refreshPopupQrCode(): void {
const orderParams = this.generateOrderParams()
const sellerId = orderParams.getInteger('sellerId')
const content = orderParams.getString('content')
const sign = orderParams.getString('sign')
PaymentDrawer.refresh(sellerId, content, sign)
}
generateOrderParams(): JSONObject {
const sellerId = 123 // 商户淘宝 ID
const contentParams = new JSONObject()
contentParams.set('sellerId', sellerId) // 商户淘宝ID
contentParams.set('amount', 1) // 订单金额:1 分钱
contentParams.set('outItemId', '123') // 商品 ID
contentParams.set('outItemName', '商品名称') // 商品名称
contentParams.set('outOrderId', 'abc') // 订单ID
/**
* 订单的过期时间:超过这个时间,该笔订单将不能被支付
* 注意:每个商户的 “待支付订单” 有数量限制
* 建议不要将过期时间设置得太久,以避免占用限额,导致无法创建新的订单
*/
contentParams.set('payExpireTime', '2049-12-30 23:59:59')
const content = contentParams.toString() // 该字段为 JSON 字符串形式
// 根据 `content` 生成签名
const sign = 'xxx'
const orderParams = new JSONObject()
orderParams.set('sellerId', sellerId)
orderParams.set('content', content)
orderParams.set('sign', sign)
return orderParams
}
}
在 pages/index.axml
中使用组件:
<!-- 渲染内嵌形式的支付二维码 -->
<view>
<view onTap="createEmbeddedPayment">创建订单(内嵌二维码)</view>
<x-payment-qrcode
a:if="{{ sellerId && content && sign }}"
sellerId="{{ sellerId }}"
content="{{ content }}"
sign="{{ sign }}"
onStatus="onPaySuccess"
></x-payment-qrcode>
</view>
<!-- 以浮窗形式打开支付二维码 -->
<view>
<view onTap="createPopupPayment">创建订单(浮窗)</view>
<x-payment-drawer
requestNewOrder="requestNewOrder"
onStatus="onPaySuccess"
></x-payment-drawer>
</view>
加签验签说明
// 通过支付宝 SDK 提供的工具类进行加签验签操作
// 可以在 maven 中央仓库下载到,版本选择 3.7.80.ALL 以上即可
// https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java
<dependency>
<groupId>alipay-sdk-java</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.7.80.ALL</version>
</dependency>
// content:需要加签的业务参数,以 JSON 字符串表示
// 加签
String sign = AlipaySignature.rsaSign(content, sysPriKey, "UTF-8", "RSA");
// 验签
boolean signCheck = AlipaySignature.rsaCheck(content, sign2, sysPubKey, "UTF-8", "RSA");
支付状态 HTTP 回调
点击查看参考文档。