About wechat H5 payment (wechat payment and jump connect payment)

Posted by tronicsmasta on Wed, 11 Dec 2019 15:15:40 +0100

I haven't updated my blog for a long time. Recently, I met wechat payment for my project. I need to sort out the demand. I need to adjust wechat payment for an activity page!
Application framework THINKPHP5.1

Note: for wechat payment, if it is the h5 page, you need to obtain the code in a silent login state, so as to ensure that the parameter openid of the payment call is normal. The hole here has been filled for a long time. After the h5 user of the wechat browser enters the mobile number and logs in, the cookie information is saved on the page. Sometimes, the obtained openid will not be updated, resulting in "order account and payment" Account number is inconsistent, please check ";

The refresh page of wechat browser is executed with jq: window.location.href = location.href+'?time='+((new Date()).getTime());

Direct up code: front end
function get_form(){
var price1 =$(".get_price1").val();
var price2 =$(".get_price2").val();
var price3 =$(".get_price3").val();
var price4 =$(".get_price4").val();
var pid =$(".pid").val();
var username =$(".username").val();
var mobile =$(".mobile").val();
var address =$(".address").val();

    if(!username && !mobile && !address){
        layer.alert('Consignee information cannot be empty');
        return false;
    }
    $.post("home/get_from",//Get from is the logic of background payment request
            {"price1":price1,"price2":price2,"price3":price3,"price4":price4,"username":username,"mobile":mobile,"address":address,"pid":pid},function(apiConfig){
           console.log(apiConfig);

        var ua = navigator.userAgent.toLowerCase();//Whether the object for obtaining judgment is wechat internal or external
        if (ua.match(/MicroMessenger/i) == "micromessenger") {
           //inside
            WeixinJSBridge.invoke(
                    'getBrandWCPayRequest', {
                        "appId":apiConfig.appId,     //The name of the public is imported from merchants.
                        "timeStamp":apiConfig.timeStamp,         //Time stamp, seconds since 1970
                        "nonceStr":apiConfig.nonceStr, //Random strings
                        "package":apiConfig.package,
                        "signType":apiConfig.signType,         //Wechat signature method:
                        "paySign":apiConfig.paySign //WeChat signature
                    },
                    function(res){
                        if(res.err_msg == "get_brand_wcpay_request:ok" ){

                            window.location.href ="Method path"
                        }
                    });

            if (typeof WeixinJSBridge == "undefined"){
                if( document.addEventListener ){
                    document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
                }else if (document.attachEvent){
                    document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                    document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
                }
            }else{
                onBridgeReady();
            }

        }else{

     //external
            var url="Payment successful jump";
            window.location.href =apiConfig.mweb_url+"&redirect_url="+url;

        }

    });
}

Back end code:
Reset the route through tp5 redirect during silent login request page
Go to the page again to find out if there is openid
$sa = Cookie::get('kj_phone');
$uid =$sa['id ']; / / user ID
$userAgent = $_SERVER['HTTP_USER_AGENT']; / / judgement is public number payment or external web site payment?
If (strpos ($userAgent,'MicroMessenger')) {/ / public number payment
$uid =$sa['id ']; / / user ID
$open_id= Cache::get($uid);
// print_r($open_id);
if(empty($open_id)){
$this->redirect("Https://open.weixin.qq.com/connect/oauth2/authorize? Appid = appid & redirect  URI = after entering the page, first get the code through get  open method to get openid & response  type = code & scope = snsapi  base & state = 1  wechat  redirect");

          }

      }

Get open method
public function get_open(){

    $code1=empty($_GET['code']) ? '' : $_GET['code'];

    $sa =Cookie::get('kj_phone');

   // $appId ='appId ';
    //$secret ='secret';
    $get_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=Appid&secret=secre&code=' . $code1 . '&grant_type=authorization_code';
    $json_obj = $this->http_request($get_token_url);
    $json_obj = json_decode($json_obj,true);
    $openid = empty($json_obj['openid']) ? "" : $json_obj['openid'];

    $uid =$sa['id'];//User id

    Cache::set($uid,$openid,3600);
    if($code1 == ''){

        $this->redirect('Redirect to render page');
    }
    if(!empty($open_id)){
        $this->redirect('Redirect to render page');
    }else{

        $this->redirect('Redirect to render page');
    }

}

get_from:
public function get_from(){
if(request()->isPost()){
$data =input("post."); / / write logic for the data from the front end

             $userAgent = $_SERVER['HTTP_USER_AGENT']; // Is the public number paid or the external web site paid?

             if (strpos($userAgent, 'MicroMessenger')) { // Public address payment

                 $sa = Cookie::get('kj_phone');
                 $uid =$sa['id'];//User id
                 $open_id= Cache::get($uid);
                 //print_r($open_id);exit;
                 $return = $this->weixinapp($open_id,$body,$order_id,$price,$attact);
                 return $return;
             }else{

                 $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
                 $parameters = array(
                     'appid' => "Small program ID", //Applet ID
                     'mch_id' => "Merchant number", //Merchant number
                     'attach'=>$attact,
                     'nonce_str' => $this->createNoncestr(), //Random string
                     'body' =>$body, //Commodity Description
                     'out_trade_no' =>$order_id,//Merchant order number
                     'total_fee' => $price * 100, //Total amount unit: minute
                     'spbill_create_ip' => '111111', //Terminal IP
                     'notify_url' => 'token url', //Notification address to ensure normal access to the Internet
                     'trade_type' => 'MWEB'//Transaction type
                 );

                 //Unified order signature
                 $parameters['sign'] = $this->getSign($parameters);

                 $xmlData = $this->arrayToXml($parameters);

                 $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));

                 return $return;
             }

        }

    }
}

