PHP js服务商支付和服务商退款


public function get_open_id()
{
    $sub_appid = '客户APPID';
    $sub_mch_id = '客户macID';
    $app_secret = "客户appsecret";
    //通过code获得openid
    if (!isset($_GET['code'])) {
        //触发微信返回code码
        $baseUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']);
        $url = $this->_CreateOauthUrlForCode($sub_appid, $baseUrl);
        Header("Location: $url");
        exit();
    } else {
        //获取code码,以获取openid
        $code = $_GET['code'];
        $openid = $this->getOpenidFromMp($code, $sub_appid, $app_secret, $sub_mch_id);
        return $openid;
    }

}

public static function getSign($params, $key)
{
    ksort($params, SORT_STRING);
    $unSignParaString = self::formatQueryParaMap($params, false);
    $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));

    return $signStr;
}

protected static function formatQueryParaMap($paraMap, $urlEncode = false)
{
    $buff = "";
    ksort($paraMap);
    foreach ($paraMap as $k => $v) {
        if (null != $v && "null" != $v) {
            if ($urlEncode) {
                $v = urlencode($v);
            }
            $buff .= $k . "=" . $v . "&";
        }
    }
    $reqPar = '';
    if (strlen($buff) > 0) {
        $reqPar = substr($buff, 0, strlen($buff) - 1);
    }

    return $reqPar;
}

//支付
public function pay($datas)
{

    $order_no = '';

    $data = ['type' => '', 'order_no' => $order_no];
    $attach = json_encode($data, JSON_UNESCAPED_UNICODE);

    $appid = '服务商APPID';

    $sub_appid = '客户APPID';

    $sub_mch_id = '客户MCHID';

    $mch_id = '服务商MCHID';
    $open_id = $this->get_open_id();
    $sub_openid = $open_id;
    $body = '';
    $out_trade_no = $order_no;
    $total_fee = $datas['money'] * 100;
    $spbill_create_ip = \request()->ip();
    $notify_url = '回调地址';
    $trade_type = "JSAPI";
    $nonce_str = getRandom(32);
    $key = '服务商支付key';

    $arr = [
        'attach' => $attach,
        'appid' => $appid,
        'sub_mch_id' => $sub_mch_id,
        'body' => $body,
        'sub_appid' => $sub_appid,
        'sub_openid' => $sub_openid,
        'mch_id' => $mch_id,
        'nonce_str' => $nonce_str,
        'notify_url' => $notify_url,
        'out_trade_no' => $out_trade_no,
        'spbill_create_ip' => $spbill_create_ip,
        'total_fee' => $total_fee,
        'trade_type' => $trade_type,
    ];

    ksort($arr);

    $sign_str = "";
    foreach ($arr as $k => $v) {
        $sign_str .= $k . '=' . $v . '&';
    }

    $sign_str = rtrim($sign_str, '&');
    $sign_str = $sign_str . '&key=' . $key;
    $sign_str = strtoupper(md5($sign_str));

    // 构造xml数据
    $xmlData = "
<xml>
<appid>${appid}</appid>
<sub_appid>${sub_appid}</sub_appid>
<sub_mch_id>${sub_mch_id}</sub_mch_id>
<attach>${attach}</attach>
<body>${body}</body>
<mch_id>${mch_id}</mch_id>
<nonce_str>${nonce_str}</nonce_str>
<notify_url>${notify_url}</notify_url>
<sub_openid>${sub_openid}</sub_openid>
<out_trade_no>${out_trade_no}</out_trade_no>
<spbill_create_ip>${spbill_create_ip}</spbill_create_ip>
<total_fee>${total_fee}</total_fee>
<trade_type>${trade_type}</trade_type>
<sign>${sign_str}</sign>
</xml>";
    $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; //接收xml数据的文件
    $ch = curl_init();  // 初始一个curl会话
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    $result = curl_exec($ch);   // 抓取URL并把它传递给浏览器
    // 是否报错
    if (curl_errno($ch)) {
        print curl_error($ch);
    }
    curl_close($ch);    // //关闭cURL资源,并且释放系统资源

    $timeStamp = time() . "";
    $result = xmlToArray($result);
    $result['signType'] = "MD5";
    $result['timeStamp'] = $timeStamp;
    $result['nonce_str'] = $nonce_str;
    $result['package'] = "prepay_id=" . $result['prepay_id'];

    $arr = [
        "appId" => $result['appid'],
        "timeStamp" => $timeStamp,  //这里是字符串的时间戳,不是int,所以需加引号
        "nonceStr" => $nonce_str,
        "package" => "prepay_id=" . $result['prepay_id'],
        "signType" => 'MD5',
    ];

    $result['paySign'] = self::getSign($arr, $key);

    return $result;
}

