微信支付 JSAPI支付(V2)

本文介绍了一个基于PHP的微信支付接口实现方案,包括统一下单、支付回调等核心功能,并提供了详细的代码示例。
下单

    public function unifyPay(){
        $param = (I('get.'));
        if(!$param['member_id'] || !$param['order_sn']){
            return json_encode(['code'=>201,'message'=>'缺少参数']);
        }
        $data = [];
        $paydata = [];
        $unifydata = [];
        $orderinfo = Db::name('order')->where(['order_sn'=>$param['order_sn'],'user_id'=>$param['member_id']])->find();
        if(empty($orderinfo)){
            return json_encode(['code'=>201,'message'=>'订单不存在']);
        }
        $userinfo = Db::name('users')->where(['user_id'=>$param['member_id']])->find();
        if(empty($userinfo)){
            return json_encode(['code'=>201,'message'=>'用户不存在']);
        }
        $config = Db::name('config')->where('name','site_url')->find();
        $wechatconf = config('wechat');
//这个数组里所有的数据都是必填的
        $unifydata = [
            'appid' => $wechatconf['appid'],//appid
            'mch_id' => $wechatconf['mchid'],//商户id
            'nonce_str' => md5(rand(100000,999999)),//随机字符串
            'body' => '商品',
            'out_trade_no' => $param['order_sn'],//订单号
//            'total_fee' => bcmul((string)$orderinfo['order_amount'], '100',0),
            'total_fee' => bcmul(0.01, '100',0),//金额
            'spbill_create_ip' => $_SERVER["REMOTE_ADDR"],
            'notify_url' => $config['value'].'/index.php/mobile/Pay/notify',//回调地址
            'trade_type' => 'JSAPI',
            'openid' => $userinfo['openid'],
        ];
        $this->closeorder($unifydata);//关闭以前的订单,当前项目需要,可以不加
//        'total_fee' => bcmul((string)$orderinfo['order_amount'], '100'),
//        'key' => $wechatconf['pay_key'],   // API 密钥
        // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
//                    'cert_path' => '', // XXX: 绝对路径!!!!
//                    'key_path' => '',      // XXX: 绝对路径!!!!
        $this->pay_key = $wechatconf['sign'];//32位签名
        $orderResult = $this->create_pay_order($unifydata);创建订单
        $timeStamp = time();
        $paydata = [
            'appId' => $wechatconf['appid'],
            'timeStamp' => "$timeStamp",
            'nonceStr' => md5(rand(100000,999999)),
            'package' => 'prepay_id=' . $orderResult['prepay_id'],
            'signType' => 'MD5'
        ];
        $sign = $this->getSign($paydata);//给小程序生成验证签名
        $paydata['paySign'] = $sign;
        $data = ['code'=>0,'message'=>'统一下单成功','data'=>$paydata];
        return json_encode($data);
    }
POST 调用API
    public function post_data($url,$data=[]){
        $ch = curl_init ();
        // print_r($ch);
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
        $return = curl_exec ( $ch );
        curl_close ( $ch );
        return $return;
    }
获取签名
    protected function getSign($data) {
        ksort($data);
        $tmpstr = $this->arrToTempStr($data);
        $tmpSign = $tmpstr . '&key=' . $this->pay_key;
        $sign = strtoupper(md5($tmpSign));
        return $sign;
    }
数组转签名字符串
    private function arrToTempStr($arr) {
        $str = '';
        foreach ($arr as $key => $value) {
            $str .= $key . '=' . $value . '&';
        }
        return substr($str,0,-1);
    }
数组转微信XML
    protected function arrayToXml($arr) {
        $xml = "<xml>";
        foreach ($arr as $key=>$val) {
            if ($key == 'detail') {
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            } else {
                $xml.="<".$key.">".$val."</".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }
解析XML
    protected function analyze_xml($xml) {
        $dom = new DOMDocument();
        $dom->loadXML($xml);
        $node = $dom->documentElement;
        $array = $this->getArray($node);
        return $array;
    }
解析XML 转数组
    private function getArray($node) {
        $array = false;
        if ($node->hasAttributes()) {
            foreach ($node->attributes as $attr) {
                $array[$attr->nodeName] = $attr->nodeValue;
            }
        }

        if ($node->hasChildNodes()) {
            if ($node->childNodes->length == 1) {
                $array[$node->firstChild->nodeName] = $this->getArray($node->firstChild);
            } else {
                foreach ($node->childNodes as $childNode) {
                    if ($childNode->nodeType != XML_TEXT_NODE) {
                        $array[$childNode->nodeName][] = $this->getArray($childNode);
                    }
                }
            }
        } else {
            return $node->nodeValue;
        }
        return $array;
    }
关闭订单
    public function closeorder($order){
        $apiparams=[
            'appid'=>$order['appid'],
            'mch_id'=>$order['mch_id'],
            'out_trade_no'=>$order['out_trade_no'],
            'nonce_str'=>$order['nonce_str'],
        ];
        $apiparams['sign']=$this->getSign($apiparams);
        $apiparams = $this->arrayToXml($apiparams);
        $this->post_data('https://api.mch.weixin.qq.com/pay/closeorder',$apiparams);
        return true;
    }
封装微信支付订单 下单数据
    private function create_pay_order($inputData) {
        $return = array();
        $inputData['sign'] = $this->getSign($inputData);
        $inputData = $this->arrayToXml($inputData);
        $result = $this->post_data('https://api.mch.weixin.qq.com/pay/unifiedorder',$inputData);
        $result = $this->analyze_xml($result);
        $return['return_code'] = isset($result['return_code']['0']['#cdata-section'])?$result['return_code']['0']['#cdata-section']:'';
        $return['return_msg'] = isset($result['return_msg']['0']['#cdata-section'])?$result['return_msg']['0']['#cdata-section']:'';
        $return['appid'] = isset($result['app_id']['0']['#cdata-section'])?$result['app_id']['0']['#cdata-section']:'';
        $return['mchid'] = isset($result['mch_id']['0']['#cdata-section'])?$result['mch_id']['0']['#cdata-section']:'';
        $return['nonce_str'] = isset($result['nonce_str']['0']['#cdata-section'])?$result['nonce_str']['0']['#cdata-section']:'';
        $return['sign'] = isset($result['sign']['0']['#cdata-section'])?$result['sign']['0']['#cdata-section']:'';
        $return['result_code'] = isset($result['result_code']['0']['#cdata-section'])?$result['result_code']['0']['#cdata-section']:'';
        $return['prepay_id'] = isset($result['prepay_id']['0']['#cdata-section'])?$result['prepay_id']['0']['#cdata-section']:'';
        $return['trade_type'] = isset($result['trade_type']['0']['#cdata-section'])?$result['trade_type']['0']['#cdata-section']:'';;
        return $return;
    }
支付回调
    public function notify(){
        $testxml  = file_get_contents("php://input");
        $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
        $result = json_decode($jsonxml, true);//转成数组,
        $wechatconf = config('wechat');
        if($result){
            //如果成功返回了
            if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
                if($result['sign'] == $wechatconf['sign'] && $result['appid'] == $wechatconf['appid']){
                    Db::name('service_order')->where('orderno',$result['out_trade_no'])->update([
                        'pay_state'=>1,
                        'trade_no'=>$result['transaction_id'],
                        'pay_time'=>time()
                    ]);
                }
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值