Pay.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace addon\alipay\model;
  11. use addon\alipay\data\sdk\AopClient;
  12. use addon\alipay\data\sdk\request\AlipayFundTransToaccountTransferRequest;
  13. use addon\alipay\data\sdk\request\AlipayTradeAppPayRequest;
  14. use addon\alipay\data\sdk\request\AlipayTradeCloseRequest;
  15. use addon\alipay\data\sdk\request\AlipayTradeCreateRequest;
  16. use addon\alipay\data\sdk\request\AlipayTradePagePayRequest;
  17. use addon\alipay\data\sdk\request\AlipayTradeRefundRequest;
  18. use addon\alipay\data\sdk\request\AlipayTradeWapPayRequest;
  19. use addon\alipay\data\sdk\request\AlipayTradePrecreateRequest;
  20. use addon\alipay\data\sdk\request\AlipayTradePayRequest;
  21. use app\exception\ApiException;
  22. use app\model\BaseModel;
  23. use app\model\system\Pay as PayCommon;
  24. use addon\alipay\data\sdk\request\AlipayFundTransUniTransferRequest;
  25. use addon\alipay\data\sdk\AopCertClient;
  26. use app\model\system\Pay as PayModel;
  27. use addon\aliapp\model\Config as AliappConfig;
  28. /**
  29. * 支付宝支付配置
  30. */
  31. class Pay extends BaseModel
  32. {
  33. public $aop;
  34. private $is_aliapp = 0;
  35. /**
  36. *
  37. * @param $site_id
  38. * @param $is_aliapp 是否是小程序
  39. */
  40. function __construct($site_id, $is_aliapp = 0)
  41. {
  42. $this->is_aliapp = $is_aliapp;
  43. try {
  44. // 获取支付宝支付参数(统一支付到平台账户)
  45. if ($is_aliapp) {
  46. $config_info = (new AliappConfig())->getAliappConfig($site_id)['data']['value'];
  47. } else {
  48. $config_info = (new Config())->getPayConfig($site_id)['data']['value'];
  49. }
  50. if (empty($config_info)) {
  51. exit(json_encode($this->error('', '支付宝支付未配置')));
  52. }
  53. $countersign_type = $config_info[ 'countersign_type' ] ?? 0;
  54. if ($countersign_type == 1) {
  55. $appCertPath = $config_info[ "public_key_crt" ] ?? "";
  56. $alipayCertPath = $config_info[ "alipay_public_key_crt" ] ?? "";
  57. $rootCertPath = $config_info[ "alipay_with_crt" ] ?? "";
  58. $this->aop = new AopCertClient();
  59. //调用getPublicKey从支付宝公钥证书中提取公钥
  60. $this->aop->alipayrsaPublicKey = $this->aop->getPublicKey($alipayCertPath);
  61. //是否校验自动下载的支付宝公钥证书,如果开启校验要保证支付宝根证书在有效期内
  62. $this->aop->isCheckAlipayPublicCert = false;
  63. //调用getCertSN获取证书序列号
  64. $this->aop->appCertSN = $this->aop->getCertSN($appCertPath);
  65. //调用getRootCertSN获取支付宝根证书序列号
  66. $this->aop->alipayRootCertSN = $this->aop->getRootCertSN($rootCertPath);
  67. } else {
  68. // 获取支付宝支付参数(统一支付到平台账户)
  69. $this->aop = new AopClient();
  70. $this->aop->alipayrsaPublicKey = $config_info[ 'public_key' ] ?? "";
  71. $this->aop->alipayPublicKey = $config_info[ 'alipay_public_key' ] ?? "";
  72. }
  73. $this->aop->appId = $config_info[ "app_id" ] ?? "";
  74. $this->aop->rsaPrivateKey = $config_info[ 'private_key' ] ?? "";
  75. $this->aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
  76. $this->aop->apiVersion = '1.0';
  77. $this->aop->signType = 'RSA2';
  78. $this->aop->postCharset = 'UTF-8';
  79. $this->aop->format = 'json';
  80. } catch (\Exception $e) {
  81. exit(json_encode($this->error('', '支付宝配置错误')));
  82. }
  83. }
  84. /**
  85. * 生成支付
  86. * @param $param
  87. */
  88. public function pay($param)
  89. {
  90. //构造要请求的参数数组,无需改动
  91. $parameter = array (
  92. "out_trade_no" => $param[ "out_trade_no" ],
  93. "subject" => str_sub($param[ "pay_body" ], 15),
  94. "total_amount" => (float) $param[ "pay_money" ],
  95. "body" => str_sub($param[ "pay_body" ], 60),
  96. "product_code" => 'FAST_INSTANT_TRADE_PAY',
  97. );
  98. switch ( $param[ "app_type" ] ) {
  99. case "h5":
  100. $request = new AlipayTradeWapPayRequest();
  101. break;
  102. case "pc":
  103. $request = new AlipayTradePagePayRequest();
  104. break;
  105. case "app":
  106. $request = new AlipayTradeAppPayRequest();
  107. break;
  108. case 'wechat':
  109. $request = new AlipayTradeWapPayRequest();
  110. break;
  111. case 'cashier':
  112. $request = new AlipayTradePrecreateRequest();
  113. break;
  114. case 'aliapp':
  115. $parameter['product_code'] = 'FACE_TO_FACE_PAYMENT';
  116. $member_info = model('member')->getInfo([ [ "member_id", "=", $param[ "member_id" ] ] ], 'ali_openid');
  117. if (empty($member_info)) return $this->error(-1, '未获取到会员信息');
  118. $parameter['buyer_id'] = $member_info['ali_openid'];
  119. $request = new AlipayTradeCreateRequest();
  120. break;
  121. }
  122. $parameter = json_encode($parameter);
  123. $request->setBizContent($parameter);
  124. $request->SetReturnUrl($param[ "return_url" ]);
  125. $request->SetNotifyUrl($param[ "notify_url" ]);
  126. ///绑定商户数据
  127. $pay_model = new PayModel();
  128. $pay_model->bindMchPay($param[ "out_trade_no" ], [ "is_aliapp" => $this->is_aliapp ]);
  129. if ($param[ "app_type" ] == 'h5' || $param[ "app_type" ] == 'wechat' || $param[ "app_type" ] == 'pc') {
  130. $result = $this->aop->pageExecute($request, 'get');
  131. return $this->success([
  132. 'type' => 'url',
  133. 'data' => $result
  134. ]);
  135. }
  136. $result = $this->aop->execute($request);
  137. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  138. $resultCode = $result->$responseNode->code;
  139. if (!empty($resultCode) && $resultCode == 10000) {
  140. switch ($param[ "app_type" ]) {
  141. case 'cashier':
  142. return $this->success([
  143. 'type' => 'qrcode',
  144. 'data' => [
  145. 'qrcode' => $result->$responseNode->qr_code
  146. ]
  147. ]);
  148. break;
  149. case 'aliapp':
  150. return $this->success([
  151. 'type' => 'data',
  152. 'data' => [
  153. 'orderInfo' => $result->$responseNode->trade_no
  154. ]
  155. ]);
  156. break;
  157. default:
  158. return $this->success();
  159. }
  160. } else {
  161. return $this->error("", $result->$responseNode->sub_msg);
  162. }
  163. }
  164. /**
  165. * 支付关闭
  166. * @param unknown $orderNumber
  167. * @return multitype:number string |multitype:number mixed
  168. */
  169. public function close($param)
  170. {
  171. $parameter = array (
  172. "out_trade_no" => $param[ "out_trade_no" ]
  173. );
  174. // 建立请求
  175. $request = new AlipayTradeCloseRequest();
  176. $request->setBizContent(json_encode($parameter));
  177. $result = $this->aop->execute($request);
  178. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  179. $resultCode = $result->$responseNode->code;
  180. if (!empty($resultCode) && $resultCode == 10000) {
  181. return $this->success();
  182. } else {
  183. return $this->error("", $result->$responseNode->sub_msg);
  184. }
  185. }
  186. /**
  187. * 支付宝支付原路返回
  188. * @param unknown $param 支付参数
  189. */
  190. public function refund($param)
  191. {
  192. $pay_info = $param[ "pay_info" ];
  193. $refund_no = $param[ "refund_no" ];
  194. $out_trade_no = $pay_info[ "trade_no" ] ?? '';
  195. $refund_fee = $param[ "refund_fee" ];
  196. $parameter = array (
  197. 'trade_no' => $out_trade_no,
  198. 'refund_amount' => sprintf("%.2f", $refund_fee),
  199. 'out_request_no' => $refund_no
  200. );
  201. // 建立请求
  202. $request = new AlipayTradeRefundRequest ();
  203. $request->setBizContent(json_encode($parameter));
  204. $result = $this->aop->execute($request);
  205. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  206. $resultCode = $result->$responseNode->code;
  207. if (!empty($resultCode) && $resultCode == 10000) {
  208. return $this->success();
  209. } else {
  210. return $this->error("", $result->$responseNode->sub_msg);
  211. }
  212. }
  213. /**
  214. * 支付宝转账
  215. * @param $param
  216. * @return array
  217. * @throws \think\Exception
  218. */
  219. public function payTransfer($param)
  220. {
  221. try {
  222. $config_model = new Config();
  223. $config_result = $config_model->getPayConfig($param[ 'site_id' ]);
  224. if ($config_result[ 'code' ] < 0) return $config_result;
  225. $config = $config_result[ 'data' ][ 'value' ];
  226. if (empty($config)) return $this->error([], '未配置支付宝支付');
  227. if (!$config[ 'transfer_status' ]) return $this->error([], '未启用支付宝转账');
  228. $parameter = [
  229. 'out_biz_no' => $param[ 'out_trade_no' ],
  230. 'payee_type' => 'ALIPAY_LOGONID',
  231. 'payee_account' => $param[ "account_number" ],
  232. 'amount' => sprintf("%.2f", $param[ 'amount' ]),
  233. 'payee_real_name' => $param[ "real_name" ],
  234. 'remark' => $param[ "desc" ]
  235. ];
  236. // 建立请求
  237. $request = new AlipayFundTransToaccountTransferRequest();
  238. $request->setBizContent(json_encode($parameter));
  239. $result = $this->aop->execute($request);
  240. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  241. $resultCode = $result->$responseNode->code;
  242. if (!empty($resultCode) && $resultCode == 10000) {
  243. return $this->success([
  244. 'out_trade_no' => $result->$responseNode->out_biz_no, // 商户交易号
  245. 'payment_no' => $result->$responseNode->order_id, // 微信付款单号
  246. 'payment_time' => date_to_time($result->$responseNode->pay_date) // 付款成功时间
  247. ]);
  248. } else {
  249. return $this->error([], $result->$responseNode->sub_msg);
  250. }
  251. } catch (\Exception $e) {
  252. return $this->error([], $e->getMessage());
  253. }
  254. }
  255. /**
  256. * 异步完成支付
  257. * @param $param
  258. */
  259. public function payNotify()
  260. {
  261. // Log::write('pay_notifiy_log:alipay:'.json_encode(input()), 'notice');
  262. try {
  263. $res = $this->aop->rsaCheckV1($_POST, $this->aop->alipayrsaPublicKey, $this->aop->signType);
  264. if ($res) { // 验证成功
  265. $out_trade_no = $_POST[ 'out_trade_no' ];
  266. // 支付宝交易号
  267. $trade_no = $_POST[ 'trade_no' ];
  268. // 交易状态
  269. $trade_status = $_POST[ 'trade_status' ];
  270. $pay_common = new PayCommon();
  271. if ($trade_status == "TRADE_SUCCESS") {
  272. $retval = $pay_common->onlinePay($out_trade_no, "alipay", $trade_no, "alipay");
  273. }
  274. echo "success";
  275. } else {
  276. // 验证失败
  277. echo "fail";
  278. }
  279. } catch (\Exception $e) {
  280. echo "fail";
  281. }
  282. }
  283. public function payNewTransfer($param)
  284. {
  285. try {
  286. $config_model = new Config();
  287. $config_result = $config_model->getPayConfig($param[ 'site_id' ]);
  288. if ($config_result[ 'code' ] < 0) return $config_result;
  289. $config = $config_result[ 'data' ][ 'value' ];
  290. if (empty($config)) return $this->error([], '未配置支付宝支付');
  291. if (!$config[ 'transfer_status' ]) return $this->error([], '未启用支付宝转账');
  292. $parameter = [
  293. 'out_biz_no' => $param[ 'out_trade_no' ],
  294. 'trans_amount' => sprintf("%.2f", $param[ 'amount' ]),
  295. 'product_code' => 'TRANS_ACCOUNT_NO_PWD',
  296. 'biz_scene' => 'DIRECT_TRANSFER',
  297. 'order_title' => '支付宝转账',
  298. 'remark' => $param[ "desc" ],
  299. 'payee_info' => [
  300. 'identity' => $param[ "account_number" ],
  301. 'identity_type' => "ALIPAY_LOGON_ID",
  302. 'name' => $param[ "real_name" ]
  303. ]
  304. ];
  305. // 建立请求
  306. $request = new AlipayFundTransUniTransferRequest();
  307. $request->setBizContent(json_encode($parameter));
  308. $result = $this->aop->execute($request);
  309. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  310. $resultCode = $result->$responseNode->code;
  311. if (!empty($resultCode) && $resultCode == 10000) {
  312. return $this->success([
  313. 'out_trade_no' => $result->$responseNode->out_biz_no, // 商户交易号
  314. 'payment_no' => $result->$responseNode->order_id, // 微信付款单号
  315. 'payment_time' => date_to_time($result->$responseNode->trans_date) // 付款成功时间
  316. ]);
  317. } else {
  318. return $this->error([], $result->$responseNode->sub_msg);
  319. }
  320. } catch (\Exception $e) {
  321. return $this->error([], $e->getMessage());
  322. }
  323. }
  324. /**
  325. * 付款码支付
  326. * @param $param
  327. */
  328. public function micropay($param)
  329. {
  330. try {
  331. //构造要请求的参数数组,无需改动
  332. $parameter = array (
  333. "out_trade_no" => $param[ "out_trade_no" ],
  334. "subject" => str_sub($param[ "pay_body" ], 15),
  335. "total_amount" => (float) $param[ "pay_money" ],
  336. "scene" => "bar_code",
  337. "auth_code" => $param[ 'auth_code' ],
  338. );
  339. $parameter = json_encode($parameter);
  340. $request = new AlipayTradePayRequest();
  341. $request->setBizContent($parameter);
  342. $result = $this->aop->execute($request);
  343. $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
  344. $resultCode = $result->$responseNode->code;
  345. if (!empty($resultCode) && $resultCode == 10000) {
  346. $pay_common = new PayModel();
  347. return $res = $pay_common->onlinePay($param[ 'out_trade_no' ], 'alipay', $result->$responseNode->trade_no, 'alipay');
  348. } else {
  349. return $this->error([], $result->$responseNode->sub_msg);
  350. }
  351. } catch (\Exception $e) {
  352. return $this->error([], $e->getMessage());
  353. }
  354. }
  355. }