virtual-payment.uvue 9.5 KB
Newer Older
1
<template>
2 3 4
  <!-- #ifdef APP -->
  <scroll-view style="flex: 1;">
  <!-- #endif -->
5
    <page-head title="苹果虚拟支付"></page-head>
6 7 8 9 10 11 12 13 14 15 16
    <view style="padding-left: 20px; padding-right: 20px;">
      <text>
        requestVirtualPayment api 适用于消耗性类型、非消耗性类型、自动续期订阅类型、非自动续期订阅类型产品的购买。\n\n
        1. 消耗性类型:该类型的产品可以设置购买数量,默认是1,最大值是10; \n
        2. 非消耗性类型、自动续期订阅类型、非自动续期订阅类型: 这些类型的产品购买数量设置无效,数量只能是1; \n
        3. 非消耗性类型:该类型产品一个appleId只能购买一次,可以在任何登陆该appleId账号的设备上restore获取。
      </text>
      <button style="margin-top: 20px;" type="primary" v-for="(item,index) in productList" :key="index"
        @click="requestVirtualPayment(item)">{{item.name}}</button>

      <text>
17
        \nrestoreTransactions api 适用于非消耗性类型、自动续期订阅类型、非自动续期订阅类型产品的购买。\n\n
18 19 20 21 22
        1. 非消耗性类型: 返回每个已购买的非消耗性类型产品的购买记录;\n
        2. 自动续期订阅类型: 返回每个已购买的自动续期订阅类型产品的最新购买记录,沙盒账号最多可自动续订 12 次;\n
        3. 非自动续期订阅类型: 返回每个已购买的非自动续期订阅类型产品的最新购买记录, 该类型订阅可以连续多次购买,开发者需要自己的后台计算产品过期的时间。\n
        Note: 不能用来恢复消耗性类型的购买记录。
      </text>
23
      <button style="margin-top: 20px;" type="primary" @click="restoreTransactions">恢复购买订单列表</button>
24 25 26 27 28 29

      <text>
        \ngetUnfinishedTransactions api 适用于获取未完成的各种类型产品的购买记录(用来防止丢单)。\n\n
        1. 比如用户点击购买已经付款成功,但因网络、手机没电关机等特殊情况,Apple IAP
        没有返回客户端对应的购买凭证,从而导致无法finish该交易导致的丢单,可以在需要的地方调用该api获得此类未finished的交易记录; \n
        2. 针对消耗性类型产品交易,只能通过该api获取未finished的交易,防止丢单;\n
30
        3. 对于其他类型产品未finished交易, 不仅可以通过该api获取,也可以通过restoreTransactions api (也可获取已经finished的交易)获取;
31 32 33 34 35 36 37
      </text>
      <button style="margin-top: 20px; margin-bottom: 50px;" type="primary"
        @click="getUnfinishedTransactions">获取未结束的订单列表</button>
    </view>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
38 39
</template>

40

