​ PHP实现微信支付及退款流程的实例详解-php教程

资源魔 25 0

PHP完成微信领取及退款流程实例

微信小顺序领取的次要逻辑集中正在后端,前端只要携带领取所需的数据申请后端接口而后依据前往后果做相应胜利失败解决便可。本篇文章后端应用的是php,偏重于整个领取的流程以及一些细节方面的货色。以是应用其余后端言语的冤家有需求也是能够看一下的。不少时分开发的需要以及相应成绩的处理真的要跳出言语语法层面,去从零碎以及流程的角度思考。

1、微信领取

领取次要分为几个步骤:

前端携带领取需求的数据(商品id,采办数目等)发动领取申请

后端正在接纳到领取申请后,解决领取数据,而后携带解决后的数据申请 微服气务器 的 领取对立下单接口

后端接纳到上一步申请微服气务器的前往数据,再次解决,而后前往前端让前端能够开端领取。

前端进行领取举措

前端领取实现后,微服气务器会向后端发送领取告诉(也就是微信要通知你客户曾经付过钱了),后端依据这个告诉确定领取实现,而后就去做领取实现后的相应举措,比方修正定单状态,增加买卖日记啊等等。

从这几个步骤能够看出,后端次要的作用就是将领取需求的数据传给微服气务器,再依据微服气务器的呼应确定领取能否实现。

这个流程仍是蛮容易了解的。抽象的说,前端就是个主顾,后端就是店家,微服气务器的对立下单接口就像收银员。主顾跟店家说,我是谁谁谁,如今我要付几何几何钱给你买甚么甚么。店家就跟收银员说,阿谁谁谁谁要付几何钱,你预备收钱吧。收银员收到钱后,就去通知店家,我曾经收到钱了,你给他货色吧。

上面就具体的阐明一下各个步骤的详细完成。

1. 前端申请领取

前端申请领取,就是简略的携带领取需求的数据,例如用户标识,领取金额,领取定单 ID 等等跟 **你的营业逻辑无关** 或许跟 **下一步申请微服气务器领取对立下单接口需求的数据相关** 的相干数据,应用微信小顺序的 wx.request( ) 去申请后真个领取接口。

2. 后端申请微服气务器

后端接纳到前端发送的领取申请后,能够进行一下相干验证,例如判别一下用户有无成绩,领取金额对不合错误等等。

正在验证没甚么成绩,能够向微服气务器请求领取之后,后端需求应用 微信规则的数据格局 去申请微信的领取对立下单接口。

微信规则的申请数据:

这需求较多代码完成。由于需求的数据个数较多,并且还需求加密并以 XML 格局发送。

起首,有如下数据是应用小顺序领取必需提供应微服气务器的参数。

小顺序 appid。写小顺序的大略不没有晓得这个的。。。

用户标识 openid。也就是用户的小顺序标识,正在我上篇博客中阐明了若何猎取。

商户号 mch_id 。请求守旧微信领取商户认证胜利后微信发给你的邮件里有

商户定单号 out_trade_no 。商户为此次领取天生的定单号

总金额 total_fee 。定单总金额,很首要的一点是单元是分,要特地留意。

微服气务器回调告诉接口地点 notify_url。微信确认钱曾经到账后,会往这个地点屡次发送音讯,通知你主顾曾经付完钱了,你需求前往音讯给微信示意你曾经收到了告诉。。这个地点不克不及有端标语,同时要能间接承受POST办法申请。

买卖类型 trade_type 。微信小顺序领取此值对立为 JSAPI

商品信息 Body。相似"腾讯-游戏"这类格局

终端IP地点 spbill_create_ip 。终端地点IP,也就是申请领取的 IP 地点。

随机字符串 nonce_str 。需求后端随机天生的字符串用于保障数据平安。微信要求没有长于32位。

署名 sign 。应用下面的一切参数进行相应解决加密天生署名。(详细解决形式可见下文代码,可间接复用。)

正在解决好以上一切数据后,将这些数据以 XML 格局整顿并以 POST 办法发送到 微信领取对立下单接口

3.后端承受微服气务器前往数据

微服气务器正在接纳到领取数据之后,假如数据不成绩,其会前往用于领取的相应数据,此中十分首要的是 称号为 prepay_id 的数据字段,需求将此数据前往前端,前端能力持续领取。

因而,正在后端接纳到微服气务器的前往数据后,需求进行相应的解决,终极前往到前端以下数据:

appid 没有需多说

timeStamp 以后工夫戳

nonceStr 随机字符串

