iOS Review

网易云信Demo接入红包详细流程--iOS

2017-01-10  本文已影响1993人  我了个卡

网易云信金融魔方红包接入文档v2.0


一、文档说明

基于网易云信的IM,接入金融魔方IM红包SDK实现App快速集成发单聊红包、发群聊红包、拆红包并查看交易记录等功能

【注:示例中的partnerId为金融魔方分配给商户的唯一标识的渠道id】


在阅读下面内容之前请确保在项目有中已经导入了金融魔方红包SDK
如若想集成钱包功能,也请导入钱包SDK
金融魔方SDK下载地址
金融魔方红包接入文档
网易云信集成红包Demo
网易云信demo下载地址(网易原生)


二、集成流程详解

1、获取token值
#pragma mark - 登录成功后获取红包thirdToken
// 云信登录之后的回调方法
@implementation NTESAppDelegate
- (void)onLogin:(NIMLoginStep)step {
    if(step == NIMLoginStepSyncOK) {
        NSLog(@"同步完成");
        
        [JRMFTools getJrmfPacketThirdTokenWithUserId:[[NIMSDK sharedSDK].loginManager currentAccount] partnerId:[JRMFSington GetPacketSington].JrmfPartnerId appMethod:NO completion:^(NSString *thirdToken, BOOL isOnline) {
            
            [JRMFSington GetPacketSington].JrmfThirdToken = thirdToken;

            [JrmfPacket instanceJrmfPacketWithPartnerId:[JRMFSington GetPacketSington].JrmfPartnerId EnvelopeName:@"云红包" SchemeUrl:kSchemeUrl appMothod:isOnline];
            [JrmfWalletSDK instanceJrmfWalletSDKWithPartnerId:[JRMFSington GetPacketSington].JrmfPartnerId AppMethod:isOnline];
        }];

    }
}
2、定义消息枚举(在NTESCustomAttachmentDefines中)
typedef NS_ENUM(NSInteger,NTESCustomMessageType){
    CustomMessageTypeJanKenPon  = 1, //剪子石头布
    CustomMessageTypeSnapchat   = 2, //阅后即焚
    CustomMessageTypeChartlet   = 3, //贴图表情
    CustomMessageTypeWhiteboard = 4,  //白板会话
    CustomMessageTypeRedPacket = 5, // 发送红包
    CustomMessageTypeRedPacketOpen = 6 //领取红包提示信息
};
3、自定义消息体

红包消息对象

@interface JRMFRedPacketAttachment : NSObject <NIMCustomAttachment, NTESCustomAttachmentInfo>

/**
 祝福语,如:恭喜发财,大吉大利
 */
@property (copy, nonatomic) NSString *title;

/**
 红包的描述,如:云信红包
 */
@property (copy, nonatomic) NSString *desc;

/**
 红包的文字内容,为title和desc拼接的字符串
 */
@property (nonatomic,copy) NSString *content;

/**
 红包ID
 */
@property (copy, nonatomic) NSString *bribery_ID;
@implementation JRMFRedPacketAttachment
// 自定义消息解码,必须实现的方法
- (NSString *)encodeAttachment {
    
    NSDictionary *dictContent = @{CMBriberyMsg: self.title, CMContent: self.content, CMBriberyName: self.desc , CMBriberyId: self.bribery_ID};
    NSDictionary *dict = @{CMType: @(CustomMessageTypeTest), CMData: dictContent};
    
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
                                                       options:0
                                                         error:nil];
    
    return [[NSString alloc] initWithData:jsonData
                                 encoding:NSUTF8StringEncoding];
}

// 该方法返回消息view的大小 
// kRedPacketImage为自己在外部定义的静态方法,用来获取图片Image,用户可自行定义
- (CGSize)contentSize:(NIMMessage *)message cellWidth:(CGFloat)width {
   return kRedPacketImage(@"bg_from_hongbao");
}

// 该方法返回消息内容和消息view的边界距离
- (UIEdgeInsets)contentViewInsets:(NIMMessage *)message {
    CGFloat bubblePaddingForImage    = 3.f;
    CGFloat bubbleArrowWidthForImage = 5.f;
    if (message.isOutgoingMsg) {
        return  UIEdgeInsetsMake(bubblePaddingForImage,bubblePaddingForImage,bubblePaddingForImage,bubblePaddingForImage + bubbleArrowWidthForImage);
    }else{
        return  UIEdgeInsetsMake(bubblePaddingForImage,bubblePaddingForImage + bubbleArrowWidthForImage, bubblePaddingForImage,bubblePaddingForImage);
    }
}

// 该方法返回与之相关联的显示消息的view,JRMFSessionRedPacketContentView为创建的消息view
- (NSString *)cellContent:(NIMMessage *)message{
    return @"JRMFSessionRedPacketContentView";
}

红包领取提示消息对象

