Heim  >  Artikel  >  Backend-Entwicklung  >  关于微店整合微信支付时出现的的各种问题的记录 php版

关于微店整合微信支付时出现的的各种问题的记录 php版

WBOY
WBOYOriginal
2016-06-23 13:41:14904Durchsuche

由于公司项目的需要,需要在项目里整合微信支付,公司原有的项目中已有老版本的支付功能,在此不作讨论。我需要作的就是加入新版本的支付功能

让项目里可以支持新老两种版本的功能。在微信官方下载到了新版支付的php版sdk,看到 WxPay.ub.config.php,SDKRuntimeException.php, WxPayPubHelper.php

三个文件。我需要改造的就是WxPayPubHelper.php这个文件,因为这个文件现在是单用户配置的,所以我要让它变成多用户的,在改造的过程中遇到了几点问题,也是大家

可能会经常遇到的,在这分享出来,希望能给他人一些帮助。


q1:redirect_uri 参数错误的问题 !

这个问题出现的比例比较大,在sdk包里有一个demo的文件夹,里面有一个js_api_call.php文件,在他的13行里有如下代码:

	//使用jsapi接口	$jsApi = new JsApi_pub();	//=========步骤1:网页授权获取用户openid============	//通过code获得openid	if (!isset($_GET['code']))	{		//触发微信返回code码		$url = $jsApi->createOauthUrlForCode(WxPayConf_pub::JS_API_CALL_URL);		Header("Location: $url"); 	}else	{		//获取code码,以获取openid	    $code = $_GET['code'];		$jsApi->setCode($code);		$openid = $jsApi->getOpenId();	}

$url = $jsApi->createOauthUrlForCode(WxPayConf_pub::JS_API_CALL_URL);
这一句就是设置redirect_uri参数的地方,我把它改造成了自己的地址,代码如下:

$url = $jsApi->createOauthUrlForCode( $site_domain.base64_decode($_GET['uri']));

为什么要用base64编码呢,因为我的url是像这样的 :

index.php?g=Wap&m=Wxpay&a=newpay&token=$1&wecha_id=$2&orderid=$3

这个url又臭又长,而且很多&符,无法识别出哪部分是自己的url了,还有最重要的部分 WxPayHubHelper.php在大概822行的部分,有一个方法叫createOauthUrlForCode($redirectUrl),这个里面的$url这个变量没有进行url编码,请自己加一下,否则你的url里有参数将不能正常被识别,代码很简单:

$url = urlencode($redirectUrl); 这样就行。

进行了以上的设置后如果还出现redirect_uri的错误的话就要考虑你的支付路径权限的问题了,进入微信公众号的后台,请确保你的是服务号,并且已认证,查看方法是页面右上角。在确认了之后  点左侧菜单的 “开发者中心”,然后如图:

点击修改,填入“授权回调页面域名”,请确保这个域名和你的应用域名一致,这样应该就解决了这个问题。


q2:无法获取prepay_id的问题

首选请确保你 WxPayPubHelper.php这个文件里 UnifiedOrder_pub 这个类的getPrepayId这个方法能正常使用。

此方法代码如下:

	/**	 * 获取prepay_id	 */	function getPrepayId()	{		$this->postXml();		$this->result = $this->xmlToArray($this->response);		$prepay_id = $this->result["prepay_id"];		return $prepay_id;	}

查看posXml这个方法后发现调用了自己的createXml这个方法

postXml方法如下:

	/**	 * 	作用:post请求xml	 */	function postXml()	{	    $xml = $this->createXml();		$this->response = $this->postXmlCurl($xml,$this->url,$this->curl_timeout);		return $this->response;	}

这时需要确认你的$xml这个变量形式如下:

<xml><openid></openid>201501201705551389<out_trade_no></out_trade_no><total_fee>1</total_fee><notify_url></notify_url><trade_type></trade_type><appid></appid><mch_id>10020230</mch_id><spbill_create_ip></spbill_create_ip><nonce_str></nonce_str><sign></sign></xml>
尤其注意 openid的形式一定要类似这样的,全是数字或全是字母的一定是错误

然后postXmlCurl才能正确提交,提交后就能得到正确的prepay_id了


q3:在取到了prepay_id后,在进行付款的时候提示:公众号支付使用了无效的商户号

这个问题大部分是出现在二次签名的时候,由于第二次签名和第一次签名不一致导致的

这时我们需要看WxPayPubHelper.php这个文件里的JsApi_pub这个类,这个类中的getParameters这个方法是进行第二次签名的关键,代码如下:

	/**	 * 	作用:设置jsapi的参数	 */	public function getParameters()	{		$jsApiObj["appId"] = WxPayConf_pub::APPID;		$timeStamp = time();	    $jsApiObj["timeStamp"] = "$timeStamp";	    $jsApiObj["nonceStr"] = $this->createNoncestr();		$jsApiObj["package"] = "prepay_id=$this->prepay_id";	    $jsApiObj["signType"] = "MD5";	    $jsApiObj["paySign"] = $this->getSign($jsApiObj);	    $this->parameters = json_encode($jsApiObj);				return $this->parameters;	}

由于我需要根据数据表里的设置来动态的调用key,所以我的这个签名要符合多个商家的,代码改动如下:

	/**	 * 	作用:设置jsapi的参数	 */	public function getParameters()	{		$jsApiObj["appId"] = $this->config['appid'];		$timeStamp = time();	    $jsApiObj["timeStamp"] = "$timeStamp";	    $jsApiObj["nonceStr"] = $this->createNoncestr();		$jsApiObj["package"] = "prepay_id=$this->prepay_id";	    $jsApiObj["signType"] = "MD5";	    $jsApiObj["paySign"] = $this->getSign($jsApiObj, $this->config['key']);	    $this->parameters = json_encode($jsApiObj);				return $this->parameters;	}

getSign这个方法原型不帖了,改动后如下:

	/**	 * 	作用:生成签名	 */	public function getSign($Obj, $key ='')	{		foreach ($Obj as $k => $v)		{			$Parameters[$k] = $v;		}		//签名步骤一:按字典序排序参数		ksort($Parameters);		$String = $this->formatBizQueryParaMap($Parameters, false);		//echo '【string1】'.$String.'';		//签名步骤二:在string后加入KEY		if ($key!='') {			$String = $String."&key=".$key;		}else{			$String = $String."&key=".WxPayConf_pub::KEY;		}		//echo "【string2】".$String."";		//签名步骤三:MD5加密		$String = md5($String);		//echo "【string3】 ".$String."";		//签名步骤四:所有字符转为大写		$result_ = strtoupper($String);		//echo "【result】 ".$result_."";		return $result_;	}

可以看到,我只是多加了一个参数,加了一个判断,因为我不想过多的破坏原来的代码,所以这样加了。

在这样的改造完成后,我遇到的问题都解决了。希望对正在看的你能有所帮助,如果还有问题可以给我留言!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn