php实现微信jsapi支付流程

jsapi支付实现过程比较简单。
开发前必备:
1,已申请公众平台账号,并且开通微信支付认证功能。
2,获取appid
3, 已申请商户平台,需要拿到商户号。

    //公众号 appid 
    private $appid = EVERY_APPID;
    //商户号
    private $mch_id = '151****';
    //支付回调
    private $notify_url = '配置自己服务器调用域名/notify_url';
    /**
     * 立即支付
     */
    public function immediatel_pay()
    {   
        $openid = input('openid');//调用接口传递
        if(empty($openid)){
            return json(
                ['code'=>1000,'msg'=>'openid不能为空']
            );
        }
        //生成订单号
        $order_no = $this->create_order_on();
       //支付金额 单位 元
       $pay_money = 0.01;
       $pay_result = $this->wx_jsapi($order_no,'定金支付成功',$openid,$pay_money);
  
         //入库
        try {
           //录入数据库信息
        } catch (\Exception $e) {
            return json(
                ['code'=>1000,'msg'=>'下单失败,请重新下单']
            );
        }
    }
    /**
     * 生成订单号
     */
    private function create_order_on()
    {
        $order_id_main = date('YmdHis') . rand(10000000,99999999);

          $order_id_len = strlen($order_id_main);

          $order_id_sum = 0;

          for($i=0; $i<$order_id_len; $i++){

          $order_id_sum += (int)(substr($order_id_main,$i,1));
            
          }

          $osn = $order_id_main . str_pad((100 - $order_id_sum % 100) % 100,2,'0',STR_PAD_LEFT);

       return $osn;
    }
private function wx_jsapi($order_no,$body,$openid,$total_fee)
    {
        // echo '333';
        // exit;

       
        $request_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//接口链接

        //签名数据
        $sign_data = [
            'appid' => $this->appid, //公众号appid
            'mch_id' => $this->mch_id,  //商户号
            'nonce_str' => $this->createNoncestr(),
            'body' => $body, 
            'out_trade_no' => $order_no, //商户订单号
            'total_fee' => $total_fee*100, //标价金额 分
            'notify_url' => $this->notify_url,
            'trade_type' => 'JSAPI',
            'openid' => $openid   //授权获取的openid
        ];

         $sign_data['sign'] = makeSign($sign_data);

         $request_param = ArrToXml($sign_data);
   
         $result_xml = $this->https_request($request_url,$request_param);
         $result_arr = XmlToArr($result_xml);
       
         //获取预支付交易会话标识
         if($result_arr['return_code'] == 'SUCCESS' && $result_arr['result_code'] == 'SUCCESS'){
            $timeStamp = time();
             //返回前端 $arr
             $arr = array(
                "appId" => $this->appid,
                "timeStamp" => "$timeStamp",        //这里是字符串的时间戳,不是int,所以需加引号
                "nonceStr" => $this->createNoncestr(),
                "package" => "prepay_id=" . $result_arr['prepay_id'],
                "signType" => 'MD5',
            );
            $arr['paySign'] = makeSign($arr);

         }else{
         
         }

        return $arr;
    }


    /**
     *  作用:产生随机字符串,不长于32位
     */
    private 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;
    }


        /**
     * 模拟 http 请求
     * @param  String $url  请求网址
     * @param  Array  $data 数据
     */
    private function https_request($url, $data = null){
        // curl 初始化
        $curl = curl_init();

        // curl 设置
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

        // 判断 $data get  or post
        if ( !empty($data) ) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }

        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

        // 执行
        $res = curl_exec($curl);
        curl_close($curl);
        return $res;
    }

数组转xml

 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."><![CDATA[".$val."]]></".$key.">";
        }
    }
    $xml.="</xml>";

xml转数组

 libxml_disable_entity_loader(true);
    $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

生成签名

/**
     * 生成签名
     * @return 签名,
     */
    function makeSign($data)
    {
        unset($data['sign']);
        foreach ($data as $k => $v) {
            $Parameters[$k] = $v;
        }
        //签名步骤一:按字典序排序参数
        ksort($Parameters);
        $String = formatBizQueryParaMap($Parameters, false);
        //签名步骤二:在string后加入KEY
        $String = $String . "&key=" . WX_KEY;
        //签名步骤三:MD5加密
        $String = md5($String);
        //签名步骤四:所有字符转为大写
        $result_ = strtoupper($String);
        return $result_;

    }

异步调用

//异步通知
    public function notify_url(){
        //接收数据
        $input_xml = file_get_contents("php://input");
       
        try {

            $input_arr = XmlToArr($input_xml);
            if(!isset($input_arr['sign'])){
                \think\Log::write('WxJsapi---'.var_export('签名未找到',true). 'debug');
                exit;
            }
            //验证签名
            $sign_2 = makeSign($input_arr);
            
            if($input_arr['sign'] != $sign_2){
                \think\Log::write('WxJsapi---'.var_export('签名错误',true). 'debug');
                exit;
            } 

            //修改订单状态
            $where = ['order_no'=>$input_arr['out_trade_no'],'status'=>1];
             db('bargain_money_order')->where($where)->find()} catch ( \Exception $e) {
            \think\Log::write('WxJsapi---异步通知-------notify_url-- 捕获异常---'.var_export($e->getMessage(),true). 'debug');
        }


        
    }

进行了分拆,可以组合使用。如有疑问,欢迎留言沟通

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值