Pay.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * Author: 芸众商城 www.yunzshop.com
  5. * Date: 2017/3/17
  6. * Time: 上午9:47
  7. */
  8. namespace app\common\services;
  9. use app\common\models\PayAccessLog;
  10. use app\common\models\PayLog;
  11. use app\common\models\PayOrder;
  12. use app\common\models\PayWithdrawOrder;
  13. use app\common\models\PayRefundOrder;
  14. use app\common\models\PayRequestDataLog;
  15. use app\common\models\PayResponseDataLog;
  16. abstract class Pay
  17. {
  18. /**
  19. * 无效的Uniacid长度
  20. */
  21. const INVALID_UNIACID_LENGTH = -1;
  22. /**
  23. * 订单支付
  24. */
  25. const PAY_TYPE_COST = 1;
  26. /**
  27. * 充值
  28. */
  29. const PAY_TYPE_RECHARGE = 2;
  30. /**
  31. * 退款
  32. */
  33. const PAY_TYPE_REFUND = 3;
  34. /**
  35. * 提现
  36. */
  37. const PAY_TYPE_WITHDRAW = 4;
  38. /**
  39. * 微信支付
  40. */
  41. const PAY_MODE_WECHAT = 1;
  42. /**
  43. * 支付宝支付
  44. */
  45. const PAY_MODE_ALIPAY = 2;
  46. /**
  47. * 余额支付
  48. */
  49. const PAY_MODE_CREDIT = 3;
  50. /**
  51. * 微信app支付
  52. */
  53. const PAY_MODE_APPWECHAT = 9;
  54. /**
  55. * 支付宝app支付
  56. */
  57. const PAY_MODE_APPALIPAY = 10;
  58. /**
  59. * 货到付款
  60. */
  61. const PAY_MODE_CASH = 4;
  62. /**
  63. * 后台付款
  64. */
  65. const PAY_MODE_BACKEND = 5;
  66. /**
  67. * 云收银微信支付
  68. */
  69. const PAY_MODE_CLOUDWECHAT = 6;
  70. /**
  71. * 云收银微信支付
  72. */
  73. const PAY_MODE_CLOUDALI = 7;
  74. /**
  75. * 未付款
  76. */
  77. const ORDER_STATUS_NON = 0;
  78. /**
  79. * 待付款
  80. */
  81. const ORDER_STATUS_WAITPAY = 1;
  82. /**
  83. * 完成
  84. */
  85. const ORDER_STATUS_COMPLETE = 2;
  86. /**
  87. * 请求的参数
  88. *
  89. * @var array
  90. */
  91. protected $parameters;
  92. /**
  93. * 密钥
  94. *
  95. * @var string
  96. */
  97. protected $key;
  98. /**
  99. * 请求接口
  100. *
  101. * @var string
  102. */
  103. protected $gateUrl;
  104. /**
  105. * url请求地址
  106. *
  107. * @var string
  108. */
  109. protected $url;
  110. /**
  111. * url请求方式
  112. *
  113. * @var string
  114. */
  115. protected $method;
  116. /**
  117. * 访问IP地址
  118. *
  119. * @var string
  120. */
  121. protected $ip;
  122. /**
  123. * 订单支付/充值
  124. *
  125. * @param $subject 名称
  126. * @param $body 详情
  127. * @param $amount 金额
  128. * @param $order_no 订单号
  129. * @param $extra 附加数据
  130. * @return mixed
  131. */
  132. abstract function doPay($data);
  133. /**
  134. * 退款
  135. *
  136. * @param $out_trade_no 订单号
  137. * @param $totalmoney 订单总金额
  138. * @param $refundmoney 退款金额
  139. * @return mixed
  140. */
  141. abstract function doRefund($out_trade_no, $totalmoney, $refundmoney);
  142. /**
  143. * 提现
  144. *
  145. * @param $member_id 提现者用户ID
  146. * @param $out_trade_no 提现批次单号
  147. * @param $money 提现金额
  148. * @param $desc 提现说明
  149. * @param $type 只针对微信 1-企业支付(钱包) 2-红包
  150. * @return mixed
  151. */
  152. abstract function doWithdraw($member_id, $out_trade_no, $money, $desc, $type);
  153. /**
  154. * 构造签名
  155. *
  156. * @return mixed
  157. */
  158. abstract function buildRequestSign();
  159. /**
  160. * 获取访问URL
  161. *
  162. * @return string
  163. */
  164. private static function getHttpURL()
  165. {
  166. $url = \URL::current();
  167. $url .= '?' . $_SERVER['QUERY_STRING'];
  168. return $url;
  169. }
  170. /**
  171. * 获取HTTP请求方式
  172. *
  173. * @return mixed
  174. */
  175. private static function getHttpMethod()
  176. {
  177. return $_SERVER['REQUEST_METHOD'] ?: "CLI";
  178. }
  179. /**
  180. * 获取客户端IP
  181. *
  182. * @return string
  183. */
  184. protected static function getClientIP()
  185. {
  186. return \Request::getClientIp();
  187. }
  188. /**
  189. * 获取入口地址,不包含参数值
  190. *
  191. * @return string
  192. */
  193. protected function getGateURL() {
  194. return $this->gateUrl;
  195. }
  196. /**
  197. * 设置入口地址,不包含参数值
  198. *
  199. * @param $gateUrl
  200. */
  201. protected function setGateURL($gateUrl) {
  202. $this->gateUrl = $gateUrl;
  203. }
  204. /**
  205. * 获取参数值
  206. *
  207. * @param $parameter
  208. * @return mixed
  209. */
  210. protected function getParameter($parameter) {
  211. return $this->parameters[$parameter];
  212. }
  213. /**
  214. * 设置参数值
  215. *
  216. * @param $parameter
  217. * @param $parameterValue
  218. */
  219. protected function setParameter($parameter, $parameterValue) {
  220. $this->parameters[$parameter] = $parameterValue;
  221. }
  222. /**
  223. * 获取所有请求的参数
  224. *
  225. * @return array
  226. */
  227. protected function getAllParameters() {
  228. return $this->parameters;
  229. }
  230. /**
  231. * 获取密钥
  232. *
  233. * @return string
  234. */
  235. function getKey() {
  236. return $this->key;
  237. }
  238. /**
  239. * 设置密钥
  240. *
  241. * @param $key
  242. * @return void
  243. */
  244. function setKey($key) {
  245. $this->key = $key;
  246. }
  247. /**
  248. * 预下单
  249. *
  250. * @return array
  251. */
  252. protected function preOrder() {
  253. $params = ksort($this->parameters);
  254. $params = array2xml($params);
  255. $response = ihttp_request($this->getGateURL(), $params);
  256. return $response;
  257. }
  258. public function encryption() {}
  259. protected function decryption() {}
  260. protected function noticeUrl() {}
  261. protected function returnUrl() {}
  262. /**
  263. * 统一化支付失败返回数据格式
  264. * @param string $msg
  265. * @param array $result
  266. * @return array
  267. */
  268. public function fail($msg = '',$result = [])
  269. {
  270. return ['status' => 0, 'msg' => $msg, 'data' => $result];
  271. }
  272. /**
  273. * 统一化支付成功返回数据格式
  274. * @param string $msg
  275. * @param array $result
  276. * @return array
  277. */
  278. public function success($msg = '',$result = [])
  279. {
  280. return ['status' => 1, 'msg' => $msg, 'data' => $result];
  281. }
  282. /**
  283. * 支付访问日志
  284. *
  285. * @var void
  286. */
  287. public static function payAccessLog()
  288. {
  289. PayAccessLog::create([
  290. 'uniacid' => \YunShop::app()->uniacid?:0,
  291. 'member_id' => \YunShop::app()->getMemberId(),
  292. 'url' => self::getHttpURL(),
  293. 'http_method' => self::getHttpMethod(),
  294. 'ip' => self::getClientIP(),
  295. 'input' => file_get_contents('php://input'),
  296. ]);
  297. }
  298. /**
  299. * 支付日志
  300. *
  301. * @param $type
  302. * @param $third_type
  303. * @param $price
  304. * @param $operation
  305. */
  306. public static function payLog($type, $third_type, $price, $operation, $member_id)
  307. {
  308. PayLog::create([
  309. 'uniacid' => \YunShop::app()->uniacid,
  310. 'member_id' => $member_id,
  311. 'type' => $type,
  312. 'third_type' => $third_type,
  313. 'price' => $price,
  314. 'operation' => $operation,
  315. 'ip' => self::getClientIP()
  316. ]);
  317. }
  318. /**
  319. * 支付单
  320. *
  321. * @param $out_order_no 订单号
  322. * @param $status 支付单状态
  323. * @param $type 支付类型
  324. * @param $third_type 支付方式
  325. * @param $price 支付金额
  326. */
  327. public static function payOrder($out_order_no, $status, $type, $third_type, $price)
  328. {
  329. return PayOrder::create([
  330. 'uniacid' => \YunShop::app()->uniacid,
  331. 'member_id' => \YunShop::app()->getMemberId(),
  332. 'int_order_no' => self::createPayOrderNo(),
  333. 'out_order_no' => $out_order_no,
  334. 'status' => $status,
  335. 'type' => $type,
  336. 'third_type' => $third_type,
  337. 'price' => $price
  338. ]);
  339. }
  340. protected function payWithdrawOrder($out_order_no, $status, $third_type, $price)
  341. {
  342. return PayWithdrawOrder::create([
  343. 'uniacid' => \YunShop::app()->uniacid,
  344. 'member_id' => \YunShop::app()->getMemberId(),
  345. 'int_order_no' => self::createPayOrderNo(),
  346. 'out_order_no' => $out_order_no,
  347. 'status' => $status,
  348. 'type' => $third_type,
  349. 'price' => $price
  350. ]);
  351. }
  352. protected function payRefundOrder($out_order_no, $status, $third_type, $price)
  353. {
  354. return PayRefundOrder::create([
  355. 'uniacid' => \YunShop::app()->uniacid,
  356. 'member_id' => \YunShop::app()->getMemberId(),
  357. 'int_order_no' => self::createPayOrderNo(),
  358. 'out_order_no' => $out_order_no,
  359. 'status' => $status,
  360. 'type' => $third_type,
  361. 'price' => $price
  362. ]);
  363. }
  364. /**
  365. * 支付请求数据记录
  366. *
  367. * @param string $out_order_no 订单号
  368. * @param int $type 支付类型
  369. * @param string $third_type 支付方式
  370. * @param array $params 请求数据
  371. */
  372. public static function payRequestDataLog($out_order_no, $type, $third_type, $params)
  373. {
  374. PayRequestDataLog::create([
  375. 'uniacid' => \YunShop::app()->uniacid,
  376. 'out_order_no' => $out_order_no,
  377. 'type' => $type,
  378. 'third_type' => $third_type,
  379. 'params' => $params
  380. ]);
  381. }
  382. /**
  383. * 支付响应数据记录
  384. *
  385. * @param $out_order_no 订单号
  386. * @param $third_type 支付方式
  387. * @param $params 响应结果
  388. */
  389. public static function payResponseDataLog($out_order_no, $third_type, $params)
  390. {
  391. PayResponseDataLog::create([
  392. 'uniacid' => \YunShop::app()->uniacid ? : 0,
  393. 'out_order_no' => $out_order_no,
  394. 'third_type' => $third_type,
  395. 'params' => $params
  396. ]);
  397. }
  398. /**
  399. * 支付单号
  400. *
  401. * 格式:P+YYMMDD+31位流水号(数字+字母)
  402. *
  403. * @return string
  404. */
  405. private static function createPayOrderNo()
  406. {
  407. return 'P' . date('Ymd', time()) . self::generate_string(23);
  408. }
  409. /**
  410. * 创建退款/提现订单批次号
  411. *
  412. * @param $uniacid 统一公众号
  413. * @param $strleng 统一公众号长度
  414. * @return string
  415. */
  416. public static function setUniacidNo($uniacid, $strleng=5)
  417. {
  418. $part1 = date('Ymd', time());
  419. $part2 = self::generate_string();
  420. $uniacid_lenght = strlen($uniacid);
  421. if ($uniacid_lenght > $strleng) {
  422. return self::INVALID_UNIACID_LENGTH;
  423. }
  424. if ($uniacid_lenght >= 1 && $uniacid_lenght <= $strleng) {
  425. $part3 = sprintf("%0{$strleng}s", $uniacid);
  426. } else {
  427. return self::INVALID_UNIACID_LENGTH;
  428. }
  429. return $part1 . substr($part2, 0, 9) . $part3 . substr($part2, 9);
  430. }
  431. /**
  432. * 退款/提现流水号
  433. *
  434. * @param int $length
  435. * @return string
  436. */
  437. private static function generate_string ($length = 19)
  438. {
  439. $nps = "";
  440. for($i=0;$i<$length;$i++)
  441. {
  442. $nps .= chr((mt_rand(1, 36) <= 26) ? mt_rand(97, 122) : mt_rand(48, 57 ));
  443. }
  444. return $nps;
  445. }
  446. /**
  447. * 支付日志
  448. *
  449. * @param $type
  450. * @param $third_type
  451. * @param $amount
  452. * @param $operation
  453. * @param $order_no
  454. * @param $status
  455. *
  456. * @return mixed
  457. */
  458. protected function log($type, $third_type, $amount, $operation, $order_no, $status, $member_id)
  459. {
  460. //访问日志
  461. self::payAccessLog();
  462. //支付日志
  463. self::payLog($type, $third_type, $amount, $operation, $member_id);
  464. //支付单记录
  465. $model = self::payOrder($order_no, $status, $type, $third_type, $amount);
  466. return $model;
  467. }
  468. /**
  469. * 退款日志
  470. *
  471. * @param $type
  472. * @param $third_type
  473. * @param $amount
  474. * @param $operation
  475. * @param $order_no
  476. * @param $status
  477. *
  478. * @return mixed
  479. */
  480. protected function refundlog($type, $third_type, $amount, $operation, $order_no, $status, $member_id)
  481. {
  482. //访问日志
  483. self::payAccessLog();
  484. //支付日志
  485. self::payLog($type, $third_type, $amount, $operation, $member_id);
  486. //退款单记录
  487. $model = self::payRefundOrder($order_no, $status, $third_type, $amount);
  488. return $model;
  489. }
  490. /**
  491. * 提现日志
  492. *
  493. * @param $type
  494. * @param $third_type
  495. * @param $amount
  496. * @param $operation
  497. * @param $order_no
  498. * @param $status
  499. *
  500. * @return mixed
  501. */
  502. protected function withdrawlog($type, $third_type, $amount, $operation, $order_no, $status, $member_id)
  503. {
  504. //访问日志
  505. self::payAccessLog();
  506. //支付日志
  507. self::payLog($type, $third_type, $amount, $operation, $member_id);
  508. //提现单记录
  509. $model = self::payWithdrawOrder($order_no, $status, $third_type, $amount);
  510. return $model;
  511. }
  512. }