//退款
public function refund($order_no, $total_fee, $refund_fee)
{
    // 当前时间
    $time = time();
    // 生成随机字符串
    $nonceStr = md5($time . $order_no . $total_fee . $refund_fee);

    $main_appid = '服务商APPID';
    $appid = '客户';
    $sub_mch_id = '服务商';
    $mch_id = '客户';
    $key = '服务商支付key';

    // API参数
    $params = [
        'sub_appid' => $appid,
        'appid' => $main_appid,
        'mch_id' => $mch_id,
        'sub_mch_id' => $sub_mch_id,
        'nonce_str' => $nonceStr,
        'out_trade_no' => $order_no,
        'out_refund_no' => $time,
        'total_fee' => $total_fee * 100,
        'refund_fee' => $refund_fee * 100,
    ];

    // 生成签名
    $params['sign'] = $this->makeSign($params, $key);

    // 请求API
    $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
    $result = $this->post($url, $this->toXmls($params), true, $this->getCertPem());

    // 请求失败
    if (empty($result)) {
        throw new BaseException(['msg' => '微信退款api请求失败']);
    }
    // 格式化返回结果
    $prepay = $this->fromXml($result);
    // 请求失败
    if ($prepay['return_code'] === 'FAIL') {
        throw new BaseException(['msg' => 'return_msg: ' . $prepay['return_msg']]);
    }
    if ($prepay['result_code'] === 'FAIL') {
        throw new BaseException(['msg' => 'err_code_des: ' . $prepay['err_code_des']]);
    }
    return true;
}

 /**
* 生成签名
 */
private function makeSign($values, $key = null)
{
    //签名步骤一:按字典序排序参数
    ksort($values);
    $string = $this->toUrlParams($values);
    //签名步骤二:在string后加入KEY
    $string = $string . '&key=' . $key;
    //签名步骤三:MD5加密
    $string = md5($string);
    //签名步骤四:所有字符转为大写
    $result = strtoupper($string);
    return $result;
}

private function ToUrlParams($urlObj)
{
    $buff = "";
    foreach ($urlObj as $k => $v) {
        if ($k != "sign") {
            $buff .= $k . "=" . $v . "&";
        }
    }

    $buff = trim($buff, "&");
    return $buff;
}

private function getCertPem()

    // cert目录
    $filePath ='';
    $res = [
        'certPem' => $filePath . 'cert.pem',
        'keyPem' => $filePath . 'key.pem'
    ];
    return $res;
}

public function _CreateOauthUrlForCode($appid, $redirectUrl)
{
    $urlObj["appid"] = $appid;
    $urlObj["redirect_uri"] = "$redirectUrl";
    $urlObj["response_type"] = "code";
    $urlObj["scope"] = "snsapi_base";
    $urlObj["state"] = "STATE" . "#wechat_redirect";
    $bizString = $this->ToUrlParams($urlObj);
    return "https://open.weixin.qq.com/connect/oauth2/authorize?" . $bizString;
}

public function GetOpenidFromMp($code, $appid, $appsecret, $mch_id)
{
    $url = $this->__CreateOauthUrlForOpenid($code, $appid, $appsecret);

    //初始化curl
    $ch = curl_init();
    $curlVersion = curl_version();
    $ua = "WXPaySDK/3.0.9 (" . PHP_OS . ") PHP/" . PHP_VERSION . " CURL/" . $curlVersion['version'] . " "
        . $mch_id;

    //设置超时
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_USERAGENT, $ua);
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $res = curl_exec($ch);
    curl_close($ch);
    //取出openid
    $data = json_decode($res, true);
    $this->data = $data;
    $openid = $data['openid'];
    return $openid;
}

private function __CreateOauthUrlForOpenid($code, $appid, $appsecret)
{
    $urlObj["appid"] = $appid;
    $urlObj["secret"] = $appsecret;
    $urlObj["code"] = $code;
    $urlObj["grant_type"] = "authorization_code";
    $bizString = $this->ToUrlParams($urlObj);
    return "https://api.weixin.qq.com/sns/oauth2/access_token?" . $bizString;
}

private function fromXml($xml)
{
    // 禁止引用外部xml实体
    libxml_disable_entity_loader(true);
    return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
}

private function toXmls($values)
{
    if (!is_array($values)
        || count($values) <= 0
    ) {
        return false;
    }

    $xml = "<xml>";
    foreach ($values as $key => $val) {
        if (is_numeric($val)) {
            $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
        } else {
            $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
    }
    $xml .= "</xml>";
    return $xml;
}

protected function post($url, $data = [], $useCert = false, $sslCert = [])
{
    $header = [
        'Content-type: application/json;'
    ];
    $curl = curl_init();
    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_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_POST, TRUE);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

    if ($useCert == true) {
        // 设置证书:cert 与 key 分别属于两个.pem文件
        curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
        curl_setopt($curl, CURLOPT_SSLCERT, $sslCert['certPem']);
        curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($curl, CURLOPT_SSLKEY, $sslCert['keyPem']);
    }
    $result = curl_exec($curl);
    curl_close($curl);
    return $result;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值