微信支付

来源:互联网 发布:java游戏引擎制作 编辑:程序博客网 时间:2024/06/04 03:35

大纲:

  • 支付流程图
  • 开发前期准备
  • 开发过程


    一、支付流程图

    微信支付业务流程时序图
    微信支付业务流程时序图

我理解的微信支付流程
我理解的微信支付流程

二、开发前期准备

1、服务号配置

  • 服务器资源认证配置
  • JS接口安全域名配置
  • OAuth2.0 网页授权配置(不需要协议)
  • 微信支付,支付目录配置

2、开发需要的资源

  • 微信服务号(已认证) appId、appScert
  • 微信商户号的 mch_id、mch_key
  • 服务器
  • 域名

三、开发过程

1、假设服务器资源认证完成, OAuth 2.0 验证已经完成,js 接口安全域名正确,微信支付目录配置正确。

2、后台统一下单接口的调用
我选择的有以下参数

参数 说明 appid 微信服务号 appId mch_id 微信商户号 mch_id nonce_str 随机字符串 attach 备注 body 信息 notify_url 微信支付结果通知 openid 微信用户在该公众号的 openid trade_type 交易类型 out_trade_no 商户系统订单号 total_fee 支付金额 单位为分 spbill_create_ip 支付设备 ip


参数代码

$paramArray = array(            "appid" => C("APPID"),            "mch_id" => C("MACH_ID"),            "nonce_str" => $this->weixinService->getRandChar(32),            "attach" => "购买支付",            "body" => "谢谢惠顾",            "notify_url" => C("WEIXIN_PAY_REPLY"),            "openid" => session(C("SESSION_OPEN_ID")),            "trade_type" => "JSAPI",            "out_trade_no" => $outTradeNo , //商户系统的订单号            "total_fee" => 1,            "spbill_create_ip" => $_SERVER['REMOTE_ADDR'],        );

随机字符串代码

/**     * 获取随机串     * @param $length 要随机的长度     * @return null|string     */    static function getRandChar($length){        $str = null;        $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";        $max = strlen($strPol)-1;        for($i=0;$i<$length;$i++){            $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数        }        return $str;    }

订单号生成方法

/**     * 生成订单号     */    public function create_guid(){        $charid = strtoupper(md5(uniqid(mt_rand(), true)));        return $charid;    }

参数排序,加上商户号 mch_key,如果要生成签名,可以使用 strtoupper(md5(sortArrayByKey($paramArray )));

 /**     * 根据键值进行排序,并拼接成字符串返回     * @param $array 参数列表     * @param $mch_secret 是否要生成支付签名     * @return string     */    static function sortArrayByKey($array,$mch_secret = false){        ksort($array);        $paramArray = array();        foreach($array as $key => $val){            array_push($paramArray,"$key=$val");        }        if($mch_secret){            array_push($paramArray,"key=".C("MACH_SECRET"));        }        return join("&",$paramArray);    }

由于统一下单接口所需要传递参数为 xml 格式,所以还需要将 array 转换成 xml 格式:

// 将 key => value 转为 XML 格式    public function toXML($paramArray){        $xml = "<xml>";        foreach ($paramArray as $key=>$val)        {            if (is_numeric($val)){                $xml.="<".$key.">".$val."</".$key.">";            }else{                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";            }        }        $xml.="</xml>";        return $xml;    }

最后调用统一下单接口(在这里统一下单部分就完成了):

/*** xmlParam 为转成xml了后的参数*/public function unifiedorder($xmlParam){        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";        $responeArray = self::post_CurlMethodXml($url,$xmlParam);//        var_dump($responeArray);        return $responeArray;    }

post_CurlMethodXml 是我编写的封装所有微信 请求方式为post 请求 参数格式为 xml 的接口请求方法:

/*** $url 为请求接口地址* $xmlParam 为请求接口所需要的参数* 返回值为 array 键值对*/public function post_CurlMethodXml($url,$xmlParam){        $header[] = "Content-type: text/xml";        //定义content-type为xml,注意是数组        $ch = curl_init ($url);        curl_setopt($ch, CURLOPT_URL, $url);        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);//严格校验        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);        curl_setopt($ch, CURLOPT_POST, 1);        curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlParam);        $data  = curl_exec($ch);       /* if(curl_errno($ch)){            print curl_error($ch);        }*/        $error = curl_error($ch);        curl_close($ch);        if($error) {            throw new Exception('请求发生错误:' . $error);        }        libxml_disable_entity_loader(true);        //xml 转 array        $dataTmp = json_decode(json_encode(simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA)), true);        return $dataTmp;    }

以下未经过 xml 转 array 的统一下单接口的返回信息:

<xml>   <return_code><![CDATA[SUCCESS]]></return_code>   <return_msg><![CDATA[OK]]></return_msg>   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>   <mch_id><![CDATA[10000100]]></mch_id>   <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>   <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>   <result_code><![CDATA[SUCCESS]]></result_code>   <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>   <trade_type><![CDATA[JSAPI]]></trade_type></xml>

最后在完成统一下单后需要为前端提供 h5 调起支付 Api 提供参数:

//$resultUnifiedorder(统一下单接口返回信息xml 转 array 后)$returnWxH5PayParam = array();        if($resultUnifiedorder["return_code"] == "SUCCESS"){            $returnWxH5PayParam["appId"] = $resultUnifiedorder["appid"];            $returnWxH5PayParam["nonceStr"] = $resultUnifiedorder["nonce_str"];            $time = time();            $returnWxH5PayParam["timeStamp"] = "$time";            $returnWxH5PayParam["package"] = "prepay_id=".$resultUnifiedorder["prepay_id"];            $returnWxH5PayParam["signType"] = "MD5";            $paySign = $this->weixinService->sortArrayByKey($returnWxH5PayParam,true); // 未进行 md5 加密的签名            $returnWxH5PayParam["paySign"] = strtoupper(md5($paySign));            $result["status"] = 0;            $result["data"] = $returnWxH5PayParam;        }else{            $result["status"] = 1;        }        $this->ajaxReturn($result);

3、h5 调起支付 Api
找不到代码。。。参考微信的吧
前端接收支付返回可以做点处理

4、后台等待微信支付结果通知

大体流程就这样了。

0 0
原创粉丝点击