You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

298 lines
11 KiB

  1. <?php
  2. namespace addons\epay\library;
  3. use addons\unishop\model\Config;
  4. use Exception;
  5. use think\Log;
  6. use think\Response;
  7. use think\Session;
  8. use Yansongda\Pay\Gateways\Alipay\Alipay;
  9. use Yansongda\Pay\Pay;
  10. /**
  11. * 订单服务类
  12. *
  13. * @package addons\epay\library
  14. */
  15. class Service
  16. {
  17. public static function submitOrder($amount, $orderid = null, $type = null, $title = null, $notifyurl = null, $returnurl = null, $method = null)
  18. {
  19. if (!is_array($amount)) {
  20. $params = [
  21. 'amount' => $amount,
  22. 'orderid' => $orderid,
  23. 'type' => $type,
  24. 'title' => $title,
  25. 'notifyurl' => $notifyurl,
  26. 'returnurl' => $returnurl,
  27. 'method' => $method,
  28. ];
  29. } else {
  30. $params = $amount;
  31. }
  32. $type = isset($params['type']) && in_array($params['type'], ['alipay', 'wechat']) ? $params['type'] : 'wechat';
  33. $method = isset($params['method']) ? $params['method'] : 'web';
  34. $orderid = isset($params['orderid']) ? $params['orderid'] : date("YmdHis") . mt_rand(100000, 999999);
  35. $amount = isset($params['amount']) ? $params['amount'] : 1;
  36. $title = isset($params['title']) ? $params['title'] : "支付";
  37. $auth_code = isset($params['auth_code']) ? $params['auth_code'] : '';
  38. $openid = isset($params['openid']) ? $params['openid'] : '';
  39. $request = request();
  40. $notifyurl = isset($params['notifyurl']) ? $params['notifyurl'] : $request->root(true) . '/addons/epay/index/' . $type . 'notify';
  41. $returnurl = isset($params['returnurl']) ? $params['returnurl'] : $request->root(true) . '/addons/epay/index/' . $type . 'return/out_trade_no/' . $orderid;
  42. $html = '';
  43. $config = Service::getConfig($type);
  44. $config[$type]['notify_url'] = $notifyurl;
  45. $config[$type]['return_url'] = $returnurl;
  46. if ($type == 'alipay') {
  47. //创建支付对象
  48. $pay = new Pay($config);
  49. //支付宝支付,请根据你的需求,仅选择你所需要的即可
  50. $params = [
  51. 'out_trade_no' => $orderid,//你的订单号
  52. 'total_amount' => $amount,//单位元
  53. 'subject' => $title,
  54. ];
  55. //如果是移动端自动切换为wap
  56. $method = $request->isMobile() ? 'wap' : $method;
  57. switch ($method) {
  58. case 'web':
  59. //电脑支付,跳转
  60. $html = $pay->driver($type)->gateway('web')->pay($params);
  61. Response::create($html)->send();
  62. break;
  63. case 'wap':
  64. //手机网页支付,跳转
  65. $html = $pay->driver($type)->gateway('wap')->pay($params);
  66. Response::create($html)->send();
  67. break;
  68. case 'app':
  69. //APP支付,直接返回字符串
  70. $html = $pay->driver($type)->gateway('app')->pay($params);
  71. break;
  72. case 'scan':
  73. //扫码支付,直接返回字符串
  74. $html = $pay->driver($type)->gateway('scan')->pay($params);
  75. break;
  76. case 'pos':
  77. //刷卡支付,直接返回字符串
  78. //刷卡支付必须要有auth_code
  79. $params['auth_code'] = $auth_code;
  80. $html = $pay->driver($type)->gateway('pos')->pay($params);
  81. break;
  82. default:
  83. //其它支付类型请参考:https://docs.pay.yansongda.cn/alipay
  84. }
  85. } else {
  86. //如果是PC支付,判断当前环境,进行跳转
  87. if ($method == 'web') {
  88. if ((strpos($request->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false)) {
  89. Session::delete("openid");
  90. Session::set("wechatorderdata", $params);
  91. $url = addon_url('epay/api/wechat', [], true, true);
  92. header("location:{$url}");
  93. exit;
  94. } elseif ($request->isMobile()) {
  95. $method = 'wap';
  96. }
  97. }
  98. //创建支付对象
  99. $pay = new Pay($config);
  100. $params = [
  101. 'out_trade_no' => $orderid,//你的订单号
  102. 'body' => $title,
  103. 'total_fee' => $amount * 100, //单位分
  104. ];
  105. switch ($method) {
  106. case 'web':
  107. //电脑支付,跳转到自定义展示页面(FastAdmin独有)
  108. $html = $pay->driver($type)->gateway('web')->pay($params);
  109. Response::create($html)->send();
  110. break;
  111. case 'mp':
  112. //公众号支付
  113. //公众号支付必须有openid
  114. $params['openid'] = $openid;
  115. $html = $pay->driver($type)->gateway('mp')->pay($params);
  116. break;
  117. case 'wap':
  118. //手机网页支付,跳转
  119. $params['spbill_create_ip'] = $request->ip(0, false);
  120. $html = $pay->driver($type)->gateway('wap')->pay($params);
  121. header("location:{$html}");
  122. exit;
  123. break;
  124. case 'app':
  125. //APP支付,直接返回字符串
  126. $html = $pay->driver($type)->gateway('app')->pay($params);
  127. break;
  128. case 'scan':
  129. //扫码支付,直接返回字符串
  130. $html = $pay->driver($type)->gateway('scan')->pay($params);
  131. break;
  132. case 'pos':
  133. //刷卡支付,直接返回字符串
  134. //刷卡支付必须要有auth_code
  135. $params['auth_code'] = $auth_code;
  136. $html = $pay->driver($type)->gateway('pos')->pay($params);
  137. break;
  138. case 'miniapp':
  139. //小程序支付,直接返回字符串
  140. //小程序支付必须要有openid
  141. $params['openid'] = $openid;
  142. $html = $pay->driver($type)->gateway('miniapp')->pay($params);
  143. break;
  144. default:
  145. }
  146. }
  147. //返回字符串
  148. $html = is_array($html) ? json_encode($html) : $html;
  149. return $html;
  150. }
  151. /**
  152. * @param string $orderNo 订单号
  153. * @param string $type 支付类型 wechat alipay
  154. * @param int $amount 退款金额
  155. */
  156. public static function refund($orderNo,$type,$amount){
  157. $config = Service::getConfig($type);
  158. $pay = new Pay($config);
  159. if ($type == "alipay") {
  160. $config_biz = [
  161. 'out_trade_no' => $orderNo,
  162. 'refund_amount' => $amount,
  163. ];
  164. $pay->driver($type)->gateway()->refund($config_biz);
  165. } else {
  166. $config_biz = [
  167. 'out_trade_no' => $orderNo,
  168. 'out_refund_no' => $orderNo,
  169. 'total_fee' => bcmul($amount, 100),
  170. 'refund_fee' => bcmul($amount, 100),
  171. ];
  172. $pay->driver($type)->gateway()->refund($config_biz);
  173. }
  174. }
  175. /**
  176. * 创建支付对象
  177. * @param string $type 支付类型
  178. * @param array $config 配置信息
  179. * @return bool
  180. */
  181. public static function createPay($type, $config = [])
  182. {
  183. $type = strtolower($type);
  184. if (!in_array($type, ['wechat', 'alipay'])) {
  185. return false;
  186. }
  187. $config = self::getConfig($type);
  188. $config = array_merge($config[$type], $config);
  189. $pay = new Pay($config);
  190. return $pay;
  191. }
  192. /**
  193. * 验证回调是否成功
  194. * @param string $type 支付类型
  195. * @param array $config 配置信息
  196. * @return bool|Pay
  197. */
  198. public static function checkNotify($type, $config = [])
  199. {
  200. $type = strtolower($type);
  201. if (!in_array($type, ['wechat', 'alipay'])) {
  202. return false;
  203. }
  204. try {
  205. file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/".date("d"). '.log', "开始获取参数" . PHP_EOL, FILE_APPEND);
  206. $pay = new Pay(self::getConfig($type));
  207. $data = $type == 'wechat' ? file_get_contents("php://input") : request()->post('', null, 'trim');
  208. file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/".date("d"). '.log', json_encode($data) . PHP_EOL, FILE_APPEND);
  209. $data = $pay->driver($type)->gateway()->verify($data);
  210. if ($type == 'alipay') {
  211. if (in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
  212. return $pay;
  213. }
  214. } else {
  215. return $pay;
  216. }
  217. } catch (Exception $e) {
  218. return false;
  219. }
  220. return false;
  221. }
  222. /**
  223. * 验证返回是否成功
  224. * @param string $type 支付类型
  225. * @param array $config 配置信息
  226. * @return bool|Pay
  227. */
  228. public static function checkReturn($type, $config = [])
  229. {
  230. $type = strtolower($type);
  231. if (!in_array($type, ['wechat', 'alipay'])) {
  232. return false;
  233. }
  234. //微信无需验证
  235. if ($type == 'wechat') {
  236. return true;
  237. }
  238. try {
  239. $pay = new Pay(self::getConfig($type));
  240. $data = $type == 'wechat' ? file_get_contents("php://input") : request()->get('', null, 'trim');
  241. $data = $pay->driver($type)->gateway()->verify($data);
  242. if ($data) {
  243. return $pay;
  244. }
  245. } catch (Exception $e) {
  246. return false;
  247. }
  248. return false;
  249. }
  250. /**
  251. * 获取配置
  252. * @param string $type 支付类型
  253. * @return array|mixed
  254. */
  255. public static function getConfig($type = 'wechat')
  256. {
  257. $config = get_addon_config('epay');
  258. $config = isset($config[$type]) ? $config[$type] : $config['wechat'];
  259. if ($config['log']) {
  260. $config['log'] = [
  261. 'file' => LOG_PATH . '/epaylogs/' . $type . '-' . date("Y-m-d") . '.log',
  262. 'level' => 'debug'
  263. ];
  264. }
  265. if (isset($config['cert_client']) && substr($config['cert_client'], 0, 6) == '/epay/') {
  266. $config['cert_client'] = ADDON_PATH . $config['cert_client'];
  267. }
  268. if (isset($config['cert_key']) && substr($config['cert_key'], 0, 6) == '/epay/') {
  269. $config['cert_key'] = ADDON_PATH . $config['cert_key'];
  270. }
  271. $config['notify_url'] = empty($config['notify_url']) ? addon_url('epay/api/notifyx', [], false) . '/type/' . $type : $config['notify_url'];
  272. $config['notify_url'] = !preg_match("/^(http:\/\/|https:\/\/)/i", $config['notify_url']) ? request()->root(true) . $config['notify_url'] : $config['notify_url'];
  273. $config['return_url'] = empty($config['return_url']) ? addon_url('epay/api/returnx', [], false) . '/type/' . $type : $config['return_url'];
  274. $config['return_url'] = !preg_match("/^(http:\/\/|https:\/\/)/i", $config['return_url']) ? request()->root(true) . $config['return_url'] : $config['return_url'];
  275. return [$type => $config];
  276. }
  277. }