微信支付小微商戶V3版本介面使用libsodium擴充套件以及程式碼示例

wd731869706發表於2022-01-12

微信支付小微商戶介面:

微信支付小微商戶介面地址

其介面操作中需要下載證照針對返回的AEAD_AES_256_GCM演算法解密,其中用到了sodium_crypto_aead_aes256gcm_decrypt ( string $ciphertext , string $ad , string $nonce , string $key )這個函式。使用這個函式需要開啟 libsodium 擴充套件。

官方文件對該擴充套件的說明如下:
As of PHP 7.2.0 this extension is bundled with PHP. For older PHP versions this extension is available via PECL.
從php 7.2.0開始,這個擴充套件與php捆綁在一起。對於舊的PHP版本,此擴充套件可通過pecl獲得。

驗證方法

<?php


namespace WechatBundleServices;

use CarbonCarbon;
use DingoApiExceptionResourceException;

/**
 * Class WechatCouponService
 * @package WechatBundleServices
 */
class WechatCouponService
{
    /**
     * @var string
     */
    public $baseUrl;
    /**
     * @var string
     */
    public $mch_id;
    /**
     * @var string
     */
    public $sub_mch_id;
    /**
     * @var string
     */
    public $app_id;
    /**
     * @var string
     */
    public $private_key;
    /**
     * @var string
     */
    public $serial_no;
    /**
     * @var string
     */
    public $mch_key;

    const REDIS_NAME_WECHAT_PAY_CERT = 'wechat_pay_v3_cert_no';

    const KEY_LENGTH_BYTE = 32;
    const AUTH_TAG_LENGTH_BYTE = 16;


    const GET_CERTIFICATES = '/v3/certificates';//獲取商戶平臺證照
    const CREATE_COUPON_STOCKS = '/v3/marketing/favor/coupon-stocks';//建立代金券批次API
    const START_COUPON_STOCKS = '/v3/marketing/favor/stocks/%d/start';//啟用代金券批次API
    const COUPON_SEND = '/v3/marketing/favor/users/%s/coupons';//發放代金券API
    const PAUSE_COUPON_STOCKS = '/v3/marketing/favor/stocks/%d/pause';//暫停代金券批次API
    const RESTART_COUPON_STOCKS = '/v3/marketing/favor/stocks/%d/pause';//重啟代金券批次API
    const QUERY_COUPON_STOCKS = '/v3/marketing/favor/stocks';//條件查詢批次列表API
    const QUERY_COUPON_STOCKS_INFO = '/v3/marketing/favor/stocks/%s';//查詢批次詳情API
    const QUERY_COUPON_INFO = '/v3/marketing/favor/users/%s/coupons/%s';//查詢代金券詳情API
    const QUERY_COUPON_MERCHANTS = '/v3/marketing/favor/stocks/%s/merchants';//查詢代金券可用商戶API
    const QUERY_COUPON_ITEMS = '/v3/marketing/favor/stocks/%s/items';//查詢代金券可用單品API
    const QUERY_USER_COUPON = '/v3/marketing/favor/users/%s/coupons';//根據商戶號查使用者的券
    const COUPON_STOCKS_USER_FLOW_DOWNLOAD = '/v3/marketing/favor/stocks/%s/use-flow';//下載批次核銷明細API
    const COUPON_STOCKS_REFUND_FLOW_DOWNLOAD = '/v3/marketing/favor/stocks/%s/refund-flow';//下載批次退款明細API
    const SETTING_COUPON_CALLBACKS = '/v3/marketing/favor/callbacks';//設定訊息通知地址API
    /**
     * @var string
     */
    private $wechat_app_id;

    /**
     * WechatCouponService constructor.
     */
    public function __construct()
    {
        $this->baseUrl = 'https://api.mch.weixin.qq.com';
        // 微信支付 商戶號
        $this->mch_id = '';
        // 二級商戶號,需要走進件系統生成
        $this->sub_mch_id = '';
        // 微信支付 商戶號繫結的appid
        $this->app_id = '';
        // 商戶私鑰
        $this->private_key = wordwrap(file_get_contents(storage_path('apiclient_key.pem')), 64, "n", true);
        // 商戶證照序列號
        // 如何檢視證照序列號:https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao
        $this->serial_no = '';
        // apiv3祕鑰:https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/api-v3-mi-yao
        $this->mch_key = '';
    }

