PaymentController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <?php
  2. namespace app\payment;
  3. use app\common\components\BaseController;
  4. use app\common\events\payment\ChargeComplatedEvent;
  5. use app\common\events\payment\RechargeComplatedEvent;
  6. use app\common\exceptions\ShopException;
  7. use app\common\models\AccountWechats;
  8. use app\common\models\OrderPay;
  9. use app\common\models\PayOrder;
  10. use app\frontend\modules\finance\services\BalanceRechargeResultService;
  11. use app\frontend\modules\order\services\OrderService;
  12. use Illuminate\Support\Facades\DB;
  13. use Yunshop\ClockIn\models\ClockPayLogModel;
  14. use Yunshop\Gold\frontend\services\RechargeService;
  15. /**
  16. * Created by PhpStorm.
  17. * Author: 芸众商城 www.yunzshop.com
  18. * Date: 24/03/2017
  19. * Time: 09:06
  20. */
  21. class PaymentController extends BaseController
  22. {
  23. public function __construct()
  24. {
  25. parent::__construct();
  26. $this->init();
  27. }
  28. protected function init()
  29. {
  30. $script_info = pathinfo($_SERVER['SCRIPT_NAME']);
  31. \Log::debug('init');
  32. \Log::debug($script_info);
  33. if (!empty($script_info)) {
  34. switch ($script_info['filename']) {
  35. case 'notifyUrl':
  36. \YunShop::app()->uniacid = $this->getUniacid();
  37. break;
  38. case 'refundNotifyUrl':
  39. case 'withdrawNotifyUrl':
  40. $batch_no = !empty($_REQUEST['batch_no']) ? $_REQUEST['batch_no'] : '';
  41. \YunShop::app()->uniacid = (int)substr($batch_no, 17, 5);
  42. break;
  43. case 'returnUrl':
  44. if (strpos($_GET['out_trade_no'], '_') !== false) {
  45. $data = explode('_', $_GET['out_trade_no']);
  46. \YunShop::app()->uniacid = $data[0];
  47. } else {
  48. \YunShop::app()->uniacid = $this->getUniacid();
  49. }
  50. break;
  51. default:
  52. \YunShop::app()->uniacid = $this->getUniacid();
  53. break;
  54. }
  55. }
  56. \Setting::$uniqueAccountId = \YunShop::app()->uniacid;
  57. AccountWechats::setConfig(AccountWechats::getAccountByUniacid(\YunShop::app()->uniacid));
  58. }
  59. /**
  60. * 支付宝获取当前公众号
  61. *
  62. * @return int
  63. */
  64. private function getUniacid()
  65. {
  66. $body = !empty($_REQUEST['body']) ? $_REQUEST['body'] : '';
  67. \Log::debug('body===========', $body);
  68. //区分app支付获取
  69. if ($_REQUEST['sign_type'] == 'MD5') {
  70. $uniacid = substr($body, strrpos($body, ':') + 1);
  71. } else {
  72. $uniacid = $this->substr_var($_REQUEST['body']);
  73. }
  74. \Log::debug('body获取unicid', $uniacid);
  75. if (!empty($uniacid)) {
  76. return intval($uniacid);
  77. } else {
  78. return 0;
  79. }
  80. }
  81. /**
  82. * 去除前后引号
  83. *
  84. * @param $value
  85. * @return bool|string
  86. */
  87. public function substr_var($str)
  88. {
  89. if (strstr($str, '"')) {
  90. return str_replace('"', '', $str);
  91. }
  92. return $str;
  93. }
  94. protected function _payResutl($data)
  95. {
  96. $type = $this->getPayType($data['out_trade_no']);
  97. $pay_order_model = PayOrder::getPayOrderInfo($data['out_trade_no'])->first();
  98. if ($pay_order_model) {
  99. $pay_order_model->status = 2;
  100. $pay_order_model->pay_type_id = $data['pay_type_id'];
  101. $pay_order_model->trade_no = $data['trade_no'];
  102. $pay_order_model->third_type = $data['pay_type'];
  103. $pay_order_model->save();
  104. }
  105. switch ($type) {
  106. case "charge.succeeded":
  107. \Log::debug("{$data['out_trade_no']}支付操作", ['charge.succeeded']);
  108. $orderPay = OrderPay::where('pay_sn', $data['out_trade_no'])->orderBy('id', 'desc')->first();
  109. if ($data['unit'] == 'fen') {
  110. $amount = $orderPay->amount * 100;
  111. } else {
  112. $amount = $orderPay->amount;
  113. }
  114. if (bccomp($amount, $data['total_fee'], 2) == 0) {
  115. //这里先验证支付号对应的订单状态是否关闭
  116. $bool = (new OrderPayException($data))->handle($orderPay);
  117. if ($bool) {
  118. \Log::debug('更新订单状态出现异常');
  119. break;
  120. }
  121. \Log::debug('更新订单状态');
  122. OrderService::ordersPay(['order_pay_id' => $orderPay->id, 'pay_type_id' => $data['pay_type_id']]);
  123. event(new ChargeComplatedEvent([
  124. 'order_sn' => $data['out_trade_no'],
  125. 'pay_sn' => $data['trade_no'],
  126. 'order_pay_id' => $orderPay->id
  127. ]));
  128. } else {
  129. \Log::debug("金额校验失败", "{$orderPay->amount}不等于{$data['total_fee']}");
  130. throw new ShopException("金额校验失败:{$orderPay->amount}不等于{$data['total_fee']}");
  131. }
  132. break;
  133. case "recharge.succeeded":
  134. \Log::debug('支付操作', ['recharge.succeeded', $data['out_trade_no']]);
  135. //充值成功事件
  136. event(new RechargeComplatedEvent([
  137. 'order_sn' => $data['out_trade_no'],
  138. 'pay_sn' => $data['trade_no'],
  139. 'total_fee' => $data['total_fee'],
  140. 'unit' => $data['unit']
  141. ]));
  142. break;
  143. case "gold_recharge.succeeded":
  144. \Log::debug('金币支付操作', ['gold_recharge.succeeded', $data['out_trade_no']]);
  145. RechargeService::payResult([
  146. 'order_sn' => $data['out_trade_no'],
  147. 'pay_sn' => $data['trade_no'],
  148. 'total_fee' => $data['total_fee']
  149. ]);
  150. //充值成功事件
  151. event(new RechargeComplatedEvent([
  152. 'order_sn' => $data['out_trade_no'],
  153. 'pay_sn' => $data['trade_no'],
  154. 'total_fee' => $data['total_fee']
  155. ]));
  156. break;
  157. case "card_charge.succeeded":
  158. \Log::debug('打卡支付操作', ['card_charge.succeeded', $data['out_trade_no']]);
  159. $orderPay = ClockPayLogModel::where('order_sn', $data['out_trade_no'])->first();
  160. if ($data['unit'] == 'fen') {
  161. $orderPay->amount = $orderPay->amount * 100;
  162. }
  163. if (bccomp($orderPay->amount, $data['total_fee'], 2) == 0) {
  164. \Log::debug('更新订单状态');
  165. event(new ChargeComplatedEvent([
  166. 'order_sn' => $data['out_trade_no'],
  167. 'pay_sn' => $data['trade_no'],
  168. 'total_fee' => $data['total_fee']
  169. ]));
  170. }
  171. break;
  172. case "dashang_charge.succeeded":
  173. \Log::debug('打赏支付操作', ['dashang_charge.succeeded', $data['out_trade_no']]);
  174. event(new ChargeComplatedEvent([
  175. 'order_sn' => $data['out_trade_no'],
  176. 'pay_sn' => '',
  177. 'unit' => $data['unit'],
  178. 'total_fee' => $data['total_fee']
  179. ]));
  180. break;
  181. case "auction_charge.succeeded":
  182. \Log::debug('拍卖', ['auction_charge.succeeded', $data['out_trade_no']]);
  183. event(new RechargeComplatedEvent([
  184. 'order_sn' => $data['out_trade_no'],
  185. 'pay_sn' => '',
  186. 'unit' => $data['unit'],
  187. 'total_fee' => $data['total_fee']
  188. ]));
  189. break;
  190. case "crowdfunding.succeeded":
  191. \Log::debug('众筹活动', ['auction_charge.succeeded', $data['out_trade_no']]);
  192. event(new ChargeComplatedEvent([
  193. 'order_sn' => $data['out_trade_no'],
  194. 'unit' => $data['unit'],
  195. 'total_fee' => $data['total_fee']
  196. ]));
  197. break;
  198. case "travel_around.succeeded":
  199. \Log::debug('周边游支付', ['travel_around.succeeded', $data['out_trade_no']]);
  200. event(new ChargeComplatedEvent([
  201. 'order_sn' => $data['out_trade_no'],
  202. 'unit' => $data['unit'],
  203. 'total_fee' => $data['total_fee']
  204. ]));
  205. break;
  206. }
  207. }
  208. /**
  209. * 支付回调操作
  210. * @param $data
  211. */
  212. public function payResutl($data)
  213. {
  214. try {
  215. $this->_payResutl($data);
  216. return true;
  217. } catch (\Exception $e) {
  218. $msg = $e->getMessage();
  219. \Log::debug('回调失败:', $msg);
  220. echo $msg;
  221. exit();
  222. }
  223. }
  224. public function payEvent($data)
  225. {
  226. try {
  227. $this->_payResutl($data);
  228. return ['code'=> true, 'msg' => '成功'];
  229. } catch (\Exception $e) {
  230. $msg = $e->getMessage();
  231. \Log::debug('事件支付通知失败:', $msg);
  232. return ['code'=> false, 'msg' => $msg];
  233. }
  234. }
  235. /**
  236. * 支付方式
  237. *
  238. * @param $order_id
  239. * @return string
  240. */
  241. public function getPayType($order_id)
  242. {
  243. if (!empty($order_id)) {
  244. $tag = substr($order_id, 0, 2);
  245. if ('PN' == strtoupper($tag)) {
  246. return 'charge.succeeded';
  247. } elseif ('RV' == strtoupper($tag) || "RF" == strtoupper($tag) || "RL" == strtoupper($tag) || "KA" == strtoupper($tag) || "RI" == strtoupper($tag) || "RS" == strtoupper($tag) || "RI" == strtoupper($tag)) {
  248. return 'recharge.succeeded';
  249. } elseif ('RG' == strtoupper($tag)) {
  250. return 'gold_recharge.succeeded';
  251. } elseif ('CI' == strtoupper($tag)) {
  252. return 'card_charge.succeeded';
  253. } elseif ('APR' == strtoupper(substr($order_id, 0, 3))) {
  254. return 'auction_charge.succeeded';
  255. } elseif ('DS' == strtoupper($tag) || "PG" == strtoupper($tag)) {
  256. return 'dashang_charge.succeeded';
  257. } elseif ('CG' == strtoupper($tag)) {
  258. return 'crowdfunding.succeeded';
  259. }elseif ('ZBY' == strtoupper(substr($order_id, 0, 3))) {
  260. return 'travel_around.succeeded';
  261. }
  262. }
  263. return '';
  264. }
  265. }