基础库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

turn_chain_util.dart 16 KiB

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