##前端开发第三方分享【/三方登录】功能备忘(facebook脸书、Whatsapp、weibo、QQ、weixin好友或者朋友圈)
平台 | 支持域名 | 备案 | 切换域名调整 | 平台名称 | 注意事项 | 🇭🇰境外 | 文档地址 |
---|---|---|---|---|---|---|---|
微信手机端H5 | 2个 | 不需要 | 支持2个域名,不用调整 | 微信公众平台 | 手机端和pc端注意用户二合一,通过unionId; 微信分享和登录都支持 | 支持 | 微信公众平台—>微信网页开发; 🔍网页授权、分享关键字 |
PC端微信登录 | 仅仅只能配置一个域名,必须修改1个 | 不需要 | 支持一个 | 微信开放平台 | 网页应用,切换环境必须修改配置,否则报错:redirect_uri参数错误,配置地址:应用详情->授权回调域;支持香港注册公司;pc扫描登录支持、pc分享其实是扫二维码,直接打开二维码。 | 支持 | 微信开放品台-网站应用微信登录 |
多个 | 必须,除非发邮件说明是国际域名证书 、公司营业执照 | 支持多个回调地址,必须配置到具体的页面 | 配置好,不用修改 | 常见问题,账号没有开通。或者 需要备案比较麻烦,需要配置回调地址,否则:redirect uri is illegal(100010) QQ互联加强网站应用回调地址校验 | - | QQ互联-OpenAPI调用说明_OAuth2.0 | |
sina | 3个+ | 不需要 | 不用,支持多个回到地址 | 新浪开发平台 | 支持相关个人公司 | 微博开放平台-授权机制 | |
n个 | 不需要 | 不用注册账号都可以 | facebook官网开发者 | 不用注册公司,当然需要扶梯一把 | 支持 | 分享调试器、facebook爬虫策略 | |
n个 | 不需要 | 不用注册账号都可以 | 不用注册公司,当然需要扶梯一把 | 支持 | HTML5网页点击分享到WHATSAPP |
前端分享有很多,常见有(facebook、weibo、QQ、weixin)
- 网站分享到facebook
- 微信授权登录问题【公众号登录、PC扫描登录】- 自己博客
- 微博.开放品台.授权机制
- QQ互联.openApi调用说明, web分享QQ好友、QQ空间、新浪微博的api接口, QQ的里面必须备案,一个账号只能添加一个域名。
- 微信-公众平台-JS-SDK说明文档 分享到朋友、朋友圈, 微信好友或者微信朋友,微信api提供的支持能力和修改分享标题和图片的能力。前提接口需要后期jsconfig信息。微信JSSDK使用步骤(用于在微信浏览器中自定义分享,分享到朋友圈,拍照,扫一扫等功能)
另外,在手机浏览器里面,facebook、weibo是直接打开他们的网站的。微信朋友圈、微信好友、QQ好友都是粘贴复制的。
网站分享到facebook
一、 facebook分享
1.1. facebook分享
facebook全球最大的社交网络平台,当然大陆的话是访问不了的,需要自己的解决。当经常有项目或者香港、澳门的项目或者稍微有点国际化的项目也需要使用facebook.
- facebook分享其实特别简单,第一不用注册开发者账号也可以正常使用。【一般就弹框打开一个链接,就可以分享了,pc和手机端是一样的】
- facebook风向出来的图片、文字、描述,需要在页面顶部meta标签里面说明。当然动态网站就需要自己想办法,比如vue、react写的页面,要么页面进行静态化、要么就后台走一个代理(判断是facebook排虫访问,就动态返回一个页面)。
#这里是java代码,就网页进行代理一次;
# 1:用户分享链接到facebook。
# 2:facebook 爬虫 访问我们系统,
# 3:当我们系统的代理nginx发现是是facebook爬虫访问话,我们重定向到 这个代理方法。
# 4:后台java 动态访问一个网页
/**
* 给动态facebook爬虫做代理
* 给动态网页做代理,比如网页分享到facebook的话,需要从【源码】读取 title、img,但是这些都是读取的源码 动态网页 vue、react 因此无法更改源码,动态更新的没用;
* 这里后台进行一次代理;这里配合 nginx 进行配置
* <p>
* # 如果user_agent是从facebook爬虫过来的; 我们 就 进入代理接口
* if ($http_user_agent ~* "facebookexternalhit") {
* ###### proxy ^/(.*)$ http://127.0.0.1:7777/ redirect;irect; #这种不能加$uri后缀了,很麻烦,需要同时有两个tomcat
* rewrite ^/(.*)$ https://test189.ourslook.com/qcure/proxy?$uri redirect; #直接302过去 后面不用 增加【?$args】; 会自动增加args的
* rewrite ^/(.*)$ $scheme://$host/qcure/proxy?$uri redirect; #直接302过去; 原始访问地址是: https://$host/qcurepc/xxx
* }
* <p>
* 网页分享到facebook, 异常简单,甚至 连 appid都不需要的; 网页分享到FACEBOOK https://www.cnblogs.com/phperlinxinlan/p/10529012.html
* <p>
* facebook 爬虫设置nginx设置 https://blog.csdn.net/moliyiran/article/details/54846799
* https://www.cnblogs.com/phperlinxinlan/p/10529012.html
* facebook web分享: 源站见评论 https://developers.facebook.com/docs/sharing/reference/feed-dialog
* facebook 分享的爬虫策略 源站见评论 https://developers.facebook.com/docs/sharing/webmasters/crawler?locale=zh_CN
* <p>
* 分享调试器:分享调试器:https://developers.facebook.com/tools/debug/sharing/
*
* @return 网页
*/
@ApiIgnore
@IgnoreAuthToken
@ResponseBody
@RequestMapping(value = "/proxy", produces = "text/html;charset=UTF-8", method = RequestMethod.GET)
public String proxy(
@ApiParam("网页的title,字段名:title,选填,默认是项目名称,方便调试") @RequestParam(value = "title", defaultValue = "QCURE", required = false) String title,
@ApiParam("网页的image,字段名:image,选填,默认这里放一个空图片,方便调试") @RequestParam(value = "image", defaultValue = "https://static.xx.fbcdn.net/rsrc.php/v3/y6/r/hlFyGnljr-d.png", required = false) String image,
HttpServletRequest request) {
try {
//这里对图片进行解码,防止图片是被多次encode之后的,encode之后的路径,可能访问不了
//这里就先两次解码把,应该不会有问题;如果出问题,后台就不帮前台处理了
image = EncodeUtils.urlDecode(image);
image = EncodeUtils.urlDecode(image);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String emptyHtml = "<!DOCTYPE html>\n" +
"<html>\n" +
"<head>\n" +
"\t<title>@@tilte</title>\n" +
"\t<title>@@image</title>\n" +
"\t<meta property=\"og:title\" content=\"@@tilte\" />\n" +
"\t<meta property=\"og:image\" content=\"@@image\" />\n" +
"</head>\n" +
"<body>\n" +
"\t我是后台转发的内容\n" +
"</body>\n" +
"</html>";
if (XaUtils.isValid(title)) {
emptyHtml = emptyHtml.replace("@@tilte", title);
}
if (XaUtils.isValid(image)) {
emptyHtml = emptyHtml.replace("@@image", image);
}
return emptyHtml;
}
参考:
网页分享到FACEBOOK【前端看这个文档就够了】
FACEBOOK分享调试器
facebook 分享的爬虫策略 源站见评论
二、 Whatsapp分享
网页不做处理,直接分享到Whatsapp是不显示标题、图片,体验不好;
因此,分享的时候我们需要对网页做处理。
由于我们做的网站是vue做的动态网站,并且没有做网页静态化,爬取到网页,这数据都是空的;因此需要我们后台做一个代理
<meta name="whatsapp:url" class="share_url" content="http://www.abc.com">
<meta name="whatsapp:title" class="share_title" content="测试分享到whatsapp">
/**
* 参考:HTML5网页点击分享到WHATSAPP https://www.cnblogs.com/phperlinxinlan/p/10305376.html
* 核心:
* <meta name="whatsapp:url" class="share_url" content="http://www.abc.com">
* <meta name="whatsapp:title" class="share_title" content="测试分享到whatsapp">
*
* agent:WhatsApp
*
* # 如果user_agent是从facebook爬虫过来的; 我们 就 进入代理接口
* if ($http_user_agent ~* "WhatsApp") {
* #proxy ^/(.*)$ http://127.0.0.1:7777/ redirect;irect; #这种不能加$uri后缀了,很麻烦,需要同时有两个tomcat
* rewrite ^/(.*)$ $scheme://$host/qcure/proxy/WhatsApp?$uri redirect; #直接302过去; 原始访问地址是: https://$host/qcurepc/xxx
* }
*
*
* 116.48.97.249 - - [18/Jan/2021:10:53:17 +0800] "GET /qcurepc/level2/283 HTTP/1.1" 200 1325 "-" "WhatsApp/2.20.206.24 A"
*
* 12.15.176.108 - - [18/Jan/2021:10:58:07 +0800] "GET /qcure/upload/product/20201119112124868_qan3l.jpg HTTP/1.1" 302 138 "https://www.qcure.com/qcureweb/" "Mozilla/5.0 (Linux; Android 10; LIO-AN00 Build/HUAWEILIO-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2693 MMWEBSDK/201201 Mobile Safari/537.36 MMWEBID/2818 MicroMessenger/7.0.22.1820(0x270016A2) Process/toolsmp WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64"
*
* @param title
* @param url
* @param request
* @return
*/
@ApiIgnore
@IgnoreAuthToken
@ResponseBody
@RequestMapping(value = "/proxy/WhatsApp", produces = "text/html;charset=UTF-8", method = RequestMethod.GET)
public String proxyWhatsApp(
@ApiParam("网页的title,字段名:title,选填,默认是项目名称,方便调试") @RequestParam(value = "title", defaultValue = "QCURE", required = false) String title,
@ApiParam("分享图片") @RequestParam(value = "image", defaultValue = "https://static.xx.fbcdn.net/rsrc.php/v3/y6/r/hlFyGnljr-d.png", required = false) String url,
HttpServletRequest request) {
try {
title = EncodeUtils.urlDecode(title);
title = EncodeUtils.urlDecode(title);
url = EncodeUtils.urlDecode(url);
url = EncodeUtils.urlDecode(url);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String emptyHtml = "<!DOCTYPE html>\n" +
"<html>\n" +
"\n" +
"<head>\n" +
" <title>@@title</title>\n" +
" <meta name=\"image\" content=\"@@url\">\n" +
"</head>\n" +
"\n" +
"<body>\n" +
" 转发内容\n" +
"</body>\n" +
"\n" +
"</html>";
if (XaUtils.isValid(title)) {
emptyHtml = emptyHtml.replace("@@title", title);
}
if (XaUtils.isValid(url)) {
emptyHtml = emptyHtml.replace("@@url", url);
}
sysLogService.saveLogManual("sys:系统管理员", "WhatsApp 爬虫 proxy", emptyHtml, null);
return emptyHtml;
}
分享成功,如图:
三、微博weibo
3.1. 微博必须要有注册好的微博账号
- 微博授权及获取信息文档: https://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6
- 新浪授权1:OAuth2/authorize 请求用户授权Token 【会获取到一个code】
- 新浪授权2:OAuth2/access_token 获取授权过的Access 【会获取到accesstoken和uid】
- 新浪授权3:通过openId、accessToken获取微博信息【获取微博用户信息】
- 账号问题,测试环境和正式环境使用的是一套账号,一个账号可以添加超过3个域名。
// 微博授权第二步,根据第一步的code换取access-token和uid
/**
* @param redirectUri 授权完成之后,重定向的页面;注意,这里的传参,好像只能返回一个参数
* @param code 微博第一步获取到的code
* @return
*/
@IgnoreAuthToken
@RequestMapping(value = "sina/access_token", method = {RequestMethod.POST, RequestMethod.GET})
@ApiOperation(value = "微博授权第二步,根据第一步的code换取access-token和uid ", notes = "这里是,新浪授权2:OAuth2/access_token 获取授权过的Access 【会获取到accesstoken和uid】", position = 2)
public XaResult<String> sinaAuth(
@ApiParam("回调地址,字段名:redirectUri") @RequestParam(value = "redirectUri") String redirectUri,
@ApiParam("code,字段名:code") @RequestParam(value = "code") String code
) {
HttpClientSimpleUtil httpClient = HttpClientSimpleUtil.getInstance();
Map<String, String> params = new HashMap<>();
params.put("client_id", SINA_APP_KEY);
params.put("client_secret", SINA_APP_SECRET);
params.put("redirect_uri", redirectUri);
params.put("grant_type", "authorization_code");
params.put("code", code);
String url = "https://api.weibo.com/oauth2/access_token";
String response = httpClient.doPostRequest(url, params);
return new XaResult<String>().setObject(response);
}
//授权最后一步,根据 获取第三方的openId和accestoken获取第三方的用户信息
/**
* 第三方登录
*
* @see Constant.ThreeAccontType 所有第三方登录类型
* @see ApiWeappUserController#loginByWxJSCode(String, Integer, Boolean, HttpServletRequest) 微信的注册见
*
* @return
*/
@IgnoreAuthToken
@RequestMapping(value = "threeLogin", method = {RequestMethod.GET})
@ApiOperation(value = "第三方授权登录接口,根据openId与accessToken登录", notes = "第三方登录注册用户&生成token", position = 2)
public XaResult<TbUserVo> threeLogin(
@ApiParam(value = "access_token,字段名:accessToken") @RequestParam(value = "accessToken") String accessToken,
@ApiParam(value = "openId,字段名:微信/微博/qq 唯一的ID openId", defaultValue = "openId") @RequestParam(value = "openId") String openId,
@ApiParam(value = "type,字段名:类型,取值是sinaWeibo、qq, 具体查看常量:Constant.ThreeAccontType , 见接口: /mall/constants/ ", defaultValue = "取值是sinaWeibo") @RequestParam(value = "type") String type
) {
XaResult<TbUserVo> xr = new XaResult<>();
if (!XaUtils.isValid(accessToken)) {
return xr.error("accessToken不能为空!accessToken = " + accessToken);
}
if (!XaUtils.isValid(openId)) {
return xr.error("openId不能为空!openId = " + openId);
}
if (!Constant.ThreeAccontType.isConstantVal(type)) {
return xr.error("threeLogin方法请输入有效的type, type = " + type +"!");
}
TbUserEntity user = null;
TbUserVo userVo = new TbUserVo();
if (Constant.ThreeAccontType.QQ.equalsIgnoreCase(type)) {
//qq
user = userService.queryByqqAcc(openId);
if (XaUtils.isEmpty(user)) {
//不存在则获取信息进行存储
user = getQqInfo(accessToken, openId);
userService.save(user);
}
} else if (Constant.ThreeAccontType.SINA_WEIBO.equalsIgnoreCase(type)) {
//微博
user = userService.queryByWeiboAcc(openId);
if (XaUtils.isEmpty(user)) {
//不存在则获取用户信息并进行存储
user = getWeiboInfo(accessToken, openId);
userService.save(user);
}
} else {
return xr.error("不支持的type, type = " + type);
}
if (XaUtils.isNotEmpty(user)) {
Map<String, Object> tokenMap = tokenService.createToken(user.getUserId(), false);
beanMapper.copy(user, userVo);
userVo.setToken(tokenMap.get("token") + "");
}
return xr.setObject(userVo);
}
/**
* QQ登录根据access_token与openId获取qq用户信息
*
* @param accessToken
* @param openId
* @return
*/
private TbUserEntity getQqInfo(String accessToken, String openId) {
TbUserEntity user = new TbUserVo();
String url = "https://graph.qq.com/user/get_user_info?oauth_consumer_key="
+ QQ_APP_ID + "&access_token="
+ accessToken + "&openid=" + openId + "&format=json";
HttpClientSimpleUtil httpClient = HttpClientSimpleUtil.getInstance();
String response = httpClient.doGetRequest(url);
JSONObject jsonObject = JSON.parseObject(response.replaceAll("\n", ""));
user.setName(jsonObject.getString("nickname"));
user.setHeadPortraitImg(jsonObject.getString("figureurl_qq_2"));
user.setStatus(Constant.Status.valid);
user.setCreateTime(LocalDateTime.now());
user.setQqAcc(openId);
user.setUserTypes(Constant.UserTypes.USER_NORMAL_1);
return user;
}
/**
* 通过openId、accessToken获取微博信息
* @param accessToken
* @param openId
* @return
*/
private TbUserEntity getWeiboInfo(String accessToken, String openId){
TbUserEntity user = new TbUserEntity();
String url = "https://api.weibo.com/2/users/show.json?access_token=" + accessToken + "&uid=" + openId;
HttpClientSimpleUtil httpClient = HttpClientSimpleUtil.getInstance();
String response = httpClient.doGetRequest(url);
JSONObject jsonObject = JSON.parseObject(response.replaceAll("\n", ""));
user.setName(jsonObject.getString("screen_name"));
user.setHeadPortraitImg(jsonObject.getString("profile_image_url"));
user.setStatus(Constant.Status.valid);
user.setCreateTime(LocalDateTime.now());
user.setSinaAcc(openId);
user.setUserTypes(Constant.UserTypes.USER_NORMAL_1);
return user;
}
四. weixin公众平台(手机端)分享
微信中国最大的社交平台, 微信可以同时配置两个地址,即测试环境和正式环境可以使用一个账号。
五. weixin开放平台(PC)登录、分享
微信中国最大的社交平台, 微信可开放平台的授权地址只能配置一个,修改域名,需要重新配置。
六. QQ互联平台
腾讯开发平台是腾讯总体对外所有开发平台的集合,包含应用开放平台就是应用宝相关、**QQ互联平台[开放]**就是QQ登录和分享的能力、微信公众号、微信开发平台等
七. 移动端使用NativeShare.js进行分享
手机端的h5页面分享手机端的分享能力有限,自己开发比较麻烦,这里接入插件NativeShare.js,但插件目前实践中,支持持UC*和QQ**,其他浏览器都不支持,不支持的浏览器,提示用户自己去粘贴;
- 目前仅仅支持UC和QQ
- 不支持的浏览器,无法弹出自己的弹框,需要自己开发一个页面,点击分享,进行粘贴链接地址;
- 在微信里面,如果分享,直接提示 在浏览器中打开,或者 在右上角用微信自带的分享能力。 注意微信自带分享,前端开发也要开发的,不处理的话,可能分享图片、连接全是错误的。
八. 国际域名证书
GoDaddy注册的域名,在大陆不好备案,国内需要国际域名证书。
類似,打過去等了很久才有人接,然後她叫我在godaddy公眾號裡面下載證書就可以了…[偷笑]。godaddy有微信公眾號,太方便了