1、支付模块流程说明
为保证支付安全性,不出现掉单、漏单的情况,SDK
采用了苹果验证和LT
服务器二次验证的方式,主要业务逻辑为:
(1)、客户端调用支付模块代码,由SDK
向LT
服务器发起一个订单请求;
(2)、拿到服务器给的订单ID
后,SDK
发起苹果支付;
(3)、苹果支付返回结果后,拿到支付transaction
和receipt_data
信息;
(4)、SDK
把苹果返回的receiptData
信息发给服务端,LT
服务器向苹果服务器校验;
(5)、服务端对苹果服务器响应数据做处理和校验订单的合法性;
(6)、通过服务器验证的结果来确定支付的结果;
(7)、支付成功回调 支付成功回调的使用方法: 需要CP服务器建立一个API供乐推服务调用 回调地址所接受的参数格式
METHOD: POST
HEADER:Content-Type:application/json
BODY:
参数 | 类型 | 说明 |
---|---|---|
lt_order_id |
string | 乐推订单号 |
pay_mode |
int | 支付方式 |
custom |
array | dict |
app_name |
string | app名 |
package_name |
string | 包ID |
lt_gid |
int | 乐推商品ID |
price |
double | 金额 |
abb |
string | 币种缩写 |
time |
int | 支付时间戳 |
token |
string | 加密验证token |
CP方为了安全起见需要对token进行验证 token的加密方法为 md5({BODY的第二个参数}{APPSECRETKEY}{支付时间戳})
BODY参数除了custom和token其他参数均为乱序,和上表顺序不一样,所以每次需要针对BODY取第二个参数 APPSECRETKEY在乐推平台创建应用时生成 支付时间戳为BODY中的time。
2、支付SDK简介
SDK
支付模块目前给的有3个.h
文件:
(1)、LTPlayErrorCode
可以查看支付时的各种状态码或错误码;
(2)、GoodsModel
传人参数的Model
文件,可以查看有哪些参数是必传的,哪些是非必传的;
(3)、LTPlayManager
支付主类,用于完成支付、支付验证、支付回调等操作;
3、准备工作
iOS 9
以及之后的所有版本的iPhone
和iPad
设备;info.plist
中设置Allow Arbitrary Loads
为YES!设置方法请点这里4、导入头文件
// 支付管理类
#import <LTGameSDK/LTPlayManager.h>
// Model类
#import <LTGameSDK/GoodsModel.h>
5、初始化
@property (strong, nonatomic) LTPlayManager *playManager;
SDK
提供了两套回调方法,通过delegate
模式和Blocks
方式;
//==============================
GoodsModel *goodsModel = [[GoodsModel alloc]init];
goodsModel.gid = @"1";
goodsModel.productId = @"com.gnetop.339Golds";
goodsModel.custom = @{};
goodsModel.payType = LTPayTypeDevelop;
self.playManager = [[LTPlayManager alloc]initPlayWithViewModel:goodsModel SuccessBlocks:^(int code, NSDictionary * _Nonnull successInfoData, NSString * _Nonnull secuessInfoMessage) {
} failureBlocks:^(int error, NSString * _Nonnull errorInfoMessage) {
}];
self.playManager.nowStatusBlocks = ^(int code, NSString * _Nonnull nowInfoMessage) {
};
GoodsModel *goodsModel = [[GoodsModel alloc]init];
goodsModel.gid = @"1";
goodsModel.productId = @"com.gnetop.339Golds";
goodsModel.custom = @{};
goodsModel.payType = LTPayTypeDevelop;
//==============================
self.playManager = [[LTPlayManager alloc]init];
self.playManager.goodsModel = goodsModel;
self.playManager.delegatePlay = self;
如果使用了这种方式初始化,那么必须实现成功和失败代理:
// pay Success delegate
-(void)playSuccessDelegate:(int)code secuessInfoData:(NSDictionary *)secuessInfoData secuessInfoMessage:(NSString *)secuessInfoMessage{
NSLog(@"errorInfoMessage===========%@,%@",secuessInfoData,secuessInfoMessage);
}
// pay failure delegate
-(void)playFailureDelegate:(int)error errorInfoMessage:(NSString *)errorInfoMessage{
NSLog(@"errorInfoMessage===========%d,%@",error,errorInfoMessage);
}
建议使用第一种方式初始化,使用Blocks
回调。
6、回调返回参数
不论支付成功还是失败都返回状态码和对应的信息,
如支付成功后,返回的code
为1000
,同时返回了支付成功的键值对,举例:
code,secuessInfoData,secuessInfoMessage===========1000,{
code = 200;
msg = success;
result = OK;
},==============Transaction is in queue, user has been charged. Client should complete the transaction.
7、GoodsModel类
GoodsModel
类中有四个参数,
// your APP Bundle Id
@property (nonatomic, copy) NSString *package_id;
//Must and cannot be null
@property (nonatomic, copy, nonnull) NSString *gid;
//商品ID 形如(com.test.1gold) Must and cannot be null
@property (nonatomic, copy, nonnull) NSString *productId
//预留的,数组或者字典Reserved, array or dictionary,Must and cannot be null
@property (nonatomic, copy, nonnull) id custom
8、错误码
在LTPlayErrorCode
类中返回了各种情况状态码:可根据返回的不同状态码来判断是哪里出错了。
/// 购买成功
TypePlaySuccess = 1000,
/// 请求订单时失败
TypeGetOrderFailure = 1001,
/// 没有商品 Product list is null
TypeProductListIsNull = 10002,
/// 商品ID和苹果给的不匹配Product ID and apple server do not match
TypeProductIDNotMatch = 1003,
/// 正在购买 buying
TypePlayingfromAppleServer = 1004,
/// 已经收到Apple的购买成功通知 正在和服务器验证
TypeMineServerVerifying = 1005,
/// 购买失败
TypePlayFailureCode = 1006,
/// 已经购买, Apple正在处理
TypePlaymentTransactionStateRestored = 1007,
/// 正在购买中,最终状态还没确定
TypePlaymentTransactionStateDeferred = 1008,
/// 服务器验证支付失败
TypeServerPlaymentVerificationFailed = 1009,
9、test or release
typedef NS_ENUM(NSInteger,LTPayType)
{
LTPayTypeDistribute = 0,
LTPayTypeDevelop,
};
在初始化SDK
时需要传入当前环境标记,如果是测试环境,
goodsModel.payType = LTPayTypeDevelop;
如果是正式环境:
goodsModel.payType = LTPayTypeDistribute;