Thinkphp6接入微信支付V3版电商收付通简单示例

开发框架:thinkphp6

Api封装类:extend/library/WxPay.php

appId = isset($config['appId']) ? $config['appId'] : '';$this->appSecret = isset($config['appSecret']) ? $config['appSecret'] : '';$this->mchId = isset($config['mchId']) ? $config['mchId'] : '';$this->mchKey = isset($config['mchKey']) ? $config['mchKey'] : '';$this->path = str_replace('\\', '/', ROOT_PATH);$this->sslCert = $this->path . (isset($config['sslCert']) ? $config['sslCert'] : $this->sslCert);$this->sslKey = $this->path . (isset($config['sslKey']) ? $config['sslKey'] : $this->sslKey);$this->platCert = $this->path . (isset($config['platCert']) ? $config['platCert'] : $this->platCert);$folder = dirname($this->platCert);if (!is_dir($folder)) {mkdir($folder, 0755, true);}$this->serialNo = isset($config['serialNo']) ? $config['serialNo'] : '';$this->platKey = isset($config['platKey']) ? $config['platKey'] : '';$this->getPrivateKey();$this->getCertificates();}/*** 预支付*/public function prepay(array $data){$data['appid'] = $this->appId;$data['mchid'] = $this->mchId;$data = json_encode($data, JSON_UNESCAPED_UNICODE);$this->method = 'POST';$this->panel = '/v3/pay/transactions/jsapi';$this->body = $data;$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->post($url, $data), true);return $result;}/*** JSAPI支付*/public function invoke($preid){$this->body = 'prepay_id=' . $preid;$this->buildSignature();$data = array('timeStamp' => $this->stamp,'nonceStr' => $this->nonce,'package' => $this->body,'signType' => 'RSA','paySign' => $this->signature,);return $data;}/*** 原生支付*/public function native(array $data){$data['sp_appid'] = $this->appId;$data['sp_mchid'] = $this->mchId;$data = json_encode($data, JSON_UNESCAPED_UNICODE);$this->method = 'POST';$this->panel = '/v3/pay/partner/transactions/native';$this->body = $data;$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->post($url, $data), true);return $result;}/*** 合单*/public function combine(array $data){$data = json_encode($data, JSON_UNESCAPED_UNICODE);$this->method = 'POST';$this->panel = '/v3/combine-transactions/native';$this->body = $data;$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->post($url, $data), true);return $result;}/*** 退款*/public function refund(array $data){$data = json_encode($data, JSON_UNESCAPED_UNICODE);$this->method = 'POST';$this->panel = '/v3/refund/domestic/refunds';$this->body = $data;$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->post($url, $data), true);return $result;}/*** 余额查询*/public function balance($sub_mchid){$this->method = 'GET';$this->panel = '/v3/ecommerce/fund/balance/' . $sub_mchid;$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->get($url), true);return $result;}/*** 交易账单下载*/public function bill($sub_mchid, $date = ''){if (!$date) {$date = date('Y-m-d', strtotime('-1 day'));}$this->method = 'GET';$this->panel = '/v3/bill/tradebill?bill_date=' . $date . '&sub_mchid=' . $sub_mchid . '&bill_type=ALL';$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->get($url), true);if (isset($result['download_url'])) {$this->panel = str_replace($this->rootUrl, '', $result['download_url']);$this->buildHeader();$result = $this->get($result['download_url']);}return $result;}/*** 上传图片*/public function upload($file){if (!$file && is_file($file)) {return false;}if (!in_array(pathinfo($file, PATHINFO_EXTENSION), array('jpg', 'png', 'bmp'))) {return false;}$file = str_replace('\\', '/', $file);$info = new \finfo(FILEINFO_MIME_TYPE);$mime = $info->file($file);$name = basename($file);$stream = file_get_contents($file);$meta = json_encode(array('filename' => $name,'sha256' => hash_file('sha256', $file),));$boundary = uniqid();$this->method = 'POST';$this->panel = '/v3/merchant/media/upload';$this->body = $meta;$this->httpHeader = array('Accept: application/json','User-Agent: ' . $_SERVER['HTTP_USER_AGENT'],'Authorization: ' . $this->buildAuthorization(),'Content-Type: multipart/form-data;boundary=' . $boundary,);$url = $this->rootUrl . $this->panel;$sep = '--' . $boundary . "\r\n";$out = $sep;$out .= 'Content-Disposition: form-data; name="meta";' . "\r\n";$out .= 'Content-Type: application/json' . "\r\n";$out .= "\r\n";$out .= $meta . "\r\n";$out .= $sep;$out .= 'Content-Disposition: form-data; name="file"; filename="' . $name . '";' . "\r\n";$out .= 'Content-Type: ' . $mime . "\r\n";$out .= "\r\n";$out .= $stream . "\r\n";$out .= '--' . $boundary . '--' . "\r\n";$result = json_decode($this->post($url, $out), true);return $result;}/*** 二级商户进件*/public function applyment(array $data){if (!isset($data['id_card_info']['id_card_name'])) {return false;}if (!isset($data['id_card_info']['id_card_number'])) {return false;}if (!isset($data['account_info']['account_name'])) {return false;}if (!isset($data['account_info']['account_number'])) {return false;}if (!isset($data['contact_info']['contact_name'])) {return false;}if (!isset($data['contact_info']['contact_id_card_number'])) {return false;}if (!isset($data['contact_info']['mobile_phone'])) {return false;}if (!isset($data['contact_info']['contact_email'])) {return false;}$data['appid'] = $this->appId;$data['id_card_info']['id_card_name'] = $this->encrypt($data['id_card_info']['id_card_name']);$data['id_card_info']['id_card_number'] = $this->encrypt($data['id_card_info']['id_card_number']);$data['account_info']['account_name'] = $this->encrypt($data['account_info']['account_name']);$data['account_info']['account_number'] = $this->encrypt($data['account_info']['account_number']);$data['contact_info']['contact_name'] = $this->encrypt($data['contact_info']['contact_name']);$data['contact_info']['contact_id_card_number'] = $this->encrypt($data['contact_info']['contact_id_card_number']);$data['contact_info']['mobile_phone'] = $this->encrypt($data['contact_info']['mobile_phone']);$data['contact_info']['contact_email'] = $this->encrypt($data['contact_info']['contact_email']);$data = json_encode($data, JSON_UNESCAPED_UNICODE);$this->method = 'POST';$this->panel = '/v3/ecommerce/applyments/';$this->body = $data;$this->buildHeader(true);$url = $this->rootUrl . $this->panel;$result = json_decode($this->post($url, $data), true);return $result;}/*** 二级商户审核状态查询*/public function auditState($no, $type = 0){if (!$no) {return false;}$this->method = 'GET';$this->panel = '/v3/ecommerce/applyments/' . ($type ? 'out-request-no/' : '') . $no;$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->get($url), true);return $result;}/*** 添加分账接收方*/public function addReceivers(array $data){if (!isset($data['name'])) {return false;}$data['appid'] = $this->appId;$data = json_encode($data, JSON_UNESCAPED_UNICODE);$this->method = 'POST';$this->panel = '/v3/ecommerce/profitsharing/receivers/add';$this->body = $data;$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->post($url, $data), true);return $result;}/*** 分账*/public function divide(array $data){if (!$data && is_array($data)) {return false;}$data['appid'] = $this->appId;$data = json_encode($data, JSON_UNESCAPED_UNICODE);$this->method = 'POST';$this->panel = '/v3/ecommerce/profitsharing/orders';$this->body = $data;$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->post($url, $data), true);return $result;}/*** 敏感字段加密*/public function encrypt($str){$encrypted = '';if (openssl_public_encrypt($str, $encrypted, $this->platPublicKey, OPENSSL_PKCS1_OAEP_PADDING)) {$sign = base64_encode($encrypted);} else {throw new Exception('encrypt failed');}return $sign;}/*** 报文解密*/public function decrypt($text, $assoc, $nonce){$check = extension_loaded('sodium');if (false === $check) {return false;}$check = sodium_crypto_aead_aes256gcm_is_available();if (false === $check) {return false;}return sodium_crypto_aead_aes256gcm_decrypt(base64_decode($text), $assoc, $nonce, $this->platKey);}/*** 生成Header*/private function buildHeader($usePlatSerial = false){$this->httpHeader = array('Accept: application/json','User-Agent: ' . $_SERVER['HTTP_USER_AGENT'],'Content-Type: application/json',);if ($usePlatSerial) {$this->httpHeader[] = 'Wechatpay-Serial: ' . $this->platSerialNo;}$this->httpHeader[] = 'Authorization: ' . $this->buildAuthorization();if ($this->body) {$this->httpHeader[] = 'Content-Length: ' . strlen($this->body);}}/*** 生成Authorization*/private function buildAuthorization(){$this->signer();$str = 'mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"';$str = sprintf($str, $this->mchId, $this->nonce, $this->stamp, $this->serialNo, $this->signature);return $this->schema . ' ' . $str;}/*** 签名生成器*/private function signer(){$this->stamp = time();$this->nonce = $this->buildNonceStr();$message = $this->method . "\n" . $this->panel . "\n" . $this->stamp . "\n" . $this->nonce . "\n" . $this->body . "\n";openssl_sign($message, $signature, $this->privateKey, $this->signAlg);$this->signature = base64_encode($signature);}/*** 生成JSSDK签名*/private function buildSignature(){$this->stamp = time();$this->nonce = $this->buildNonceStr();$message = $this->appId . "\n" . $this->stamp . "\n" . $this->nonce . "\n" . $this->body . "\n";openssl_sign($message, $signature, $this->privateKey, $this->signAlg);$this->signature = base64_encode($signature);}/*** 获取商户私钥*/private function getPrivateKey(){if (is_file($this->sslKey)) {$this->privateKey = openssl_pkey_get_private(file_get_contents($this->sslKey));}}/*** 获取平台证书*/private function getCertificates(){if (is_file($this->platCert)) {$json = file_get_contents($this->platCert);$data = json_decode($json, true);if (isset($data['serial_no'])) {$this->platSerialNo = $data['serial_no'];}if (isset($data['cipher'])) {$this->platPublicKey = $data['cipher'];}}if (!($this->platSerialNo && $this->platPublicKey)) {$this->method = 'GET';$this->panel = '/v3/certificates';$this->buildHeader();$url = $this->rootUrl . $this->panel;$result = json_decode($this->get($url), true);if ($result && isset($result['data']) && $result['data']) {$data = $result['data'][0];$serial_no = $data['serial_no'];$cert = $data['encrypt_certificate'];$cipher = $this->decrypt($cert['ciphertext'], $cert['associated_data'], $cert['nonce']);$this->platSerialNo = $serial_no;$this->platPublicKey = $cipher;$json = json_encode(array('serial_no' => $serial_no,'cipher' => $cipher,));file_put_contents($this->platCert, $json);}}}/** 生成随机字符串*/private function buildNonceStr($len = 32){$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';$str = '';for ($i = 0; $i < $len; $i++) {$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);}return $str;}/** get请求*/private function get($url){$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_HEADER, 0);curl_setopt($ch, CURLOPT_HTTPHEADER, $this->httpHeader);$out = curl_exec($ch);curl_close($ch);return $out;}/** post请求*/private function post($url, $data = ''){$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);curl_setopt($ch, CURLOPT_AUTOREFERER, 1);curl_setopt($ch, CURLOPT_HTTPHEADER, $this->httpHeader);curl_setopt($ch, CURLOPT_POSTFIELDS, $data);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$result = curl_exec($ch);curl_close($ch);return $result;}/*** 获取客户端ip*/public function getClientIp(){if (getenv('HTTP_CLIENT_IP')) {$ip = getenv('HTTP_CLIENT_IP');} elseif (getenv('HTTP_X_FORWARDED_FOR')) {$ip = getenv('HTTP_X_FORWARDED_FOR');} elseif (getenv('HTTP_X_FORWARDED')) {$ip = getenv('HTTP_X_FORWARDED');} elseif (getenv('HTTP_FORWARDED_FOR')) {$ip = getenv('HTTP_FORWARDED_FOR');} elseif (getenv('HTTP_FORWARDED')) {$ip = getenv('HTTP_FORWARDED');} else {$ip = $_SERVER['REMOTE_ADDR'];}return $ip;}
}

