开发日记 —— 苹果支付指南

· 0 · 0 ·
个人开发者 苹果 flutter 支付
超级浩码
作者
超级浩码
数字手艺人,独立开发体验师。
目录

上一篇文章分享了实践 Apple 登录的开发过程。 今天主要分享一下 Apple 支付的实践。

前言 #

本次实践中,笔者采用了 订阅 + 一次性付费 的模式。用户可根据自己的需求,选择会员订阅周期。从大部分开发者角度来说,订阅模式是比较常见的,因为订阅更有力于APP的长期发展。

Alt text


购买项配置 #

进入 开发者后台配置

  1. App 内购买项目 中创建 永久会员

  2. 订阅 创建订阅组,后分别 月度会员 年度会员

Alt text

需要注意两点:

  • 创建的购买项需要设置多语言,否则会出现报错 缺少元数据
  • 审核信息的截图有设备尺寸限制,可参考官方文档:https://developer.apple.com/help/app-store-connect/reference/screenshot-specifications

客户端 #

我使用 in_app_purchase 插件,在客户端进行支付。可以运行插件的example进行测试。成功运行效果如下:

Alt text

具体细节可以参考插件文档,需要注意的是,我们需要如何进行iOS订单的验证。 通过插件的demo我们看到默认返回true,所以这部分逻辑需要开发者自己实现。

  Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) async {
    // IMPORTANT!! Always verify a purchase before delivering the product.
    // For the purpose of an example, we directly return true.
    
    return Future<bool>.value(true);
  }

通过方法返回的类型可以得到:

class PurchaseVerificationData {
  /// ...

  /// The data used for local verification.
  ///
  /// The data is formatted according to the specifications of the respective
  /// store. You can use the [source] field to determine the store from which
  /// the data originated and proces the data accordingly.
  final String localVerificationData;

  /// The data used for server verification.
  final String serverVerificationData;
}

我们看到 localVerificationData 用于本地验证,serverVerificationData 用于服务器验证。


    final verificationData =
        purchaseDetails.verificationData.serverVerificationData;

    final Dio dio = Dio();
    dio.options.headers['Accept'] = 'application/json';
    dio.options.headers['Content-Type'] = 'application/json';
    var response = await dio.post('https://buy.itunes.apple.com/verifyReceipt',
        data: {
          'password': password,
          'receipt-data': verificationData
        });
    var _response = json.decode(response.toString());
    if (_response["status"] == 21007) {
      var response = await dio
          .post('https://sandbox.itunes.apple.com/verifyReceipt', data: {
        'password': password,
        'receipt-data': verificationData
      });
    }
    if (_response["status"] == 0) {
      return Future<bool>.value(true);
    } else {
      return Future<bool>.value(false);
    }

以前苹果提供了一个验证接口,可以跳过服务端进行验证,可惜在去年5月份被标记 Deprecated(已弃用),虽然目前看来还是可以使用,但是保不齐哪天就被苹果给删掉了。

Alt text

通过文档我们得知:

该接口已弃用。要验证服务器上的收据,请按照在服务器上的设备上验证收据中的步骤操作。要在不使用收据的情况下验证服务器上的应用内购买,请调用App Store Server API为您的客户获取 Apple 签名的交易和订阅信息,或验证您的应用获取的签名数据。您还可以从App Store Server Notifications V2端点获取相同的签名交易和订阅信息 。

所以需要改用 App Store Server API 进行验证。

获取交易信息 #

https://developer.apple.com/documentation/appstoreserverapi/get_transaction_info 根据文档的描述,我们得知此接口我们可以获取 包含签名的单个交易信息的结果

接着,通过苹果开发后台进行配置下载 私钥匙文件 + KeyID + BundleID + Issuer 进行验签比对订单号等数据判断交易是否成功。

获取历史交易信息 #

https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history 根据此接口我们可以获取包含签名的多个交易信息的结果,同样验签后获取详细数据。

我们可以通过此接口进行订阅到期续费情况等数据进行判断。


验签及API配置 #

在此页面我们可以获取验签需要的数据 私钥匙文件、 KeyID + BundleID + Issuer

Alt text

创建沙盒账号后可进行购买订阅的测试,不会收取费用。

Alt text


内购被拒 #

另外,在完成所有工作发布可能会被拒,因为我之前没有订阅经验,所以遇到了一些问题。

Alt text

如果做了订阅我建议你完成以下步骤,如果这些步骤都做到了,那么大概率是不会被拒的。

  1. 在付费页面提供隐私政策及使用条款的入口。
  2. 在使用条款中明确说明和介绍你的订阅服务,包含的服务内容、订阅周期、退订、取消订阅等信息。
  3. 在APP详情页中,提供订阅服务的详细说明。
  4. 提供恢复购买的功能。

如果还是不知道如何做,可以参考一些其他的APP,一般在他们的App详情页和使用条款中都有订阅相关的说明。


总结 #

理论上来说,获取交易信息 获取历史交易信息 这两个接口的数据都可以放在客户端本地调用,只是验证这一步放在服务端去做比较符合逻辑。

无论是全部交易接口在服务端还是验签在服务端,都可能被劫持,即在返回客户端前,对数据进行加工处理,比如修改交易状态来欺瞒客户端。

所以,最好是对接口数据进行加密。我采用对请求参数返回结构进行 AES 加密,及时数据被劫持也无法进行修改。

如果没有服务端,极端的方式是把验签放在客户端进行能跑通,因安全性问题不推荐这么做。





评论