php实现微信jsapi支付(v2版本)

统一下单

    /**
     * 下单方法
     * @param   $params 下单参数
     */
    public function unifiedOrder($product_type = 1, $openid = '', $phone = '')
    {
        //订单总价
        $total_fee = 79900;
        if ($product_type == 1) {
            $total_fee = 79900;
        }
        if ($product_type == 2) {
            $total_fee = 99900;
        }
        //$total_fee = 1;
        $data = array(
            'appid' => config('mp.appid'),//参数
            'body' => '商城',
            'mch_id' => config('mp.mch_id'),//商户id
            'nonce_str' => self::getRandChar(32), //随机字符串
            'notify_url' => '', //回调地址
            'out_trade_no' => $phone . '_' . time(), //订单号
            'spbill_create_ip' => self::get_client_ip(),
            'total_fee' => $total_fee,
            'trade_type' => "JSAPI",
            'openid' => $openid,
        );
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $signkey = config('mp.key');
        $data["sign"] = self::getSign($data, $signkey);
        $xml = self::arrayToXml($data);
        $response = self::postXmlCurl($xml, $url);
        $ress = self::xmlstr_to_array($response);
        if ($ress['return_code'] == 'FAIL') {
            return array('code' => 0, 'message' => $ress['return_msg']);
        }
        if ($ress['result_code'] == 'FAIL') {
            return array('code' => $ress['err_code'], 'message' => $ress['err_code_des']);
        }
        $datas = [
            'appId' => config('mp.appid'),//参数
            'timeStamp' => time() . '',
            'nonceStr' => self::getRandChar(32),
            'package' => "prepay_id=" . $ress['prepay_id'],
            'signType' => "MD5",
        ];
        //生成签名
        $datas['paySign'] = self::getSign($datas, $signkey);
        $this->success('success', $datas);
    }
    
    /**
     * 获取随机字符串
     */
    private static function getRandChar($length)
    {
        $str = null;
        $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
        $max = strlen($strPol) - 1;
        for ($i = 0; $i < $length; $i++) {
            $str .= $strPol[rand(0, $max)]; // rand($min,$max)生成介于min和max两个数之间的一个随机整数
        }
        return $str;
    }

    /**
     * 获取服务器真实IP
     */
    private static function get_client_ip()
    {
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            //ip from share internet
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            //ip pass from proxy
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        return $ip;
    }

    /**
     * 支付签名
     * @param  [type] $Obj     [description]
     * @param  [type] $api_key [description]
     * @return [type]          [description]
     */
    private static function getSign($Obj, $api_key)
    {
        foreach ($Obj as $k => $v) {
            //$Parameters[strtolower($k)] = $v;
            $Parameters[$k] = $v;
        }
        ksort($Parameters);
        //dump($Parameters);
        $String = self::formatBizQueryParaMap($Parameters, false);
        //dump($String);
        $String = $String . "&key=" . $api_key;
        //dump($String);
        $result = strtoupper(md5($String));
        return $result;
    }

    /**
     * 将数组转成uri字符串
     * @param  [type] $paraMap   [description]
     * @param  [type] $urlencode [description]
     * @return [type]            [description]
     */
    private static function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if ($urlencode) {
                $v = urlencode($v);
            }
            //$buff .= strtolower($k) . "=" . $v . "&";
            $buff .= $k . "=" . $v . "&";
        }
        $reqPar;
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

    /**
     * 数组转xml
     * @param  [type] $arr [description]
     * @return [type]      [description]
     */
    private static function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    /**
     * @param $xml
     * @param $url
     * @param int $second
     * @return bool|string
     */
    private static function postXmlCurl($xml, $url, $second = 30)
    {
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置 header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post 提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行 curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            echo "curl 出错,错误码:$error" . "<br>";
        }
    }

    /**
     * xml转数组
     * @param  [type] $xmlstr [description]
     * @return [type]         [description]
     */
    private static function xmlstr_to_array($xmlstr)
    {
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $xmlstring = simplexml_load_string($xmlstr, 'SimpleXMLElement', LIBXML_NOCDATA);
        $val = json_decode(json_encode($xmlstring), true);
        return $val;
    }
支付成功回调
    /**
     * 异步回调地址
     */
    public function notify()
    {
        //获取返回的xml
        $testxml = file_get_contents("php://input");
        //将xml转化为json格式
        $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
        //转成数组
        $result = json_decode($jsonxml, true);
        file_log("mp_pay_notify_content.log", json_encode($result));
        echo '<xml> <return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
		//业务逻辑
    }
微信小程序端
uni.request({
	url: '后端下单地址',
	method: 'GET',
	data: {
		product_type: this.product_type,
		openid: this.openid,
		phone: this.phone
	},
	success: (cts) => {
		var result = cts.data.data
		let that = this
		uni.requestPayment({
			appId: result.appId, // 公众号名称,由商户传入
			timeStamp: result.timeStamp, // 时间戳,自1970年以来的秒数
			nonceStr: result.nonceStr, // 随机串
			package: result.package,
			signType: 'MD5', // 微信签名方式:
			paySign: result.paySign, // 微信签名
			success(res) {
				if (res.errMsg === 'requestPayment:ok') {
					//支付成功跳转
					uni.navigateTo({
						url: "/pages/index/order?phone=" + that.phone
					})
				}
			},
			fail(err) {
				console.log("支付失败", err)
			}
		})

	}
});
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值