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.
 
 
 
 
 
 

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