微信现金红包接口实现红包发放:
一:流程:【
流程:微信用户访问红包活动页面--》后端判断是否是微信访问的
【否:提示用微信打开连接,是:提示用户是否授权允许,获取其的用户信息【openID等信息】】--》
进入红包活动页面---》用户点击领取红包【判断是否领取过红包】是:【提示已领取过红包】否
--》后端程序调用接口发放红包
--》微信用户在微信中收到红包
--》打开红包
--》红包金额会添加到钱包零钱里
--》完成红包发放。
】
二:要实现微信现金红包接口实现红包发放,首先要符合以下条件:
1.用于发放红包的微信公众号要是服务类型
2.登录微信公众平台官网后,在公众平台后台管理页面 - 开发者中心页,
点击“修改配置”按钮,填写服务器地址(URL)、Token和EncodingAESKey,
其中URL是开发者用来接收微信消息和事件的接口URL。Token可由开发者可以任意填写,
用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)。
EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥。
3.获取access_token:公众号可以使用AppID和AppSecret调用本接口来获取access_token。
【AppID和AppSecret可在微信公众平台官网-开发者中心页中获得(需要已经成为开发者,且帐号没有异常状态)。】
4.微信公众号要开通 “网页授权接口” 用户获取用户基本信息【特别是openID ,发红包时用到】
5.微信公众号的 “微信支付“ 中的 ”商户号” 要开通微信支付【发红包的金额是该支付账户扣款】,开通“现金红包”接口【调用该接口发放红包】。
6. 登陆 ”商户号”【微信公众号分配的商户号。第5 中有说明】 在 “API安全” 中 下载PHP版的 证书 【.pem格式】
以上如描述不清楚,请查看 微信开发者文档 里面有详细的秒杀。
部分代码如下【其余的请查看附件】:
<?php
namespace RedClient\Controller;
use Think\Controller;
use RedClient\Redpack\WeiXinInfo;
use RedClient\Redpack\Oauth;
use RedClient\Redpack\SendRedPack;
use RedClient\Redpack\CreateRedPack;
class IndexController extends Controller
{
public function index()
{
$this->isWeixin();//是否是微信打开
if($this->access)
{
$this->display();
}
else
{
$class=new Oauth();
$class->index('http://www.myweb.com/index.php/Index/oauth');
}
}
//获取用户信息 openID
public function oauth()
{
$code=isset($_GET['code'])?strip_tags(trim($_GET['code'])):'';
$state=isset($_GET['state'])?strip_tags(trim($_GET['state'])):'';
$class=new Oauth();
$userInfo=$class->getCode($code,$state);//获取用户信息
if(!empty($userInfo['data']))
{
//$model=M('wxuser');
//$result=$model->where('openid = "'.$userInfo['data']->openid.'"')->field('openid')->select();
if(empty($result))
{
$userInfo['data']=$this->object2array($userInfo['data']);
$model->data($userInfo['data'])->add();
}
}
$userInfo['data']=$this->object2array($userInfo['data']);
//创建红包
$class=new CreateRedPack();
$red=$class->redval();
//发红包
$class=new SendRedPack();
$configs=array(
'send_name'=>'红包发送者名称',//红包发送者名称
're_openid'=>$userInfo['data']['openid'],//接受红包的用户,用户在wxappid下的openid
'total_amount'=>$red,//付款金额,单位分
'total_num'=>'1',//红包发放总人数
'wishing'=>'红包祝福语',//红包祝福语
'client_ip'=>$_SERVER['SERVER_ADDR'],//调用接口的机器Ip地址
'act_name'=>'活动名称',//活动名称
'remark'=>'备注信息',// 备注信息
);
$class->setFields($configs);
$result=$class->requestXml();
//微信返回信息处理
if(strtoupper($result['return_code'])=='SUCCESS')
{
if(strtoupper($result['result_code'])=='SUCCESS')
{
//红包发送成功!
$datas['flag']=1;
echo $result['err_code_des'];
}
else
{
//红包发送失败
$datas['flag']=0;
$datas['msg']=$result['err_code_des'];
echo $result['err_code_des'];
}
}
else
{
//红包发送失败
$datas['flag']=0;
$datas['msg']=$result['err_code_des'];
echo $result['err_code_des'];
}
}
public function isWeixin()
{
if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false)
{
$this->access=true;
}
return false;
}
//类转换成数组
public function object2array($object)
{
if (is_object($object))
{
foreach ($object as $key => $value)
{
$array[$key] = $value;
}
}
else
{
$array = $object;
}
return $array;
}
}
?>
<?php
namespace RedClient\Redpack;
/**
简单红包算法类
**/
class CreateRedPack
{
private $rid=0;//当前红包随机数
private $rand_arr=array();//35%是1.0到1.1 红包随机数
private $rand_arr1=array();//35%是1.1到1.2 红包随机数
private $rand_arr2=array();//30%是1.2到1.95 红包随机数
private $red=0;//红包金额
private $simplered=0;
private $red_config=array(
array('min'=>1.0,'max'=>1.1),
array('min'=>1.1,'max'=>1.2),
array('min'=>1.2,'max'=>1.95)
);
public function __construct()
{
$this->rid=mt_rand(1,10000);//当前红包随机数
$this->rand_arr=range(1,3500);//35%是1.0到1.1
$this->rand_arr1=range(3501,7000);//35%是1.1到1.2
$this->rand_arr2=range(7001,10000);//30%是1.2到1.95
$this->simplered=666;
}
public function redval()
{
$maxrp=$this->maxred();//随机最大红包金额
if($maxrp!=$this->simplered)
{
if(in_array($this->rid,$this->rand_arr))
{
$red_val=$this->red_config[0];
$min=$red_val['min']*100;
$max=$red_val['max']*100;
$this->red=mt_rand($min,$max);
$this->red=$this->red/100;
}
elseif(in_array($this->rid,$this->rand_arr1))
{
$red_val=$this->red_config[1];
$min=$red_val['min']*100;
$max=$red_val['max']*100;
$red=mt_rand($min,$max);
$this->red=$this->red/100;
}
elseif(in_array($this->rid,$this->rand_arr2))
{
$red_val=$this->red_config[2];
$min=$red_val['min']*100;
$max=$red_val['max']*100;
$this->red=mt_rand($min,$max);
$this->red=$this->red/100;
}
}
else
{
$this->red=$maxrp;
}
return $this->red?$this->red:1;
}
protected function maxred()
{
$rid=mt_rand(1,100000);
$rid1=mt_rand(1,100000);
$red=0;
$dff=$rid-$rid1;
if($dff > 0)
{
if(($rid1%$rid1)==$this->simplered)
{
$red=$this->simplered;
}
}
else
{
if(($rid1%$rid)==$this->simplered)
{
$red=$this->simplered;
}
}
return $red;
}
}
?>
<?php
namespace RedClient\Redpack;
/*********
先在公共平台配置授权的域名;
然后才能通过,
网页授权方式获取微信用户基本信息
网页授权流程分为四步:
1.引导用户进入授权页面同意授权,获取code
2.通过code换取网页授权access_token(与基础支持中的access_token不同)
3.如果需要,开发者可以刷新网页授权access_token,避免过期
4.通过网页授权access_token和openid获取用户基本信息
**********/
class Oauth
{
protected $appid='';
protected $redirect_uri='';
protected $state='';//mt_rand(100,999);
protected $appsecret='';
protected $data=array('flag'=>0,'msg'=>'','data'=>'');
public function __construct()
{
$this->appid='appid';//
$this->appsecret='secret';//;
$this->state=mt_rand(100,999);
}
//引导用户访问链接处理函数
public function index($redirect_uri)
{
$this->redirect_uri=urlencode($redirect_uri);//微信自动跳转到$redirect_uri
header('location:https://open.weixin.qq.com/connect/oauth3/authorize?appid='.$this->appid.'&redirect_uri='.$this->redirect_uri.'/oauth.php&response_type=code&scope=snsapi_userinfo&state='.$this->state.'&connect_redirect=1#wechat_redirect');
}
public function getCode($code='',$state='',$token='',$webToken='')
{
$data=array(
'errorno'=>'',
'errormsg'=>'',
'data'=>''
);
if(empty($code))
{
$this->data['flag']=0;
$this->data['msg']='授权失败!';
}
else
{ /*
1获取webtoken
2获取reflash_token
3获取用户信息
*/
$token_url = 'https://api.weixin.qq.com/sns/oauth3/access_token?appid='.$this->appid.'&secret='.$this->appsecret.'&code='.$code.'&grant_type=authorization_code';
$token = json_decode(file_get_contents($token_url));
if (isset($token->errcode))
{
$data['errorno']=$token->errcode;
$data['errormsg']=$token->errmsg;
}
else
{
$access_token_url = 'https://api.weixin.qq.com/sns/oauth3/refresh_token?appid='.$this->appid.'&grant_type=refresh_token&refresh_token='.$token->refresh_token;
//转成对象
$accessToken = json_decode(file_get_contents($access_token_url));
if (isset($accessToken->errcode))
{
$data['errorno']=$token->errcode;
$data['errormsg']=$token->errmsg;
}
else
{
$user_info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token='.$accessToken->access_token.'&openid='.$accessToken->openid.'&lang=zh_CN';
//转成对象
$userInfo = json_decode(file_get_contents($user_info_url));
if (isset($userInfo->errcode))
{
$data['errorno']=$token->errcode;
$data['errormsg']=$token->errmsg;
}
else
{
$data['data']=$userInfo;
}
}
}
}
return $data;
}
}
?>
<?php
/******
用于企业向微信用户个人发现金红包
目前支持向指定微信用户的openid发放指定金额红包。
(获取openid参见微信公众平台开发者文档:
网页授权获取用户基本信息)
****/
namespace RedClient\Redpack;
class SendRedPack
{
private $config=array(
'nonce_str'=>'',//随机字符串,不长于32位
'sign'=>'',//签名
'mch_billno'=>'',//商户订单号
'mch_id'=>'1111sdfsafsaddf',//微信支付分配的商户号
'wxappid'=>'sddafdsadfdsafdsdd',//微信分配的公众账号ID
'send_name'=>'',//红包发送者名称
're_openid'=>'',//接受红包的用户,用户在wxappid下的openid
'total_amount'=>'',//付款金额,单位分
'total_num'=>'',//红包发放总人数
'wishing'=>'',//红包祝福语
'client_ip'=>'',//调用接口的机器Ip地址
'act_name'=>'',//活动名称
'remark'=>'',// 备注信息
);
protected $key='';
protected $url='https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack';
protected $requestXml='';
//设置必要参数
public function setFields($conf=array())
{
foreach($conf as $k=>$v)
{
if(isset($this->config[$k]) && !empty($v))
{
$this->config[$k]=$v;
}
}
$this->config['mch_billno']=$this->billno();
$this->config['nonce_str']=$this->createNonceStr();
$this->createSign($conf);
$this->createXml();
//echo $this->requestXml;
}
protected function billno()
{
return $this->config['mch_id'].time().md5(mt_rand(1000,9999));
}
/* //检查必要参数是否为空!
public function checkConfig()
{
$flag=true;
foreach($this->config as $k=>$v)
{
if(empty($v))
{
$flag=false;
break;
}
}
} */
//随机字符串,不长于32位
public function createNonceStr( $len=32 )
{
$strs = "abcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
$len=$len<=32?$len:32;
for ( $i = 0; $i < $len; $i++ )
{
$str.= substr($strs, mt_rand(0, strlen($strs)-1), 1);
}
return $str;
}
//格式化参数
public function formatParam($config=array(),$flag=1)
{
$format='';
if(!empty($config))
{
ksort($config);
foreach($config as $k=>$v)
{
if($flag)
{
$v=urlencode($v);
}
if($flag==0 && strtolower($k)=='sign')
{
continue;
}
$format.=$k.'='.$v.'&';
}
$format=trim($format,'&');
}
return $format;
}
//创建SIGNATURE
protected function createSign($config)
{
$format=$this->formatParam($config,0);
$format.='&key='.$this->key;
$signature=strtoupper(md5($format));
$this->config['sign']=$signature;
return true;//$signature;
}
//创建xml格式数据
protected function createXml()
{
$xml='<xml>';
foreach($this->config as $k=>$v)
{
if(!empty($v))
{
$xml.='<'.$k.'><![CDATA['.$v.']]></'.$k.'>';
}
}
$xml.='</xml>';
$this->requestXml=$xml;
}
//XML格式数据转换为数组
public function createArray($xml='')
{
$arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $arr;
}
//发送红包
public function requestXml($timeout=30,$header=array())
{
$ch = curl_init();
//超时时间
curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_URL,$this->url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT,dirname(__FILE__).'/apiclient_cert.pem');//pem证书地址
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY,dirname(__FILE__).'/apiclient_key.pem');//key证书地址
curl_setopt($ch,CURLOPT_CAINFO,'PEM');
curl_setopt($ch,CURLOPT_CAINFO,dirname(__FILE__).'/rootca.pem');//CA证书地址
//两个文件合成一个.pem文件
//curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/all.pem');
if( count($header) >= 1 )
{
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$this->requestXml);
$data = curl_exec($ch);
var_dump($data);
if($data)
{
curl_close($ch);
var_dump($data);
return $data;
}
else
{
$error = curl_errno($ch);
echo 'ERROR:'.$error;
curl_close($ch);
return false;
}
}
//返回非空值,非NULL
public function notEmpty($val='')
{
$return='';
if(null !=$val && strlen($val) != 0)
{
$return=$val;
}
return $return?$return:false;
}
}
?>
<?php
namespace RedClient\Redpack;
class WeiXinInfo
{
private $AppID='appid';
private $AppSecret='secret';
private $grant_type='client_credential';
private $url='https://api.weixin.qq.com/cgi-bin/token';
public function __construct()
{
//$arr=array('access_token'=>'1','expires'=>'7200');
}
//设置获取ACCESSTOKEN 的URL
public function setUrl()
{
return $this->url=$this->url.'?grant_type='.$this->grant_type.'&appid='.$this->AppID.'&secret='.$this->AppSecret;
}
//获取APPID,SECRET
public function getAppid()
{
$sql='select appid,secret from ly_appid where flag=1';
$model=M();
$result=$model->query($sql);
if(!empty($result))
{
$this->AppID=$result[0]['appid'];
$this->AppSecret=$result[0]['secret'];
return $result[0];
}
}
public function object2array($object)
{
if (is_object($object))
{
foreach ($object as $key => $value)
{
$array[$key] = $value;
}
}
else
{
$array = $object;
}
return $array;
}
//检验URL有效
public function checkUrl()
{
$signature=isset($_GET['signature'])?strip_tags(trim($_GET['signature'])):'';
$timestamp=isset($_GET['timestamp'])?strip_tags(trim($_GET['timestamp'])):'';
$nonce=isset($_GET['nonce'])?strip_tags(trim($_GET['nonce'])):'';
$echostr=isset($_GET['echostr'])?$_GET['echostr']:'';
if(!empty($signature) && !empty($timestamp) && !empty($nonce))
{
if($this->checkSign($signature,$timestamp,$nonce))
{
echo $echostr;
return true;
}
else
{
return false;
}
}
}
//验证SIGNATURE是否有效
private function checkSign($sign,$timestamp,$nonce)
{
$token=$this->getAccessToken();
//$token=$this->object2array($token);
$sign_arr=array($token,$timstamp,$nonce);
sort($sign_arr,SORT_STRING);
$signStr=implode($sign_arr);
$signStr=sha1($signStr);
if(strtoupper($signStr)==strtoupper($sign))
{
return true;
}
return false;
}
//通过微信接口获取微信Access_Token
public function getAccessToken()
{
$token='';
$this->setUrl();
$check=$this->checkToken();
if(session('?'.md5('getaccesstoken')) && $check)
{
$tokens=session(md5('getaccesstoken'));
$token=$tokens->access_token;
}
else
{
$result=file_get_contents($this->url);
$result=json_decode($result);
$token=$result->access_token;
$result->expires_in=$result->expires_in+time();
session(md5('getaccesstoken'),$result);
}
return $token;
}
//检查微信ACCESS_TOKEN是否有效
public function checkToken()
{
if(session('?'.md5('getaccesstoken')) && session(md5('getaccesstoken')))
{
$time=time();
$token=session(md5('getaccesstoken'));
if($token->expires_in-$time > 30)
{
return true;
}
else
{
session(md5('getaccesstoken'),null);
}
}
return false;
}
//保存微信ACCESSTOKEN到数据库
public function saveAccessToken()
{
$token=$this->getAccessToken();
$sql='select `id`,`rate`,token,ex_time,createtime from ly_token where token="'.$token.'" where appid="'.$this->AppID.'" AND secret="'.$this->AppSecret.'"';
$model=M();
$result=$model->query($sql);
if(!empty($result))
{
$time=time();
$expires=$time-$result[0]['createtime'];
if($result[0]['ex_time']-$expires > 0)
{
return $result[0]['token'];
}
else
{
$token=$this->getAccessToken();
if(!empty($token))
{
$token=json_decode($token);
if(!isset($token['errcode']) or !$token['errcode'])
{
if(isset($token['access_token']) && $token['access_token'])
{
$data['access_token']=$token['access_token'];
$data['createtime']=$time;
$data['ex_time']=$token['expires_in'];
$data['rate']=$result[0]['rate']+1;
//$sql='update ly_token set token="'.$token['access_token'].'" ,createtime='.$time.',ex_time='.$token['expires_in'].' where `id`='.$result[0]['id'];
$model=M('token');
$update=$model->where('`id`='.$result[0]['id'])->save($data);
if($update)
{
return $token['access_token'];
}
}
}
else
{//微信返回的错误信息
$data['errcode']=$token['errcode'];
$data['errmsg']=$token['errmsg'];
$data['appid']=$this->AppID;
$data['secret']=$this->AppSecret;
$data['createtime']=time();
$data['rate']=$result[0]['rate']+1;
$ein=$model->where('`id`='.$result[0]['id'])->save($data);
if($ein)
{
return false;
}
}
}
}
}
else
{//新插入数据库保存
$token=$this->getAccessToken();
$model=M('token');
if(!empty($token))
{
$data=array();
$token=json_decode($token);
if(!isset($token['errcode']) or !$token['errcode'])
{
if(isset($token['access_token']) && $token['access_token'])
{
$data['access_token']=$token['access_token'];
$data['createtime']=$time;
$data['ex_time']=$token['expires_in'];
//$sql='insert into ly_token() vlaues()';
$data['rate']=1;
$in=$model->data($data)->add();
if($ein)
{
$token['access_token'];
}
}
}
else
{//微信返回的错误信息
$data['errcode']=$token['errcode'];
$data['errmsg']=$token['errmsg'];
$data['appid']=$this->AppID;
$data['secret']=$this->AppSecret;
$data['createtime']=time();
$data['rate']=1;
$ein=$model->data($data)->add();
if($ein)
{
return false;
}
}
}
}
return false;
}
}
?>