package 就是下面提到的 prepay_id,不外切记格局如 “prepay_id= prepay_id_item“。不然会招致谬误。

signType 加密形式,普通应该是 MD5

paySign 对以上数据进行相应解决并加密。

到这里,后真个领取接口曾经实现了接纳前端领取申请,并前往了前端领取所需数据的性能。

4. 前端发动领取

前端正在接纳到前往数据后,应用 wx.requestPayment() 来申请发动领取。此 API 需求的工具参数各项值就是咱们上一步前往的各个数据。

5.后端承受微服气务器回调

前端实现领取后,微服气务器确认领取曾经实现。就会向第一步中设置的回调地点发送告诉。后真个接纳回调接口正在接纳到告诉后,就能够判别领取能否实现,从而决议后续举措。

需求留意的是,正在接纳到微服气务器的回调告诉后,依据告诉的result_code字段判别领取能否胜利。正在承受到胜利的告诉后,后端需求前往success数据向微服气务器奉告已失去回调告诉。不然微服气务器会不绝的向后端发送音讯。另外微信的告诉是以XML格局发送的,正在承受解决时需求留意。

微信的大略领取流程就是这样。如下是PHP语法的微信领取类,能够对比下面的步骤引见,加深了解。正在需求领取时,间接传入参数实例化此类再挪用类的 pay 办法便可。

//微信领取类

class WeiXinPay{
  //=======【根本信息设置】=====================================
  //微信大众号身份的惟一标识
  protected $APPID = appid;//填写您的appid。微信大众平台里的
  protected $APPSECRET = secret;
  //受理商ID,身份标识
  protected $MCHID = '11111111';//商户id
  //商户领取密钥Key
  protected $KEY = '192006250b4c09247ec02edce69f6a2d';
  //回调告诉接口
  protected $APPURL =   'https://smart.afei.com/receivesuc';
  //买卖类型
  protected $TRADETYPE = 'JSAPI';
  //商品类型信息
  protected $BODY = 'wx/book';
  //微信领取类的结构函数
  function __construct($openid,$outTradeNo,$totalFee){
    $this->openid = $openid; //用户惟一标识
    $this->outTradeNo = $outTradeNo; //商品编号
    $this->totalFee = $totalFee; //总价
  }
  //微信领取类向外暴露的领取接口
  public function pay(){
    $result = $this->weixinapp();
    return $result;
  }
   //对微信对立下单接口前往的领取相干数据进行解决
   private function weixinapp(){
     $unifiedorder=$this->unifiedorder();
     $parameters=array(
     'appId'=>$this->APPID,//小顺序ID
     'timeStamp'=>''.time().'',//工夫戳
     'nonceStr'=>$this->createNoncestr(),//随机串
     'package'=>'prepay_id='.$unifiedorder['prepay_id'],//数据包
     'signType'=>'MD5'//署名形式
       );
     $parameters['paySign']=$this->getSign($parameters);
     return $parameters;
   }
  /*
   *申请微信对立下单接口
   */
  private function unifiedorder(){
    $parameters = array(
      'appid' => $this->APPID,//小顺序id
      'mch_id'=> $this->MCHID,//商户id
      'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],//终端ip
      'notify_url'=>$this->APPURL, //告诉地点
      'nonce_str'=> $this->createNoncestr(),//随机字符串
      'out_trade_no'=>$this->outTradeNo,//商户定单编号
      'total_fee'=>floatval($this->totalFee), //总金额
      'open_id'=>$this->openid,//用户openid
      'trade_type'=>$this->TRADETYPE,//买卖类型
      'body' =>$this->BODY, //商品信息
    );
    $parameters['sign'] = $this->getSign($parameters);
    $xmlData = $this->arrayToXml($parameters);
    $xml_result = $this->postXmlCurl($xmlData,'https://api.mch.weixin.qq.com/pay/unifiedorder',60);
    $result = $this->xmlToArray($xml_result);
    return $result;
  }
  //数组转字符串办法
  protected function arrayToXml($arr){
    $xml = "<xml>";
    foreach ($arr as $key=>$val)
    {
      if (is_numeric($val)){
        $xml.="<".$key.">".$val."</".$key.">";
      }else{
         $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
      }
    }
    $xml.="</xml>";
    return $xml;
  }
  protected function xmlToArray($xml){
    $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $array_data;
  }
  //发送xml申请办法
  private static function postXmlCurl($xml, $url, $second = 30)
  {
    $ch = curl_init();
    //设置超时
    curl_setopt($ch, CURLOPT_TIMEOUT, $second);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
    //设置header
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    //要求后果为字符串且输入到屏幕上
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    //post提交形式
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
    curl_setopt($ch, CURLOPT_TIMEOUT, 40);
    set_time_limit(0);
    //运转curl
    $data = curl_exec($ch);
    //前往后果
    if ($data) {
      curl_close($ch);
      return $data;
    } else {
      $error = curl_errno($ch);
      curl_close($ch);
      throw new WxPayException("curl犯错,谬误码:$error");
    }
  }
  /*
   * 对要发送到微信对立下单接口的数据进行署名
   */
  protected function getSign($Obj){
     foreach ($Obj as $k => $v){
     $Parameters[$k] = $v;
     }
     //署名步骤一:按字典序排序参数
     ksort($Parameters);
     $String = $this->formatBizQueryParaMap($Parameters, false);
     //署名步骤二:正在string后退出KEY
     $String = $String."&key=".$this->KEY;
     //署名步骤三:MD5加密
     $String = md5($String);
     //署名步骤四:一切字符转为年夜写
     $result_ = strtoupper($String);
     return $result_;
   }
  /*
   *排序并格局化参数办法,署名时需求应用
   */
  protected function formatBizQueryParaMap($paraMap, $urlencode)
  {
    $buff = "";
    ksort($paraMap);
    foreach ($paraMap as $k => $v)
    {
      if($urlencode)
      {
        $v = urlencode($v);
      }
      //$buff .= strtolower($k) . "=" . $v . "&";
      $buff .= $k . "=" . $v . "&";
    }
    $reqPar;
    if (strlen($buff) > 0)
    {
      $reqPar = substr($buff, 0, strlen($buff)-1);
    }
    return $reqPar;
  }
  /*
   * 天生随机字符串办法
   */
  protected function createNoncestr($length = 32 ){
     $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
     $str ="";
     for ( $i = 0; $i < $length; $i++ ) {
     $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
     }
     return $str;
     }
}

