PaymentService.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. /**
  3. * 支付方式相关.
  4. *
  5. * @author jim <jim458734573@gmail.com>
  6. * @date 2020-01-22 22:37:21
  7. */
  8. declare(strict_types=1);
  9. namespace App\Repositories\Service;
  10. use App\Exception\ApiException;
  11. use App\Jobs\AddPaymentResultJob;
  12. use App\Model\PaymentModel;
  13. use App\Model\PaymentTypeModel;
  14. use App\Model\VipOrderModel;
  15. use App\Repositories\CoinsRepository;
  16. use App\Repositories\OrderRepository;
  17. use App\Repositories\Service\Payment\PaymentInterface;
  18. use App\Repositories\Utils\M3u8CacheRepository;
  19. use App\Repositories\VipRepository;
  20. use Modules\Api\Services\AuthService;
  21. use Psr\SimpleCache\CacheInterface;
  22. class PaymentService
  23. {
  24. /**
  25. * 获取支付方式信息
  26. * @return mixed
  27. */
  28. public function getAllPayments($id = 0)
  29. {
  30. $key = 'paymentType';
  31. $payments = make(CacheInterface::class)->get($key);
  32. if (empty($payments)) {
  33. $res = make(CommonService::class)->httpPost(env('PAY_CENTER_URL') . '/api/get/payment', ['data' => ['merchant_code' => env('PAY_CENTER_MERCHANT_CODE'), 'key' => env('PAY_CENTER_KEY')]]);
  34. if (empty($res)) {
  35. payLogger(__CLASS__, '获取支付列表失败'. $res);
  36. return [];
  37. }
  38. $res = json_decode($res, true);
  39. if (empty($res) || empty($res['data'])) {
  40. $this->_lastError = '请求异常!';
  41. payLogger(__CLASS__, '支付列表解码异常或者没有返回通道');
  42. return [];
  43. }
  44. $payments = $res['data'];
  45. make(CacheInterface::class)->set($key, $payments);
  46. }
  47. return $payments;
  48. }
  49. /**
  50. * @return bool
  51. */
  52. public function delPaymentCache()
  53. {
  54. make(CacheInterface::class)->delete('payment');
  55. return true;
  56. }
  57. /**
  58. * @return bool
  59. */
  60. public function delPaymentTypeCache()
  61. {
  62. make(CacheInterface::class)->delete('paymentType');
  63. return true;
  64. }
  65. /**
  66. * 根据金额获取可用的支付网关
  67. * @param float $amount
  68. * @return array
  69. */
  70. public function getPayGatewayByAmount($amount = 0.0, $deviceType = '', $paymentList = [])
  71. {
  72. $result = array();
  73. if ($paymentList) {
  74. $payGetway = ['支付宝', '微信', '银行卡', '余额', '虚拟币'];
  75. foreach ($paymentList as $item) {
  76. // 排除(设备 状态)
  77. if (!empty($item['belong_device']) && ($deviceType != $item['belong_device'])) {
  78. continue;
  79. }
  80. $tempKey = $item['pay_type'] - 1;
  81. // 金额范围
  82. if ($amount > 0) {
  83. if ($item['limit_type'] == 2) {
  84. $tempArr = explode('-', $item['limit']);
  85. if ($amount < $tempArr[0] || $amount > $tempArr[1]) {
  86. continue;
  87. }
  88. } else {
  89. $tempArr = explode(',', $item['limit']);
  90. if (!in_array($amount, $tempArr)) {
  91. continue;
  92. }
  93. }
  94. }
  95. $imgUrl = 'f2|/' . env('STATIC_DIR_NAME', 'doukui')
  96. . '/pay_type/' . $item['pay_type'] . '_144x144.ceb';
  97. // 选项卡
  98. if (empty($result[$tempKey])) {
  99. $result[$tempKey]['name'] = $payGetway[$tempKey];
  100. $result[$tempKey]['img'] = M3u8CacheRepository::getImageUrl($imgUrl);
  101. $result[$tempKey]['pay_type'] = $item['pay_type'];
  102. }
  103. //解析数据
  104. $result[$tempKey]['pay_list'][] = [
  105. 'id' => $item['id'],
  106. 'name' => $item['name'],
  107. 'img' => M3u8CacheRepository::getImageUrl($imgUrl),
  108. 'pay_type' => $item['pay_type'],
  109. ];
  110. }
  111. if ($result) {
  112. ksort($result);
  113. $result = array_values($result);
  114. }
  115. }
  116. return $result;
  117. }
  118. /**
  119. * 根据金额获取可用的支付网关(大鲨鱼版)
  120. * @param array $amount
  121. * @return array
  122. */
  123. public function getGatewayByAmount($amount)
  124. {
  125. $url = 'https://umio.zjcthbkj.com/api/shark/getPayType';
  126. $params = [
  127. 'mercId' => 10070,
  128. 'money' => $amount,
  129. 'time' => (string)(int)(microtime(true) * 1000),
  130. ];
  131. $params['sign'] = md5($params['mercId'] . implode(',', $params['money']) . '442811313797cef2cc857967fdb5f1a9');
  132. $result = make(CommonService::class)->httpPost($url, $params);
  133. $result = json_decode($result, true);
  134. //记录mongo日志
  135. make(QueueService::class)->addPaymentResultJob($result);
  136. $ways = [];
  137. if (isset($result['msg'])) {
  138. $ways = $result['msg'];
  139. }
  140. $key = [];
  141. foreach ($ways as $w) {
  142. $t = [];
  143. $w['money'] = floatval($w['money']);
  144. foreach ($w['types'] as $k => $v) {
  145. $type = substr(strval($v['payMent']), -1);
  146. $t[$k]['id'] = $v['type'] . ':' . $type;
  147. $t[$k]['name'] = $v['name'];
  148. $t[$k]['img'] = 'f2|/' . env('STATIC_DIR_NAME', 'doukui') . '/pay_type/' . $type . '_144x144.ceb';
  149. }
  150. $key[round($w['money']) . ''] = $t;
  151. }
  152. return $key;
  153. }
  154. /**
  155. * 根据支付类型和金额匹配具体支付方式
  156. * @param $payId
  157. * @param $amount
  158. * @return \Hyperf\Database\Model\Builder|\Hyperf\Database\Model\Model|\Hyperf\Database\Query\Builder|object|null
  159. */
  160. public function getPaymentByAmount($payId, $amount)
  161. {
  162. $result = null;
  163. if ($amount <= 0) {
  164. return $result;
  165. }
  166. //获取合适的支付通道
  167. $result = make(OrderRepository::class)->getPayChannel($payId);
  168. //根据金额和权重匹配对应的支付渠道
  169. // $result = $this->weightsAmountChannel($paymentData, $amount);
  170. return $result;
  171. }
  172. /**
  173. * 根据金额和权重匹配通道
  174. *
  175. * @param $PaymentData
  176. * @param $amount
  177. * @return mixed
  178. */
  179. private function weightsAmountChannel($PaymentData, $amount)
  180. {
  181. $channel = [];
  182. $amount = (int)$amount;
  183. foreach ($PaymentData as $item) {
  184. //获取合适范围内的通道
  185. switch ($item->limit_type) {
  186. case 1: //固定金额
  187. $limitMap = explode(',', $item->limit);
  188. if (in_array($amount, $limitMap)) {
  189. $channel[] = $item;
  190. }
  191. break;
  192. case 2: //范围金额
  193. $limitMap = explode('-', $item->limit);
  194. if ($amount >= $limitMap[0] && $amount < $limitMap[1]) {
  195. $channel[] = $item;
  196. }
  197. break;
  198. }
  199. }
  200. $res = [];
  201. if (!empty($channel)) {
  202. //通过权重匹配通道
  203. $res = countWeight($channel);
  204. }
  205. return $res;
  206. }
  207. /**
  208. * 请求支付中心获取支付网关
  209. * @param object $order
  210. * @return string
  211. */
  212. public function getGateway($order, $payId)
  213. {
  214. $payData = array(
  215. 'orderSn' => $order->order_sn,
  216. 'orderId' => $order->id,
  217. 'money' => $order->real_amount,
  218. 'type' => $order->order_type,
  219. 'payId' => $payId
  220. );
  221. $result = PaymentInterface::factory('Paycenter')->createPayLink($payData);
  222. if ($result) {
  223. return $result;
  224. }
  225. throw new ApiException('亲,换个支付方式试试呢?');
  226. }
  227. /**
  228. * 支付异步通知
  229. * @param int $orderId
  230. * @param string $orderType
  231. * @param string $gateway
  232. */
  233. public function notify($orderId, $orderType)
  234. {
  235. logger(json_encode(request()->all()) . '发送回调信息!');
  236. if (!$orderId || !$orderType) {
  237. throw new ApiException('参数错误');
  238. }
  239. //我方订单号
  240. $orderSn = '';
  241. //交易单号(三方单号)
  242. $tradeNo = '';
  243. //订单金额
  244. $money = '';
  245. $result = PaymentInterface::factory('Paycenter')->notify($orderSn, $tradeNo, $money);
  246. if ($result) {
  247. if ($orderType == 1) { //vip
  248. $result = make(VipRepository::class)
  249. ->doBuy($orderId, $tradeNo, $money, $orderType);
  250. } else { //金币
  251. $result = make(CoinsRepository::class)->doBuy($orderId, $tradeNo, $money);
  252. }
  253. }
  254. if ($result) {
  255. return 'SUCCESS';
  256. }
  257. return 'nook';
  258. }
  259. }