IntegralForm.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <?php
  2. /**
  3. * IntegralForm.php
  4. * 积分充值模型
  5. * Created on 2024/12/2 下午4:24
  6. * @author: hankaige
  7. */
  8. namespace app\modules\client\models\v1\cashier;
  9. use app\constants\OptionSetting;
  10. use app\models\AccountLog;
  11. use app\models\CashierActionLog;
  12. use app\models\IntegralRechargeOrder;
  13. use app\models\Option;
  14. use app\models\User;
  15. use app\utils\OrderNo;
  16. use app\utils\Wechat\WechatNewPay;
  17. use app\utils\Wechat\WechatPay;
  18. use yii\base\Model;
  19. use yii\db\Exception;
  20. class IntegralForm extends Model
  21. {
  22. public $store_id;
  23. public $integral;
  24. public $pay_price;
  25. public $pay_type;
  26. public $user_id;
  27. public $order_no;
  28. public $pay_code;
  29. // 支付方式
  30. const WECHAT_PAY = 1;
  31. const CASH_PAY = 3;
  32. const INTEGRAL_SUBMIT = 'integral_submit';
  33. const INTEGRAL_PAY = 'integral_pay';
  34. public function rules(): array
  35. {
  36. return [
  37. [['store_id', 'user_id'], 'required', 'on' => [self::INTEGRAL_SUBMIT, self::INTEGRAL_PAY]],
  38. ['pay_price', 'number', 'on' => [self::INTEGRAL_SUBMIT]],
  39. [['pay_price', 'pay_type', 'integral'], 'required', 'on' => [self::INTEGRAL_SUBMIT]],
  40. [['order_no', 'pay_code'], 'required', 'on' => [self::INTEGRAL_PAY]],
  41. [['store_id', 'integral', 'user_id', 'pay_type'], 'integer', 'on' => [self::INTEGRAL_SUBMIT]],
  42. [['order_no', 'pay_code'], 'string', 'on' => [self::INTEGRAL_PAY]]
  43. ];
  44. }
  45. public function attributeLabels(): array
  46. {
  47. return [
  48. 'store_id' => '商城ID',
  49. 'user_id' => '用户ID',
  50. 'integral' => '购买积分',
  51. 'order_no' => '积分购买订单',
  52. 'pay_price' => '积分充值支付金额',
  53. 'pay_type' => '支付方式',
  54. 'pay_code' => '支付二维码信息'
  55. ];
  56. }
  57. /**
  58. * 创建积分充值订单
  59. * @return array
  60. * @author: hankaige
  61. * @Time: 2024/12/3 上午10:45
  62. */
  63. public function submitIntegral(): array
  64. {
  65. try {
  66. if (!$this->validate()) {
  67. return ['code' => 1, 'msg' => $this->getErrorSummary(FALSE)[0]];
  68. }
  69. $user = User::findOne($this->user_id);
  70. if (empty($user)) {
  71. throw new Exception('用户不存在');
  72. }
  73. $setting = Option::get(OptionSetting::STORE_INTEGRAL, $this->store_id, 'gift', Option::get(OptionSetting::STORE_INTEGRAL, $this->store_id, 'store')['value']);
  74. // 计算积分支付金额
  75. $realPayPrice = bcdiv($this->integral, $setting['value'], 2);
  76. if ($realPayPrice !== sprintf('%.2f', $this->pay_price)) {
  77. throw new Exception('实际支付金额不一致');
  78. }
  79. $order = new IntegralRechargeOrder();
  80. $order->store_id = $this->store_id;
  81. $order->user_id = $this->user_id;
  82. $order->order_no = OrderNo::getOrderNo(OrderNo::INTEGRAL_RECHARGE);
  83. $order->pay_price = $realPayPrice;
  84. $order->is_pay = 0;
  85. $order->pay_type = $this->pay_type;
  86. $order->is_delete = 0;
  87. $order->created_at = time();
  88. $order->is_cashier = 1;
  89. $order->send_integral = $this->integral;
  90. $order->create_user_id = get_user_id();
  91. if (!$order->save()) {
  92. throw new Exception('订单创建失败');
  93. }
  94. if ($this->pay_type == self::CASH_PAY) {
  95. $this->payConfirm($order, $user);
  96. return [
  97. 'code' => 0,
  98. 'msg' => '订单创建成功',
  99. 'data' => [
  100. 'need_pay' => 0,
  101. 'order_no' => $order->order_no
  102. ]
  103. ];
  104. } else {
  105. return [
  106. 'code' => 0,
  107. 'msg' => '订单创建成功',
  108. 'data' => [
  109. 'need_pay' => 1,
  110. 'order_no' => $order->order_no
  111. ]
  112. ];
  113. }
  114. } catch (\Exception $e) {
  115. return ['code' => 1, 'msg' => $e->getMessage()];
  116. }
  117. }
  118. /**
  119. * 充值积分订单微信支付
  120. * @return array
  121. * @author: hankaige
  122. * @Time: 2024/12/3 上午10:45
  123. */
  124. public function pay(): array
  125. {
  126. try {
  127. if (!$this->validate()) {
  128. throw new \Exception($this->getErrorSummary(FALSE)[0]);
  129. }
  130. $order = IntegralRechargeOrder::find()->where(['order_no' => $this->order_no, 'is_pay' => IntegralRechargeOrder::NOT_PAY, 'is_delete' => IntegralRechargeOrder::NOT_DELETE])->one();
  131. if (empty($order)) {
  132. throw new \Exception('订单不存在');
  133. }
  134. $user = User::findOne($order->user_id);
  135. if ($order->pay_type == self::WECHAT_PAY) {
  136. debug_log(is_profit_pay(), 'cashier.log');
  137. if (is_profit_pay()) {
  138. $result = WechatNewPay::micropay($order, OrderNo::ORDER_MALL, '积分充值', $order->pay_price, 0, $this->pay_code);
  139. } else {
  140. $result = WechatPay::micropay($order, OrderNo::ORDER_MALL, '积分充值', $order->pay_price, 0, $this->pay_code);
  141. }
  142. if ($result['return_code'] == 'SUCCESS') {
  143. if ($result['result_code'] === 'FAIL') {
  144. // 如果返回结果不是 等待用户输入密码 则直接返回
  145. if ($result['err_code'] == 'USERPAYING') {
  146. $result = $this->checkOrderPay($order, 0);
  147. } else {
  148. return [
  149. 'code' => 1,
  150. 'msg' => '微信支付参数错误',
  151. 'data' => $result
  152. ];
  153. }
  154. }
  155. if ($result['result_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS' && $result['trade_type'] == 'MICROPAY') {
  156. $t = \Yii::$app->db->beginTransaction();
  157. $order->transaction_id = $result['transaction_id'];
  158. $order->is_pay = 1;
  159. $order->pay_time = time();
  160. if (!$order->save()) {
  161. $t->rollBack();
  162. throw new \Exception('订单状态更新失败');
  163. }
  164. self::payConfirm($user, $order);
  165. $t->commit();
  166. return ['code' => 0, 'msg' => '余额充值成功'];
  167. }
  168. return [
  169. 'code' => 1,
  170. 'msg' => '微信支付错误',
  171. 'data' => $result
  172. ];
  173. } else {
  174. throw new \Exception('微信支付失败' . $result['return_msg']);
  175. }
  176. } else {
  177. throw new \Exception('暂不支持该支付方式');
  178. }
  179. } catch (\Exception $e) {
  180. return ['code' => 1, 'msg' => $e->getMessage()];
  181. }
  182. }
  183. /**
  184. * 校验扫码付款结果
  185. * @param $order
  186. * @param $num
  187. * @return array|string[]|void
  188. * @author: hankaige
  189. * @Time: 2024/12/3 上午10:46
  190. */
  191. public function checkOrderPay($order, $num = 0)
  192. {
  193. sleep(5);
  194. if ($num >= 45) {
  195. return ['result_code' => 'FAIL', 'data' => '支付超时'];
  196. }
  197. $num += 5;
  198. if (is_profit_pay()) {
  199. $result = WechatNewPay::orderQuery($order);
  200. } else {
  201. $result = WechatPay::orderQuery($order);
  202. }
  203. if ($result['return_code'] == 'SUCCESS') {
  204. if ($result['trade_state'] == 'USERPAYING') {
  205. return $this->checkOrderPay($order, $num);
  206. } else {
  207. return $result;
  208. }
  209. }
  210. }
  211. /**
  212. * 支付成功后操作
  213. * @param $user
  214. * @param $order
  215. * @author: hankaige
  216. * @Time: 2024/12/3 上午10:46
  217. */
  218. private static function payConfirm($user, $order): void
  219. {
  220. try {
  221. $t = \Yii::$app->db->beginTransaction();
  222. $old_integral = $user->integral;
  223. $user->integral += $order->send_integral;
  224. $user->total_integral += $order->send_integral;
  225. if (!$user->save()) {
  226. $t->rollBack();
  227. return;
  228. }
  229. // 添加积分变动记录
  230. $log = new AccountLog();
  231. $log->store_id = get_store_id();
  232. $log->user_id = $user->id;
  233. $log->type = AccountLog::TYPE_INTEGRAL;
  234. $log->log_type = AccountLog::LOG_TYPE_INCOME;
  235. $log->amount = $order->send_integral;
  236. $log->desc = "充值积分, 订单号:{$order->order_no}";
  237. $log->before = $old_integral;
  238. $log->after = $user->integral;
  239. $log->operator = 'system';
  240. $log->operator_id = 0;
  241. $log->operator_type = AccountLog::TYPE_OPERATOR_NORMAL;
  242. $log->created_at = time();
  243. $log->order_id = $order->id;
  244. $log->order_type = AccountLog::TYPE_PLATFORM_ORDER;
  245. $log->save();
  246. // 生成操作记录
  247. $user = User::findOne($order->user_id);
  248. CashierActionLog::setLog($order->store_id,get_user_id(),CashierActionLog::RECHARGE_INTEGRAL,'给'.$user->nickname.'用户充值积分');
  249. $t->commit();
  250. return;
  251. } catch (\Exception $e) {
  252. \Yii::warning('积分充值失败' . $e->getMessage());
  253. }
  254. }
  255. }