ThinkPay의 최신 WeChat 결제 공식 계정 결제 드라이버 공유
모두의 편의를 위해 ThinkPay의 WeChat 결제 드라이버를 공유해 보겠습니다. 궁금한 점이 있으면 QQ 그룹 토론 105108204<?php<br />에 참여하세요.
// +--------------------- --- ----------<br />
// | 제로 클라우드 [간단하고 효율적이며 우수함]<br />
// +--------------------- --- ----------<br />
// | Copyright (c) 2016 http://www.lingyun.net All Rights Reserved.<br />
// +--------------------- --- ----------<br />
// | 작성자: jry <598821125@qq.com><br>
// +--------------------- --- ----------<br>
네임스페이스 AddonsPayThinkPayPayDriver;<br>
<br>
/**<br>
* 위챗 결제 드라이버<br>
*/<br>
클래스 Wxpay는 AddonsPayThinkPayPayPay를 확장합니다<br>
{<br>
protected $gateway = 'https://api.mch.weixin.qq.com/pay/unifiedorder';<br>
보호된 $orderquery = 'https://api.mch.weixin.qq.com/pay/orderquery';<br>
보호된 $config = 배열(<br>
>
'appsecret' => '',<br>
'mchid' => '',<br>
'열쇠'
);<br>
<br>
공개함수 확인()<br>
{<br>
if (!$this->config['appid'] || !$this->config['appsecret'] || !$this->config['mchid'] || !$this-> config['키']) {<br>
E("위챗 결제 설정이 잘못되었습니다!");<br>
}<br>
true를 반환합니다.<br>
}<br>
<br>
공개 함수 buildRequestForm($pay_data)<br>
{<br>
// 앱 결제<br>
If (C('IS_API')) {<br>
$param = 배열(<br>
> > > 한 번도 없었습니다.”
'Mch_id' = & gt; $ this- & gt; config ['mchid'], <br>
~ ~ 왜냐면
~ 왜냐하면
'OUT_TRADE_NO' = & GT; $ Pay_data ['OUT_TRADE_NO'], <br>
~
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],<br>
'Notify_url' = & gt; $ this-& gt; config ['notify_url'], <br>
'trade_type' ~ );<br>
<br>
// 서명
$param['sign'] = $this->MakeSign($param);<br>
~
$result = $this->FromXml($this->postXmlCurl($xml_param, $this->gateway));<br>
If ($result['return_code'] === '성공') {<br>
If ($this->CheckSign($result)) {<br>
// 주문 인터페이스를 통일하여 일반 prepay_id를 반환한 다음 서명 사양에 따라 서명을 다시 생성하고 데이터를 앱으로 전송합니다. <br>
// 참여하는 서명 필드는 Appid, Partnerid, Prepayid, Noncestr, Timestamp, Package입니다. 참고: 패키지의 값 형식은 Sign=WXPay<br>입니다.
$prepayparams = 배열();<br>
~
$prepayparams['partnerid'] = $result['mch_id'];<br>
$prepayparams['prepayid'] = $result['prepay_id'];<br>
$prepayparams['noncestr'] = $result['nonce_str'];<br>
~
$prepayparams['timestamp'] = time();<br>
~ ~
$ Return ['json'] = json_encode ($ prepayparams) <br>
$return 반환;<br>
}<br>
}<br>
} else {<br>
// 사용자 openId 획득, WeChat 공개 계정 JSAPI 결제는 <br>이어야 합니다.
$openId = $this->GetOpenid();<br>
$param = 배열(<br>
'Appid' = & gt; $ this-& gt; config ['appid'], <br>
'Mch_id' = & gt; $ this- & gt; config ['mchid'], <br> 'nonce_str' => $this->getNonceStr(),<br>
'본문' => $pay_data['몸'],<br>
'out_trade_no' => $pay_data['out_trade_no'],<br>
'total_fee' => $pay_data['money'] * 100,<br>
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],<br>
'notify_url' => $this->config['notify_url'],<br>
'무역 유형' => 'JSAPI',<br>
'openid' => $openId,<br>
);<br>
<br>
// 설명<br>
$param['sign'] = $this->MakeSign($param);<br>
$xml_param = $this->ToXml($param);<br>
$result = $this->FromXml($this->postXmlCurl($xml_param, $this->gateway));<br>
if ($result['return_code'] === '성공') {<br>
if ($this->CheckSign($result)) {<br>
// 获取JSAPI所需参数<br>
$jsApiParameters = $this->GetJsApiParameters($result);<br>
$pay_page = <<<EOF<br />
<html><br>
<br>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/><br>
<meta name="viewport" content="width=device-width, initial-scale=1"/><br>
<title>微信支付</title>
<br>
<script type="text/javascript"><br>//WeChat JS API 결제 호출<br>
함수 jsApiCall()<br>
~
WeixinJSBridge.invoke(<br>
'getBrandWCPayRequest',<br>
~
함수(res){<br>
WeixinJSBridge.log(res.err_msg);<br>
>
} <br>
~ ~ }
<br>
함수 callpay()<br>
~
If (WeixinJSBridge 유형 == "정의되지 않음"){<br>
If(document.addEventListener){<br>
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);<br>
} Else if (document.attachevent) {<br>
document.attachEvent('WeixinJSBridgeReady', jsApiCall);<br>
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);<br>
}<br>
}else{<br>
jsApiCall();<br>
}<br>
}<br>
</script><br>
</head><br>
<body><br>
<br/><br>
<font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">{$pay_data['money']}</span>元</b></font><br/><br/><br>
<div align="center"><br>
<button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()" >立即支付</button><br>
</div><br>
~
~
EOF;<br>
$ pay_page 반환 <br>
}<br>
그 외 {<br>
E("위챗 주문 오류!" . $result['return_msg']);<br>
}<br>
}<br>
}<br>
<br>
/**<br>
* * 비동기 알림 확인<br>
*/<br>
공개 함수 verifyNotify($notify)<br>
{<br>
//알림 데이터 가져오기<br>
If ($notify['return_code'] === '성공') {<br>
If (!array_key_exists("transaction_id", $notify)) {<br>
E("입력 매개변수가 올바르지 않습니다!");<br>
}<br>
$param['transaction_id'] = $notify["transaction_id"];<br>
~ ~ 를 통해
~ ~ 를 통해
> ~
$param['sign'] = $this->MakeSign($param);<br>
>
$result = $this->FromXml($this->postXmlCurl($xml_param, $this->orderquery));<br>
If ($this->CheckSign($result)) {<br>
$result['status'] = ($result['result_code'] == 'SUCCESS') ? true : false;<br>
$result['money'] = $result['total_fee'] / 100;<br>
~ ~
true를 반환합니다.<br>
}<br>
} else {<br>
E('오류 알림');<br>
}<br>
}<br>
<br>
/**<br>
*<br>
* jsapi 결제 매개변수 가져오기<br>
* @param array $UnifiedOrderResult 통합 결제 인터페이스에서 반환된 데이터<br>
* @WxPayException 발생<br>*<br>
* @return json 데이터, js 함수에 매개변수로 직접 입력할 수 있음 <br>
*/<br>
공용 함수 GetJsApiParameters($UnifiedOrderResult)<br>
{<br>
If (!array_key_exists("appid", $UnifiedOrderResult)<br>
>
|| $UnifiedOrderResult['prepay_id'] == "") {<br>
E("매개변수 오류");<br>
}<br>
$jsapi['appId']
$jsapi['timeStamp'] = (문자열) 시간();<br>
$jsapi['nonceStr'] = $this->getNonceStr();<br>
>
$jsapi['package'] = "prepay_id=" . $UnifiedOrderResult['prepay_id'];<br>
$jsapi['signType'] = 'MD5';<br>
>
$parameters = json_encode($jsapi);<br>
$매개변수를 반환합니다.<br>
}<br>
<br>
/**<br>
* 포스트 모드에서 해당 인터페이스 URL에 xml을 제출하세요<br>
*<br>
* @param string $xml 게시에 필요한 XML 데이터<br>
* @param 문자열 $url url<br>
* @param bool $useCert 인증서 필수 여부, 기본적으로 필수 아님<br>
* @param int $second URL 실행 시간 초과, 기본값은 30초<br>
* @WxPayException 발생<br>
*/<br>
비공개 정적 함수 postXmlCurl($xml, $url, $useCert = false, $second = 30)<br>
{<br>
$ch = 컬_init();<br>
//시간 초과 설정<br>
cur_setopt($ch, CURLOPT_TIMEOUT, $second);<br>
<br>
//프록시가 구성되어 있으면 여기서 프록시를 설정하세요<br>
// if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"<br>
~ ~
cur_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);<br>
curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);<br>
|
컬_setopt($ch, CURLOPT_URL, $url);<br>
컬_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);<br>
cur_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2) //엄격한 검증<br>
//헤더 설정<br>
cur_setopt($ch, CURLOPT_HEADER, false);<br>
//결과를 문자열로 요구하고 화면에 출력합니다<br>컬_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br>
<br>
If ($useCert == true) {<br>
> 인증서를 설정하려면 <br>
//인증서 사용: 인증서와 키는 각각 두 개의 .pem 파일에 속합니다 <br>
cur_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');<br>
cur_setopt($ch, CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH);<br>
cur_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');<br>
cur_setopt($ch, CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH);<br>
}<br>
//포스트 제출 방법<br>
cur_setopt($ch, CURLOPT_POST, true);<br>
컬_setopt($ch, CURLOPT_POSTFIELDS, $xml);<br>
//컬 실행<br>
$data = 컬_exec($ch);<br>
//결과 반환<br>
if ($data) {<br>
컬_닫기($ch);<br>
$data 반환;<br>
} else {<br>
$error = 컬_errno($ch);<br>
컬_닫기($ch);<br>
E("컬 오류, 오류 코드: $error");<br>
}<br>
}<br>
<br>
/*<br>
* 32자 이하의 임의 문자열을 생성합니다. <br>
* @param int $length<br>
* * @return 무작위 문자열 생성 <br>
*/<br>
공용 정적 함수 getNonceStr($length = 32)<br>
{<br>
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";<br>
~
for ($i = 0; $i < $length; $i++) {<br />
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);<br />
}<br />
$str 반환<br />
}<br />
<br />
/**<br />
* 서명 생성<br />
* @return Signature, 이 함수는 sign 멤버 변수를 포함하지 않습니다. 서명을 설정하려면 SetSign 메서드를 호출하여 값을 할당해야 합니다. <br />
*/<br />
공용 함수 MakeSign($param)<br />
{<br />
//서명 1단계: 사전순으로 매개변수 정렬<br />
ksort($param);<br />
$string = $this->ToUrlParams($param);<br>
//서명 2단계: 문자열 뒤에 KEY<br> 추가
$string = $string . "&key=" . $this->config['key'];<br>
//서명 3단계: MD5 암호화<br>
$string = md5($string);<br>
//서명 4단계: 모든 문자를 대문자로 변환<br>
$result = strtoupper($string);<br>
$result 반환<br>
}<br>
<br>
/**<br>
*<br> * 检测签명<br>
*/<br>
공개 함수 CheckSign($param)<br>
{<br>
$sign = $this->MakeSign($param);<br>
if ($param['sign'] == $sign) {<br>
true를 반환합니다.<br>
} 그밖에 {<br>
E("签name错误!");<br>
}<br>
}<br>
<br>
/**<br>
*<br>
* * 서명문자열 접합<br>
* @param 배열 $urlObj<br>
*<br>
* @return 연결된 문자열을 반환합니다 <br>
*/<br>
공개 함수 ToUrlParams($param)<br>
{<br>
$buff = "";<br>
foreach($param은 $k =>$v) {<br>
if ($k != "sign" && $v != "" && !is_array($v)) {<br>
$버프 .= $k . "=" . $v . "&";<br>
}<br>
}<br>
<br>
$buff = trim($buff, "&");<br>
$buff 반환;<br>
}<br>
<br>
/**<br>
* XML 문자 출력 <br>
* @WxPayException 발생<br>
**/<br>
공개 함수 ToXml($param)<br>
{<br>
if (!is_array($param)<br>
|| 개수($param) <= 0) {<br />
E("数组数据异常!");<br />
}<br />
<br />
$xml = "<xml>";<br>
foreach($param은 $key로 =>$val) {<br>
if (is_numeric($val)) {<br>
$xml .= "<" . $키 . ">" . $발 . "</" . $키 . ">";<br>
} 그밖에 {<br>
$xml .= "<" . $키 . "><![CDATA[" . $발 . "]]></" . $키 . ">";<br>
}<br>
}<br>
$xml .= "</xml>";<br>
$xml 반환<br>
}<br>
<br>
/**<br>
* XML을 배열로 변환<br>
* @param 문자열 $xml<br>
* @WxPayException 발생<br>
*/<br>
공개 함수 FromXml($xml)<br>
{<br>
if (!$xml) {<br>
E("xml数据异常!");<br>
}<br> //XML을 배열로 변환<br>
//외부 XML 엔터티 참조는 금지됩니다<br>
libxml_disable_entity_loader(true);<br>
$this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);<br>
$this->값 반환<br>
}<br>
<br>
/**<br>
*<br>
* 점프를 통해 사용자의 openid를 가져옵니다. <br>
* 1. 콜백에 필요한 URL 및 기타 매개변수를 설정하고 WeChat 서버 https://open.weixin.qq.com/connect/oauth2/authorize<br>로 이동합니다.
* 2. WeChat 서비스 처리가 완료되면 사용자 리디렉션_uri 주소로 다시 이동합니다. 이때 다음과 같은 일부 매개변수가 가져옵니다.<br>
*<br>
* @return 사용자의 openid<br>
*/<br>
공개 함수 GetOpenid()<br>
{<br>
//코드를 통해 openid 얻기<br>
If (!isset($_GET['code'])) {<br>
//WeChat 반환 코드 실행<br>
$baseUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);<br>
>
Header("위치: $url");<br>
종료();<br>
} else {<br>
// Openid를 얻기 위한 코드를 얻습니다 <br>
$code = $_GET['코드'];<br>
$openid = $this->getOpenidFromMp($code);<br>
$openid 반환;<br>
}<br>
}<br>
<br>
/**<br>
*<br>
* 코드를 통해 작업 플랫폼에서 openid 머신 access_token을 가져옵니다<br>
* @param string $code 위챗에서 가져온 코드<br>
*<br>
* @return openid<br>
*/<br>
공개 함수 GetOpenidFromMp($code)<br>
{<br>
$url = $this->__CreateOauthUrlForOpenid($code);<br>
//컬 초기화<br>
$ch = 컬_init();<br>
//시간 초과 설정<br>
컬_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);<br>
컬_setopt($ch, CURLOPT_URL, $url);<br>
cur_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);<br>
cur_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);<br>
cur_setopt($ch, CURLOPT_HEADER, false);<br>
컬_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br>
// if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"<br>
~ ~
cur_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);<br> // curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);<br>
// }<br>
//运行curl,结果以jason형式返回<br>
$res = curl_exec($ch);<br>
컬_닫기($ch);<br>
//출출openid<br>
$data = json_decode($res, true);<br>
$this->data = $data;<br>
$openid = $data['openid'];<br>
$openid 반환;<br>
}<br>
<br>
/**<br>
*<br>
* 코드를 얻으려면 URL 연결을 구성하세요<br>
* @param string $redirectUrl WeChat 서버가 반송하는 URL, URL 인코딩이 필요합니다 <br>
*<br>
* @return 생성된 URL을 반환합니다<br>
*/<br>
비공개 함수 __CreateOauthUrlForCode($redirectUrl)<br>
{<br>
$urlObj["appid"] = $this->config['appid'];<br>
$urlObj["redirect_uri"] = "$redirectUrl";<br>
$urlObj["response_type"] = "코드";<br>
$urlObj["scope"] = "snsapi_base";<br>
$urlObj["state"] = "#wechat_redirect";<br>
$bizString = $this->ToUrlParams($urlObj);<br>
"https://open.weixin.qq.com/connect/oauth2/authorize?"를 반환합니다. . $bizString;<br>
}<br>
<br>
/**<br>
*<br>
* open 및 access_toke의 URL 주소를 얻기 위한 구성<br>
* @param string $code, 위챗 점프에서 가져온 코드<br>
*<br>
* @return 요청 URL<br>
*/<br>
비공개 함수 __CreateOauthUrlForOpenid($code)<br>
{<br>
$urlObj["appid"] = $this->config['appid'];<br>
$urlObj["secret"] = $this->config['appsecret'];<br>
$urlObj["code"] = $code;<br>
$urlObj["grant_type"] = "authorization_code";<br>
$bizString = $this->ToUrlParams($urlObj);<br>
"https://api.weixin.qq.com/sns/oauth2/access_token?"을 반환합니다. . $bizString;<br>
}<br>
}