41 42 43 44 45
<script>
  export type PayItem = { id : string, name : string, quantity ?: number }
  export default {
    data() {
      return {
46
        productList: [] as PayItem[],
47
        virtualPaymentManager: Object
48 49 50
      }
    },
    onLoad: function () {
51
      this.virtualPaymentManager = uni.getVirtualPaymentManager()
52
      this.initProductList()
53
    },
54 55 56
    methods: {
      initProductList() {
        this.productList.push({
57
          name: '消耗性产品:个人赞助1元',
58
          id: this.isDebug() ? "uniappx.consumable.sponsor_1" : "uniappx.consumable.sponsor1",
59
          quantity: 1
60 61 62
        } as PayItem);

        this.productList.push({
63
          name: '消耗性产品:金牌赞助5元, 数量=2',
64
          id: this.isDebug() ? "uniappx.consumable.sponsor_50" : "uniappx.consumable.sponsor50",
65
          quantity: 2
66 67 68 69 70 71
        } as PayItem);

        this.productList.push({
          name: '非消耗性产品: 赞助特效1元',
          id: this.isDebug() ? "uniappx.nonconsumable.sponsorskin_1" : "uniappx.nonconsumable.sponsorskin1"
        } as PayItem);
72 73 74 75 76

        // this.productList.push({
        //   name: '自动续期订阅产品:每月定期赞助1元',
        //   id: this.isDebug() ? "uniappx.autorenewable.monthly_1" : "uniappx.autorenewable.monthly1"
        // } as PayItem);
77 78 79 80 81 82

        this.productList.push({
          name: '非自动续期订阅产品:月赞助1元',
          id: this.isDebug() ? "uniappx.nonrenewable.monthly_1" : "uniappx.nonrenewable.monthly1"
        } as PayItem);

83 84 85 86
        // this.productList.push({
        //   name: '测试不存在的产品',
        //   id: "uniappx.nonrenewable.none"
        // } as PayItem);
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
      },
      getPackageName() : string {
        const res = uni.getAppBaseInfo();
        let packageName : string = ""

        // #ifdef APP-ANDROID
        packageName = res.packageName
        // #endif

        // #ifdef APP-IOS
        packageName = res.bundleId
        // #endif

        return packageName
      },
      isDebug() : boolean {
        if (this.getPackageName() == 'io.dcloud.uniappx') {
          return true
        }
        return false
      },
      isProd() : boolean {
        if (this.getPackageName() == 'io.dcloud.hellouniappx') {
          return true
        }
        return false
      },
      isCustom() : boolean {
        if (this.isDebug() == false && this.isProd() == false) {
          return true
        }
        return false
119
      },
120 121 122 123 124
      requestVirtualPayment(e : PayItem) {
        uni.showLoading({
          title: "",
          mask: true
        });
125

DCloud-WZF's avatar
DCloud-WZF 已提交
126
        uni.requestVirtualPayment({
127
          //需要将orderId转换为如下符合UUID规则的字符串,然后赋值给参数appAccountToken, 传入不符合UUID规则的字符串无效
128 129
          apple: {
            productId: e.id,
130
            appAccountToken: "123eaaaa-e89b-12d3-a456-42661417400b",
131
            quantity: e.quantity ?? 1,
132 133 134
          },
          success: (res) => {
            uni.hideLoading()
135
            console.log("购买成功:该productId= " + res.apple?.productId)
136 137 138
            //TODO: 开发者server验证逻辑

            //经过开发者server验证成功后请结束该交易
139
            uni.showToast({
140
              title: "购买成功:" + res.apple?.productId,
141 142 143
              icon: 'success'
            })

144
            this.virtualPaymentManager.finishTransaction({
145 146
              transaction: res.apple,
              success: (r) => {
147
                console.log("关单成功, 该productId= " + res.apple?.productId)
148 149
              },
              fail: (e) => {
150
                console.log("关单失败, 该productId= " + res.apple?.productId)
151 152 153 154 155 156 157
              }
            })
          },
          fail: (e) => {
            uni.hideLoading()
            console.log("购买失败:errSubject= " + e.errSubject + ", errCode= " + e.errCode + ", errMsg= " + e.errMsg)
            uni.showToast({
158
              title: "购买失败错误码:" + e.errCode,
159 160 161 162 163
              icon: 'error'
            })
          }
        })
      },
164
      restoreTransactions() {
165 166 167 168
        uni.showLoading({
          title: "",
          mask: true
        });
169

170
        this.virtualPaymentManager.restoreTransactions({
171 172 173 174 175 176 177
          success: (res) => {
            uni.hideLoading()
            console.log("restore成功的交易个数:" + res.transactions.length)
            res.transactions.forEach(transaction => {

              //TODO: 开发者server验证逻辑

178
              console.log("restore成功的交易productId= " + transaction.productId)
179 180 181
            })
            uni.showToast({
              title: "restore成功的交易个数:" + res.transactions.length,
182
              icon: 'success'
183 184 185 186 187 188
            })
          },
          fail: (e) => {
            uni.hideLoading()
            console.log("restore失败:errSubject= " + e.errSubject + ", errCode= " + e.errCode + ", errMsg= " + e.errMsg)
            uni.showToast({
189
              title: "restore失败错误码:" + e.errCode,
190 191 192 193 194 195 196 197 198 199
              icon: 'error'
            })
          }
        })
      },
      getUnfinishedTransactions() {
        uni.showLoading({
          title: "",
          mask: true
        });
200

201
        this.virtualPaymentManager.getUnfinishedTransactions({
202
          success: (res) => {
203
            uni.hideLoading()
DCloud-WZF's avatar
DCloud-WZF 已提交
204 205 206 207 208
            console.log("获取未结束的订单列表个数:" + res.transactions.length)
            uni.showToast({
              title: "获取未结束的订单列表个数:" + res.transactions.length,
              icon: 'success'
            })
209

210 211
            res.transactions.forEach(transaction => {

212
              console.log("getUnfinishedTransactions成功的交易productId= " + transaction.productId)
213 214 215
              //TODO: 开发者server验证逻辑

              //经过开发者server验证成功后请结束该交易
216
              this.virtualPaymentManager.finishTransaction({
217 218
                transaction: transaction,
                success: (r) => {
219
                  console.log("关单成功, 该productId= " + transaction.productId)
220 221
                },
                fail: (e) => {
222
                  console.log("关单失败, 该productId= " + transaction.productId)
223 224 225 226 227 228 229 230
                }
              })
            })
          },
          fail: (e) => {
            uni.hideLoading()
            console.log("获取未结束的订单列表失败:errSubject= " + e.errSubject + ", errCode= " + e.errCode + ", errMsg= " + e.errMsg)
            uni.showToast({
231
              title: "获取未结束的订单列表失败错误码" + e.errCode,
232 233 234 235 236 237 238 239 240 241 242 243
              icon: 'error'
            })
          }
        })
      }
    }
  }
</script>

<style>

</style>