AlipayThirdMerchantForm.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\admin\models;
  8. use AopClient;
  9. use app\models\AliMiniSign;
  10. use app\models\Option;
  11. use app\models\Salesman;
  12. use app\models\StoreAliMini;
  13. use app\models\StoreMiniToken;
  14. use app\utils\Alipay\alipaySdk\aop\request\AlipayOpenAgentCommonSignRequest;
  15. use app\utils\Alipay\alipaySdk\aop\request\AlipayOpenAgentConfirmRequest;
  16. use app\utils\Alipay\alipaySdk\aop\request\AlipayOpenAgentCreateRequest;
  17. use app\utils\Alipay\alipaySdk\aop\request\AlipayOpenAgentMobilepaySignRequest;
  18. use app\utils\Alipay\alipaySdk\aop\request\AlipayOpenAgentOrderQueryRequest;
  19. use app\utils\CurlHelper;
  20. use app\utils\QrCode;
  21. use yii\base\Model;
  22. include_once \Yii::$app->basePath . "/utils/Alipay/alipaySdk/aop/AopClient.php";;
  23. class AlipayThirdMerchantForm extends Model
  24. {
  25. public $ali_mini_id;
  26. public $status;
  27. public $params_info;
  28. public $base_info;
  29. public $template_info;
  30. public $app_type;
  31. public function rules()
  32. {
  33. return [
  34. [['ali_mini_id', 'status', 'app_type'], 'integer'],
  35. [['params_info'], 'safe']
  36. ];
  37. }
  38. //构造函数
  39. public function __construct($config = [])
  40. {
  41. parent::__construct($config);
  42. //获取三方平台信息
  43. //三方平台Appid
  44. $this->base_info['appid'] = Option::get("alipay_appid", 0, 'saas')['value'];
  45. //获取当前时间戳
  46. $this->base_info['timestamp'] = date("Y-m-d H:i:s");
  47. //设置加解密方式
  48. $this->base_info['sign_type'] = "RSA2";
  49. //获取私钥
  50. $this->base_info['private_key'] = Option::get("alipay_app_private_key", 0, 'saas')['value'];
  51. //获取公钥
  52. $this->base_info['public_key'] = Option::get("alipay_public_key", 0, 'saas')['value'];
  53. //获取ase_key,加签方式
  54. $this->base_info['alipay_aes_key'] = Option::get("alipay_aes_key", 0, 'saas')['value'];
  55. //获取模板aes加签方式
  56. $this->template_info['ali_template_aes'] = Option::get("ali_template_aes", 0, 'saas')['value'];
  57. //获取模板appid
  58. $this->template_info['ali_template_appid'] = Option::get("ali_template_appid", 0, 'saas')['value'];
  59. //获取模板auth_token
  60. $this->template_info['ali_template_token'] = Option::get("ali_template_token", 0, 'saas')['value'];
  61. }
  62. public function miniCommon($request, $biz_content = null, $is_hidden_token = 0, $token = '')
  63. {
  64. try {
  65. //模板信息
  66. $template_info = $this->template_info;
  67. //请求的基础信息
  68. $base_info = $this->base_info;
  69. //模板token
  70. $auth_token = $template_info['ali_template_token'];
  71. //小程序ID
  72. $ali_mini_id = $this->ali_mini_id;
  73. if (!empty($ali_mini_id)) {
  74. $store_token = StoreAliMini::findOne($ali_mini_id);
  75. //如果小程序ID存在,则将token从模板转成商家小程序的token
  76. if (!empty($store_token->auth_token)) {
  77. $auth_token = $store_token->auth_token;
  78. }
  79. }
  80. //设置基础请求数据
  81. $aop = new AopClient();
  82. //设置appid
  83. $aop->appId = $base_info['appid'];
  84. //设置私钥
  85. $aop->rsaPrivateKey = $base_info['private_key'];
  86. //设置公钥
  87. $aop->alipayrsaPublicKey = $base_info['public_key'];
  88. //设置ase_key,加签方式
  89. $aop->encryptKey = $base_info['alipay_aes_key'];
  90. //设置加解密方式
  91. $aop->signType = $base_info['sign_type'];
  92. //处理没有biz_content情况
  93. if ($biz_content) {
  94. $request->setBizContent($biz_content);
  95. }
  96. //处理不需要token情况
  97. if ($is_hidden_token === 0) {
  98. //开始请求
  99. $result = $aop->execute($request, null, ($token ?: $auth_token));
  100. } else {
  101. //开始请求
  102. $result = $aop->execute($request);
  103. }
  104. //请求后的数据处理
  105. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  106. return $result->$responseNode;
  107. } catch (\Exception $e) {
  108. return [
  109. 'sub_msg' => $e->getMessage()
  110. ];
  111. }
  112. }
  113. /**
  114. * @return array
  115. * 创建事务
  116. */
  117. public function getMerchantPay(): array
  118. {
  119. try {
  120. $ali_mini_id = $this->ali_mini_id;
  121. $params_info = $this->params_info;
  122. $ali_sign = AliMiniSign::findOne(['ali_mini_id' => $ali_mini_id, 'type' => 1]) ?: new AliMiniSign();
  123. $ali_sign->type = 1;
  124. $ali_sign->ali_mini_id = $ali_mini_id;
  125. $ali_sign->app_type = intval($this->app_type);
  126. $store_ali_mini = StoreAliMini::findOne($ali_mini_id);
  127. if (intval($this->app_type)) {
  128. $store_ali_token = StoreMiniToken::findOne($ali_mini_id);
  129. $store_ali_mini = (object)[
  130. 'alipay_account' => $store_ali_token->account,
  131. 'contact_name' => $store_ali_token->contact_name,
  132. 'service_phone' => $store_ali_token->contact_mobile,
  133. 'service_email' => $store_ali_token->contact_email,
  134. 'app_name' => $store_ali_token->contact_name . '分账签约应用'
  135. ];
  136. }
  137. //获取事务状态
  138. $batch_status = intval($ali_sign->batch_status);
  139. //如果已经开始审核,且没有失败,没有被商户手动拒绝
  140. if ($batch_status > 4 && $batch_status !== 8) {
  141. throw new \Exception("审核中,无需操作");
  142. }
  143. if (
  144. empty($params_info['alipay_account']) ||
  145. empty($params_info['contact_name']) ||
  146. empty($params_info['service_phone']) ||
  147. empty($params_info['service_email']) ||
  148. empty($params_info['license_pic']) ||
  149. empty($params_info['license_no'])
  150. ) {
  151. throw new \Exception("请完善信息");
  152. }
  153. $param = json_encode([
  154. 'account' => $params_info['alipay_account'] ?: $store_ali_mini->alipay_account,
  155. 'contact_info' => [
  156. 'contact_name' => $params_info['contact_name'] ?: $store_ali_mini->contact_name,
  157. 'contact_mobile' => $params_info['service_phone'] ?: $store_ali_mini->service_phone,
  158. 'contact_email' => $params_info['service_email'] ?: $store_ali_mini->service_email
  159. ]
  160. ]);
  161. //调用接口配置信息
  162. $request = new AlipayOpenAgentCreateRequest();
  163. //调用接口
  164. $mini_token = null;
  165. if (intval($this->app_type) === 1) {
  166. $store_token = StoreMiniToken::findOne($ali_mini_id);
  167. if ($store_token) {
  168. $mini_token = $store_token->app_auth_token;
  169. }
  170. }
  171. $result = $this->miniCommon($request, $param, 0, $mini_token);
  172. if ($result->code == 10000) {
  173. //保存事务编号,用作签约等操作
  174. $batch_no = $result->batch_no;
  175. $ali_sign->batch_no = $batch_no;
  176. if (intval($this->app_type) === 0) {
  177. $store_ali_mini->alipay_account = $params_info['alipay_account'];
  178. $store_ali_mini->contact_name = $params_info['contact_name'];
  179. $store_ali_mini->service_phone = $params_info['service_phone'];
  180. $store_ali_mini->service_email = $params_info['service_email'];
  181. //保存信息
  182. if (!$store_ali_mini->save()) {
  183. throw new \Exception(json_encode($store_ali_mini->errors));
  184. }
  185. }
  186. //保存状态信息
  187. $ali_sign->batch_status = 1;
  188. //保存信息
  189. if (!$ali_sign->save()) {
  190. throw new \Exception(json_encode($ali_sign->errors));
  191. }
  192. $result = $this->appPay($ali_sign, $store_ali_mini, $batch_no);
  193. if ($result['code'] !== 0) {
  194. throw new \Exception($result['msg']);
  195. }
  196. $result = $this->openAgentConfirm($ali_sign, $batch_no);
  197. if ($result['code'] !== 0) {
  198. throw new \Exception($result['msg']);
  199. }
  200. return [
  201. 'code' => 0,
  202. 'msg' => $result['msg'],
  203. 'data' => $result['data']
  204. ];
  205. } else {
  206. throw new \Exception($result->sub_msg);
  207. }
  208. } catch (\Exception $e) {
  209. return [
  210. 'code' => 1,
  211. 'msg' => $e->getMessage()
  212. ];
  213. }
  214. }
  215. /**
  216. * @param array | AliMiniSign $model
  217. * @param array | StoreAliMini $ali_model
  218. * @param string $batch_no
  219. * @return array
  220. * 签约分账
  221. */
  222. public function appPay($model, $ali_model, string $batch_no = '')
  223. {
  224. try {
  225. $params_info = $this->params_info;
  226. $request = new AlipayOpenAgentCommonSignRequest();
  227. $license_pic = $this->saveTempImage($params_info['license_pic']);
  228. //设置业务编号
  229. $request->setBatchNo($batch_no);
  230. //设置商家经营类目编码
  231. $request->setMccCode("A0002_B0201");
  232. //特殊资质证书
  233. if (!empty($params_info['special_license_pic'])) {
  234. $request->setSpecialLicensePic($params_info['other_data']);
  235. }
  236. // $request->setBusinessLicenseNo($params_info['license_no']);
  237. // $request->setDateLimitation("2099-12-31");
  238. $request->setProductCode('DOMESTIC_ALLOC');
  239. $request->setBusinessLicensePic("@". $license_pic);
  240. $request->setAppName($ali_model->app_name);
  241. $request->setLongTerm(true);
  242. $request->setDateLimitation("2999-12-31");
  243. $request->setBusinessLicenseNo($params_info['license_no']);
  244. //调用接口
  245. $result = $this->miniCommon($request,null, 1);
  246. //如果请求成功或者报同类产品已经签约就显示成功
  247. if (($result->code == 10000) || $result->sub_code == "ANT_PRODUCT_CONFLICT") {
  248. $model->batch_status = 2;
  249. if (intval($this->app_type) === 0) {
  250. $ali_model->license_pic = $params_info['license_pic'];
  251. $ali_model->license_no = $params_info['license_no'];
  252. if (!$ali_model->save()) {
  253. throw new \Exception(json_encode($model->errors));
  254. }
  255. }
  256. if (!$model->save()) {
  257. throw new \Exception(json_encode($model->errors));
  258. }
  259. return [
  260. 'code' => 0,
  261. 'msg' => "操作成功",
  262. 'batch_status' => $ali_model->batch_status
  263. ];
  264. }
  265. throw new \Exception($result->sub_msg);
  266. } catch (\Exception $e) {
  267. return [
  268. 'code' => 1,
  269. 'msg' => $e->getMessage()
  270. ];
  271. }
  272. }
  273. /**
  274. * @param array | AliMiniSign $model
  275. * @param string $batch_no
  276. * @return array
  277. * 提交事务
  278. */
  279. public function openAgentConfirm($model, string $batch_no = '')
  280. {
  281. try {
  282. //请求参数
  283. $param = json_encode([
  284. //业务编号
  285. 'batch_no' => $batch_no
  286. ]);
  287. //请求配置信息
  288. $request = new AlipayOpenAgentConfirmRequest();
  289. $result = $this->miniCommon($request, $param, 1);
  290. //请求成功
  291. if ($result->code == 10000) {
  292. $model->batch_status = 3;
  293. if (!$model->save()) {
  294. throw new \Exception($model->errors);
  295. }
  296. return [
  297. 'code' => 0,
  298. 'msg' => "成功",
  299. 'data' => $result
  300. ];
  301. }
  302. throw new \Exception($result->sub_msg);
  303. } catch (\Exception $e) {
  304. return [
  305. 'code' => 1,
  306. 'msg' => $e->getMessage(),
  307. ];
  308. }
  309. }
  310. /**
  311. * @return array|void
  312. * 查询状态
  313. */
  314. public function openAgentOrderStatus()
  315. {
  316. try {
  317. $ali_mini_id = $this->ali_mini_id;
  318. if (intval($this->app_type) === 1) {
  319. $model = AliMiniSign::findOne(['ali_mini_id' => $ali_mini_id, 'type' => 1]);
  320. } else {
  321. $model = AliMiniSign::findOne(['id' => $ali_mini_id, 'type' => 1]);
  322. }
  323. if (empty($model)) {
  324. throw new \Exception('没有待查询的信息');
  325. }
  326. $batch_no = $model->batch_no;
  327. if (empty($batch_no)) {
  328. throw new \Exception('未创建事务');
  329. }
  330. //请求参数
  331. $param = json_encode([
  332. //业务编号
  333. 'batch_no' => $batch_no
  334. ]);
  335. $request = new AlipayOpenAgentOrderQueryRequest();
  336. $result = $this->miniCommon($request, $param, 1);
  337. if ($result->code == 10000) {
  338. $status = $result->order_status;
  339. $msg = "成功";
  340. switch ($status) {
  341. case "MERCHANT_INFO_HOLD": //异常单 4
  342. $model->batch_status = 4;
  343. $model->fail_reason = "订单异常";
  344. break;
  345. case "MERCHANT_AUDITING": //审核中 3
  346. $model->batch_status = 3;
  347. $model->fail_reason = "订单审核中";
  348. break;
  349. case "MERCHANT_CONFIRM": //待确认 5
  350. $model->batch_status = 5;
  351. $model->batch_url = $result->confirm_url;
  352. $model->fail_reason = "等待商户确认,请注意查收邮件以及短信或访问" . $result->confirm_url . "进行授权";
  353. break;
  354. case "MERCHANT_CONFIRM_SUCCESS": //商户确认成功 6
  355. $model->batch_status = 2;
  356. $model->fail_reason = "商户确认成功";
  357. break;
  358. case "MERCHANT_CONFIRM_TIME_OUT": //商户超时未确认 7
  359. $model->batch_status = 7;
  360. $model->fail_reason = "商户超时未确认";
  361. break;
  362. case "MERCHANT_APPLY_ORDER_CANCELED": //审核失败或商户拒绝 8
  363. $model->batch_status = 8;
  364. $model->fail_reason = $result->reject_reason;
  365. break;
  366. }
  367. if (!$model->save()) {
  368. throw new \Exception($model->errors);
  369. }
  370. return [
  371. 'code' => 0,
  372. 'msg' => $msg,
  373. 'data' => $result
  374. ];
  375. }
  376. throw new \Exception($result->sub_msg);
  377. } catch (\Exception $e) {
  378. $file_name = \Yii::$app->runtimePath . '/logs/app_pay.log';
  379. file_put_contents($file_name, "\r\n" . '[商城申请商家分账支付][' . date('Y-m-d H:i:s') . ']' . $e->getMessage(), FILE_APPEND);
  380. return [
  381. 'code' => 1,
  382. 'msg' => $e->getMessage() . $this->ali_mini_id,
  383. ];
  384. }
  385. }
  386. public function getAppInfo($type = 0)
  387. {
  388. try {
  389. $ali_mini_id = $this->ali_mini_id;
  390. $where = [];
  391. if ($type) { //App分账
  392. $where = [
  393. 'app_type' => 1
  394. ];
  395. $store_ali_mini = StoreMiniToken::find()->where(['id' => $ali_mini_id])
  396. ->select('id, account alipay_account, contact_name, contact_mobile service_phone, contact_email service_email, license_pic, license_no')
  397. ->asArray()->one();
  398. } else {
  399. $store_ali_mini = StoreAliMini::find()->where(['id' => $ali_mini_id])
  400. ->select('id, alipay_account, contact_name, service_phone, service_email, license_pic, license_no')
  401. ->asArray()->one();
  402. }
  403. $ali_sign = AliMiniSign::findOne(array_merge(['ali_mini_id' => $ali_mini_id, 'type' => 1], $where));
  404. $store_ali_mini['batch_status'] = $ali_sign['batch_status'] ?? 0;
  405. $store_ali_mini['fail_reason'] = $ali_sign['fail_reason'] ?? '';
  406. return [
  407. 'code' => 0,
  408. 'data' => $store_ali_mini ?: [
  409. "alipay_account" => '',
  410. "contact_name" => '',
  411. "service_phone" => '',
  412. "service_email" => '',
  413. "license_pic" => '',
  414. "license_no" => '',
  415. "batch_status" => 0
  416. ]
  417. ];
  418. } catch (\Exception $e) {
  419. return [
  420. 'code' => 1,
  421. 'msg' => $e->getMessage(),
  422. ];
  423. }
  424. }
  425. //获取网络图片到临时目录
  426. public function saveTempImage($url)
  427. {
  428. if (strpos($url, 'http') === false) {
  429. $url = 'http:' . trim($url);
  430. }
  431. if (!is_dir(\Yii::$app->runtimePath . '/image')) {
  432. mkdir(\Yii::$app->runtimePath . '/image');
  433. }
  434. $save_path = \Yii::$app->runtimePath . '/image/' . md5($url) . '.jpg';
  435. CurlHelper::download($url, $save_path);
  436. return $save_path;
  437. }
  438. }