CI框架

  > 微信支付的签名问题

微信支付的签名问题

最近在小程序折腾微信支付的时候,签名什么的怕是最麻烦的事情。

我封装到了ci框架中的方法。

准备支付的条件

1.微信认证

2.开通了微信支付

3.开通了商户号

线上代码,然后在慢慢解释。

吊起微信支付的统一下单接口,这个接口不仅仅小程序要使用,其他的web,公众号开发都要使用。

最重要的东西prepay_id

接口如下

https://api.mch.weixin.qq.com/pay/unifiedorder

完整代码如下:

private function pay($data_info,$openid)
{
	// URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder
	// https_request($url,$data = null)
	$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

	$now = time();

	$pid = $data_info['pid']; //订单号
	$total_fee = $data_info['price'] * 100; //微信以分为单位
	$attach = $this->Product_model->getProductInfo($pid,'title');//商品名称


	// $out_trade_no = $oid.time();
	$out_trade_no = $pid."_".time();
	$appid = '你的appid';
	$mch_id = '1505358751';
	$nonce_str = $this->nonce_str();
	$notify_url = "https://lebeier.caisangzi.com/";//回调地址;
	$spbill_create_ip = $this->getIp();
	
	$trade_type = 'JSAPI';
	$body = '商城小程序-测试付款';

	$tmp['appid'] = $appid;
	// $tmp['attach'] = $attach;
    $tmp['body'] = $body;
    $tmp['mch_id'] = $mch_id;
    $tmp['nonce_str'] = $nonce_str;//随机字符串
    $tmp['notify_url'] = $notify_url;
    $tmp['openid'] = $openid;
    $tmp['out_trade_no'] = $out_trade_no;
    $tmp['spbill_create_ip'] = $spbill_create_ip;//终端的ip
    $tmp['total_fee'] = $total_fee;//总金额 最低为1分钱 必须是整数
    $tmp['trade_type'] = $trade_type;



    $sign = $this->sign($tmp);//签名



	// $this->sign($data);wKSVYvlsWdHRfHEunEJqtPpUETSIkEWF

	$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>
	<spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
	<total_fee>'.$total_fee.'</total_fee>
	<trade_type>'.$trade_type.'</trade_type>
	<openid>'.$openid.'</openid>
	<sign>'.$sign.'</sign>
	</xml>
	';



	$xml = $this->https_request($url,$xml);
	$res = $this->xml($xml);//全要大写
	
	$data = array();
	if( $res['RETURN_CODE'] == 'SUCCESS' && $res['RESULT_CODE'] == 'SUCCESS')
	{
        $time = time();
        $tmp='';//临时数组用于签名
        $tmp['appId'] = $appid;
        $tmp['nonceStr'] = $nonce_str;
        $tmp['package'] = 'prepay_id='.$res['PREPAY_ID'];
        $tmp['signType'] = 'MD5';
        $tmp['timeStamp'] = "{$time}";
        $data['state'] = 1;
        $data['timeStamp'] = "{$time}";//时间戳
        $data['nonceStr'] = $nonce_str;//随机字符串
        $data['signType'] = 'MD5';//签名算法,暂支持 MD5
        $data['package'] = 'prepay_id='.$res['PREPAY_ID'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
        $data['paySign'] = $this->sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档;
        $data['out_trade_no'] = $out_trade_no;
    }
    else
    {
        $data['state'] = 0;
        $data['text'] = "错误";
        $data['RETURN_CODE'] = $res['RETURN_CODE'];
        $data['RETURN_MSG'] = $res['RETURN_MSG'];
    }

	return $data; //小程序需要的数据 返回前端
	// exit;

}

其中的方法

private function sign($data)
{
    $stringA = '';
    foreach ($data as $key=>$value){
        if(!$value) continue;
        if($stringA) $stringA .= '&'.$key."=".$value;
        else $stringA = $key."=".$value;
    }
    $wx_key = '后台自己设置的32位key,pay.weixin.qq.com';//申请支付后有给予一个商户账号和密码,登陆后自己设置key
    $stringSignTemp = $stringA.'&key='.$wx_key;//申请支付后有给予一个商户账号和密码,登陆后自己设置key 
    return strtoupper(md5($stringSignTemp));

}

private function nonce_str()
{
    $result = '';
    $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
    for ($i=0;$i<32;$i++)
    {
        $result .= $str[rand(0,48)];
    }
    return $result;
}


private function getIp() 
{
    static $realip = NULL;
    if ($realip !== NULL) {
        return $realip;
    }
 
    if (getenv( 'HTTP_X_FORWARDED_FOR')) {
        $realip = getenv( 'HTTP_X_FORWARDED_FOR');
    } elseif (getenv( 'HTTP_CLIENT_IP')) {
        $realip = getenv( 'HTTP_CLIENT_IP');
    } else {
        $realip = getenv( 'REMOTE_ADDR');
    }
    preg_match("/[\d\.]{7,15}/", $realip, $onlineip);
    $realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';
 
    return $realip;
}


private function 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') continue;
        $tag = $vals[$value[0]]['tag'];
        $value = $vals[$value[0]]['value'];
        $data[$tag] = $value;
    }
    return $data;
}

先到这里有时间我再解释。

sign方法就是获取签名,

getip就是获取ip的方法,

xml方法就是将返回的xml文件转变为php可以使用的数组,

至于noncestr就是随机字符串,

其实出错最多的也就是签名的问题。

也就是sign的问题,那么我们先看看需要的参数

$tmp['appid'] = $appid;//appid,注意这里是小程序的appid
// $tmp['attach'] = $attach;
$tmp['body'] = $body;
$tmp['mch_id'] = $mch_id;
$tmp['nonce_str'] = $nonce_str;//随机字符串
$tmp['notify_url'] = $notify_url;
$tmp['openid'] = $openid;
$tmp['out_trade_no'] = $out_trade_no;
$tmp['spbill_create_ip'] = $spbill_create_ip;//终端的ip
$tmp['total_fee'] = $total_fee;//总金额 最低为一块钱 必须是整数
$tmp['trade_type'] = $trade_type;

官方的解释

官方文档点击这里

暂时不用考虑证书的问题,解决签名的重要步骤就是要先确认签名的验证看看你的参数得到的和系统得到的是否一样

要使用校验工具

如果确实是一致的签名,那么就是最重要的appid和密匙是否正确,另外小程序的支付不需要考虑证书的问题,

但是如果是企业付款,就必须要考虑在服务器上安装证书。


over。有不明白的可以留言或者直接邮件联系,或者qq

发布时间:2018-08-27,15:28:19

微信支付,小程序支付代码接口。

作者:澎蠡

让学习成为一种习惯,让知识交流变成一种生活方式。