@interface JRMFRedPacketOpenAttchment : NSObject <NIMCustomAttachment, NTESCustomAttachmentInfo>

/**
 红包发送者ID
 */
@property (nonatomic, strong) NSString * sendPacketId;

/**
 红包发送者名字
 */
@property (strong, nonatomic) NSString *sendNickName;

/**
 拆红包ID
 */
@property (nonatomic, strong) NSString * openPacketId;

/**
 *  红包ID
 */
@property (nonatomic, strong) NSString * packetId;

/**
 是否为最后一个红包
 */
@property (nonatomic, strong) NSString * isGetDone;

/**
 *  拆红包者昵称
 */
@property (nonatomic, strong) NSString * openNickName;

/**
 展示的领取信息
 */
@property (copy, nonatomic) NSString *openMessage;

【注:在@implementation JRMFRedPacketOpenAttchment中的实现和JRMFRedPacketAttachment大体相同,具体内部实现根据需求操作(参考demo)】

红包消息界面

static NSString *const JRMFRedPacketEventOpen = @"JRMFRedPacketEventOpen";

@interface JRMFSessionRedPacketContentView : NIMSessionMessageContentView
/**
 祝福语
 */
@property (nonatomic,strong) UILabel *titleLabel;

/**
 红包操作描述语,如:领取红包,查看红包
 */
@property (nonatomic,strong) UILabel *subTitleLabel;

/**
 红包描述,如:云信红包
 */
@property (strong, nonatomic) UILabel *descLabel;
@interface JRMFSessionRedPacketContentView ()
// 拆红包的点击手势
@property (strong, nonatomic) UITapGestureRecognizer *tap;

@end

@implementation JRMFSessionRedPacketContentView

- (instancetype)initSessionMessageContentView{
    self = [super initSessionMessageContentView];
    if (self) {
        
        // 添加点击手势 -- 用于拆红包
        _tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)];
        [self addGestureRecognizer:_tap];
        // 内容布局
        _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _titleLabel.font = [UIFont systemFontOfSize:13.f];
        _subTitleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _subTitleLabel.font = [UIFont systemFontOfSize:12.f];
        _descLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _descLabel.font = [UIFont systemFontOfSize:12.f];
        
        [self addSubview:_titleLabel];
        [self addSubview:_subTitleLabel];
        [self addSubview:_descLabel];
    }
    return self;
}

#pragma mark - 点击手势
- (void)tapGesture:(UITapGestureRecognizer *)recognizer {
    if ([self.delegate respondsToSelector:@selector(onCatchEvent:)]) {
        NIMKitEvent *event = [[NIMKitEvent alloc] init];
        event.eventName = JRMFRedPacketEventOpen;
        event.messageModel = self.model;
        event.data = self;
        [self.delegate onCatchEvent:event];
    }
}

#pragma mark - 系统父类方法
- (void)refresh:(NIMMessageModel*)data{
    //务必调用super方法
    [super refresh:data];
    
    NIMCustomObject *object = data.message.messageObject;
    JRMFRedPacketAttachment *attachment = (JRMFRedPacketAttachment *)object.attachment;
    
    self.titleLabel.text = attachment.title;
    self.descLabel.text = attachment.desc;

    self.titleLabel.textColor = [UIColor whiteColor];
    self.subTitleLabel.textColor = [UIColor whiteColor];
    self.descLabel.textColor = [UIColor lightGrayColor];

    [_titleLabel sizeToFit];
    CGRect rect = _titleLabel.frame;
    if (CGRectGetMaxX(rect) > self.bounds.size.width) {
        rect.size.width = self.bounds.size.width - rect.origin.x - 20;
        _titleLabel.frame = rect;
    }
    
    [_subTitleLabel sizeToFit];
    [_descLabel sizeToFit];
}

- (UIImage *)chatBubbleImageForState:(UIControlState)state outgoing:(BOOL)outgoing {
    if (outgoing) {
        // 当消息头像位于右边的时候cell显示的内容,以及返回背景图片
    }else {
        // 当消息头像位于左边的时候cell显示的内容,以及返回背景图片
    }
}

红包领取提示消息界面

static NSString *const JRMFRedPacketEventOpenMessage = @"JRMFRedPacketEventOpenMessage";

@interface JRMFSessionRedPacketOpenContentView : NIMSessionMessageContentView

// 提示的Label
@property(strong, nonatomic) UILabel *messageLabel;

@implementation JRMFSessionRedPacketOpenContentView 

// 实现JRMFSessionRedPacketContentView(红包发送界面)中相同的方法
.........

// 注意在以下方法中返回一个空的图片就好
- (UIImage *)chatBubbleImageForState:(UIControlState)state outgoing:(BOOL)outgoing {
    return [UIImage alloc];
}

