基础库
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 

434 rader
16 KiB

  1. import 'dart:io';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter_alibc/alibc_model.dart';
  4. import 'package:flutter_alibc/flutter_alibc.dart';
  5. import 'package:fluttertoast/fluttertoast.dart';
  6. import 'package:jdsdk/jdsdk.dart';
  7. import 'package:url_launcher/url_launcher.dart';
  8. import 'package:zhiying_comm/models/user/user_info_model.dart';
  9. import 'package:zhiying_comm/util/dialog/loading/loading.dart';
  10. import 'package:zhiying_comm/util/empty_util.dart';
  11. import 'package:zhiying_comm/util/global_config.dart';
  12. import 'package:zhiying_comm/util/log/let_log.dart';
  13. import 'package:zhiying_comm/util/net_util.dart';
  14. import 'package:zhiying_comm/util/pdd_auth/pdd_auth.dart';
  15. import 'package:zhiying_comm/util/taobao/taobao_auth.dart';
  16. import 'package:zhiying_comm/util/turn_chain/turn_chain_dialog_repository.dart';
  17. import 'package:zhiying_comm/util/turn_chain/turn_chain_style_model.dart';
  18. import 'package:zhiying_comm/zhiying_comm.dart';
  19. import '../router_util.dart';
  20. import 'turn_chain_dialog.dart';
  21. import 'package:zhiying_comm/util/shared_prefe_util.dart';
  22. class TurnChainUtil {
  23. ///
  24. /// 跳转app或者打开url进行领券
  25. /// userInfoModel: 用户登陆的带有token 与 淘宝是否授权的 model类
  26. /// provider: 商品的渠道
  27. /// data: 转链需要的请求参数
  28. ///
  29. /// 一些常用的APP的 URL scheme:
  30. /// 来源:https://blog.csdn.net/jdazy/article/details/79208754
  31. /// QQ: mqq://
  32. /// 微信: weixin://
  33. /// 京东: openapp.jdmobile://
  34. /// 淘宝: taobao://
  35. /// 美团: imeituan://
  36. /// 点评: dianping://
  37. /// 1号店: wccbyihaodian://
  38. /// 支付宝: alipay://
  39. /// 微博: sinaweibo://
  40. /// 腾讯微博: TencentWeibo://
  41. /// weico微博: weico://
  42. /// 知乎: zhihu://
  43. /// 豆瓣fm: doubanradio://
  44. /// 网易公开课: ntesopen://
  45. /// Chrome: googlechrome://
  46. /// QQ浏览器: mqqbrowser://
  47. /// uc浏览器: ucbrowser://
  48. /// 搜狗浏览器: SogouMSE://
  49. /// 百度地图: baidumap:// bdmap://
  50. /// 优酷: youku://
  51. /// 人人: renren://
  52. /// 我查查: wcc://
  53. /// 有道词典: yddictproapp://
  54. /// 微盘: sinavdisk://
  55. /// 名片全能王: camcard://
  56. ///
  57. static Future<void> openReceiveCoupon(BuildContext context, UserInfoModel userInfoModel, String goodsId, String provider, Map<String, dynamic> data,
  58. {bool isFree = false}) async {
  59. /// iOS 审核状态
  60. // String is_ios_review = await SharedPreferencesUtil.getStringValue(GlobalConfig.IS_IOS_REVIEW, defaultVal: '0');
  61. /// 1、先判断是否登陆
  62. if (EmptyUtil.isEmpty(userInfoModel) || EmptyUtil.isEmpty(userInfoModel?.token)) {
  63. RouterUtil.goLogin(context);
  64. return;
  65. }
  66. /// 2、如果是淘宝或者天猫,判断是否授权
  67. ///
  68. /// ⚠️ 因业务修改,淘宝或者天猫每次都必须请求网络请求状态
  69. // if ((provider == GlobalConfig.PROVIDER_TB || provider == GlobalConfig.PROVIDER_TM ) && !userInfoModel.isTBAuth) {
  70. // TaobaoAuth.auth(context);
  71. // return;
  72. // }
  73. if (provider == GlobalConfig.PROVIDER_TB || provider == GlobalConfig.PROVIDER_TM) {
  74. bool isAuth = await TaobaoAuth.auth(context);
  75. if (!isAuth) return;
  76. }
  77. /// 3、获取转链,进行跳转
  78. Map<String, dynamic> result = await getTurnChainResult(context, goodsId, provider, data, isShare: false, isFree: isFree);
  79. if (!EmptyUtil.isEmpty(result)) {
  80. String openAppUrl = result['open_app_url'];
  81. String appUrl = result['app_url'];
  82. String webUrl = result['no_open_app_url'];
  83. bool jumpResult = await jumpNative(context, provider: provider, openAppUrl: openAppUrl, appUrl: appUrl, webUrl: webUrl);
  84. if (!jumpResult) {
  85. Fluttertoast.cancel();
  86. Fluttertoast.showToast(msg: '购买链接不存在');
  87. }
  88. // /// 4、根据渠道进行不同的跳转
  89. // switch (provider) {
  90. // case GlobalConfig.PROVIDER_TB:
  91. // case GlobalConfig.PROVIDER_TM:
  92. // if (!EmptyUtil.isEmpty(openAppUrl)) {
  93. // TradeResult tradeResult;
  94. // if (Platform.isAndroid) {
  95. // // print("跳转链接"+openAppUrl);
  96. // tradeResult = await FlutterAlibc.openByUrl(url: openAppUrl, backUrl: "alisdk://");
  97. // } else if (Platform.isIOS) {
  98. // if (is_ios_review == '1') {
  99. // print('iOS审核:' + is_ios_review);
  100. // RouterUtil.openWebview(webUrl, context);
  101. // } else {
  102. // tradeResult = await FlutterAlibc.openByUrl(url: openAppUrl);
  103. // }
  104. // }
  105. // Logger.debug('taobao result = ${tradeResult.errorCode} ${tradeResult.errorMessage} ');
  106. // } else if (!EmptyUtil.isEmpty(webUrl)) {
  107. // RouterUtil.openWebview(webUrl, context);
  108. // } else {
  109. // Fluttertoast.cancel();
  110. // Fluttertoast.showToast(msg: '购买链接不存在');
  111. // }
  112. //
  113. // break;
  114. // case GlobalConfig.PROVIDER_JD:
  115. // String tempURLScheme1 = 'openapp.jdmobile://virtual?params=%';
  116. // String tempURLScheme2 = 'openapp.jdmobile://';
  117. // if (!EmptyUtil.isEmpty(openAppUrl) && await canLaunch(tempURLScheme1) || await canLaunch(tempURLScheme2)) {
  118. // Jdsdk.openUrl(url: openAppUrl);
  119. // } else if (!EmptyUtil.isEmpty(webUrl)) {
  120. // RouterUtil.openWebview(webUrl, context);
  121. // } else {
  122. // Fluttertoast.cancel();
  123. // Fluttertoast.showToast(msg: '购买链接不存在');
  124. // }
  125. // break;
  126. // case GlobalConfig.PROVIDER_KL:
  127. // case GlobalConfig.PROVIDER_PDD:
  128. // case GlobalConfig.PROVIDER_SN:
  129. // bool launchable = await canLaunch(appUrl);
  130. // if (Platform.isIOS) {
  131. // launchable = await launch(appUrl);
  132. // }
  133. // if (launchable) {
  134. // if (!Platform.isIOS) {
  135. // if (appUrl.startsWith("suning")) {
  136. // RouterUtil.openWebview(webUrl, context);
  137. // } else {
  138. // RouterUtil.openWebview(webUrl, context);
  139. // }
  140. // }
  141. // } else if (!EmptyUtil.isEmpty(webUrl)) {
  142. // Logger.log('打开${provider} webUrl, url = ${webUrl}');
  143. // RouterUtil.openWebview(webUrl, context);
  144. // } else {
  145. // Fluttertoast.cancel();
  146. // Fluttertoast.showToast(msg: '购买链接不存在');
  147. // }
  148. // break;
  149. // case GlobalConfig.PROVIDER_VIP:
  150. // bool launchable = await canLaunch(appUrl);
  151. // if (Platform.isIOS) {
  152. // launchable = await launch(appUrl);
  153. // }
  154. // if (launchable) {
  155. // if (!Platform.isIOS) {
  156. // await launch(appUrl);
  157. // }
  158. // } else if (!EmptyUtil.isEmpty(webUrl)) {
  159. // Logger.log('打开${provider} webUrl, url = ${webUrl}');
  160. // RouterUtil.openWebview(webUrl, context);
  161. // } else {
  162. // Fluttertoast.cancel();
  163. // Fluttertoast.showToast(msg: '购买链接不存在');
  164. // }
  165. // break;
  166. // default:
  167. // if (!EmptyUtil.isEmpty(openAppUrl)) {
  168. // bool launchable = await canLaunch(appUrl);
  169. // if (launchable) {
  170. // launchable = await launch(appUrl);
  171. // }
  172. // if (launchable) {
  173. // if (!Platform.isIOS) {
  174. // RouterUtil.openWebview(webUrl, context);
  175. // }
  176. // } else if (!EmptyUtil.isEmpty(webUrl)) {
  177. // Logger.log('打开${provider} webUrl, url = ${webUrl}');
  178. // RouterUtil.openWebview(webUrl, context);
  179. // } else {
  180. // Fluttertoast.cancel();
  181. // Fluttertoast.showToast(msg: '购买链接不存在');
  182. // }
  183. // } else {
  184. // Fluttertoast.cancel();
  185. // Fluttertoast.showToast(msg: '购买链接不存在');
  186. // }
  187. // break;
  188. // }
  189. } else {
  190. Fluttertoast.cancel();
  191. Fluttertoast.showToast(msg: '购买链接不存在');
  192. }
  193. }
  194. ///
  195. /// 跳转原生或者webView打开购买链接
  196. ///
  197. /// provider: 商品渠道
  198. /// openAppUrl: 打开商品链接
  199. /// appUrl: 打开商品链接,不是Http开头,类似 taobao://, opennapp.jdxxx://
  200. /// webUrl: 打开商品WebView链接
  201. ///
  202. static Future<bool> jumpNative(BuildContext context, {String provider = GlobalConfig.PROVIDER_TB, String openAppUrl, String appUrl, String webUrl}) async {
  203. bool rlt = false;
  204. ///iOS 审核状态
  205. String isIosReview = await SharedPreferencesUtil.getStringValue(GlobalConfig.IS_IOS_REVIEW, defaultVal: '0');
  206. print("渠道" + provider);
  207. /// 4、根据渠道进行不同的跳转
  208. switch (provider) {
  209. case GlobalConfig.PROVIDER_TB:
  210. case GlobalConfig.PROVIDER_TM:
  211. if (!EmptyUtil.isEmpty(openAppUrl)) {
  212. TradeResult tradeResult;
  213. if (Platform.isAndroid) {
  214. tradeResult = await FlutterAlibc.openByUrl(url: openAppUrl, backUrl: "alisdk://");
  215. rlt = true;
  216. } else if (Platform.isIOS) {
  217. if (isIosReview == '1') {
  218. print('iOS审核:' + isIosReview);
  219. RouterUtil.openWebview(webUrl, context);
  220. rlt = true;
  221. } else {
  222. tradeResult = await FlutterAlibc.openByUrl(url: openAppUrl);
  223. rlt = true;
  224. }
  225. }
  226. Logger.debug('taobao result = ${tradeResult.errorCode} ${tradeResult.errorMessage} ');
  227. } else if (!EmptyUtil.isEmpty(webUrl)) {
  228. RouterUtil.openWebview(webUrl, context);
  229. rlt = true;
  230. } else {
  231. rlt = false;
  232. }
  233. break;
  234. case GlobalConfig.PROVIDER_JD:
  235. String tempURLScheme1 = 'openapp.jdmobile://virtual?params=%';
  236. String tempURLScheme2 = 'openapp.jdmobile://';
  237. if (!EmptyUtil.isEmpty(openAppUrl) && await canLaunch(tempURLScheme1) || await canLaunch(tempURLScheme2)) {
  238. Jdsdk.openUrl(url: openAppUrl);
  239. rlt = true;
  240. } else if (!EmptyUtil.isEmpty(webUrl)) {
  241. RouterUtil.openWebview(webUrl, context);
  242. rlt = true;
  243. } else {
  244. rlt = false;
  245. }
  246. break;
  247. case GlobalConfig.PROVIDER_KL:
  248. case GlobalConfig.PROVIDER_PDD:
  249. case GlobalConfig.PROVIDER_SN:
  250. bool launchable = await canLaunch(appUrl);
  251. if (Platform.isIOS) {
  252. launchable = await launch(appUrl);
  253. }
  254. if (launchable) {
  255. if (!Platform.isIOS) {
  256. if (provider == GlobalConfig.PROVIDER_SN) {
  257. RouterUtil.openWebview(webUrl, context);
  258. }else{
  259. await launch(appUrl);
  260. }
  261. rlt = true;
  262. }
  263. } else if (!EmptyUtil.isEmpty(webUrl)) {
  264. Logger.log('打开${provider} webUrl, url = ${webUrl}');
  265. RouterUtil.openWebview(webUrl, context);
  266. rlt = true;
  267. } else {
  268. rlt = false;
  269. }
  270. break;
  271. case GlobalConfig.PROVIDER_VIP:
  272. bool launchable = await canLaunch(appUrl);
  273. if (Platform.isIOS) {
  274. launchable = await launch(appUrl);
  275. }
  276. if (launchable) {
  277. if (!Platform.isIOS) {
  278. await launch(appUrl);
  279. rlt = true;
  280. }
  281. } else if (!EmptyUtil.isEmpty(webUrl)) {
  282. Logger.log('打开${provider} webUrl, url = ${webUrl}');
  283. RouterUtil.openWebview(webUrl, context);
  284. rlt = true;
  285. } else {
  286. rlt = false;
  287. }
  288. break;
  289. default:
  290. if (!EmptyUtil.isEmpty(openAppUrl)) {
  291. bool launchable = await canLaunch(appUrl);
  292. if (launchable) {
  293. launchable = await launch(appUrl);
  294. }
  295. if (launchable) {
  296. if (!Platform.isIOS) {
  297. RouterUtil.openWebview(webUrl, context);
  298. rlt = true;
  299. }
  300. } else if (!EmptyUtil.isEmpty(webUrl)) {
  301. Logger.log('打开${provider} webUrl, url = ${webUrl}');
  302. RouterUtil.openWebview(webUrl, context);
  303. rlt = true;
  304. } else {
  305. rlt = false;
  306. }
  307. } else {
  308. rlt = false;
  309. }
  310. break;
  311. }
  312. return Future.value(rlt);
  313. }
  314. ///
  315. /// 获取分享的转链
  316. /// userInfoModel: 用户登陆的带有token 与 淘宝是否授权的 model类
  317. /// provider: 商品的渠道
  318. /// data: 转链需要的请求参数
  319. ///
  320. /// 返回参数: 只需要获取返回结果的 open_app_url 值即可。
  321. /// 例如: Map<String, dynamic> result = await getShareTurnChain(context, _user, provider, data);
  322. /// String buyUrl = result['open_app_url']
  323. ///
  324. static Future<Map<String, dynamic>> getShareTurnChain(BuildContext context, UserInfoModel userInfoModel, String goodsId, String provider, Map<String, dynamic> data) async {
  325. /// 1、先判断是否登陆
  326. if (EmptyUtil.isEmpty(userInfoModel) || EmptyUtil.isEmpty(userInfoModel?.token)) {
  327. RouterUtil.goLogin(context);
  328. return null;
  329. }
  330. /// 2、如果是淘宝,判断是否授权
  331. // if ((provider == GlobalConfig.PROVIDER_TB || provider == GlobalConfig.PROVIDER_TM) && !userInfoModel.isTBAuth) {
  332. // TaobaoAuth.auth(context);
  333. // return null;
  334. // }
  335. /// ⚠️ 因业务修改,淘宝或者天猫每次都必须请求网络请求状态
  336. if (provider == GlobalConfig.PROVIDER_TB || provider == GlobalConfig.PROVIDER_TM) {
  337. bool isAuth = await TaobaoAuth.auth(context);
  338. if (!isAuth) return null;
  339. }
  340. /// 2.5 如果是拼多多,判断是否需要授权
  341. if (provider == GlobalConfig.PROVIDER_PDD) {
  342. // 如果为true,说明需要进行授权,停止执行。
  343. bool result = await PddAuth.auth(context);
  344. if (result) return null;
  345. }
  346. /// 3、获取转链的结果
  347. Map<String, dynamic> result = await getTurnChainResult(context, goodsId, provider, data, isShare: true);
  348. if (!EmptyUtil.isEmpty(result) && !EmptyUtil.isEmpty(result['open_app_url'])) {
  349. return result;
  350. }
  351. Fluttertoast.cancel();
  352. Fluttertoast.showToast(msg: '购买链接不存在');
  353. return null;
  354. }
  355. ///
  356. /// 获取跳转的dialog样式
  357. ///
  358. static Future<dynamic> getCacheTurnChainDialogStyle(String goodsId, String provider, String commission, String coupon) async {
  359. TurnChainDialogRepository repository = TurnChainDialogRepository();
  360. var result = await repository.fetchCacheData(goodsId, provider, commission, coupon);
  361. if (!EmptyUtil.isEmpty(result)) {
  362. return result;
  363. }
  364. return null;
  365. }
  366. ///
  367. /// 缓存跳转的dialog样式
  368. ///
  369. static Future<bool> cacheTurnChainDialogStyle(String goodsId, String provider, String commission, String coupon) async {
  370. TurnChainDialogRepository repository = TurnChainDialogRepository();
  371. bool result = await repository.cacheData(goodsId, provider, commission, coupon);
  372. return result;
  373. }
  374. ///
  375. /// 接口文档:https://www.showdoc.com.cn/1003739271891029?page_id=5760575662067820
  376. /// 根据商品id等信息,获取领券或者分享的转链接
  377. ///
  378. ///
  379. static Future<Map<String, dynamic>> getTurnChainResult(BuildContext context, String goodsId, String provider, Map<String, dynamic> data,
  380. {bool isShare = false, bool isFree = false}) async {
  381. try {
  382. TurnChainDialogRepository repository = TurnChainDialogRepository();
  383. if (!EmptyUtil.isEmpty(context) && !EmptyUtil.isEmpty(provider) && !EmptyUtil.isEmpty(data) && !EmptyUtil.isEmpty('gid')) {
  384. TurnChainStyleModel model = await repository.fetchCacheData(goodsId, provider, data['commission'], data['coupon_price']);
  385. // 设置是否分享还是转链
  386. data['is_share'] = isShare ? '1' : '0';
  387. ///1为免单,0为普通
  388. data['is_free'] = (isFree ?? false) ? "1" : "0";
  389. (isFree ?? false) ? print("免单") : print("普通");
  390. if (EmptyUtil.isEmpty(model)) {
  391. // 开启loading
  392. Loading.show(context);
  393. } else {
  394. TurnChainLoading.show(context, model);
  395. }
  396. var result = await NetUtil.post('/api/v1/convert/$provider', params: data, method: NetMethod.POST);
  397. if (EmptyUtil.isEmpty(model)) {
  398. // 关闭loading
  399. Loading.dismiss();
  400. } else {
  401. TurnChainLoading.dismiss();
  402. }
  403. if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
  404. return result[GlobalConfig.HTTP_RESPONSE_KEY_DATA];
  405. }
  406. }
  407. } catch (e, s) {
  408. Logger.error(e, s);
  409. }
  410. return null;
  411. }
  412. }