小程序微信支付TP5

配置微信支付信息

小程序

function wxPay(order) {
  let token = wx.getStorageSync('token')
  wx.request({
    url: '**/api/wxpay/index',
    data: {
      order: order,
      token: token,
      shop_id:shop_id
    },
    success: (res) => {
      //返回微信支付所有参数      
      let dataArr = res.data
      if (dataArr.code == 200) {
        wx.requestPayment({
          timeStamp: dataArr.data.timeStamp + "",
          nonceStr: dataArr.data.nonceStr,
          package: dataArr.data.package,
          signType: 'MD5',
          paySign: dataArr.data.paySign,
          success(res) {
            ui.navigateTo('../order/order')
          },
          fail(res) {
            console.log(res)
          }
        })
      }
    }

后台接口

<?php
namespace app\api\controller\v1;

use think\Request;
use think\Controller;
use app\api\controller\BaseController;
use app\common\controller\WeChatPay as WeChatPayCommon;

class WeChat extends BaseController
{
    public function getData()
    {
        $param = $this->request->param();
        try {
            $wechat = new WeChatPayCommon($param['shop_id']);
            return $wechat->getData($param);
        } catch (\Exception $e) {
            return $this->r_json(400,$e->getMessage());
        }
    }
}

支付模型

这边参数全部保存到数据库了

<?php
namespace app\common\controller;

use think\Request;
use think\Controller;
use app\common\model\User as UserModel;
use app\common\model\Orders as OrdersModel;
use app\common\model\ShopList as ShopListModel;
use app\common\validate\WeChatPay as WeChatPayValidate;

class WeChatPay extends Controller
{
    private $appid = '';
    private $mch_id = '';
    private $key = '';

    function __construct($shop_id)
    {
        $shop = (new ShopListModel())->get($shop_id);//重数据库获取参数
        $this->appid = $shop['wx_appid'];
        $this->mch_id = $shop['wx_mch_id'];
        $this->key = $shop['wx_key'];
        $this->spbill_create_ip = $shop['spbill_create_ip'];
        $this->notify_url = $shop['notify_url'];
    }

    public function getData($param){
        $this->param = $param;
        $validate = new WeChatPayValidate();//TP5验证其验证返回的参数
        if (!$validate->check($this->param)) return $this->msg(400,$validate->getError());
        //查看订单状态 是否满足条件
        $this->orders  = (new OrdersModel())->get(['orders_number' => $param['orders_number'] , 'orders_status' => 1]);
        if (empty($this->orders )) return $this->msg(400,"订单错误");
        $this->user = (new UserModel())->get($param['uid']);
        //调起支付
        return $this->msg(200,'ok',$this->getSign());
    }

    /**
     * JSAPI调起支付
     */
    private function getSign()
    {
        $this->getOrders();
        $config = [];
        $config['appId'] = $this->appid;
        $config['timeStamp'] = time();
        $config['nonceStr'] = 'x'.time().'x';
        $config['package'] = "prepay_id=".$this->getOrders();
        $config['signType'] = "MD5";
        $config['paySign'] = $this->MakeSign($config);
        return $config;
    }

    /**
     * 统一下单
     */
    private function getOrders()
    {
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $msg = [];
        $msg['appid'] = $this->appid;
        $msg['mch_id'] = $this->mch_id;
        $msg['nonce_str'] = 'o'.time().'o';      
        $msg['body'] = $this->orders['orders_number'];
        $msg['out_trade_no'] = $this->orders['orders_number'];
        $msg['total_fee'] = $this->orders['orders_money']*100;
        $msg['spbill_create_ip'] = $this->spbill_create_ip;
        $msg['notify_url'] = $this->notify_url;
        $msg['trade_type'] = 'JSAPI';
        $msg['openid'] = $this->user['openid'];
        $msg['sign'] = $this->MakeSign($msg);
        $xml = $this->ToXml($msg);
        $data = $this->https_request($url,$xml);
        $data = $this->FromXml($data);
        if (!empty($data['return_msg']) && !empty($data['return_code'])){
            if ($data['return_code'] == "FAIL") {
                throw new \Exception($data['return_msg']);
            }
        }
        return $data['prepay_id'];
    }

    /**
     * 生成签名
     * @return 签名
     */
    private function MakeSign($data)
    {
        //签名步骤一:按字典序排序参数
        ksort($data);
        $string = $this->ToUrlParams($data);
        //签名步骤二:在string后加入KEY
        $string = $string . "&key=".$this->key;
        //签名步骤三:MD5加密或者HMAC-SHA256
        $string = md5($string);
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    /**
     * 格式化参数格式化成url参数
     */
    private function ToUrlParams($data)
    {
        $buff = "";
        foreach ($data as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }
        
        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     * 输出xml字符
     * @throws Exception
    **/
    private function ToXml($data)
    {
        if(!is_array($data) || count($data) <= 0)
        {
            throw new \Exception("数组数据异常!");
        }
        
        $xml = "<xml>";
        foreach ($data as $key=>$val)
        {
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml; 
    }

    /**
     * 将xml转为array
     * @param string $xml
     * @throws WxPayException
     */
    private function FromXml($xml)
    {   
        if(!$xml){
            throw new WxPayException("xml数据异常!");
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

    /**
     * curl请求
     */
    private function https_request($url,$data=null,$time_out=60,$out_level="s",$headers=array())
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_NOSIGNAL, 1);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        if($out_level=="s") {
            //超时以秒设置
            curl_setopt($curl, CURLOPT_TIMEOUT,$time_out);//设置超时时间
        }elseif ($out_level=="ms"){
            curl_setopt($curl, CURLOPT_TIMEOUT_MS,$time_out);  //超时毫秒,curl 7.16.2中被加入。从PHP 5.2.3起可使用 
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        if($headers){
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);//如果有header头 就发送header头信息
        }
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    private function msg($code,$msg,$data=[]){
        return json_encode(['code' => $code , 'msg' => $msg , 'data' => $data]);
    }
}
posted @ 2021-01-26 16:11  野香蕉  阅读(392)  评论(0)    收藏  举报