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

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

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

39

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

			this.productList.push({
				name: '消耗性产品:金牌赞助50元',
				id: this.isDebug() ? "uniappx.consumable.sponsor_50" : "uniappx.consumable.sponsor50",
				quantity: 1
			} as PayItem);
60

61 62 63 64
			this.productList.push({
				name: '非消耗性产品: 赞助特效1元',
				id: this.isDebug() ? "uniappx.nonconsumable.sponsorskin_1" : "uniappx.nonconsumable.sponsorskin1"
			} as PayItem);
65

66 67 68 69
			this.productList.push({
				name: '自动续期订阅产品:每月定期赞助1元',
				id: this.isDebug() ? "uniappx.autorenewable.monthly_1" : "uniappx.autorenewable.monthly1"
			} as PayItem);
70

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

76 77 78 79
			this.productList.push({
				name: '测试不存在的产品',
				id: "uniappx.nonrenewable.none"
			} as PayItem);
80
    },
81 82 83 84 85 86 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
    methods: {
      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
      },
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
      requestVirtualPayment(e : PayItem) {
        uni.showLoading({
          title: "",
          mask: true
        });
        uni.requestVirtualPayment({
          apple: {
            productId: e.id,
            appAccountToken: "orderId+accountId",
            quantity: e.quantity ?? 1
          },
          success: (res) => {
            uni.hideLoading()
            console.log("购买成功:该productId= " + res.apple?.payment.productId)
            //TODO: 开发者server验证逻辑

            //经过开发者server验证成功后请结束该交易
            uni.finishedTransaction({
              transaction: res.apple,
              success: (r) => {
                console.log("关单成功, 该productId= " + res.apple?.payment.productId)
              },
              fail: (e) => {
                console.log("关单失败, 该productId= " + res.apple?.payment.productId)
              }
            })
            uni.showToast({
              title: "购买成功:" + res.apple?.payment.productId,
              icon: 'error'
            })
          },
          fail: (e) => {
            uni.hideLoading()
            console.log("购买失败:errSubject= " + e.errSubject + ", errCode= " + e.errCode + ", errMsg= " + e.errMsg)
            uni.showToast({
              title: "购买失败:errCode=" + e.errCode,
              icon: 'error'
            })
          }
        })
      },
      restoreCompletedTransactions() {
        uni.showLoading({
          title: "",
          mask: true
        });
        uni.restoreCompletedTransactions({
          success: (res) => {
            uni.hideLoading()
            console.log("restore成功的交易个数:" + res.transactions.length)
            res.transactions.forEach(transaction => {

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

              console.log("restore成功的交易productId= " + transaction.payment.productId)
            })
            uni.showToast({
              title: "restore成功的交易个数:" + res.transactions.length,
              icon: 'error'
            })
          },
          fail: (e) => {
            uni.hideLoading()
            console.log("restore失败:errSubject= " + e.errSubject + ", errCode= " + e.errCode + ", errMsg= " + e.errMsg)
            uni.showToast({
              title: "restore失败:errCode=" + e.errCode,
              icon: 'error'
            })
          }
        })
      },
      getUnfinishedTransactions() {
        uni.showLoading({
          title: "",
          mask: true
        });
        uni.getUnfinishedTransactions({
          success: (res) => {
192
            uni.hideLoading()
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
            console.log("获取未结束的订单列表个数:" + res.transactions.length)
            res.transactions.forEach(transaction => {

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

              //经过开发者server验证成功后请结束该交易
              uni.finishedTransaction({
                transaction: transaction,
                success: (r) => {
                  console.log("关单成功, 该productId= " + transaction.payment.productId)
                },
                fail: (e) => {
                  console.log("关单失败, 该productId= " + transaction.payment.productId)
                }
              })
            })

            uni.showToast({
              title: "获取未结束的订单列表个数:" + res.transactions.length,
              icon: 'error'
            })
          },
          fail: (e) => {
            uni.hideLoading()
            console.log("获取未结束的订单列表失败:errSubject= " + e.errSubject + ", errCode= " + e.errCode + ", errMsg= " + e.errMsg)
            uni.showToast({
              title: "获取未结束的订单列表失败:errCode= " + e.errCode,
              icon: 'error'
            })
          }
        })
      }
    }
  }
</script>

<style>

</style>