/**
* 购买会员
* @ApiMethod (POST)
* @ApiReturn ({ "code": 1,"msg": "登录成功", "time": "1562726766"})
* @ApiParams (name="type", type="string", required=true, description="会员类型:1=1级会员,2=2级会员")
* @ApiParams (name="price", type="string", required=true, description="价格")
*/
public function member()
{
$user = $this->auth->getUser();
$type = $this->request->param('type');
$price = $this->request->param('price');
if (empty($type) || empty($price)){
$this->error('缺少参数');
}
if ($user['level']==1){
$this->error('很抱歉!您已经是会员了');
}
//2020年12月31号前购买有效期2年
if (time()< 1609430399){
$end_time = strtotime(date('Y-m-d 23:59:59',strtotime("+2 year"))) - 86400;//会员结束时间
}else{
$end_time = strtotime(date('Y-m-d 23:59:59',strtotime("+1 year"))) - 86400;//会员结束时间
}
$member_order1 = date('Y',time()).date('m',time()).date('d',time()).rand(10000,99999);
$member_order = [
'member_order'=>$member_order1,
'user_id' => $user['id'],
'type' => $type,
'price' => $price,
'create_time'=>time(),
'end_time'=>$end_time
];
//生成订单
//to do 微信支付
$user = $this->auth->getUser();
$openid = $this->auth->getUser()->openid;
$appid = '';
$mch_id = '';
$key = '';
$nonce_str = 'omso8gakbdqtxmzjc63pcj0b71v5qy68';
$body = '会员费';
$out_trade_no = $member_order1;
$total_fee = $price*100;
$spbill_create_ip = get_client_ip();
$notify_url = 'https://xxx.xxx.com/api/member/back';
$trade_type = 'JSAPI';
$data = compact('body', 'appid','mch_id', 'nonce_str','out_trade_no','total_fee','spbill_create_ip', 'notify_url','trade_type','openid');
$sign = get_sign($data, $key, false);
$info =[
'appid' =>$appid,
'mch_id'=>$mch_id,
'nonce_str'=>$nonce_str,
'sign'=>$sign,
'body'=>$body,
'out_trade_no'=>$out_trade_no,
'total_fee'=>$total_fee,
'spbill_create_ip'=>$spbill_create_ip,
'notify_url'=>$notify_url,
'trade_type'=>$trade_type,
'openid'=>$user['openid']
];
$info = $this->arrayToXml($info);
// print_r($info);exit;
$data = $this->curl_post('https://api.mch.weixin.qq.com/pay/unifiedorder',$info);
// var_dump($data);exit;
$data1 = $this->xmlToArray($data);
$prepay_id = $data1['prepay_id'];
$time = time();
$params_for_paysign = compact('appid','nonce_str','prepay_id','time');
$paySign = strtoupper(MD5("appId=$appid&nonceStr=$nonce_str&package=prepay_id=$prepay_id&signType=MD5&timeStamp=$time&key=$key"));
file_put_contents('2.txt',$prepay_id.PHP_EOL.$paySign);
// 存入订单
$order = Db::name('member_order')->insert($member_order);
// $paysign = get_sign($params_for_paysign, $key, false);
return json(['code'=>1,'msg'=>'','data'=>['appId'=>$appid,'nonceStr'=>$nonce_str,'package'=>'prepay_id='.$prepay_id,'signType'=>'MD5','timeStamp'=>$time,'paySign'=>$paySign]]);
}
/**
* 回调
*/
public function back()
{
$xml = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
if (empty($xml)) {
# 如果没有数据,直接返回失败
return "错误";
}
$info1 = $this->xmlToArray($xml);
$appid = $info1['appid'];
$mch_id = $info1['mch_id'];
$nonce_str = $info1['nonce_str'];
$transaction_id = $info1['transaction_id'];
$sign = strtoupper(md5("appid=$appid&mch_id=$mch_id&nonce_str=$nonce_str&transaction_id=$transaction_id&key=gengyunpeng412018298412018298412"));
$info2 = [
'appid'=>$info1['appid'],
'mch_id'=>$info1['mch_id'],
'nonce_str'=>$info1['nonce_str'],
'transaction_id'=>$info1['transaction_id'],
'sign'=>$sign,
];
$info3 = $this->arrayToXml($info2);
$xml_data = $this->curl_post('https://api.mch.weixin.qq.com/pay/orderquery',$info3);
$end_data = $this->xmlToArray($xml_data);
if ($end_data['return_msg']!="OK"){
$this->error('签名错误');
}
Db::startTrans();
try {
//成功
$status = Db::name('member_order')->where('member_order',$end_data['out_trade_no'])->value('status');
if($status != 1){
Db::name('member_order')->where('member_order',$end_data['out_trade_no'])->update(['status'=>1]);
Db::name('user')->where('openid',$end_data['openid'])->update(['level'=>1]);
$userid = Db::name('user')->where('openid',$end_data['openid'])->value('id');
$money = Db::name('user')->where('openid',$end_data['openid'])->value('money');
$money_log = [
'user_id'=>$userid,
'number'=>$end_data['total_fee']/100,
'before'=>$money,
'after' =>$money,
'type'=>$userid.'购买会员',
'create_time'=>time(),
];
Db::name('money_log')->insert($money_log);
$this->benefit($userid,$end_data['total_fee']/100);
}
Db::commit();
} catch (\Exception $e) {
// file_put_contents('4.txt',$end_data['out_trade_no']);
Db::rollback();
}
}
/**
- 生成签名
- @param WxPayConfigInterface $config 配置对象
- @param String $key 商户秘钥
- @param bool $needSignType 是否需要补signtype
- @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
*/
function get_sign($config, $key, $needSignType = true)
{ $sign_type = 'MD5';
if($needSignType) {
$sign_type = GetSignType();
}
//签名步骤一:按字典序排序参数
ksort($config);
$string = ToUrlParams($config);
//签名步骤二:在string后加入KEY
$string = $string . "&key=".$key;
//签名步骤三:MD5加密或者HMAC-SHA256
if($sign_type == "MD5"){
$string = md5($string);
} else if($sign_type == "HMAC-SHA256") {
$string = hash_hmac("sha256", $string, $key);
} else {
throw new Exception("签名类型不支持!");
}
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
/**
- 获取客户端IP地址
- @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
- @param boolean $adv 是否进行高级模式获取(有可能被伪装)
- @return mixed
*/
function get_client_ip($type = 0,$adv=false) {
$type = $type ? 1 : 0;
static $ip = NULL;
if ($ip !== NULL) return $ip[$type];
if($adv){
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$pos = array_search('unknown',$arr);
if(false !== $pos) unset($arr[$pos]);
$ip = trim($arr[0]);
}elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
}elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
}elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
// IP地址合法验证
$long = sprintf("%u",ip2long($ip));
$ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
return $ip[$type];
}
/**
- 格式化参数格式化成url参数
- @param $config array 待排序的参数数组
*/
function ToUrlParams($config)
{
$buff = "";
foreach ($config as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
/**
- 产生随机字符串,不长于32位
- @param int $length
- @return 产生的随机字符串
*/
function get_nonce_str($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
//数组转xml
function arrayToXml($arr) {
$xml = "<xml>";
foreach ($arr as $key => $val){
$xml.="<$key>$val</$key>";
}
if (!is_numeric($val)){
$xml.="<$key>$val</$key>";
}
else
$xml.="<$key><![CDATA[$val]]></$key>";
// }
$xml.="</xml>";
return $xml;
}
//Xml转数组
function xmlToArray($xml) {
$arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $arr;
}
/**
* 发送post请求
*/
public function curl_post($url , $data=array()){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
// POST数据
curl_setopt($ch, CURLOPT_POST, 1);
// 把post的变量加上
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}