Skip to content

Commit eae34bb

Browse files
committed
introduce error handling
* purchase call and * transction finish
1 parent af9eb87 commit eae34bb

File tree

11 files changed

+333
-31
lines changed

11 files changed

+333
-31
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ See also [bevy_ios_notifications](https://github.com/rustunit/bevy_ios_notificat
1919
* does not return locally un-signed/un-verified transactions
2020

2121
## Todo
22+
* forward transaction.id inside of successful purchase result to allow early finish
2223
* support subscription product type
23-
* catch exceptions in swift functions and report errors to rust
24+
* remaining error handling in: `ios_iap_transactions_all` and `ios_iap_products`
2425
* allow access to signature for remote verification
2526
* support offers
2627
* support family sharing

RustXcframework.xcframework/ios-arm64/Headers/bevy_ios_iap.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
// File automatically generated by swift-bridge.
22
#include <stdint.h>
33
#include <stdbool.h>
4+
typedef struct IosIapTransactionFinished IosIapTransactionFinished;
5+
void __swift_bridge__$IosIapTransactionFinished$_free(void* self);
6+
7+
void* __swift_bridge__$Vec_IosIapTransactionFinished$new(void);
8+
void __swift_bridge__$Vec_IosIapTransactionFinished$drop(void* vec_ptr);
9+
void __swift_bridge__$Vec_IosIapTransactionFinished$push(void* vec_ptr, void* item_ptr);
10+
void* __swift_bridge__$Vec_IosIapTransactionFinished$pop(void* vec_ptr);
11+
void* __swift_bridge__$Vec_IosIapTransactionFinished$get(void* vec_ptr, uintptr_t index);
12+
void* __swift_bridge__$Vec_IosIapTransactionFinished$get_mut(void* vec_ptr, uintptr_t index);
13+
uintptr_t __swift_bridge__$Vec_IosIapTransactionFinished$len(void* vec_ptr);
14+
void* __swift_bridge__$Vec_IosIapTransactionFinished$as_ptr(void* vec_ptr);
15+
416
typedef struct IosIapStorefront IosIapStorefront;
517
void __swift_bridge__$IosIapStorefront$_free(void* self);
618

@@ -92,6 +104,7 @@ void* __swift_bridge__$IosIapProductType$new_auto_renewable(void);
92104
void* __swift_bridge__$IosIapPurchaseResult$success(void);
93105
void* __swift_bridge__$IosIapPurchaseResult$canceled(void);
94106
void* __swift_bridge__$IosIapPurchaseResult$pending(void);
107+
void* __swift_bridge__$IosIapPurchaseResult$error(void* e);
95108
void* __swift_bridge__$IosIapEnvironment$sandbox(void);
96109
void* __swift_bridge__$IosIapEnvironment$production(void);
97110
void* __swift_bridge__$IosIapEnvironment$xcode(void);
@@ -101,9 +114,13 @@ void __swift_bridge__$IosIapTransaction$add_revocation(void* t, uint64_t date);
101114
void __swift_bridge__$IosIapTransaction$add_expiration(void* t, uint64_t date);
102115
void* __swift_bridge__$IosIapTransactionReason$renewal(void);
103116
void* __swift_bridge__$IosIapTransactionReason$purchase(void);
117+
void* __swift_bridge__$IosIapTransactionFinished$finished(void* t);
118+
void* __swift_bridge__$IosIapTransactionFinished$error(void* e);
119+
void* __swift_bridge__$IosIapTransactionFinished$unknown(uint64_t id);
104120
void __swift_bridge__$products_received(void* products);
105121
void __swift_bridge__$all_transactions(void* transactions);
106122
void __swift_bridge__$purchase_processed(void* result);
107123
void __swift_bridge__$transaction_update(void* t);
124+
void __swift_bridge__$transaction_finished(void* t);
108125

109126

RustXcframework.xcframework/ios-arm64_x86_64-simulator/Headers/bevy_ios_iap.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
// File automatically generated by swift-bridge.
22
#include <stdint.h>
33
#include <stdbool.h>
4+
typedef struct IosIapTransactionFinished IosIapTransactionFinished;
5+
void __swift_bridge__$IosIapTransactionFinished$_free(void* self);
6+
7+
void* __swift_bridge__$Vec_IosIapTransactionFinished$new(void);
8+
void __swift_bridge__$Vec_IosIapTransactionFinished$drop(void* vec_ptr);
9+
void __swift_bridge__$Vec_IosIapTransactionFinished$push(void* vec_ptr, void* item_ptr);
10+
void* __swift_bridge__$Vec_IosIapTransactionFinished$pop(void* vec_ptr);
11+
void* __swift_bridge__$Vec_IosIapTransactionFinished$get(void* vec_ptr, uintptr_t index);
12+
void* __swift_bridge__$Vec_IosIapTransactionFinished$get_mut(void* vec_ptr, uintptr_t index);
13+
uintptr_t __swift_bridge__$Vec_IosIapTransactionFinished$len(void* vec_ptr);
14+
void* __swift_bridge__$Vec_IosIapTransactionFinished$as_ptr(void* vec_ptr);
15+
416
typedef struct IosIapStorefront IosIapStorefront;
517
void __swift_bridge__$IosIapStorefront$_free(void* self);
618

@@ -92,6 +104,7 @@ void* __swift_bridge__$IosIapProductType$new_auto_renewable(void);
92104
void* __swift_bridge__$IosIapPurchaseResult$success(void);
93105
void* __swift_bridge__$IosIapPurchaseResult$canceled(void);
94106
void* __swift_bridge__$IosIapPurchaseResult$pending(void);
107+
void* __swift_bridge__$IosIapPurchaseResult$error(void* e);
95108
void* __swift_bridge__$IosIapEnvironment$sandbox(void);
96109
void* __swift_bridge__$IosIapEnvironment$production(void);
97110
void* __swift_bridge__$IosIapEnvironment$xcode(void);
@@ -101,9 +114,13 @@ void __swift_bridge__$IosIapTransaction$add_revocation(void* t, uint64_t date);
101114
void __swift_bridge__$IosIapTransaction$add_expiration(void* t, uint64_t date);
102115
void* __swift_bridge__$IosIapTransactionReason$renewal(void);
103116
void* __swift_bridge__$IosIapTransactionReason$purchase(void);
117+
void* __swift_bridge__$IosIapTransactionFinished$finished(void* t);
118+
void* __swift_bridge__$IosIapTransactionFinished$error(void* e);
119+
void* __swift_bridge__$IosIapTransactionFinished$unknown(uint64_t id);
104120
void __swift_bridge__$products_received(void* products);
105121
void __swift_bridge__$all_transactions(void* transactions);
106122
void __swift_bridge__$purchase_processed(void* result);
107123
void __swift_bridge__$transaction_update(void* t);
124+
void __swift_bridge__$transaction_finished(void* t);
108125

109126

Sources/bevy_ios_iap/BevyIosIAP.swift

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,26 @@ public func ios_iap_products(products:RustVec<RustString>)
4343
public func ios_iap_purchase(id: RustString)
4444
{
4545
Task {
46-
let productIds = [id.toString()]
47-
let products = try await Product.products(for: productIds)
48-
let purchase = try! await products[0].purchase()
49-
// print("purchase:\n \(purchase)")
50-
51-
let result = switch purchase {
52-
case .success(_):
53-
IosIapPurchaseResult.success()
54-
case .userCancelled:
55-
IosIapPurchaseResult.canceled()
56-
case .pending:
57-
IosIapPurchaseResult.pending()
46+
do {
47+
let productIds = [id.toString()]
48+
let products = try await Product.products(for: productIds)
49+
let purchase = try await products[0].purchase()
50+
51+
let result = switch purchase {
52+
case .success(_):
53+
//TODO: forward t.id
54+
IosIapPurchaseResult.success()
55+
case .userCancelled:
56+
IosIapPurchaseResult.canceled()
57+
case .pending:
58+
IosIapPurchaseResult.pending()
59+
}
60+
61+
purchase_processed(result)
62+
} catch {
63+
print("ios_iap_purchase error: \(error).")
64+
purchase_processed(IosIapPurchaseResult.error(error.localizedDescription))
5865
}
59-
60-
purchase_processed(result)
6166
}
6267
}
6368

@@ -68,15 +73,24 @@ public func ios_iap_init()
6873

6974
public func ios_iap_transaction_finish(id: UInt64) {
7075
Task {
71-
for await t in Transaction.unfinished {
72-
// ignore un-signed/verified transactions
73-
guard case .verified(let transaction) = t else {
74-
continue
76+
do {
77+
for await t in Transaction.unfinished {
78+
// ignore un-signed/verified transactions
79+
guard case .verified(let transaction) = t else {
80+
continue
81+
}
82+
83+
if transaction.id == id {
84+
await transaction.finish()
85+
transaction_finished(IosIapTransactionFinished.finished(convert_transaction(transaction)))
86+
return;
87+
}
7588
}
7689

77-
if transaction.id == id {
78-
await transaction.finish()
79-
}
90+
transaction_finished(IosIapTransactionFinished.unknown(id))
91+
}catch {
92+
print("ios_iap_transaction_finish error: \(error).")
93+
transaction_finished(IosIapTransactionFinished.error(error.localizedDescription))
8094
}
8195
}
8296
}

Sources/bevy_ios_iap/bevy_ios_iap.swift

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ public func purchase_processed(_ result: IosIapPurchaseResult) {
1111
public func transaction_update(_ t: IosIapTransaction) {
1212
__swift_bridge__$transaction_update({t.isOwned = false; return t.ptr;}())
1313
}
14+
public func transaction_finished(_ t: IosIapTransactionFinished) {
15+
__swift_bridge__$transaction_finished({t.isOwned = false; return t.ptr;}())
16+
}
1417
@_cdecl("__swift_bridge__$ios_iap_init")
1518
public func __swift_bridge__ios_iap_init () {
1619
ios_iap_init()
@@ -37,6 +40,94 @@ public func __swift_bridge__ios_iap_transaction_finish (_ id: UInt64) {
3740
}
3841

3942

43+
public class IosIapTransactionFinished: IosIapTransactionFinishedRefMut {
44+
var isOwned: Bool = true
45+
46+
public override init(ptr: UnsafeMutableRawPointer) {
47+
super.init(ptr: ptr)
48+
}
49+
50+
deinit {
51+
if isOwned {
52+
__swift_bridge__$IosIapTransactionFinished$_free(ptr)
53+
}
54+
}
55+
}
56+
extension IosIapTransactionFinished {
57+
class public func finished(_ t: IosIapTransaction) -> IosIapTransactionFinished {
58+
IosIapTransactionFinished(ptr: __swift_bridge__$IosIapTransactionFinished$finished({t.isOwned = false; return t.ptr;}()))
59+
}
60+
61+
class public func error<GenericIntoRustString: IntoRustString>(_ e: GenericIntoRustString) -> IosIapTransactionFinished {
62+
IosIapTransactionFinished(ptr: __swift_bridge__$IosIapTransactionFinished$error({ let rustString = e.intoRustString(); rustString.isOwned = false; return rustString.ptr }()))
63+
}
64+
65+
class public func unknown(_ id: UInt64) -> IosIapTransactionFinished {
66+
IosIapTransactionFinished(ptr: __swift_bridge__$IosIapTransactionFinished$unknown(id))
67+
}
68+
}
69+
public class IosIapTransactionFinishedRefMut: IosIapTransactionFinishedRef {
70+
public override init(ptr: UnsafeMutableRawPointer) {
71+
super.init(ptr: ptr)
72+
}
73+
}
74+
public class IosIapTransactionFinishedRef {
75+
var ptr: UnsafeMutableRawPointer
76+
77+
public init(ptr: UnsafeMutableRawPointer) {
78+
self.ptr = ptr
79+
}
80+
}
81+
extension IosIapTransactionFinished: Vectorizable {
82+
public static func vecOfSelfNew() -> UnsafeMutableRawPointer {
83+
__swift_bridge__$Vec_IosIapTransactionFinished$new()
84+
}
85+
86+
public static func vecOfSelfFree(vecPtr: UnsafeMutableRawPointer) {
87+
__swift_bridge__$Vec_IosIapTransactionFinished$drop(vecPtr)
88+
}
89+
90+
public static func vecOfSelfPush(vecPtr: UnsafeMutableRawPointer, value: IosIapTransactionFinished) {
91+
__swift_bridge__$Vec_IosIapTransactionFinished$push(vecPtr, {value.isOwned = false; return value.ptr;}())
92+
}
93+
94+
public static func vecOfSelfPop(vecPtr: UnsafeMutableRawPointer) -> Optional<Self> {
95+
let pointer = __swift_bridge__$Vec_IosIapTransactionFinished$pop(vecPtr)
96+
if pointer == nil {
97+
return nil
98+
} else {
99+
return (IosIapTransactionFinished(ptr: pointer!) as! Self)
100+
}
101+
}
102+
103+
public static func vecOfSelfGet(vecPtr: UnsafeMutableRawPointer, index: UInt) -> Optional<IosIapTransactionFinishedRef> {
104+
let pointer = __swift_bridge__$Vec_IosIapTransactionFinished$get(vecPtr, index)
105+
if pointer == nil {
106+
return nil
107+
} else {
108+
return IosIapTransactionFinishedRef(ptr: pointer!)
109+
}
110+
}
111+
112+
public static func vecOfSelfGetMut(vecPtr: UnsafeMutableRawPointer, index: UInt) -> Optional<IosIapTransactionFinishedRefMut> {
113+
let pointer = __swift_bridge__$Vec_IosIapTransactionFinished$get_mut(vecPtr, index)
114+
if pointer == nil {
115+
return nil
116+
} else {
117+
return IosIapTransactionFinishedRefMut(ptr: pointer!)
118+
}
119+
}
120+
121+
public static func vecOfSelfAsPtr(vecPtr: UnsafeMutableRawPointer) -> UnsafePointer<IosIapTransactionFinishedRef> {
122+
UnsafePointer<IosIapTransactionFinishedRef>(OpaquePointer(__swift_bridge__$Vec_IosIapTransactionFinished$as_ptr(vecPtr)))
123+
}
124+
125+
public static func vecOfSelfLen(vecPtr: UnsafeMutableRawPointer) -> UInt {
126+
__swift_bridge__$Vec_IosIapTransactionFinished$len(vecPtr)
127+
}
128+
}
129+
130+
40131
public class IosIapStorefront: IosIapStorefrontRefMut {
41132
var isOwned: Bool = true
42133

@@ -390,6 +481,11 @@ public class IosIapPurchaseResult: IosIapPurchaseResultRefMut {
390481
}
391482
}
392483
}
484+
extension IosIapPurchaseResult {
485+
class public func error<GenericIntoRustString: IntoRustString>(_ e: GenericIntoRustString) -> IosIapPurchaseResult {
486+
IosIapPurchaseResult(ptr: __swift_bridge__$IosIapPurchaseResult$error({ let rustString = e.intoRustString(); rustString.isOwned = false; return rustString.ptr }()))
487+
}
488+
}
393489
public class IosIapPurchaseResultRefMut: IosIapPurchaseResultRef {
394490
public override init(ptr: UnsafeMutableRawPointer) {
395491
super.init(ptr: ptr)

bevy_ios_iap/generated/SwiftBridgeCore.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import RustXcframework
21
import Foundation
32

43
extension RustString {

bevy_ios_iap/generated/bevy_ios_iap/bevy_ios_iap.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
// File automatically generated by swift-bridge.
22
#include <stdint.h>
33
#include <stdbool.h>
4+
typedef struct IosIapTransactionFinished IosIapTransactionFinished;
5+
void __swift_bridge__$IosIapTransactionFinished$_free(void* self);
6+
7+
void* __swift_bridge__$Vec_IosIapTransactionFinished$new(void);
8+
void __swift_bridge__$Vec_IosIapTransactionFinished$drop(void* vec_ptr);
9+
void __swift_bridge__$Vec_IosIapTransactionFinished$push(void* vec_ptr, void* item_ptr);
10+
void* __swift_bridge__$Vec_IosIapTransactionFinished$pop(void* vec_ptr);
11+
void* __swift_bridge__$Vec_IosIapTransactionFinished$get(void* vec_ptr, uintptr_t index);
12+
void* __swift_bridge__$Vec_IosIapTransactionFinished$get_mut(void* vec_ptr, uintptr_t index);
13+
uintptr_t __swift_bridge__$Vec_IosIapTransactionFinished$len(void* vec_ptr);
14+
void* __swift_bridge__$Vec_IosIapTransactionFinished$as_ptr(void* vec_ptr);
15+
416
typedef struct IosIapStorefront IosIapStorefront;
517
void __swift_bridge__$IosIapStorefront$_free(void* self);
618

@@ -92,6 +104,7 @@ void* __swift_bridge__$IosIapProductType$new_auto_renewable(void);
92104
void* __swift_bridge__$IosIapPurchaseResult$success(void);
93105
void* __swift_bridge__$IosIapPurchaseResult$canceled(void);
94106
void* __swift_bridge__$IosIapPurchaseResult$pending(void);
107+
void* __swift_bridge__$IosIapPurchaseResult$error(void* e);
95108
void* __swift_bridge__$IosIapEnvironment$sandbox(void);
96109
void* __swift_bridge__$IosIapEnvironment$production(void);
97110
void* __swift_bridge__$IosIapEnvironment$xcode(void);
@@ -101,9 +114,13 @@ void __swift_bridge__$IosIapTransaction$add_revocation(void* t, uint64_t date);
101114
void __swift_bridge__$IosIapTransaction$add_expiration(void* t, uint64_t date);
102115
void* __swift_bridge__$IosIapTransactionReason$renewal(void);
103116
void* __swift_bridge__$IosIapTransactionReason$purchase(void);
117+
void* __swift_bridge__$IosIapTransactionFinished$finished(void* t);
118+
void* __swift_bridge__$IosIapTransactionFinished$error(void* e);
119+
void* __swift_bridge__$IosIapTransactionFinished$unknown(uint64_t id);
104120
void __swift_bridge__$products_received(void* products);
105121
void __swift_bridge__$all_transactions(void* transactions);
106122
void __swift_bridge__$purchase_processed(void* result);
107123
void __swift_bridge__$transaction_update(void* t);
124+
void __swift_bridge__$transaction_finished(void* t);
108125

109126

0 commit comments

Comments
 (0)