PHP微信APP支付流程

**

PHP微信APP端支付流程(已通)

**

关于微信支付,看了很多遍tx的文档。不得不说,很辣鸡,遇到过很多坑,我在这里总结一下,希望能给大家有所帮助。话不多说,上代码!!!

1、首先调用微信统一下单接口

// 实际参数可以根据业务写入
$data = [
            'appid' => 'APP应用id’,
            'mch_id' => '商户号id',
            // 随机字符串
            'nonce_str' => $this->actionRandomString(), 
            'body' => '商品描述’,
            'out_trade_no' => '订单号’,
            // 金额要乘100,因为微信是以分为单位,而且不能有小数点
            'total_fee' => '金额',
            // IP地址
            'spbill_create_ip' => $this->actionClientIp();
            'notify_url' => '回调地址(很重要)',
            // 支付方式
            'trade_type' => ‘APP’, 
        ];
        // 签名验证
        $data['sign'] = $this->actionSign($data);
        // 将数组转为xml格式
        $datas = $this->arrayToXml($data);
        // 请求微信的url地址
        $response = $this->httpRequest($url, $datas);

这里用到了几个方法:
获取随机字符串

// 生成32位随机字符串
public function actionRandomString() {
        $str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; //62个字符
        $str = str_shuffle($str);
        $strimg = substr($str, 0, 32);
        return $strimg;
    }

获取IP地址

// 获取当前IP地址
public function actionClientIp() {
        if (isset($_SERVER['REMOTE_ADDR'])) {
            $cip = $_SERVER['REMOTE_ADDR'];
        } elseif (getenv("REMOTE_ADDR")) {
            $cip = getenv("REMOTE_ADDR");
        } elseif (getenv("HTTP_CLIENT_IP")) {
            $cip = getenv("HTTP_CLIENT_IP");
        } else {
            $cip = "127.0.0.1";
        }
        return $cip;
    }

签名的生成

// 微信签名生成
public function actionSign($params) {
        // 将参数数组按照参数名ASCII码从小到大排序
        ksort($params);
        foreach ($params as $key => $item) {
            if (!empty($item)) {
                // 剔除参数值为空的参数并整合为新的数组
                $newArr[] = $key . '=' . $item;
            }
        }
        $stringA = implode("&", $newArr);
        // 使用 & 符号连接参数
        $stringSignTemp = $stringA . "&key=" . "自己的key值(32位)";
        // 将字符串进行MD5加密
        $stringSignTemp = MD5($stringSignTemp);
        // 将所有字符转换为大写
        $sign = strtoupper($stringSignTemp);
        return $sign;
    }

将数组转为xml格式

// 有些数组转xml格式会出现CDATA字符,在微信平台校验的时候会出现错误,把代码中CDATA删除即可
public function arrayToXml($arr) {
        if (!is_array($arr) || count($arr) <= 0) {
            return '数组异常';
        }
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

请求url地址

// http请求
public function httpRequest($url, $data = null) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, TRUE);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

到这里可以打印下输出的内容,到微信签名校验平台校验一下,看一下是否出现问题
然后在第一段代码中接着往下写,进行二次签名校验

// 请求微信接口后会下发xml格式,这里要把xml格式转为数组进行判断
$responseArr = $this->xmlToArray($response);
        if ($responseArr["return_code"] == 'SUCCESS' && $responseArr["return_code"] == 'SUCCESS') {
            // 进行二次签名验证
            $two_data['appid'] = '同上',
            $two_data['partnerid'] = '同上',
            // 预支付id是微信下发的
            $two_data['prepayid'] = $responseArr['prepay_id'];
            // 32位随机字符串
            $two_data['noncestr'] = $this->actionRandomString();
            // 时间,可以直接获取为int类型,这里我处理为字符串格式(前端需要)
            $two_data['timestamp'] = '' . time() . '';
            $two_data['package'] = "Sign=WXPay";
            // 再次进行签名验证
            $two_data['sign'] = $this->actionSign($two_data);
            return $two_data;
        } else {
            return '错误';
        }

这里用到一个方法,将xml格式转为数组

public static function xmlToArray($xml) {
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $array_data;
    }

到此为止,可以让前端把输出$two_data数组的内容去请求微信支付,查看是否能支付
2、回调
回调地址是统一下单接口中的notify_url字段,是支付成功后,处理自己业务逻辑的一个步骤

// 微信下发的依旧是xml格式,需要进行转换
public function actionWxCallBack() {
        // 获取返回的xml
        $testxml = file_get_contents("php://input");
        // 将xml转化为数组
        $result = $this->xmlToArray($testxml);
        if ($result) {
            if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
              // 微信会下发订单号$result['out_trade_no']
              echo '处理自己的业务逻辑';
           }else{
               echo '错误';
           }
        }else{
            echo '错误';
        }
    }

微信支付到这里已经完成了,希望可以帮助到您! ! !
小白一名
不足之处
多多担待
共同进步

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值