PHP實現微信小程序支付的幫助類

背景

事先準備工做

  1. 申請一個小程序,並開通微信支付,詳細見:微信小程序支付業務說明
  2. 仔細查閱微信支付官方文檔,詳細見: 微信支付開發者文檔
  3. 仔細閱讀 微信支付統一下單接口
  4. 仔細閱讀 支付結果通知接口
  5. 整理並在商戶平臺設置好相應的回掉地址,好比http://test.dev.com/wechat/pa...
  6. 服務端編寫兩個接口
    1) 微信預支付接口,http://test.dev.com/wechat/pr... , 以商品訂單爲例,此接口接受兩個參數,goods_id 和 uid ,goods_id表示商品編號,uid表示用戶編號,返回參數以下
{
        errcode: 200,
        msg: "SUCCESS",
        data: {
            status: 1,  //狀態,爲1表示成功,其餘的表示失敗
            result: "success",
            data: {
                appId: "xxx",  //小程序的appid
                timeStamp: 1545909092, //時間戳
                nonceStr: "vuryhptlafvpee92pxhji6zs5jl2n0gu", //隨機串
                package: "prepay_id=wx27191130962951f060bfa1323531879649", //支付的包參數
                signType: "MD5", //簽名方式
                paySign: "B04272BB9BBDB1F52863D3B0EF580BE8" //支付簽名
            }
        }
    }

2) 微信支付回調接口,http://test.dev.com/wechat/pa... ,此接口最好是get和post都設置,由於 微信在進行回調的時候會以post的形式進行請求php

5.建表
1) 商品訂單表(shop_goods_order),其中重要的字段有out_trade_no,out_trade_no傳遞給微信支付的支付訂單號,也是咱們本身的系統與微信對接的訂單惟一標識;bill_no表示微信支付的交易訂單號,這個字段只有在訂單支付成功以後進行更新,該字段也是查詢位置支付訂單的惟一標識,詳細的表結構以下前端

CREATE TABLE `shop_goods_order` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `uid` int(10) DEFAULT '0' COMMENT '用戶編號',
  `goods_id` int(10) DEFAULT '0' COMMENT '商品編號',
  `out_trade_no` varchar(30) DEFAULT '' COMMENT '訂單序列號',
  `bill_no` varchar(30) DEFAULT '' COMMENT '支付方返回的交易訂單號',
  `paid_money` int(10) DEFAULT '0' COMMENT '支付的金額',
  `paid_integral` int(10) DEFAULT '0' COMMENT '支付的健康幣',
  `paid_type` varchar(15) DEFAULT 'WXPAY' COMMENT '支付類型,有WXPAY和INTEGRAL等值',
  `paid_status` varchar(10) DEFAULT 'CHECKED' COMMENT '支付狀態,CHECKED表示初始狀態,SUCC表示支付成功,FAILED表示支付失敗,REFUND表示已退款',
  `add_time` int(10) DEFAULT '0' COMMENT '添加時間',
  `paid_time` int(10) DEFAULT '0' COMMENT '支付時間',
  `update_time` int(10) DEFAULT '0' COMMENT '更新時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;

2) 商品信息表(shop_goods_info),字段以下redis

