Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

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