⼩程序⽀付PHP后台源码实现,NATIVE扫码⽀付PHP后台源码实现,
⽹上有不少的⼩程序⽀付后台源码,可惜⼤部分都存在⽑病并且注释⾮常少,对新⼿不太友好;因此决定把我的源码分享出来,给新⼿做⼀个参考。
顺便把NATIVE扫码⽀付的源码也写进来了。
第⼀步。发送⽀付请求到服务器,获取预⽀付id,并传给前端
<?php
//由此才可以正常使⽤db类
require_once('../../include/db.class.php');
//这⾥是⼩程序的⽀付参数⽣成页⾯
//引进简单的安全输⼊过滤
require_once'../safy_input/safy_input.php';
//前端发来的code小程序开发一键生成平台源码
//⼀块钱⼀个
$code=safyInput($_GET['code'])?:0;
//⽀付⾦额
$fee=safyInput($_GET['fee'])?:0;
//充值来源
$from='⼩程序充值';
//充值⽤户
$userId=safyInput($_GET['user_id'])?:0;
//ip
$ip=safyInput($_GET['ip'])?:'0';
//uid
$row=$db->getRow('select id from spt_member where userid = "'.$userId.'"');
$uid=$row[id];
//获取openid
$appid="你的id";
$appsecret="你的app密钥";
$url="api.weixin.qq/sns/jscode2session?appid={$appid}&secret={$appsecret}&js_code={$code}&grant_type=authorization_code";
//curl获取openid
$openid=getKey($url);
$openid=json_decode($openid,true)['openid']?:0;
//测试⾦额
//$fee=0.01;
$body='⾦币充值';
$mch_id='商家的⽀付账号';
//随机字符串⽣成
$nonce_str=createStr();
//⽀付结果回调地址,暂时空
$notify_url='你的回调地址';
//商户订单号⽣成
$out_trade_no=createTradeNo();
//当前服务器的ip地址,暂时是空
$spbill_create_ip='服务器的ip地址';
//⽀付的单位默认是分,因此需要乘以100来变分
$total_fee=$fee*100;
//交易类型
//PC来源
$from=safyInput($_GET['from'])?:'wechat';
if($from=='PC'||$from=='pc'){
$trade_type='NATIVE';
}else{
$trade_type='JSAPI';
}
//赋值签名数组,顺序不可以变化,否则签名错误,也可以使⽤ksort对数组进⾏按照键名asii码从⼩到⼤排序
$post=array();
$post['appid']=$appid;
$post['body']=$body;
$post['mch_id']=$mch_id;
$post['nonce_str']=$nonce_str;
$post['notify_url']=$notify_url;
//PC来源
if($from=='PC'||$from=='pc'){
//⽆操作
}else{
$post['openid']=$openid;
}
$post['out_trade_no']=$out_trade_no;
$post['spbill_create_ip']=$spbill_create_ip;
$post['total_fee']=$total_fee;
$post['trade_type']=$trade_type;
//拼接签名
$sign=signStr($post);
//发送给的xml
//PC来源
if($from=='PC'||$from=='pc'){
$post_xml='<xml>
<appid>'.$appid.'</appid>
<body>'.$body.'</body>
<mch_id>'.$mch_id.'</mch_id>
<nonce_str>'.$nonce_str.'</nonce_str>
<notify_url>'.$notify_url.'</notify_url>
<out_trade_no>'.$out_trade_no.'</out_trade_no>
<sign>'.$sign.'</sign>
<spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
<total_fee>'.$total_fee.'</total_fee>
<trade_type>'.$trade_type.'</trade_type>
</xml> ';
}else{
$post_xml='<xml>
<appid>'.$appid.'</appid>
<body>'.$body.'</body>
<mch_id>'.$mch_id.'</mch_id>
<nonce_str>'.$nonce_str.'</nonce_str>
<notify_url>'.$notify_url.'</notify_url>
<openid>'.$openid.'</openid>
<out_trade_no>'.$out_trade_no.'</out_trade_no>
<sign>'.$sign.'</sign>
<spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
<total_fee>'.$total_fee.'</total_fee>
<trade_type>'.$trade_type.'</trade_type>
</xml> ';
}
//⽀付请求地址
$url='h.weixin.qq/pay/unifiedorder';
$xml=wx_pay($url,$post_xml);
//解析出来的xml数据数组
$array=getXmlDate($xml);
//file_put_contents('./3.txt',$xml);
//PC来源
if($from=='PC'||$from=='pc'){
/
/⽆操作
}else{
//处理发送给前端的数据
if($array['RETURN_CODE']=='SUCCESS'&&$array['RESULT_CODE']=='SUCCESS'){
$time=time();
//file_put_contents('./4.txt',$time);
//⽀付验证签名
$tmp='';
//这⾥的⼆次签名appid必须是appId,否则可以唤醒调试⽀付⼆维码,但是⽀付时显⽰签名验证失败$tmp['appId']=$appid;
$tmp['nonceStr']=$nonce_str;
//⽀付的商家id
$tmp['package']='prepay_id='.$array['PREPAY_ID'];
//加密⽅式
$tmp['signType']='MD5';
//时间戳转字符串
$tmp['timeStamp']=$time.'';
$data['state']=200;
$data['timeStamp']=$time.'';
$data['nonceStr']=$nonce_str;
$data['signType']='MD5';
$data['package']='prepay_id='.$array['PREPAY_ID'];
//⽀付签名字符串
$data['paySign']=signStr($tmp);
$data['out_trade_no']=$out_trade_no;
}else{
$data['state']=0;
$data['text']='错误';
$data['RETURN_CODE']=$array['RETURN_CODE'];
$data['RETURN_MSG']=$array['RETURN_MSG'];
}
}
///file_put_contents('./3.txt',$time);
//开始写⼊充值数据
$db->query("insert into spt_payrecord (uid,userid,orderid,money,paybz,type,payip,posttime,ifadd) values ('$uid','$userId','$time','$fee','等待⽀付','wechatAp p','$ip','$time','0')");
//输出数据
if($from=='PC'||$from=='pc'){
echo json_encode($array);
}else{
echo json_encode($data);
}
//获取xml的数据
function getXmlDate($xml){
//开启xml解析句柄
$p=xml_parser_create();
xml_parse_into_struct($p,$xml,$vals,$index);
xml_parser_free($p);
$data="";
foreach($index as$key=>$value){
if($key=='xml'||$key=='XML'){
//排除xml⾥⾯嵌套的xml
continue;
}
//提取,赋值xml数据
$tag=$vals[$value[0]]['tag'];
$value=$vals[$value[0]]['value'];
$data[$tag]=$value;
}
return$data;
}
//拼接签名函数,需要按照参数名ASCII码从⼩到⼤排序,不可以随意排序
function signStr($post){
//初始字符串
$strA='';
foreach($post as$key=>$value){
if(!$value&&$value!=0){
//值为空的情况下,跳过
continue;
}
//判断是否是拼接第⼀个字段
if($strA){
$strA.='&'.$key.'='.$value;
}else{
//第⼀次拼接
$strA=$key.'='.$value;
}
}
//拼接
$wx_key='⽀付的商家密码';
$strA.='&key='.$wx_key;
//file_put_contents('./1.txt',$strA);
return strtoupper(md5($strA));
}
//⽣成商户订单号码,就是时间戳了
//在⼤量订单的情况下是存在重复的问题的,不过之前的⼈是这样做的,为了延续订单号风格,暂时没有更换订单号⽣成规则
//在⼤量订单的情况下是存在重复的问题的,不过之前的⼈是这样做的,为了延续订单号风格,暂时没有更换订单号⽣成规则
function createTradeNo(){
return time();
}
//随机字符串⽣成
function createStr(){
$result='';
//挑选的随机字符串
$str='QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
for($i=0;$i<32;$i++){
//拼接随机字符串
$result.=$str[rand(0,48)];
}
return$result;
}
//curl请求sessionkey,参数是请求地址
function getKey($url)
{
$curl=curl_init();
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl,CURLOPT_TIMEOUT,500);
// 为保证第三⽅服务器与服务器之间数据传输的安全性,所有接⼝采⽤https⽅式调⽤,必须使⽤下⾯2⾏代码打开ssl安全校验。
// 如果在部署过程中代码在此处验证失败,请到 curl.haxx.se/ca/cacert.pem 下载新的证书判别⽂件。
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,true);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,true);
curl_setopt($curl,CURLOPT_CAINFO,dirname(__FILE__).'/cacert.pem');//这是根据curl.haxx.se/ca/cacert.pem 下载的证书,添加这句话之后就运⾏正常了
curl_setopt($curl,CURLOPT_URL,$url);
$res=curl_exec($curl);
curl_close($curl);
return$res;
}
//cur请求⽀付地址
function wx_pay($url,$xmlData){
$curl=curl_init();
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl,CURLOPT_HEADER,0);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,false);
//发送的post
curl_setopt($curl,CURLOPT_POST,true);
//发送的post数据
curl_setopt($curl,CURLOPT_POSTFIELDS,$xmlData);
$res=curl_exec($curl);
curl_close($curl);
return$res;
}
第⼆步前端接受后台传来的数据,调起⽀付(或⽣成⼆维码),⽤户扫码,将⽀付信息发送到回调地址,回调地址确认订单、回复
<?php
//由此才可以正常使⽤db类
require_once('../include/db.class.php');
//获取腾讯发来的xml数据
$xml=file_get_contents('php://input');
//创建xml解析器句柄
$xml_parse_handle=xml_parser_create();
//判断是否是xml格式的数据
//参数true表⽰读取xml⽂件的最后⼀段
$result=xml_parse($xml_parse_handle,$xml,true);
if(!$result){
//xml数据不对,给请求者⼀个亲切的问候
echo'好are you';
exit();
}else{
//释放xml解析器句柄
xml_parser_free($xml_parse_handle);
}
//存放数据的数组
$dataArr=getXmlDate($xml);
/
/拼接数据库的商家⽀付密码
$payData='商家⽀付密码';
//按照⿇花疼的要求,对数组元素进⾏排序
ksort($dataArr);
$MD5Str='';
//拼接
foreach($dataArr as$key=>$values){
if($key=='SIGN'){
continue;
}else{
if($MD5Str){
$MD5Str=$MD5Str.'&'.strtolower($key).'='.$values;
}else{
$MD5Str=strtolower($key).'='.$values;
}
}
};
$MD5Str=$MD5Str.'&key='.$payData['paykey'];
$verifySign=strtoupper(md5($MD5Str));
$OUT_TRADE_NO=$dataArr['OUT_TRADE_NO'];
//⾦额核对
$money=intval($dataArr['money']-0)/100;
if($dataArr['SIGN']==$verifySign){
//订单⽀付验证成功
//开始写数据库
$db->query("updata spt_payrecord set paybz = '⽀付成功',money = '$money' where orderid = '$OUT_TRADE_NO'"); echo'<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>';
}
//获取xml的数据
function getXmlDate($xml)
{
//开启xml解析句柄
$p=xml_parser_create();
//将xml解析为array,$vals是数组指针,$index是数据
xml_parse_into_struct($p,$xml,$vals,$index);
xml_parser_free($p);
$data="";
foreach($index as$key=>$value){
if($key=='xml'||$key=='XML'){
//排除xml⾥⾯嵌套的xml
continue;
}
/
/提取,赋值xml数据
$tag=$vals[$value[0]]['tag'];
$value=$vals[$value[0]]['value'];
$data[$tag]=$value;
}
return$data;
}
如果⽂章对你有帮助,请点⼀个赞。欢迎讨论。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论