CREATE TABLE `shop_goods_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `name` varchar(100) DEFAULT '' COMMENT '商品名稱',
  `note` varchar(300) DEFAULT '' COMMENT '商品描述',
  `market_price` int(10) DEFAULT '0' COMMENT '原價',
  `sale_price` int(10) DEFAULT '0' COMMENT '售價',
  `integral` int(8) DEFAULT '0' COMMENT '健康幣',
  `main_thumbnail` varchar(40) DEFAULT '' COMMENT '主圖',
  `thumbnail1` varchar(40) DEFAULT '' COMMENT '縮略圖1',
  `thumbnail2` varchar(40) DEFAULT '' COMMENT '縮略圖2',
  `thumbnail3` varchar(40) DEFAULT '' COMMENT '縮略圖3',
  `thumbnail4` varchar(40) DEFAULT '' COMMENT '縮略圖4',
  `thumbnail5` varchar(40) DEFAULT '' COMMENT '縮略圖5',
  `content` text COMMENT '詳細介紹',
  `add_time` int(10) DEFAULT '0' COMMENT '添加時間',
  `update_time` int(10) DEFAULT '0' COMMENT '更新時間',
  `is_online` tinyint(1) DEFAULT '1' COMMENT '商品是否上線',
  `sort` int(4) DEFAULT '0' COMMENT '排序值,越大越靠前',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

實現步驟

業務實現時序圖

clipboard.png

實現步驟說明

客戶端

  1. 客戶端調用 微信預支付接口 獲取對應的微信支付參數
  2. 獲取基礎的支付參數後,調用wx.requetPayment接口調起微信支付
  3. 用戶輸入密碼完成支付

服務端

  1. 客戶端在發起支付前先往商品訂單表裏面建立一條訂單,並生成對應的out_trade_no參數
  2. 調用微信支付的統一下單接口https://api.mch.weixin.qq.com...,向微信發起支付訂單請求,統一下單接口文檔地址,見微信支付統一下單接口
  3. 支付請求結束後微信將支付結果返回給 微信支付回調接口
  4. 若支付成功,服務端將訂單的paid_status字段設置succ ,並將bill_no、paid_time、update_time更新,bill_no的值爲微信支付的transaction_id;若支付失敗,將paid_status字段更新爲failed,並更新update_time字段

關鍵代碼

客戶端

發起微信支付

wxPay:function () {
    var that = this
    var params = {
      goods_id: that.data.goods_id,
      uid: that.data.uid,
      paid_type: 'WXPAY'
    }

    var param = JSON.stringify(params)
    console.log(param)
    param = app.Encrypt(param)
    var url = app.data.API_DOMAIN + "/wechat/prepay?param=" + param
    wx.showModal({
      title: '提示',
      content: '肯定要微信支付購買此係列課嗎?',
      success(res) {
        if (res.confirm) {
          if (that.data.iswxpay == 0) {
            that.setData({
              iswxpay: 1
            })
            app.httpRequest(that.data.uid, url, function (response) {
              var payinfo = response.data.data.data
              wx.requestPayment({
                timeStamp: payinfo.timeStamp.toString(),
                nonceStr: payinfo.nonceStr,
                package: payinfo.package,
                signType: 'MD5',
                paySign: payinfo.paySign,
                success(res) {
                  wx.showToast({
                    title: '購買成功',
                    icon: 'success'
                  })
                  that.setData({
                    is_paid: 1
                  })
                  that.getSeminarInfo(that.data.sid, that.data.uid)
                },
                fail(res) {
                  that.setData({
                    iswxpay: 0
                  })
                  wx.showToast({
                    title: '購買失敗',
                    icon: 'none'
                  })
                }
              })
              console.log(response.data.data.data)
            }, function (f_res) { }, function (f_res) { })
          }
        } else {
          that.setData({
            iswxpay: 0
          })
          console.log('取消微信支付')
        }
      }
    })
  },

服務端

預支付接口關鍵代碼

一、入口方法:orderPay算法

/**
     * 微信支付的獲取支付參數的接口
     * 1.先要用戶編號和支付方式獲取對應的訂單,若是存在則取存在的,若不存在則建立,一種支付類型的訂單值存在一條記錄
     * 2.建立訂單後根據out_trade_no來調用微信支付的統一下單接口獲得微信支付的支付參數
     * 3.將參數返回給前端進行支付
     * 4.支付成功以後進行回掉
     */
    public function orderPay($uid, $goodsId, $paidType){
        $result = [];
        $lockKey = BusinessHelper::getPayOrderLockRedisKey();
        //枷鎖是爲了防止併發
        $this->doWithLock(function()use(&$result,$uid,$goodsId,$paidType){
            error_log('$paidType ================>'.$paidType);
            switch ($paidType){
                case Constant::PAID_TYPE_MIXED :
                    error_log('doIntegralPay ================>');
                    $result = $this->doMixedPay($uid,$goodsId,$paidType);
                    error_log('integral pay result ================>'.json_encode($result));
                    break;
                case Constant::PAID_TYPE_WXPAY :
                    $result = $this->doWxaPay($uid,$goodsId,$paidType);
                    error_log('wx pay result ================>'.json_encode($result));
                    break;
            }
        },$lockKey,5);
        error_log('result ================>'.json_encode($result));
        return $result;
    }

二、微信核心支付方法:doWxaPayjson

/**
     * 經過小程序支付的邏輯
     * @param $uid 用戶編號
     * @param $goodsId 系列課編號
     * @param $paidType 支付類型,有INTEGRAL和WXPAY兩種
     * @return array
     */
    public function doWxaPay($uid, $goodsId, $paidType){
        $goodsInfo = ShopGoodsInfoService::getById($goodsId);
        if(!$goodsInfo){
            return [
                'status' => -1,
                'result' => '商品已經下架或者不存在'
            ];
        }
        $config = BusinessHelper::getWechatPayConfig();
        $payHelper = new WechatPayHelper($config);
        $payContent = $this->getWxaPrepayContent($uid,$paidType,$goodsId);
        $params = $payHelper->prepay($payContent);
        error_log('param ==============>'.json_encode($params));
        return $params;
    }

三、建立訂單方法:createOrder
這個方法是爲了創建訂單,爲了保證表示每一次支付都創建一個訂單,我這邊作兩重的訂單複用,先根據訂單狀態去查詢是否有待支付的訂單,若是有在判斷這個訂單的差功能鍵時間是否已經超過7天,若是超過七天則另外建立新的訂單,盡最大的進行數據複用小程序

/**
     * 建立和驗證訂單,接口方法
     * @param $uid 用戶編號
     * @param $paidType 支付類型
     * @param $goodsId 系列課編號
     * @return array
     */
    protected function createOrder($uid, $paidType, $goodsId){
        $existOrder = $this->getUserGoodsOrderWithPaidType($uid,$paidType,$goodsId);
        if(!$existOrder){
            return $this->generateOrder($uid,$paidType,$goodsId);
        }
        //驗證7天之類訂單有效
        $createTime = date('Y-m-d',$existOrder['add_time']);
        $today = date('Y-m-d');
        $diff = TimeHelper::getDiffBetweenTwoDays($today,$createTime);
        if($diff > 7){
            return $this->generateOrder($uid,$paidType,$goodsId);
        }
        return $existOrder;
    }

四、訂單查重方法:getUserGoodsOrderWithPaidType微信小程序

/**
     * 根據支付類型獲取用戶對應的商品的訂單
     */
    public function getUserGoodsOrderWithPaidType($uid, $paidType, $goodsId){
        $order = BeanHelper::convertStdClsToArr(
            ShopGoodsOrder::where('uid', $uid)
                ->where('goods_id',$goodsId)
                ->where('paid_type',$paidType)
                ->whereIn('paid_status',[Constant::PAID_STATUS_CHECKED])
                ->orderBy('add_time','desc')
                ->first()
        );
        return $order;
    }

五、生成訂單方法:api

/**
     * 生成訂單,輔助方法
     * @param $uid 用戶編號
     * @param $paidType 支付類型
     * @param $goodsId 系列課編號
     * @return array
     */
    public function generateOrder($uid, $paidType, $goodsId){
        $goodsInfo = ShopGoodsInfoService::getById($goodsId);
        $priceKey = $paidType == Constant::PAID_TYPE_WXPAY ? 'market_price' : 'sale_price';
        $price = formatArrValue($goodsInfo,$priceKey,0);
        $integral = $paidType == Constant::PAID_TYPE_WXPAY ? 0 : formatArrValue($goodsInfo,'integral',0);
        $baseMeasureUnit = 100;
        $insertOrderData = [
            'uid' => $uid,
            'goods_id' => $goodsId,
            'out_trade_no' => BusinessHelper::generateOutTradeNo(Constant::PAID_SCENE_SHOP_GOODS_ORDER),
            'paid_money' => $price * $baseMeasureUnit,
            'paid_integral' => $integral,
            'paid_type' => $paidType,
            'paid_status' => Constant::PAID_STATUS_CHECKED,
            'add_time' => time(),
            'update_time' => time(),
        ];
        $existOrder = BeanHelper::convertStdClsToArr($this->store($insertOrderData));
        return $existOrder;
    }

六、生成outTradeNo方法
這個方法中的getPaidSceneMapping方法返回的是一個數組,out_trade_no方法有3個部分組成,分別是當前時間,場景值(這個是爲了保證不一樣的支付場景對應的不一樣的業務代碼)以及10位隨機數字組成數組

/**
     * 生成第三方支付的外部訂單號
     */
    public static function generateOutTradeNo($paidScene = Constant::PAID_SCENE_SEMINAR_ORDER){
        $prefix = date('YmdHis');
        $paidSceneMap = self::getPaidSceneMapping();
        $scene = formatArrValue($paidSceneMap,$paidScene,'0001');
        $suffix = generateRandomNum(10);
        return $prefix.$scene.$suffix;
    }
    
    /**
     * 獲取支付場景的map,這個是爲了區分不一樣的支付場景時候更新不一樣的業務字段,爲了拓展進行的預留
     */
    public static function getPaidSceneMapping(){
        return [
            Constant::PAID_SCENE_SEMINAR_ORDER => '0001',
            Constant::PAID_SCENE_SHOP_GOODS_ORDER => '0002'
        ];
    }

支付回調接口關鍵代碼

入口方法:payNotify服務器

/**
 * 支付的回掉
 */
public function payNotify(Request $request){
    error_log('notify request param ========>');
    $config = BusinessHelper::getWechatPayConfig();
    $helper = new WechatPayHelper($config);
    $result = $helper->notify($request);
    return $result;
}

微信支付幫助類

<?php

namespace App\Http\Helper\Pay;
use App\Http\Helper\Jz\BusinessHelper;
use App\Http\Helper\Jz\Constant;
use App\Http\Helper\LogHelper;
use SeminarOrderService;
use ShopGoodsOrderService;
/**
 * Created by PhpStorm.
 * User: Auser
 * Date: 2018/12/17
 * Time: 15:41
 */
class WechatPayHelper {

    public $config;
    public function __construct($config)
    {
        $this->config = $config;
    }

    /**
     * 預支付請求接口(POST)
     * 返回json的數據
     */
    public function prepay($payContent)
    {
        $config = $this->config;
        $unifiedorder = [
            'appid'            =>$config['appid'],
            'mch_id'        =>$config['mchid'],
            'nonce_str'         =>self::getNonceStr(),
            'body'         =>$payContent['body'],
            'out_trade_no'   =>$payContent['out_trade_no'],
            'total_fee'         =>$payContent['fee'],
            'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],
            'notify_url'     =>$config['notify_url'],
            'trade_type'     =>'JSAPI',
            'openid'        =>$payContent['openid']
        ];
        error_log('config ===============>'.json_encode($config));
        $unifiedorder['sign'] =  $this->makeSign($unifiedorder);
        error_log('unifine order param ===============>'.json_encode($unifiedorder));
        //請求數據
        $xmldata =  $this->array2xml($unifiedorder);
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $res = $this->request($url, $xmldata);
        if(!$res){
             return $this->errorResult("Can't connect the server");
        }
        $content =  $this->xml2array($res);
        error_log('unifine order result ===============>'.json_encode($content));
        if(strval($content['result_code']) == 'FAIL'){
            return $this->errorResult(strval($content['return_msg']));
        }
        if(strval($content['return_code']) == 'FAIL'){
            return $this->errorResult(strval($content['return_msg']));
        }
        //拼接小程序的接口數據
        $resData = [
            'appId'       => strval($content['appid']),
            'timeStamp'    => time(),
            'nonceStr' =>  $this->getNonceStr(),
            'package'  => 'prepay_id='.strval($content['prepay_id']),
            'signType' => 'MD5'
        ];
        //加密簽名
        $resData['paySign'] =  $this->makeSign($resData);
        return $this->successResult($resData);
    }


    /**
     * @return array|bool
     * 微信支付回調驗證
     * 返回數據
     */
    public function notify(){
        //$xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        error_log("wechat pay notify message ============>");
        $xml = file_get_contents('php://input');
        //將服務器返回的XML數據轉化爲數組
        $data =  $this->xml2array($xml);
        // 保存微信服務器返回的簽名sign
        $dataSign = $data['sign'];
        // sign不參與簽名算法
        unset($data['sign']);
        $sign =  $this->makeSign($data);
        // 判斷簽名是否正確  判斷支付狀態
        $result = false;
        error_log("return data ============>".json_encode($data));
        //驗證訂單是否已經支付,調用訂單查詢接口
        $isPayment = $this->verifyPament($data);
        error_log("isPayment ============>".$isPayment);
        if($isPayment && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS')) {
            error_log("isPayment success============>");
            $outTradeNo = $data['out_trade_no'];
            $concurrentTime = 30;
            $lockKey = getCacheKey('redis_key.cache_key.zset_list.lock') . $outTradeNo;
            //採用併發鎖控制併發
            SeminarOrderService::doWithLock(function()use(&$result , $data){
                $result = $data;
                $this->setPaidSuccess($data);
            },$lockKey,$concurrentTime);
        }else{
            error_log("isPayment failed============>");
            $this->setPaidFail($data);
        }
        // 返回狀態給微信服務器
        if($result){
            $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[簽名失敗]]></return_msg></xml>';
        }
        return $str;
    }


    /**
     * 支付成功
     */
    public function setPaidSuccess($data){
        error_log('current paid  data =============>'.json_encode($data));
        $paidType = substr($data['out_trade_no'], 14, 4);
        error_log('current paid type is =============>'.$paidType);
        switch ($paidType){
            case '0001' :
                SeminarOrderService::setOrderPaid($data);
                break;
            case '0002':
                ShopGoodsOrderService::setOrderPaid($data);
                break;
        }
    }

    /**
     * 支付失敗
     */
    public function setPaidFail($data){
        $paidType = intval(substr($data['out_trade_no'], 14, 4));
        LogHelper::info('current paid type is =============>'.$paidType);
        switch ($paidType){
            case '0001' :
                SeminarOrderService::setOrderPaidFailed($data);
                break;
            case '0002':
                ShopGoodsOrderService::setOrderPaidFailed($data);
                break;
        }
    }


    /**
     * 驗證支付的問題
     */
    public function verifyPament($wxPayResp){
        error_log("verify paymnent method=======>".json_encode($wxPayResp));
        $url = "https://api.mch.weixin.qq.com/pay/orderquery";
        //檢測必填參數
        if(!$wxPayResp['transaction_id'] && !$wxPayResp['out_trade_no']) {
            error_log("訂單查詢接口中,out_trade_no、transaction_id至少填一個!");
            return false;
        }
        error_log("開始查詢==============》接口");
        $config = BusinessHelper::getWechatPayConfig();
        error_log("post config ==============》".json_encode($config));
        error_log("transaction is===============>".$wxPayResp['transaction_id']);
        error_log("appid is===============>".$config['appid']);
        error_log("transaction is===============>".$config['mchid']);
        error_log("nonce_string is===============>".$this->getNonceStr());
        $params = [
            'appid' => $config['appid'],
            'mch_id' => $config['mchid'],
            'nonce_str' => $this->getNonceStr(),
            'transaction_id' => $wxPayResp['transaction_id']
        ];
        error_log("post PARAM without sign==============》");
        $params['sign'] = $this->makeSign($params);
        error_log("post PARAM0 with sign ==============》");
        $xmlData = $this->array2xml($params);
        $response = $this->request($url,$xmlData);
        if(!$response){
            error_log("接口請求錯誤:");
            return false;
        }
        $result =  $this->xml2array($response);
        error_log("查詢訂單接口返回結果:".json_encode($result));
        if(array_key_exists("return_code", $result)
            && array_key_exists("trade_state", $result)
            && $result["return_code"] == "SUCCESS"
            && $result["trade_state"] == "SUCCESS"){
            return true;
        }
        return false;
    }



//---------------------------------------------------------------用到的函數------------------------------------------------------------
    /**
     * 錯誤返回提示
     * @param string $errMsg 錯誤信息
     * @param string $status 錯誤碼
     * @return  array json的數據
     */
    protected function errorResult($errMsg = 'error', $status = Constant::PAID_RESULT_FAILED)
    {
        return [
            'status'=>$status,
            'result'=>'fail',
            'data'=>$errMsg
        ];
    }


    /**
     * 正確返回
     * @param  array $data 要返回的數組
     * @return  array json的數據
     */
    protected function successResult($data=[]){
        return [
            'status'=> Constant::PAID_RESULT_SUCCESS,
            'result'=>'success',
            'data'=>$data
        ];
    }

    /**
     * 將一個數組轉換爲 XML 結構的字符串
     * @param array $arr 要轉換的數組
     * @param int $level 節點層級, 1 爲 Root.
     * @return string XML 結構的字符串
     */
    protected function array2xml($arr, $level = 1){
        $s = $level == 1 ? "<xml>" : '';
        foreach($arr as $tagname => $value) {
            if (is_numeric($tagname)) {
                $tagname = $value['TagName'];
                unset($value['TagName']);
            }
            if(!is_array($value)) {
                $s .= "<{$tagname}>".(!is_numeric($value) ? '<![CDATA[' : '').$value.(!is_numeric($value) ? ']]>' : '')."</{$tagname}>";
            }else {
                $s .= "<{$tagname}>" . $this->array2xml($value, $level + 1)."</{$tagname}>";
            }
        }
        $s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s);
        return $level == 1 ? $s."</xml>" : $s;
    }

    /**
     * 將xml轉爲array
     * @param  string  $xml xml字符串
     * @return array    轉換獲得的數組
     */
    protected function xml2array($xml)
    {
        //禁止引用外部xml實體
        libxml_disable_entity_loader(true);
        $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $result;
    }

    /**
     *
     * 產生隨機字符串,不長於32位
     * @param int $length
     * @return 產生的隨機字符串
     */
    protected function getNonceStr($length = 32){
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ ) {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    /**
     * 生成簽名
     * @return 簽名
     */
    protected function makeSign($data){
        //獲取微信支付祕鑰
        $key = $this->config['mch_secret'];
        //去空
        $data = array_filter($data);
        //簽名步驟一:按字典序排序參數
        ksort($data);
        $signParam = http_build_query($data);
        $signParam = urldecode($signParam);
        //簽名步驟二:在string後加入KEY
        $signContent = $signParam."&key=".$key;
        //簽名步驟三:MD5加密
        $sign = md5($signContent);
        // 簽名步驟四:全部字符轉爲大寫
        $result=strtoupper($sign);
        return $result;
    }

    /**
     * 微信支付發起請求
     */
    protected function request($url, $xmldata, $second=30, $aHeader=array()){
        $ch = curl_init();
        //超時時間
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
        //這裏設置代理,若是有的話
        //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
        if( count($aHeader) >= 1 ){
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
        }
        curl_setopt($ch,CURLOPT_POST, 1);
        curl_setopt($ch,CURLOPT_POSTFIELDS,$xmldata);
        $data = curl_exec($ch);
        if($data){
            curl_close($ch);
            return $data;
        }
        else {
            $error = curl_errno($ch);
            echo "call faild, errorCode:$error\n";
            curl_close($ch);
            return false;
        }
    }


}

踩坑點

一、支付回調接口http://test.dev.com/wechat/pa... 必定要設置成get、post都能訪問,我當初只設置了get請求能夠訪問,浪費了好多時間進行排查,而微信回調的數據基本都是以post形式進行調用的

相關文章
相關標籤/搜索