这里开发时使用的是thinkphp5.1
1.直接唤起微信支付
<?php namespace app\index\controller; use wechatpay\lib\WxPayApi; use wechatpay\lib\WxPayUnifiedOrder; use wechatpay\example\JsApiPay; use wechatpay\example\WxPayConfig; use think\facade\Env; class Pay { /* 1、交易金额 交易金额默认为人民币交易,接口中参数支付金额单位为【分】,参数值不能带小数。对账单中的交易金额单位为【元】。 外币交易的支付金额精确到币种的最小单位,参数值不能带小数点。 2、交易类型 JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里 MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口 3、货币类型 货币类型的取值列表: CNY:人民币 4、时间 标准北京时间,时区为东八区;如果商户的系统时间为非标准北京时间。参数值必须根据商户系统所在时区先换算成标准北京时间, 例如商户所在地为0时区的伦敦,当地时间为2014年11月11日0时0分0秒,换算成北京时间为2014年11月11日8时0分0秒。 5、时间戳 标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数。注意:部分系统取到的值为毫秒级,需要转换成秒(10位数字)。 6、商户订单号 商户支付的订单号由商户自定义生成,仅支持使用字母、数字、中划线-、下划线_、竖线|、星号*这些英文半角字符的组合,请勿使用汉字或全角等特殊字符。微信支付要求商户订单号保持唯一性(建议根据当前系统时间加随机序列来生成订单号)。重新发起一笔支付要使用原订单号,避免重复支付;已支付过或已调用关单、撤销(请见后文的API列表)的订单号不能重新发起支付。 */ /** * 微信支付调用 * @author ffx * @param int $userId 用户id * @param float $money 金额 * @param int $type 支付类型(1充值,2订单支付) * @param string $body 显示title,提示头信息 * @param string $backUrl 回调地址(/index/pay/wxPayBack) * @param string $addition 附加参数(微信回调时原样返回) * @return bool|mixed */ public function wxPay($userId,$money,$type,$body,$backUrl,$addition = '') { $out_trade_no = self::getOrderNo(); $wxchid = config('wechat.wxmchid'); $wxAppId = config('wechat.paywxAppId'); //微信支付sdk中的文件 include_once EXTEND_PATH."wechatpay/lib/WxPay.Api.php"; include_once EXTEND_PATH."wechatpay/example/WxPay.JsApiPay.php"; $total_money = floor(sprintf("%0.3f",$money)*100); if(!$total_money || $total_money <= 0){ return ['code'=>100001,'message'=>"支付金额小于0"]; } if($_SERVER["REQUEST_SCHEME"] == "http"){ $notify_url = 'http://'.$_SERVER['HTTP_HOST'].$backUrl; }else{ $notify_url = 'https://'.$_SERVER['HTTP_HOST'].$backUrl; } //此处查询的是登录时存起来的openid $openid = Db::name('member')->where('id',$userId)->value('openid'); $input = new \WxPayUnifiedOrder(); $input->SetAppid($wxAppId); $input->SetMch_id($wxchid); //商户号 $input->SetAttach($addition); //附加参数 $nonceStr = self::createNonceStr(); $input->SetNonce_str($nonceStr);//自定义随机字符串 $input->SetBody($body);// $input->SetOut_trade_no($out_trade_no);//订单号,自己建 $input->SetTotal_fee($total_money);//金钱 $input->SetSpbill_create_ip($this->getIP());//客户端ip $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600));//过期时间 $input->SetNotify_url($notify_url);//回调的接口地址 $input->SetTrade_type("JSAPI");//支付类型 $input->SetOpenid($openid); //此处两个是微信支付的sdk的类 $WxPayApi = new WxPayApi(); $config = new WxPayConfig(); $response = $WxPayApi->unifiedOrder($config,$input);//预创建订单 //写入支付记录表(业务逻辑处理) $res = $this->insertWxPayLog($userId,$out_trade_no,$money,$type,0); if(!$res){ return false; } if($response['result_code']=='SUCCESS' && $response['return_code']=='SUCCESS' && $response['return_msg']=='OK') { $tools = new JsApiPay(); $response['nonce_str'] = $nonceStr; $jsApiParameters = $tools->GetJsApiParameters($response); return json_decode($jsApiParameters); //$jsApiParameters示例 //{"appId":"wx194a1075c8bca3d9","nonceStr":"4tmc7nttscu5w6u6cqbxlgvum4qs6p8y","package":"prepay_id=wx05155440194924091e0efc912670185750","signType":"MD5","timeStamp":"1541404480","paySign":"CD4DE57A6B5B2B5418B5F07536C4DF10"} //输出直接唤起支付 // $str = "<html><body></body></html>"; // // $str .='<html><head><meta http-equiv="content-type" content="text/html;charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>微信支付</title></head><body>'; // // $str .= "<script>function onBridgeReady(){WeixinJSBridge.invoke('getBrandWCPayRequest',$jsApiParameters)}if(typeof WeixinJSBridge=='undefined'){if(document.addEventListener){document.addEventListener('WeixinJSBridgeReady',onBridgeReady,false)}else if(document.attachEvent){document.attachEvent('WeixinJSBridgeReady',onBridgeReady);document.attachEvent('onWeixinJSBridgeReady',onBridgeReady)}}else{onBridgeReady()}</script></body></html>"; // // echo $str;exit; }else{ return false; } } /** * 余额支付回调 * @author ffx * */ function amountPayBack() { $xml = file_get_contents('php://input'); $xmlJson = json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)); $arr = json_decode($xmlJson, true); //此处注释暂未用到 /* //用户http_build_query()将数据转成URL键值对形式 $sign = http_build_query($arr); //md5处理 $sign = md5($sign); //转大写 $sign = strtoupper($sign); //验签名。默认支持MD5 if($sign === $arr['sign']) { // 校验返回的订单金额是否与商户侧的订单金额一致。修改订单表中的支付状态。 } $return = ['return_code'=>'SUCCESS','return_msg'=>'OK']; $xml = '<xml>'; foreach($return as $k=>$v){ $xml.='<'.$k.'><![CDATA['.$v.']]></'.$k.'>'; } $xml.='</xml>';*/ $out_trade_no=$arr['out_trade_no']; //订单号 //判断金额 $total_fee=$arr['total_fee']/100*10000; //回调回来的xml文件中金额是以分为单位的 $money = Db::name('recharge_log')->where('out_trade_no',$out_trade_no)->value('money'); if($money != $total_fee){ return; } $result_code=$arr['result_code']; //状态 if($result_code=='SUCCESS'){ //处理数据库操作 $post = [ 'out_trade_no'=>$out_trade_no, 'total_fee'=>$arr['total_fee'] //微信实际收到金额(分为单位) ]; //处理业务逻辑 $res = $this->amountPayBackLogic($xmlJson,$post,1,$money); if($res['code'] == 0){ echo 'SUCCESS'; //返回成功给微信端 一定要带上不然微信会一直回调8次 exit; } }else{ //失败 return; } } /** * 获取随机字符串 * @author ffx * @param int $length 长度 * @return string */ public static function createNonceStr($length = 16) { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $str = ''; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } /** * 获取订单号 * @author ffx * @return string */ public static function getOrderNo() { $outTradeNo = time() . rand(1000, 9999); return $outTradeNo; } /** * @purpose 获取请求来源的ip * @author ffx * @return mixed */ function getIp() { if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } else { $ip = $_SERVER['REMOTE_ADDR']; } $ip_arr = explode(',', $ip); return $ip_arr[0]; } }
2.生成二维码支付
回调和唤起支付一样
/** * 微信支付调用 * @author ffx * @param int $userId 用户id * @param float $money 金额 * @param string $body 显示title,提示头信息 * @param string $backUrl 回调地址(/v1/pay/wxPayBack) * @param string $addition 附加参数(微信回调时原样返回) * @return bool */ public function wxPayErWeiMa($userId,$money,$body,$backUrl,$addition = '') { $out_trade_no = self::getOrderNo(); $total_money = $money; include_once EXTEND_PATH."wxpay/lib/WxPay.Api.php"; include_once EXTEND_PATH."wxpay/example/WxPay.JsApiPay.php"; include_once EXTEND_PATH."wxpay/example/WxPay.NativePay.php"; $total_money = floor(sprintf("%0.3f",$total_money)*100); if(!$total_money || $total_money <= 0){ return ['code'=>100001,'message'=>"支付金额小于0"]; } $notify_url = 'http://'.$_SERVER['HTTP_HOST'].$backUrl; $wxPayConfig = Db::name('user_wxpay_config') ->alias('c') ->join('member m','m.admin_user=c.admin_user') ->where('m.id', $userId) ->where('c.status', 1) ->field('c.*') ->order('update_time','desc') ->find(); if(empty($wxPayConfig)){ return false; } if(empty($body)){ $body = $wxPayConfig['body']; } $wxchid = $wxPayConfig['mac_id']; $wxAppId = $wxPayConfig['appid']; $wxAppSecret = $wxPayConfig['app_secret']; $wxKey = $wxPayConfig['key']; $config = new WxPayConfig(); $config->SetAppSecret($wxAppSecret); $config->SetKey($wxKey); $config->SetAppId1($wxAppId); $config->SetMerchantId1($wxchid); $input = new WxPayUnifiedOrder(); $input->SetBody($body); $input->SetAttach($addition); //附加参数 $input->SetOut_trade_no($out_trade_no); //订单号,自己建 $input->SetTotal_fee($total_money);//金钱 $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600)); //过期时间 $input->SetGoods_tag("test"); $input->SetNotify_url($notify_url); //回调的接口地址 $input->SetTrade_type("NATIVE"); //支付类型(二维码) $input->SetProduct_id("123456789"); //写入支付记录表 $res = $this->insertRechargeLog($userId,$out_trade_no,$money,0,'wxpay'); if(!$res){ return false; } $notify = new \NativePay(); $result = $notify->GetPayUrl($input); if(isset($result["code_url"]) && !empty($result["code_url"])){ require_once './../extend/wxpay/example/phpqrcode/phpqrcode.php'; $url = urldecode($result['code_url']); if(substr($url, 0, 6) == "weixin"){ QRcode::png($url); }else{ header('HTTP/1.1 404 Not Found'); } }else{ return false; } }