0.1.3 • Published 3 years ago

waft-payment v0.1.3

Weekly downloads
-
License
MIT
Repository
-
Last release
3 years ago

Waft 收银台

Waft 应用提供收银台能力。

功能特性

  • 支持 支付宝 扫码支付
  • 支持两种展示形式
    • 内嵌:极简的二维码样式
    • 浮窗:内置统一的浮窗样式,除了二维码,同时展示更多的订单信息(订单金额、商户名称等)

接入说明

安装

npm install --save waft-payment

API

参数说明

属性类型必填说明
sellerIdi64商户淘宝 ID
contentstring支付内容(内容的字段说明见下方),以 JSON 字符串表示
signstring根据商户 RSA 私钥对 content 的签名,平台会根据商户提交的公钥进行验签(加签、验签方式见下方)
sizei64(仅内嵌形式下可用)二维码的宽高,默认为 200
onStatusFunction订单支付状态回调(状态枚举值见下方)
requestNewOrderFunction(仅浮窗形式下可用)请求订单刷新时,该回调会执行

content 支付内容字段说明:

属性类型必填说明
sellerIdi64商户淘宝 ID
amounti64订单金额 (单位:分)
outItemIdstring商户的商品 ID
outItemNamestring商户售卖的商品名称
outOrderIdstring商户订单号
payExpireTimestring订单的超时时间(如: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 回调

点击查看参考文档

0.1.3

3 years ago

0.1.2

3 years ago

0.1.1

3 years ago

0.1.0

3 years ago