以上就是微信领取的相干流程。无理清思绪后,流程仍是比拟明晰以及简略的。重点正在于需求留意一些细节成绩,例如数据格局,加密办法等。

上面说一下微信小顺序退款的详细完成

2、微信退款

小顺序退款的流程以及付款类似,但有一些细节上的没有同。

起首退款的步骤通常以下:

用户前端点击退款按钮后,后端接纳到用户的退款申请经过商城后盾出现给商户,商户确定容许退款后,后端再发动向微信退延接口的申请来申请退款。

后端向微信退延接口发送申请后,失去呼应信息,确定退款能否实现,依据退款能否实现再去进行扭转定单状态等营业逻辑。

退款的步骤绝对微信领取来讲比拟简略。

值患上留意的有如下两点:

1.向微信退延接口申请退款后,依据失去的呼应是能够间接确定退款能否实现的。再也不需求设置专门的回调接口期待微信告诉。当然假如需求也是能够正在微信商户平台设置回调接口承受从而承受微信回调的,但并非必需的。

2.退款申请需求正在申请效劳器装置微信提供的平安证书,也就是说,发动退款申请相比拟领取申请正在申请时申请办法不克不及复用,由于微信退款需求携带证书的申请,此证书可正在请求微信商户号胜利后从微信商户平台自行下载,Linux下的PHP开发环境的证书只要要放正在网站根目次的cert文件夹中便可。其余开发环境可能需求导入操作。

上面解说一下退款的详细步骤

一. 用户发动退款申请

用户正在前端发动退款申请,后端接纳到退款申请,将相应定单标志为请求退款,展现正在后盾.商户查看后,假如赞同退款再进行相应操作.尔后才进入真实的退款流程.

二. 商户发动退款申请

商户赞同退款后,后端即向微信提供的退款 API 发动申请.

同申请微信领取API同样.退款申请也需求将需求的参数进行署名后以XML发送到微信的退款API

退款申请需求的参数以下(多个参数正在领取API申请时也有应用):

参数:

appid

mch_id 商户号。请求守旧微信领取商户认证胜利后微信发给你的邮件里有

out_trade_no 商户定单号。退款定单正在领取时天生的定单号

out_refund_no 退款定单号。由后端天生的退款单号,需求保障惟一,由于多个一样的退款单号只会退款一次。

total_fee 总金额。定单总金额,单元为分。

refund_fee 退款金额。 需求退款的金额,单元一样为分

op_user_id 操作员。与商户号相反便可

nonce_str 随机字符串。同领取申请

