微信公众号支付
本地调试微信登录可以修改hosts文件把微信回调域名映射到127.0.0.1上,并在本地搭建代码环境,通过域名可以正常访问到程序
登录公众号
function login(){
$redirect_uri = '';// 登录展示页面地址
$appId = '';
//1.准备scope为snsapi_base网页授权页面
$redirect_uri = urlencode($redirect_uri);
$snsapi_base_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$appId.'&redirect_uri='.$redirect_uri.'&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect';
//2.静默授权,获取code
//页面跳转至redirect_uri/?code=CODE&state=STATE
header('Location:'.$snsapi_base_url);
}
// login方法里$redirect_uri定向的地址
function index(){
$code = $_GET['code'];
$appId = '';
$secret = '';
$url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$code.'&secret='.$secret.'&code='.$code.'&grant_type=authorization_code';
$content = getCurl($url); // 获取access_token和openid,换取微信用户信息
$content = json_decode($content, true);
$weChatUserinfo = getCurl("https://api.weixin.qq.com/sns/userinfo?access_token={$content['access_token']}&openid={$content['openid']}&lang=zh_CN");
$weChatUserinfo = json_decode($weChatUserinfo, true);
/**
* $weChatUserinfo数据
Array
(
[openid] => xxxxxx
[nickname] => 早上七八点钟的太阳
[sex] => 1
[language] => zh_CN
[city] => 合肥
[province] => 安徽
[country] => 中国
[headimgurl] => http://thirdwx.qlogo.cn/mmopen/vi_32/DtfUiaYkxDhRq7QUcyvZyNkiag0GCKjKv5dCHmHXjRQpxl4lU3DCPlKPBsAbMiaz9IK7yo7bbviafkTnibjwmT97uhA/132
[privilege] => Array
(
)
[unionid] => xxxxxxxx
)
*/
}
后端
前端支付请求调用接口
function payment(){
$param = [
'appid' => '',//微信公众平台appId
'mch_id' => '',// 商户号
'nonce_str' => md5(uniqid()), // 随机字符串、最大长度32位
'body' => '',// 商品信息
'out_trade_no' => '', // 商户订单号,唯一
'total_fee' => 1,//支付金额,单位分
'spbill_create_ip' => '',// IP地址
'notify_url' => '', // 回调地址
'trade_type' => 'JSAPI', // 公众号支付
'openid' => $_POST['openid'] // 微信用户openid,在公众号登录时就已获取
];
$param['sign'] = $this->sign($param);
$xml = arrayToXml($param);
$response = postXmlCurl($xml, $url);
$data = xmlToArray($response);
if(isset($data['return_code']) && $data['return_code'] == 'SUCCESS'){
$result = [
'nonce_str' => $data['nonce_str'],
'appId' => $data['appid'],
'timeStamp' => time(),
'package' => 'prepay_id='.$data['prepay_id'],
'signType' => 'MD5',
'paySign' => $data['sign'],
];
echo json_encode($result);
}else{
echo json_encode(['msg' => 'fail']);
}
}
PHP数组转XML
function arrayToXml($arr){
$xml = "<xml>";
foreach ($arr as $key=>$val){
if(is_array($val)){
$xml.="<".$key.">".arrayToXml($val)."</".$key.">";
}else{
$xml.="<".$key.">".$val."</".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
PHP XML转数组
function xmlToArray($xml){
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring),true);
return $val;
}
微信签名函数
function sign($data)
{
ksort($data);
$stringA = '';
foreach ($data as $key => $value) {
if (!$value || $key == 'sign') continue;
if ($stringA) $stringA .= '&' . $key . "=" . $value;
else $stringA = $key . "=" . $value;
}
$wx_key = 'xxxxxx';//申请支付后有给予一个商户账号和密码,登陆后自己设置key
$stringSignTemp = $stringA . '&key=' . $wx_key;
return strtoupper(md5($stringSignTemp));
}
/**
* 以post方式提交xml到对应的接口url
* @param string $xml 需要post的xml数据
* @param string $url url
* @param int $second url执行超时时间,默认30s
*/
function postXmlCurl($xml, $url, $second = 30)
{
$ch = curl_init();
$curlVersion = curl_version();
$m_id = '';//商户号
$ua = "WXPaySDK/3.0.10 (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']." ".$m_id;
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); // 微信DEMO中,此处为TRUE,但使用中会报错
// curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
curl_setopt($ch,CURLOPT_USERAGENT, $ua);
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
//返回结果
if($data){
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
exit("curl出错,错误码:$error");
}
}
GET请求
function getCurl($url) {
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
// curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证
$responseText = curl_exec($curl);
curl_close($curl);
return $responseText;
}
前端
点击支付按钮返回支付数据后调用此函数
payment: function(){
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}else{
this.jsApiCall();
}
}
jsApiCall: function(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{ // 此处数据为后端请求微信下单接口正确返回的数据处理后传入
"appId":"xxxxxx", //公众号名称,由商户传入
"timeStamp":"1395712654", //时间戳,自1970年以来的秒数
"nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串
"package":"prepay_id=u802345jgfjsdfgsdg888",
"signType":"MD5", //微信签名方式:
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},
function(res){
WeixinJSBridge.log(res.err_msg);
alert(res.err_code+res.err_desc+res.err_msg);
}
;
}