PayForm.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <?php
  2. namespace common\forms;
  3. use Yii;
  4. use yii\base\Model;
  5. use yii\helpers\Json;
  6. use yii\web\UnprocessableEntityHttpException;
  7. use common\enums\PayTypeEnum;
  8. use common\models\extend\PayLog;
  9. use common\interfaces\PayHandler;
  10. use common\helpers\ArrayHelper;
  11. use common\helpers\StringHelper;
  12. use common\enums\PayTradeTypeEnum;
  13. /**
  14. * 支付校验
  15. *
  16. * Class PayForm
  17. * @package common\forms
  18. * @author jianyan74 <751393839@qq.com>
  19. */
  20. class PayForm extends PayLog
  21. {
  22. public $data;
  23. /**
  24. * 授权码
  25. *
  26. * @var
  27. */
  28. public $code;
  29. /**
  30. * @var
  31. */
  32. private $_handlers;
  33. /**
  34. * @return array
  35. */
  36. public function rules()
  37. {
  38. return [
  39. [['order_group', 'pay_type', 'data', 'trade_type', 'member_id'], 'required'],
  40. [['pay_type'], 'in', 'range' => PayTypeEnum::getKeys()],
  41. [['notify_url', 'return_url', 'code', 'auth_code', 'openid'], 'string'],
  42. [['data'], 'safe'],
  43. [['trade_type'], 'verifyTradeType'],
  44. ];
  45. }
  46. /**
  47. * 校验交易类型
  48. *
  49. * @param $attribute
  50. * @throws UnprocessableEntityHttpException
  51. * @throws \EasyWeChat\Kernel\Exceptions\HttpException
  52. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  53. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  54. * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
  55. * @throws \Psr\SimpleCache\InvalidArgumentException
  56. */
  57. public function verifyTradeType($attribute)
  58. {
  59. try {
  60. $this->data = Json::decode($this->data);
  61. } catch (\Exception $e) {
  62. $this->addError($attribute, $e->getMessage());
  63. return;
  64. }
  65. switch ($this->pay_type) {
  66. case PayTypeEnum::WECHAT :
  67. if (!in_array($this->trade_type, array_keys(PayTradeTypeEnum::getWechatMap()))) {
  68. $this->addError($attribute, '微信交易类型不符');
  69. return;
  70. }
  71. // 直接通过授权码进行支付
  72. if ($this->code) {
  73. if ($this->trade_type == PayTradeTypeEnum::WECHAT_MINI) {
  74. $auth = Yii::$app->wechat->miniProgram->auth->session($this->code);
  75. Yii::$app->services->base->getWechatError($auth);
  76. $this->openid = $auth['openid'];
  77. }
  78. if ($this->trade_type == PayTradeTypeEnum::WECHAT_MP) {
  79. $user = Yii::$app->wechat->app->oauth->userFromCode($this->code);
  80. $this->openid = $user->getId();
  81. }
  82. }
  83. if ($this->trade_type == PayTradeTypeEnum::WECHAT_POS && !$this->auth_code) {
  84. $this->addError($attribute, '找不到付款码');
  85. }
  86. break;
  87. case PayTypeEnum::ALI :
  88. if (!in_array($this->trade_type, array_keys(PayTradeTypeEnum::getAliMap()))) {
  89. $this->addError($attribute, '支付宝交易类型不符');
  90. }
  91. // 面对面收款
  92. if ($this->trade_type == PayTradeTypeEnum::ALI_POS && !$this->auth_code) {
  93. $this->addError($attribute, '找不到付款码');
  94. }
  95. break;
  96. case PayTypeEnum::UNION :
  97. if (!in_array($this->trade_type, array_keys(PayTradeTypeEnum::getUnionMap()))) {
  98. $this->addError($attribute, '银联交易类型不符');
  99. }
  100. break;
  101. // 海外信用卡 stripe
  102. case PayTypeEnum::STRIPE :
  103. if (!in_array($this->trade_type, ['cards', 'card'])) {
  104. $this->addError($attribute, 'Strip交易类型不符');
  105. }
  106. break;
  107. }
  108. }
  109. /**
  110. * 执行类
  111. *
  112. * @param array $handlers
  113. */
  114. public function setHandlers(array $handlers)
  115. {
  116. $this->_handlers = $handlers;
  117. }
  118. /**
  119. * @return array|\EasyWeChat\Kernel\Support\Collection|mixed|object|\Psr\Http\Message\ResponseInterface|string
  120. * @throws UnprocessableEntityHttpException
  121. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  122. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  123. * @throws \GuzzleHttp\Exception\GuzzleException
  124. * @throws \yii\base\InvalidConfigException
  125. */
  126. public function getConfig()
  127. {
  128. if (!isset($this->_handlers[$this->order_group])) {
  129. throw new UnprocessableEntityHttpException('找不到订单组别');
  130. }
  131. /** @var Model|PayHandler $model */
  132. $model = new $this->_handlers[$this->order_group]();
  133. if (!($model instanceof PayHandler)) {
  134. throw new UnprocessableEntityHttpException('无效的订单组别');
  135. }
  136. $model->attributes = $this->data;
  137. if (!$model->validate()) {
  138. throw new UnprocessableEntityHttpException(Yii::$app->services->base->analysisErr($model->getFirstErrors()));
  139. }
  140. // 系统内支付
  141. if (in_array($this->pay_type, [PayTypeEnum::USER_MONEY, PayTypeEnum::PAY_ON_DELIVERY])) {
  142. return [];
  143. }
  144. $log = new PayLog();
  145. if ($model->isQueryOrderSn() == true && ($history = Yii::$app->services->extendPay->findByOrderSn($model->getOrderSn()))) {
  146. $log = $history;
  147. }
  148. $log->out_trade_no = $model->getOutTradeNo();
  149. if (empty($log->out_trade_no)) {
  150. $log->out_trade_no = date('YmdHis') . StringHelper::random(8, true);
  151. }
  152. $log->attributes = ArrayHelper::toArray($this);
  153. $log->order_sn = $model->getOrderSn();
  154. $log->body = $model->getBody() . '-' . $log->order_sn;
  155. $log->detail = $model->getDetails();
  156. $log->merchant_id = $model->getMerchantId();
  157. $log->total_fee = $model->getTotalFee();
  158. $log->pay_fee = $log->total_fee;
  159. if ($log->total_fee <= 0) {
  160. throw new UnprocessableEntityHttpException('请使用余额支付');
  161. }
  162. if (!$log->save()) {
  163. throw new UnprocessableEntityHttpException(Yii::$app->services->base->analysisErr($log->getFirstErrors()));
  164. }
  165. return $this->payConfig($log);
  166. }
  167. /**
  168. * @return array|\EasyWeChat\Kernel\Support\Collection|mixed|object|\Psr\Http\Message\ResponseInterface|string
  169. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  170. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  171. * @throws \GuzzleHttp\Exception\GuzzleException
  172. * @throws \yii\base\InvalidConfigException
  173. */
  174. protected function payConfig(PayLog $log)
  175. {
  176. switch ($log->pay_type) {
  177. case PayTypeEnum::WECHAT :
  178. return Yii::$app->services->extendPay->wechat($log);
  179. break;
  180. case PayTypeEnum::ALI :
  181. return Yii::$app->services->extendPay->alipay($log);
  182. break;
  183. case PayTypeEnum::UNION :
  184. return Yii::$app->services->extendPay->unipay($log);
  185. break;
  186. case PayTypeEnum::BYTE_DANCE :
  187. return Yii::$app->services->extendPay->byteDance($log);
  188. break;
  189. case PayTypeEnum::STRIPE :
  190. return Yii::$app->services->extendPay->stripe($log);
  191. break;
  192. }
  193. }
  194. }
粤ICP备19079148号