|
@@ -1,424 +0,0 @@
|
|
|
-<?php
|
|
|
-
|
|
|
- * 微信支付
|
|
|
- * Created by PhpStorm.
|
|
|
- * User: phperstar
|
|
|
- * Date: 2019/11/28
|
|
|
- * Time: 2:12 PM
|
|
|
- */
|
|
|
-namespace Util\WeiXin;
|
|
|
-
|
|
|
-
|
|
|
-class QnWxPay
|
|
|
-{
|
|
|
-
|
|
|
- * 小程序 appId
|
|
|
- * @var string $appid
|
|
|
- */
|
|
|
- private $appid;
|
|
|
-
|
|
|
- * 商户号
|
|
|
- * @var string $mch_id
|
|
|
- */
|
|
|
- private $mch_id;
|
|
|
-
|
|
|
-
|
|
|
- * 商户支付密钥
|
|
|
- */
|
|
|
- private $partnerKey;
|
|
|
-
|
|
|
-
|
|
|
- * 微信支付异步通知地址
|
|
|
- */
|
|
|
- private $notifyUrl = PAY_NOTIFY_URL.'/common/WeiXinPayNotify/notify';
|
|
|
-
|
|
|
-
|
|
|
- * 公共的接口请求地址
|
|
|
- * @var string
|
|
|
- */
|
|
|
- private $apiUrl = 'https://api.mch.weixin.qq.com/pay/';
|
|
|
-
|
|
|
-
|
|
|
- * 基础得请求地址
|
|
|
- */
|
|
|
- private $baseUrl = 'https://api.mch.weixin.qq.com/';
|
|
|
-
|
|
|
-
|
|
|
- private $config;
|
|
|
-
|
|
|
-
|
|
|
- * Pay constructor.
|
|
|
- * @param string $appid
|
|
|
- * @param $mch_id
|
|
|
- * @param $partnerKey
|
|
|
- */
|
|
|
- public function __construct($appid='', $mch_id, $partnerKey)
|
|
|
- {
|
|
|
- $this->appid = $appid;
|
|
|
- $this->mch_id = $mch_id;
|
|
|
- $this->partnerKey = $partnerKey;
|
|
|
- if(empty($config)) $config = config('wxpay');
|
|
|
- $this->config = $config;
|
|
|
- }
|
|
|
-
|
|
|
- public function wxmpPay($post=[]){
|
|
|
- $url = $this->apiUrl.'unifiedorder';
|
|
|
- $params = [
|
|
|
- 'appid' => $this->config["APPID"],
|
|
|
- 'mch_id' => $this->config["MCHID"],
|
|
|
- 'nonce_str' => md5(md5(time().randString(10))),
|
|
|
- 'out_trade_no' => $post["out_trade_no"],
|
|
|
- 'total_fee' => (int)(floatval($post["total"])*100),
|
|
|
- 'spbill_create_ip' => empty($post["payer_client_ip"])?"127.0.0.1":$post["payer_client_ip"],
|
|
|
- 'trade_type' => "JSAPI",
|
|
|
- 'notify_url' => $this->config["NOTIFY_URL"],
|
|
|
- 'body' => empty($post["body"]) ?"微信小程序支付":$post["body"],
|
|
|
- 'attach' => empty($post["attach"])?"微信小程序支付":$post["attach"],
|
|
|
- 'openid' => $post["openid"],
|
|
|
- ];
|
|
|
- $params["sign"] = self::getSign($params);
|
|
|
-
|
|
|
- $curl_content = request($url, $post_xml);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * 统一下单接口
|
|
|
- */
|
|
|
- public function unifiedorder($orderNo, $total_fee, $ip, $source, $shopName, $openid = '', $attach = '')
|
|
|
- {
|
|
|
- $url = $this->apiUrl.'unifiedorder';
|
|
|
-
|
|
|
- switch ($source){
|
|
|
- case 'H5':
|
|
|
- $trade_type = 'MWEB';
|
|
|
- break;
|
|
|
- case 'APP':
|
|
|
- $trade_type = 'APP';
|
|
|
- break;
|
|
|
- default:
|
|
|
- $trade_type = 'JSAPI';
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- $params = [
|
|
|
- 'appid' => $this->appid,
|
|
|
- 'mch_id' => $this->mch_id,
|
|
|
- 'nonce_str' => md5(md5(time().'qianniao.vip')),
|
|
|
- 'out_trade_no' => $orderNo,
|
|
|
- 'total_fee' => yuanToFen($total_fee),
|
|
|
- 'spbill_create_ip' => $ip,
|
|
|
- 'trade_type' => $trade_type,
|
|
|
- 'notify_url' => $this->notifyUrl,
|
|
|
- 'body' => $shopName.'-'.'线上商城',
|
|
|
- 'attach' => $attach,
|
|
|
- ];
|
|
|
- if($trade_type == 'JSAPI'){
|
|
|
- $params['openid'] = $openid;
|
|
|
- }
|
|
|
-
|
|
|
- $params['sign'] = self::getSign($params);
|
|
|
- $post_xml = $this->arrayToWeiXinXml($params);
|
|
|
- $curl_content = request($url, $post_xml);
|
|
|
-
|
|
|
- $result = $this->commonResult($curl_content);
|
|
|
- if(!$result->isSuccess()){
|
|
|
- return ResultWrapper::fail($result->getData(), $result->getErrorCode());
|
|
|
- }
|
|
|
- $response_content = $result->getData();
|
|
|
-
|
|
|
-
|
|
|
- $prepay_id = $response_content['prepay_id'];
|
|
|
-
|
|
|
-
|
|
|
- $mweb_url = isset($response_content['mweb_url']) ? $response_content['mweb_url'] : '';
|
|
|
-
|
|
|
- switch ($source){
|
|
|
- case 'byteDanceH5':
|
|
|
- $payParams = $mweb_url;
|
|
|
- break;
|
|
|
- case 'H5':
|
|
|
- $payParams = self::payment($prepay_id);
|
|
|
- break;
|
|
|
- case 'APP':
|
|
|
- $payParams = self::payment($prepay_id);
|
|
|
- break;
|
|
|
- default:
|
|
|
- $payParams = self::paymentToMinprogram($prepay_id);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return ResultWrapper::success($payParams);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * 小程序调起支付用到的参数
|
|
|
- * 官方接口地址: https:
|
|
|
- */
|
|
|
- public function paymentToMinprogram($prepay_id)
|
|
|
- {
|
|
|
- unset($params);
|
|
|
- $params = [
|
|
|
- 'appId' => $this->appid,
|
|
|
- 'timeStamp' => (string)time(),
|
|
|
- 'nonceStr' => md5(md5(time().'qianniao.vip')),
|
|
|
- 'package' => 'prepay_id='.$prepay_id,
|
|
|
- 'signType' => 'MD5',
|
|
|
- ];
|
|
|
- $params['paySign'] = self::getSign($params);
|
|
|
- return $params;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * 调起支付用到的参数
|
|
|
- * 官方接口地址: https:
|
|
|
- * @param $prepay_id
|
|
|
- */
|
|
|
- public function payment($prepay_id)
|
|
|
- {
|
|
|
- unset($parm);
|
|
|
- $parm = array(
|
|
|
- 'appid' => $this->appid,
|
|
|
- 'partnerid' => $this->mch_id,
|
|
|
- 'timestamp' => (string)time(),
|
|
|
- 'noncestr' => md5(md5(time().'qianniao.vip')),
|
|
|
- 'prepayid' => $prepay_id,
|
|
|
- 'package' => 'Sign=WXPay',
|
|
|
- );
|
|
|
- $parm['sign'] = self::getSign($parm);
|
|
|
- return $parm;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * 付款码支付
|
|
|
- * 官方文档地址: https:
|
|
|
- */
|
|
|
- public function micropay($orderNo, $total_fee, $ip, $shopName, $auth_code)
|
|
|
- {
|
|
|
- $url = $this->apiUrl.'micropay';
|
|
|
-
|
|
|
- $params = [
|
|
|
- 'appid' => $this->appid,
|
|
|
- 'mch_id' => $this->mch_id,
|
|
|
- 'nonce_str' => md5(md5(time().'qianniao.vip')),
|
|
|
- 'body' => $shopName.'-'.'线上商城',
|
|
|
- 'out_trade_no' => $orderNo,
|
|
|
- 'total_fee' => yuanToFen($total_fee),
|
|
|
- 'spbill_create_ip' => $ip,
|
|
|
- 'auth_code' => $auth_code,
|
|
|
- ];
|
|
|
- $params['sign'] = self::getSign($params);
|
|
|
- $post_xml = $this->arrayToWeiXinXml($params);
|
|
|
- $curl_content = request($url, $post_xml);
|
|
|
-
|
|
|
- if($curl_content['httpcode'] != '200'){
|
|
|
- return ResultWrapper::fail($curl_content['errorMsg'], ErrorCode::$apiNotResult);
|
|
|
- }
|
|
|
-
|
|
|
- $response_content = (array)simplexml_load_string($curl_content['content'], 'SimpleXMLElement', LIBXML_NOCDATA);
|
|
|
- if($response_content['return_code'] != 'SUCCESS'){
|
|
|
- return ResultWrapper::fail($response_content['return_msg'], ErrorCode::$weixinPayError);
|
|
|
- }
|
|
|
-
|
|
|
- if($response_content['result_code'] != 'SUCCESS' && $response_content['err_code'] != 'USERPAYING' ){
|
|
|
- return ResultWrapper::fail($response_content['err_code_des'], ErrorCode::$weixinPayError);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- for($i=1; $i<=10; $i++)
|
|
|
- {
|
|
|
- $url = $this->apiUrl.'orderquery';
|
|
|
- $params = [
|
|
|
- 'appid' => $this->appid,
|
|
|
- 'mch_id' => $this->mch_id,
|
|
|
- 'nonce_str' => md5(md5(time().'qianniao.vip')),
|
|
|
- 'out_trade_no' => $orderNo,
|
|
|
- ];
|
|
|
-
|
|
|
- $params['sign'] = self::getSign($params);
|
|
|
- $post_xml = $this->arrayToWeiXinXml($params);
|
|
|
- $curl_content = request($url, $post_xml);
|
|
|
-
|
|
|
- if($curl_content['httpcode'] != '200'){
|
|
|
- return ResultWrapper::fail($curl_content['errorMsg'], ErrorCode::$apiNotResult);
|
|
|
- }
|
|
|
-
|
|
|
- $response_content = (array)simplexml_load_string($curl_content['content'], 'SimpleXMLElement', LIBXML_NOCDATA);
|
|
|
- if($response_content['return_code'] != 'SUCCESS'){
|
|
|
- return ResultWrapper::fail($response_content['return_msg'], ErrorCode::$weixinPayError);
|
|
|
- }
|
|
|
-
|
|
|
- if($response_content['result_code'] != 'SUCCESS' && $response_content['err_code'] == 'ORDERNOTEXIST'){
|
|
|
- return ResultWrapper::fail($response_content['err_code_des'], ErrorCode::$weixinPayError);
|
|
|
- }
|
|
|
-
|
|
|
- if($response_content['return_code'] == 'SUCCESS' && $response_content['result_code'] == 'SUCCESS' && $response_content['trade_state'] == 'SUCCESS'){
|
|
|
- return ResultWrapper::success($response_content['trade_state']);
|
|
|
- }
|
|
|
-
|
|
|
- sleep(2);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- for($i=1; $i<=10; $i++){
|
|
|
- $url = $this->baseUrl.'secapi/pay/reverse';
|
|
|
- $params = [
|
|
|
- 'appid' => $this->appid,
|
|
|
- 'mch_id' => $this->mch_id,
|
|
|
- 'nonce_str' => md5(md5(time().'qianniao.vip')),
|
|
|
- 'out_trade_no' => $orderNo,
|
|
|
- ];
|
|
|
-
|
|
|
- $params['sign'] = self::getSign($params);
|
|
|
- $post_xml = $this->arrayToWeiXinXml($params);
|
|
|
- $curl_content = request($url, $post_xml, 10, false, [], true);
|
|
|
-
|
|
|
- if($curl_content['httpcode'] != '200'){
|
|
|
- return ResultWrapper::fail($curl_content['errorMsg'], ErrorCode::$apiNotResult);
|
|
|
- }
|
|
|
- $response_content = (array)simplexml_load_string($curl_content['content'], 'SimpleXMLElement', LIBXML_NOCDATA);
|
|
|
- if($response_content['return_code'] != 'SUCCESS'){
|
|
|
- return ResultWrapper::fail($response_content['return_msg'], ErrorCode::$weixinPayError);
|
|
|
- }
|
|
|
-
|
|
|
- if($response_content['result_code'] != 'SUCCESS' && $response_content['recall'] == 'N'){
|
|
|
- return ResultWrapper::fail($response_content['err_code_des'], ErrorCode::$weixinPayError);
|
|
|
- }
|
|
|
-
|
|
|
- if($response_content['return_code'] == 'SUCCESS' && $response_content['result_code'] == 'SUCCESS' && $response_content['recall'] == 'N'){
|
|
|
- return ResultWrapper::success($response_content['result_code']);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * H5查询支付状态接口
|
|
|
- */
|
|
|
- public function orderquery($orderNo)
|
|
|
- {
|
|
|
- $url = $this->apiUrl.'orderquery';
|
|
|
- $params = [
|
|
|
- 'appid' => $this->appid,
|
|
|
- 'mch_id' => $this->mch_id,
|
|
|
- 'nonce_str' => md5(md5(time().'qianniao.vip')),
|
|
|
- 'out_trade_no' => $orderNo,
|
|
|
- ];
|
|
|
-
|
|
|
- $params['sign'] = self::getSign($params);
|
|
|
- $post_xml = $this->arrayToWeiXinXml($params);
|
|
|
- $curl_content = request($url, $post_xml);
|
|
|
-
|
|
|
- $result = $this->commonResult($curl_content);
|
|
|
- if(!$result->isSuccess()){
|
|
|
- return ResultWrapper::fail($result->getData(), $result->getErrorCode());
|
|
|
- }
|
|
|
- $response_content = $result->getData();
|
|
|
-
|
|
|
- $trade_state = $response_content['trade_state'];
|
|
|
-
|
|
|
- return ResultWrapper::success($trade_state);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * 申请退款API
|
|
|
- * 官方文档地址:https:
|
|
|
- */
|
|
|
- public function transfers($outerTradeNo, $out_refund_no, $refundMoney, $orderMoney, $sslData)
|
|
|
- {
|
|
|
- $url = $this->baseUrl.'secapi/pay/refund';
|
|
|
- $params = [
|
|
|
- 'appid' => $this->appid,
|
|
|
- 'mch_id' => $this->mch_id,
|
|
|
- 'nonce_str' => md5(md5(time().'qianniao.vip')),
|
|
|
- 'transaction_id' => $outerTradeNo,
|
|
|
- 'out_refund_no' => $out_refund_no,
|
|
|
- 'refund_fee' => yuanToFen($refundMoney),
|
|
|
- 'total_fee' => yuanToFen($orderMoney),
|
|
|
- ];
|
|
|
-
|
|
|
- $params['sign'] = self::getSign($params);
|
|
|
- $post_xml = $this->arrayToWeiXinXml($params);
|
|
|
- $curl_content = request($url, $post_xml, 10, false, [], true, $sslData);
|
|
|
-
|
|
|
- $result = $this->commonResult($curl_content);
|
|
|
- if(!$result->isSuccess()){
|
|
|
- return ResultWrapper::fail($result->getData(), $result->getErrorCode());
|
|
|
- }
|
|
|
- $response_content = $result->getData();
|
|
|
-
|
|
|
- return ResultWrapper::success($response_content['refund_id']);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * 公共处理返回结果方法
|
|
|
- */
|
|
|
- public function commonResult($curl_content)
|
|
|
- {
|
|
|
- if($curl_content['httpcode'] == '200'){
|
|
|
- $response_content = (array)simplexml_load_string($curl_content['content'], 'SimpleXMLElement', LIBXML_NOCDATA);
|
|
|
- if($response_content['return_code'] == 'SUCCESS'){
|
|
|
- if($response_content['result_code'] == 'SUCCESS'){
|
|
|
- return ResultWrapper::success($response_content);
|
|
|
- }else{
|
|
|
- return ResultWrapper::fail($response_content['err_code_des'], ErrorCode::$weixinPayError);
|
|
|
- }
|
|
|
- }else{
|
|
|
- return ResultWrapper::fail($response_content['return_msg'], ErrorCode::$weixinPayError);
|
|
|
- }
|
|
|
- }else{
|
|
|
- return ResultWrapper::fail($curl_content['errorMsg'], ErrorCode::$apiNotResult);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * 生成签名方法
|
|
|
- * 官方接口地址: https:
|
|
|
- * 官方签名测试地址: https:
|
|
|
- * @param $parm
|
|
|
- * @return string
|
|
|
- */
|
|
|
- public function getSign($parm)
|
|
|
- {
|
|
|
-
|
|
|
- if(ksort($parm)){
|
|
|
- $stringA = '';
|
|
|
-
|
|
|
- foreach($parm as $key => $value){
|
|
|
- if($value == 0 || !empty($value)){
|
|
|
- $stringA .=$key.'='.$value.'&';
|
|
|
- }
|
|
|
- }
|
|
|
- }else{
|
|
|
- echo "对参数排序出错";
|
|
|
- exit();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- $stringSignTemp = $stringA.'key='.$this->config["ApiV2Key"];
|
|
|
-
|
|
|
-
|
|
|
- $signValue = strtoupper(md5($stringSignTemp));
|
|
|
- return $signValue;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- public function arrayToWeiXinXml($arr)
|
|
|
- {
|
|
|
- $xml = '<xml>';
|
|
|
- foreach($arr as $key => $value){
|
|
|
- if (is_string($value)) {
|
|
|
- $xml .= '<' . $key . '><![CDATA[' . $value . ']]></' . $key . '>';
|
|
|
- } else {
|
|
|
- $xml .= '<' . $key . '>' . $value . '</' . $key . '>';
|
|
|
- }
|
|
|
- }
|
|
|
- $xml .='</xml>';
|
|
|
- return $xml;
|
|
|
- }
|
|
|
-
|
|
|
-}
|