微信支付v3版本PHP营销图片上传

微信支付v3版本PHP营销图片上传

       昨晚又接到一个需求,依然是微信接口相关的,这一次是微信支付v3图片上传接口,由于也是第一次接触到,所以还是仔细阅读了下文档介绍以及相关流程,再加上前两天已经成功调试出微信支付V3签名验证,所以调试出来也没浪费多少时间,我还弄了一个前端上传图片,后端调用微信接口返回图片地址的功能。

       其实调试主要难题是body体的构造,百度了查询相关的代码,最终还是成功调试出,下面是公共配置文件代码,命名为wxComm.php,代码如下:

#微信基础信息
$wxMerchantId = "商户号";                                          //商户号
$wxMerchantApiCertificate = __DIR__ . "/cert/apiclient_cert.pem";  //商户证书
$wxMerchantApiPrivateKey = __DIR__ . "/cert/apiclient_key.pem";    //商户私钥
$wxApiV3Key = "微信API v3密钥";                                    //微信API v3密钥
$wxApiSerialNo = "商户API证书序列号";                              //商户API证书序列号

######微信 API V3构造签名流程#######


/**
 * 生成签名
 * @param string $method 请求方法 POST 或者GET
 * @param string $url 请求URL
 * @param string $request 请求中的请求报文主体
 * @param $wxMerchantId商户号
 * @param $certKey商户私钥
 * @param $wxApiSerialNo商户API证书序列号
 * @return string
 */
function RequestSign($method = "POST", $url = "", $request = "", $wxMerchantId, $certKey, $wxApiSerialNo)
{
    #截取获取当前请求地址【去除域名】
    $url_parts = parse_url($url);
    $path = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
    #获取当前时间戳
    $timeStamp = time();
    #生成一个随机字符串
    $nonceStr = getNonceStr();
    #构造签名串
    $requestSign = sprintf("%s\n%s\n%s\n%s\n%s\n", $method, $path, $timeStamp, $nonceStr, $request);
    #计算计算签名值
    $sign = calculateSignatureValue($requestSign, $certKey);
    #设置HTTP头获取Authorization
    $token = createToken($wxMerchantId, $nonceStr, $timeStamp, $wxApiSerialNo, $sign);
    #返回
    return $token;
}

/**
 * 计算签名值
 * @param $requestSign
 * @param $certKey
 * @return string
 * 使用商户私钥对待签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值
 */
function calculateSignatureValue($requestSign, $certKey)
{
    $certKey = file_get_contents($certKey);
    openssl_sign($requestSign, $raw_sign, $certKey, 'sha256WithRSAEncryption');
    $sign = base64_encode($raw_sign);
    return $sign;
}

/**
 * 获取token
 * @param $merchant_id
 * @param $nonce
 * @param $timestamp
 * @param $serial_no
 * @param $sign
 * @return string
 */
function createToken($merchant_id, $nonce, $timestamp, $serial_no, $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;
}

/**
 * 产生随机字符串,不长于32位
 * @param int $length
 * @return string
 */
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;
}

/**
 * POST发送图片数据源
 * @param $url
 * @param $data
 * @param array $header
 * @param string $referer
 * @param int $timeout
 * @return mixed
 */
function curlPostToImage($url, $data, $header = array(), $referer = '', $timeout = 30)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    //避免https 的ssl验证
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSLVERSION, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    // 模拟来源
    curl_setopt($ch, CURLOPT_REFERER, $referer);
    $response = curl_exec($ch);
    if ($error = curl_error($ch)) {
        die($error);
    }
    curl_close($ch);
    //json转数组
    $result = json_decode($response,true);
    //返回
    return $result;
}

       然后是调用文件代码,我们先提前创建好一个images的文件夹,并给777权限,用来存放图片,代码如下:

#引入微信公共配置文件
require __DIR__ . "/wxComm.php";

#头部响应设置
header('Access-Control-Allow-Origin:*');
// 响应类型
header('Access-Control-Allow-Methods:GET');
// 响应头设置
header('Access-Control-Allow-Headers:x-requested-with,content-type');

header('Content-Type:application/json; charset=utf-8');

#获取上传图片
$file = $_FILES["file"];
#判断上传的是否为图片格式
if ((($_FILES["file"]["type"] != "image/gif")
    && ($_FILES["file"]["type"] != "image/jpeg")
    && ($_FILES["file"]["type"] != "image/jpg")
    && ($_FILES["file"]["type"] != "image/pjpeg")
    && ($_FILES["file"]["type"] != "image/x-png")
    && ($_FILES["file"]["type"] != "image/png"))
) {
    $json = json_encode(array(
        'status' => '-1',
        'msg' => "请上传图片"
    ));
    echo($json);
    exit();
}
#重新设置文件名
$fileType = str_replace("image/", "", $_FILES["file"]["type"]);
$saveName = time() . rand(1, 1000);
$fileName = $saveName . "." . $fileType;
#保存图片
move_uploaded_file($_FILES["file"]["tmp_name"], "images/" . $fileName);
#拼接当前地址
$src = "images/" . $fileName;
$imageUrl = __DIR__ . "/images/" . $fileName;
#请求地址
$url = "https://api.mch.weixin.qq.com/v3/marketing/favor/media/image-upload";
#请求参数
$params = array(
    "filename" => $fileName,                              //文件名
    'sha256' => hash_file('sha256', $imageUrl)     //图片文件的二进制内容进行sha256
);
#获取authorization
$authorization = RequestSign("POST", $url, json_encode($params), $wxMerchantId, $wxMerchantApiPrivateKey, $wxApiSerialNo);
#组合body请求体
$boundary = uniqid(); //分割符号
$boundaryStr = "--{$boundary}\r\n";
$out = $boundaryStr;
$out .= 'Content-Disposition: form-data; name="meta"' . "\r\n";
$out .= 'Content-Type: application/json' . "\r\n";
$out .= "\r\n";
$out .= json_encode($params) . "\r\n";
$out .= $boundaryStr;
$out .= 'Content-Disposition: form-data; name="file"; filename="' . $params['filename'] . '"' . "\r\n";
$out .= 'Content-Type: ' . $fileType . ';' . "\r\n";
$out .= "\r\n";
$out .= file_get_contents($imageUrl) . "\r\n";
$out .= "--{$boundary}--\r\n";
#组合请求头
$header[] = 'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36';
$header[] = 'Accept:application/json';
$header[] = 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $authorization;
$header[] = 'Content-Type:multipart/form-data;boundary=' . $boundary;
#请求发送文件
$result = curlPostToImage($url, $out, $header);
#删除本地图片
unlink($imageUrl);
#判断是否成功
if (!isset($result["media_url"])) {
    $json = json_encode(array(
        'status' => '-1',
        'msg' => "上传失败"
    ));
    echo($json);
    exit();
}
#返回请求结果
$json = json_encode(array(
    'status' => '1',
    'msg' => $result["media_url"]
));
echo($json);
exit();

       附上效果图

2222.png

       这样我们就成功的将图片上传至微信,并获得图片地址。

0条评论

发表评论