1.配置
//微信支付配置
"wx_pay_config" => [
'appId' => '********',
'mchId' => '**********',
'key' => '**********',
'notify_url' => config('app.notify_url').'wxCallback',
],
2.下单
扫码支付
$config = config('dailian.wx_pay_config'); $wPay = new WxControl($config); $pay_arr = $wPay->unifiedorder('云顶之弈代练', $order['order_num'], 1??$order['price'], 'NATIVE'); if (isset($pay_arr['err_code']) ||$pay_arr['return_code'] != 'SUCCESS' || $pay_arr['result_code'] != 'SUCCESS') return wx_errorReturn(null, -1201, $pay_arr['err_code_des']); $pay_str = $pay_arr['code_url'];
APP支付
$config = config('dailian.wx_pay_config'); $wPay = new WxControl($config); $pay_arr = $wPay->unifiedorder('云顶之弈代练', $order['order_num'], 1??$order['price'], 'APP'); if (isset($pay_arr['err_code']) ||$pay_arr['return_code'] != 'SUCCESS' || $pay_arr['result_code'] != 'SUCCESS') return wx_errorReturn(null, -1201, $pay_arr['err_code_des']); $pay_str = $wPay->returnWxPayParams($pay_arr);
H5支付
//h5支付 $pay_arr = $wPay->unifiedorder('战点充值', $order_num, $money * 100, 'MWEB'); if ($pay_arr['return_code'] != 'SUCCESS' && $pay_arr['result_code'] != 'SUCCESS') return wx_errorReturn(null, -1201, $pay_arr['return_msg']); $pay_str = $pay_arr['mweb_url'];
js_api支付
//js_api支付 $openid = Db::name('user_wx')->where('user_id',$user_id)->value('openid'); $pay_arr = $wPay->unifiedorder('战点充值', $order_num, $money * 100,'JSAPI',$openid); if (isset($pay_arr['err_code']) || $pay_arr['return_code'] != 'SUCCESS' || $pay_arr['result_code'] != 'SUCCESS') return wx_errorReturn(null, -1201, $pay_arr['err_code_des']); $pay_str = $wPay->returnWxJsPayParams($pay_arr);//js_api支付所需要的参数和其他方式不一样
工具类/** * 处理微信相关的操作 * User: oliwen * Date: 2017/8/25
*/ class WxControl { public $appId; public $mchId;
public $key
public $notify_url; public $secret; public function __construct($config = []){ $config || $config = config('const.wx_pay_config'); $this->appId = $config['appId']; $this->mchId = $config['mchId']; $this->key = $config['key']; $this->notify_url = $config['notify_url']; $this->secret = config('const.wx_app_config')['secret']; } /** * 微信统一下单 */ public function unifiedorder($body, $out_trade_no, $total_price, $trade_type = "JSAPI",$openid = null) { $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $qdata = [ 'appid' => $this->appId, 'mch_id' => $this->mchId, 'nonce_str' => getNonceStr(), 'body' => $body, 'out_trade_no' => $out_trade_no, 'total_fee' => $total_price, 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], 'notify_url' => $this->notify_url, 'trade_type' => $trade_type, ]; if($trade_type == "MWEB"){ $qdata['scene_info']='{"h5_info": { "type": "Wap","wap_url": "网站地址","wap_name": "网站名称",}}'; } if($trade_type == "JSAPI"){ $qdata['openid'] = $openid; } //签名步骤一:去除空字符 $signData = array_filter($qdata); //签名步骤二:按字典序排序参数 ksort($signData); $string = toUrlParams($signData); //签名步骤二:在string后加入KEY $string = $string . "&key=" . $this->key; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $sign = strtoupper($string); //添加签名 $qdata['sign'] = $sign; $xml = toXml($qdata); //发送请求 $http = new HttpClient(); $result = $http->postXmlCurl($xml, $url); return $resultArr = xmlToArray($result); } //检查回调参数验证签名 public function checkSign($data){ $sign = $data['sign']; $data['sign']=""; // $data['sign']=""; //签名步骤一:去除空字符 $signData = array_filter($data); //签名步骤二:按字典序排序参数 ksort($signData); $string = toUrlParams($signData); //签名步骤二:在string后加入KEY $string = $string . "&key=" . $this->key; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $signA = strtoupper($string); //添加签名 if($sign == $signA) return true; return false; } /** * 返回微信支付的参数 */ public function returnWxPayParams($param) { //根据返回的字段再进行一次签名 $arr = [ 'appid' => $param['appid'], 'partnerid' => $param['mch_id'], 'prepayid' => $param['prepay_id'], 'package' => 'Sign=WXPay', 'noncestr' => $param['nonce_str'], 'timestamp' => time(), ]; ksort($arr); $arr = array_filter($arr); $str = ""; foreach ($arr as $k=>$v){ if($str) $str .= "&"; $str.="{$k}={$v}"; } $str.="&key=".$this->key; $sign = strtoupper(md5($str)); $arr['sign'] = $sign; return $arr; } /** * 返回微信js_api支付的参数 */ public function returnWxJsPayParams($param) { //根据返回的字段再进行一次签名 $arr = [ 'appId' => $param['appid'], 'timeStamp' => time().'', 'nonceStr' => $param['nonce_str'], 'package' => 'prepay_id='.$param['prepay_id'], 'signType' => 'MD5', ]; ksort($arr); $arr = array_filter($arr); $str = ""; foreach ($arr as $k=>$v){ if($str) $str .= "&"; $str.="{$k}={$v}"; } $str.="&key=".$this->key; $sign = strtoupper(md5($str)); $arr['paySign'] = $sign; return $arr; }
3.前端调起支付
4.回调
回调里面要验证签名参数和金额是否与商户所保存的金额数据相等
$str = file_get_contents('php://input'); $data = simplexml_load_string($str, 'SimpleXMLElement', LIBXML_NOCDATA); $data = json_decode(json_encode($data), true); $config = config('const.wx_pay_config'); //验证商户号 if($config['mchId']!=$data['mch_id']) { Log::error('商户号不对');exit; } //验签 $wx = new WxControl($config); $flage = $wx->checkSign($data); if($flage) {
$status = $data['return_code'] == 'SUCCESS' || $data['code'] = 10000;
if($status){ $order = Db::name('order')->where('order_num', $order_num)->where('status',0)->find(); if($order['price']*100 != $money){ Log::error('金额不对');//exit; }
} }
private $key = "";