Yspay.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <?php namespace Pay\Lib;
  2. use Dever;
  3. class Yspay extends Core
  4. {
  5. public function __construct($config)
  6. {
  7. $project = Dever::project('pay');
  8. # 通知接口
  9. $config['notify'] = $this->url($config['type'], $config['id']);
  10. $this->config = $config;
  11. }
  12. /**
  13. * 通知
  14. */
  15. public function notify()
  16. {
  17. $input = file_get_contents("php://input");
  18. if ($input) {
  19. parse_str($input, $input);
  20. } else {
  21. $input = Dever::input();
  22. }
  23. $this->log('支付回调-初始化', $input);
  24. return;
  25. ksort($input);
  26. $input = http_build_query($input);
  27. $tools = new \Cmbc\Handle();
  28. $callback = $tools->get('notify', $this->config);
  29. $result = $callback->request($input, $this);
  30. if ($result) {
  31. $this->log('支付回调-获取数据', $result);
  32. $this->updateOrder($result['mhtOrderNo'], $result['mhtOrderAmt']);
  33. echo 'SUCCESS';die;
  34. } else {
  35. echo 'FAILED';die;
  36. }
  37. }
  38. /**
  39. * 获取统一下单的基本信息
  40. */
  41. public function order($account_id, $project_id, $uid, $username, $product_id, $name, $cash, $openid = false, $type = 1, $order_id = false)
  42. {
  43. $trade_type = $this->getType($type);
  44. $order_id = $this->createOrder($uid, $username, $account_id, $project_id, $product_id, $name, $cash, $this->config['type'], $order_id);
  45. $request['merOrderId'] = $order_id;
  46. $request['mid'] = $this->config['mchid'];
  47. $request['tid'] = $this->config['key'];
  48. $request['instMid'] = 'MINIDEFAULT';
  49. $request['totalAmount'] = $cash * 100;
  50. $request['subAppId'] = $this->config['appid'];
  51. $request['requestTimestamp'] = date("Y-m-d H:i:s");
  52. $request['expireTime'] = $this->config['timeout'];
  53. $request['notifyUrl'] = $this->config['notify'];
  54. $request['tradeType'] = 'MINI';
  55. /*
  56. # 是否启用分账
  57. $request['divisionFlag'] = true;
  58. # 平台分账金额
  59. $request['platformAmount'] = $request['totalAmount'] * 0.1;
  60. if ($request['divisionFlag']) {
  61. $request['subOrders'] = array();
  62. $request['subOrders']['mid'] = 1;
  63. $request['subOrders']['totalAmount'] = $request['totalAmount'] - $request['platformAmount'];
  64. }*/
  65. if (!$openid) {
  66. # 测试的openid
  67. $request['subOpenId'] = 'ofBUV0RUoy_8C4VctZjrSDGzhUfY';
  68. } else {
  69. $request['subOpenId'] = $openid;
  70. }
  71. $result = Base::pay($request, $this->config);
  72. $this->updateOrderParam($order_id, $result);
  73. return $result;
  74. }
  75. # 退款
  76. public function refund($order_id, $cash, $refund_order_id = false)
  77. {
  78. $request['merOrderId'] = $order_id;
  79. $request['mid'] = $this->config['mchid'];
  80. $request['tid'] = $this->config['key'];
  81. $request['instMid'] = 'MINIDEFAULT';
  82. $request['subAppId'] = $this->config['appid'];
  83. $request['requestTimestamp'] = date("Y-m-d H:i:s");
  84. $request['targetOrderId'] = $order_id;
  85. $request['refundAmount'] = $cash * 100;
  86. if ($refund_order_id) {
  87. $request['refundOrderId'] = $refund_order_id;
  88. }
  89. $result = Base::refund($request, $this->config);
  90. if (isset($result['refundStatus']) && $result['refundStatus'] == 'SUCCESS') {
  91. return true;
  92. }
  93. return false;
  94. }
  95. # 查询
  96. public function query($order_id)
  97. {
  98. $request['merOrderId'] = $order_id;
  99. $request['mid'] = $this->config['mchid'];
  100. $request['tid'] = $this->config['key'];
  101. $request['instMid'] = 'MINIDEFAULT';
  102. $request['requestTimestamp'] = date("Y-m-d H:i:s");
  103. $result = Base::refund($request, $this->config);
  104. return $result;
  105. }
  106. # 关闭订单
  107. public function close($order_id)
  108. {
  109. $request['merOrderId'] = $order_id;
  110. $request['mid'] = $this->config['mchid'];
  111. $request['tid'] = $this->config['key'];
  112. $request['instMid'] = 'MINIDEFAULT';
  113. $request['requestTimestamp'] = date("Y-m-d H:i:s");
  114. $result = Base::close($request, $this->config);
  115. return $result;
  116. }
  117. /**
  118. * 获取二维码支付
  119. */
  120. public function qrcode($order, $refer)
  121. {
  122. $notify = new \NativePay();
  123. $result = $notify->GetPayUrl($order);
  124. $url = $result['code_url'];
  125. return $url;
  126. }
  127. /**
  128. * 获取小程序支付
  129. */
  130. public function applet($order)
  131. {
  132. $result = array();
  133. if (isset($order['prepay_id'])) {
  134. $result['time'] = $order['timeStamp'];
  135. $result['nonce_str'] = $order['nonceStr'];
  136. $result['prepay_id'] = $order['prepay_id'];
  137. $result['sign_type'] = $order['signType'];
  138. $result['sign'] = $order['paySign'];
  139. }
  140. return $result;
  141. }
  142. /**
  143. * 获取页面支付
  144. */
  145. public function page($order, $refer)
  146. {
  147. $refer = urldecode($refer);
  148. $tools = new \JsApiPay($this->config);
  149. $info = $tools->GetJsApiParameters($order);
  150. $html = '<script type="text/javascript">
  151. function jsApiCall()
  152. {
  153. WeixinJSBridge.invoke(
  154. "getBrandWCPayRequest",
  155. '.$info.',
  156. function(res){
  157. //WeixinJSBridge.log(res.err_msg);
  158. if(res.err_msg == "get_brand_wcpay_request:ok")
  159. {
  160. location.href = "'.$refer.'";
  161. } else {
  162. alert(res.err_code+res.err_desc+res.err_msg);
  163. }
  164. }
  165. );
  166. }
  167. function callpay()
  168. {
  169. if (typeof WeixinJSBridge == "undefined"){
  170. if( document.addEventListener ){
  171. document.addEventListener("WeixinJSBridgeReady", jsApiCall, false);
  172. }else if (document.attachEvent){
  173. document.attachEvent("WeixinJSBridgeReady", jsApiCall);
  174. document.attachEvent("onWeixinJSBridgeReady", jsApiCall);
  175. }
  176. }else{
  177. jsApiCall();
  178. }
  179. }
  180. callpay();
  181. </script>';
  182. return $html;
  183. }
  184. private function getType($type)
  185. {
  186. switch ($type) {
  187. case 1:
  188. $type = 'JSAPI';
  189. break;
  190. case 2:
  191. $type = 'NATIVE';
  192. break;
  193. case 3:
  194. $type = 'APP';
  195. break;
  196. case 4:
  197. $type = 'MWEB';
  198. break;
  199. }
  200. return $type;
  201. }
  202. }
  203. class Base
  204. {
  205. static $test_host = 'https://test-api-open.chinaums.com/';
  206. static $host = 'https://api-mop.chinaums.com/';
  207. static $signMethod = 'SHA256'; //签名方式
  208. # 获取token
  209. static $token_url = 'v1/token/access';
  210. # 微信下单支付
  211. static $pay_wechat_url = 'v1/netpay/wx/unified-order';
  212. # 支付宝下单支付
  213. static $pay_alipay_url = 'v1/netpay/trade/create';
  214. # 云闪付下单支付
  215. static $pay_uac_url = 'v1/netpay/uac/mini-order';
  216. # 交易查询
  217. static $query_url = 'v1/netpay/query';
  218. # 退款
  219. static $refund_url = 'v1/netpay/refund';
  220. # 退款查询
  221. static $refund_query_url = 'v1/netpay/refund-query';
  222. # 订单关闭
  223. static $close_url = 'v1/netpay/close';
  224. //===================== 支付相关 ==============================
  225. /**
  226. * 支付交易
  227. */
  228. static public function pay($param, $config)
  229. {
  230. $url = self::$refund_url;
  231. $result = self::get($url, $param, $config);
  232. return $result;
  233. }
  234. /**
  235. * 支付撤销
  236. */
  237. static public function close()
  238. {
  239. $url = self::$close_url;
  240. $result = self::get($url, $param, $config);
  241. return $result;
  242. }
  243. /**
  244. * 交易退款
  245. */
  246. static public function refund($param, $config)
  247. {
  248. $url = self::$pay_wechat_url;
  249. $result = self::get($url, $param, $config);
  250. return $result;
  251. }
  252. /**
  253. * 交易查询
  254. */
  255. static public function query()
  256. {
  257. $url = self::$query_url;
  258. $result = self::get($url, $param, $config);
  259. return $result;
  260. }
  261. /**
  262. * 交易退款查询
  263. */
  264. static public function refundQuery()
  265. {
  266. $url = self::$refund_query_url;
  267. $result = self::get($url, $param, $config);
  268. return $result;
  269. }
  270. //====================== 获取调用凭证===========================
  271. /**
  272. * 通用调用凭证获取
  273. * 默认使用token方式,使用签名方式需要传入参数
  274. */
  275. static public function getAuth($type = 'token', $param, $config)
  276. {
  277. if ($type === 'token') {
  278. return self::getAccessTokenByToken($config);
  279. }
  280. return self::getAccessTokenBySig($param, $config);
  281. }
  282. /**
  283. * 方式一,OPEN-ACCESS-TOKEN方式
  284. */
  285. static function getAccessTokenByToken($config)
  286. {
  287. $param = [
  288. 'appId' => $config['appid'],
  289. 'timestamp' => date('YmdHis'),
  290. 'nonce' => md5(uniqid(microtime(true),true)),
  291. 'signMethod' => self::$signMethod,
  292. ];
  293. $param['signature'] = self::signature($param, $config['appsecret']);
  294. $result = self::get(self::$token_url, $param, $config);
  295. if (isset($result['errCode']) && isset($result['accessToken'])) {
  296. return 'OPEN-ACCESS-TOKEN AccessToken='.$result['accessToken'];
  297. }
  298. return '';
  299. }
  300. /**
  301. * 方式二,OPEN-BODY-SIG方式
  302. */
  303. static function getAccessTokenBySig($data, $config)
  304. {
  305. $param = [
  306. 'AppId' => $config['appid'],
  307. 'Timestamp' => date('YmdHis'),
  308. 'Nonce' => md5(uniqid(microtime(true),true))
  309. ];
  310. return 'OPEN-BODY-SIG AppId="'.$param['AppId'].'", Timestamp="'.$param['Timestamp'].'", Nonce="'.$param['Nonce'].'", Signature="'.self::signature2($data, $param, $config['appsecret']).'"';
  311. }
  312. /**
  313. * 计算签名,方式一
  314. */
  315. static function signature($param, $appsecret)
  316. {
  317. return bin2hex(hash(self::$signMethod, $param['appId'].$param['timestamp'].$param['nonce'].$appsecret, true));
  318. }
  319. /**
  320. * 计算签名,方式二
  321. */
  322. static function signature2($data, $param, $appsecret)
  323. {
  324. $str = bin2hex(hash('sha256', Dever::json_encode($data), true));
  325. return base64_encode(hash_hmac('sha256', $param['AppId'].$param['Timestamp'].$param['Nonce'].$str, $appsecret, true));
  326. }
  327. /**
  328. * 获取信息
  329. */
  330. static function get($url, $param, $config)
  331. {
  332. $url = $config['box'] == 1 ? self::$host . $url : self::$test_host . $url;
  333. $header = array();
  334. $header['Authorization'] = self::getAuth('sig', $param, $config);
  335. $result = Dever::curl($url, $param, 'post', true, $header);
  336. if (strstr($result, '<html><head>')) {
  337. Dever::alert('系统错误');
  338. }
  339. $result = Dever::json_decode($result);
  340. print_r($param);
  341. print_r($result);die;
  342. if (isset($result['errCode'])) {
  343. if ($result['errCode'] == '0000') {
  344. return $result;
  345. } elseif (isset($result['errInfo'])) {
  346. Dever::alert($result['errInfo']);
  347. } elseif (isset($result['errMsg'])) {
  348. Dever::alert($result['errMsg']);
  349. }
  350. } else {
  351. Dever::alert('系统错误');
  352. }
  353. }
  354. }