红包

网易云信红包服务依托于金融魔方,所由涉及钱包、金钱相关的业务均由金融魔方SDK(以下简称jrmf SDK)提供,云信IM 能力提供账号绑定以及红包发送、接收通道。基于网易云信以及jrmf可以快速集成发单聊红包、发群聊红包、拆红包并查看交易记录等功能。一个完整的红包操作流程如下图

image

开发者从云信SDK获取thirdToken,以标识操作者身份,作为调用jrmf SDK 每一个接口的必备参数。

注意,云信 SDK 只负责提供 thirdToken。

接入准备

导入 jrmf SDK

jrmf SDK 以Android Library 的方式提供,全称 jrmfneteaselib,jrmf 为云信提供了专属定制SDK,与通用版本存在差异。开发者有多种方式获取jrmf SDK:

配置说明

jrmf SDK 需要开发者在 AndroidManifest.xml 中配置渠道id以及红包名字:渠道是 金融魔方给客户分配的唯一识别id;红包名字为用户发红包时显示的名称。值得注意的是,对于网易云信版SDK,直接使用云信为客户分配的 appKey 作为渠道id,并且如果已经在 AndroidManifest.xml 配置了云信appkey,就不需要再配置渠道id。

云信appkey 配置示例,如果配置了此项,不必再配置 JRMF_PARTNER_ID。

<meta-data
    android:name="com.netease.nim.appKey"
    android:value="45c6af3c98409b18a84451215d0bdd6e" />

渠道ID 配置示例:

<meta-data
    android:name="JRMF_PARTNER_ID"
    android:value="45c6af3c98409b18a84451215d0bdd6e"/>

红包名称配置示例:

<meta-data
    android:name="JRMF_PARTNER_NAME"
    android:value="云信红包"/>

此外,如果需要使用微信支付(需要开发者到微信和银行申请开通),需要添加如下配置

<!--微信配置开始-->

    <!-- 请替换实际工程中 WXPayEntryActivity 的包路径 -->
    <activity
        android:name=".wxapi.WXPayEntryActivity" 
        android:exported="true"
        android:launchMode="singleTop" />
    <activity
        android:name="com.switfpass.pay.activity.PayResultActivity"
        android:exported="true"
        android:launchMode="singleTop" />
<!--微信配置结束-->

获取thirdToken

由云信 SDK 提供获取thirdToken 接口。

/**
 * 获取红包SDK token
 *
 * @return InvocationFuture 可以设置回调函数
 */
InvocationFuture<String> getRedPacketAuthToken();
NIMClient.getService(RedPacketService.class).getRedPacketAuthToken().setCallback(new RequestCallbackWrapper<String>() {
        @Override
        public void onResult(int code, String result, Throwable exception) {
            if (code == ResponseCode.RES_SUCCESS) {
                // 缓存token
                thirdToken = result;
            } else if (code == ResponseCode.RES_RP_INVALID) {
                // 红包功能不可用

            } else if (code == ResponseCode.RES_FORBIDDEN) {
                // 应用没开通红包功能
            }
        }
    });
}

jrmf SDK 功能介绍

发单个红包、发群聊红包、转账、转账收款、转账退款、抢单聊红包、抢群红包,查看交易记录以及更新用户信息(头像和昵称)功能都由JrmfRpClient提供。

初始化

需要在应用自定义的Application中初始化金融魔方的类库,示例代码如下:

public class MyApplication extends Application {

    @Override public void onCreate() {
        super.onCreate();
        //用户可以调用该方法进行测试环境,正式环境切换;默认是正式环境
        //设置为测试环境
        JrmfClient.isDebug(true);
        /**
        * 初始化程序-必须调用
        *    【必传】上下文
        */
        JrmfClient.init(this);
        /**
         * 设置微信您在微信平台申请的appid
         * 如果不使用微信支付可以不调用
         * 
         */
        JrmfClient.setWxAppid("wx2a5538052969956e");
    }
}

红包功能

