StoreAdminPatternForm.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\alliance\models\salesman;
  8. use AopClient;
  9. use app\models\AggregateQrcode;
  10. use app\models\AggregateSaasQrcode;
  11. use app\models\MdFoodsQrcode;
  12. use app\models\Option;
  13. use app\models\SalesmanNewStore;
  14. use app\models\Store;
  15. use app\models\StoreAliMini;
  16. use app\models\StoreMini;
  17. use app\modules\alliance\models\third\wechat\BaseForm;
  18. use app\utils\Alipay\alipaySdk\aop\request\AlipayOpenMiniQrcodeBindRequest;
  19. use app\utils\QrCode;
  20. use EasyWeChat\Factory;
  21. use EasyWeChat\Kernel\BaseClient;
  22. use yii\base\Model;
  23. include_once \Yii::$app->basePath . "/utils/Alipay/alipaySdk/aop/AopClient.php";;
  24. class StoreAdminPatternForm extends Model
  25. {
  26. public $model;
  27. public $openPlatform;
  28. public $id;
  29. public $store_id;
  30. public $mini_id;
  31. public $ali_mini_id;
  32. public $business_model;
  33. public $qrcode_id;
  34. public $s_id;
  35. public function rules()
  36. {
  37. return [
  38. [['id', 'business_model', 'qrcode_id', 's_id'], 'integer'],
  39. ];
  40. }
  41. //微信初始化配置
  42. public function initWx()
  43. {
  44. //微信三方配置信息
  45. $wx_config = [
  46. //微信三方appid
  47. 'app_id' => Option::get("platform_third_appid", 0, 'saas')['value'],
  48. //微信三方appSecret
  49. 'secret' => Option::get("platform_third_secret", 0, 'saas')['value'],
  50. //微信三方平台设置的token
  51. 'token' => Option::get("platform_token", 0, 'saas')['value'],
  52. //微信三方平台设置的加密key
  53. 'aes_key' => Option::get("platform_encodingAesKey", 0, 'saas')['value']
  54. ];
  55. $openPlatform = Factory::openPlatform($wx_config);
  56. //获取小程序信息
  57. $store_mini = StoreMini::findOne($this->mini_id);
  58. if (empty($store_mini->appid) || empty($store_mini->authorizer_refresh_token)) {
  59. return false;
  60. } else {
  61. return $openPlatform->miniProgram($store_mini->appid, $store_mini->authorizer_refresh_token);
  62. }
  63. }
  64. //支付宝初始化配置
  65. public function initAli($request, $biz_content)
  66. {
  67. $ali_mini_id = $this->ali_mini_id;
  68. $store_mini = StoreAliMini::findOne($ali_mini_id);
  69. if (!empty($store_mini->auth_token)) {
  70. $auth_token = $store_mini->auth_token;
  71. } else {
  72. return false;
  73. }
  74. $aop = new AopClient();
  75. //设置appid
  76. $aop->appId = Option::get("alipay_appid", 0, 'saas')['value'];
  77. //设置私钥
  78. $aop->rsaPrivateKey = Option::get("alipay_app_private_key", 0, 'saas')['value'];
  79. //设置公钥
  80. $aop->alipayrsaPublicKey = Option::get("alipay_public_key", 0, 'saas')['value'];
  81. //设置ase_key,加签方式
  82. $aop->encryptKey = Option::get("alipay_aes_key", 0, 'saas')['value'];
  83. //设置加解密方式
  84. $aop->signType = "RSA2";
  85. //处理没有biz_content情况
  86. if ($biz_content) {
  87. $request->setBizContent($biz_content);
  88. }
  89. $result = $aop->execute($request, null, $auth_token);
  90. //请求后的数据处理
  91. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  92. return $result->$responseNode;
  93. }
  94. //物料配置
  95. public function getConfig() {
  96. $t = \Yii::$app->db->beginTransaction();
  97. try {
  98. $store_id = $this->store_id;
  99. $mini_id = $this->mini_id;
  100. $ali_mini_id = $this->ali_mini_id;
  101. $s_id = $this->s_id;
  102. $business_model = Store::findOne($store_id)->business_model;
  103. $self_mini = \app\models\Option::get('self_mini', $store_id, 'store', 0)['value']; //
  104. if ((int)$business_model === 1 || (\Yii::$app->prod_is_dandianpu() && $self_mini)) {
  105. $qrcode = AggregateQrcode::findOne(['store_id' => $store_id]);
  106. if (!$qrcode) {
  107. $qrcode_ = AggregateQrcode::findOne(['store_id' => $store_id]);
  108. if (!$qrcode_) {
  109. throw new \Exception("后台缺少配置信息");
  110. }
  111. $qrcode_->store_id = $store_id;
  112. $qrcode_->save();
  113. $qrcode = AggregateQrcode::findOne(['store_id' => $store_id]);
  114. }
  115. $data = [
  116. 'param_url' => $qrcode->param_url,
  117. 'wx_url' => $qrcode->wx_url,
  118. 'ali_url' => $qrcode->ali_url
  119. ];
  120. //判断微信是否绑定
  121. $result = $this->bindQrcode($qrcode, $data, 1);
  122. if ($result['code'] !== 0) {
  123. return $result;
  124. }
  125. $type = 'store';
  126. } else {
  127. $qrcode = AggregateSaasQrcode::findOne(['store_id' => $store_id]);
  128. if (!$qrcode) {
  129. $qrcode_ = AggregateSaasQrcode::findOne(['store_id' => $store_id]);
  130. if (!$qrcode_) {
  131. throw new \Exception("后台缺少配置信息");
  132. }
  133. $qrcode_->store_id = $store_id;
  134. $qrcode_->save();
  135. $qrcode = AggregateSaasQrcode::findOne(['store_id' => $store_id]);
  136. }
  137. $type = 'saas';
  138. }
  139. $filename = md5(time() . $type . $qrcode->id);
  140. $path = \Yii::$app->runtimePath . '/image/' . $filename . '.jpg';
  141. $pic_url = str_replace('http://', 'https://', \Yii::$app->request->hostInfo . '/runtime/image/' . $filename . '.jpg');
  142. if(empty($qrcode->qrcode_url) || !file_exists(str_replace(\Yii::$app->request->hostInfo,\Yii::$app->basePath,$qrcode->qrcode_url))){
  143. $text = $qrcode->param_url;
  144. QrCode::image($text, 500, false, 'L', 'JPEG', 0, ['255,255,255', '0,0,0'], 1, false, $path);
  145. $qrcode->qrcode_url = $pic_url;
  146. $qrcode->save();
  147. }
  148. $new_store = SalesmanNewStore::findOne($s_id);
  149. $store_params = json_decode($new_store->store_params, true);
  150. $foods_qrcode = "";
  151. if ($store_params['foods_qrcode_id']) {
  152. $md_foods_qrcode = MdFoodsQrcode::findOne(['id' => $store_params['foods_qrcode_id'], 'is_delete' => 0]);
  153. $foods_qrcode = $md_foods_qrcode->qrcode_url ?: '';
  154. }
  155. $t->commit();
  156. return [
  157. 'code' => 0,
  158. 'msg' => '操作完成',
  159. 'data' => [
  160. 'qrcode' => $qrcode->qrcode_url,
  161. 'business_model' => $business_model,
  162. 'foods_qrcode' => $foods_qrcode
  163. ]
  164. ];
  165. } catch (\Exception $e) {
  166. return [
  167. 'code' => 1,
  168. 'msg' => $e->getMessage(),
  169. ];
  170. }
  171. }
  172. public function setFoodsQrcode() {
  173. $t = \Yii::$app->db->beginTransaction();
  174. try {
  175. $store_id = $this->store_id;
  176. $qrcode_id = $this->qrcode_id;
  177. // $mini_id = $this->mini_id;
  178. // $ali_mini_id = $this->ali_mini_id;
  179. $store = Store::findOne($store_id);
  180. $self_mini = Option::get('self_mini', $store_id, 'store', 0)['value'];
  181. //联盟、供应链端都可适用
  182. $url_path = \Yii::$app->request->hostInfo . "/web/food/saas?scene=store:{$store_id},store_id:{$store_id}";
  183. //独立版小程序使用
  184. if (
  185. (!\Yii::$app->prod_is_dandianpu() && intval($store->business_model) === 1) ||
  186. (\Yii::$app->prod_is_dandianpu() && $self_mini)
  187. ) {
  188. $url_path = \Yii::$app->request->hostInfo . '/web/food/store/' . $qrcode_id . '/?id='. $qrcode_id;
  189. }
  190. $md_foods_qrcode = MdFoodsQrcode::findOne(['id' => $qrcode_id, 'is_delete' => 0]);
  191. if (!$md_foods_qrcode) {
  192. throw new \Exception('查询失败,请检查状态是否被删除');
  193. }
  194. if (!$store) {
  195. throw new \Exception('商城信息查询失败');
  196. }
  197. if ($md_foods_qrcode->store_id && $md_foods_qrcode->store_id !== $store_id) {
  198. throw new \Exception('二维码已经绑定其他商城');
  199. }
  200. $md_foods_qrcode->url_path = $url_path;
  201. $md_foods_qrcode->save();
  202. //TODO 此处是将子父级全部替换为同一商城
  203. // if ($md_foods_qrcode->parent_id) {
  204. // $parent_ = MdFoodsQrcode::findOne(['id' => $md_foods_qrcode->parent_id, 'is_delete' => 0]);
  205. // if ($parent_) {
  206. // if ($parent_->store_id && $parent_->store_id !== $store_id) {
  207. // throw new \Exception('父级二维码已经绑定其他商城');
  208. // }
  209. // if ($parent_->parent_id) {
  210. // $_parent_ = MdFoodsQrcode::findOne(['id' => $parent_->parent_id, 'is_delete' => 0]);
  211. // if ($_parent_) {
  212. // if ($_parent_->store_id && $_parent_->store_id !== $store_id) {
  213. // throw new \Exception('父级二维码已经绑定其他商城');
  214. // }
  215. // $_parent_->store_id = $store_id;
  216. // $_parent_->save();
  217. // }
  218. // }
  219. // $parent_->store_id = $store_id;
  220. // $parent_->save();
  221. // }
  222. // } else {
  223. $md_foods_qrcode->store_id = $store_id;
  224. // }
  225. if (!$md_foods_qrcode->save()) {
  226. throw new \Exception('保存失败:' . json_encode($md_foods_qrcode->errors, JSON_UNESCAPED_UNICODE));
  227. }
  228. $data = [
  229. 'param_url' => $md_foods_qrcode->url_path,
  230. 'wx_url' => $md_foods_qrcode->mini_path,
  231. 'ali_url' => $md_foods_qrcode->mini_path
  232. ];
  233. //判断微信是否绑定
  234. $result = $this->bindQrcode($md_foods_qrcode, $data);
  235. if ($result['code'] !== 0) {
  236. return $result;
  237. }
  238. $s_id = $this->s_id;
  239. $new_store = SalesmanNewStore::findOne($s_id);
  240. $store_params = json_decode($new_store->store_params, true);
  241. $store_params = array_merge($store_params, [
  242. 'foods_qrcode_id' => $qrcode_id
  243. ]);
  244. $new_store->store_params = json_encode($store_params, JSON_UNESCAPED_UNICODE);
  245. if (!$new_store->save()) {
  246. throw new \Exception($new_store->errors, JSON_UNESCAPED_UNICODE);
  247. }
  248. $t->commit();
  249. return [
  250. 'code' => 0,
  251. 'msg' => '操作成功'
  252. ];
  253. } catch (\Exception $e) {
  254. $t->rollBack();
  255. return [
  256. 'code' => 1,
  257. 'msg' => $e->getMessage() . $e->getLine() . $e->getFile()
  258. ];
  259. }
  260. }
  261. public function bindQrcode($qrcode, $data, $type = 0) {
  262. try {
  263. $mini_id = $this->mini_id;
  264. $ali_mini_id = $this->ali_mini_id;
  265. //判断微信是否绑定
  266. if (!$qrcode->wx_status) {
  267. $init = $this->initWx();
  268. if ($init) {
  269. //保存文件到本地
  270. $url = '/web/food/store/' . $qrcode->id;
  271. $result = $this->saveFile($init, $type, $url);
  272. if ($result['code'] !== 0) {
  273. return $result;
  274. }
  275. //生成规则
  276. $data_ = [
  277. 'prefix' => $data['param_url'],
  278. 'permit_sub_rule' => 1,
  279. 'path' => $data['wx_url'],
  280. 'open_version' => 2,
  281. 'debug_url' => [
  282. $data['param_url']
  283. ],
  284. 'is_edit' => 0
  285. ];
  286. //自定义请求接口
  287. $client = new BaseClient($init);
  288. //请求接口
  289. $result = $client->httpPostJson('cgi-bin/wxopen/qrcodejumpadd', $data_);
  290. if ($result['errcode'] != 0) {
  291. $msg = (new BaseForm())->getZnMsg($result);
  292. debug_log($msg, 'salesman_store_qrcode.log');
  293. //获取中文错误信息(微信返回为英文信息)
  294. // $msg = (new BaseForm())->getZnMsg($result);
  295. // throw new \Exception($msg);
  296. } else {
  297. throw new \Exception("数据错误");
  298. }
  299. //发布规则
  300. //所需参数
  301. $data_ = [
  302. 'prefix' => $data['param_url']
  303. ];
  304. //自定义接口提交地址
  305. $client = new BaseClient($init);
  306. //发布二维码规则接口
  307. $result = $client->httpPostJson('cgi-bin/wxopen/qrcodejumppublish', $data_);
  308. if ($result['errcode'] === 0) {
  309. $qrcode->wx_status = 1;
  310. if ($type) {
  311. $qrcode->wx_mini_id = $mini_id;
  312. if ((int)$qrcode->ali_status === 1) {
  313. $qrcode->is_use = 2;
  314. }
  315. }
  316. if (!$qrcode->save()) {
  317. throw new \Exception(json_encode($qrcode->errors));
  318. }
  319. } elseif ($result['errcode'] != 0) {
  320. $msg = (new BaseForm())->getZnMsg($result);
  321. debug_log($msg, 'salesman_store_qrcode.log');
  322. //获取中文错误信息(微信返回为英文信息)
  323. //
  324. // throw new \Exception($msg);
  325. } else {
  326. throw new \Exception("数据错误");
  327. }
  328. }
  329. }
  330. //判断支付宝是否绑定
  331. if (!$qrcode->ali_status) {
  332. //
  333. //判断关键参数是否为空
  334. if (empty($data['param_url']) || empty($data['ali_url'])) {
  335. throw new \Exception("参数错误");
  336. }
  337. //配置请求参数
  338. $data_ = json_encode([
  339. "route_url" => $data['param_url'],
  340. 'mode' => "EXACT",
  341. "page_redirection" => $data['ali_url']
  342. ]);
  343. //获取接口信息
  344. $request = new AlipayOpenMiniQrcodeBindRequest();
  345. //请求接口
  346. $result = $this->initAli($request, $data_);
  347. //请求接口错误
  348. if ($result && $result->code != 10000) {
  349. debug_log($result->sub_msg, 'salesman_store_qrcode.log');
  350. // throw new \Exception($result->sub_msg);
  351. } else {
  352. //将当前二维码支付宝状态改为已经被使用
  353. $qrcode->ali_status = 1;
  354. if ($type) {
  355. $qrcode->ali_mini_id = $ali_mini_id;
  356. if ((int)$qrcode->wx_status === 1) {
  357. $qrcode->is_use = 2;
  358. }
  359. }
  360. if (!$qrcode->save()) {
  361. throw new \Exception('保存数据失败,绑定二维码成功');
  362. }
  363. }
  364. }
  365. return [
  366. 'code' => 0,
  367. 'msg' => '操作成功'
  368. ];
  369. } catch (\Exception $e) {
  370. return [
  371. 'code' => 1,
  372. 'msg' => $e->getMessage()
  373. ];
  374. }
  375. }
  376. public function saveConfig() {
  377. try {
  378. if (!\Yii::$app->prod_is_shangmengduli()) {
  379. throw new \Exception('当前版本不可切换');
  380. }
  381. $store_id = $this->store_id;
  382. $store = Store::findOne($store_id);
  383. $store->business_model = $this->business_model;
  384. if (!$store->save()) {
  385. throw new \Exception(json_encode($store->errors));
  386. }
  387. return [
  388. 'code' => 0,
  389. 'msg' => '配置成功'
  390. ];
  391. } catch (\Exception $e) {
  392. return [
  393. 'code' => 1,
  394. 'msg' => $e->getMessage(),
  395. ];
  396. }
  397. }
  398. //获取校验文件,并保存本地
  399. public function saveFile($result, $type = 0, $url = '')
  400. {
  401. try {
  402. //获取微信配置
  403. $miniProgram = $result;
  404. //使用自定义接口
  405. $client = new BaseClient($miniProgram);
  406. //请求自定义接口
  407. $result = $client->httpPostJson('cgi-bin/wxopen/qrcodejumpdownload');
  408. if ($result['errcode'] === 0) {
  409. if ($type) {
  410. $url = '/web/face/pay';
  411. }
  412. //判断目录是否存在
  413. if (!is_dir(\Yii::$app->basePath . $url)) {
  414. //不存在则创建目录
  415. mkdir(\Yii::$app->basePath . $url, 0777, true);
  416. }
  417. //文件写入
  418. $file_result = file_put_contents(\Yii::$app->basePath . $url . '/' . $result['file_name'], $result['file_content']);
  419. //写入成功
  420. if ($file_result) {
  421. return [
  422. 'code' => 0,
  423. 'msg' => "文件写入成功"
  424. ];
  425. }
  426. //写入失败
  427. \Yii::error(json_encode($result));
  428. throw new \Exception("文件写入失败,请重新请求或手动添加。");
  429. } elseif ($result['errcode'] != 0) {
  430. //获取中文错误信息(微信返回为英文信息)
  431. $msg = (new BaseForm())->getZnMsg($result);
  432. throw new \Exception($msg);
  433. } else {
  434. throw new \Exception("数据错误");
  435. }
  436. } catch (\Exception $e) {
  437. return [
  438. 'code' => 1,
  439. 'msg' => $e->getMessage()
  440. ];
  441. }
  442. }
  443. }