RemitForm.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. namespace common\pay;
  3. use backend\models\RemitLog;
  4. use backend\models\RemitOrder;
  5. use yii\base\Model;
  6. class RemitForm extends Model
  7. {
  8. /**
  9. * @var string 通知地址
  10. */
  11. public $notifyUrl;
  12. /**
  13. * @var int 打款单号
  14. */
  15. public $remitNo;
  16. /**
  17. * @var string 打款密码
  18. */
  19. public $password;
  20. /**
  21. * @var int 操作人id
  22. */
  23. public $adminId;
  24. /**
  25. * @var string 操作人名字
  26. */
  27. public $adminName;
  28. /**
  29. * @var string 操作人ip
  30. */
  31. public $adminIp;
  32. /**
  33. * @var string 异步通知响应结果
  34. */
  35. private $_outNotifyResult;
  36. /**
  37. * @return array
  38. */
  39. public function rules()
  40. {
  41. return [
  42. [['notifyUrl', 'remitNo', 'password'], 'required'],
  43. [['remitNo'], 'integer'],
  44. [['notifyUrl', 'password', 'adminId', 'adminName', 'adminIp'], 'string'],
  45. ];
  46. }
  47. /**
  48. * @return bool
  49. */
  50. public function outRemit()
  51. {
  52. if ($this->validate()) {
  53. $remitOrder = RemitOrder::find()->where(['remit_no' => $this->remitNo])->limit(1)->asArray()->one();
  54. if ($remitOrder == null) {
  55. $this->addError('remitNo', '打款单不存在');
  56. return false;
  57. }
  58. if ($remitOrder['audit_status'] != RemitOrder::STATUS_REAUDIT_SUCCESS) {
  59. // 复审未通过
  60. $this->addError('remitNo', '复审未通过');
  61. return false;
  62. }
  63. if ($remitOrder['pay_status'] != RemitOrder::STATUS_PAY_INIT) {
  64. $this->addError('remitNo', '打款单状态必须是未打款');
  65. return false;
  66. }
  67. $handler = BaseRemitHandler::getRemitHandlerByPayType($remitOrder['pay_type']);
  68. if ($handler == null) {
  69. $this->addError('remitNo', '打款通道不存在');
  70. return false;
  71. }
  72. // 待打款 -> 内部打款中
  73. $saveData = [
  74. 'pay_status' => RemitOrder::STATUS_PAY_INNER_PROCESS,
  75. 'pay_time' => time(),
  76. ];
  77. $saveWhere = [
  78. 'id' => $remitOrder['id'],
  79. 'remit_no' => $remitOrder['remit_no'],
  80. 'pay_status' => RemitOrder::STATUS_PAY_INIT,
  81. ];
  82. $logData = [];
  83. $logData['admin_id'] = $this->adminId;
  84. $logData['admin_name'] = $this->adminName;
  85. $logData['admin_ip'] = $this->adminIp;
  86. $transaction = RemitOrder::getDb()->beginTransaction();
  87. try {
  88. $affectRows = RemitOrder::updateAll($saveData, $saveWhere);
  89. if ($affectRows == 0) {
  90. throw new \Exception("打款单状态更新失败1,remitNo: " . $remitOrder['remit_no']);
  91. }
  92. $logData['memo'] = "打款单状态: 未打款 -> 内部打款中";
  93. RemitLog::addLog($remitOrder, $logData);
  94. $transaction->commit();
  95. } catch (\Exception $e) {
  96. $transaction->rollBack();
  97. $logData['memo'] = $e->getMessage();
  98. RemitLog::addLog($remitOrder, $logData);
  99. $this->addError('remitNo', $e->getMessage());
  100. return false;
  101. }
  102. // 内部打款中 -> 外部打款中
  103. $handler->notifyUrl = $this->notifyUrl;
  104. $params = [];
  105. $params['ip'] = $this->adminIp;
  106. $params['password'] = $this->password;
  107. $isSuccess = false;
  108. // for ($i = 0; $i < 2; $i++) {
  109. $result = $handler->outRemit($remitOrder, $params);
  110. $saveData = [];
  111. foreach (['pay_status', 'out_no', 'out_no_crc32', 'ret_code', 'res_code', 'ret_msg'] as $field) {
  112. isset($result[$field]) && $saveData[$field] = trim($result[$field]);
  113. }
  114. unset($result);
  115. $logData = [];
  116. $logData['admin_id'] = 0;
  117. $logData['admin_name'] = '系统';
  118. $logData['admin_ip'] = '';
  119. $transaction = RemitOrder::getDb()->beginTransaction();
  120. try {
  121. if (isset($saveData['pay_status']) && $saveData['pay_status'] == RemitOrder::STATUS_PAY_OUTER_PROCESS) {
  122. $isSuccess = true;
  123. $logData['memo'] = '打款单打款状态:内部打款中 -> 外部打款中';
  124. } else {
  125. unset($saveData['pay_status']); // 不更新状态
  126. $retMsg = '';
  127. if (isset($saveData['ret_code'])) {
  128. $retMsg .= trim($saveData['ret_code']) . ' ';
  129. }
  130. if (isset($saveData['res_code'])) {
  131. $retMsg .= trim($saveData['res_code']) . ' ';
  132. }
  133. if (isset($saveData['ret_msg'])) {
  134. $retMsg .= trim($saveData['ret_msg']) . ' ';
  135. }
  136. $logData['memo'] = '外部打款异常:' . trim($retMsg);
  137. }
  138. $affectRows = RemitOrder::updateAll($saveData, ['remit_no' => $remitOrder['remit_no'], 'pay_status' => [RemitOrder::STATUS_PAY_INNER_PROCESS, RemitOrder::STATUS_PAY_EXCEPTION]]);
  139. if ($affectRows == 0) {
  140. throw new \Exception("打款单状态更新失败2,remitNo: {$remitOrder['remit_no']}");
  141. }
  142. RemitLog::addLog($remitOrder, $logData);
  143. $transaction->commit();
  144. } catch (\Exception $e) {
  145. $transaction->rollBack();
  146. $logData['memo'] = $e->getMessage();
  147. RemitLog::addLog($remitOrder, $logData);
  148. }
  149. // if ($isSuccess) {
  150. // break;
  151. // }
  152. // usleep(100000); // 休眠100ms 重试
  153. // }
  154. if ($isSuccess == false) {
  155. $this->addError('remitNo', '打款失败');
  156. }
  157. }
  158. return !$this->hasErrors();
  159. }
  160. /**
  161. * @param array $data
  162. * @return bool
  163. */
  164. public function handleNotify($data)
  165. {
  166. if (!isset($data['remitNo']) || trim($data['remitNo']) == '') {
  167. return false;
  168. }
  169. $remitOrder = RemitOrder::findByRemitNo($data['remitNo']);
  170. if ($remitOrder == null) {
  171. return false;
  172. }
  173. unset($data['token']);
  174. unset($data['remitNo']);
  175. $handler = BaseRemitHandler::getRemitHandlerByPayType($remitOrder['pay_type']);
  176. $success = false;
  177. if ($handler != null) {
  178. $success = $handler->handleNotify($data);
  179. $this->_outNotifyResult = $handler->outNotify($success);
  180. }
  181. return $success;
  182. }
  183. /**
  184. * @return string
  185. */
  186. public function getOutNotifyResult()
  187. {
  188. return $this->_outNotifyResult;
  189. }
  190. }