支付宝授权获取芝麻信用分数

来源:互联网 发布:mac u盘装win8单系统 编辑:程序博客网 时间:2024/04/30 05:07

貌似好久没写文章了,今天来记录下最近用支付宝SDK获取芝麻信用分数的过程,以及踩过的坑。

个人感觉接芝麻信用分数时还是很简单的,基本都是服务端的任务,我们这边只需要将从支付宝授权获取的auth_code传给服务端,剩下的就是服务器的事了。但是还是有些小坑需要记录。

如果以后需要做支付宝登陆的,可以看这里,还是很详细的
Android 集成支付宝第三方登录

其实看官方的Demo也是很好的

踩坑一

当我把官方Demo下下来,配好APPID,PID,RSA2_PRIVATE之后,直接运行Demo直接蹦了,我就懵了,官方Demo居然会有问题,好吧,通过调试,定位是空指针

String oriSign = SignUtils.sign(authInfo.toString(), rsaKey, rsa2);

这里返回了null,无语了,通过网上查找问题,需要对其中封装好的方法修改

public static String sign(String content, String privateKey, boolean rsa2) {    try {        PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(                Base64.decode(privateKey));    //后面需要下个"BC"参数                  KeyFactory keyf = KeyFactory.getInstance(ALGORITHM, "BC");        PrivateKey priKey = keyf.generatePrivate(priPKCS8);        java.security.Signature signature = java.security.Signature                .getInstance(getAlgorithms(rsa2));        signature.initSign(priKey);        signature.update(content.getBytes(DEFAULT_CHARSET));        byte[] signed = signature.sign();        return Base64.encode(signed);    } catch (Exception e) {        e.printStackTrace();    }    return null;}

修改之后就不会返回null。

然后就可以通过将签名之后的参数传给AuthTask的authV2授权,授权成功之后就可以获取auth_code,然后传给服务器。

踩坑二

我从支付宝获取的auth_code传给服务器,服务器居然不能用,好吧,尴尬的我本来想去问支付宝技术人员的,但是后台人员说可以修改scope的value为auth_zhima,当我修改之后居然真的成功了,好吧,支付宝文档上居然没有记录,这文档真心烂。。。。

public static Map<String, String> buildAuthInfoMap(String pid, String app_id, String target_id, boolean rsa2) {    Map<String, String> keyValues = new HashMap<String, String>();    // 商户签约拿到的app_id,如:2013081700024223    keyValues.put("app_id", app_id);    // 商户签约拿到的pid,如:2088102123816631    keyValues.put("pid", pid);    // 服务接口名称, 固定值    keyValues.put("apiname", "com.alipay.account.auth");    // 商户类型标识, 固定值    keyValues.put("app_name", "mc");    // 业务类型, 固定值    keyValues.put("biz_type", "openservice");    // 产品码, 固定值    keyValues.put("product_id", "APP_FAST_LOGIN");    // 修改这里    // 授权范围, 固定值    keyValues.put("scope", "auth_zhima");    // 商户唯一标识,如:kkkkk091125    keyValues.put("target_id", target_id);    // 授权类型, 固定值    keyValues.put("auth_type", "AUTHACCOUNT");    // 签名类型    keyValues.put("sign_type", rsa2 ? "RSA2" : "RSA");    return keyValues;}

注意:支付宝的芝麻信用分数获取和支付公用的一套SDK,并且授权用到的sign,需要从服务器获取,如果直接在客户端生成那是不安全的。

获取分数的部分代码

public class ZhiMaUtil {    private static final int SDK_AUTH_Cacel = -1;    private static final int SDK_AUTH_Fail = 0;    private static final int SDK_AUTH_Success = 1;    private Context mContext;    private Callback mCallback;    private String token;    public ZhiMaUtil(Context context){        this.mContext = context;            }    @SuppressLint("HandlerLeak")    private Handler mHandler = new Handler() {        @Override        @SuppressWarnings("unused")        public void handleMessage(Message msg) {            switch (msg.what) {                case SDK_AUTH_Cacel: {                    mCallback.getScoreFailed("用户取消授权");                    break;                }                case SDK_AUTH_Fail: {                    mCallback.getScoreFailed("授权失败");                    break;                }                case SDK_AUTH_Success:{                    AuthResult authResult = new AuthResult((Map<String, String>) msg.obj, true);                    getMineService().getZmScore(token, authResult.getAuthCode()).enqueue(new retrofit2.Callback<BaseBean>() {                        @Override                        public void onResponse(Call<BaseBean> call, Response<BaseBean> response) {                            if(response.isSuccessful()&&response.body() != null){                                BaseBean baseBean = response.body();                                mCallback.getScoreSuccess(baseBean.getData(), "获取分数成功");                            }                        }                        @Override                        public void onFailure(Call<BaseBean> call, Throwable t) {                            mCallback.getScoreFailed("获取分数失败");                            circleProgressDialog.dismiss();                        }                    });                }                default:                    break;            }        }    };    public void zhiMaAuthTask(Callback callback){        if(callback == null){            throw new RuntimeException("callback can not null!!");        }        mCallback = callback;        token = "Bearer "+Preferences.getInstance().getAccessToken(mContext);        getMineService().getAuthSign(token).enqueue(new retrofit2.Callback<BaseBean>() {            @Override            public void onResponse(Call<BaseBean> call, final Response<BaseBean> response) {                if(response.isSuccessful()&&response.body().getErrcode() == 0&&response.body()!=null){                    BaseBean body = response.body();                    Map<String, String> authInfoMap = OrderInfoUtil2_0.buildAuthInfoMap("你的pid", "你的app_id", String.valueOf(System.currentTimeMillis()), true);                    String info = OrderInfoUtil2_0.buildOrderParam(authInfoMap);                    final String authInfo = info + "&" + body.getData();                    Runnable authRunnable = new Runnable() {                        @Override                        public void run() {                            AuthTask authTask = new AuthTask((Activity) mContext);                            // 调用授权接口,获取授权结果                            Map<String, String> result = authTask.authV2(authInfo, true);                            AuthResult authResult = new AuthResult(result, true);                            String resultStatus = authResult.getResultStatus();                            //授权成功                            if(TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")){                                Message msg = new Message();                                msg.obj = result;                                msg.what = SDK_AUTH_Success;                                mHandler.sendMessage(msg);                            }else if(TextUtils.equals(resultStatus, "6001")){                                Message msg = new Message();                                msg.what = SDK_AUTH_Cacel;                                mHandler.sendMessage(msg);                            }else {                                Message msg = new Message();                                msg.what = SDK_AUTH_Fail;                                mHandler.sendMessage(msg);                            }                        }                    };                    // 必须异步调用                    Thread authThread = new Thread(authRunnable);                    authThread.start();                }else if(response.body() != null){                    LljApplication.showToastShort(response.body().getErrmsg());                }            }            @Override            public void onFailure(Call<BaseBean> call, Throwable t) {                mCallback.getScoreFailed("获取分数失败");            }        });    }    public interface Callback{        void getScoreSuccess(String score, String msg);        void getScoreFailed(String msg);    }

我们需要拷贝Demo里面的AuthResult,Base64,OrderInfoUtil2_0,SignUtils四个封装好的类。

上面代码是个工具类,功能还是很简单的,主要步骤如下:
1.获取服务器的sign,拼接客户端生成的info
2.通过拼接的参数,调用支付宝的SDK授权处理
3.获取auth_code,传给服务器获取分数
4.成功之后通过回调,传给ui显示

OK,芝麻信用分数获取成功。

原创粉丝点击