/**
 * 打开发送群组红包界面
 *
 * @param context【必传】上下文对象
 * @param targetId【必传】目标ID(会话ID)
 * @param userid【必传】用户ID|当前用户ID
 * @param thirdToken【必传】三方签名令牌(服务端计算后给到app,服务端算法为md5(custUid+appsecret))
 * @param groupNum【必传】群组人数
 * @param username【可为NULL或""】用户昵称
 * @param usericon【可为NULL或""】用户头像URL
 * @param requestCode【必传】在onActivityResult方法中回调
 */
public static void sendGroupEnvelopeForResult(Context context, String 
    targetId, String userid, String thirdToken, int groupNum,
    String username, String usericon, int requestCode);
/**
 * 打开发送单聊红包界面
 *
 * @param context【必传】上下文对象
 * @param targetId【必传】目标ID(单聊会话ID)
 * @param userid【必传】用户ID|当前用户ID
 * @param thirdToken【必传】三方签名令牌
 * @param username【可为NULL或""】用户昵称
 * @param usericon【可为NULL或""】用户头像URL
 * @param requestCode【必传】在onActivityResult方法中回调
 */
public static void sendSingleEnvelopeForResult(Context context, 
    String targetId, String userid, String thirdToken, String username, 
    String usericon, int requestCode)
/**
 * 抢群红包
 * 
 * @param activity [必传] 上下文
 * @param userid [必传] 用户id
 * @param thirdToken [必传]三方签名令牌
 * @param username [可为空] 用户姓名
 * @param usericon [可为空] 用户头像
 * @param envelopeId [必传] 红包id
 * @param callBack [必传] 抢红包回调接口
 */
public static void openGroupRp(FragmentActivity activity, String userid,  String thirdToken, String username,  String usericon,
    String envelopeId,GrabRpCallBack callBack);
/**
 * 打开单聊红包
 * 
 * @param activity [必传] 上下文
 * @param userid [必传] 用户id
 * @param thirdToken [必传]
 * @param username [可为空] 用户姓名
 * @param usericon [可为空] 用户头像
 * @param envelopeId [必传] 红包id
 * @param callBack [必传] 抢红包回调接口
 */
public static void openSingleRp( FragmentActivity activity,
     String userid,  String thirdToken,  String username,  String usericon, 
     String envelopeId, GrabRpCallBack callBack);
/**
 * 打开红包详情,只针对群红包使用
 * 
 * @param fromActivity [必传] 上下文
 * @param userId [必传] 用户id
 * @param thirdToken [必传]三方签名令牌
 * @param rpId [必传] 红包id
 * @param username [可为空] 用户昵称
 * @param usericon [可为空] 用户头像
 */
public static void openRpDetail(Activity fromActivity, 
    String userId, String thirdToken, String rpId, String username,
    String usericon);
@Override
public void grabRpResult(GrabRpBean grabRpBean) {
    if (grabRpBean.isHadGrabRp()) {
        cb.sendMessage(selfInfo.getAccount(), briberyId, grabRpBean.getHasLeft() == 0);
    }
}

发红包的回调

发红包通过请求码在onActivityResult中处理回调

/**
 * 发红包成功的回调
 * @param requestCode
 * @param resultCode
 * @param data
 */
@Override protected void onActivityResult(int requestCode, int
resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case SEND_GROUP:
            if (resultCode == RESULT_OK) {
                groupRpBean = JrmfRpClient.getEnvelopeInfo(data);
            }
            break;
        case SEND_SINGLE:
            // 发了单聊红包
            if (resultCode == RESULT_OK) {
                singleRpbean = JrmfRpClient.getEnvelopeInfo(data);
            }
            break;
    }
}

发红包成功过后会得到EnvelopeBean,包含下面三个属性:

查看交易记录

查看交易记录接口,如果开发者集成了钱包则无需使用该接口,因为钱包中有此功能

/**
 * 打开查看交易记录
 * 
 * @param fromActivity [必传] 上下文
 * @param userId [必传] 用户id
 * @param thirdToken [必传]
 */
public static void openTradeHistory(Activity fromActivity, 
String userId, String thirdToken);

更新用户信息