    /**
     * 獲取API v3證照
     * @return mixed
     */
    public function getCert()
    {
        $wechatPayV3CertNo = app('redis')->get(self::REDIS_NAME_WECHAT_PAY_CERT);
        if (empty($wechatPayV3CertNo)) {
            try {
                $url = $this->baseUrl . self::GET_CERTIFICATES;
                $timestamp = time();
                $nonce = $this->nonce_str();
                $body = '';
                $sign = $this->sign($url, 'GET', $timestamp, $nonce, $body, $this->getPrivateKey($this->private_key), $this->mch_id,
                    $this->serial_no);

                $header = [
                    'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $sign,
                    'Accept:application/json',
                    'User-Agent:' . $this->mch_id,
                ];
                $result = $this->curl($url, '', $header, 'GET');
                $result = json_decode($result, true);
                if (!isset($result['data'])) {
                    throw new Exception('微信支付商戶平臺小微企業請求證照請求失敗' . json_encode($result, 256));
                }
            } catch (Exception $e) {
                throw new ResourceException($e->getMessage());
                app('api.exception')->report($e->getMessage());
            }
            $wechatPayV3CertNo = $result['data']['0']['serial_no'];
            app('redis')->set(self::REDIS_NAME_WECHAT_PAY_CERT, $wechatPayV3CertNo, 'EX', 600);
        }
        return $wechatPayV3CertNo;
    }

    /**
     * 獲取隨機字串
     * @return string
     */
    protected function nonce_str()
    {
        static $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < 32; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }

