微信开发篇章外篇 常用支付实现

来源:互联网 发布:python爬虫开发 编辑:程序博客网 时间:2024/05/23 18:52

微信开发篇章外篇常用支付实现(公众号支付、扫码支付、h5支付)

本来想接着上篇博客记录如何实现服务商模式下,多个代理商公众号支付的解决方案,但是这其中会设计到一些微信的常用支付,因此令开一篇记录如何实现微信的几种常用支付方式。(公众号支付、扫码支付、h5支付),这其中需要注意的是扫码支付现在不支持长按识别二维码跳转到支付页面,h5支付不能在微信端完成。


其实微信有如何调用支付的实例代码,但我不太喜欢,主要是有点复杂,而且很多参数都写死,不是分灵活,我希望所有的微信端参数都可以以函数参数传递的方式实现,因此自己写了一个支付类。(后续会不断更新这个类)


<?phpnamespace App\Libs\Weixin;use Exception;class CommWeiXinPay{    private $appid;    private $mch_id;    private $sub_appid;    private $sub_mch_id;    private $device_info;    private $nonce_str;    private $sign;    private $sign_type;    private $body;    private $detail;    private $attach;    private $out_trade_no;    private $fee_type;    private $total_fee;    private $spbill_create_ip;    private $time_start;    private $time_expire;    private $goods_tag;    private $notify_url;    private $trade_type;    private $product_id;    private $limit_pay;    private $openid;    private $sub_openid;    private $scene_info;    public function setAppid($appid) {        $this->appid = $appid;    }    public function setMchid($mch_id) {        $this->mch_id = $mch_id;    }    public function setSubAppid($sub_appid) {        $this->sub_appid = $sub_appid;    }    public function setSubMchId($sub_mch_id) {        $this->sub_mch_id = $sub_mch_id;    }    public function setDeviceInfo($device_info) {        $this->device_info = $device_info;    }    public function setSignType($sign_type) {        $this->sign_type = $sign_type;    }    public function setBody($body) {        $this->body = $body;    }    public function setDetail($detail) {        $this->detail = $detail;    }    public function setAttach($attach) {        $this->attach = $attach;    }    public function setOutTradeNo($out_trade_no) {        $this->out_trade_no = $out_trade_no;    }    public function setFeeType($fee_type) {        $this->fee_type = $fee_type;    }    public function setTotalFee($total_fee) {        $this->total_fee = $total_fee;    }    public function setSpbillCreateIp($spbill_create_ip) {        $this->spbill_create_ip = $spbill_create_ip;    }    public function setTimeStart($time_start) {        $this->time_start = $time_start;    }    public function setTimeExpire($time_expire) {        $this->time_expire = $time_expire;    }    public function setGoodsTag($goods_tag) {        $this->goods_tag = $goods_tag;    }    public function setNotifyUrl($notify_url) {        $this->notify_url = $notify_url;    }    public function setTradeType($trade_type) {        $this->trade_type = $trade_type;    }    public function setProductId($product_id) {        $this->product_id = $product_id;    }    public function setOpenid($openid) {        $this->openid = $openid;    }    public function setLimitPay($limit_pay) {        $this->limit_pay = $limit_pay;    }    public function setSubOpenid($sub_openid) {        $this->sub_openid = $sub_openid;    }    public function setSceneinfo($scene_info) {        $this->scene_info = $scene_info;    }    private function commCheck() {        if(empty($this->appid)) {            throw new Exception("appid is null, init please", 1);        }        if(empty($this->mch_id)) {            throw new Exception("mch_id is null, init please", 1);        }        if(empty($this->body)) {            throw new Exception("body is null, init please", 1);        }        if(empty($this->out_trade_no)) {            throw new Exception("out_trade_no is null, init please", 1);        }        if(empty($this->total_fee)) {            throw new Exception("total_fee is null, init please", 1);        }        if(empty($this->notify_url)) {            throw new Exception("notify_url is null, init please", 1);        }        if(empty($this->trade_type)) {            throw new Exception("trade_type is null, init please", 1);        }    }    private function merchantCheck() {        $this->commCheck();        if(empty($this->sub_mch_id)) {            throw new Exception("sub_mch_id is null, init please", 1);        }    }    private function createSign($params = array(), $signKey ='123456789qwer') {        $signA = "";        $i = 0;        foreach ($params as $key => $value) {            if($i == 0) {                $signA .= $key."=".$value;            } else {                $signA .= "&".$key."=".$value;            }            $i++;        }        $stringSignTemp = $signA."&key=".$signKey;        return $sign = ucwords(MD5($stringSignTemp));    }    private function createXmlData($params = array()) {        $xmlString = "<xml>";        foreach ($params as $key => $value) {            $xmlString .= "<$key>$value</$key>";        }        $xmlString .= "</xml>";        return $xmlString;    }    private function createNonceStr() {        return MD5(rand(00000,99999));    }    public function CreatePayParams($type = "comm") {        if($type == "comm") {            $this->commCheck();        } elseif($type == "merchant") {            $this->merchantCheck();            if (empty($this->trade_type)) {                throw new Exception("trade_type can't be null", 1);            }            if($this->trade_type == "JSAPI") {              if(empty($this->openid) && empty($this->sub_openid)) {                  throw new Exception("openid and sub_openid can't be null at the same time", 1);              }            }        } else {            throw new Exception("pay model is error, comm and merchant", 1);        }        $this->nonce_str = $this->createNonceStr();        $arr = get_object_vars($this);        foreach ($arr as $key => $value) {            if(empty($value)) {               unset($arr[$key]);            }        }        ksort($arr);        $sign = $this->createSign($arr);        $this->sign = $sign;        $arr['sign'] = $sign;        return $xmlData = $this->createXmlData($arr);    }}

