美文网首页
PHP微信公众号支付demo

PHP微信公众号支付demo

作者: 寂寞的棍棍 | 来源:发表于2019-07-15 11:14 被阅读0次

备注:以下代码基于PHP laravel框架,引用了自带的函数。array_get($array, "key") 为数组中取元素,类似于$array["key"]

后端发起支付

    /**
     * 微信公众号支付请求
     * @param $userOpenId      用户uid
     * @param $orderNumber     商户订单编号
     * @param $money           支付金额,元为单位
     * @param $notify_url      回调地址
     * @param $body            支付提醒文案
     * @param $wechatConfig
     * @return array|bool
     */
    function wechatPay($userOpenId, $orderNumber, $money, $notify_url, $body, $wechatConfig)
    {
        //将预支付订单提交到微信支付
        $url          = "https://api.mch.weixin.qq.com/pay/unifiedorder";  //微信统一下单请求地址
        $data = [
            "openid"           => $userOpenId,
            "appid"            => array_get($wechatConfig, "app_id"),          //微信appId
            "mch_id"           => array_get($wechatConfig, "merchant_id"),     //微信商户id
            "nonce_str"        => uniqid(),
            "body"             => $body,
            "out_trade_no"     => $orderNumber,
            "total_fee"        => $money * 100,                               //微信订单金额以分为单位
            "spbill_create_ip" => getClientIP(),
            "notify_url"       => $notify_url,
            "trade_type"       => "JSAPI",
        ];
        $signData     = wechat_sign($data, array_get($wechatConfig, "pay_miyao"));    //获取签名,需要进入商户平台配置好支付秘钥
        $data['sign'] = $signData;   
        $result       = postXmlCurl(arrayToXml($data), $url, false, 30);
        $result       = xmlToArray($result);   
        if (array_get($result, "return_code") != "SUCCESS" && array_get($result, "result_code") != "SUCCESS") {
            return false;                                                       //请求支付失败
        }
   
        $data = [
            "appId"      => array_get($wechatConfig, "app_id"),
            "timeStamp"  => (string)time(),
            "nonceStr"   => uniqid(),
            "package"    => "prepay_id=".array_get($result, "prepay_id"),
            "signType"   => "MD5",
        ];
        $sign = wechat_sign($data, array_get($wechatConfig, "pay_miyao"));
        $data["paySign"] = $sign;
        return $data;
    }

/**
 * 微信支付签名
 * @param $data         要加密的参数
 * @param $pay_miyao    微信支付秘钥
 * @return string
 */
function wechat_sign($data, $pay_miyao)
{
    ksort($data);
    $res = "";
    foreach ($data as $key => $value) {
        if (!$value) continue;   //参数值为空时不参与签名
        $res .= $key."=".$value."&";
    }
    $stringSignTemp = $res."key=".$pay_miyao;
    return strtoupper(md5($stringSignTemp));
}

/**
 * xml to array
 * @param $result
 */
function xmlToArray($xml)
{
    libxml_disable_entity_loader(true);
    $result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $result;
}

/**
 * @param $arr
 * @return string
 */
function arrayToXml($arr)
{
    $xml = "<xml>";
    foreach ($arr as $key=>$val) {
        $xml.="<".$key.">".$val."</".$key.">";
    }
    $xml.="</xml>";
    return $xml;
}

/**
 * 微信支付xml请求
 * @param $xml
 * @param $url
 * @param bool $useCert
 * @param int $second
 * @return mixed
 * @throws \Exception
 */
function postXmlCurl($xml, $url, $useCert = false, $second = 30)
{
    $ch = curl_init();
    //设置超时
    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);//严格校验
    //设置header
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    //要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    if($useCert == true){
        //设置证书 微信支付不需要证书,此处证书验证可以忽略
        //使用证书:cert 与 key 分别属于两个.pem文件
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT, base_path("public/xxx/apiclient_cert.pem"));
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY, base_path("public/xxx/apiclient_key.pem"));
    }
    //post提交方式
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
    //运行curl
    $data = curl_exec($ch);
    //返回结果
    if($data){
        curl_close($ch);
        return $data;
    } else {
        $error = curl_errno($ch);
        curl_close($ch);
        throw new \Exception("curl出错,错误码:$error");
    }
}