在demo中已经实现了该协议的方法,我们只需要在内部添加我们需要的配置就可以了

  1. 在init方法的_type中添加自定义消息对象JRMFRedPacketAttachmentJRMFRedPacketOpenAttchment

  2. 当显示的消息是领取红包的提示信息的时候不显示头像和昵称

// 头像显示
- (BOOL)shouldShowAvatar:(NIMMessageModel *)model{
    .......  
    if ([self isRedPacketOpenMessage:model.message]) {
        return NO;
    }
    
    return [super shouldShowAvatar:model];
}
// 昵称显示
- (BOOL)shouldShowNickName:(NIMMessageModel *)model{
    .......
    if ([self isRedPacketOpenMessage:model.message]) {
        return NO;
    }
    
    return [super shouldShowNickName:model];
}

// 不显示红包领取的头像和昵称
- (BOOL)isRedPacketOpenMessage:(NIMMessage *)message {
    if (message.messageType == NIMMessageTypeCustom) {
        NIMCustomObject *object = message.messageObject;
        if (object) {
            if ([object.attachment isKindOfClass:[JRMFRedPacketOpenAttchment class]]) {
                return YES;
            }
        }
    }
    return NO;
}

3.将创建好的布局配置类注入到组件中,保证在会话页实例化之前注入即可。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
   ...

    //注册 NIMKit 自定义排版配置
    [[NIMKit sharedKit] registerLayoutConfig:[CellLayoutConfig class]];

   ...
}
// onTapMediaItemRedPacket:是点击事件的方法名,一定要与NTESSessionViewController中的自定义的点击方法名称一样
NIMMediaItem *redPacket = [NIMMediaItem item:@"onTapMediaItemRedPacket:" normalImage:[UIImage imageNamed:@"ic_hongbao"] selectedImage:[UIImage imageNamed:@"ic_hongbao"] title:@"红包"];

......

// 將redPacket按钮添加到数组items中,并将items添加defaultMediaItems返回
return [defaultMediaItems arrayByAddingObjectsFromArray:items];
// 发送红包
+ (NIMMessage *)msgWithRedPacket:(JRMFRedPacketAttachment *)attachment {
    NIMMessage *message               = [[NIMMessage alloc] init];
    NIMCustomObject *customObject     = [[NIMCustomObject alloc] init];
    customObject.attachment           = attachment;
    message.messageObject             = customObject;
    
    NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
    setting.apnsEnabled = NO;
    message.setting = setting;
    return message;
}

// 领取红包后显示的提示信息
+ (NIMMessage *)msgWithOpenRedPacket:(JRMFRedPacketOpenAttchment *)attachment {
    NIMMessage *message               = [[NIMMessage alloc] init];
    NIMCustomObject *customObject     = [[NIMCustomObject alloc] init];
    customObject.attachment           = attachment;
    message.messageObject             = customObject;
    message.remoteExt                 = @{
                                          CMSendPacketAccid: attachment.sendPacketId,
                                          CMOpenPacketAccid: attachment.openPacketId
                                          };
    
    NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
    setting.apnsEnabled = NO;
    message.setting = setting;
    return message;
}
4、消息发送及消息事件处理
// 附加按钮中红包发送点击事件
- (void)onTapMediaItemRedPacket:(NIMMediaItem *)item {
   .......
// 在这里调用红包发送的接口
}

#pragma mark - 红包发送回调
// 调用红包发送的回调方法(魔方SDK提供)
- (void)dojrmfActionDidSendEnvelopedWithID:(NSString *)envId Name:(NSString *)envName Message:(NSString *)envMsg Stat:(jrmfSendStatus)jrmfStat {

// 当红包发送成功之后,给消息对象赋值,并发送消息
    if (jrmfStat == kjrmfStatSucess) {
        JRMFRedPacketAttachment *attachment = [[JRMFRedPacketAttachment alloc] init];
        attachment.title = envMsg;
        attachment.bribery_ID = envId;
        attachment.desc = envName;

        // 发送消息
        [self sendMessage:[NTESSessionMsgConverter msgWithRedPacket:attachment]];
    }
}


- (void)onTapCell:(NIMKitEvent *)event {
   .......
   // 拆(领取)红包
   if([eventName isEqualToString:JRMFRedPacketEventOpen]){
      // 用户相关信息获取(参照Demo)
      ......
      // 调用拆红包的接口(魔方SDK提供)
      [jrmf doActionPresentOpenViewController:self thirdToken:[JRMFSington GetPacketSington].JrmfThirdToken withUserName:nickName userHead:headUrl userID:userId envelopeID:attachment.bribery_ID isGroup:isGroup];
      handled = YES;  //必须设置为YES,不然会崩溃
      
    //拆红包消息提示语“红包”字段的点击事件
   }else if([eventName isEqualToString:JRMFRedPacketEventOpenMessage]) {
        ......
        // 调用展示详情页面的接口
        [jrmf doActionPresentPacketDetailInViewWithUserID:userId packetID:attachment.packetId thirdToken:[JRMFSington GetPacketSington].JrmfThirdToken];
        handled = YES;
    }
}

