微信支付之H5支付

  1. <?php
  2. /**
  3. * H5支付
  4. *
  5. * 常见错误:
  6. * 1.网络环境未能通过安全验证,请稍后再试(原因:终端IP(spbill_create_ip)与用户实际调起支付时微信侧检测到的终端IP不一致)
  7. * 2.商家参数格式有误,请联系商家解决(原因:当前调起H5支付的referer为空)
  8. * 3.商家存在未配置的参数,请联系商家解决(原因:当前调起H5支付的域名与申请H5支付时提交的授权域名不一致)
  9. * 4.支付请求已失效,请重新发起支付(原因:有效期为5分钟,如超时请重新发起支付)
  10. * 5.请在微信外打开订单,进行支付(原因:H5支付不能直接在微信客户端内调起)
  11. */
  12. header('Content-type:text/html; Charset=utf-8');
  13. /** 请填写以下配置信息 */
  14. $mchid = 'xxxxx'; //微信支付商户号 PartnerID 通过微信支付商户资料审核后邮件发送
  15. $appid = 'xxxxx'; //微信支付申请对应的公众号的APPID
  16. $appKey = 'xxxxx'; //微信支付申请对应的公众号的APP Key
  17. $apiKey = 'xxxxx'; //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥
  18. $outTradeNo = uniqid(); //你自己的商品订单号
  19. $payAmount = 0.01; //付款金额,单位:元
  20. $orderName = '支付测试'; //订单标题
  21. $notifyUrl = 'http://www.xxx.com/wx/notify.php'; //付款成功后的回调地址(不要有问号)
  22. $returnUrl = 'http://www.baidu.com'; //付款成功后,页面跳转的地址
  23. $wapUrl = 'www.xxx.com'; //WAP网站URL地址
  24. $wapName = 'H5支付'; //WAP 网站名
  25. /** 配置结束 */
  26. $wxPay = new WxpayService($mchid,$appid,$apiKey);
  27. $wxPay->setTotalFee($payAmount);
  28. $wxPay->setOutTradeNo($outTradeNo);
  29. $wxPay->setOrderName($orderName);
  30. $wxPay->setNotifyUrl($notifyUrl);
  31. $wxPay->setReturnUrl($returnUrl);
  32. $wxPay->setWapUrl($wapUrl);
  33. $wxPay->setWapName($wapName);
  34. $mwebUrl= $wxPay->createJsBizPackage($payAmount,$outTradeNo,$orderName,$notifyUrl);
  35. echo "<h1><a href='{$mwebUrl}'>点击跳转至支付页面</a></h1>";
  36. exit();
  37. class WxpayService
  38. {
  39. protected $mchid;
  40. protected $appid;
  41. protected $apiKey;
  42. protected $totalFee;
  43. protected $outTradeNo;
  44. protected $orderName;
  45. protected $notifyUrl;
  46. protected $returnUrl;
  47. protected $wapUrl;
  48. protected $wapName;
  49. public function __construct($mchid, $appid, $key)
  50. {
  51. $this->mchid = $mchid;
  52. $this->appid = $appid;
  53. $this->apiKey = $key;
  54. }
  55. public function setTotalFee($totalFee)
  56. {
  57. $this->totalFee = $totalFee;
  58. }
  59. public function setOutTradeNo($outTradeNo)
  60. {
  61. $this->outTradeNo = $outTradeNo;
  62. }
  63. public function setOrderName($orderName)
  64. {
  65. $this->orderName = $orderName;
  66. }
  67. public function setWapUrl($wapUrl)
  68. {
  69. $this->wapUrl = $wapUrl;
  70. }
  71. public function setWapName($wapName)
  72. {
  73. $this->wapName = $wapName;
  74. }
  75. public function setNotifyUrl($notifyUrl)
  76. {
  77. $this->notifyUrl = $notifyUrl;
  78. }
  79. public function setReturnUrl($returnUrl)
  80. {
  81. $this->returnUrl = $returnUrl;
  82. }
  83. /**
  84. * 发起订单
  85. * @return array
  86. */
  87. public function createJsBizPackage()
  88. {
  89. $config = array(
  90. 'mch_id' => $this->mchid,
  91. 'appid' => $this->appid,
  92. 'key' => $this->apiKey,
  93. );
  94. $scene_info = array(
  95. 'h5_info' =>array(
  96. 'type'=>'Wap',
  97. 'wap_url'=>$this->wapUrl,
  98. 'wap_name'=>$this->wapName,
  99. )
  100. );
  101. $unified = array(
  102. 'appid' => $config['appid'],
  103. 'attach' => 'pay', //商家数据包,原样返回,如果填写中文,请注意转换为utf-8
  104. 'body' => $this->orderName,
  105. 'mch_id' => $config['mch_id'],
  106. 'nonce_str' => self::createNonceStr(),
  107. 'notify_url' => $this->notifyUrl,
  108. 'out_trade_no' => $this->outTradeNo,
  109. 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
  110. 'total_fee' => intval($this->totalFee * 100), //单位 转为分
  111. 'trade_type' => 'MWEB',
  112. 'scene_info'=>json_encode($scene_info)
  113. );
  114. $unified['sign'] = self::getSign($unified, $config['key']);
  115. $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified));
  116. $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
  117. if ($unifiedOrder->return_code != 'SUCCESS') {
  118. die($unifiedOrder->return_msg);
  119. }
  120. if($unifiedOrder->mweb_url){
  121. return $unifiedOrder->mweb_url.'&redirect_url='.urlencode($this->returnUrl);
  122. }
  123. exit('error');
  124. }
  125. public static function curlPost($url = '', $postData = '', $options = array())
  126. {
  127. if (is_array($postData)) {
  128. $postData = http_build_query($postData);
  129. }
  130. $ch = curl_init();
  131. curl_setopt($ch, CURLOPT_URL, $url);
  132. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  133. curl_setopt($ch, CURLOPT_POST, 1);
  134. curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
  135. curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
  136. if (!empty($options)) {
  137. curl_setopt_array($ch, $options);
  138. }
  139. //https请求 不验证证书和host
  140. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  141. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  142. $data = curl_exec($ch);
  143. curl_close($ch);
  144. return $data;
  145. }
  146. public static function createNonceStr($length = 16)
  147. {
  148. $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  149. $str = '';
  150. for ($i = 0; $i < $length; $i++) {
  151. $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  152. }
  153. return $str;
  154. }
  155. public static function arrayToXml($arr)
  156. {
  157. $xml = "<xml>";
  158. foreach ($arr as $key => $val) {
  159. if (is_numeric($val)) {
  160. $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
  161. } else
  162. $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
  163. }
  164. $xml .= "</xml>";
  165. return $xml;
  166. }
  167. /**
  168. * 获取签名
  169. */
  170. public static function getSign($params, $key)
  171. {
  172. ksort($params, SORT_STRING);
  173. $unSignParaString = self::formatQueryParaMap($params, false);
  174. $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
  175. return $signStr;
  176. }
  177. protected static function formatQueryParaMap($paraMap, $urlEncode = false)
  178. {
  179. $buff = "";
  180. ksort($paraMap);
  181. foreach ($paraMap as $k => $v) {
  182. if (null != $v && "null" != $v) {
  183. if ($urlEncode) {
  184. $v = urlencode($v);
  185. }
  186. $buff .= $k . "=" . $v . "&";
  187. }
  188. }
  189. $reqPar = '';
  190. if (strlen($buff) > 0) {
  191. $reqPar = substr($buff, 0, strlen($buff) - 1);
  192. }
  193. return $reqPar;
  194. }
  195. }


评论 0

发表评论

Top