php 小程式服務商支付模式

weixin_43761212發表於2020-10-19

不明白可以直接評論留言

詳見微信支付-開發文件:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_sl_api.php?chapter=9_1

 /**
     * @Notes: 小程式服務商支付模式 測試(完)
     * @Date: 2020-10-19 16:13
     */
    public function add_pay()
    {
        $appid        = $this->mch_appid; //  服務商的APPID
        $mch_id       = $this->mch_id; //  微信支付分配的商戶號
        $key          = $this->key; // 服務商戶支付祕鑰
        $sub_appid    = $this->appid; //當前調起支付的小程式APPID
        $sub_mch_id   = $this->sub_mch_id; // 微信支付分配的子商戶號 子商戶號
        $body         = "測試";
        $out_trade_no = "1415659990";//訂單號
        $openid       = $this->userInfo['openid']??"";// 使用者openid
        $total_fee    = 0.01;// 支付金額
        $notify_url   = "/";//支付成功回掉
        $res          = Pay::get_pay($appid, $mch_id, $key, $sub_appid, $sub_mch_id, $body, $out_trade_no, $openid, $total_fee, $notify_url);
        
    }

pay 檔案

<?php
/**
 * Desc:小程式服務商支付模式
 * Date: 2020-10-19 13:18
 */

namespace app\model;

use think\Db;
use think\Cache;
use think\Exception;
use think\facade\Config;
use think\Request;

class Pay
{

    /**
     * @Notes: 訂單支付
     * @Date: 2020-10-19 13:20
     * $appid   服務商的APPID
     * $mch_id  商戶號
     * $key 服務商key
     * $sub_appid   小程式的APPID
     * $sub_mch_id  子商戶號
     * $body    商品描述
     * $out_trade_no    商戶訂單號
     * $openid  使用者標示
     * $total_fee   貨幣型別
     * $notify_url  通知地址
     */
    public static function get_pay($appid = '', $mch_id = '', $key = '', $sub_appid = '', $sub_mch_id = '', $body = '', $out_trade_no = '', $openid = '', $fee = 0.00, $notify_url = '')
    {
        $ip               = $_SERVER['SERVER_ADDR'];
        $nonce_str        = nonce_str();//隨機字串
        $spbill_create_ip = $ip;//伺服器IP
        $trade_type       = 'JSAPI';//交易型別 預設
        $total_fee        = $fee * 100;// 微信支付單位是分,所以這裡需要*100


        //這裡是按照順序的 因為下面的簽名是按照順序 排序錯誤 肯定出錯
        $post['appid']            = $appid;
        $post['body']             = $body;
        $post['mch_id']           = $mch_id;
        $post['nonce_str']        = $nonce_str; //隨機字串
        $post['notify_url']       = $notify_url;
        $post['sub_openid']       = $openid;  //支付者在子商戶的openid
        $post['out_trade_no']     = $out_trade_no;
        $post['spbill_create_ip'] = $spbill_create_ip; //終端的ip
        $post['sub_appid']        = $sub_appid;
        $post['sub_mch_id']       = $sub_mch_id;
        $post['total_fee']        = $total_fee; //總金額 最低為一塊錢 必須是整數
        $post['trade_type']       = $trade_type;
//        p($post,1);
        $sign     = Dev::get_sign($post, $key);
        $post_xml = "<xml>
                        <appid>$appid</appid>
                        <body>$body</body>
                        <mch_id>$mch_id</mch_id>
                        <nonce_str>$nonce_str</nonce_str>
                        <notify_url>$notify_url</notify_url>
                        <out_trade_no>$out_trade_no</out_trade_no>
                        <spbill_create_ip>$spbill_create_ip</spbill_create_ip>
                        <sub_appid>$sub_appid</sub_appid>
                        <sub_mch_id>$sub_mch_id</sub_mch_id>
                        <sub_openid>$openid</sub_openid>
                        <total_fee>$total_fee</total_fee>
                        <trade_type>$trade_type</trade_type>
                        <sign>$sign</sign>
                    </xml>";
        //統一介面prepay_id
        $url   = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $xml   = http_request($url, $post_xml);
        $array = self::xml($xml);//全要大寫
        write_log($array, 'get_pay');

        if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
            $time = time();
            $tmp  = [];//臨時陣列用於簽名
            //$tmp['appId']         = $appid;
            $tmp['appId']         = $sub_appid;
            $tmp['nonceStr']      = $nonce_str;
            $tmp['package']       = 'prepay_id=' . $array['PREPAY_ID'];
            $tmp['signType']      = 'MD5';
            $tmp['timeStamp']     = "$time";
            $data['state']        = 1;
            $data['timeStamp']    = "$time";//時間戳
            $data['nonceStr']     = $nonce_str;//隨機字串
            $data['signType']     = 'MD5';//簽名演算法,暫支援 MD5
            $data['package']      = 'prepay_id=' . $array['PREPAY_ID'];//統一下單介面返回的 prepay_id 引數值,提交格式如:prepay_id=*
            $data['paySign']      = Dev::get_sign($tmp, $key);//簽名,具體簽名方案參見微信公眾號支付幫助文件;
            $data['out_trade_no'] = $out_trade_no;

        } else {
            $data['state']       = 0;
            $data['text']        = "錯誤";
            $data['RETURN_CODE'] = $array['RETURN_CODE'];
            $data['RETURN_MSG']  = $array['RETURN_MSG'];
        }
        return json_encode($data);
    }

    //獲取xml
    private static function xml($xml)
    {
        $p = xml_parser_create();
        xml_parse_into_struct($p, $xml, $vals, $index);
        xml_parser_free($p);
        $data = [];
        foreach ($index as $key => $value) {
            if ($key == 'xml' || $key == 'XML') continue;
            $tag        = $vals[$value[0]]['tag'];
            $value      = $vals[$value[0]]['value'];
            $data[$tag] = $value;
        }
        return $data;
    }

}

//隨機32位字串
function nonce_str()
{
    $result = '';
    $str    = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
    for ($i = 0; $i < 32; $i++) {
        $result .= $str[rand(0, 48)];
    }
    return $result;
}

/**
 * curl請求
 * @param $url
 * @param null $data
 * @param array $headers
 * @return bool|string
 */
function http_request($url, $data = null, $headers = array())
{
    $curl = curl_init();
    if (count($headers) >= 1) {
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    }
    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);
    }
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($curl);
    curl_close($curl);
    return $output;
}

Dev檔案

<?php
/**
 * 生成微信簽名
 * Date: 2020-10-19
 * Time: 10:41
 */
namespace app\model;

class Dev
{
    //作用:生成簽名
    public static function get_sign($params, $secret) {
        foreach ($params as $k => $v) {
            $Parameters[$k] = $v;
        }
        //簽名步驟一:按字典序排序引數
        ksort($Parameters);
        $String = self::formatBizQueryParaMap($Parameters, false);
        //簽名步驟二:在string後加入KEY
        $String = $String . "&key=" . $secret;
        //簽名步驟三:MD5加密
        $String = md5($String);
        //簽名步驟四:所有字元轉為大寫
        $result_ = strtoupper($String);
        return $result_;
    }


    ///作用:格式化引數,簽名過程需要使用
    public static function formatBizQueryParaMap($paraMap, $urlencode) {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if ($urlencode) {
                $v = urlencode($v);
            }
            $buff .= $k . "=" . $v . "&";
        }
        $reqPar="";
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

}

相關文章