#pragma mark - 成功领取一个红包
// 成功领取一个红包后的回调方法(魔方SDK提供)
- (void)dojrmfActionOpenPacketSuccessWithGetDone:(BOOL)isDone{
   ......
   [self sendMessage:[NTESSessionMsgConverter msgWithOpenRedPacket:attachment]];
}
5、消息接收
@implementation NTESCustomAttachmentDecoder
- (id<NIMCustomAttachment>)decodeAttachment:(NSString *)content
{
    ......
        if ([dict isKindOfClass:[NSDictionary class]])
        {
           ......
           switch (type) {
           ......
           // 在当前方法中添加红包消息的解码信息
                case CustomMessageTypeRedPacket:
                {
                    attachment = [[JRMFRedPacketAttachment alloc] init];
                    ((JRMFRedPacketAttachment *)attachment).title = [data jsonString:CMBriberyMsg];
                    ((JRMFRedPacketAttachment *)attachment).content = [data jsonString:CMContent];
                    ((JRMFRedPacketAttachment *)attachment).desc = [data jsonString:CMBriberyName];
                    ((JRMFRedPacketAttachment*)attachment).bribery_ID = [data jsonString:CMBriberyId];
                }
                    break;
                case CustomMessageTypeRedPacketOpen:
                {
                    attachment = [[JRMFRedPacketOpenAttchment alloc] init];
                    ((JRMFRedPacketOpenAttchment *)attachment).sendPacketId = [data jsonString:CMSendPacketId];
                    ((JRMFRedPacketOpenAttchment *)attachment).openNickName = [data jsonString:CMOpenNickName];
                    ((JRMFRedPacketOpenAttchment *)attachment).packetId = [data jsonString:CMPacketId];
                    ((JRMFRedPacketOpenAttchment *)attachment).isGetDone = [data jsonString:CMIsGetDone];
                    ((JRMFRedPacketOpenAttchment *)attachment).openPacketId = [data jsonString:CMOpenPacketId];
                    ((JRMFRedPacketOpenAttchment *)attachment).openMessage = [data jsonString:CMOpenMessage];
                    ((JRMFRedPacketOpenAttchment *)attachment).sendNickName = [data jsonString:CMSendNickName];
                }
                    break;
                default:
                    break;
            }
            attachment = [self checkAttachment:attachment] ? attachment : nil;
        }
    ......
}


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ...
    [NIMCustomObject registerCustomDecoder:[[AttachmentDecoder alloc]init]];
    ... 
}
@implementation NTESAppDelegate
- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages{
    // 在该方法中对消息进行筛选,并在筛选完成之后通知UI界面不显示该消息(详情见Demo)
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 设置代理对象
    [[NIMSDK sharedSDK].chatManager addDelegate:self];
    ......
}
6、消息列表最近消息展示
// 在该方法中添加对应的展示信息
- (NSString *)contentForRecentSession:(NIMRecentSession *)recent{
    // 根据object.attachment的类型来确定展示的信息
}

7、在设置页面接入“我的钱包”
@interface NTESSettingViewController ()<NIMUserManagerDelegate>
- (void)buildData{
    ......
    NSArray *data = @[
                      ......
                      @{
                          HeaderTitle:@"",
                          RowContent :@[
                                          @{
                                             Title       :@"我的钱包",
                                             CellAction  :@"onTouchShowWallet:",
                                             ShowAccessory : @(YES)
                                          },
                                       ],
                          FooterTitle:@""
                                  },
                      ......
                    ];
    ......
}

// 点击“我的钱包”事件
- (void)onTouchShowWallet:(id)sender {
    JrmfWalletSDK * jrmf = [[JrmfWalletSDK alloc] init];
    NSString *userId = [[NIMSDK sharedSDK].loginManager currentAccount];
    NIMKitInfo *userInfo = [[NIMKit sharedKit] infoByUser:userId];

    //展示我的钱包页面
    [jrmf doPresentJrmfWalletPageWithBaseViewController:self userId:userId userName:userInfo.showName userHeadLink:userInfo.avatarUrlString thirdToken:[JRMFSington GetPacketSington].JrmfThirdToken];
}
8、用户基本信息更新
//  在云信中更新用户信息之后需要手动调用该方法来更新红包中的用户信息(魔方SDK接口)
+ (void)updateUserMsgWithUserId:(NSString *)userId userName:(NSString *)userName userHead:(NSString *)userHeadLink thirdToken:(NSString *)thirdToken completion:(void (^)(NSError *error, NSDictionary *resultDic))completionAction;
上一篇下一篇

猜你喜欢

热点阅读