解决微信支付:https://ask.dcloud.net.cn/article/34913
重点:第二次签名
两个点:
1、先生成prepareid(预订单),
2、根据prepareid再进行一次签名才可以返回给app!
预支付:要返回值:对应7个值
{
"appid": "wx779a**27b1aaeb10",
"partnerid": "143**41502",
"noncestr": "ZeIlmt3FbV8MzfIo",
"package": "Sign=WXPay",
"prepayid": "wx2017041420152166c4aa07b80812189917",
"timestamp": 1492172122,
"sign": "5b89b644d95779dc304928cdfac68a86"
}
http://demo.dcloud.net.cn/payment/wxpayv3.HBuilder/?total=1
这个签名,要重新根据参数自己生成出来,不能用之前生成的签名
修改后的代码:
/**
* 生成APP第二次签名专用
* @param int $wx_type $wx_type =2用另一个微信商户帐号支付参数 =0所有微信支付都只用一个商户支付帐号参数
* @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
*/
public function signapp($data,$wx_type='') //$prepayid这个参数就是第1步里面获取的预订单id
{
// $data = [];
// $time = (string)time();
// $rand = md5(time() . mt_rand(0, 1000));
// $data['timestamp'] = $time;
// $data['appid'] = '这是你的appid';
// $data['partnerid'] = '这是你的商户号';
// $data['prepayid'] = $prepayid;
// $data['noncestr'] = $rand;
// $data['package'] = 'Sign=WXPay'; //介个是固定的
// $sign = MakeSignapp2($data,$wx_type);
//取得支付参数
$wxconfing=wx_confing();
if($wx_type==2){//=2用另一个微信商户帐号支付参数 =0所有微信支付都只用一个商户支付帐号参数
$KEY='hgfuhy88888888888890g45';//商户API密私
}else{
$KEY=$wxconfing['KEY'];
}
//签名步骤一:按字典序排序参数
ksort($data);
// $string = $this->ToUrlParamsapp($data);
$buff = "";
foreach ($data as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$string = trim($buff, "&");
//签名步骤二:在string后加入KEY
$string = $string . "&key=".$KEY; //注意,敲黑板了,这里还要加上在config中配置过的key
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
//dump($result);die;
$data['sign'] = $result;
return $data; //这个数组就是返回给app的信息
}
/**
* 获取设置的值
*/
public function GetValues()
{
return $this->values;
}
}
具体例子:
/**
* 获取预支付信息
*
* @param array $params 订单信息
* @param string $params['body'] 商品简单描述
* @param string $params['out_trade_no'] 商户订单号, 要保证唯一性
* @param string $params['total_fee'] 标价金额, 请注意, 单位为分!!!!!
* @param int $type =0所有微信支付都只用一个商户支付帐号参数,=1用另一个微信商户帐号支付参数
* @param int $wx_type 0=微信其它支付 =1是微信小程序(支付需要用小程appid、secret)
* @return array 预支付信息
*/
public static function getAppParams($params,$type='')
{
// 1.校检参数
$that = new self();
//dump("00");
//dump($params);die;
$that->checkParams($params);
// 2.组装参数
//dump($params);
//dump($params['openid']);die;
$input = $that->getPostData($params);
//dump($input);die;
if($type==2){//=1用另一个微信商户帐号支付参数
$wx_type=2;
}
// 3.获取预支付信息
$result = \WxPayApi::unifiedOrderApp($input,'',$wx_type);//=2用另一个微信商户帐号支付参数
//$result=json_encode($result2,true);
//dump($result);die;
// 4.返回支付参数
return $result;
}
/**
*
* APP支付统一下单,WxPayUnifiedOrder中out_trade_no、body、total_fee、trade_type必填
* appid、mchid、spbill_create_ip、nonce_str不需要填入
* @param WxPayUnifiedOrder $inputObj
* @param int $timeOut
* @param int $wx_type 0=微信其它支付 =1是微信小程序(支付需要用小程appid、secret) =2用另一个微信商户帐号支付参数
* @throws WxPayException
* @return 成功时返回,其他抛异常
*/
public static function unifiedOrderApp($inputObj, $timeOut = 6,$wx_type='')
{
//初始化,取得微信支付参数
$wxconfing=wx_confing();
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//检测必填参数
if(!$inputObj->IsOut_trade_noSet()) {
throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");
}else if(!$inputObj->IsBodySet()){
throw new WxPayException("缺少统一支付接口必填参数body!");
}else if(!$inputObj->IsTotal_feeSet()) {
throw new WxPayException("缺少统一支付接口必填参数total_fee!");
}else if(!$inputObj->IsTrade_typeSet()) {
throw new WxPayException("缺少统一支付接口必填参数trade_type!");
}
//关联参数
if($inputObj->GetTrade_type() == "JSAPI" && !$inputObj->IsOpenidSet()){
throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
}
if($inputObj->GetTrade_type() == "NATIVE" && !$inputObj->IsProduct_idSet()){
throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
}
$NOTIFY_URL=$wxconfing['NOTIFY_URL'];//异步通知url
if($wx_type==2){
$APPID='wxd49cae4321347238';//appID
$MCHID='1522613141';//商户号
}else{
$APPID=$wxconfing['wx_appid'];//appID
$MCHID=$wxconfing['MCHID'];//商户号
}
//dump($APPID);die;
//异步通知url未设置,则使用配置文件中的url
if(!$inputObj->IsNotify_urlSet()){
$inputObj->SetNotify_url($NOTIFY_URL);//异步通知url
}
$inputObj->SetAppid($APPID);//公众账号ID
$inputObj->SetMch_id($MCHID);//商户号
$inputObj->SetSpbill_create_ip(get_client_ip());//终端ip
//$inputObj->SetSpbill_create_ip("1.1.1.1");
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
//签名
$inputObj->SetSignApp($wx_type);
$xml = $inputObj->ToXml();
$startTimeStamp = self::getMillisecond();//请求开始时间
$response = self::postXmlCurl($xml, $url, false, $timeOut);
//xml转数组
libxml_disable_entity_loader(true);
$result= json_decode(json_encode(simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
//dump($result['sign']);die;
// 统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。
// 参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay
//$Sign=$result['sign'];
$time_stamp = time();
$pack = 'Sign=WXPay';//介个是固定的
//$pack = 'Sign='.$Sign;
//输出参数列表
$prePayParams =array();
$prePayParams['appid'] =$result['appid'];
$prePayParams['noncestr'] =$result['nonce_str'];
$prePayParams['package'] =$pack;
$prePayParams['partnerid'] =$result['mch_id'];
$prePayParams['prepayid'] =$result['prepay_id'];
$prePayParams['timestamp'] =$time_stamp;
//dump($prePayParams);
//第二次签名:
$sign = WxPayDataBase::signapp($prePayParams,2);//=2用另一个微信商户帐号支付参数 =0所有微信支付都只用一个商户支付帐号参数
$prePayParams['sign'] =$sign;
//echo json_encode($prePayParams);
$result3 = WxPayResults::InitFromArray($prePayParams,true)->GetValues();
self::reportCostTime($url, $startTimeStamp, $result3);//上报请求花费时间
return $result3;
}