微信支付

大纲:

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


    一、支付流程图

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

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

二、开发前期准备

1、服务号配置

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值