收藏
回答

米大师支付mp_sig签名一直提示错误

框架类型 问题类型 API/组件名称 终端类型 微信版本 基础库版本
小游戏 Bug midas.pay 微信安卓客户端 7.0.13 2.0.0
<?php
namespace Mypay;


use think\facade\Config;
use think\facade\Log;
use think\facade\Cache;
class miWxpay
{
	public function order($para,$openid,$cpData,$code,$gameid)
    {   
        $config = Config::get("pay.miWxpay");


        // Log::write("miWxpay::order()zzzzzzzzz".var_export($code,true),'notice');
        $offerId = '1450015409';
        $amt = 3;
        // $wxPay = new PayService($config['appid'],$config['appsecret'],$config['appKey']);
        $wxPay = new PayService($cpData['wxappId'],$cpData['wxappSecret'],$config['appKey']);
        $wxPay->createJsBizPackage($openid,$offerId,$amt, '11111122222222222aab',$code,$gameid);
    }
}


class PayService
{
	protected $appid;
    protected $appsecret;
    protected $appKey;


   	public function __construct($appid, $appsecret,$appKey)
    {
        $this->appid = $appid; 
        $this->appsecret = $appsecret;   
        $this->appKey = $appKey; 
    }




    //下单
    public function createJsBizPackage($openid, $offer_id, $amt, $orderid ,$code,$gameid)
    {
        $time = time();
    	//生成签名的数据
    	$unified = [
    		'openid' => $openid,
            'appid' => $this->appid,
            'offer_id' => $offer_id,
            'ts'	=> $time,
            'zone_id' => '1'//游戏服务器大区id		
            'pf'	=>	'android',
            // 'user_ip' => '127.0.0.1',
            // 'amt'	  => $amt,				//扣除游戏币数量,不能为0
            // 'bill_no'	  => $orderid,		//订单号
            // 'pay_item'	  => 'xxxxxxxabss' ,		//道具名称
            // 'app_remark'	  => 1 ,		//备注。会写到账户流水


        ];


    	//请求的数据
        $req = [
        	'openid' => $openid,
            'appid' => $this->appid,
            'offer_id' => $offer_id,
            'ts'	=> $time,
            'zone_id' => '1'//游戏服务器大区id		
            'pf'	=>	'android',
            // 'user_ip' => '127.0.0.1',
            'amt'	  => $amt,				//扣除游戏币数量,不能为0
            'bill_no'	  => $orderid,		//订单号
            // 'pay_item'	  => 'xxxxxxxabss' ,		//道具名称
            // 'app_remark'	  => 1 ,		//备注。会写到账户流水


        ];
    	$ACCESS_TOKEN = $this->getAccessToken($gameid);
        // $curl = 'https://api.weixin.qq.com/cgi-bin/midas/sandbox/pay?access_token='.$ACCESS_TOKEN;   //沙箱环境


        $curl = "https://api.weixin.qq.com/cgi-bin/midas/pay?access_token=".$ACCESS_TOKEN;   //正式


        //获取session_key
        if(!$session_key = $this->getSessionKey($code)){
            return ['status' => 0, 'msg' => 'session_key get error'];
        }
        //检察session_key是否过期
        if( !$this->checkSessionKey($session_key,$ACCESS_TOKEN,$openid) ){
            return ['status' => 0, 'msg'=>'session_key checkSessionKey error'];
        }


        $unified['sig'] = $this->GenerateSig($unified);
        $unified['mp_sig'] = $this->GenerateMpSig($ACCESS_TOKEN,$unified,$session_key);
        $req['sig'] = $unified['sig'];
        $req['mp_sig'] = $unified['mp_sig'];


        // $req['access_token'] = $ACCESS_TOKEN;


        Log::write("PayService::createJsBizPackage()===============req".var_export($req,true),'notice');


        $data = self::curlPost($curl,json_encode($req));


        //测试
  //       $test = [
  //           "openid"=>"odkx20ENSNa2w5y3g_qOkOvBNM1g",
		//     "appid"=>"wx1234567",
		//     "offer_id"=>"12345678",
		//     "ts"=>1507530737,
		//     "zone_id"=>"1",
		//     "pf"=>"android"	
  //       ];
		// $key =  "zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u";
		// $stingABC = $this->ToUrlParams($test);
  //       $stringSignTemp = $stingABC."&org_loc=/cgi-bin/midas/getbalance&method=POST&secret=".$key;
  //       $jmsf = hash_hmac('sha256', $stringSignTemp,$key );


        // Log::write("PayService::getAccessToken()session_key".var_export($session_key,true),'notice');
    	Log::write("PayService::createJsBizPackage()".var_export($data,true),'notice');


    }


