PayNotify.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. namespace common\traits;
  3. use Yii;
  4. use yii\helpers\Json;
  5. use yii\web\NotFoundHttpException;
  6. use yii\web\UnprocessableEntityHttpException;
  7. use common\enums\StatusEnum;
  8. use common\helpers\ArrayHelper;
  9. use common\helpers\FileHelper;
  10. use common\helpers\WechatHelper;
  11. use common\models\extend\PayLog;
  12. use common\enums\PayTypeEnum;
  13. use common\helpers\BcHelper;
  14. use common\helpers\ResultHelper;
  15. /**
  16. * 支付回调
  17. *
  18. * Trait PayNotify
  19. * @package common\traits
  20. */
  21. trait PayNotify
  22. {
  23. /**
  24. * 支付宝
  25. *
  26. * @return void
  27. */
  28. public function actionAlipay()
  29. {
  30. try {
  31. $result = Yii::$app->pay->alipay->callback();
  32. $message = Yii::$app->request->post();
  33. unset($message['app_id']);
  34. $message['pay_fee'] = $message['total_amount'];
  35. $message['transaction_id'] = $message['trade_no'];
  36. $message['mch_id'] = $message['auth_app_id'];
  37. // 日志记录
  38. FileHelper::writeLog($this->getLogPath('alipay'), Json::encode(ArrayHelper::toArray($message)));
  39. if ($this->pay($message)) {
  40. die('success');
  41. }
  42. die('fail');
  43. } catch (\Exception $e) {
  44. // 记录报错日志
  45. FileHelper::writeLog($this->getLogPath('error'), $e->getMessage());
  46. die('fail'); // 通知响应
  47. }
  48. }
  49. /**
  50. * 公用支付回调 - 微信(v3)
  51. *
  52. * @return bool|string
  53. */
  54. public function actionWechat()
  55. {
  56. try {
  57. $result = Yii::$app->pay->wechat->callback();
  58. // 记录日志
  59. FileHelper::writeLog($this->getLogPath('wechat'), Json::encode(ArrayHelper::toArray($result)));
  60. if (
  61. $result['event_type'] === 'TRANSACTION.SUCCESS' &&
  62. $result['resource_type'] === 'encrypt-resource' &&
  63. $this->pay($result['resource']['ciphertext'])
  64. ) {
  65. return Yii::$app->pay->wechat->success();
  66. }
  67. throw new UnprocessableEntityHttpException($result['summary']);
  68. } catch (\Exception $e) {
  69. // 记录日志
  70. FileHelper::writeLog($this->getLogPath('wechat-error-sign'), Json::encode($e->getMessage()).date('Y-m-d H:i:s'));
  71. }
  72. return WechatHelper::fail();
  73. }
  74. /**
  75. * 公用支付回调 - 银联
  76. */
  77. public function actionUnion()
  78. {
  79. $response = Yii::$app->pay->unipay->notify();
  80. if ($response->isPaid()) {
  81. //pay success
  82. } else {
  83. //pay fail
  84. }
  85. }
  86. /**
  87. * 字节跳动小程序支付
  88. *
  89. * @return array|false|mixed
  90. */
  91. public function actionByteDance()
  92. {
  93. $response = Json::decode(file_get_contents('php://input'));
  94. $logPath = $this->getLogPath('byte-dance');
  95. FileHelper::writeLog($logPath, Json::encode($response));
  96. if (!Yii::$app->extendPay->byteDance->isPaid($response)) {
  97. return false;
  98. }
  99. // 重新组合数据
  100. $originalMsg = Json::decode($response['msg']);
  101. $message = [];
  102. $message['out_trade_no'] = $originalMsg['cp_orderno']; // 开发者传入订单号
  103. $message['pay_type'] = $originalMsg['way']; // way 字段中标识了支付渠道:2-支付宝,1-微信
  104. $message['pay_fee'] = BcHelper::div($originalMsg['total_amount'], 100);
  105. $message['transaction_id'] = $originalMsg['payment_order_no'];
  106. $message['mch_id'] = $originalMsg['appid'];
  107. if (!$this->pay($message)) {
  108. return false;
  109. }
  110. return ResultHelper::json(200, '成功', [
  111. 'err_no' => '0',
  112. 'err_tips' => 'success',
  113. ]);
  114. }
  115. /**
  116. * 公用支付回调 - Stripe
  117. *
  118. * @return bool|string
  119. */
  120. public function actionStripe()
  121. {
  122. $response = Json::decode(file_get_contents('php://input'));
  123. unset($response['data']['object']['charges']);
  124. if ($response['data']['object']['status'] == 'succeeded') {
  125. $logPath = $this->getLogPath('stripe');
  126. FileHelper::writeLog($logPath, Json::encode(ArrayHelper::toArray($response)));
  127. $response['out_trade_no'] = $response['data']['object']['metadata']['out_trade_no'];
  128. $response['pay_fee'] = $response['data']['object']['amount'] / 100;
  129. if ($this->pay($response)) {
  130. http_response_code(200);
  131. die('success');
  132. }
  133. http_response_code(400);
  134. die('fail');
  135. } else {
  136. die('fail');
  137. }
  138. }
  139. /**
  140. * @param $message
  141. * @return bool
  142. */
  143. protected function pay($message)
  144. {
  145. $transaction = Yii::$app->db->beginTransaction();
  146. try {
  147. if (!($payLog = Yii::$app->services->extendPay->findByOutTradeNo($message['out_trade_no']))) {
  148. throw new UnprocessableEntityHttpException('找不到支付信息');
  149. }
  150. // 支付完成
  151. if ($payLog->pay_status == StatusEnum::ENABLED) {
  152. return true;
  153. }
  154. unset($message['trade_type']);
  155. $payLog->attributes = $message;
  156. $payLog->pay_type == PayTypeEnum::WECHAT && $payLog->total_fee = $payLog->total_fee / 100;
  157. $payLog->pay_status = StatusEnum::ENABLED;
  158. $payLog->pay_time = time();
  159. if (!$payLog->save()) {
  160. throw new UnprocessableEntityHttpException('日志修改失败');
  161. }
  162. // 业务回调
  163. $this->notify($payLog);
  164. $transaction->commit();
  165. return true;
  166. } catch (\Exception $e) {
  167. $transaction->rollBack();
  168. $errorInfo = Yii::$app->services->base->getErrorInfo($e);
  169. $errorInfo = ArrayHelper::toArray($errorInfo);
  170. // 记录报错日志
  171. FileHelper::writeLog($this->getLogPath('error'), Json::encode($errorInfo));
  172. return false;
  173. }
  174. }
  175. /**
  176. * 支付回调
  177. *
  178. * @param PayLog $payLog
  179. * @throws NotFoundHttpException
  180. */
  181. public function notify(PayLog $payLog)
  182. {
  183. Yii::$app->services->extendPay->notify($payLog);
  184. }
  185. /**
  186. * @param $type
  187. * @return string
  188. */
  189. protected function getLogPath($type)
  190. {
  191. return Yii::getAlias('@runtime')."/pay-logs/".date('Y_m_d').'/'.$type.'.txt';
  192. }
  193. }
粤ICP备19079148号