AliPayService.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <?php
  2. namespace App\Service;
  3. use App\Modes\ErrorLog;
  4. use App\Modes\Order;
  5. use App\Modes\PayLog;
  6. use Yansongda\Pay\Pay;
  7. use Yansongda\Pay\Log;
  8. use alipay\aop;
  9. use alipay\aop\request\AlipayTradeAppPayRequest;
  10. use alipay\aop\request\AlipayTradeRefundRequest;
  11. use ErrorException;
  12. use GuzzleHttp\Client;
  13. class AliPayService
  14. {
  15. protected $config = [];
  16. protected $pay;
  17. public function __construct()
  18. {
  19. $this->pay = Pay::alipay(config('pay.alipay'));
  20. }
  21. /**
  22. * 获取支付信息
  23. * @author lyh
  24. * @date 2019/3/22
  25. * @param string $outTradeNo 订单号
  26. * @param double $price 支付金额
  27. * @param string $subject 备注
  28. * @return \Symfony\Component\HttpFoundation\Response
  29. * @description
  30. */
  31. public function getPayInfo($outTradeNo, $price, $subject = '')
  32. {
  33. // $order = [
  34. // 'out_trade_no' => $outTradeNo,
  35. // 'total_amount' => $price,
  36. // 'subject' => $subject,
  37. // //'http_method' => 'GET'
  38. // ];
  39. // $alipay = $this->pay->wap($order);
  40. // $retData = $alipay->getContent();
  41. $client = new Client();
  42. $response = $client->request('GET',env('APP_URL').'/pay',[
  43. 'query'=>[
  44. 'op'=>'getPayInfo',
  45. 'outTradeNo'=>$outTradeNo,
  46. 'price'=>$price,
  47. 'subject'=>$subject,
  48. ]
  49. ]
  50. );
  51. $retData = $response->getBody()->getContents();
  52. ErrorLog::saveMsg('aliPay请求支付参数', $retData, 1);
  53. return $retData;
  54. }
  55. /*
  56. * pc支付信息
  57. * add bu wsl
  58. * 20190701
  59. * */
  60. public function getPcpayinfo($outTradeNo, $price, $subject = ''){
  61. $order = [
  62. 'out_trade_no' => $outTradeNo,
  63. 'total_amount' => $price,
  64. 'subject' => $subject,
  65. 'qr_pay_mode' => 4,
  66. 'qrcode_width' => 150,
  67. //'http_method' => 'GET'
  68. ];
  69. $alipay = $this->pay->web($order);
  70. //ErrorLog::saveMsg('aliPay请求支付参数', $alipay->getContent(), 1);
  71. return $alipay->getContent();
  72. }
  73. public function getReturnInfo($outTradeNo, $trade_no,$price)
  74. {
  75. // $order = [
  76. // 'out_trade_no' => $outTradeNo,
  77. // 'refund_amount' => $price,
  78. // 'trade_no' => $trade_no,
  79. // ];
  80. // $alirefund=$this->pay->refund($order);
  81. $client = new Client();
  82. $response = $client->request('GET',env('APP_URL').'/pay',[
  83. 'query'=>[
  84. 'op'=>'getReturnInfo',
  85. 'outTradeNo'=>$outTradeNo,
  86. 'price'=>$price,
  87. 'trade_no'=>$trade_no,
  88. ]
  89. ]
  90. );
  91. $alirefund = $response->getBody()->getContents();
  92. $resArr = json_decode($alirefund,true);
  93. if($resArr['code']!='10000'){
  94. throw new \ErrorException($resArr['msg']);
  95. }
  96. return json_decode($alirefund);
  97. }
  98. /**
  99. * [getPayInfo 获取支付信息,app原生支付]
  100. * @author lgs
  101. * @DateTime 2019-06-21T15:46:57+0800
  102. * @param [type] $outTradeNo [description]
  103. * @param [type] $price [description]
  104. * @param string $subject [description]
  105. * @return [type] [description]
  106. */
  107. public function getAppPayInfo($outTradeNo, $price, $subject = '')
  108. {
  109. // ErrorLog::saveMsg('aliPay请求支付参数222', $outTradeNo, 1);
  110. include(dirname(dirname(dirname(__FILE__))).'/public/alipay/AopSdk.php');
  111. include(dirname(dirname(dirname(__FILE__))).'/public/alipay/aop/AopClient.php');
  112. include(dirname(dirname(dirname(__FILE__))).'/public/alipay/aop/request/AlipayTradeAppPayRequest.php');
  113. //======================lzj 2021/4/23 注销========================//
  114. // $order = [
  115. // 'out_trade_no' => $outTradeNo,
  116. // 'total_amount' => $price,
  117. // 'subject' => $subject,
  118. // //'http_method' => 'GET'
  119. // ];
  120. // $alipay = $this->pay->app($order);
  121. // ErrorLog::saveMsg('aliPay请求支付参数', $alipay->getContent(), 1);
  122. //=================================================================//
  123. $config = config('pay.alipay');
  124. $aop = new aop\AopClient();
  125. $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
  126. $aop->appId = $config["app_id"];
  127. $aop->rsaPrivateKey = $config['private_key'];
  128. $aop->format = "json";
  129. $aop->charset = "UTF-8";
  130. $aop->signType = "RSA2";
  131. $aop->alipayrsaPublicKey = $config['ali_public_key'];
  132. //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
  133. $request = new AlipayTradeAppPayRequest();
  134. //SDK已经封装掉了公共参数,这里只需要传入业务参数
  135. $bizcontent = "{\"body\":\"点币购买支付\","
  136. . "\"subject\": \"{$subject}\","
  137. . "\"out_trade_no\": \"{$outTradeNo}\","
  138. . "\"timeout_express\": \"30m\","
  139. . "\"total_amount\": \"{$price}\","
  140. . "\"product_code\":\"QUICK_MSECURITY_PAY\""
  141. . "}";
  142. $request->setNotifyUrl($config['notify_url']);
  143. $request->setBizContent($bizcontent);
  144. //这里和普通的接口调用不同,使用的是sdkExecute
  145. $response = $aop->sdkExecute($request);
  146. //$this->logResult('alipayreplay:',$response,'response');
  147. ErrorLog::saveMsg('aliPay请求支付orderstring', $response, 1);
  148. //htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题
  149. //===============lzj 2021/4/23 注销 =================//
  150. // $alipay->response = htmlspecialchars($response);//就是orderString 可以直接给客户端请求,无需再做处理。
  151. // ===================================================//
  152. //echo $alipay->response ;exit;
  153. // return $alipay;
  154. return $response;
  155. }
  156. /**
  157. * h5 支付结果返回
  158. * 同步通知 示例:
  159. * http://nn19030510.vb.com/api/notify/return?charset=GBK&out_trade_no=1554970679424629&method=alipay.trade.wap.pay.return&total_amount=0.01&sign=LCrRfIJXlR2Zsg%2FCr3IlKiUFuLW3emGnLyQB4tjUTZn7zxKJ3sktsYT32EG%2BRG6xH1WrJvLRp%2FuNqvL5f%2Bwd6dG2QX2PgnyhSDS8F7lH5PG5MrK%2FkpD7vzVId4%2FdInZtLVn2EStWX7LRoXzrxAoweaGWL6HKun30Fk1yd80cYpd3N9N0%2Bf20kCSiekcsGozJgurvcUIAT%2BTfh2kYVRc0wXS8NDGJxOpqHowBTJm2gn0MdvsDPLoGYcfxyjBjKDtXFEA%2BpWHQfZgaS6vfyH97qeB4chG%2BmfxfYx1n1APSnTz2nZMyYo8B28uZE5IaWZrqjhbxtqitb4kw9gZdpAHLVg%3D%3D&trade_no=2019041122001444231025690858&auth_app_id=2019040263728819&version=1.0&app_id=2019040263728819&sign_type=RSA2&seller_id=2088431832595334&timestamp=2019-04-11+16%3A18%3A07
  160. * $result 示例:
  161. * Collection {#582 ▼
  162. * #items: array:12 [▼
  163. * "charset" => "GBK"
  164. * "out_trade_no" => "1554970679424629"
  165. * "method" => "alipay.trade.wap.pay.return"
  166. * "total_amount" => "0.01"
  167. * "sign" => "LCrRfIJXlR2Zsg/Cr3IlKiUFuLW3emGnLyQB4tjUTZn7zxKJ3sktsYT32EG+RG6xH1WrJvLRp/uNqvL5f+wd6dG2QX2PgnyhSDS8F7lH5PG5MrK/kpD7vzVId4/dInZtLVn2EStWX7LRoXzrxAoweaGWL6HKun30 ▶"
  168. * "trade_no" => "2019041122001444231025690858"
  169. * "auth_app_id" => "2019040263728819"
  170. * "version" => "1.0"
  171. * "app_id" => "2019040263728819"
  172. * "sign_type" => "RSA2"
  173. * "seller_id" => "2088431832595334"
  174. * "timestamp" => "2019-04-11 16:18:07"
  175. * ]
  176. * }
  177. */
  178. public function return($data)
  179. {
  180. if (is_array($data)) {
  181. $insert = [];
  182. foreach ($data as $key => $item) {
  183. $insert[$key] = urldecode($item);
  184. }
  185. }
  186. $insert['type'] = 1;
  187. PayLog::insert($insert);
  188. try {
  189. ErrorLog::saveMsg('aliPay同步返回支付结果', $data, 1);
  190. $data = $this->pay->verify($data); // 是的,验签就这么简单!
  191. // dd($result->out_trade_no);
  192. // 订单号:$data->out_trade_no
  193. // 支付宝交易号:$data->trade_no
  194. // 订单总金额:$data->total_amount
  195. // 更具订单类型、跳转
  196. $order = Order::whereOrderNo($data->out_trade_no)->first();
  197. return $order;
  198. } catch (\Exception $e) {
  199. ErrorLog::saveMsg('aliPay后台同步通知异常', [
  200. 'msg' => $e->getMessage(),
  201. 'file' => $e->getFile(),
  202. 'line' => $e->getLine(),
  203. 'code' => $e->getCode(),
  204. 'data' => $data,
  205. ], 1);
  206. }
  207. }
  208. /**
  209. * 异步通知
  210. * @author lyh
  211. * @date 2019/3/22
  212. * @param array $data
  213. * {
  214. * "gmt_create": "2019-04-11+18%3A40%3A57",
  215. * "charset": "GBK",
  216. * "seller_email": "34696432%40qq.com",
  217. * "subject": "18978059931%B9%BA%C2%F2%B9%E3%B8%E6%CE%BB",
  218. * "sign": "arVZFl3Xxx%2F%2F3prTUu1ohBetSJNQtL0z5DEM6XqJbL4VYRlVjMabCeXTGbTfGUwMyjhIbRI6CNGrm4OBK7s41ss1N5FOElXk9yEKSEHXEIFAsFcGjKhBhsTexPuTudSNIUM%2F%2B%2B3TH9Ty9L%2FZPa2i8b%2FLbt3yDumcCnLyeAtmwAPMWmCcptSWGf24R5JTTKuJwnhC6Kw8GAyVA8HYpODajwYRCvedh0aDhIAdvyWGaGCaxHKbU%2FRz5NYr3J5ODXpFrhjMq4WS%2FD%2BK6wBBUQ9xHZiBI0FLEEt004vNYudkjPAQgioYmFscQuRPIEnlywaee3V%2BZCSxmR6N0G3dh1qgiQ%3D%3D",
  219. * "buyer_id": "2088702691344231",
  220. * "invoice_amount": "0.01",
  221. * "notify_id": "2019041100222184058044231003716600",
  222. * "fund_bill_list": "%5B%7B%22amount%22%3A%220.01%22%2C%22fundChannel%22%3A%22ALIPAYACCOUNT%22%7D%5D",
  223. * "notify_type": "trade_status_sync",
  224. * "trade_status": "TRADE_SUCCESS",
  225. * "receipt_amount": "0.01",
  226. * "buyer_pay_amount": "0.01",
  227. * "app_id": "2019040263728819",
  228. * "sign_type": "RSA2",
  229. * "seller_id": "2088431832595334",
  230. * "gmt_payment": "2019-04-11+18%3A40%3A58",
  231. * "notify_time": "2019-04-11+18%3A43%3A18",
  232. * "version": "1.0",
  233. * "out_trade_no": "1554979252073513",
  234. * "total_amount": "0.01",
  235. * "trade_no": "2019041122001444231025848894",
  236. * "auth_app_id": "2019040263728819",
  237. * "buyer_logon_id": "151***%40139.com",
  238. * "point_amount": "0.00"
  239. * }
  240. * @return \Symfony\Component\HttpFoundation\Response
  241. * @description
  242. * 支付宝回复状态
  243. * 9000 订单支付成功
  244. * 8000 正在处理中,支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
  245. * 4000 订单支付失败
  246. * 5000 重复请求
  247. * 6001 用户中途取消
  248. * 6002 网络连接出错
  249. * 6004 支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
  250. * 其它 其它支付错误
  251. *
  252. * // 请自行对 trade_status 进行判断及其它逻辑进行判断,在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
  253. * // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
  254. * // 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
  255. * // 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email);
  256. * // 4、验证app_id是否为该商户本身。
  257. * // 5、其它业务逻辑情况
  258. *{"msg":"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'body' in 'field list' (SQL: insert into `zx_pay_log` (`gmt_create`, `charset`, `seller_email`, `subject`, `sign`, `body`, `buyer_id`, `invoice_amount`, `notify_id`, `fund_bill_list`, `notify_type`, `trade_status`, `receipt_amount`, `app_id`, `buyer_pay_amount`, `sign_type`, `seller_id`, `gmt_payment`, `notify_time`, `version`, `out_trade_no`, `total_amount`, `trade_no`, `auth_app_id`, `buyer_logon_id`, `point_amount`, `type`) values (2019-06-25 16:23:49, UTF-8, 34696432@qq.com, 18928798343SmztlVtqrZF+Fy9mT\/h4PN48a\/rv8BaGPlXnIxwmEGIJPRfVypVlpKuyB9MMWVjgc8xjljLmKqzB\/JEoM7yNaL5sdoopjZZEa2M0uCAoNuCJUq6Rl9D456VYfBDIMLthBlfw2C0FlOLI\/wEzXqgdHLOhHDXOlv1ssRklc+QUIGVCC343VEO5uqLHs+xREB42uWiYRDm5PHaIMied6HMfDfOcIm+twiyS24XOfpNb+LAN36ah02cV\/YRGwXHqBkH4fN66C\/DKsxYaxjMv5TRonAeQp5bv9u376aL+HhwoD07oPaTeRDDpG3ez3951Q2s1gQqLP+uOy+vuj9Jai34JAw==\u74702088802534445384\u74700.01\u74902019062500222162349045380558162099\u62f1[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]trade_status_syncTRADE_SUCCESS\u74900.01\u62f1, 2019040263728819, 0.01, RSA2, 2088431832595334, 2019-06-25 16:23:49, 2019-06-25 16:23:50, 1.0, 1561451016259457, 0.01, 2019062522001445380512216373, 2019040263728819, 189****8343, 0.00, 2, ?, ?, ?, ?, ?, ?, ?, ?, ?))","file":"\/www\/wwwroot\/10dsm\/vendor\/laravel\/framework\/src\/Illuminate\/Database\/Connection.php","line":664,"code":"42S22","data":{"gmt_create":"2019-06-25 16:23:49","charset":"UTF-8","seller_email":"34696432@qq.com","subject":"18928798343?\u7470?\u7490?\u62f1","sign":"SmztlVtqrZF+Fy9mT\/h4PN48a\/rv8BaGPlXnIxwmEGIJPRfVypVlpKuyB9MMWVjgc8xjljLmKqzB\/JEoM7yNaL5sdoopjZZEa2M0uCAoNuCJUq6Rl9D456VYfBDIMLthBlfw2C0FlOLI\/wEzXqgdHLOhHDXOlv1ssRklc+QUIGVCC343VEO5uqLHs+xREB42uWiYRDm5PHaIMied6HMfDfOcIm+twiyS24XOfpNb+LAN36ah02cV\/YRGwXHqBkH4fN66C\/DKsxYaxjMv5TRonAeQp5bv9u376aL+HhwoD07oPaTeRDDpG3ez3951Q2s1gQqLP+uOy+vuj9Jai34JAw==","body":"?\u7470?\u7490?\u62f1???","buyer_id":"2088802534445384","invoice_amount":"0.01","notify_id":"2019062500222162349045380558162099","fund_bill_list":"[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]","notify_type":"trade_status_sync","trade_status":"TRADE_SUCCESS","receipt_amount":"0.01","app_id":"2019040263728819","buyer_pay_amount":"0.01","sign_type":"RSA2","seller_id":"2088431832595334","gmt_payment":"2019-06-25 16:23:49","notify_time":"2019-06-25 16:23:50","version":"1.0","out_trade_no":"1561451016259457","total_amount":"0.01","trade_no":"2019062522001445380512216373","auth_app_id":"2019040263728819","buyer_logon_id":"189****8343","point_amount":"0.00"}}
  259. */
  260. public function notify($data)
  261. {
  262. try {
  263. $insert = $data;
  264. $insert['type'] = 2;
  265. if(isset($insert['body'])){
  266. unset($insert['body']);
  267. }
  268. PayLog::insert($insert);
  269. //$this->pay->verify($data); // 是的,验签就这么简单!先不验签吧
  270. $order = Order::whereOrderNo($data['out_trade_no'])->first();
  271. //$this->logResult('alipaynotify:',$data,'notify');
  272. if ($data['trade_status'] == 'TRADE_SUCCESS' && $data['total_amount']==$order['price'] && $order['is_pay']==0) {
  273. Order::verifyOrder($data['out_trade_no'], $data['total_amount'], 2,$data['trade_no']);
  274. }
  275. } catch (\Exception $e) {
  276. ErrorLog::saveMsg('aliPay后台异步通知异常', [
  277. 'msg' => $e->getMessage(),
  278. 'file' => $e->getFile(),
  279. 'line' => $e->getLine(),
  280. 'code' => $e->getCode(),
  281. 'data' => $data,
  282. ], 1);
  283. }
  284. return $this->pay->success();
  285. }
  286. function logResult($word = '',$var=array(),$filenames) {
  287. define('MROOT',dirname(__FILE__).'/');
  288. $output= strftime("%Y%m%d %H:%M:%S", time()) . "\n" ;
  289. $output .= $word."\n" ;
  290. if(!empty($var)){
  291. $output .= print_r($var, true)."\n";
  292. }
  293. $output.="\n";
  294. $log_path=MROOT . "/paylog/";
  295. if(!is_dir($log_path)){
  296. @mkdir($log_path, 0777, true);
  297. }
  298. file_put_contents($log_path."alipay".date("Ymd-His").$filenames.".txt", $output, FILE_APPEND | LOCK_EX);
  299. }
  300. }