    /**
     * 獲取簽名
     * @param $url
     * @param $http_method
     * @param $timestamp
     * @param $nonce
     * @param $body
     * @param $mch_private_key
     * @param $merchant_id
     * @param $serial_no
     * @return string
     */
    protected function sign($url, $http_method, $timestamp, $nonce, $body, $mch_private_key, $merchant_id, $serial_no)
    {
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message = $http_method . "n" .
            $canonical_url . "n" .
            $timestamp . "n" .
            $nonce . "n" .
            $body . "n";

        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);

        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $merchant_id, $nonce, $timestamp, $serial_no, $sign);
        return $token;
    }

    /**
     * 驗籤
     * @param $message
     * @param $signature
     * @param $merchantPublicKey
     * @return bool|int
     */
    private function verify($message, $signature, $merchantPublicKey)
    {
        if (empty($merchantPublicKey)) {
            return false;
        }

        if (!in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) {
            throw new RuntimeException("當前PHP環境不支援SHA256withRSA");
        }
        $signature = base64_decode($signature);
        return openssl_verify($message, $signature, $this->getPublicKey($merchantPublicKey), 'sha256WithRSAEncryption');
    }

    /**
     * @param $associatedData
     * @param $nonceStr
     * @param $ciphertext
     * @param $aesKey
     * @return bool|string
     */
    private function decryptToString($associatedData, $nonceStr, $ciphertext, $aesKey = '')
    {
        if (empty($aesKey)) {
            $aesKey = $this->mch_key;
        }
        $ciphertext = base64_decode($ciphertext);
        if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
            return false;
        }

        // ext-sodium (default installed on >= PHP 7.2)
        if (function_exists('sodium_crypto_aead_aes256gcm_is_available') &&
            sodium_crypto_aead_aes256gcm_is_available()) {
            return sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
        }

        // ext-libsodium (need install libsodium-php 1.x via pecl)
        if (function_exists('Sodiumcrypto_aead_aes256gcm_is_available') &&
            Sodiumcrypto_aead_aes256gcm_is_available()) {
            return Sodiumcrypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
        }

        // openssl (PHP >= 7.1 support AEAD)
        if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', openssl_get_cipher_methods())) {
            $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
            $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);

            return openssl_decrypt($ctext, 'aes-256-gcm', $aesKey, OPENSSL_RAW_DATA, $nonceStr,
                $authTag, $associatedData);
        }

        throw new RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安裝libsodium-php');
    }

    /**
     * 請求
     * @param $url
     * @param array $data
     * @param $header
     * @param string $method
     * @param int $time_out
     * @return mixed
     */
    private function curl($url, $data = [], $header, $method = 'POST', $time_out = 3)
    {
        $curl = curl_init();
        // 設定curl允許執行的最長秒數

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_TIMEOUT, $time_out);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

        if ($method == 'POST') {
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }

        // 執行操作
        $result = curl_exec($curl);

        curl_close($curl);
        return $result;
    }

    /**
     * 獲取請求頭
     * @param $url
     * @param $body
     * @param $method
     * @return array
     */
    protected function getCurlHeader($url, $body, $method)
    {
        $timestamp = time();
        $nonce = $this->nonce_str();
        $sign = $this->sign($url, $method, $timestamp, $nonce, $body, $this->getPrivateKey($this->private_key), $this->mch_id,
            $this->serial_no);

        return [
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $sign,
            'Accept:application/json',
            'User-Agent:' . $this->mch_id,
            'Content-Type:application/json',
            'Wechatpay-Serial:' . $this->getCert(),
        ];
    }

    /**
     * 獲取私鑰
     * @param $key
     * @return bool|resource
     */
    protected function getPrivateKey($key)
    {
        return openssl_get_privatekey($key);
    }

    /**
     * @param $key
     * @return resource
     */
    protected function getPublicKey($key)
    {
        return openssl_get_publickey($key);
    }

    /**
     * 獲取請求頭
     * @return array
     */
    private function getHeaders()
    {
        $headers = array();
        foreach ($_SERVER as $key => $value) {
            if ('HTTP_' == substr($key, 0, 5)) {
                $headers[str_replace('_', '-', substr($key, 5))] = $value;
            }
            if (isset($_SERVER['PHP_AUTH_DIGEST'])) {
                $header['AUTHORIZATION'] = $_SERVER['PHP_AUTH_DIGEST'];
            } elseif (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
                $header['AUTHORIZATION'] = base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW']);
            }
            if (isset($_SERVER['CONTENT_LENGTH'])) {
                $header['CONTENT-LENGTH'] = $_SERVER['CONTENT_LENGTH'];
            }
            if (isset($_SERVER['CONTENT_TYPE'])) {
                $header['CONTENT-TYPE'] = $_SERVER['CONTENT_TYPE'];
            }
        }
        return $headers;
    }

    /**
     * 發放代金券API
     * @param string $stockId 批次號
     * @param string $openId 使用者openid
     * @param string $outRequestNo 商戶單據號
     * @param int|null $couponValue 指定面額發券,面額
     * @param int|null $couponMinimum 指定面額發券,券門檻
     * @return array
     * @throws Exception
     */
    public function couponSend(string $stockId, string $openId, string $outRequestNo, ?int $couponValue, ?int $couponMinimum): array
    {
        try {
            $requestData = [
                'stock_id' => $stockId,
                'out_request_no' => $outRequestNo,
                'appid' => $this->app_id,
                'stock_creator_mchid' => $this->mch_id,
            ];
            if (!empty($couponValue)) {
                $requestData['coupon_value'] = $couponValue;
            }
            if (!empty($couponMinimum)) {
                $requestData['coupon_minimum'] = $couponMinimum;
            }
            $header = $this->getCurlHeader($this->baseUrl . sprintf(self::COUPON_SEND, $openId), json_encode($requestData), 'POST');
            $result = $this->curl($this->baseUrl . sprintf(self::COUPON_SEND, $openId), json_encode($requestData), $header, 'POST');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 條件查詢批次列表API
     * @param string|null $createStartTime 起始時間
     * @param string|null $createEndTime 終止時間
     * @param string|null $status 批次狀態unactivated:未啟用 audit:稽核中 running:執行中 stoped:已停止 paused:暫停發放
     * @param int $offset 分頁頁碼
     * @param int $limit 分頁大小
     * @return array
     * @throws Exception
     */
    public function queryCouponStocks(?string $createStartTime, ?string $createEndTime, ?string $status, $offset = 0, $limit = 10): ?array
    {
        try {
            if (!empty($status) && !in_array($status, ['unactivated', 'audit', 'running', 'stoped', 'paused'])) {
                throw new Exception('狀態錯誤');
            }
            $requestData = [
                'stock_creator_mchid' => $this->mch_id,
                'offset' => $offset,
                'limit' => $limit
            ];
            if (!empty($status)) {
                $requestData['status'] = $status;
            }
            if (!empty($createStartTime)) {
                $requestData['create_start_time'] = Carbon::createFromTimestamp(strtotime($createStartTime))->toRfc3339String();
            }
            if (!empty($createEndTime)) {
                $requestData['create_end_time'] = Carbon::createFromTimestamp(strtotime($createEndTime))->toRfc3339String();
            }
            $url = $this->baseUrl . self::QUERY_COUPON_STOCKS . '?' . getSignContent($requestData);
            $header = $this->getCurlHeader($url, '', 'GET');
            $result = $this->curl($url, '', $header, 'GET');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 查詢批次詳情API
     * @param string $stockId 批次號
     * @return mixed
     */
    public function queryCouponStocksInfo(string $stockId)
    {
        try {
            if (empty($stockId)) {
                throw new Exception('批次號不能為空');
            }
            $requestData = [
                'stock_creator_mchid' => $this->mch_id
            ];
            $url = $this->baseUrl . sprintf(self::QUERY_COUPON_STOCKS_INFO, $stockId) . '?' . getSignContent($requestData);
            $header = $this->getCurlHeader($url, '', 'GET');
            $result = $this->curl($url, '', $header, 'GET');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 查詢代金券詳情API
     * @param string $openId openid
     * @param string $couponId 代金券id
     * @return mixed
     */
    public function queryCouponInfo(string $openId, string $couponId)
    {
        try {
            if (empty($openId)) {
                throw new Exception('openId不能為空');
            }
            if (empty($couponId)) {
                throw new Exception('優惠券id不能為空');
            }
            $requestData = [
                'appid' => $this->app_id
            ];
            $url = $this->baseUrl . sprintf(self::QUERY_COUPON_INFO, $openId, $couponId) . '?' . getSignContent($requestData);
            $header = $this->getCurlHeader($url, '', 'GET');
            $result = $this->curl($url, '', $header, 'GET');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 查詢代金券可用商戶API
     * @param string $stockId 批次號
     * @param int $offset 分頁頁碼,最大1000。
     * @param int $limit 分頁大小,最大50。
     * @return mixed
     */
    public function queryCouponMerchants(string $stockId, $offset = 1, $limit = 10)
    {
        try {
            if (empty($stockId)) {
                throw new Exception('批次號不能為空');
            }
            $requestData = [
                'stock_creator_mchid' => $this->mch_id,
                'offset' => $offset,
                'limit' => $limit
            ];
            $url = $this->baseUrl . sprintf(self::QUERY_COUPON_MERCHANTS, $stockId) . '?' . getSignContent($requestData);
            $header = $this->getCurlHeader($url, '', 'GET');
            $result = $this->curl($url, '', $header, 'GET');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 查詢代金券可用單品API
     * @param string $stockId 批次號
     * @param int $offset 分頁頁碼,最大1000。
     * @param int $limit 分頁大小,最大50。
     * @return mixed
     */
    public function queryCouponItems(string $stockId, $offset = 1, $limit = 10)
    {
        try {
            if (empty($stockId)) {
                throw new Exception('批次號不能為空');
            }
            $requestData = [
                'stock_creator_mchid' => $this->mch_id,
                'offset' => $offset,
                'limit' => $limit
            ];
            $url = $this->baseUrl . sprintf(self::QUERY_COUPON_ITEMS, $stockId) . '?' . getSignContent($requestData);
            $header = $this->getCurlHeader($url, '', 'GET');
            $result = $this->curl($url, '', $header, 'GET');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 根據商戶號查使用者的券
     * @param string $openId 使用者標識
     * @param string $stockId 批次號
     * @param string $status 狀態SENDED:可用 USED:已實扣
     * @param string $creatorMchid 建立批次的商戶號
     * @param string $senderMchid 批次發放商戶號
     * @param string $availableMchid 可用商戶號
     * @param int $offset 分頁頁碼
     * @param int $limit 分頁大小
     * @return mixed
     */
    public function queryUserCoupon(string $openId, $stockId = '', $status = '', $creatorMchid = '', $senderMchid = '', $availableMchid = '', $offset = 0, $limit = 20)
    {
        try {
            if (!empty($status) && !in_array($status, ['SENDED', 'USED'])) {
                throw new Exception('狀態錯誤');
            }
            $requestData = [
                'appid' => $this->app_id,
                'offset' => $offset,
                'limit' => $limit,
                'creator_mchid' => $this->mch_id,
            ];
            if (!empty($stockId)) {
                $requestData['stock_id'] = $stockId;
            }
            if (!empty($status)) {
                $requestData['status'] = $status;
            }
            if (!empty($senderMchid)) {
                $requestData['available_mchid'] = $senderMchid;
            }
            if (!empty($availableMchid)) {
                $requestData['available_mchid'] = $availableMchid;
            }
            $url = $this->baseUrl . sprintf(self::QUERY_USER_COUPON, $openId) . '?' . getSignContent($requestData);
            $header = $this->getCurlHeader($url, '', 'GET');
            $result = $this->curl($url, '', $header, 'GET');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 下載批次核銷明細API
     * @param string $stockId 批次號
     * @return mixed
     */
    public function couponStocksUserFlowDownload(string $stockId)
    {
        try {
            if (empty($stockId)) {
                throw new Exception('批次號不能為空');
            }
            $url = $this->baseUrl . sprintf(self::COUPON_STOCKS_USER_FLOW_DOWNLOAD, $stockId);
            $header = $this->getCurlHeader($url, '', 'GET');
            $result = $this->curl($url, '', $header, 'GET');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 下載批次退款明細API
     * @param string $stockId 批次號
     * @return mixed
     */
    public function couponStocksRefundFlowDownload(string $stockId)
    {
        try {
            if (empty($stockId)) {
                throw new Exception('批次號不能為空');
            }
            $url = $this->baseUrl . sprintf(self::COUPON_STOCKS_REFUND_FLOW_DOWNLOAD, $stockId);
            $header = $this->getCurlHeader($url, '', 'GET');
            $result = $this->curl($url, '', $header, 'GET');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }

    /**
     * 設定訊息通知地址API
     * @param string $notifyUrl 支付通知商戶url地址。
     * @param bool $switch 如果商戶不需要再接收營銷事件通知,可通過該開關關閉。列舉值:true:開啟推送 false:停止推送
     * @return mixed
     */
    public function settingCouponCallbacks(string $notifyUrl, bool $switch)
    {
        try {
            if (empty($notifyUrl)) {
                throw new ResourceException('回撥地址不能為空,且必須是完整的https連結');
            }
            $requestData = [
                'mchid' => $this->mch_id,
                'notify_url' => $notifyUrl,
                'switch' => $switch
            ];
            $url = $this->baseUrl . self::SETTING_COUPON_CALLBACKS;
            $header = $this->getCurlHeader($url, json_encode($requestData), 'POST');
            $result = $this->curl($url, json_encode($requestData), $header, 'POST');
            $result = json_decode($result, true);
            if (!$result || isset($result['code'])) {
                if (!$result) {
                    throw new ResourceException('操作失敗,請重新整理頁面後重試');
                }
                throw new ResourceException($result['code'] . '---' . $result['message']);
            }
            return $result;
        } catch (Exception $e) {
            throw new ResourceException($e->getMessage());
        }
    }
}
?>
<?php
if (!function_exists('getSignContent')) {
    /**
     * 拼接uri 用於驗籤等功能
     */
    function getSignContent($params) {
        ksort($params);
        $i                = 0;
        $stringToBeSigned = "";
        foreach ($params as $k => $v) {
            if ($i == 0) {
                $stringToBeSigned .= "$k" . "=" . "$v";
            } else {
                $stringToBeSigned .= "&" . "$k" . "=" . "$v";
            }
            $i++;
        }
        unset ($k, $v);
        return $stringToBeSigned;
    }

}
?>php
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章