PayService.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. namespace app\common\Service\Pay;
  3. use think\Log;
  4. use think\Exception;
  5. use app\common\Enum\ChannelEnum;
  6. use app\common\Service\Pay\Provider\Base;
  7. use app\common\exception\BusinessException;
  8. use app\common\model\pay\Index as PayModel;
  9. /**
  10. * 支付服务类 - 工厂模式
  11. * 配合 yansongda 支付库
  12. */
  13. class PayService
  14. {
  15. protected $payment;
  16. protected $platform;
  17. protected $channel;
  18. /**
  19. * 构造函数
  20. * @param string $payment 支付方式 (wechat|alipay)
  21. * @param string $platform 平台标识 (可选)
  22. * @param string $channel 渠道标识 (可选)
  23. */
  24. public function __construct($payment, $platform = null, $channel = null)
  25. {
  26. $this->payment = $payment;
  27. $this->platform = $platform ?: $this->getPlatformFromRequest();
  28. $this->channel = $channel ?: $this->getChannelFromRequest();
  29. // 验证平台参数
  30. if (!$this->platform) {
  31. throw new BusinessException('缺少用户端平台参数');
  32. }
  33. // 验证支付方式
  34. if (!in_array($payment, ['wechat', 'alipay','douyin'])) {
  35. throw new BusinessException('不支持的支付方式: ' . $payment);
  36. }
  37. }
  38. /**
  39. * 获取支付提供器
  40. * @param string $payment 支付方式
  41. * @return Base
  42. * @throws Exception
  43. */
  44. public function provider($payment = null)
  45. {
  46. try {
  47. $payment = $payment ?: $this->payment;
  48. $className = "\\app\\common\\Service\\Pay\\Provider\\" . ucfirst(strtolower($payment));
  49. if (!class_exists($className)) {
  50. throw new Exception("支付提供器不存在: {$className}");
  51. }
  52. return new $className($this, $this->platform, $this->channel);
  53. } catch (\Exception $e) {
  54. Log::error('PayService provider error: ' . $e->getMessage());
  55. throw new Exception('支付类型不支持: ' . $payment);
  56. }
  57. }
  58. /**
  59. * 获取当前平台
  60. * @return string
  61. */
  62. public function getPlatform()
  63. {
  64. return $this->platform;
  65. }
  66. /**
  67. * 获取当前渠道
  68. * @return string
  69. */
  70. public function getChannel()
  71. {
  72. return $this->channel;
  73. }
  74. /**
  75. * 获取当前支付方式
  76. * @return string
  77. */
  78. public function getPayment()
  79. {
  80. return $this->payment;
  81. }
  82. /**
  83. * 从请求中获取平台参数
  84. * @return string|null
  85. */
  86. protected function getPlatformFromRequest()
  87. {
  88. $request = request();
  89. return $request->header('platform') ?: $request->param('platform');
  90. }
  91. /**
  92. * 从请求中获取渠道参数
  93. * @return string|null
  94. */
  95. protected function getChannelFromRequest()
  96. {
  97. $request = request();
  98. $channel = $request->header('channel') ?: $request->param('channel');
  99. // 如果没有明确的渠道参数,尝试从平台推断
  100. if (!$channel && $this->platform) {
  101. $channel = $this->inferChannelFromPlatform($this->platform);
  102. }
  103. return $channel;
  104. }
  105. /**
  106. * 从平台推断渠道
  107. * @param string $platform
  108. * @return string|null
  109. */
  110. protected function inferChannelFromPlatform($platform)
  111. {
  112. $platformToChannel = [
  113. 'WechatOfficialAccount' => ChannelEnum::CHANNEL_WECHAT_OFFICIAL_ACCOUNT,
  114. 'WechatMiniProgram' => ChannelEnum::CHANNEL_WECHAT_MINI_PROGRAM,
  115. 'H5' => ChannelEnum::CHANNEL_H5,
  116. 'App' => ChannelEnum::CHANNEL_ANDROID_APP, // 默认Android,可根据具体情况调整
  117. 'PC' => ChannelEnum::CHANNEL_PC,
  118. ];
  119. return $platformToChannel[$platform] ?? null;
  120. }
  121. /**
  122. * 验证支付环境
  123. * @param string $payment 支付方式
  124. * @param string $channel 渠道
  125. * @return bool
  126. * @throws Exception
  127. */
  128. public function validatePaymentEnvironment($payment, $channel = null)
  129. {
  130. $channel = $channel ?: $this->channel;
  131. if (!$channel) {
  132. return true; // 如果没有渠道信息,跳过验证
  133. }
  134. // 微信支付环境验证
  135. if ($payment === 'wechat') {
  136. if (!ChannelEnum::isWechatChannel($channel) && $channel !== ChannelEnum::CHANNEL_H5) {
  137. throw new BusinessException('当前渠道不支持微信支付');
  138. }
  139. }
  140. // 支付功能验证
  141. if (!ChannelEnum::channelSupportsFeature($channel, 'payment')) {
  142. throw new BusinessException('当前渠道不支持支付功能');
  143. }
  144. return true;
  145. }
  146. /**
  147. * 魔术方法,代理到支付提供器
  148. * @param string $funcname
  149. * @param array $arguments
  150. * @return mixed
  151. */
  152. public function __call($funcname, $arguments)
  153. {
  154. return $this->provider()->{$funcname}(...$arguments);
  155. }
  156. /**
  157. * 获取支付信息
  158. * @param string $orderId
  159. * @return array
  160. */
  161. public static function getPayInfo($orderId = 0)
  162. {
  163. $payInfo = PayModel::where('order_id', $orderId)->select();
  164. return $payInfo;
  165. }
  166. }