YunstMiniMerchantController.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\admin\controllers;
  8. use app\constants\OptionSetting;
  9. use app\models\MerchantInfo;
  10. use app\models\Option;
  11. use app\models\Store;
  12. use app\models\StoreSchedule;
  13. use app\modules\admin\models\SaasForm;
  14. use app\modules\admin\models\WechatMiniMerchantForm;
  15. use app\modules\admin\models\YunstMiniMerchantForm;
  16. use app\plugins\scanCodePay\models\Order;
  17. use app\utils\yunst\src\MemberService;
  18. class YunstMiniMerchantController extends BaseController
  19. {
  20. /**
  21. * 设置通联商户进件
  22. * @return \yii\web\Response
  23. */
  24. public function actionSetMerchantInfo()
  25. {
  26. $form = new YunstMiniMerchantForm();
  27. $form->id = post_params("id", 0) ?: get_params("id", 0);
  28. //如果是get就获取数据
  29. if (\Yii::$app->request->isGet) {
  30. $res = $form->merchantInfo();
  31. } else {
  32. $form->merchant_info = post_params("merchant_info");
  33. $res = $form->save();
  34. }
  35. return $this->asJson($res);
  36. }
  37. /**
  38. * 商户进件结果查询
  39. * @return \yii\web\Response
  40. */
  41. public function actionMerchantStatus()
  42. {
  43. $Merchant = new \app\utils\yunst\src\Merchant();
  44. $res = $Merchant->queryMerchantStatus(get_store_id());
  45. }
  46. /**
  47. * 商户进件信息查询
  48. * @return \yii\web\Response
  49. */
  50. public function actionMerchantInfo()
  51. {
  52. $Merchant = new \app\utils\yunst\src\Merchant();
  53. $res = $Merchant->queryMerchantInfo(get_store_id());
  54. }
  55. /**
  56. * 是否可以协议签约
  57. */
  58. public function actionIsSignProtocol()
  59. {
  60. $merchant_info = MerchantInfo::findOne(['store_id' => get_store_id(), 'status'=> 3, 'is_yunst' => 1, 'is_delete' => 0]);
  61. if ($merchant_info){
  62. $store = Store::findOne(['id' => get_store_id()]);
  63. return $this->asJson(['code'=>0,'msg'=>'协议可签约','data'=>['ratio'=>$store->ratio??0]]);
  64. }else{
  65. return $this->asJson(['code'=>1,'msg'=>'商户进件信息不存在']);
  66. }
  67. }
  68. /**
  69. * 商户协议签约URL
  70. * @return \yii\web\Response
  71. */
  72. public function actionSignProtocol()
  73. {
  74. $Merchant = new \app\utils\yunst\src\Merchant();
  75. $store = Store::findOne(['id' => get_store_id()]);
  76. $ratio = post_params("ratio", 0);
  77. if (!$ratio){
  78. return $this->asJson(['code'=>1,'msg'=>'抽成比例不能为空']);
  79. }
  80. if (floatval($store->ratio) > 0) {
  81. return $this->asJson(['code'=>1,'msg'=>'已经签约过 不可重复操作']);
  82. }
  83. $store->ratio = $ratio;
  84. $store->save();
  85. //查询商户进件信息
  86. $merchant_info = MerchantInfo::findOne(['store_id' => get_store_id(),'status'=> 3, 'is_yunst' => 1, 'is_delete' => 0]);
  87. if (!$merchant_info){
  88. return $this->asJson(['code'=>1,'msg'=>'商户进件信息不存在']);
  89. }
  90. $authorizedCustName = json_decode($merchant_info->business_info,true)['merchant_shortname'];
  91. $authorizedCustId = $merchant_info->sub_mch_id;
  92. $data['bizUserId'] = $store->store_number;
  93. $data['cusid'] = $authorizedCustId;
  94. $data['commMode'] = 'rate';
  95. $data['commRatio'] = $ratio;
  96. $data['commAmoun'] = '';
  97. $data['authWay']= 'smscode';
  98. $data['authorizedCustName']= $authorizedCustName;//被授权的客户名称 ISV 入驻通联时提交的营业执照名称
  99. // $data['authorizedCustName']= "大同三然珠宝有限公司"; //被授权的客户名称 ISV 入驻通联时提交的营业执照名称
  100. // $data['authorizedCustId']= '082207111000028';
  101. $data['protocolType']= '2';
  102. $data['notifyUrl']= \Yii::$app->request->hostInfo;
  103. $data['jumpUrl']= \Yii::$app->request->hostInfo;
  104. $oldConf = Option::get(OptionSetting::SAAS_YUNST_SETTING, 0, 'saas')['value'];
  105. if ($oldConf){
  106. $oldConf = json_decode($oldConf, true);
  107. // $data['authorizedCustName']= '贵州名宾连锁科技有限公司';
  108. $data['authorizedCustId']= $oldConf['customer_number'];
  109. }
  110. // print_r($data);die();
  111. $res = $Merchant->signProtocol(get_store_id(),$data);
  112. // return $this->asJson(['code'=>1,'msg'=>$data]);
  113. // return $this->asJson(['code'=>1,'msg'=>$res]);
  114. if ($res['code'] == 10000 && $res['subCode']=='SUCCESS'){
  115. return $this->asJson(['code'=>0,'data'=>$res['data'],'msg'=>$res['subMsg'],'signProtocolUrl'=>$res['data']['signProtocolUrl']]);
  116. }else{
  117. return $this->asJson(['code'=>1,'msg'=>$res['subMsg']]);
  118. }
  119. // print_r($res);die;
  120. }
  121. /**
  122. * 商户协议签约状态查询
  123. * @return \yii\web\Response
  124. */
  125. public function actionSignProtocolStatus()
  126. {
  127. $Merchant = new \app\utils\yunst\src\Merchant();
  128. $store = Store::findOne(['id' => get_store_id()]);
  129. // if (!$store->cusid){
  130. // return [
  131. // 'code' => 1,
  132. // 'msg' => '进件商户号不存在'
  133. // ];
  134. // }
  135. $data['cusid'] = $store->cusid;
  136. $data['protocolType']= '2';
  137. //print_r($data);die();
  138. $res = $Merchant->protocolStaus(get_store_id(),$data);
  139. // return $this->asJson(['code'=>0,'msg'=>$res['subMsg']]);
  140. if ($res['subCode']!='FAIL'){
  141. return $this->asJson(['code'=>0,'data'=>$res['data']??'','msg'=>$res['subMsg']]);
  142. }else{
  143. return $this->asJson(['code'=>1,'msg'=>$res['subMsg']]);
  144. }
  145. }
  146. public function actionPay()
  147. {
  148. $orderYunst = new \app\utils\yunst\src\OrderYunst();
  149. $store = Store::findOne(['id' => get_store_id()]);
  150. $res = $orderYunst->payYunst();
  151. return $this->asJson(['code'=>0,'msg'=>$res]);
  152. if ($res['subCode']!='FAIL'){
  153. return $this->asJson(['code'=>0,'data'=>$res['data']??'','msg'=>$res['subMsg']]);
  154. }else{
  155. return $this->asJson(['code'=>1,'msg'=>$res['subMsg']]);
  156. }
  157. }
  158. /**
  159. * 聚合收款交易对账文件(收银宝接口)
  160. * @return \yii\web\Response
  161. */
  162. public function actionGetFile()
  163. {
  164. if (empty(SaasForm::yunstSetting(1))) {
  165. return $this->asJson(['code' => 1, 'msg' => '通联服务商参数配置不完善']);
  166. }
  167. $orderYunst = new \app\utils\yunst\src\OrderYunst();
  168. $store = Store::findOne(['id' => get_store_id()]);
  169. if (empty($store->cusid)) {
  170. return $this->asJson(['code' => 1, 'msg' => '通联参数配置不完善']);
  171. }
  172. $date = post_params('date','');
  173. $res = $orderYunst->getTrxFile($date,$store->cusid);
  174. if ($res['subCode']!='FAIL'){
  175. return $this->asJson(['code'=>0,'data'=>$res['data']??'','msg'=>$res['subMsg']]);
  176. }else{
  177. return $this->asJson(['code'=>1,'msg'=>$res['subMsg']]);
  178. }
  179. }
  180. /**
  181. *商户结算资金管理类交易对账文件
  182. * @return \yii\web\Response
  183. */
  184. public function actionGetAccountFile()
  185. {
  186. if (empty(SaasForm::yunstSetting(1))) {
  187. return $this->asJson(['code' => 1, 'msg' => '通联服务商参数配置不完善']);
  188. }
  189. $orderYunst = new \app\utils\yunst\src\OrderYunst();
  190. $date = post_params('date','');
  191. $res = $orderYunst->getCheckAccountFile($date);
  192. // print_r($res);die;
  193. if ($res['subCode']!='FAIL'){
  194. $file_url = $res['data']['detailUrl'];
  195. // 获取文件内容并转码
  196. $dataString = file_get_contents($file_url);
  197. $dataString = mb_convert_encoding($dataString, 'UTF-8', 'GBK');
  198. // $dataString = "CY0b6eb06781205e81706235034|202401261862102508906876928|服务商抽佣|100|10||20240126101035||
  199. // CY413362f65eb60431706238185|202401261862115728317091840|服务商抽佣|10|1||20240126110307||
  200. // AL20240125172538203993|202401261862163495248859136|服务商抽佣|20000|2000||20240126141256||
  201. // AL20240126142846101335|202401261862169223070093312|服务商抽佣|10000|1000||20240126143542||
  202. // AL20240126151652308322|202401261862179960379281408|服务商抽佣|10000|1000||20240126151821||
  203. // AL20240126160130287708|202401261862191204138094592|服务商抽佣|10000|1000||20240126160302||
  204. // SC20240126161814865844|202401261862195170238402560|服务商抽佣|12000|1200||20240126161847||";
  205. // 使用 explode() 函数将字符串拆分成数组
  206. $dataArray = explode('|', $dataString);
  207. // 删除数组中的最后一个元素
  208. array_pop($dataArray);
  209. // 移除数组中的空元素
  210. // $dataArray = array_filter($dataArray);
  211. // 将一维数组转换为二维数组,每个子数组包含8个元素
  212. $resultArray = [];
  213. $chunkedArray = array_chunk($dataArray, 8);
  214. // print_r($chunkedArray);die;
  215. // 输出结果
  216. // print_r($chunkedArray);die;
  217. if ($chunkedArray){
  218. foreach ($chunkedArray as $item) {
  219. $resultArray[] = [
  220. 'order_no' => trim($item[0]),//商户订单号
  221. 'order_time' => $item[1],//云商通联商户订单号
  222. 'order_type' => $item[2],//订单类型
  223. 'order_amount' => $item[3],//订单金额
  224. 'order_fee' => $item[4],//抽用金额
  225. 'order_status' => $item[5],//手续费
  226. 'order_remark' => $item[6],//交易完成时间
  227. 'order_time_str' => $item[7],//原商户订单号
  228. ];
  229. }
  230. foreach ($resultArray as $key=>$item){
  231. $resultArray[$key]['mch_name'] = '';
  232. //处理数据结构
  233. //查询商户信息
  234. $orderNoHead = substr($item['order_no'], 0, 2);
  235. if ($orderNoHead == 'SC'){
  236. $order_info = Order::find()->where(['order_no' => $item['order_no']])->one();
  237. if ($order_info){
  238. $store_info = Store::find()->where(['store_id' => $order_info->store_id])->one();
  239. if ($store_info){
  240. $resultArray[$key]['mch_name'] = $store_info->name;
  241. }else{
  242. $resultArray[$key]['mch_name'] = '平台';
  243. }
  244. }else{
  245. $resultArray[$key]['mch_name'] = '';
  246. }
  247. }
  248. if ($orderNoHead == 'AL'){
  249. $order_info = \app\models\Order::find()->where(['order_no' => $item['order_no']])->one();
  250. if ($order_info){
  251. $store_info = Store::find()->where(['store_id' => $order_info->store_id])->one();
  252. if ($store_info){
  253. $resultArray[$key]['mch_name'] = $store_info->name;
  254. }else{
  255. $resultArray[$key]['mch_name'] = '平台';
  256. }
  257. }else{
  258. $resultArray[$key]['mch_name'] = '';
  259. }
  260. }
  261. }
  262. return $this->asJson(['code'=>0,'data'=>$resultArray??'']);
  263. }else{
  264. return $this->asJson(['code'=>1,'msg'=>'暂无对账数据']);
  265. }
  266. return $this->asJson(['code'=>0,'data'=>$res['data']??'','msg'=>$res['subMsg']]);
  267. }else{
  268. return $this->asJson(['code'=>1,'msg'=>$res['subMsg']]);
  269. }
  270. }
  271. /**
  272. * 订单查询 本接口支持查询“服务商抽佣、服务商抽佣退款、商户资金结算/服务商提现”的订单的订单状态
  273. * @return \yii\web\Response
  274. */
  275. public function actionOrderCheck()
  276. {
  277. $orderYunst = new \app\utils\yunst\src\OrderYunst();
  278. $store = Store::findOne(['id' => get_store_id()]);
  279. $data['bizOrderNo'] = 'SC20240123145958400674';
  280. $data['orderNo'] ='202401241861428958520807424';
  281. $res = $orderYunst->getOrderStatus($data);
  282. return $this->asJson(['code'=>0,'msg'=>$res]);
  283. if ($res['subCode']!='FAIL'){
  284. return $this->asJson(['code'=>0,'data'=>$res['data']??'','msg'=>$res['subMsg']]);
  285. }else{
  286. return $this->asJson(['code'=>1,'msg'=>$res['subMsg']]);
  287. }
  288. }
  289. public function actionOrder()
  290. {
  291. $orderYunst = new \app\utils\yunst\src\OrderYunst();
  292. $store = Store::findOne(['id' => get_store_id()]);
  293. $data['bizOrderNo'] = 'SC20240123145958400674';
  294. $data['orderNo'] ='202401241861428958520807424';
  295. $res = $orderYunst->getOrderStatus($data);
  296. return $this->asJson(['code'=>0,'msg'=>$res]);
  297. if ($res['subCode']!='FAIL'){
  298. return $this->asJson(['code'=>0,'data'=>$res['data']??'','msg'=>$res['subMsg']]);
  299. }else{
  300. return $this->asJson(['code'=>1,'msg'=>$res['subMsg']]);
  301. }
  302. }
  303. public function actionList()
  304. {
  305. $form = new WechatMiniMerchantForm();
  306. $form->status = get_params("status",-1);
  307. $res = $form->list2();
  308. return $this->asJson($res);
  309. }
  310. public function actionGetCountry()
  311. {
  312. $form = new WechatMiniMerchantForm();
  313. $res = $form->getCountry();
  314. return $this->asJson($res);
  315. }
  316. // 获取小程序开始使用/暂停使用
  317. public function actionMiniIsUse(){
  318. $form = new WechatMiniMerchantForm();
  319. $form->id = post_params("id")??get_params("id");
  320. $form->is_use = post_params("is_use");
  321. $res = $form->unbind();
  322. return $this->asJson($res);
  323. }
  324. //设置店铺会员号
  325. public function actionSetStoreNumber() {
  326. try {
  327. $store_number = trim(post_params('store_number'));
  328. $store_id = get_store_id();
  329. $store = Store::findOne($store_id);
  330. if (!$store) {
  331. throw new \Exception('店铺信息不存在');
  332. }
  333. if (\Yii::$app->request->isPost) {
  334. if (!empty(trim($store->yunst_user_id))) {
  335. throw new \Exception('已经设置并提交成功 不可重复操作!');
  336. }
  337. if (!$store_number) {
  338. throw new \Exception('请输入商城会员编号!');
  339. }
  340. $store_info = Store::find()->where(['is_delete' => 0, 'store_number' => $store_number])->one();
  341. if ($store_info){
  342. throw new \Exception('会员编号已存在');
  343. }
  344. //判断后台开启通联
  345. $oldConf = Option::get(OptionSetting::SAAS_YUNST_SETTING, 0, 'saas')['value'];
  346. if ($oldConf) {
  347. $oldConf = json_decode($oldConf, true);
  348. if (empty($oldConf) || empty(trim($oldConf['appid']))) {
  349. throw new \Exception('平台配置信息缺失 需完善后重试');
  350. }
  351. //调用第三方会员创建接口
  352. $memberService = new MemberService();
  353. $res_member = $memberService->createMember($store_number,2);
  354. if ($res_member['subCode'] == "FAIL"){
  355. throw new \Exception($res_member['subMsg']);
  356. }
  357. $store->yunst_user_id = $res_member['data']['userId'] ?? '';
  358. }
  359. $store->store_number = $store_number;
  360. if (!$store->save()) {
  361. throw new \Exception(json_encode($store->errors, JSON_UNESCAPED_UNICODE));
  362. }
  363. return $this->asJson([
  364. 'code' => 0,
  365. 'msg' => '操作成功'
  366. ]);
  367. } else {
  368. $data = [
  369. 'store_number' => $store->store_number ?? ''
  370. ];
  371. return $this->asJson([
  372. 'code' => 0,
  373. 'msg' => '获取成功',
  374. 'data' => $data
  375. ]);
  376. }
  377. } catch (\Exception $e) {
  378. return $this->asJson([
  379. 'code' => 1,
  380. 'msg' => $e->getMessage()
  381. ]);
  382. }
  383. }
  384. }