当前位置: 首页 > 后端技术 > PHP

微信小程序支付问题解决

时间:2023-03-29 21:08:14 PHP

这几天一直在做小程序支付,没有使用官方SDK,所以发个帖子纯粹用官方文档。*注意作者使用的是PHP,但是支付过程是这样的。开发前必须阅读主流程。wx.requestPayment发起支付请求准备工具申请小程序微信支付获取商户ID,设置小程序微信支付秘钥注意:小程序只需要这两步。如果是web的话还需要设置支付目录授权域名,文档里面也写着:https://pay.weixin.qq.com/wik...统一下单官方文档:https://pay.weixin.qq.com/wik.../***Unifiedorder*/publicfunctionunifiedorder(){//需要进行以下配置,如有其他需求请自行配置$config=array('appid'=>'xxxxxxx',//这里是小程序appid'mch_id'=>'xxxxxxx',//商户ID'nonce_str'=>$this->getNonceStr(),//随机字符串'body'=>'Hereisthetest-test',//请按照文档要求填写合格名称'out_trade_no'=>time().$this->getNonceStr(2),//序号'total_fee'=>'20',//金额,分个单位,这里是0.2元'spbill_create_ip'=>'123.123.123.123',//当前IP'notify_url'=>'http://xxxx.com',//见谅孤陋寡闻,不明白'trade_type'=>'JSAPI',//必须填写JSAPI'openid'=>'xxxxxxxx'//当前用户的openid,在trade_type=使用JSAPI时,此项为必填项);$config['sign']=$this->getSignPay($config);$xmlData=$this->ToXml($config);//转换为xml数据$postData=$this->http_post($xmlData);$arrayData=$this->FromXml($postData);if($arrayData['return_code']=='SUCCESS'||$arrayData['result_code']=='SUCCESS'){return$arrayData['prepay_id'];//重点来了:走完so很多方法,只要这个值达到这一步就证明成功了一大半。}else{return$arrayData;//返回错误}}/***获取签名*/publicfunctiongetSignPay($config){$key='xxxxxxx';//商户秘钥,即生成的32位密码自己$strA='appid='.$config['appid'].'&body='.$config['body'].'&mch_id='.$config['mch_id'].'&nonce_str='.$config['nonce_str'].'¬ify_url='.$config['notify_url'].'&spbill_create_ip'.$config['spbill_create_ip'].'&total_fee='.$config['total_fee'].'&trade_type='.$config['trade_type'];//ASCII字典顺序$strB=$strA.'&key='.$key;$sign=strtoupper(md5($strB));//大写MD5return$sign;}/***随机字符串32位*/publicfunctiongetNonceStr($length=32){$chars="abcdefghijklmnopqrstuvwxyz0123456789";$str="";对于($i=0;$i<$length;$i++){$str.=substr($chars,mt_rand(0,strlen($chars)-1),1);}return$str;}/***arraytoXML*/publicfunctionToXml($data){if(!is_array($data)||count($data)<=0){thrownewWxPayException("数组数据例外!”);}$xml="";foreach($dataas$key=>$val){$xml.="<".$key.">".$val."";$xml.="";返回$xml;}/***xml转array*/publicfunctionFromXml($xml){if(!$xml){thrownewWxPayException("xml数据异常!");}libxml_disable_entity_loader(true);$this->values=json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true);return$this->values;}/***post请求*/publicfunctionhttp_post($url,$param,$post_file=false){$oCurl=curl_init();if(stripos($url,"https://")!==FALSE){curl_setopt($oCurl,CURLOPT_SSL_VERIFYPEER,FALSE);curl_setopt($oCurl,CURLOPT_SSL_VERIFYHOST,false);curl_setopt($oCurl,CURLOPT_SSLVERSION,1);//CURL_SSLVERSION_TLSv1}if(PHP_VERSION_ID>=50500&&class_exists('\CURLFile')){$is_curlFile=true;}else{$is_curlFile=false;if(defined('CURLOPT_SAFE_UPLOAD')){curl_setopt($oCurl,CURLOPT_SAFE_UPLOAD,false);}}if(is_string($param)){$strPOST=$param;}elseif($post_file){if($is_curlFile){foreach($paramas$key=>$val){if(substr($val,0,1)=='@'){}}}$strPOST=$参数;}else{$aPOST=array();foreach($paramas$key=>$val){$aPOST[]=$key."=".urlencode($val);}$strPOST=join("&",$aPOST);}curl_setopt($oCurl,CURLOPT_URL,$url);curl_setopt($oCurl,CURLOPT_RETURNTRANSFER,1);curl_setopt($oCurl,CURLOPT_POST,true);curl_setopt($oCurl,CURLOPT_POSTFIELDS,$strPOST);$sContent=curl_exec($oCurl);$aStatus=curl_getinfo($oCurl);curl_close($oCurl);if(intval($aStatus["http_code"])==200){返回$sContent;}else{返回错误;}}好现在已经获得了prepay_id的值,就算我们统一下单完成了,其实我更愿意称他为数据打包小程序的微信支付官方文档:https://developers.weixin.qq...先说一个小插曲,首先,我们的小程序前端需要触发pay,实现的功能肯定是点击小程序的一个trigger,然后pay,对吧,pay:function(e){//这里使用post请求然后使用我接下来要写的API支付代码获取小程序的支付参数success:function(res){wx.requestPayment({'timeStamp':toString(res.timeStamp),//把字符串传到这里,就可以了这里被骗了,不转账total_fee可能为空'nonceStr':toString(res.nonceStr),'package':toString(res.package),'signType':'MD5','paySign':toString(res.paySign),success:function(res){console.log(res);//这里可以跳转到带参数的地址},fail:function(res){console.info('支付失败',res);},complete:function(){console.info('支付触发回调',res);}})}}api支付为上述小程序代码的后端请求地址/***api组装数据*/publicfunctionpayApiBlack(){$appid='xxxxxx';//一个小程序appid,上面有重复,但是这样更直观$timeStamp=time();$nonceStr=$this->getNonceStr();//这是调用统一订单的方法,为了直观,我把这些代码写在一个类中$package='prepay_id='.$this->unifiedorder();$signType='MD5';$key='xxxxxx';//这里是商户Secretkey,32位,同上Face还有$strA='appId='.$appid.'&nonceStr='.$nonceStr.'package='.$package.'&=signType='.$signType.'&timeStamp='.$timeStamp.'&key='.$key;$paySign=strtoupper(md5($strA));$data=array('appid'=>$appid,'timeStamp'=>$timeStamp,'nonceStr'=>$nonceStr,'package'=>$package,'signType'=>$signType);return$data;//返回小程序}以上就是全部代码,并没有小程序支付回调的信息,所以我的想法是判断成功后跳转传递参数//这段代码是wx.requestPayment成功,省略部分代码//res回调参数包括用户uid等重要投递success:function(res){wx.redirect({url:'pages/pay/done?uid='+res.uid})}当然统一点餐的notify_url好像跟回调有关。至于怎么用,试了几次回调的CURD都没有反应,有时间再研究一下。以上代码仅作为支付流程的说明。所以如果真的要在项目中使用,还是要用官方的SDK,毕竟涉及到钱。