署名 sign 。应用下面的一切参数进行相应解决加密天生署名。(详细解决形式与领取相反,可间接复用。)

注:我就是由于正在实例化的时分不传入key(秘钥)参数,不断报错署名谬误。

三. 退款实现

正在发动退款申请后,就能够间接依据申请的呼应XML中的 result_code字段来判别退款能否胜利,从而对定单状态进行解决以及后续操作。没有需求像领取那样期待另外一个接口的告诉来确定申请状态。当然如上文所说,假如需求微服气务器发送告诉到后真个话,能够到微信商户平台进行设置。

退款由于流程与领取迥然不同,因而退款的PHP类我抉择了间接承继领取类,

代码以下,留意区别退款申请办法postXmlSSLCurl以及领取申请办法postXmlCurl的区分,这也就是上文提到的退款需求的双向证书的应用。

class WinXinRefund extends WeiXinPay{
  protected \$SSLCERT_PATH = 'cert/apiclient_cert.pem';//证书门路
  protected \$SSLKEY_PATH = 'cert/apiclient_key.pem';//证书门路
  protected \$opUserId = '1234567899';//商户号
function __construct($openid,$outTradeNo,$totalFee,$outRefundNo,$refundFee){
  //初始化退款类需求的变量
  $this->openid = $openid;
  $this->outTradeNo = $outTradeNo;
  $this->totalFee = $totalFee;
  $this->outRefundNo = $outRefundNo;
  $this->refundFee = $refundFee;
} 
public function refund(){
  //对外暴露的退延接口
  $result = $this->wxrefundapi();
  return $result;
}
private function wxrefundapi(){
  //经过微信api进行退款流程
  $parma = array(
    'appid'=> $this->APPID,
    'mch_id'=> $this->MCHID,
    'nonce_str'=> $this->createNoncestr(),
    'out_refund_no'=> $this->outRefundNo,
    'out_trade_no'=> $this->outTradeNo,
    'total_fee'=> $this->totalFee,
    'refund_fee'=> $this->refundFee,
    'op_user_id' => $this->opUserId,
  );
  $parma['sign'] = $this->getSign($parma);
  $xmldata = $this->arrayToXml($parma);
  $xmlresult = $this->postXmlSSLCurl($xmldata,'https://api.mch.weixin.qq.com/secapi/pay/refund');
  $result = $this->xmlToArray($xmlresult);
  return $result;
}
//需求应用证书的申请
function postXmlSSLCurl($xml,$url,$second=30)
{
  $ch = curl_init();
  //超不时间
  curl_setopt($ch,CURLOPT_TIMEOUT,$second);
  //这里设置代办署理,假如有的话
  //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
  //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
  curl_setopt($ch,CURLOPT_URL, $url);
  curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
  curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
  //设置header
  curl_setopt($ch,CURLOPT_HEADER,FALSE);
  //要求后果为字符串且输入到屏幕上
  curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
  //设置证书
  //应用证书:cert 与 key 辨别属于两个.pem文件
  //默许格局为PEM,能够正文
  curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
  curl_setopt($ch,CURLOPT_SSLCERT, $this->SSLCERT_PATH);
  //默许格局为PEM,能够正文
  curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
  curl_setopt($ch,CURLOPT_SSLKEY, $this->SSLKEY_PATH);
  //post提交形式
  curl_setopt($ch,CURLOPT_POST, true);
  curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
  $data = curl_exec($ch);
  //前往后果
  if($data){
    curl_close($ch);
    return $data;
  }
  else {
    $error = curl_errno($ch);
    echo "curl犯错,谬误码:$error"."<br>";
    curl_close($ch);
    return false;
  }
}}

三. 总结

以上就是对于微信领取以及退款的流程及相干常识的引见。文中的 PHP类 均封装间接可用。

由于微信领取以及退款触及的货色较为冗杂,不少人间接看民间文档可能会一头雾水,以是看过此文理解流程以及要点后,再去看微信民间文档。一方面能够更明晰的理解小顺序的领取以及退款流程。另外一方面,本文由于篇幅无限及作者才能无限,一定有没有暇顾及或有所纰漏的地方。为求稳当,仍是需求多看看民间开发文档。究竟结果事涉领取,出个BUG可没有是大事。

保举教程:《PHP视频教程》

以上就是​ PHP完成微信领取及退款流程的实例详解的具体内容,更多请存眷资源魔其它相干文章!

标签: php开发教程 php开发资料 php开发自学 微信支付及退款

抱歉,评论功能暂时关闭!