Home  >  Article  >  Backend Development  >  PHP code sharing to implement the paid reading function of WeChat public account articles

PHP code sharing to implement the paid reading function of WeChat public account articles

小云云
小云云Original
2018-03-08 09:42:113168browse

About php to implement the paid reading function of WeChat public account articles. It is a public account article. Click to display the title, author, time, public account name and part of the content. If you want to read all the content, then pay 0.01 yuan You can read all the content, this is paid reading! ! ! Of course the amount can be customized....

In fact, the development principle is very simple. It is nothing more than adding a WeChat payment button to the article page, and after clicking the payment, the hidden part will be displayed. Or jump directly to the full text address.

Of course, the interface of this article is also written to imitate the official one. You can check the official style and then imitate it. This is not difficult. The main thing is to add a button to this page. The following is the code of this page:

readpay.php

<?php
header(&#39;Content-type:text/html; Charset=utf-8&#39;);
$mchid = &#39;微信支付商户号&#39;;          //微信支付商户号
$appid = &#39;微信支付申请对应的公众号的APPID&#39;;  //微信支付申请对应的公众号的APPID
$appKey = &#39;微信支付申请对应的公众号的APPSECRET&#39;;   //微信支付申请对应的公众号的APPSECRET
$apiKey = &#39;API密钥&#39;;   //帐户设置-安全设置-API安全-API密钥-设置API密钥
//①、获取用户openid
$wxPay = new WxpayService($mchid,$appid,$appKey,$apiKey);
$openId = $wxPay->GetOpenid();      //获取openid
if(!$openId) exit(&#39;获取openid失败&#39;);
//②、统一下单
$outTradeNo = uniqid();     //你自己的商品订单号
$payAmount = 0.01;          //付款金额,单位:元
$orderName = &#39;test&#39;;    //订单标题
$notifyUrl = &#39;nofity.php&#39;;     //付款成功后的回调地址,一般放在本页面的同级目录即可
$payTime = time();      //付款时间
$jsApiParameters = $wxPay->createJsBizPackage($openId,$payAmount,$outTradeNo,$orderName,$notifyUrl,$payTime);
$jsApiParameters = json_encode($jsApiParameters);
?>

    <!--下面就是木方官方微信文章页面-->
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <title>新版微信支持双开,王利芬庆祝“茅侃侃去世”文阅读10w+被批人血馒头</title>
        <script type="text/javascript">
            //调用微信JS api 支付
            function jsApiCall()
            {
                WeixinJSBridge.invoke(
                    &#39;getBrandWCPayRequest&#39;,
                    <?php echo $jsApiParameters; ?>,
                    function(res){
                        WeixinJSBridge.log(res.err_msg);
                        //alert(res.err_code+res.err_desc+res.err_msg);
                        if(res.err_msg == "get_brand_wcpay_request:ok"){
                            //支付成功跳转页面
                            window.location.href="这里填写支付成功后要跳转的查看全文文章地址";
                        }else{
                            //支付失败/或取消支付跳转页面,自己自定义开发页面
                            window.location.href="false.html";
                        }
                    }
                );
            }
            function callpay()
            {
                if (typeof WeixinJSBridge == "undefined"){
                    if( document.addEventListener ){
                        document.addEventListener(&#39;WeixinJSBridgeReady&#39;, jsApiCall, false);
                    }else if (document.attachEvent){
                        document.attachEvent(&#39;WeixinJSBridgeReady&#39;, jsApiCall);
                        document.attachEvent(&#39;onWeixinJSBridgeReady&#39;, jsApiCall);
                    }
                }else{
                    jsApiCall();
                }
            }
        </script>
        <!--下面就是木方官方微信文章页面的CSS-->
        <style>
            #title{
                   margin-bottom:10px;
                   line-height:1.4;
                   font-weight:400;
                   font-size:24px;
                   width: 97%;
                   margin:0 auto;
            }
            
            #meta_content .time{
                color: #8C8C8C;
                font-family: "SimHei";
            }

            .author{
                color: #8C8C8C;
                font-family: "SimHei";
            }

            .name{
                color: #607fa6;
            }

            #con{
                width:95%;
                font-size: 15px;
                margin:15px auto 25px;
                color: #595757;
            }
        </style>
    </head>
    <body>
    <br/>
    <!--文章标题-->
    <h2 id="title">新版微信支持双开,王利芬庆祝“茅侃侃去世”文阅读10w+被批人血馒头</h2>
    <p id="meta_content">
    <!--发布时间、作者、公众号昵称-->
       <span class="time">2018-01-27</span>   <span class="author">tanking</span>   <span class="name">里客云</span>
    </p>
    <!--显示的部分内容,未支付前显示的内容-->
    <p id="con">
        这一周,公众号议论最多的有“周冲的影像声色”因洗稿被撕、80后创业者茅侃侃去世、刘亦菲分手......几乎每件事都能在朋友圈刷到相关报道。此外,视频大号“一条”又拿到了新一轮融资,你最关心哪一件事呢?
    </p>
    <!--支付按钮-->
    <p align="center">
        <button style="width:180px; height:35px;background: none; border-radius: 5px;border:1px #1AAD19 solid; cursor: pointer;  color:#1AAD19;  font-size:15px;-webkit-tap-highlight-color:rgba(255,0,0,0);" type="button" onclick="callpay()" >支付0.01阅读全文</button>
    </p>
    </body>
    </html>

    <!--下面是微信支付逻辑了-->
<?php
header("Content-Type:text/html; charset=utf-8");
class WxpayService
{
    protected $mchid;
    protected $appid;
    protected $appKey;
    protected $apiKey;
    public $data = null;
    public function __construct($mchid, $appid, $appKey,$key)
    {
        $this->mchid = $mchid; //https://pay.weixin.qq.com 产品中心-开发配置-商户号
        $this->appid = $appid; //微信支付申请对应的公众号的APPID
        $this->appKey = $appKey; //微信支付申请对应的公众号的APP Key
        $this->apiKey = $key;   //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥
    }
    /**
     * 通过跳转获取用户的openid,跳转流程如下:
     * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
     * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
     * @return 用户的openid
     */
    public function GetOpenid()
    {
        //通过code获得openid
        if (!isset($_GET[&#39;code&#39;])){
            //触发微信返回code码
            $scheme = $_SERVER[&#39;HTTPS&#39;]==&#39;on&#39; ? &#39;https://&#39; : &#39;http://&#39;;
            $baseUrl = urlencode($scheme.$_SERVER[&#39;HTTP_HOST&#39;].$_SERVER[&#39;PHP_SELF&#39;].$_SERVER[&#39;QUERY_STRING&#39;]);
            $url = $this->__CreateOauthUrlForCode($baseUrl);
            Header("Location: $url");
            exit();
        } else {
            //获取code码,以获取openid
            $code = $_GET[&#39;code&#39;];
            $openid = $this->getOpenidFromMp($code);
            return $openid;
        }
    }
    /**
     * 通过code从工作平台获取openid机器access_token
     * @param string $code 微信跳转回来带上的code
     * @return openid
     */
    public function GetOpenidFromMp($code)
    {
        $url = $this->__CreateOauthUrlForOpenid($code);
        $res = self::curlGet($url);
        //取出openid
        $data = json_decode($res,true);
        $this->data = $data;
        $openid = $data[&#39;openid&#39;];
        return $openid;
    }
    /**
     * 构造获取open和access_toke的url地址
     * @param string $code,微信跳转带回的code
     * @return 请求的url
     */
    private function __CreateOauthUrlForOpenid($code)
    {
        $urlObj["appid"] = $this->appid;
        $urlObj["secret"] = $this->appKey;
        $urlObj["code"] = $code;
        $urlObj["grant_type"] = "authorization_code";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
    }
    /**
     * 构造获取code的url连接
     * @param string $redirectUrl 微信服务器回跳的url,需要url编码
     * @return 返回构造好的url
     */
    private function __CreateOauthUrlForCode($redirectUrl)
    {
        $urlObj["appid"] = $this->appid;
        $urlObj["redirect_uri"] = "$redirectUrl";
        $urlObj["response_type"] = "code";
        $urlObj["scope"] = "snsapi_base";
        $urlObj["state"] = "STATE"."#wechat_redirect";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
    }
    /**
     * 拼接签名字符串
     * @param array $urlObj
     * @return 返回已经拼接好的字符串
     */
    private function ToUrlParams($urlObj)
    {
        $buff = "";
        foreach ($urlObj as $k => $v)
        {
            if($k != "sign") $buff .= $k . "=" . $v . "&";
        }
        $buff = trim($buff, "&");
        return $buff;
    }
    /**
     * 统一下单
     * @param string $openid 调用【网页授权获取用户信息】接口获取到用户在该公众号下的Openid
     * @param float $totalFee 收款总费用 单位元
     * @param string $outTradeNo 唯一的订单号
     * @param string $orderName 订单名称
     * @param string $notifyUrl 支付结果通知url 不要有问号
     * @param string $timestamp 支付时间
     * @return string
     */
    public function createJsBizPackage($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp)
    {
        $config = array(
            &#39;mch_id&#39; => $this->mchid,
            &#39;appid&#39; => $this->appid,
            &#39;key&#39; => $this->apiKey,
        );
        $orderName = iconv(&#39;GBK&#39;,&#39;UTF-8&#39;,$orderName);
        $unified = array(
            &#39;appid&#39; => $config[&#39;appid&#39;],
            &#39;attach&#39; => &#39;pay&#39;,             //商家数据包,原样返回,如果填写中文,请注意转换为utf-8
            &#39;body&#39; => $orderName,
            &#39;mch_id&#39; => $config[&#39;mch_id&#39;],
            &#39;nonce_str&#39; => self::createNonceStr(),
            &#39;notify_url&#39; => $notifyUrl,
            &#39;openid&#39; => $openid,            //rade_type=JSAPI,此参数必传
            &#39;out_trade_no&#39; => $outTradeNo,
            &#39;spbill_create_ip&#39; => &#39;127.0.0.1&#39;,
            &#39;total_fee&#39; => intval($totalFee * 100),       //单位 转为分
            &#39;trade_type&#39; => &#39;JSAPI&#39;,
        );
        $unified[&#39;sign&#39;] = self::getSign($unified, $config[&#39;key&#39;]);
        $responseXml = self::curlPost(&#39;https://api.mch.weixin.qq.com/pay/unifiedorder&#39;, self::arrayToXml($unified));
        $unifiedOrder = simplexml_load_string($responseXml, &#39;SimpleXMLElement&#39;, LIBXML_NOCDATA);
        if ($unifiedOrder === false) {
            die(&#39;parse xml error&#39;);
        }
        if ($unifiedOrder->return_code != &#39;SUCCESS&#39;) {
            die($unifiedOrder->return_msg);
        }
        if ($unifiedOrder->result_code != &#39;SUCCESS&#39;) {
            die($unifiedOrder->err_code);
        }
        $arr = array(
            "appId" => $config[&#39;appid&#39;],
            "timeStamp" => "$timestamp",        //这里是字符串的时间戳,不是int,所以需加引号
            "nonceStr" => self::createNonceStr(),
            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
            "signType" => &#39;MD5&#39;,
        );
        $arr[&#39;paySign&#39;] = self::getSign($arr, $config[&#39;key&#39;]);
        return $arr;
    }
    public static function curlGet($url = &#39;&#39;, $options = array())
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    public static function curlPost($url = &#39;&#39;, $postData = &#39;&#39;, $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    public static function createNonceStr($length = 16)
    {
        $chars = &#39;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&#39;;
        $str = &#39;&#39;;
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    public static function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }
    public static function getSign($params, $key)
    {
        ksort($params, SORT_STRING);
        $unSignParaString = self::formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }
    protected static function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = &#39;&#39;;
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }
}
?>

nofity.php

<?php
/**
 * 原生支付(扫码支付)及公众号支付的异步回调通知
 * 说明:需要在native.php或者jsapi.php中的填写回调地址。例如:http://www.xxx.com/wx/notify.php
 * 付款成功后,微信服务器会将付款结果通知到该页面
 */
header(&#39;Content-type:text/html; Charset=utf-8&#39;);
$mchid = &#39;微信支付商户号&#39;;
$appid = &#39;公众号APPID&#39;; 
$apiKey = &#39;API密钥&#39;; 
$wxPay = new WxpayService($mchid,$appid,$apiKey);
$result = $wxPay->notify();
if($result){
    //完成你的逻辑
    //例如连接数据库,获取付款金额$result[&#39;cash_fee&#39;],获取订单号$result[&#39;out_trade_no&#39;],修改数据库中的订单状态等;
}else{
    echo &#39;pay error&#39;;
}
class WxpayService
{
    protected $mchid;
    protected $appid;
    protected $apiKey;
    public function __construct($mchid, $appid, $key)
    {
        $this->mchid = $mchid;
        $this->appid = $appid;
        $this->apiKey = $key;
    }
    public function notify()
    {
        $config = array(
            &#39;mch_id&#39; => $this->mchid,
            &#39;appid&#39; => $this->appid,
            &#39;key&#39; => $this->apiKey,
        );
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        $postObj = simplexml_load_string($postStr, &#39;SimpleXMLElement&#39;, LIBXML_NOCDATA);
        if ($postObj === false) {
            die(&#39;parse xml error&#39;);
        }
        if ($postObj->return_code != &#39;SUCCESS&#39;) {
            die($postObj->return_msg);
        }
        if ($postObj->result_code != &#39;SUCCESS&#39;) {
            die($postObj->err_code);
        }
        $arr = (array)$postObj;
        unset($arr[&#39;sign&#39;]);
        if (self::getSign($arr, $config[&#39;key&#39;]) == $postObj->sign) {
            echo &#39;<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>&#39;;
            return $arr;
        }
    }
    /**
     * 获取签名
     */
    public static function getSign($params, $key)
    {
        ksort($params, SORT_STRING);
        $unSignParaString = self::formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }
    protected static function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = &#39;&#39;;
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }
}

Simple instructions:
1] Create a new readpay.php, copy the above code, modify the merchant number, appid, appsecret, key, and the following callback address The path (nofity.php), as for the page to be redirected if the payment is successful or if the payment is failed, you can modify it according to your own needs.
Payment amount, article title] time, author, public account name, etc. can be modified according to your own needs.
Please note that the order title cannot be in Chinese, otherwise it will prompt a body parameter error or something.
2】Create a new nofity.php
Copy the above code and modify the merchant number, appid, and key.
Upload to the payment authorization directory, and then visit the readpay.php page to test.
3】Create new false.html. This is the page for payment failure. As for what should be displayed or output when payment fails, this can be customized and developed according to your business.

Related recommendations:

PHP writing method for WeChat public account article page collection_php example

WeChat public account implements user management function

Detailed introduction to WeChat public account development

The above is the detailed content of PHP code sharing to implement the paid reading function of WeChat public account articles. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn