25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

307 lines
11 KiB

  1. <?php
  2. namespace common\util;
  3. /**
  4. * Class WxPayService
  5. * 微信交易接口调用核心
  6. * @package Base\Tool
  7. */
  8. class WeChatPay
  9. {
  10. public $unifiedOrderUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//统一下单API
  11. /************************web支付**************************************/
  12. /**
  13. * Function Description:去微信下单并获取返回
  14. * Function Name: unifiedOrderByOrderId
  15. * @param $params array
  16. * $order_id string 订单表 订单ID
  17. * $name string 产品名称
  18. * $total_fee int 总金额 单位分
  19. * $openid string 用户opendid
  20. * @return array
  21. *
  22. * @author nzf
  23. */
  24. public function unifiedOrderByOrderIdForWeChat($params)
  25. {
  26. $siteConfig = Util::getSiteConfig();
  27. if (empty($params['notify_url'])) {
  28. $params['notify_url'] = $siteConfig['notify_url'];
  29. }
  30. $data = array(
  31. 'name' => $params['name'],//名称
  32. 'order_id' => (string)$params['order_id'],//支付ID
  33. 'total_fee' => (string)$params['total_fee'] * 100,//总金
  34. 'notify_url' => $siteConfig['host_name'] . $params['notify_url'],//支付回调接口
  35. 'openid' => empty($params['openid']) ? '' : $params['openid'],//用户的OPENID
  36. );
  37. $getPrepayId = $this->unifiedOrderForWeChat($data);//统一下单API
  38. if ($getPrepayId['flag'] == false) {
  39. return $getPrepayId;
  40. }
  41. //设置成功返回的结果数
  42. $wxPayConfig = static::getAuthWeChatConfig();
  43. $return = array(
  44. 'appId' => $wxPayConfig['appid'],//微信�?放平台审核�?�过的应用APPID
  45. 'package' => 'prepay_id=' . $getPrepayId['data']['prepay_id'],//微信返回的支付交易会话ID
  46. 'nonceStr' => self::getNonceStr(),//随机字符�?
  47. 'signType' => 'MD5',
  48. 'timeStamp' => strval(time()),//当前时间�?
  49. );
  50. $return['paySign'] = self::getSign($return);
  51. return Util::returnArrSu('', array('payData' => $return, 'price' => $params['total_fee']));
  52. }
  53. /**
  54. * Function Description:统一下单API
  55. * Function Name: unifiedOrder
  56. * @param $params array
  57. * attach 附加数据,在查询API和支付知中原样返回,该字段主要用于商户携带订单的自定义数
  58. * line_name 线路名称
  59. * order_id 订单ID
  60. * total_fee 总金
  61. * notify_url 回调地址
  62. *
  63. * @return array
  64. *
  65. * @author nzf
  66. */
  67. public function unifiedOrderForWeChat($params)
  68. {
  69. $wxPayConfig = static::getAuthWeChatConfig();
  70. $data = array(
  71. 'appid' => $wxPayConfig['appid'],//微信开放平台审核过的应用APPID
  72. 'attach' => empty($params['attach']) ? '' : $params['attach'],
  73. 'body' => $params['name'],//产品名称
  74. 'mch_id' => $wxPayConfig['mch_id'],//商户微信支付分配的商户号
  75. 'nonce_str' => $this->getNonceStr(),//随机字符
  76. 'notify_url' => $params['notify_url'],//通知地址
  77. 'out_trade_no' => $params['order_id'],//商户订单ID加上当前时间
  78. 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],//用户端实际ip
  79. 'total_fee' => $params['total_fee'],//订单总金额,单位为分
  80. 'trade_type' => empty($params['openid']) ? 'WAP' : 'JSAPI',//交易类型
  81. 'openid' => empty($params['openid']) ? '' : $params['openid']
  82. );
  83. $data['sign'] = $this->getSign($data);//交易签名
  84. $curl = new CurlInterface($data, 2);//函数
  85. $curl->setBaseUrl($this->unifiedOrderUrl);
  86. $result = $curl->execute('', 'POST');
  87. if (empty($result['prepay_id'])) {
  88. return Util::returnArrEr('预支付交易会话异常!');
  89. }
  90. return Util::returnArrSu('', array('prepay_id' => $result['prepay_id']));
  91. }
  92. /************************扫描支付**************************************/
  93. /**
  94. * Function Description:去微信下单并获取返回
  95. * Function Name: unifiedOrderByOrderId
  96. * @param $par
  97. * @return array
  98. *
  99. * @author nzf
  100. */
  101. public function unifiedOrderByOrderIdForSao($par)
  102. {
  103. $siteConfig = Util::getSiteConfig();
  104. $notify_url = $siteConfig['host_name'] . $siteConfig['notify_url'];
  105. $data = array(
  106. 'name' => $par['name'],//线路名称
  107. 'order_id' => (string)$par['order_id'] . '_' . rand(100, 999),//订单ID
  108. 'total_fee' => $par['total_fee'] * 100,//总金
  109. 'notify_url' => $notify_url
  110. );
  111. $codUrl = $this->unifiedOrderForSao($data);//统一下单API
  112. if ($codUrl['flag'] == false) {
  113. return $codUrl;
  114. }
  115. //设置成功返回的结果数�?
  116. $url = $siteConfig['host_name'] . '/fx/?r=weChat/we-chat/q-code&qCode=' . urlencode($codUrl['data']['code_url']) . '&_math=' . rand(100, 999);
  117. return Util::returnArrSu('', array('codUrl' => $url, 'price' => $par['total_fee']));
  118. }
  119. /**
  120. * Function Description:统一下单API
  121. * Function Name: unifiedOrder
  122. * @param $params array
  123. * attach 附加数据,在查询API和支付知中原样返回,该字段主要用于商户携带订单的自定义数
  124. * line_name 线路名称
  125. * order_id 订单ID
  126. * total_fee 总金
  127. * notify_url 回调地址
  128. *
  129. * @return array
  130. *
  131. * @author 倪宗�?
  132. */
  133. public function unifiedOrderForSao($params)
  134. {
  135. $wxPayConfig = static::getAuthWeChatConfig();
  136. $data = array(
  137. 'appid' => $wxPayConfig['appid'],//微信�?放平台审核�?�过的应用APPID
  138. 'mch_id' => $wxPayConfig['mch_id'],//商户�? 微信支付分配的商户号
  139. 'nonce_str' => $this->getNonceStr(),//随机字符�?
  140. 'body' => $params['name'],//线路名称 �? 上订单ID
  141. 'out_trade_no' => $params['order_id'],//商户订单ID加上当前时间
  142. 'total_fee' => $params['total_fee'],//订单总金额,单位为分
  143. 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],//用户端实际ip
  144. 'notify_url' => $params['notify_url'],//通知地址
  145. 'trade_type' => 'NATIVE',//交易类型
  146. );
  147. $data['sign'] = $this->getSign($data);//交易签名
  148. $curl = new CurlInterface($data, 2);//函数�?
  149. $curl->setBaseUrl($this->unifiedOrderUrl);
  150. $result = $curl->execute('', 'POST');
  151. if (empty($result['prepay_id'])) {
  152. return Util::returnArrEr('预支付交易会话异常!');
  153. }
  154. return Util::returnArrSu('', array('prepay_id' => $result['prepay_id'], 'code_url' => $result['code_url']));
  155. }
  156. /***************************************退款****************************************/
  157. /**
  158. * Des:微信退款接口
  159. * Name: cancelOrder
  160. * @param $params
  161. * @return array
  162. * @author 倪宗锋
  163. */
  164. public static function cancelOrder($params)
  165. {
  166. $config = static::getAuthWeChatConfig();
  167. $arr = array(
  168. 'appid' => $config['appid'],
  169. 'mch_id' => $config['mch_id'],
  170. 'nonce_str' => static::getNonceStr(),
  171. 'out_trade_no' => (string)$params['order_id'],//订单ID
  172. 'out_refund_no' => (string)date('YmdHis') . rand(100, 999),//退款ID
  173. 'total_fee' => (string)$params['total_fee'] * 100,//订单总金额 元
  174. 'refund_fee' => (string)$params['refund_fee'] * 100,//退款金额 元
  175. 'op_user_id' => $config['mch_id']
  176. );
  177. $arr['sign'] = static::getSign($arr);
  178. $curl = new CurlInterface($arr, 2);//函数类
  179. $curl->setCert($config);
  180. $curl->setBaseUrl('https://api.mch.weixin.qq.com/secapi/pay/refund');
  181. $result = $curl->execute('', 'POST');
  182. if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
  183. return Util::returnArrSu();
  184. }
  185. $msg = $result['return_msg'];
  186. if ($msg == 'OK') {
  187. $msg = $result['err_code_des'];
  188. }
  189. return Util::returnArrEr('退款失败!' . $msg);
  190. }
  191. /*************************************通用方法**************************************/
  192. public static function checkIsPay($orderId)
  193. {
  194. $config = static::getAuthWeChatConfig();
  195. $arr = array(
  196. 'appid' => $config['appid'],
  197. 'mch_id' => $config['mch_id'],
  198. 'out_trade_no' => (string)$orderId,//订单ID
  199. 'nonce_str' => static::getNonceStr(),
  200. );
  201. $arr['sign'] = static::getSign($arr);
  202. $curl = new CurlInterface($arr, 2);//函数类
  203. $curl->setCert($config);
  204. $curl->setBaseUrl('https://api.mch.weixin.qq.com/pay/orderquery');
  205. $result = $curl->execute('', 'POST');
  206. if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
  207. return Util::returnArrSu('', $result);
  208. }
  209. $msg = $result['return_msg'];
  210. if ($msg == 'OK') {
  211. $msg = $result['err_code_des'];
  212. }
  213. return Util::returnArrEr('退款失败!' . $msg);
  214. }
  215. /**
  216. * Function Description:获取签名
  217. * Function Name: getSign
  218. * @param $params
  219. * @return string
  220. *
  221. * @author nzf
  222. */
  223. public static function getSign($params)
  224. {
  225. if (isset($params['sign'])) {
  226. unset($params['sign']);
  227. }
  228. $config = static::getAuthWeChatConfig();
  229. //签名步骤按字典序排序参
  230. ksort($params);
  231. $string = self::ToUrlParams($params);
  232. //签名步骤二:在string后加入KEY
  233. $string = $string . "&key=" . $config['key'];
  234. //签名步骤三:MD5加密
  235. $string = md5($string);
  236. //签名步骤四:有字符转为大
  237. $result = strtoupper($string);
  238. return $result;
  239. }
  240. /**
  241. * Function Description:格式化参�? 格式化成url参数
  242. * Function Name: ToUrlParams
  243. * @param $params
  244. *
  245. * @return string
  246. *
  247. * @author 倪宗�?
  248. */
  249. public static function ToUrlParams($params)
  250. {
  251. $buff = "";
  252. foreach ($params as $k => $v) {
  253. if ($k != "sign" && $v != "" && !is_array($v)) {
  254. $buff .= $k . "=" . $v . "&";
  255. }
  256. }
  257. $buff = trim($buff, "&");
  258. return $buff;
  259. }
  260. /**
  261. * Function Description:产生的随机字符串 不长
  262. * Function Name: getNonceStr
  263. * @param int $length
  264. *
  265. * @return string
  266. *
  267. * @author 倪宗�?
  268. */
  269. public static function getNonceStr($length = 32)
  270. {
  271. $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  272. $str = "";
  273. for ($i = 0; $i < $length; $i++) {
  274. $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  275. }
  276. return $str;
  277. }
  278. /**
  279. * Des:获取登录授权微信配置
  280. * Name: getEntryAuthWeChatConfig
  281. * @author 倪宗锋
  282. */
  283. public static function getAuthWeChatConfig()
  284. {
  285. $weChatConfig = Util::getWeChatConfig();
  286. $siteConfig = Util::getSiteConfig();
  287. return $weChatConfig[$siteConfig['entryAuthWeChat']];
  288. }
  289. }