PayService.php 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. <?php
  2. namespace app\service;
  3. use app\common\factory\Pay;
  4. use app\common\library\WeixinPay;
  5. use think\Config;
  6. use think\Env;
  7. use think\Exception;
  8. class PayService
  9. {
  10. /**
  11. * 支付宝扫码 (官方支付宝扫码)
  12. * @param $orderid
  13. * @param $real_amount
  14. * @param $productname
  15. * @param $productdesc
  16. */
  17. public function chargeByZfbWap($orderid, $real_amount, $productname, $productdesc = '', $notify_url = '')
  18. {
  19. $config = Config::get('ali_pay_config')['configs'][Config::get('ali_pay_config')['default']['zfb']];
  20. vendor('alipayAop.AopSdk');
  21. $aop = new \AopClient();
  22. $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do"; //网关地址要使用沙箱网关alipaydev
  23. $aop->appId = $config['app_id'];
  24. $aop->rsaPrivateKey = $config['private_key'];
  25. $aop->alipayrsaPublicKey = $config['public_key'];
  26. $aop->format = "json";
  27. $aop->apiVersion = '1.0';
  28. $aop->postCharset = 'UTF-8';
  29. $aop->signType = Config::get('ali_pay_config')['sign_type'];
  30. //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
  31. $request = new \AlipayTradePagePayRequest();
  32. $productname = preg_replace("/[\&\+]+/", '', $productname); // 主题(过滤特殊字符)
  33. $subject = preg_replace("/[\&\+]+/", '', $productdesc); // 商品描述信息(过滤特殊字符)
  34. //SDK已经封装掉了公共参数,这里只需要传入业务参数
  35. $info = json_encode(['body' => $subject, 'subject' => $productname, 'out_trade_no' => $orderid,
  36. 'timeout_express' => '30m', 'total_amount' => $real_amount, 'product_code' => 'FAST_INSTANT_TRADE_PAY'], JSON_UNESCAPED_UNICODE);
  37. $request->setBizContent($info);
  38. // $request->setReturnUrl("http://" . $_SERVER['HTTP_HOST'] . "/v1.user_center/returnUrl.html");
  39. // $request->setNotifyUrl("http://" . $_SERVER['HTTP_HOST'] . "/v1.platform_pay/notify.html");
  40. $request->setNotifyUrl($notify_url);
  41. $result = $aop->pageExecute($request);
  42. return $result;
  43. }
  44. /**
  45. * 支付宝APP/扫码(官方支付宝快捷支付)
  46. *
  47. * @param string $orderid 订单号
  48. * @param float $real_amount 支付金额
  49. * @param string $productname 商品名称
  50. * @param string $productdesc 描述
  51. * @param string $notify_url 回调地址
  52. *
  53. * @return string 支付参数字符串
  54. */
  55. public function getAlipayAopParam($orderid, $real_amount, $productname, $productdesc = '', $notify_url = '')
  56. {
  57. $config = Config::get('ali_pay_config')['configs'][Config::get('ali_pay_config')['default']['zfb']];
  58. //Alipay Aop Sdk支付发起
  59. vendor('alipayAop.AopSdk');
  60. $aop = new \AopClient();
  61. $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
  62. $aop->appId = $config['app_id'];
  63. $aop->rsaPrivateKey = $config['private_key'];
  64. $aop->alipayrsaPublicKey = $config['public_key'];
  65. $aop->apiVersion = '1.0';
  66. $aop->signType = Config::get('ali_pay_config')['sign_type'];
  67. $aop->postCharset = 'utf-8';
  68. $aop->format = 'json';
  69. $request = new \AlipayTradeAppPayRequest();
  70. $bizcontent = array();
  71. $bizcontent['subject'] = preg_replace("/[\&\+]+/", '', $productname); // 主题(过滤特殊字符)
  72. $bizcontent['body'] = preg_replace("/[\&\+]+/", '', $productdesc); // 商品描述信息(过滤特殊字符)
  73. $bizcontent['out_trade_no'] = $orderid; // 订单号
  74. $bizcontent['timeout_express'] = '30m'; // 超时时间
  75. $bizcontent['total_amount'] = $real_amount; // 支付金额
  76. $bizcontent['product_code'] = 'QUICK_MSECURITY_PAY'; // 支付方式
  77. $request->setBizContent(json_encode($bizcontent));
  78. $request->setNotifyUrl($notify_url);
  79. $result = $aop->sdkExecute($request);
  80. // echo htmlspecialchars($result);
  81. // return ['error' => true, 'msg' => '支付方式发起下单异常!'];
  82. return ['error' => false, 'data' => $result];
  83. }
  84. /**
  85. * 支付宝 h5(官方支付宝h5支付)
  86. * @param $orderid
  87. * @param $real_amount
  88. * @param $productname
  89. * @param string $productdesc
  90. * @return string|\提交表单HTML文本|\构建好的、签名后的最终跳转URL(GET)或String形式的form(POST)
  91. * @throws \Exception
  92. */
  93. public function getAlipayWapAopParam($orderid, $real_amount, $productname, $productdesc = '', $notify_url = '')
  94. {
  95. //Alipay Aop Sdk支付发起
  96. vendor('alipayAop.AopSdk');
  97. $aop = new \AopClient();
  98. $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
  99. $aop->appId = Config::get('alipayAop')['appId'];
  100. $aop->rsaPrivateKey = file_get_contents(Config::get('alipayAop')['private_key']);
  101. $aop->alipayrsaPublicKey = file_get_contents(Config::get('alipayAop')['alipay_public_key']);
  102. $aop->apiVersion = '1.0';
  103. $aop->signType = Config::get('alipayAop')['sign_type'];
  104. $aop->postCharset = 'utf-8';
  105. $aop->format = 'json';
  106. $request = new \AlipayTradeWapPayRequest();
  107. $bizcontent = array();
  108. $bizcontent['subject'] = preg_replace("/[\&\+]+/", '', $productname); // 主题(过滤特殊字符)
  109. $bizcontent['body'] = preg_replace("/[\&\+]+/", '', $productdesc); // 商品描述信息(过滤特殊字符)
  110. $bizcontent['out_trade_no'] = $orderid; // 订单号
  111. $bizcontent['timeout_express'] = '30m'; // 超时时间
  112. $bizcontent['total_amount'] = $real_amount; // 支付金额
  113. $bizcontent['product_code'] = 'QUICK_MSECURITY_PAY'; // 支付方式
  114. $request->setBizContent(json_encode($bizcontent));
  115. $request->setNotifyUrl($notify_url);
  116. $result = $aop->pageExecute($request, "GET");
  117. // echo htmlspecialchars($result);
  118. return $result;
  119. }
  120. /**
  121. * 支付宝 h5(官方支付宝h5支付)带referer
  122. * @param $orderid
  123. * @param $real_amount
  124. * @param $productname
  125. * @param string $productdesc
  126. * @return array
  127. * @throws \Exception
  128. */
  129. public function getAlipayWapPostAopParam($orderid, $real_amount, $productname, $productdesc = '', $notify_url = '', $httpType = "POST")
  130. {
  131. $config = Config::get('ali_pay_config')['configs'][Config::get('ali_pay_config')['default']['old-zfb-wap']];
  132. //Alipay Aop Sdk支付发起
  133. vendor('alipayAop.AopSdk');
  134. $aop = new \AopClient();
  135. $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
  136. $aop->appId = $config['app_id'];
  137. $aop->rsaPrivateKey = $config['private_key'];
  138. $aop->alipayrsaPublicKey = $config['public_key'];
  139. $aop->apiVersion = '1.0';
  140. $aop->signType = Config::get('ali_pay_config')['sign_type'];
  141. $aop->postCharset = 'utf-8';
  142. $aop->format = 'json';
  143. $request = new \AlipayTradeWapPayRequest();
  144. $bizcontent = array();
  145. $bizcontent['subject'] = preg_replace("/[\&\+]+/", '', $productname); // 主题(过滤特殊字符)
  146. $bizcontent['body'] = preg_replace("/[\&\+]+/", '', $productdesc); // 商品描述信息(过滤特殊字符)
  147. $bizcontent['out_trade_no'] = $orderid; // 订单号
  148. $bizcontent['timeout_express'] = '30m'; // 超时时间
  149. $bizcontent['total_amount'] = $real_amount; // 支付金额
  150. $bizcontent['product_code'] = 'QUICK_MSECURITY_PAY'; // 支付方式
  151. $request->setBizContent(json_encode($bizcontent));
  152. $request->setNotifyUrl($notify_url);
  153. $result = $aop->pageExecute($request, $httpType);
  154. // echo htmlspecialchars($result);
  155. $pay_return['mweb_url'] = $result;
  156. $pay_return['referer'] = "com.yiyou.zfb";
  157. // return ['error' => true, 'msg' => '支付方式发起下单异常!'];
  158. return ['error' => false, 'data' => $pay_return];
  159. }
  160. /**
  161. * 第三方现金支付 支付宝 h5 (现在支付)
  162. * @return string
  163. */
  164. public function chargeByxzzfbzf($orderid, $real_amount, $productname, $productdesc = '', $notify_url = '')
  165. {
  166. $productdesc = "订单支付";
  167. $productname = preg_replace("/[\&\+]+/", '', $productname); // 主题(过滤特殊字符)
  168. $subject = preg_replace("/[\&\+]+/", '', $productdesc); // 商品描述信息(过滤特殊字符)
  169. $consumerCreateIp = $this->getUserIp(); //需上传用户真实ip
  170. $key = Config::get('h5_alipay_config')['key'];
  171. $req = array();
  172. $req["appId"] = Config::get('h5_alipay_config')['zfbAppId'];
  173. $req["deviceType"] = '0601'; //h5支付 0601 扫码 04
  174. $req["frontNotifyUrl"] = Config::get('h5_alipay_config')['return_url'];;//'http://sdkapi.46yx.com/v1.demo/zfbalipays.html';//前台通知,三方支付宝0模式有效,官方支付宝0、1模式有效,微信0模式有效
  175. $req["funcode"] = 'WP001';
  176. $req["mhtCharset"] = 'UTF-8';
  177. $req["mhtCurrencyType"] = '156';
  178. $req["mhtOrderAmt"] = $real_amount * 100;
  179. $req["mhtOrderDetail"] = $subject;
  180. $req["mhtOrderName"] = $productname;
  181. $req["mhtOrderNo"] = $orderid;
  182. $req["mhtOrderStartTime"] = date("YmdHis");
  183. $req["mhtOrderTimeOut"] = '3600';
  184. $req["mhtOrderType"] = '01';
  185. $req["mhtReserved"] = "test";
  186. $req["mhtSignType"] = 'MD5';
  187. $req["notifyUrl"] = $notify_url;
  188. $req["outputType"] = 1; // 0 默认值
  189. $req["payChannelType"] = 12; //12 支付宝 //13 微信 //20 银联 //25 手Q
  190. $req["version"] = "1.0.0";
  191. $req["consumerCreateIp"] = $consumerCreateIp; //微信必填// outputType=2时 无须上送该值
  192. $req_str = $this->getToStr($req, $key);
  193. $service = 'https://pay.ipaynow.cn';
  194. $res = $this->xzzfbzfpost($service, $req_str);
  195. $code = (bool)stripos($res, '&tn=');
  196. if ($code) {
  197. $arr = explode('&', $res);
  198. $gettn = '';
  199. foreach ($arr as $v) {
  200. $tn = explode('=', $v);
  201. if ($tn[0] == 'tn') {
  202. $gettn = $tn[1];
  203. }
  204. }
  205. $tn = urldecode($gettn);
  206. $pay_return['mweb_url'] = $tn;
  207. $pay_return['referer'] = 'com.yiyou.zfb';
  208. return $pay_return;
  209. // return $tn;
  210. } else {
  211. return false;
  212. }
  213. }
  214. /**
  215. * 第三方现金支付 支付宝 h5 (现在支付)
  216. * @return string
  217. */
  218. public function chargeByxzzfsmf($orderid, $real_amount, $productname, $productdesc = '', $notify_url = '')
  219. {
  220. $productdesc = "订单支付";
  221. $productname = preg_replace("/[\&\+]+/", '', $productname); // 主题(过滤特殊字符)
  222. $subject = preg_replace("/[\&\+]+/", '', $productdesc); // 商品描述信息(过滤特殊字符)
  223. $consumerCreateIp = $this->getUserIp(); //需上传用户真实ip
  224. $key = Config::get('h5_alipay_config')['key'];
  225. $req = array();
  226. $req["appId"] = Config::get('h5_alipay_config')['zfbAppId'];
  227. $req["deviceType"] = '04'; //h5支付 0601 扫码 04
  228. $req["frontNotifyUrl"] = Config::get('h5_alipay_config')['return_url'];//'http://sdkapi.46yx.com/v1.demo/zfbalipays.html';//前台通知,三方支付宝0模式有效,官方支付宝0、1模式有效,微信0模式有效
  229. $req["funcode"] = 'WP001';
  230. $req["mhtCharset"] = 'UTF-8';
  231. $req["mhtCurrencyType"] = '156';
  232. $req["mhtOrderAmt"] = $real_amount * 100;
  233. $req["mhtOrderDetail"] = $subject;
  234. $req["mhtOrderName"] = $productname;
  235. $req["mhtOrderNo"] = $orderid;
  236. $req["mhtOrderStartTime"] = date("YmdHis");
  237. $req["mhtOrderTimeOut"] = '3600';
  238. $req["mhtOrderType"] = '01';
  239. $req["mhtReserved"] = "test";
  240. $req["mhtSignType"] = 'MD5';
  241. $req["notifyUrl"] = $notify_url;
  242. $req["outputType"] = 1; // 0 默认值
  243. $req["payChannelType"] = 12; //12 支付宝 //13 微信 //20 银联 //25 手Q
  244. $req["version"] = "1.0.0";
  245. $req["consumerCreateIp"] = $consumerCreateIp; //微信必填// outputType=2时 无须上送该值
  246. $req_str = $this->getToStr($req, $key);
  247. $service = 'https://pay.ipaynow.cn';
  248. $res = $this->xzzfbzfpost($service, $req_str);
  249. $code = (bool)stripos($res, '&tn=');
  250. if ($code) {
  251. $arr = explode('&', $res);
  252. $gettn = '';
  253. foreach ($arr as $v) {
  254. $tn = explode('=', $v);
  255. if ($tn[0] == 'tn') {
  256. $gettn = $tn[1];
  257. }
  258. }
  259. $tn = urldecode($gettn);
  260. $pay_return['mweb_url'] = $tn;
  261. $pay_return['referer'] = 'com.yiyou.zfb';
  262. return $pay_return;
  263. // return $tn;
  264. } else {
  265. return false;
  266. }
  267. }
  268. /**
  269. * 获取现在支付参数
  270. *
  271. * @param string $orderid 订单号
  272. * @param float $real_amount 支付金额
  273. * @param string $productname 商品名称
  274. *
  275. * @return array 支付参数数组
  276. */
  277. public function getIpaynowParam($orderid, $real_amount, $productname, $notify_url = '')
  278. {
  279. $ipay['mhtOrderNo'] = $orderid; // 商户订单号
  280. $ipay['appId'] = Config::get('ipaynow')['appid']; // 商户应用唯一标识
  281. $ipay['mhtOrderAmt'] = $real_amount * 100; // 支付金额,以分为单位
  282. $ipay['notifyUrl'] = $notify_url; // 回调地址
  283. $ipay['funcode'] = 'WP001';
  284. $ipay['version'] = '1.0.0';
  285. $ipay["payChannelType"] = "13";
  286. $ipay["mhtOrderName"] = $productname;
  287. $ipay["mhtOrderType"] = "01";
  288. $ipay["mhtCurrencyType"] = '156';
  289. $ipay["mhtOrderStartTime"] = date('YmdHis');
  290. $ipay['mhtCharset'] = "UTF-8";
  291. $ipay['deviceType'] = "01";
  292. $ipay['mhtOrderDetail'] = $productname;
  293. $ipay['mhtSignType'] = 'MD5';
  294. ksort($ipay); //按key升序排列
  295. reset($ipay);
  296. //拼接待签名字符串
  297. $arg = "";
  298. while (list ($key, $val) = each($ipay)) {
  299. $arg .= $key . "=" . $val . "&";
  300. }
  301. //如果存在转义字符,那么去掉转义
  302. if (get_magic_quotes_gpc()) {
  303. $arg = stripslashes($arg);
  304. }
  305. //生成签名
  306. $mhtSignature = md5($arg . md5(Config::get('ipaynow')['key']));
  307. return $arg . 'mhtSignature=' . $mhtSignature;
  308. }
  309. /**
  310. * 汇付宝 微信扫码支付
  311. * @param $orderid
  312. * @param $real_amount
  313. * @param $productname
  314. * @param string $productdesc
  315. * @return mixed|string
  316. */
  317. public function getWxWapsmPostAopParam($orderid, $real_amount, $productname, $productdesc = '', $user_ip = '127.0.0.1', $notify_url = '')
  318. {
  319. //获取用户IP
  320. $user_ip = $user_ip;
  321. $version = "1";
  322. $agent_id = Config::get('wxwappay-h5')['mch_id']; //商户编号,(汇付宝商户内码:七位整数数字)
  323. $sign_key = Config::get('wxwappay-h5')['key'];
  324. // $notify_url = $notify_url;//支付后返回的商户处理页面,URL参数是以http://或https://开头的完整URL地址(后台处理),提交的url地址必须外网能访问到,否则无法通知商户。值可以为空,但不可以为null。
  325. $scene = "qr"; //支付方式,h5表示h5,qr表示扫码(如支付类型为扫码,payment_mode传UnifiedOrder返回二维码url),jsapi表示公众号(微信内拉起),app表示app拉起支付(值均为小写)
  326. $pay_type = "30"; //支付类型30
  327. $agent_bill_id = $orderid; //商户系统内部的订单号(要保证唯一)
  328. $agent_bill_time = date('YmdHis', time()); //提交单据的时间yyyyMMddHHmmss,该参数共计14位,当时不满14位时,在后面加0补足14位
  329. $pay_amt = $real_amount; //订单总金额 不可为空。小数点后保留两位
  330. $return_url = Config::get('wxwappay-h5')['return_url'] . "?URLscheme=yiyouweixin";//支付后返回的商户显示页面,URL参数是以http://或https://开头的完整URL地址(前台显示),原则上该参数与notify_url提交的参数不一致。值可以为空,但不可以为null。
  331. $user_ip = str_replace(".", "_", $user_ip); //用户所在客户端的真实ip其中的“.”替换为“_” 。因为近期我方发现用户在提交数据时,user_ip在网络层被篡改,导致签名错误,所以我们规定使用这种格式。
  332. $goods_name = $productname; //商品名称,不能为空(不参加签名)
  333. $goods_name = iconv("UTF-8", "gbk", $goods_name);
  334. $remark = "";//商户自定义,原样返回,可以为空。
  335. $goods_note = "";
  336. $payment_mode = "cashier";//收银台=cashier,接口=UnifiedOrder(目前支持扫码,app)
  337. $n = "南京麻花网络";
  338. $fileName = iconv("UTF-8", "gbk", $n);
  339. $strs = '{"s":"WAP","n":"' . $fileName . '","id":"http://46yx.com"}';
  340. $str = base64_encode($strs);
  341. $meta_option = urlencode($str);//加密后的结果
  342. $bank_card_type = "-1"; //银行类型:未知=-1,储蓄卡=0,信用卡=1。
  343. $timestamp = ""; //时间戳,传了订单有效时间上下1min,从1970年1月1日0时到现在的毫秒数,传了参与签名,签名位置在key前面。
  344. $sign_type = "MD5"; //签名类型,MD5\RSA\RSA2
  345. $data['version'] = $version;
  346. $data['scene'] = $scene;
  347. $data['payment_mode'] = $payment_mode;
  348. $data['agent_id'] = $agent_id;
  349. $data['agent_bill_id'] = $agent_bill_id;
  350. $data['agent_bill_time'] = $agent_bill_time;
  351. $data['pay_type'] = $pay_type;
  352. $data['pay_amt'] = $pay_amt;
  353. $data['notify_url'] = $notify_url;
  354. $data['return_url'] = $return_url;
  355. $data['user_ip'] = $user_ip;
  356. $data['goods_name'] = $goods_name;
  357. $data['goods_note'] = $goods_note;
  358. $data['remark'] = $remark;
  359. $data['meta_option'] = $meta_option;
  360. $data['bank_card_type'] = $bank_card_type;
  361. $sign_str = '';
  362. $sign_str = $sign_str . 'version=' . $version;
  363. $sign_str = $sign_str . '&agent_id=' . $agent_id;
  364. $sign_str = $sign_str . '&agent_bill_id=' . $agent_bill_id;
  365. $sign_str = $sign_str . '&agent_bill_time=' . $agent_bill_time;
  366. $sign_str = $sign_str . '&pay_type=' . $pay_type;
  367. $sign_str = $sign_str . '&pay_amt=' . $pay_amt;
  368. $sign_str = $sign_str . '&notify_url=' . $notify_url;
  369. $sign_str = $sign_str . '&return_url=' . $return_url;
  370. $sign_str = $sign_str . '&user_ip=' . $user_ip;
  371. $sign_str = $sign_str . '&bank_card_type=' . $bank_card_type;
  372. $sign_str = $sign_str . '&remark=' . urlencode($remark);
  373. $sign_str = $sign_str . '&key=' . $sign_key;
  374. $sign = md5($sign_str); ////MD5\RSA\RSA2签名结果
  375. $data['sign'] = $sign;
  376. $urls = Config::get('wxwappay-h5')['pay_url'];
  377. $response = $this->postXmlCurl($data, $urls);
  378. $redirectUrl = "";
  379. if (!empty($response)) {
  380. if ($response['ret_code'] == '0000') {
  381. $redirectUrl = $response['redirectUrl'];
  382. $ret_code = $response['ret_code'];
  383. $ret_msg = $response['ret_msg'];
  384. $hf_sign = md5('redirectUrl=' . $redirectUrl . '&ret_code=' . $ret_code . '&ret_msg=' . $ret_msg . '&key=' . $sign_key);
  385. if ($hf_sign != $response['sign']) {
  386. return false;
  387. }
  388. } else {
  389. return false;
  390. }
  391. } else {
  392. return false;
  393. }
  394. $pay_return['mweb_url'] = $redirectUrl;
  395. $pay_return['referer'] = Config::get('wxpay-h5')['referer'];
  396. return $pay_return;
  397. }
  398. /**
  399. * 汇付宝 微信H5支付
  400. * @param $orderid
  401. * @param $real_amount
  402. * @param $productname
  403. * @param string $productdesc
  404. * @return mixed|string
  405. */
  406. public function getWxWapPostAopParam($orderid, $real_amount, $productname, $productdesc = '', $user_ip = '127.0.0.1', $notify_url = '')
  407. {
  408. //获取用户IP
  409. $user_ip = $user_ip;
  410. $version = "1";
  411. $agent_id = Config::get('wxwappay-h5')['mch_id']; //商户编号,(汇付宝商户内码:七位整数数字)
  412. $sign_key = Config::get('wxwappay-h5')['key'];
  413. // $notify_url = $notify_url;//支付后返回的商户处理页面,URL参数是以http://或https://开头的完整URL地址(后台处理),提交的url地址必须外网能访问到,否则无法通知商户。值可以为空,但不可以为null。
  414. $scene = "h5"; //支付方式,h5表示h5,qr表示扫码(如支付类型为扫码,payment_mode传UnifiedOrder返回二维码url),jsapi表示公众号(微信内拉起),app表示app拉起支付(值均为小写)
  415. $pay_type = "30"; //支付类型30
  416. $agent_bill_id = $orderid; //商户系统内部的订单号(要保证唯一)
  417. $agent_bill_time = date('YmdHis', time()); //提交单据的时间yyyyMMddHHmmss,该参数共计14位,当时不满14位时,在后面加0补足14位
  418. $pay_amt = $real_amount; //订单总金额 不可为空。小数点后保留两位
  419. $return_url = Config::get('wxwappay-h5')['return_url'] . "?URLscheme=yiyouweixin";//支付后返回的商户显示页面,URL参数是以http://或https://开头的完整URL地址(前台显示),原则上该参数与notify_url提交的参数不一致。值可以为空,但不可以为null。
  420. $user_ip = str_replace(".", "_", $user_ip); //用户所在客户端的真实ip其中的“.”替换为“_” 。因为近期我方发现用户在提交数据时,user_ip在网络层被篡改,导致签名错误,所以我们规定使用这种格式。
  421. $productname = iconv("UTF-8", "gbk", $productname);
  422. $goods_name = $productname;//商品名称,不能为空(不参加签名)
  423. $remark = ""; //商户自定义,原样返回,可以为空。
  424. $goods_note = "";
  425. $payment_mode = "cashier";//收银台=cashier,接口=UnifiedOrder(目前支持扫码,app)
  426. $n = "南京麻花网络";
  427. $fileName = iconv("UTF-8", "gbk", $n);
  428. $strs = '{"s":"WAP","n":"' . $fileName . '","id":"http://46yx.com"}';
  429. $str = base64_encode($strs);
  430. $meta_option = urlencode($str);//加密后的结果
  431. $bank_card_type = "-1"; //银行类型:未知=-1,储蓄卡=0,信用卡=1。
  432. $timestamp = ""; //时间戳,传了订单有效时间上下1min,从1970年1月1日0时到现在的毫秒数,传了参与签名,签名位置在key前面。
  433. $sign_type = "MD5"; //签名类型,MD5\RSA\RSA2
  434. $data['version'] = $version;
  435. $data['scene'] = $scene;
  436. $data['payment_mode'] = $payment_mode;
  437. $data['agent_id'] = $agent_id;
  438. $data['agent_bill_id'] = $agent_bill_id;
  439. $data['agent_bill_time'] = $agent_bill_time;
  440. $data['pay_type'] = $pay_type;
  441. $data['pay_amt'] = $pay_amt;
  442. $data['notify_url'] = $notify_url;
  443. $data['return_url'] = $return_url;
  444. $data['user_ip'] = $user_ip;
  445. $data['goods_name'] = $goods_name;
  446. $data['goods_note'] = $goods_note;
  447. $data['remark'] = $remark;
  448. $data['meta_option'] = $meta_option;
  449. $data['bank_card_type'] = $bank_card_type;
  450. $sign_str = '';
  451. $sign_str = $sign_str . 'version=' . $version;
  452. $sign_str = $sign_str . '&agent_id=' . $agent_id;
  453. $sign_str = $sign_str . '&agent_bill_id=' . $agent_bill_id;
  454. $sign_str = $sign_str . '&agent_bill_time=' . $agent_bill_time;
  455. $sign_str = $sign_str . '&pay_type=' . $pay_type;
  456. $sign_str = $sign_str . '&pay_amt=' . $pay_amt;
  457. $sign_str = $sign_str . '&notify_url=' . $notify_url;
  458. $sign_str = $sign_str . '&return_url=' . $return_url;
  459. $sign_str = $sign_str . '&user_ip=' . $user_ip;
  460. $sign_str = $sign_str . '&bank_card_type=' . $bank_card_type;
  461. $sign_str = $sign_str . '&remark=' . urlencode($remark);
  462. $sign_str = $sign_str . '&key=' . $sign_key;
  463. $sign = md5($sign_str); ////MD5\RSA\RSA2签名结果
  464. $data['sign'] = $sign;
  465. $urls = Config::get('wxwappay-h5')['pay_url'];
  466. $response = $this->postXmlCurl($data, $urls);
  467. $redirectUrl = "";
  468. if (!empty($response)) {
  469. if ($response['ret_code'] == '0000') {
  470. $redirectUrl = $response['redirectUrl'];
  471. $ret_code = $response['ret_code'];
  472. $ret_msg = $response['ret_msg'];
  473. $hf_sign = md5('redirectUrl=' . $redirectUrl . '&ret_code=' . $ret_code . '&ret_msg=' . $ret_msg . '&key=' . $sign_key);
  474. if ($hf_sign != $response['sign']) {
  475. return false;
  476. }
  477. } else {
  478. return false;
  479. }
  480. } else {
  481. return false;
  482. }
  483. $pay_return['mweb_url'] = $redirectUrl;
  484. $pay_return['referer'] = Config::get('wxpay-h5')['referer'];
  485. return $pay_return;
  486. }
  487. /**
  488. * 微信官方h5支付
  489. *
  490. * @param string $orderid 订单号
  491. * @param float $real_amount 支付金额
  492. * @param string $body 商品名称
  493. *
  494. * @return array 支付参数数组
  495. */
  496. public function getWxpayH5Param($orderid, $real_amount, $body, $ip = '', $notify_url = '', $gameid='')
  497. {
  498. $pay_return = false;
  499. $body = '充值'; // 防止商品名展示游戏信息,统一为充值。
  500. $wap_url = 'http://' . HTTP_HOST_URL; // 支付成功后打开的网址跳回游戏
  501. if ($gameid) {
  502. $wap_url .= '?gameid=' . $gameid;
  503. }
  504. $wxPay = new WeixinPay();
  505. // $params['appid'] = Config::get('wxpay-h5')['app_id'];
  506. // $params['mch_id'] = Config::get('wxpay-h5')['mch_id'];
  507. $params['appid'] = 'wxf6d1543cec2dfa53';
  508. $params['mch_id'] = '1675127018';
  509. $params['sub_mch_id'] = '1726067763';
  510. $params['nonce_str'] = random(10);
  511. $params['body'] = $body;
  512. $params['out_trade_no'] = $orderid;
  513. $params['total_fee'] = $real_amount * 100; // 支付金额,以分为单位
  514. $params['spbill_create_ip'] = $_SERVER['REMOTE_ADDR'] ?? request()->ip();
  515. $params['notify_url'] = $notify_url;
  516. $params['trade_type'] = 'MWEB';
  517. // $params['scene_info'] = '{"h5_info":{"type":"Wap","wap_url":"'.$wap_url.'","wap_name":"祈盟"}}';
  518. $params['scene_info'] = '{"h5_info":{"type":"Wap","wap_url":"http://devsdkapi.youxi9.com","wap_name":"祈盟"}}';
  519. //获取签名数据
  520. // $params['sign'] = $wxPay->MakeSign($params, Config::get('wxpay-h5')['key']);
  521. $params['sign'] = $wxPay->MakeSign($params, '66052a198653943dbc6c8032f1a40a9c');
  522. $xml = dataToXml($params);
  523. $response = $wxPay->postXmlCurl($xml, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
  524. $result = $wxPay->xmlToArray($response);
  525. if ($result['return_code'] != 'SUCCESS') {
  526. return ['error' => true, 'msg' => $result['return_msg']];
  527. }
  528. // dump($result);
  529. if (array_key_exists("return_code", $result) && $result["return_code"] == "SUCCESS" && array_key_exists("result_code", $result) && $result["result_code"] == "SUCCESS") {
  530. $pay_return['order_id'] = $orderid;
  531. $pay_return['prepay_id'] = $result['prepay_id'];
  532. $pay_return['trade_type'] = $result['trade_type'];
  533. // $pay_return['mweb_url'] = 'http://sdkapi.' . QM_DOMAIN_URL . '/jump?key=' . base64_encode($result['mweb_url']);
  534. // $pay_return['mweb_url'] = 'http://sdkapi.' . QM_DOMAIN_URL . '/pay?orderid='.$orderid.'&payurl='.$result['mweb_url'];
  535. // $pay_return['mweb_url'] = 'https://devsdkapi.qmgames.cn/pay?orderid='.$orderid.'&payurl='.$result['mweb_url'];
  536. // $pay_return['mweb_url'] = 'http://devsdkapi.youxi9.com/pay?orderid='.$orderid.'&payurl='.$result['mweb_url'];
  537. $pay_return['mweb_url'] = $result['mweb_url'];
  538. // if (strpos($_SERVER['HTTP_USER_AGENT'],"Darwin") > -1) {
  539. // } else {
  540. // $pay_return['mweb_url'] = $result['mweb_url'];
  541. // }
  542. $pay_return['referer'] = Config::get('wxpay-h5')['referer'];
  543. } else {
  544. return ['error' => true, 'msg' => '支付方式发起下单异常!'];
  545. }
  546. return ['error' => false, 'data' => $pay_return];
  547. }
  548. /**
  549. * 酷点微信h5支付
  550. *
  551. * @param string $orderid 订单号
  552. * @param float $real_amount 支付金额
  553. * @param string $body 商品名称
  554. *
  555. * @return array 支付参数数组
  556. */
  557. public function getkdh5weixinParam($orderid, $real_amount, $body, $notify_url = '')
  558. {
  559. $pay_return = false;
  560. vendor('kdpaySdk.des');
  561. $kdh5pay = new \kdpay();
  562. $return_url = Config::get('kdh5')['return_url'] . "?orderid=" . $orderid;
  563. // $notify_url = Config::get('kdh5')['notify_url'];
  564. log_message('打印2:' . $return_url, 'log', LOG_PATH . 'apilog/');
  565. $response = $kdh5pay->oil_fee_jsapi_get($body, $orderid, $real_amount, $return_url, $notify_url);
  566. if (!$response) {
  567. return false;
  568. }
  569. $result = $response;
  570. $pay_return['mweb_url'] = $result;
  571. $pay_return['referer'] = Config::get('kdh5')['referer'];
  572. return $pay_return;
  573. }
  574. public function getkdsmweixinParam($orderid, $real_amount, $body, $notify_url = '')
  575. {
  576. $pay_return = false;
  577. vendor('kdpaySdk.des');
  578. $kdh5pay = new \kdpay();
  579. $return_url = Config::get('kdh5')['return_url'] . "?orderid=" . $orderid;
  580. // $notify_url = Config::get('kdh5')['notify_url'];
  581. log_message('打印2:' . $return_url, 'log', LOG_PATH . 'apilog/');
  582. $response = $kdh5pay->oil_fee_sm_get($body, $orderid, $real_amount, $return_url, $notify_url);
  583. if (!$response) {
  584. return false;
  585. }
  586. $result = $response;
  587. $pay_return['mweb_url'] = $result;
  588. $pay_return['referer'] = Config::get('kdh5')['referer'];
  589. return $pay_return;
  590. }
  591. /**
  592. * TODO: 全民付 h5
  593. * @param $orderid
  594. * @param $real_amount
  595. * @param $productname
  596. * @param string $productdesc
  597. * @return string 发起跳转的URL
  598. * @throws \Exception
  599. */
  600. public function getQmfWapH5Param($paytype, $orderid, $real_amount, $productname, $productdesc = '', $notify_url = '')
  601. {
  602. /**
  603. * https://test-api-open.chinaums.com/v1/netpay/trade/h5-pay
  604. * ?appId=10037ca75e6125aa015e9e12a89b001b
  605. * &timestamp=20170606135700
  606. * &nonce=99930a147f5353dd8a8f29a5329f37e9
  607. * &content={"requestTimestamp":"2018-06-14 14:31:36","sign":"88FDA8C5105C6F1091BD3EA7CDDBEFC9","mid":"898201612345678","subOrders":[{"mid":"988460101800202","totalAmount":1},{"mid":"988460101800203","totalAmount":1}],"tid%22:"88880001","instMid":"YUEDANDEFAULT","platformAmount":"1"%2C"srcReserve":"reserve","totalAmount":"3","limitCreditCard":%22","divisionFlag":"true","notifyUrl":"https://qrtest2.chinaums.com/netpayportal/test/notifyUrl.do","returnUrl":"https://qrtest2.chinaums.com/netpayportal/test/returnUrl.do","merOrderId":"1000201806141434075636511"}
  608. * &signature=IPmdGHYCcfN+mto0/02ZkwoUf1NT3YqPKaUyKMaec1I
  609. */
  610. $config = Config::get('qmf_pay');
  611. $paytypes = mb_substr($paytype, 4);
  612. $api_url = $config['api_url'][$paytypes];
  613. $content = json_encode([
  614. "requestTimestamp" => date("Y-m-d H:i:s", time()),
  615. "merOrderId" => $orderid, // 商户订单号
  616. // "srcReserve" => "xxxx", // 预留参数
  617. "mid" => "xxxx", // 商户号
  618. "tid" => "xxxx", // 终端号
  619. "instMid" => "xxxx", // 业务类型
  620. "totalAmount" => formatYuanToFen($real_amount), // 支付总金额(分)
  621. "notifyUrl" => $config['notify_url'],
  622. ]);
  623. $result = [
  624. "authorization" => "OPEN-FORM-PARAM",
  625. "appId" => "xxx",
  626. "timestamp" => date('YmdHis', time()), // yyyyMMddHHmmss
  627. "nonce" => random(32), // 随机数
  628. "content" => $content,
  629. ];
  630. $result["signature"] = $this->paySign($config['app_id'], $result['timestamp'], $result['nonce'], $content, $config['app_key']);
  631. // dump(http_build_query($result));
  632. return createRefererUrl($api_url, $result);
  633. }
  634. public function paySign($appid, $timestamp, $nonce, $content, $appkey){
  635. $hashCont = hash('sha256', $content);
  636. return base64_encode(hash_hmac("sha256", $appid.$timestamp.$nonce.$hashCont, $appkey));
  637. }
  638. /**
  639. * 易宝wxmp-h5
  640. *
  641. * @param $paytype 支付方式 1:支付宝 2:微信小程序 22:微信扫码 999 :小程序调试参数 41:微信H5小程序
  642. * @param string $orderid 订单号
  643. * @param $real_amount 订单金额
  644. * @param string $productname 商品名
  645. * @param $notify_url 支付成功回调地址
  646. *
  647. * @return array
  648. */
  649. public function getYbzfParam($paytype, $orderid, $real_amount, $productname, $notify_url = '')
  650. {
  651. $config = Config::get('ybzf_pay');
  652. // $order_type = $config['order_type'];
  653. // 判断支付方式是否存在
  654. if (!in_array($paytype, ['ybzf_wxmp_h5', 'coin-ybzf_wxmp_h5', 'mix-ybzf_wxmp_h5'])) {
  655. return ['error' => true, 'msg' => '支付方式有误!'];
  656. }
  657. $orderData = [
  658. 'pollingid' => $config['polling_id'], // 轮询ID
  659. 'orderno' => $orderid, // 订单号
  660. 'productname' => $productname, // 商品名
  661. 'productprice' => formatYuanToFen($real_amount), // 商品价格(单位:分)
  662. 'order_type' => 41, // 支付方式 = 微信H5跳小程序
  663. 'notifyurl' => $notify_url, // 支付成功回调地址
  664. 'returnurl' => $config['return_url'], // 页面回跳地址
  665. ];
  666. $res = get_http_response('https://pccp.everwings.online/matrix/getPollingPayInfo', $orderData, 'post');
  667. if (empty($res)) { // 一般是对方系统升级问题
  668. curlDD("易宝wxmp-h5 - 支付渠道异常,请迅速联系易宝平台!", Env::get('dingtalk.warning_url'));
  669. return ['error' => true, 'msg' => '支付平台下单异常.!'];
  670. }
  671. if ($res == 'error') {
  672. return ['error' => true, 'msg' => '支付方式平台异常..!'];
  673. }
  674. // if (in_array($order_type, [99])) {
  675. // $res = json_decode($res, true);
  676. // if ($res['code'] != '00000') {
  677. // return ['error' => true, 'msg' => '支付方式平台下单失败...!'];
  678. // }
  679. // }
  680. return ['error' => false, 'data' => ['mweb_url' => $res]];
  681. }
  682. /**
  683. * 联动优势-支付宝
  684. */
  685. public function getldysParam($data, $way)
  686. {
  687. return Pay::makePay('ldys_pay', $data, $way);
  688. }
  689. /**
  690. * 趣智连支付
  691. */
  692. public function getqzlParam($data, $way)
  693. {
  694. return Pay::makePay('qzl_pay', $data, $way);
  695. }
  696. /**
  697. * 优亿支付
  698. */
  699. public function getYyYbPayParam($data, $way)
  700. {
  701. return Pay::makePay('yyyb_pay', $data, $way);
  702. }
  703. /**
  704. * 喜钛游
  705. */
  706. public function getXtyPayParam($data, $way)
  707. {
  708. return Pay::makePay('xty_pay', $data, $way);
  709. }
  710. /**
  711. * 十一玩
  712. */
  713. public function getSywPayParam($data, $way)
  714. {
  715. return Pay::makePay('syw_pay', $data, $way);
  716. }
  717. //获取真实IP,可以根据实际情况自行获取
  718. function getUserIp()
  719. {
  720. return request()->ip();
  721. try {
  722. $info = getCurl('https://myip.ipip.net');
  723. if (!$info) {
  724. $info = file_get_contents('http://myip.ipip.net');
  725. }
  726. $ipstr = explode(':', $info);
  727. $ip = explode(' ', $ipstr[1]);
  728. return $ip[0];
  729. } catch (Exception $e) {
  730. return request()->ip();
  731. }
  732. }
  733. //获取请求参数串
  734. function getToStr($arr, $key)
  735. {
  736. $date = $this->getDate($arr);
  737. $info = $this->createSignaTure($arr, $key);
  738. $str = '';
  739. foreach ($date as $k => $v) {
  740. if ($v != '') {
  741. $str .= $k . '=' . urlencode($v) . '&';
  742. }
  743. }
  744. $str .= 'mhtSignature' . '=' . $info;
  745. log_message($str . "\r\n", 'log', LOG_PATH . '../paylog/');
  746. //file_put_contents('../baowen.log', $str."\r\n");
  747. return $str;
  748. }
  749. //获取参数
  750. function getDate($arr)
  751. {
  752. $result = array();
  753. $funcode = $arr['funcode'];
  754. foreach ($arr as $key => $value) {
  755. if (($funcode == 'WP001') && !($key == 'mhtSignature' || $key == 'signature')) {
  756. $result[$key] = $value;
  757. continue;
  758. }
  759. if (($funcode == 'N001' || $funcode == 'N002') && !($key == 'signature')) {
  760. $result[$key] = $value;
  761. continue;
  762. }
  763. if (($funcode == 'MQ002') && !($key == 'mhtSignature' || $key == 'signature')) {
  764. $result[$key] = $value;
  765. continue;
  766. }
  767. }
  768. return $result;
  769. }
  770. //获取签名
  771. function createSignaTure($arr, $key)
  772. {
  773. $date = $this->getDate($arr);
  774. ksort($date);
  775. $str = '';
  776. foreach ($date as $k => $v) {
  777. if ($v != '') {
  778. $str .= $k . '=' . $v . '&';
  779. }
  780. }
  781. $str .= strtolower(md5($key));
  782. return (strtolower(md5($str)));
  783. }
  784. public function xzzfbzfpost($url, $data)
  785. {
  786. $curl = curl_init(); // 启动一个CURL会话
  787. curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
  788. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
  789. //curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在
  790. curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
  791. //curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
  792. curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
  793. curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
  794. curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
  795. curl_setopt($curl, CURLOPT_TIMEOUT, 40); // 设置超时限制防止死循环
  796. curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
  797. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
  798. $tmpInfo = curl_exec($curl); // 执行操作
  799. log_message($tmpInfo, 'log', LOG_PATH . '../paylog/');
  800. // if (curl_errno($curl)) {
  801. // echo 'Errno'.curl_error($curl);
  802. // echo curl_errno($curl);//捕抓异常
  803. // }
  804. curl_close($curl); // 关闭CURL会话
  805. return $tmpInfo; // 返回数据
  806. }
  807. /**
  808. * 作用:以post方式提交xml到对应的接口url
  809. *
  810. * @param $xml string xml的报文内容
  811. * @param $second int 请求的超时时间
  812. *
  813. */
  814. public function postXmlCurl($post_data, $url = '', $second = 30)
  815. {
  816. if ($url == '') {
  817. $url = $this->url;
  818. }
  819. $ch = curl_init();
  820. curl_setopt($ch, CURLOPT_URL, $url);
  821. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  822. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  823. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  824. // post数据
  825. curl_setopt($ch, CURLOPT_POST, 1);
  826. // post的变量
  827. curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
  828. //执行请求
  829. $output = curl_exec($ch);
  830. //打印获得的数据
  831. $xml = $this->xmlToArray($output);
  832. return $xml;
  833. curl_close($ch);
  834. }
  835. /**
  836. * 将xml转为array
  837. * @param string $xml
  838. *
  839. * @return array
  840. */
  841. public function xmlToArray($xml)
  842. {
  843. if (!$xml) {
  844. return false;
  845. }
  846. $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
  847. return $data;
  848. }
  849. }