发起成功,微信正常返回demo

返回示例

{
    "code": "0",
    "msg": "请求成功",
    "data": {
        "payInfo": {
            "appId": "wx04134e1774abedc3",
            "timeStamp": "1561415899",
            "nonceStr": "5d1150db6d2f1",
            "package": "prepay_id=wx24153838009174ad41d109091656422500",
            "signType": "MD5",
            "paySign": "7D459540ACBA6A48BB3CA2E0DDB9453F"
        }
    }
}

微信支付回调

/**
     * 微信支付回调
     * @return string
     */
    public function notify()
    {
        $request = file_get_contents("php://input");
        $notifyArrData = xmlToArray($request);

        //将回调签名单独拿出来
        $sign = array_get($notifyArrData, "sign");
        unset($notifyArrData['sign']);

        //签名验证(商户平台配置,和请求支付的秘钥为同一个)
        $miyao = "";            
        $signData = wechat_sign($notifyArrData, $miyao);
        if ($signData != $sign) {
            return arrayToXml(["return_code" => "FAIL", "return_msg" => "FAIL"]);
        }
        //支付结果验证
        $resultCode = array_get($notifyArrData, "result_code");
        $returnCode = array_get($notifyArrData, "return_code");
        if ($resultCode != "SUCCESS" || $returnCode != "SUCCESS") {
            return arrayToXml(["return_code" => "FAIL", "return_msg" => "FAIL"]);
        }
        $payOrderNumber = array_get($notifyArrData, "out_trade_no");    //获取商户支付订单号
        $outOrderNumber = array_get($notifyArrData, "transaction_id");  //获取微信订单号

        //设置订单支付成功(处理订单支付完成以后的业务逻辑)
        $result = true;

        if ($result) {
            return arrayToXml(["return_code" => "SUCCESS", "return_msg" => "OK"]);
        }
        return arrayToXml(["return_code" => "FAIL", "return_msg" => "FAIL"]);
    }

后记

剩下的事情就交给前端了,有什么问题可以留言哈。

相关文章

  • PHP微信公众号支付demo

    备注:以下代码基于PHP laravel框架,引用了自带的函数。array_get($array, "key") ...

  • 微信公众号支付

    微信公众号支付使用的是JSAPI支付,后端调用微信支付demo中统一下单的接口获取支付参数返回给前端,在公众号中直...

  • PHP微信公众号支付部分流程

    1.登录微信商户平台 复制这两个签名文件,准备替换DEMO中去 微信官网下载PHP微信支付DEMO 替换掉原来微信...

  • 微信服务商下微信扫码、公众号、刷卡支付

    微信服务商下微信扫码、公众号、刷卡支付Demo。 GitHub:https://github.com/Javen2...

  • PHP微信公众号支付开发总结

    微信公众号开发是很常见的开发,其中微信支付占有很大的比重。微信公众号分为服务号和订阅号,服务号支持微信支付。 前期...

  • 关注公众号领红包常见问题解答

    一、关注领红包对公众号的要求: 公众号必须开通“微信支付”和“现金红包”功能权限 登录微信公众平台 – 微信支付(...

  • 微信APP支付

    微信支付开发文档地址SDK与DEMO下载--JAVA .NET C# PHP 微信支付参数配置 统一下单 账单查询...

  • 微信公众号配置

    微信支付 - 商户平台 商户号 支付证书 微信公众号 appid & appscret 开发 > 基本配置 > ...

  • 【微信】支付

    公众号支付 调用微信js支付接口的页面,必须接口域名授权。在公众平台中设置,最多可以授权3个。 使用微信公众号支付...

  • 关于微信公众号发红包|应该知道的几种玩法

    微信公众号发红包首先必须是开通微信支付了的公众号,支持开通微信支付的公众号类型包括:服务号和主体为政府或媒体资质的...

网友评论

      本文标题:PHP微信公众号支付demo

      本文链接:https://www.haomeiwen.com/subject/rcwgkctx.html