UniApp接入ApplePay

applepay.webp

背景

最近一个app项目中需要对接Apple Pay内购,因为也是第一次对接,所以记录下过程。

上传应用版本

添加内购项目。

  • 跟着表单提交即可。
  • 注意上传审核信息截屏和备注,提交完后当状态为准备提交即可。
  • 产品ID是唯一字母数字ID。一旦该ID添加过,即使删除该产品,此ID也无法再次使用。
    image.png
    image.png
  • 在版本中勾选上面添加好的内购项目
    image.png

完善协议/税务

image.png

  • “免费app”默认的有效期,是和账号的到期时间保持一致的,而“付费应用程序”则需要进行进一步设置,点击右侧“查看并同意条款”。
  • 填写地址信息,地址必须是英文/拼音,如果地址太长可以分2行填写。
  • 完善银行卡等信息,持卡人姓名必须是英文/拼音。如果银行收款信息不清楚可以向银行致电查询。
  • 设置【税务协议,美国税务协议】,详细流程点这里
  • 审核通过之后状态为有效即可进行下一步
    image.png

证书配置

  • 证书需要勾选,配置一个merchant。

image.png

代码对接

  • 配置文件中勾选Apple内应用支付。这里需要注意,如果不全是虚拟商品或服务的(苹果的内购条件),则可以同时集成别的支付,如微信支付宝,反之则不要勾选,不然苹果会认为你有隐藏的功能会绕过内购。
    image.png
  • 调用 plus.payment.getChannels 来获取支付通道
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
iospay() {
const that = this
uni.showLoading({
title: '检测支付环境...',
mask: true
})
plus.payment.getChannels((channels) => {
// console.log('channels=>', channels)
for (var i in channels) {
// 判断是否苹果支付
if (channels[i].id === 'appleiap') {
that.iapChannel = channels[i]
that.requestOrder()
}
}

if (that.iapChannel == '') {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '暂不支持苹果 iap 支付'
});
}
})
}
  • 调用上一步拿到对象的requestOrder方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    requestOrder() {
    console.log('获取订单信息中...')
    const that = this
    // ids 是平台申请拿到的内购商品的id
    var ids = [that.productId];
    that.iapChannel.requestOrder(ids, function(event) {
    // 获取订单信息成功回调方法
    console.log('获取订单信息成功=>', event)
    uni.hideLoading()
    that.topay(that.productId)
    }, function(erroemsg) {
    // 获取订单信息失败回调方法
    console.log('requestOrder failed: ' + JSON.stringify(erroemsg));
    uni.hideLoading()
    uni.showToast({
    title: "获取支付通道失败:" + errormsg.message,
    icon: 'none'
    })
    });
    }
  • 最后调用uni.requestPayment拿到后端接口需要的交易id校验体
  • 注意:发起支付必须要在requestOrder之后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    topay(id) {
    console.log('发起支付中...')
    const that = this
    uni.showLoading({
    title: '充值中请勿离开',
    mask: true
    })
    uni.requestPayment({
    provider: 'appleiap',
    orderInfo: {
    productid: id // 内购产品的product_id
    },
    success: (res => {
    console.log('支付成功')
    uni.hideLoading()
    const orderId = that.orderId //这个订单id 是由后端返回的
    const transactionId = res.transactionIdentifier //交易id
    const payload = res.transactionReceipt //校验体
    //给自己的服务端通知,服务端做校验和支付成功的业务
    let url = '/api/user/iosNotify';
    let parames = {
    transactionId: transactionId,
    payload: payload,
    orderId: orderId
    };
    console.log('iosNotifyParames=>', parames)
    this.$myRequest({
    url: url,
    method: 'GET',
    data: parames
    }).then(res => {
    uni.showToast({
    icon: 'success',
    title: '支付成功'
    })
    });
    }),
    fail: (e) => {
    console.log('支付失败=>', e)
    uni.hideLoading()
    uni.showModal({
    content: "支付失败",
    showCancel: false
    })
    }
    })
    }

过程中遇到的问题

  • 测试支付需要配置沙箱测试账号

    新的内购产品上线之前,测试人员一般需要对内购产品进行测试,但是内购涉及到钱,所以苹果为内购测试提供了 沙箱测试账号 的功能,Apple Pay 推出之后 沙箱测试账号,也可以用于 Apple Pay 支付的测试,沙箱测试账号 简单理解就是:只能用于内购和 Apple Pay 测试功能的 Apple ID,它并不是真实的 Apple ID。

    填写沙箱测试账号信息需要注意以下几点:

    • 电子邮件不能是别人已经注册过 AppleID 的邮箱
    • 电子邮箱可以不是真实的邮箱,但是必须符合邮箱格式
    • App Store 地区的选择,测试的时候弹出的提示框以及结算的价格会按照沙箱账号选择的地区来,建议测试的时候新建几个不同地区的账号进行测试!!!

    沙箱账号测试的使用:

    • 首先沙箱测试账号必须在真机环境下进行测试,并且是 adhoc 证书或者 develop 证书签名的安装包,沙盒账号不支持直接从 App Store 下载的安装包
    • 去真机的 App Store 退出真实的 Apple ID 账号,退出之后并不需要在App Store 里面登录沙箱测试账号
    • 然后去 App 里面测试购买商品,会弹出登录框,选择 使用现有的 Apple ID,然后登录沙箱测试账号,登录成功之后会弹出购买提示框,点击 购买,然后会弹出提示框完成购买。
  • requestOrder函数成功和失败的回调都没响应

    • 检查内购产品和税务是否完善
  • requestPayment页面提示支付成功,但是success回调无响应

    • 沙箱的回调特别特别慢且随缘…
    • 支付成功后,杀死app重新进入,再次唤起支付,上次的回调有‘几率’拿到。

个人总结,如有不妥之处,烦请指出。