同步到第三方网站的设计架构

29 篇文章 0 订阅
16 篇文章 0 订阅

经常要做到分享到其他网站的情况,新浪,renren,qq空间,豆瓣等等

如果不好好设计,就会变得越来越乱


这里简述一下我的设计过程,以及如何解决


由于最先只涉及到新浪微博,所以上来下载新浪的sdk,绑定的时候,取sina的登陆url然后设置个回调地址,将token存到数据库


分享的时候,从数据库中去得token,然后调sdk的update将内容分享到新浪微博,ok,好像没什么问题


过了几天,问题来了,由于新浪微博的接口不稳定,有时候时间反应过慢,导致分享的时候会卡在那儿,造成并发太多,且影响用户体验


解决方案,将分享的数据插入队列,然后后台启动job,每几秒跑一次,这玩意不需要什么实时性,所以这问题解决



第二天,老板说要支持腾讯微博,ok,下载sdk,同样获取qq的登陆url,token存数据库,。。。。。,每次if判断,如果是这样就这样调sdk,如果是那样就那样调sdk,每次,如分享,取信息,等,全部按照sdk的步骤来一遍,ok,it works


if($type=='sina') {
     new sina_xxx ($token);
     sina.update()
} else if($type=='qq') { qq_xxx::init(xxx,xxx); qq_xxx::pub };

大量的if else ,有的第三方异常,就再特殊处理,全写在这个地方,很长,很丑陋

,but,it works


第三天,老板说,把renren豆瓣,都加上,用if来判断,又臭又长来了,,,大量重复代码,忍不了了,要优化,,,如何优化?


我们知道,分享到第三方,需要提供三个接口,1.获取登陆地址 2.获取用户资料 3.用登陆之后回调的参数获取token 4.用token进行内容分享,我们是否可以搞个类,然后只要传一个type,比如sina,就给我们一个api对象,然后把参数传进去,而且没歌种类的参数全部相同呢?当然可以,先顶一个sina的类,这个类需要完成几个接口,ok,接口,,如下:

interface Share_Interface {
    /**
     * 获取跳转认证的地址
     * */
    public function get_auth_url();
    /**
     * 分享文字内容
     * @param String $text  文字
     * */
    public function share($text);
    /**
     * 分享带图内容
     * @param String $text 文字
     * @param Url_String $pic 图片地址
     * */
    public function share_pic($text,$pic);
    /**
     * 获取用户信息
     * @return array('name'=>'text','pic'=>'http://www.reco.cn/111.jpg');
     * */
    public function get_user_info();
    /**
     * 通过数据库存储的token信息进行认证
     * @param array $data user_token的一条记录
     * */
    public function auth_by_data($data);
    /**
     * 通过第三方回跳穿过的参数进行认证
     * @param array $params 回调的,第三方传过来的参数
     * @return array 返回的参数,可直接用来插入到user_token表
     * */
    public function auth_by_params($params);
}
很好,那么对几个第三方网站一个一个来进行实现,实现的时候,发现几个方法是可以共用的,有几个是必须要实现的,ok,咱们来个抽象类

<?php
abstract class Share_Abstract {
    public $config;
    public $return_url;
    public $token;
    public $share_user_id;
    abstract public function get_type();
    
    public function __construct() {
        $this->config = RSF::get_instance()->get_config($this->get_type(),'share');
        $this->return_url = $this->config['return_url'];
    }
    public function set_return_url($url){
        $this->return_url = $url;
    }
    public function get_return_url(){
        return $this->return_url;
    }
    public function set_token_uid($token,$uid) {
        $this->token = $token;
        $this->share_user_id = $uid;
    }
    public function get_share_user_id() {
        return $this->share_user_id;
    }
    public function auth_by_data($data) {
        $this->share_user_id = $data['share_user_id'];
        $this->token = $data['token'];
        $this->extend_data = json_decode($data['extend_data'],true);
    }
}

实现sina的接口,就要集成,和完成这些接口了

class Share_Sina_Interface extends Share_Abstract implements Share_Interface {
    public function get_type() {
        return 'sina';
    }
    public function get_auth_url() {
        $sina_auth = new Share_Sina_Auth($this->config['WB_AKEY'],$this->config['WB_SKEY']);
        $return_url = $this->get_return_url();
        $auth_url = $sina_auth->getAuthorizeURL($return_url);
        return $auth_url;
    }
    public function share($text){
        
    }
    public function share_pic($text,$pic){
        
    }
    
    public function get_user_info(){
        $pub = new Share_Sina_Publish($this->config['WB_AKEY'],$this->config['WB_SKEY'],$this->token);
        $info = $pub->show_user_by_id($this->share_user_id);
        return array('name'=>$info['name'],'pic'=>$info['avatar_large']);
    }
    public function auth_by_data($data) {
        $this->share_user_id = $data['share_user_id'];
        $this->token = $data['token'];
    }
    /**
     * 通过传过来的参数进行认证,获取token,等
     * 返回的数据用于插入token表
     * */
    public function auth_by_params($params){
        $code = $params['code'];
        $sina_auth = new Share_Sina_Auth($this->config['WB_AKEY'],$this->config['WB_SKEY']);
        $data = array('code' => $code, 'redirect_uri' => $this->get_return_url());
        $response_data = $sina_auth -> getAccessToken('code', $data);
        $this->token = $response_data['access_token'];
        $this->share_user_id = $response_data['uid'];
        $data = array(
            'token'=>$response_data['access_token'],
            'share_user_id'=>$response_data['uid'],
            'share_type'=>'sina',
            'expires_in'=>$response_data['expires_in'],
            'fresh_time'=>time(),
            'extend_data'=>''
        );
        return $data;
    }
}

同样,其它的类似实现

调的时候,还是要if(xxx=sina) {  new xxx_interface()}

不够完美,ok,很明显,来个工厂

<?php
class Share_Factory {
    public static function create($type) {
        $type = ucfirst($type);
        $api_name = 'Share_'.$type.'_Interface';
        rsf_require_class($api_name);
        if(class_exists($api_name)){
            $api = new $api_name();
            return $api;
        }
    }
}



这样只要

Share_Factory::create('sina')


很漂亮有木有?php的优化完成,



第四天,老板又说话,要加第三方登录功能,我想当然,传递不用回调地址给第三方,然后获取昵称和头像,写进数据库,so easy,实现的时候发现一个严重的问题,有些第三方的回调地址必须填写和你注册时候填写的一摸一样,加个参数都不行,代表的就是豆瓣,腾讯微博,


解决方案,每次需要登录第三方的时候,用window.open弹窗,同时这只一个js全局函数,弹窗验证完毕后,再用js的opener对象来执行这个函数,获取到的参数用base_64加密给js,然后js负责跳转,ok,同域名下完美解决,


但是如果是个二级域名下,那么窗口就没有权限执行,opener的函数,咋办?

解决方案,如果发现没有权限,可以用try{}catch(){}来判断,自动将这些参数,提交给二级域名,进行跳转,然后再来执行opener的函数,完美解决


所有的运行效果,可以来我们的网站观察  www.reco.cn




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值