<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<?php
//微信内支付,需要从c.html页面跳转至此;
$appid = "#";
$secret = "#";
$code = $_GET["code"];
$state = $_GET["state"];
if(!isset($_COOKIE['openid'])){
//获取用户openid地址
$geturl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code";
$openid = json_decode(file_get_contents($geturl))->openid;
setcookie("openid","$openid",time()+3600);
}else{
$openid = $_COOKIE['openid'];
}
?>
<?php
include_once "jssdk.php";
//生成随机字符串
function getNonceNum($numLen=16){
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $numLen; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
//获取用户ip地址
function get_client_ip(){
$cip = "unknown";
if($_SERVER['REMOTE_ADDR']){
$cip = $_SERVER['REMOTE_ADDR'];
}elseif(getenv("REMOTE_ADDR")){
$cip = getenv("REMOTE_ADDR");
}
return $cip;
}
$getNonceNumstring = getNonceNum();
$out_trade_no = date("Ymd").getNonceNum();
$ip = get_client_ip();
$param['appid'] = "$appid";
$param['mch_id'] = "#";
$param['nonce_str'] = $getNonceNumstring;
$param['body'] = "支付";
$param['out_trade_no'] = $out_trade_no;
$param['total_fee'] = 1;
$param['spbill_create_ip'] = $ip;
$param['notify_url'] = "http://www.#";
$param['trade_type'] = "JSAPI";
$param['openid'] = "$openid";
//字典排序
ksort($param);
$sign_raw = "";
foreach($param as $k => $v){
$sign_raw .= $k."=".$v."&";
}
$sign_raw .= "key=#";
//生成签名
$sign = strtoupper(md5($sign_raw));
$xml = <<<EOF
<xml>
<appid>$appid</appid>
<body>支付</body>
<mch_id>#</mch_id>
<nonce_str>$getNonceNumstring</nonce_str>
<notify_url>http://www.#</notify_url>
<out_trade_no>$out_trade_no</out_trade_no>
<spbill_create_ip>$ip</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
<openid>$openid</openid>
<sign>$sign</sign>
</xml>
EOF;
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//调用接口,返回xml数据包含跳转url;
$result = postXmlCurl($xml, $url);
//解析xml
$xml = simplexml_load_string($result);
$bigarr = array();
//循环生成数组
foreach($xml->children() as $child){
$key = $child->getName();
$bigarr["$key"] = "$child";//必须加引号
}
print_r($bigarr);
$p = new Jssdk;
$singlepage = $p->getSignPackge();
print_r($singlepage);
$noncestr123 = $singlepage["nonceStr"];
$prepay_id = $bigarr["prepay_id"];
//页面计算签名
$pagearr = array(
"appId" => "$appid",
"timeStamp" => time(),
"nonceStr" => "$noncestr123",
"package" => "prepay_id=$prepay_id",
"signType" => "MD5"
);
//字典排序
ksort($pagearr);
$sign_raw1 = "";
foreach($pagearr as $k => $v){
$sign_raw1 .= $k."=".$v."&";
}
$sign_raw1 .= "key=#";
//生成签名
$signs = strtoupper(md5($sign_raw1));
print_r($pagearr);
echo $signs;
?>
<script type="text/javascript">
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '#', // 必填,公众号的唯一标识
timestamp: <?php echo $singlepage["timestamp"] ?>, // 必填,生成签名的时间戳
nonceStr: '<?php echo $singlepage["nonceStr"] ?>', // 必填,生成签名的随机串
signature: '<?php echo $singlepage["signature"] ?>',// 必填,签名
jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表
});
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
function pay(){
wx.chooseWXPay({
timestamp: <?php echo time() ?>, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '<?php echo $singlepage["nonceStr"]?>', // 支付签名随机串,不长于 32 位
package: 'prepay_id=<?php echo $bigarr["prepay_id"]?>', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: 'MD5', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: '<?php echo $signs?>', // 支付签名
success: function (res) {
// 支付成功后的回调函数
alert(res);
}
});
}
</script>
<h1 onclick="pay()">点我支付</h1>
<?php
function postXmlCurl($xml, $url, $useCert = false, $second = 30){
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch,CURLOPT_URL, $url);
if(stripos($url,"https://")!==FALSE){
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
}else{
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
}
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if($useCert == true){
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, "###.pem");
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY, "###.pem");
curl_setopt($ch, CURLOPT_CAINFO, "###.pem");
}
//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);
echo "error";
}
}