    //检察seessionKey是否过期有效
    public function checkSessionKey($session_key,$access_token,$openid)
    {
        $SIGNATURE = hash_hmac('sha256', '' , $session_key );
        $data = self::curlGet("https://api.weixin.qq.com/wxa/checksession?access_token=".$access_token."&signature=".$SIGNATURE."&openid=".$openid."&sig_method=hmac_sha256");
        $data = json_decode($data,true);
        if($data['errcode'] != 0){
            Log::write('获取session_key->checkSessionKey::验证失败'.json_encode($data),'notice');
            return false;
        }
        return true;
        
    }


    //获取sessionkey
    public function getSessionKey($code)
    {   
        $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$this->appid.'&secret='.$this->appsecret.'&js_code='.$code.'&grant_type=authorization_code';
        $res = json_decode( GetHttps($url),true);
        if( empty($res['session_key']) || !isset($res['session_key']) )
        {   
            Log::write('获取session_key->GetSessionKey::状态::session_key does not exis,data::'.json_encode($res),'notice');
            return false;
        }
        return $res['session_key'];
    }  




    //Access_token 需要保存
    public function getAccessToken($gameid)
    {
        $CacheKey = "Access_token_".$gameid;
        // Cache::rm($CacheKey);
        $data = Cache::get($CacheKey);
        if(!$data){
            $wxdata = self::curlGet('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$this->appid.'&secret='.$this->appsecret);
            $wxdata = json_decode($wxdata,true);
            if( !isset($wxdata['access_token']) ){
                Log::write("PayService::getAccessToken()".var_export($wxdata['access_token'],true),'notice');
            }
            // Log::write("PayService::getAccessToken()ququququuuuuuuuuuuuuuuququ".var_export($wxdata,true),'notice');
            Cache::set($CacheKey,$wxdata['access_token'],3600);
            return $wxdata['access_token'];
        }
        // Log::write("PayService::getAccessToken()===================".var_export($data,true),'notice');
        return $data;


    }


    //GET
    public static function curlGet($url = '', $options = array())
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }


    //POST
    public static function curlPost($url = '', $postData = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }


    //Sig
    public function GenerateSig($urlObj)
    {	
    	$str = $this->ToUrlParams($urlObj);


    	$stringSignTemp =  $str."&org_loc=/cgi-bin/midas/pay&method=POST&secret=".$this->appsecret;
		 // Log::write("PayService::getAccessToken()sssssssssssssssssssssss".var_export($stringSignTemp,true),'notice');
    	//hmac_sha256
    	// return strtolower( hash_hmac('sha256', $this->appsecret,$stringSignTemp ) );
    	return hash_hmac('sha256', $stringSignTemp, $this->appsecret) ;


    }


    //Mp_Sig
    public function GenerateMpSig($access_token,$urlObj,$session_key)
    {	
    	$urlObj['access_token'] = $access_token;
    	$str = $this->ToUrlParams($urlObj);
    	$stringSignTemp =  $str."&org_loc=/cgi-bin/midas/pay&method=POST&session_key=".$session_key;
    	// Log::write("PayService::getAccessToken()sssssssssssssssssssssss".var_export($urlObj,true),'notice');
    	// Log::write("PayService::getAccessToken()xxxxxxxxxxxxxxxxxxxxxxx".var_export($stringSignTemp,true),'notice');
    	//hmac_sha256
    	// return strtolower( hash_hmac('sha256', $session_key, $stringSignTemp) );
    	return hash_hmac('sha256', $stringSignTemp, $session_key );
    }


    public function ToUrlParams($urlObj)
    {
        ksort($urlObj);
        $buff = "";
        foreach ($urlObj as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }
        
        $buff = trim($buff, "&");
        return $buff;
    }


}
回答关注问题邀请回答
收藏

1 个回答

登录 后发表内容
问题标签