如果当前的用户昵称或者头像发生改变请调用该方法,该方法添加了回调接口,用户可以根据接口返回的model直接判断用户信息是否更新成功;

/**
 * 更新用戶信息接口 此接口需要开发者自己回调处理
 *
 * @param custUid【必传】用户ID|当前用户ID
 * @param thirdToken【必传】
 * @param nickName 【必传】将要更新的用户昵称
 * @param avatar【必传】将要更新的用户头像URL
 */
JrmfRpClient.updateUserInfo(USER_ID, MainActivity.thirdToken,
USER_NAME_UPDATE, USER_ICON, new OkHttpModelCallBack<BaseModel>() {
        @Override
        public void onSuccess(BaseModel baseModel) {
            if (baseModel.isSuccess()) {
                ToastUtil.showToast(RedPacketActivity.this,
                "更新用户信息成功");
            } else {
                ToastUtil.showToast(RedPacketActivity.this,
                "更新用户信息失败:" + baseModel.respmsg);
            }
        }

        @Override
        public void onFail(String result) {
            ToastUtil.showToast(RedPacketActivity.this,
            "更新用户信息失败");
        }
    });

其它功能

如果您的账号被登出或者其它场景需要关闭所有已经打开的Activity的情况,可以调用如下方法去关闭jrmf sdk中的Activity:

CusActivityManager.getInstance().finishAllActivity();

至此,所有的功能介绍完了,下面介绍云信 Demo 如何利用jrmf 实现红包功能。

云信 Demo 实现红包功能流程

jrmf SDK 导入和配置完成了,接下来可以真正利用云信和jrmf 的强大功能,实现发送、接收红包消息。云信在Demo 中给出了一种实现方式,供开发者参考。

thirdToken 管理

注册登录状态观察者,接收到登录状态变成已登录的通知之后,检查缓存中是否存在 thirdToken,如果缓存 thirdToken 为空,则调用 SDK 接口获取 thirdToken。

private static Observer<StatusCode> observer = new Observer<StatusCode>() {
    @Override
    public void onEvent(StatusCode statusCode) {
        if (statusCode == StatusCode.LOGINED) {
            getThirdToken();
        }
    }
};
public static String getThirdToken() {
    if (TextUtils.isEmpty(thirdToken)) {
        NIMClient.getService(RedPacketService.class).getRedPacketAuthToken().setCallback(new RequestCallbackWrapper<String>() {
            @Override
            public void onResult(int code, String result, Throwable exception) {
                if (code == ResponseCode.RES_SUCCESS) {
                    thirdToken = result;
                } else if (code == ResponseCode.RES_RP_INVALID) {
                    // 红包功能不可用
                    Toast.makeText(DemoCache.getContext(), "红包功能不可用", Toast.LENGTH_SHORT).show();
                } else if (code == ResponseCode.RES_FORBIDDEN) {
                    // 应用没开通红包功能
                    Toast.makeText(DemoCache.getContext(), "应用没开通红包功能", Toast.LENGTH_SHORT).show();
                }
            }
        });        }
    return thirdToken;
}

分别使用自定义消息表示发送红包、解开红包

public class RedPacketAttachment extends CustomAttachment {

    private String content;//  消息文本内容
    private String redPacketId;//  红包id
    private String title;// 红包名称

    private static final String KEY_CONTENT = "content";
    private static final String KEY_ID = "redPacketId";
    private static final String KEY_TITLE = "title";
    /**
    * other
    */
}
public class RedPacketOpenedAttachment extends CustomAttachment {
    private String sendAccount; //发送红包ID
    private String openAccount; //打开红包ID
    private String redPacketId;     //红包ID
    private boolean isGetDone;    //是否被领完

    private static final String KEY_SEND = "sendPacketId";
    private static final String KEY_OPEN = "openPacketId";
    private static final String KEY_RP_ID = "redPacketId";
    private static final String KEY_DONE = "isGetDone";

    /**
    * other
    */
}

image

消息拦截

群组中的红包领取信息,如果不是红包发送者或者是领取者,则需要进行红包消息拦截处理。详见源码中 RpOpenedMessageFilter。