Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

306 wiersze
12 KiB

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