简单介绍:这里最重要的便是CreatePayParams函数,唯一参数($type)默认便是”comm”,当type=”comm”时普通商户模式,当type=”merchant”是服务商模式,普通商户模式和服务商模式在代码实现方面有什么不同呢,就是在请求微信服务器是要传递多一些参数,如sub_appid、sub_mch_id、sub_openid等,使用以上的类可便可以直接进行普通商户支付或者服务商模式支付。有一个地方要注意便是createSign函数的第二个参数,signkey默认填上你的秘钥,这个在商户页面可以设置。(否则会出现签名错误)先看实例。


//服务商公众号支付public function jsapipay1() {        //CommWeiXin类在前篇记录过        $commweixin = new CommWeiXin('appidA', 'appSecretA');        $userinfo = $commweixin->auth();        $commweixinpay = new CommWeiXinPay();        $commweixinpay->setAppid('MerChantAppid');        $commweixinpay->setMchid('MerChantMchid');        $commweixinpay->setSubAppid('subAppidA');        $commweixinpay->setSubMchId('subMchId');        $commweixinpay->setDeviceInfo('WEB');        $commweixinpay->setBody('sjdasdja');        $commweixinpay->setOutTradeNo(rand(00000,99999));        $commweixinpay->setTotalFee("0.01"*100);        $commweixinpay->setSpbillCreateIp($_SERVER['REMOTE_ADDR']);        $commweixinpay->setNotifyUrl('http://www.baidu.com/login/pay/payinfo');        $commweixinpay->setTradeType('JSAPI');        $commweixinpay->setSubOpenid($userinfo->openid);        $commweixinpay->setSceneinfo('{"h5_info": {"type":"Android","app_name": "王者荣耀","package_name": "com.tencent.tmgp.sgame"}}');        //返回请求微信服务器支付所需要的参数(xml格式)        $xmldata = $commweixinpay->CreatePayParams('merchant');        //请求微信服务器($jsApiParameters参数便是调起公众号支付的必须参数)        $jsApiParameters = $commweixin->pay($xmldata);        //var_dump($jsApiParameters);        //将$jsApiParameters参数扔给前端,前端调起微信支付(这里不记录)        return $jsApiParameters;    }
//服务商h5支付public function h5pay() {        //CommWeiXin类在前篇记录过        $commweixin = new CommWeiXin('appidA', 'appSecretA');        $userinfo = $commweixin->auth();        $commweixinpay = new CommWeiXinPay();        $commweixinpay->setAppid('MerChantAppid');        $commweixinpay->setMchid('MerChantMchid');        $commweixinpay->setSubAppid('subAppidA');        $commweixinpay->setSubMchId('subMchId');        $commweixinpay->setDeviceInfo('WEB');        $commweixinpay->setBody('sjdasdja');        $commweixinpay->setOutTradeNo(rand(00000,99999));        $commweixinpay->setTotalFee("0.01"*100);        $commweixinpay->setSpbillCreateIp($_SERVER['REMOTE_ADDR']);        $commweixinpay->setNotifyUrl('http://www.baidu.com/login/pay/payinfo');        $commweixinpay->setTradeType('MWEB');        $commweixinpay->setSceneinfo('{"h5_info": {"type":"Android","app_name": "王者荣耀","package_name": "com.tencent.tmgp.sgame"}}');        //返回请求微信服务器支付所需要的参数(xml格式)        $xmldata = $commweixinpay->CreatePayParams('merchant');        //请求微信服务器($h5payParameters参数中便有调起h5支付的url)        $h5payParameters = $commweixin->pay($xmldata);        //var_dump($h5payParameters );        //$h5payParameters参数中便有调起h5支付的url,将其扔到前端就可以,前端再点击跳转到该url    }
//服务商扫码支付public function saomapay() {        //CommWeiXin类在前篇记录过        $commweixin = new CommWeiXin('appidA', 'appSecretA');        $userinfo = $commweixin->auth();        $commweixinpay = new CommWeiXinPay();        $commweixinpay->setAppid('MerChantAppid');        $commweixinpay->setMchid('MerChantMchid');        $commweixinpay->setSubAppid('subAppidA');        $commweixinpay->setSubMchId('subMchId');        $commweixinpay->setDeviceInfo('WEB');        $commweixinpay->setBody('sjdasdja');        $commweixinpay->setOutTradeNo(rand(00000,99999));        $commweixinpay->setTotalFee("0.01"*100);        $commweixinpay->setSpbillCreateIp($_SERVER['REMOTE_ADDR']);        $commweixinpay->setNotifyUrl('http://www.baidu.com/login/pay/payinfo');        $commweixinpay->setTradeType('NATIVE');        // $commweixinpay->setSubOpenid($userinfo->openid);        $commweixinpay->setSceneinfo('{"h5_info": {"type":"Android","app_name": "王者荣耀","package_name": "com.tencent.tmgp.sgame"}}');        //返回请求微信服务器支付所需要的参数(xml格式)        $xmldata = $commweixinpay->CreatePayParams('merchant');        //请求微信服务器($saomapayParameters 便有包含该二维码的url)        $saomapayParameters = $commweixin->pay($xmldata);        //var_dump($saomapayParameters);        $objectxml = (array)simplexml_load_string($saomapayParameters, 'SimpleXMLElement', LIBXML_NOCDATA);      $code_url = "http://paysdk.weixin.qq.com/example/qrcode.php?data=";      $code_url .= urlencode($objectxml['code_url']);      //将这个图片扔到前端就OK      return '<img src="'.$code_url.'"/>';    }

总结:其实微信支付并不难,从上面看这个三个都是同样的套路,只不过trade_type这个参数不同而已,分别是JSAPI、MWEB、NATIVE,和前端的处理方式不同,除了这两点简直一模一样。明白这个套路,微信支付的面纱也就没了。你会觉得其实挺没意思的。

原创粉丝点击