支付
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
23270C292B0E037300B9303B /* MessageConentAudioView.m in Sources */ = {isa = PBXBuildFile; fileRef = 23270C272B0E037300B9303B /* MessageConentAudioView.m */; };
|
||||
23270C2C2B0E041300B9303B /* MessageAudioCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 23270C2B2B0E041300B9303B /* MessageAudioCenter.m */; };
|
||||
23270C302B0E071B00B9303B /* MewPaymentAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23270C2F2B0E071B00B9303B /* MewPaymentAction.swift */; };
|
||||
233757562B0CB577001D0B7F /* MessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 233757262B0CB577001D0B7F /* MessagePresenter.m */; };
|
||||
233757572B0CB577001D0B7F /* MessageMenuModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 2337572C2B0CB577001D0B7F /* MessageMenuModel.m */; };
|
||||
233757582B0CB577001D0B7F /* ChatLimitModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 2337572D2B0CB577001D0B7F /* ChatLimitModel.m */; };
|
||||
@@ -197,6 +198,8 @@
|
||||
23270C282B0E037300B9303B /* MessageConentAudioView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageConentAudioView.h; sourceTree = "<group>"; };
|
||||
23270C2A2B0E041300B9303B /* MessageAudioCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageAudioCenter.h; sourceTree = "<group>"; };
|
||||
23270C2B2B0E041300B9303B /* MessageAudioCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessageAudioCenter.m; sourceTree = "<group>"; };
|
||||
23270C2E2B0E071B00B9303B /* yinmeng-ios-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "yinmeng-ios-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
23270C2F2B0E071B00B9303B /* MewPaymentAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MewPaymentAction.swift; sourceTree = "<group>"; };
|
||||
233757262B0CB577001D0B7F /* MessagePresenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessagePresenter.m; sourceTree = "<group>"; };
|
||||
233757272B0CB577001D0B7F /* MessagePresenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePresenter.h; sourceTree = "<group>"; };
|
||||
233757292B0CB577001D0B7F /* MessageProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageProtocol.h; sourceTree = "<group>"; };
|
||||
@@ -599,6 +602,16 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
23270C2D2B0E06F700B9303B /* MewIAP */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23270C2F2B0E071B00B9303B /* MewPaymentAction.swift */,
|
||||
23270C2E2B0E071B00B9303B /* yinmeng-ios-Bridging-Header.h */,
|
||||
);
|
||||
name = MewIAP;
|
||||
path = "yinmeng-ios/Base/MewIAP";
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
233757242B0CB577001D0B7F /* Message */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1749,6 +1762,7 @@
|
||||
8C9C83C12B0C697A00A601BC /* Mew */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23270C2D2B0E06F700B9303B /* MewIAP */,
|
||||
8C9C83C22B0C697A00A601BC /* Home */,
|
||||
8C9C83E62B0C697A00A601BC /* Room */,
|
||||
8C9C83FA2B0C697A00A601BC /* Party */,
|
||||
@@ -2157,6 +2171,7 @@
|
||||
TargetAttributes = {
|
||||
8C4D534B2AFD4CF600238AE6 = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
LastSwiftMigration = 1500;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -2357,6 +2372,7 @@
|
||||
8C9C845D2B0C697A00A601BC /* MewHomePresenter.m in Sources */,
|
||||
2337575A2B0CB577001D0B7F /* UITableView+NIMScrollToBottom.m in Sources */,
|
||||
8C9C84252B0C697A00A601BC /* YMMessageInfoModel.m in Sources */,
|
||||
23270C302B0E071B00B9303B /* MewPaymentAction.swift in Sources */,
|
||||
8C9C82D12B0C695600A601BC /* RechargeStorage.m in Sources */,
|
||||
8C9C84792B0C697A00A601BC /* MewLoginNumberViewController.m in Sources */,
|
||||
8C9C841D2B0C697A00A601BC /* ThemeColor+Room.m in Sources */,
|
||||
@@ -2571,6 +2587,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "yinmeng-ios/yinmeng-ios.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@@ -2597,6 +2614,9 @@
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "yinmeng-ios/Base/MewIAP/yinmeng-ios-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -2607,6 +2627,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "yinmeng-ios/yinmeng-ios.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@@ -2633,6 +2654,8 @@
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "yinmeng-ios/Base/MewIAP/yinmeng-ios-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
name = Release;
|
||||
|
264
yinmeng-ios/yinmeng-ios/Base/MewIAP/MewPaymentAction.swift
Normal file
264
yinmeng-ios/yinmeng-ios/Base/MewIAP/MewPaymentAction.swift
Normal file
@@ -0,0 +1,264 @@
|
||||
//
|
||||
// MewPaymentAction.swift
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/11/22.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import StoreKit
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
typealias MewTransaction = StoreKit.Transaction
|
||||
@available(iOS 15.0, *)
|
||||
typealias MewRenewalInfo = StoreKit.Product.SubscriptionInfo.RenewalInfo
|
||||
@available(iOS 15.0, *)
|
||||
typealias MewRenewalState = StoreKit.Product.SubscriptionInfo.RenewalState
|
||||
|
||||
|
||||
|
||||
enum MewStoreError: Error {
|
||||
|
||||
|
||||
// 错误回调枚举
|
||||
case MewFailedVerification
|
||||
case MewNoProduct
|
||||
|
||||
}
|
||||
|
||||
@objc public enum MewStoreConditionResult: Int64 { // 支付状态
|
||||
case MewStart // 开始
|
||||
case MewPay // 进行苹果支付
|
||||
case MewVerifiedServer // 服务器校验
|
||||
case MewUserCancelled // 用户取消
|
||||
case MewPending // 等待(家庭用户才有的状态)
|
||||
case MewUnowned
|
||||
case MewNoProduct //没有商品
|
||||
case MewFailedVerification //验证失败
|
||||
}
|
||||
|
||||
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
public class MewPaymentAction: NSObject {
|
||||
public typealias Mew_KConditionBlock = (_ state :MewStoreConditionResult,_ param:Dictionary<String,Any>?) ->()
|
||||
@objc public var Mew_ConditionBlock: Mew_KConditionBlock! // 状态回调
|
||||
|
||||
var Mew_updateListenerTask: Task<Void, Error>? = nil // 支付事件监听
|
||||
|
||||
var Mew_transactionMap :[String:Transaction] // 用于完成Id的缓存map
|
||||
|
||||
var Mew_name: String = "Mew_iosStore" // 单例的写法
|
||||
|
||||
@objc public static let shared = {
|
||||
let instance = MewPaymentAction()
|
||||
return instance
|
||||
}()
|
||||
|
||||
private override init() { // 单例需要保证private的私有性质
|
||||
|
||||
Mew_transactionMap = [:] // 初始化
|
||||
super.init()
|
||||
Task {
|
||||
Mew_updateListenerTask = Mew_listenForTransactions()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 退订
|
||||
@objc public func Mew_refunRequest(view: UIView,transactionId:UInt64) async{
|
||||
do {
|
||||
if let scene = await view.window?.windowScene{
|
||||
try await Transaction.beginRefundRequest(for:transactionId , in: scene)
|
||||
}
|
||||
|
||||
}catch{
|
||||
print("iap error")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 购买某个产品
|
||||
@objc public func Mew_demandCommodityThing(productId:String, uuid: String) async throws {
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewStart,nil)
|
||||
}
|
||||
do {
|
||||
let list:[String] = [productId]
|
||||
let storeProducts = try await Product.products(for: Set.init(list))
|
||||
|
||||
|
||||
|
||||
|
||||
if storeProducts.count > 0 {
|
||||
try await Mew_purchase(storeProducts[0],uuid)
|
||||
}else {
|
||||
print("iap: no found product")
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewNoProduct,nil)
|
||||
}
|
||||
throw MewStoreError.MewNoProduct // 没有该产品
|
||||
}
|
||||
} catch {
|
||||
print("Failed product request from the App Store server: \(error)")
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewNoProduct,nil)
|
||||
}
|
||||
throw MewStoreError.MewNoProduct // 没有该产品
|
||||
}
|
||||
}
|
||||
|
||||
// 购买
|
||||
private func Mew_purchase(_ product: Product, _ uuid: String) async throws -> Transaction? {
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewPay,nil)
|
||||
}
|
||||
|
||||
guard let curUUID = UUID.init(uuidString: uuid) else{
|
||||
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewFailedVerification,nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
let getUUID = Product.PurchaseOption.appAccountToken(curUUID)
|
||||
let result = try await product.purchase(options: [getUUID])
|
||||
|
||||
switch result {
|
||||
case .success(let verification): // 用户购买完成
|
||||
let transaction = try await Mew_verifiedAndAccomplish(verification)
|
||||
return transaction
|
||||
case .userCancelled: // 用户取消
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewUserCancelled,nil)
|
||||
}
|
||||
return nil
|
||||
case .pending: // 此次购买被挂起
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewPending,nil)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewUnowned,nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// 校验
|
||||
func Mew_checkVerified<T>(_ result: VerificationResult<T>) throws -> T {
|
||||
//Check whether the JWS passes StoreKit verification.
|
||||
switch result {
|
||||
case .unverified:
|
||||
//StoreKit parses the JWS, but it fails verification.
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewFailedVerification,nil)
|
||||
}
|
||||
throw MewStoreError.MewFailedVerification
|
||||
case .verified(let safe):
|
||||
//The result is verified. Return the unwrapped value.
|
||||
print("iap: verified success")
|
||||
return safe
|
||||
}
|
||||
}
|
||||
|
||||
// 校验&完成后传给服务器
|
||||
func Mew_verifiedAndAccomplish(_ verification:VerificationResult<Transaction>) async throws -> Transaction?{
|
||||
//Check whether the transaction is verified. If it isn't,
|
||||
//this function rethrows the verification error.
|
||||
let transaction = try Mew_checkVerified(verification)
|
||||
// 这里将订单提交给服务器进行验证 ~~~
|
||||
let transactionId = try verification.payloadValue.id
|
||||
|
||||
// 添加进入待完成map
|
||||
let key = String(transactionId)
|
||||
Mew_transactionMap[key] = transaction
|
||||
await Mew_uploadServer(for: transactionId)
|
||||
|
||||
// 这里不触发完成,等服务器验证再触发完成逻辑
|
||||
await transaction.finish()
|
||||
|
||||
print("iap: finish")
|
||||
return transaction
|
||||
}
|
||||
/*All transactions:全部的购买交易订单
|
||||
Latest transactions:最新的购买交易订单。(分为订阅品项和除订阅品项外的所有类型二种)
|
||||
Current entitlements:当前用户有购买的权限。(全部的订阅品项、和非消耗品项)
|
||||
*/
|
||||
func Mew_getAllBusiness(transactionId:String) async {
|
||||
|
||||
let transactionIntId = UInt64(transactionId)
|
||||
for await result in Transaction.all {
|
||||
do {
|
||||
let tran = try Mew_checkVerified(result)
|
||||
let resultId = try result.payloadValue.id
|
||||
if transactionIntId == resultId {
|
||||
await tran.finish()
|
||||
break
|
||||
}
|
||||
} catch let error {
|
||||
|
||||
print("error:----\(error)")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Transaction.latest(for: "pid")
|
||||
|
||||
}
|
||||
// 事件完成处理
|
||||
|
||||
@objc public func Mew_verifyBusinessAccomplish(transaction:String) async{
|
||||
if(Mew_transactionMap[transaction] != nil){
|
||||
await Mew_transactionMap[transaction]!.finish()
|
||||
Mew_transactionMap.removeValue(forKey: transaction)
|
||||
print("verifyBusinessFinish end")
|
||||
}else {
|
||||
await Mew_getAllBusiness(transactionId: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func Mew_uploadServer(for transactionId:UInt64) async {
|
||||
let dic :Dictionary<String,Any> = ["transactionId":transactionId]
|
||||
if(Mew_ConditionBlock != nil ){
|
||||
Mew_ConditionBlock(MewStoreConditionResult.MewVerifiedServer,dic)
|
||||
}
|
||||
}
|
||||
|
||||
// 支付监听事件
|
||||
func Mew_listenForTransactions() -> Task<Void, Error> {
|
||||
return Task.detached {
|
||||
//Iterate through any transactions that don't come from a direct call to `purchase()`.
|
||||
// 修改update 为 unfinished?
|
||||
for await result in Transaction.updates { //会导致二次校验?
|
||||
do {
|
||||
print("iap: updates")
|
||||
print("result:\(result)")
|
||||
try await self.Mew_verifiedAndAccomplish(result)
|
||||
} catch {
|
||||
//StoreKit has a transaction that fails verification. Don't deliver content to the user.
|
||||
print("Transaction failed verification")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//获取推广内购商品
|
||||
func Mew_Promotion() async -> [SKProduct]?{
|
||||
let promotion = SKProductStorePromotionController()
|
||||
|
||||
let prodicts = try? await promotion.promotionOrder()
|
||||
return prodicts
|
||||
}
|
||||
// 销毁调用
|
||||
deinit {
|
||||
Mew_updateListenerTask?.cancel()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,4 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
@@ -17,7 +17,7 @@ typedef NS_ENUM(NSInteger ,PaymentStatus) {
|
||||
};
|
||||
|
||||
@protocol YMIAPHelperDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
///当前充值的状态
|
||||
- (void)rechargeProcessStatus:(PaymentStatus)status;
|
||||
|
||||
|
@@ -18,7 +18,8 @@
|
||||
#import "YMMineSettingViewController.h"
|
||||
#import "MewMineCollectionViewController.h"
|
||||
#import "MewRechargeViewController.h"
|
||||
|
||||
#import "SessionViewController.h"
|
||||
#import <NIMSDK/NIMSDK.h>
|
||||
/// Tool
|
||||
#import "YMMacro.h"
|
||||
#import "ThemeColor.h"
|
||||
@@ -238,7 +239,9 @@
|
||||
/// optionType: 0 - 取消关注 1 - 关注 2-聊天
|
||||
- (void)userIntrodctionViewWithUserOption:(NSInteger)optionType {
|
||||
if (optionType == 2) { //聊天
|
||||
|
||||
NIMSession *session = [NIMSession session:self.targetUid type:NIMSessionTypeP2P];
|
||||
SessionViewController *vc = [[SessionViewController alloc] initWithSession:session];
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
} else {
|
||||
[self.presenter attentionUser:self.targetUid state:optionType == 1];
|
||||
}
|
||||
|
@@ -12,10 +12,13 @@
|
||||
#import <Masonry/Masonry.h>
|
||||
#import "YMMacro.h"
|
||||
#import "YMIAPHelper.h"
|
||||
#import "AccountInfoStorage.h"
|
||||
/// P
|
||||
#import "MineRechargeProtocol.h"
|
||||
#import "MineRechargePresenter.h"
|
||||
|
||||
#import "YMHUDTool.h"
|
||||
#import "yinmeng_ios-Swift.h"
|
||||
#import "RechargeStorage.h"
|
||||
@interface MewRechargeViewController ()<MineRechargeProtocol, MewRechargeSubViewDelegate, YMIAPHelperDelegate>
|
||||
@property (nonatomic, strong) UIImageView *rechargeBgImageView;
|
||||
@property (nonatomic, strong) UIButton *backButton;
|
||||
@@ -65,16 +68,141 @@
|
||||
self.rechageView.rechargeModels = list;
|
||||
}
|
||||
|
||||
- (void)requestIAPRechargeOrderSuccess:(NSString *)orderId chargeProdId:(NSString *)chargeProdId {
|
||||
- (void)requestIAPRechargeOrderSuccess:(NSString *)orderId chargeProdId:(NSString *)chargeProdId uuid:(nonnull NSString *)uuid{
|
||||
if (orderId.length > 0) {
|
||||
|
||||
self.orderId = orderId;
|
||||
if (@available(iOS 15.0, *)) {
|
||||
|
||||
MewPaymentAction *iap = [MewPaymentAction shared];
|
||||
[iap Mew_demandCommodityThingWithProductId:chargeProdId uuid:uuid completionHandler:^(NSError * _Nullable error) {
|
||||
|
||||
}];
|
||||
@kWeakify(self);
|
||||
iap.Mew_ConditionBlock = ^(enum MewStoreConditionResult state, NSDictionary<NSString *,id> * _Nullable result) {
|
||||
@kStrongify(self);
|
||||
|
||||
[self rechargeNewProcessStatus:state];
|
||||
switch (state) {
|
||||
case MewStoreConditionResultMewVerifiedServer:
|
||||
{
|
||||
NSString *transactionId = result[@"transactionId"];
|
||||
|
||||
[self rechargeSuccess:transactionId];
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
//
|
||||
} else {
|
||||
[YMHUDTool hideHUDInView:kWindow];
|
||||
[self showErrorToast:@"充值失败。当前仅支持运行iOS15及以上系统的手机进行充值,请升级系统版本后重试。"];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}else{
|
||||
|
||||
[YMHUDTool hideHUDInView:kWindow];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///当前充值的状态
|
||||
- (void)rechargeNewProcessStatus:(MewStoreConditionResult)status {
|
||||
|
||||
|
||||
if (status == MewStoreConditionResultMewPay || status == MewStoreConditionResultMewStart || status == MewStoreConditionResultMewVerifiedServer) {
|
||||
|
||||
}else if (status == MewStoreConditionResultMewUnowned) {
|
||||
[YMHUDTool hideHUDInView:kWindow];
|
||||
[self showErrorToast:@"出现未知错误,请重新尝试"];
|
||||
}else{
|
||||
[YMHUDTool hideHUDInView:kWindow];
|
||||
[self showErrorToast:@"购买失败"];
|
||||
}
|
||||
}
|
||||
///充值成功回调id
|
||||
- (void)rechargeSuccess:(NSString *)transactionIdentifier {
|
||||
///保存唯一凭证
|
||||
[self saveRechageReciptWithTransactionIdentifier:transactionIdentifier];
|
||||
///二次验证
|
||||
[self.presenter checkReceiptWithOrderId:self.orderId transcationId:transactionIdentifier errorToast:YES];
|
||||
}
|
||||
///二次校验成功
|
||||
- (void)checkReceiptSuccess:(NSString *)transcationId {
|
||||
[YMHUDTool hideHUDInView:kWindow];
|
||||
if (@available(iOS 15.0, *)) {
|
||||
MewPaymentAction *iap = [MewPaymentAction shared];
|
||||
[iap Mew_verifyBusinessAccomplishWithTransaction:[NSString stringWithFormat:@"%@",transcationId] completionHandler:^{
|
||||
|
||||
}];
|
||||
}
|
||||
[self deleteRechageReciptWithTransactionIdentifier:transcationId];
|
||||
self.orderId = nil;
|
||||
//5秒之后如果没有收到开通成功的云信消息,则请求一次用户信息
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
|
||||
///刷新一下用户的信息
|
||||
[self.presenter getUserWalletInfo];
|
||||
|
||||
});
|
||||
}
|
||||
///二次校验失败
|
||||
- (void)checkReceiptFailWithCode:(NSInteger)code transcationId:(NSString *)transcationId{
|
||||
[YMHUDTool hideHUDInView:kWindow];
|
||||
if(code == 1444){
|
||||
if (@available(iOS 15.0, *)) {
|
||||
MewPaymentAction *iap = [MewPaymentAction shared];
|
||||
[iap Mew_verifyBusinessAccomplishWithTransaction:[NSString stringWithFormat:@"%@",transcationId] completionHandler:^{
|
||||
|
||||
}];
|
||||
}
|
||||
[self deleteRechageReciptWithTransactionIdentifier:transcationId];
|
||||
}
|
||||
}
|
||||
///删除本地保存的
|
||||
- (void)deleteRechageReciptWithTransactionIdentifier:(NSString *)transactionIdentifier {
|
||||
NSString * uid = [AccountInfoStorage instance].getUid;
|
||||
BOOL deleteSuccess = [RechargeStorage delegateTranscationId:transactionIdentifier uid:uid];
|
||||
if (deleteSuccess) {
|
||||
#warning to do 保存失败 需要埋点
|
||||
}
|
||||
}
|
||||
///充值成功之后保存订单到钥匙串
|
||||
- (void)saveRechageReciptWithTransactionIdentifier:(NSString *)transactionIdentifier {
|
||||
NSData *receipt = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
|
||||
NSString *encodeStr = [receipt base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
if(transactionIdentifier != nil){
|
||||
[dictionary setObject:transactionIdentifier forKey:@"transcationId"];
|
||||
}
|
||||
if(encodeStr != nil){
|
||||
[dictionary setObject:encodeStr forKey:@"recipt"];
|
||||
}
|
||||
if(self.orderId != nil){
|
||||
[dictionary setObject:self.orderId forKey:@"orderId"];
|
||||
}
|
||||
if(dictionary.allKeys.count == 0)return;
|
||||
NSString *reciptJson = [dictionary toJSONString];
|
||||
NSString * uid = [AccountInfoStorage instance].getUid;
|
||||
BOOL saveSuccess = [RechargeStorage saveTranscationId:transactionIdentifier recipt:reciptJson uid:uid];
|
||||
if (!saveSuccess) {
|
||||
#warning to do 保存失败 需要埋点
|
||||
}
|
||||
}
|
||||
#pragma mark - MewRechargeSubViewDelegate
|
||||
- (void)didSelectMewRechargeChargeProdId:(NSString *)chargeProdId {
|
||||
[YMHUDTool showLoadingInView:kWindow];
|
||||
[self.presenter requestIAPRechargeOrderWithChargeProdId:chargeProdId];
|
||||
}
|
||||
|
||||
|
@@ -88,6 +88,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
transcationId:(NSString *)transcationId
|
||||
uid:(NSString *)uid
|
||||
ticket:(NSString *)ticket;
|
||||
/// 验证凭据
|
||||
/// @param completion 完成
|
||||
/// @param chooseEnv @"true"
|
||||
/// @param chargeRecordId 服务端生成的订单编号
|
||||
/// @param transcationId 内购的唯一标识符
|
||||
/// @param uid 用户uid
|
||||
/// @param ticket ticket
|
||||
+ (void)checkReceipt:(HttpRequestHelperCompletion)completion chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@@ -81,7 +81,7 @@
|
||||
/// @param deviceInfo uuid
|
||||
/// @param clientIp ip地址
|
||||
+ (void)requestIAPRecharge:(HttpRequestHelperCompletion)completion chargeProdId:(NSString *)chargeProdId uid:(NSString *)uid ticket:(NSString *)ticket deviceInfo:(NSString *)deviceInfo clientIp:(NSString *)clientIp {
|
||||
[self makeRequest:@"order/placeV2" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,chargeProdId, uid, ticket, deviceInfo, clientIp, nil];
|
||||
[self makeRequest:[NSString stringWithFormat:@"%@/%@",@"storeKitV2",@"placeOrder"] method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,chargeProdId, uid, ticket, deviceInfo, clientIp, nil];
|
||||
}
|
||||
|
||||
|
||||
@@ -96,5 +96,15 @@
|
||||
+ (void)checkReceipt:(HttpRequestHelperCompletion)completion receipt:(NSString *)receipt chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket {
|
||||
[self makeRequest:@"verify/setiap" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,receipt, chooseEnv, chargeRecordId, transcationId, uid, ticket, nil];
|
||||
}
|
||||
/// 验证凭据
|
||||
/// @param completion 完成
|
||||
/// @param chooseEnv @"true"
|
||||
/// @param chargeRecordId 服务端生成的订单编号
|
||||
/// @param transcationId 内购的唯一标识符
|
||||
/// @param uid 用户uid
|
||||
/// @param ticket ticket
|
||||
+ (void)checkReceipt:(HttpRequestHelperCompletion)completion chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket {
|
||||
|
||||
[self makeRequest:[NSString stringWithFormat:@"%@/%@",@"storeKitV2",@"verifyOrder"] method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, chooseEnv, chargeRecordId, transcationId, uid, ticket, nil];
|
||||
}
|
||||
@end
|
||||
|
@@ -30,7 +30,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// 批量验证内购掉单
|
||||
/// @param transcations 凭据的数组
|
||||
- (void)checkTranscationIds:(NSArray *)transcations;
|
||||
|
||||
/// 充值成功二次验证
|
||||
/// @param orderId 订单编号
|
||||
/// @param transcationId 商品id
|
||||
- (void)checkReceiptWithOrderId:(NSString *)orderId transcationId:(NSString *)transcationId errorToast:(BOOL)errorToast;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@@ -48,12 +48,28 @@
|
||||
NSString * clientIp= [YYUtility ipAddress];
|
||||
[Api requestIAPRecharge:[self createHttpCompletion:^(BaseModel * _Nonnull data) {
|
||||
NSString *orderId = (NSString *)data.data[@"recordId"];
|
||||
[[self getView] requestIAPRechargeOrderSuccess:orderId chargeProdId:chargeProdId];
|
||||
NSString *mew_uuid = (NSString *)data.data[@"appAccountToken"];
|
||||
[[self getView] requestIAPRechargeOrderSuccess:orderId chargeProdId:chargeProdId uuid:mew_uuid];
|
||||
} fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
if(code != 50000){
|
||||
[[self getView]showErrorToast:msg];
|
||||
}
|
||||
[[self getView] requestIAPRechargeOrderFail];
|
||||
}] chargeProdId:chargeProdId uid:uid ticket:ticket deviceInfo:deviceInfo clientIp:clientIp];
|
||||
}
|
||||
|
||||
/// 充值成功二次验证
|
||||
/// @param orderId 订单编号
|
||||
/// @param transcationId 商品id
|
||||
- (void)checkReceiptWithOrderId:(NSString *)orderId transcationId:(NSString *)transcationId errorToast:(BOOL)errorToast{
|
||||
NSString * uid = [AccountInfoStorage instance].getUid;
|
||||
NSString * ticket = [AccountInfoStorage instance].getTicket;
|
||||
[Api checkReceipt:[self createHttpCompletion:^(BaseModel * _Nonnull data) {
|
||||
[[self getView] checkReceiptSuccess:transcationId];
|
||||
}fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
[[self getView]checkReceiptFailWithCode:code transcationId:transcationId];
|
||||
} showLoading:NO errorToast:errorToast] chooseEnv:@"true" chargeRecordId:orderId transcationId:transcationId uid:uid ticket:ticket];
|
||||
}
|
||||
|
||||
/// 充值成功二次验证
|
||||
/// @param receipt 凭据
|
||||
|
@@ -10,18 +10,21 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MineRechargeProtocol <NSObject>
|
||||
@optional
|
||||
///请求钱包余额信息
|
||||
- (void)getUserWalletInfo:(WalletInfoModel *)balanceInfo;
|
||||
///请求充值列表成功
|
||||
- (void)requestRechargeListSucccess:(NSArray *)list;
|
||||
///请求充值id的状态成功
|
||||
- (void)requestIAPRechargeOrderSuccess:(NSString *)orderId chargeProdId:(NSString *)chargeProdId;
|
||||
- (void)requestIAPRechargeOrderSuccess:(NSString *)orderId chargeProdId:(NSString *)chargeProdId uuid:(NSString *)uuid;
|
||||
///请求充值账单失败
|
||||
- (void)requestIAPRechargeOrderFail;
|
||||
///二次校验成功
|
||||
- (void)checkReceiptSuccess:(NSString *)transcationId;
|
||||
///批量验证凭据成功
|
||||
- (void)checkTranscationIdsSuccess;
|
||||
///二次校验失败
|
||||
- (void)checkReceiptFailWithCode:(NSInteger)code transcationId:(NSString *)transcationId;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
Reference in New Issue
Block a user