AlipayCallbackController.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\common\controllers;
  8. use AopClient;
  9. use \app\models\AlipayAcitvityVoucherOrder;
  10. use app\models\ActivityOrdervoucher;
  11. use app\models\AlipayActivityDelivery;
  12. use app\models\AlipayVoucherCode;
  13. use app\models\Option;
  14. use app\models\Store;
  15. use app\models\StoreAliMini;
  16. use app\models\StoreAliMiniVersion;
  17. use app\models\StoreAliShop;
  18. use app\models\StoreMiniToken;
  19. use app\models\User;
  20. use app\models\UserCoupon;
  21. use app\modules\admin\models\AlipayThirdForm;
  22. use app\modules\admin\models\alipay\Card;
  23. use app\utils\Alipay\AlipayProfit;
  24. use app\utils\Alipay\alipaySdk\aop\request\AlipayOpenAuthTokenAppRequest;
  25. use yii\web\Controller;
  26. use app\utils\Delivery\Alipay\ADelivery;
  27. include_once \Yii::$app->basePath . "/utils/Alipay/alipaySdk/aop/AopClient.php";;
  28. class AlipayCallbackController extends Controller
  29. {
  30. /**
  31. * 支付宝第三方应用授权回调
  32. */
  33. public function actionIndex()
  34. {
  35. $app_id = get_params('app_id');
  36. $app_auth_code = get_params('app_auth_code');
  37. $store_id = get_params('state');
  38. $store = Store::findOne(['is_delete' => 0, 'id' => $store_id]);
  39. if (!$store || empty($app_id) || empty($app_auth_code)) {
  40. \Yii::error('<====================> 支付宝第三方应用授权回调 参数错误, 参数为:' . json_encode([
  41. 'app_auth_code' => $app_auth_code,
  42. 'store_id' => $store_id,
  43. 'app_id' => $app_id
  44. ]));
  45. echo '授权失败,参数错误';
  46. exit;
  47. }
  48. // 拿app_auth_code换取app_auth_token
  49. $res = AlipayProfit::token($app_auth_code);
  50. if ($res['code'] != 0) {
  51. \Yii::error('<====================> token解析失败, 参数为:' . json_encode([
  52. 'app_auth_code' => $app_auth_code,
  53. 'store_id' => $store_id,
  54. 'app_id' => $app_id,
  55. 'res' => $res['res']
  56. ]));
  57. echo '授权失败,token解析失败,错误信息:' . $res['msg'];
  58. exit;
  59. }
  60. $store->app_auth_token = $res['data'];
  61. if (!$store->save()) {
  62. \Yii::error('<====================> 入库失败, 参数为:' . json_encode([
  63. 'app_auth_code' => $app_auth_code,
  64. 'store_id' => $store_id,
  65. 'app_id' => $app_id,
  66. ]));
  67. echo '授权失败,入库失败,错误信息:' . $store->errors[0];
  68. exit;
  69. }
  70. echo '授权成功!';
  71. exit;
  72. }
  73. public function actionSpi()
  74. {
  75. /**
  76. $_GET = [
  77. 'sign' => 'drbisEtHBiDpTnQrc8a3eCPq3YWZG1I5oLXoi1kyIGcpnaSvS5ecXc5GO3lbfwqCkUN9pPtmEOnnof169NcTB1U8BX8rVU3AvAzAWzi2fbnhX9Z8PrlhdlxKOXjLrUw0arwo+RUkCyr6gQDvwzGgoUzqyhaqPkk8HM922P3/rSOmy2q5Pi6Qi5Cqb+iJMhn31tSQqDnRJL+4l2Nm8EDkpTTbyKVzJMbAHrOUVlvkQnc7ifkIOTnpTtjoysP6hIjuD8ToB9MIFEl/AHq1ZTBFKcmOblPrBydiOuAuw5KekV+1znDjlU+94sJVi6n1Dl1FG1BPoBfRBD/xLttpCmne7g=='
  78. 'method' => 'spi.alipay.user.opencard.get'
  79. 'charset' => 'UTF-8'
  80. 'version' => '1.0'
  81. 'utc_timestamp' => '1672819815'
  82. 'sign_type' => 'RSA2'
  83. ]
  84. *
  85. */
  86. \Yii::error([__METHOD__, all_params()]);
  87. $method = $_GET['method'];
  88. $action = str_replace('.', '_', $method);
  89. $res = $this->$action();
  90. return $this->asJson($res);
  91. }
  92. public function spi_alipay_user_opencard_get() {
  93. /**
  94. $_POST = [
  95. 'user_id' => '2088902351536970'
  96. 'user_info' => '[{\'OPEN_FORM_FIELD_GENDER\':\'男\'},{\'OPEN_FORM_FIELD_MOBILE\':\'13888888888\'},{\'OPEN_FORM_FIELD_NAME\':\'李四\'}]'
  97. 'out_serial_no' => '1621923366000'
  98. 'biz_card_no' => '000001'
  99. 'template_id' => '20200312000000000414103000300846'
  100. 'out_string' => 'test'
  101. ]
  102. *
  103. */
  104. $card = new Card();
  105. $res = $card->spi_alipay_user_opencard_get($_POST);
  106. return $res;
  107. }
  108. /**
  109. * 支付宝审核结果通知回调
  110. */
  111. public function actionAliNotice()
  112. {
  113. try {
  114. $file_name = \Yii::$app->runtimePath . '/logs/app_ali.log';
  115. file_put_contents($file_name, "\r\n" . '[支付宝回调信息][' . date('Y-m-d H:i:s') . ']' . json_encode(post_params()), FILE_APPEND);
  116. \Yii::error("支付宝审核结果通知回调post\n" . json_encode(post_params()));
  117. if (empty(post_params('notify_type')) && empty(post_params('msg_method'))) {
  118. $aop = new AopClient();
  119. $aop->postCharset="GBK";
  120. $aop->rsaPrivateKey = Option::get("alipay_app_private_key",0,'saas')['value'];
  121. $aop->alipayrsaPublicKey=Option::get("alipay_public_key",0,'saas')['value'];
  122. $res = $aop->rsaCheckV2(post_params(),NULL,"RSA2");
  123. if ($res) {
  124. $response_xml = "<success>true</success><biz_content>" . $aop->alipayrsaPublicKey . "</biz_content>";
  125. } else {
  126. $response_xml = "<success>false</success><error_code>VERIFY_FAILED</error_code><biz_content>" . $aop->alipayrsaPublicKey . "</biz_content>";
  127. }
  128. $mysign = $aop->alonersaSign($response_xml, $aop->rsaPrivateKey, "RSA2");
  129. $return_xml = "<?xml version=\"1.0\" encoding=\"GBK\"?><alipay><response>" . $response_xml . "</response><sign>" . $mysign . "</sign><sign_type>RSA2</sign_type></alipay>";
  130. \Yii::error("response_xml: " . $return_xml);
  131. echo $return_xml;
  132. exit ();
  133. }
  134. $biz_content = post_params('biz_content');
  135. $biz_content = json_decode($biz_content, true);
  136. if (post_params('notify_type') === "open_app_auth_notify") {
  137. $detail = $biz_content['detail'];
  138. // $notify_context = $biz_content['notify_context'];
  139. // $trigger_context = $notify_context['trigger_context'];
  140. // $out_biz_no = $trigger_context['out_biz_no'];
  141. $mini = StoreAliMini::find()->where(['auth_app_id' => post_params('auth_app_id')])->one();
  142. if (!$mini && $biz_content['notify_context']['trigger_context']['out_biz_no']) {
  143. $mini = StoreAliMini::findOne(['order_no' => $biz_content['notify_context']['trigger_context']['out_biz_no']]);
  144. }
  145. $mini->auth_app_id = post_params("auth_app_id");
  146. $mini->auth_token = $detail['app_auth_token'];
  147. $mini->userid = $detail['user_id'];
  148. $mini->refresh_token = json_encode([
  149. 'app_refresh_token' => $detail['app_refresh_token'],
  150. 'end_time' => time() + $detail['re_expires_in'],
  151. ]);
  152. $mini->auth_code = $detail['app_auth_code'];
  153. $res = $mini->save();
  154. if ($res) {
  155. $form = new AlipayThirdForm();
  156. // 保存小程序资料
  157. $form->aesAuth(0, $mini->id);
  158. $res = $form->updateMiniVersion($mini->id);
  159. if ($res['code'] === 0) {
  160. echo "success";
  161. exit();
  162. } else {
  163. \Yii::error("支付宝审核结果通知回调" . $res['msg']);
  164. throw new \Exception($res['msg']);
  165. }
  166. }
  167. } elseif (post_params('msg_method') === "alipay.open.mini.merchant.confirmed") {
  168. $mini = StoreAliMini::find()->where(['or', ['order_no' => $biz_content['out_order_no']], ['order_no' => $biz_content['order_no']]])->one();
  169. $mini->auth_app_id = $biz_content['min_app_id'];
  170. $order_cancel = $biz_content['status'];
  171. if ($order_cancel === "REJECTED" || $order_cancel === "TIMEOUT") {
  172. $mini->order_cancel = 1;
  173. }
  174. $res = $mini->save();
  175. \app\modules\alliance\models\store\SalesmanNewStoreForm::aliPush($biz_content, $mini);
  176. if ($res) {
  177. echo "success";
  178. exit();
  179. } else {
  180. throw new \Exception(json_encode($mini->errors));
  181. }
  182. } elseif (post_params('msg_method') === "alipay.open.auth.appauth.cancelled") {
  183. $mini = StoreAliMini::find()->where(['auth_app_id' => $biz_content['auth_app_id']])->one();
  184. $mini->is_cancel = 1;
  185. $res = $mini->save();
  186. if ($res) {
  187. echo "success";
  188. exit();
  189. } else {
  190. throw new \Exception(json_encode($mini->errors));
  191. }
  192. } elseif (post_params('msg_method') === "alipay.open.app.api.field.changed") {
  193. $mini = StoreAliMini::find()->where(['auth_app_id' => $biz_content['user_app_id']])->one();
  194. $mini->is_get_phone = 1;
  195. if ($biz_content['status'] === "AGREE") {
  196. $mini->is_get_phone = 2;
  197. } else {
  198. $mini->is_get_phone = 3;
  199. $mini->apply_phone_fail = $biz_content['reason'];
  200. }
  201. $res = $mini->save();
  202. if ($res) {
  203. echo "success";
  204. exit();
  205. } else {
  206. throw new \Exception(json_encode($mini->errors));
  207. }
  208. } elseif (post_params('msg_method') === "ant.merchant.expand.shop.save.rejected") {
  209. //创建门店审核失败
  210. $mini_shop = StoreAliShop::findone(['shop_order_id' => $biz_content['order_id']]);
  211. $mini_shop->status = -1;
  212. $mini_shop->fail_reason = $biz_content['reason'];
  213. $res = $mini_shop->save();
  214. if ($res) {
  215. $mini = StoreAliMini::findOne($mini_shop->mini_id);
  216. $mini->shop_status = 3;
  217. if (!$mini->save()) {
  218. throw new \Exception(json_encode($mini->errors));
  219. } else {
  220. echo "success";
  221. exit();
  222. }
  223. } else {
  224. throw new \Exception(json_encode($mini_shop->errors));
  225. }
  226. } elseif (post_params('msg_method') === "ant.merchant.expand.shop.save.passed") {
  227. //创建门店审核通过
  228. $mini_shop = StoreAliShop::findone(['shop_order_id' => $biz_content['order_id']]);
  229. $mini_shop->status = 2;
  230. $res = $mini_shop->save();
  231. if ($res) {
  232. $mini = StoreAliMini::findOne($mini_shop->mini_id);
  233. $mini->shop_status = 2;
  234. if (!$mini->save()) {
  235. throw new \Exception(json_encode($mini->errors));
  236. } else {
  237. echo "success";
  238. exit();
  239. }
  240. } else {
  241. throw new \Exception(json_encode($mini_shop->errors));
  242. }
  243. } elseif (post_params('msg_method') === "alipay.marketing.activity.delivery.changed") {
  244. //推广计划审核通知
  245. $activityDelivery = AlipayActivityDelivery::findOne(['delivery_id' => $biz_content['delivery_id']]);
  246. $fail_reason = '';
  247. switch ($biz_content['delivery_status']) {
  248. case "ACTIVE":
  249. $status = 1;
  250. break;
  251. case "INACTIVE":
  252. $status = 2;
  253. break;
  254. case "AUDIT_NO_PASS":
  255. $status = 3;
  256. $fail_reason = $biz_content['delivery_error_msg'];
  257. break;
  258. default:
  259. $status = 0;
  260. break;
  261. }
  262. $activityDelivery->status = $status;
  263. $activityDelivery->fail_reason = $fail_reason;
  264. $activityDelivery->delivery_booth_code = 1;
  265. if ($biz_content['delivery_booth_code'] === 'PAYMENT_RESULT') {
  266. $activityDelivery->delivery_booth_code = 2;
  267. }
  268. $res = $activityDelivery->save();
  269. if ($res) {
  270. echo "success";
  271. exit();
  272. } else {
  273. throw new \Exception(json_encode($activityDelivery->errors));
  274. }
  275. } elseif (post_params('msg_method') === "alipay.marketing.activity.message.received") {
  276. $order_voucher = ActivityOrdervoucher::findOne(['alipay_activity_id' => $biz_content['activity_id']]);
  277. $voucher_code = AlipayVoucherCode::findOne(['voucher_code' => $biz_content['voucher_code'], 'activity_ordervoucher_id' => $order_voucher->id]);
  278. $user = User::findOne(['alipay_open_id' => $biz_content['receive_user_id']]);
  279. $has = UserCoupon::findOne(['voucher_code_id' => $voucher_code->id]);
  280. if($has){
  281. return;
  282. }
  283. $coupon = new UserCoupon();
  284. $coupon->user_id = $user ? $user->id : 0;
  285. $coupon->alipay_open_id = $biz_content['receive_user_id'];
  286. $coupon->store_id = $order_voucher->store_id;
  287. $coupon->coupon_id = $order_voucher->coupon_id;
  288. $coupon->coupon_auto_send_id = 0;
  289. $coupon->type = 1;
  290. $coupon->is_use = 0;
  291. $coupon->is_expire = 0;
  292. $coupon->is_delete = 0;
  293. $coupon->created_at = time();
  294. $coupon->begin_time = $order_voucher->publish_start_time ? strtotime($order_voucher->publish_start_time) : 0;
  295. $coupon->end_time = $order_voucher->publish_end_time ? strtotime($order_voucher->publish_end_time) : 0;
  296. $coupon->voucher_code_id = $voucher_code->id;
  297. $coupon->save();
  298. } elseif (post_params('msg_method') === "alipay.marketing.activity.message.used") {
  299. AlipayAcitvityVoucherOrder::usedNotify($biz_content);
  300. } elseif (post_params('msg_method') === "alipay.commerce.logistics.waybill.istdstatus.changed") {
  301. ADelivery::alipayCommerceLogisticsWaybillIstdstatusChanged($biz_content);
  302. } else {
  303. $version = $biz_content['mini_app_version'] ?? "";
  304. $mini = StoreAliMini::find()->where(['auth_app_id' => $biz_content['mini_app_id'], 'is_cancel' => 0])->one();
  305. $storeVersion = StoreAliMiniVersion::find()->where(['template_version' => $version, 'mini_id' => $mini->id])->one();
  306. if (!empty($mini)) {
  307. $storeVersion->is_submit = 2;
  308. if (!empty($biz_content['audit_reason'])) {
  309. $storeVersion->is_submit = 3;
  310. $storeVersion->fail_reason = $biz_content['audit_reason'];
  311. }
  312. $storeVersion->fail_time = time();
  313. if (post_params('msg_method') === "alipay.open.mini.merchant.confirmed") {
  314. $storeVersion->is_submit = 0;
  315. }
  316. $res = $storeVersion->save();
  317. if ($res) {
  318. echo "success";
  319. exit();
  320. } else {
  321. throw new \Exception($storeVersion->errors);
  322. }
  323. }
  324. }
  325. if (empty(post_params())) {
  326. echo "fail";
  327. exit();
  328. }
  329. } catch (\Exception $e) {
  330. $file_name = \Yii::$app->runtimePath . '/logs/app_ali.log';
  331. file_put_contents($file_name, "\r\n" . '[支付宝回调信息处理结果][' . date('Y-m-d H:i:s') . ']' . json_encode($e->getMEssage()), FILE_APPEND);
  332. \Yii::error("支付宝审核结果通知回调" . $e->getMessage() . $e->getLine());
  333. }
  334. }
  335. public function actionGetToken(){
  336. try {
  337. $state = get_params('state');
  338. $auth_code = get_params('app_auth_code');
  339. $state = explode('_', base64_decode($state));
  340. $store_id = $state[0];
  341. if (!empty($state[1]) && $store_id) {
  342. $form = new AlipayThirdForm();
  343. $form->auth_code = $auth_code;
  344. $form->store_id = $store_id;
  345. $res = $form->setAuthCode();
  346. throw new \Exception(json_encode($res));
  347. }
  348. $log = StoreMiniToken::findOne(['store_id' => $store_id]);
  349. //设置基础请求数据
  350. $aop = new AopClient();
  351. //设置appid
  352. $aop->appId = Option::get("alipay_appid", 0, 'saas')['value'];
  353. //设置私钥
  354. $aop->rsaPrivateKey = Option::get("alipay_app_private_key", 0, 'saas')['value'];
  355. //设置公钥
  356. $aop->alipayrsaPublicKey = Option::get("alipay_public_key", 0, 'saas')['value'];
  357. //设置ase_key,加签方式
  358. $aop->encryptKey = Option::get("alipay_aes_key", 0, 'saas')['value'];
  359. //设置加解密方式
  360. $aop->signType = "RSA2";
  361. $param = json_encode([
  362. "grant_type" => "authorization_code",
  363. "code" => $auth_code
  364. ]);
  365. $request = new AlipayOpenAuthTokenAppRequest();
  366. $request->setBizContent($param);
  367. $result = $aop->execute($request);
  368. //请求后的数据处理
  369. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  370. $result = $result->$responseNode;
  371. if (!empty($result->code) && $result->code == 10000) {
  372. $token = $result->tokens[0];
  373. $log->app_auth_token = $token->app_auth_token;
  374. $log->update_at = time();
  375. $log->status = 1;
  376. $res = $log->save();
  377. if (!$res) {
  378. throw new \Exception($log->errors);
  379. }
  380. echo "<div style='width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center;font-size: 36px;'><h1>您已完成授权,请告知操作员</h1></div>";exit();
  381. }
  382. throw new \Exception($result->sub_msg);
  383. } catch (\Exception $e) {
  384. $file_name = \Yii::$app->runtimePath . '/logs/app_ali_token.log';
  385. file_put_contents($file_name, "\r\n" . '[token返回值][' . date('Y-m-d H:i:s') . ']' . json_encode($e->getMessage()), FILE_APPEND);
  386. }
  387. }
  388. }