交易流程:

Step1:上传二级商户营业执照、身份证正反面照片(upload)

Step2:二级商户进件(applyment)

Step3:查询二级商户进件状态,审核通过后邀请二级商户签约(auditState)

Step4:添加分账接收方(addReceivers)

Step5:用户下单付款,指定分账信息(native、combine)

Step6:交易成功发起分账(divide)

使用示例:Sample.php

wxpay = new WxPay(array('appId' => '','appSecret' => '','mchId' => '','mchKey' => '','serialNo' => '','platKey' => '',));}/*** 上传图片示例*/public function uploadImage(){$file = ROOT_PATH . 'sample.png';$result = $this->wxpay->upload($file);var_dump($result);}/*** 二级商户进件示例*/public function applyment(){$data = array('out_request_no' => '<内部编号>','organization_type' => '<主体类型>','business_license_info' => array('business_license_copy' => '<上传营业执照得到的MediaID>','business_license_number' => '<营业执照号>','merchant_name' => '<商户名称>','legal_person' => '<法人姓名>',),'id_doc_type' => 'IDENTIFICATION_TYPE_MAINLAND_IDCARD','id_card_info' => array('id_card_copy' => '<上传身份证正面得到的MediaID>','id_card_national' => '<上传身份证背面得到的MediaID>','id_card_name' => '<身份证登记姓名>','id_card_number' => '<身份证号>','id_card_valid_time' => '<身份证有效期>',),'need_account_info' => true,'account_info' => array('bank_account_type' => '<银行账号类型>','account_bank' => '<开户行>','account_name' => '<银行账号开户名>','bank_address_code' => '<开户行地区编号>','bank_name' => '<银行全称>','account_number' => '<银行账号>',),'contact_info' => array('contact_type' => '64[|65]','contact_name' => '<超级管理员姓名>','contact_id_card_number' => '<超级管理员身份证号>','mobile_phone' => '<超级管理员手机号>','contact_email' => '<超级管理员电子信箱>',),'sales_scene_info' => array('store_name' => '<经营网店名称>','store_url' => '<经营网店URL地址>',),'merchant_shortname' => '<商户简称>',);$result = $this->wxpay->applyment($data);var_dump($result);}/*** 二级商户审核状态查询示例*/public function state(){$request_no = '202101010000';$result = $this->wxpay->auditState($request_no);var_dump($result);}/*** 添加分账方示例*/public function addReceivers(){$data = array('type' => 'MERCHANT_ID','account' => '<二级商户号>','name' => '<二级商户全称>','relation_type' => 'SUPPLIER',);$result = $wxpay->addReceivers($data);var_dump($result);}/*** 原生支付示例*/public function native(){$data = array('sub_mchid' => '<二级商户的商户号>','description' => '<商品描述>','out_trade_no' => '<内部订单号>','notify_url' => '<通知URL>','settle_info' => array('profit_sharing' => true,),'amount' => array('total' => '<订单总金额>','currency' => 'CNY',),'attach' => '<可选,附加数据>',);$result = $wxpay->native($data);var_dump($result);}/*** 合单支付示例*/public function combine(){$data = array('combine_appid' => '<合单发起方的appid>','combine_mchid' => '<合单发起方的商户号>','combine_out_trade_no' => '<合单支付总订单号>','scene_info' => array('payer_client_ip' => $this->wxpay->getClientIp(),),'sub_orders' => array(array('mchid' => '<子单发起方的商户号>','attach' => '<附加数据>','amount' => array('total_amount' => 1,'currency' => 'CNY',),'out_trade_no' => '<子单商户订单号>','sub_mchid' => '<二级商户号>','description' => '<商品描述>','settle_info' => array('profit_sharing' => true,),),),'notify_url' => 'https://www.xxx.com/notify.php',);$result = $wxpay->combine($data);var_dump($result);}/*** 退款示例*/public function refund(){$data = array('sub_mchid' => '<二级商户号>','transaction_id' => '<微信支付订单号>','out_trade_no' => '<内部订单号>','out_refund_no' => '<内部退款单号>','amount' => array('refund' => '<交易总金额>','total' => '<退款金额>','currency' => 'CNY',),);$result = $wxpay->refund($data);var_dump($result);}/*** 分账示例*/public function divide(){$data = array('sub_mchid' => '<二级商户号>','transaction_id' => '<微信支付订单号>','out_order_no' => '<内部订单号>','receivers' => array(array('type' => '<分账接收方类型>','account' => '<分账接收方账号>','amount' => '<分账金额>','description' => '<分账描述>',),),'finish' => true,);$result = $wxpay->divide($data);var_dump($result);}/*** 余额查询*/public function balance(){$result = $wxpay->balance('<二级商户号>');var_dump($result);}/*** 下载账单*/public function bill(){$date = date('Y-m-d');$result = $wxpay->bill('<二级商户号>', $date);var_dump($result);}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部