//Unified single interface
private function weixinapp($openid,$body,$orderId,$price,$attact) {

    $unifiedorder = $this->unifiedorder($openid,$body,$orderId,$price,$attact);

    $parameters = array(
        'appId' => "appId", //Applet ID
        'timeStamp' => '' . time() . '', //time stamp
        'nonceStr' => $this->createNoncestr(), //Random strings
        'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //data packet
        'signType' => 'MD5'//Signature method
    );
    //autograph
    $parameters['paySign'] = $this->getSign($parameters);
    return $parameters;
}
//Function: generate random string, no longer than 32 bits
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;
}
private function getSign($Obj) {
    //halt($Obj);
    foreach ($Obj as $k => $v) {
        $Parameters[$k] = $v;
    }
    //Signature step 1: sort parameters in dictionary order
    ksort($Parameters);
    $String = $this->formatBizQueryParaMap($Parameters, false);
    //Signature step 2: add KEY after string
    $String = $String . "&key=d18e10ad06222c972499296f1cefa481" ;
    //Signature step 3: MD5 encryption
    $String = md5($String);
    //Step 4: change all characters to uppercase
    $result_ = strtoupper($String);

    return $result_;
}
///Function: format parameters. Signature process needs to use
private function formatBizQueryParaMap($paraMap, $urlencode) {
    $buff = "";
    ksort($paraMap);
    foreach ($paraMap as $k => $v) {
        if ($urlencode) {
            $v = urlencode($v);
        }
        $buff .= $k . "=" . $v . "&";
    }
    $reqPar="";
    if (strlen($buff) > 0) {
        $reqPar = substr($buff, 0, strlen($buff) - 1);
    }
    return $reqPar;
}
//Array to xml
private function arrayToXml($arr) {
    $xml = "<root>";
    foreach ($arr as $key => $val) {
        if (is_array($val)) {
            $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
        } else {
            $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
        }
    }
    $xml .= "</root>";
    return $xml;
}
//xml to array
private function xmlToArray($xml) {
    //Prohibit reference to external xml entities
    libxml_disable_entity_loader(true);
    $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
    $val = json_decode(json_encode($xmlstring), true);
    return $val;
}
function http_curl($url){//Pass parameters with curl
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//Turn off ssl authentication
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch,CURLOPT_HEADER, 0);
    $output = curl_exec($ch);
    curl_close($ch);
    return json_decode($output, true);
}
private static function postXmlCurl($xml, $url, $second = 30)
{
    $ch = curl_init();
    //Set timeout
    curl_setopt($ch, CURLOPT_TIMEOUT, $second);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //Strict calibration
    //Set header
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    //The result is expected to be a string and output to the screen
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    //post submission method
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
    curl_setopt($ch, CURLOPT_TIMEOUT, 40);
    set_time_limit(0);
    //Run curl
    $data = curl_exec($ch);
    //Return result
    if ($data) {
        curl_close($ch);
        return $data;
    } else {
        $error = curl_errno($ch);
        curl_close($ch);
        throw new WxPayException("curl Error, error code:$error");
    }
}
//Callback
private function unifiedorder($openid,$body,$orderId,$price,$attact) {

    $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    $parameters = array(
        'appid' => "appid", //Applet ID
        'mch_id' =>"mch_id", //Merchant number
        'attach'=>$attact,
        'nonce_str' => $this->createNoncestr(), //Random string
        'body' => $body,
        'out_trade_no'=> $orderId,
        'total_fee' => $price * 100,
        'spbill_create_ip' => '11111111', //Terminal IP
        'notify_url' => Callback, //Notification address to ensure normal access to the Internet
        'openid' => $openid, //User id
        'trade_type' => 'JSAPI'//Transaction type
    );

    //Unified order signature
    $parameters['sign'] = $this->getSign($parameters);
    $xmlData = $this->arrayToXml($parameters);

    $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));

    return $return;
}
//Callback
public function callback(){
    $xml = file_get_contents("php://input");
    // Convert XML to array
    $xml = json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA));
    $result = json_decode($xml, true);

    //If successfully returned
    if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
        $where['order_id']=$result['out_trade_no'];
        $data_e['states']=2;
        $ud= db('hc_pr_order')->where($where)->update($data_e);
    }
    // Return value to wechat
    if ($ud) {
        $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
    }else{
        $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[Signature failed]]></return_msg></xml>';
    }
    return $str;
    return $result;
}

Topics: PHP xml Mobile curl SSL