PHP를 사용하여 APP에서 WeChat 결제 기능을 구현하는 방법
이 글은 주로 APP 측에서 WeChat 결제 기능을 구현하기 위한 PHP를 소개합니다. 매우 훌륭하고 참고할만한 가치가 있습니다. 필요한 친구는 참고할 수 있습니다.
오늘 모바일 앱에서 Alipay 결제에 대해 글을 썼습니다. 모바일 앱에서 위챗 결제를 보완하겠습니다. 여기서는 사전 준비 사항에 대해 자세히 설명하지 않겠습니다. 위챗 결제 개발 문서를 참고하시면 위험을 피할 수 있습니다. 준비가 완료되면 매개변수를 구성하고 통합 주문 인터페이스를 호출하고 결제합니다. 다음은 비동기 콜백 3부작입니다.
1. 결제 클래스 파일을 캡슐화하고 중복되는 항목을 모두 제거하고 구성 매개변수를 넣었습니다. Weixinpayandroid 메서드에서 몇 가지 매개변수만 수정하면 됩니다.
class Wxpayandroid { //参数配置 public $config = array( 'appid' => "", /*微信开放平台上的应用id*/ 'mch_id' => "", /*微信申请成功之后邮件中的商户id*/ 'api_key' => "", /*在微信商户平台上自己设定的api密钥 32位*/ ); //服务器异步通知页面路径(必填) public $notify_url = ''; //商户订单号(必填,商户网站订单系统中唯一订单号) public $out_trade_no = ''; //商品描述(必填,不填则为商品名称) public $body = ''; //付款金额(必填) public $total_fee = 0; //自定义超时(选填,支持dhmc) public $time_expire = ''; private $WxPayHelper; public function Weixinpayandroid($total_fee,$tade_no) { $this->total_fee = intval($total_fee * 100);//订单的金额 1元 $this->out_trade_no = $tade_no;// date('YmdHis') . substr(time(), - 5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));//订单号 $this->body = 'wxpay';//支付描述信息 $this->time_expire = date('YmdHis', time() + 86400);//订单支付的过期时间(eg:一天过期) $this->notify_url = "http://www.ceshi.com/notifyandroid";//异步通知URL(更改支付状态) //数据以JSON的形式返回给APP $app_response = $this->doPay(); if (isset($app_response['return_code']) && $app_response['return_code'] == 'FAIL') { $errorCode = 100; $errorMsg = $app_response['return_msg']; $this->echoResult($errorCode, $errorMsg); } else { $errorCode = 0; $errorMsg = 'success'; $responseData = array( 'notify_url' => $this->notify_url, 'app_response' => $app_response, ); $this->echoResult($errorCode, $errorMsg, $responseData); } } //接口输出 function echoResult($errorCode = 0, $errorMsg = 'success', $responseData = array()) { $arr = array( 'errorCode' => $errorCode, 'errorMsg' => $errorMsg, 'responseData' => $responseData, ); exit(json_encode($arr)); //exit可以正常发送给APP json数据 // return json_encode($arr); //在TP5中return这个json数据,APP接收到的是null,无法正常吊起微信支付 } function getVerifySign($data, $key) { $String = $this->formatParameters($data, false); //签名步骤二:在string后加入KEY $String = $String . "&key=" . $key; //签名步骤三:MD5加密 $String = md5($String); //签名步骤四:所有字符转为大写 $result = strtoupper($String); return $result; } function formatParameters($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($k=="sign"){ continue; } if ($urlencode) { $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } $reqPar; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff) - 1); } return $reqPar; } /** * 得到签名 * @param object $obj * @param string $api_key * @return string */ function getSign($obj, $api_key) { foreach ($obj as $k => $v) { $Parameters[strtolower($k)] = $v; } //签名步骤一:按字典序排序参数 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //签名步骤二:在string后加入KEY $String = $String."&key=".$api_key; //签名步骤三:MD5加密 $result = strtoupper(md5($String)); return $result; } /** * 获取指定长度的随机字符串 * @param int $length * @return Ambigous <NULL, string> */ 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; } /** * 数组转xml * @param array $arr * @return string */ 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; } /** * 以post方式提交xml到对应的接口url * * @param string $xml 需要post的xml数据 * @param string $url url * @param bool $useCert 是否需要证书,默认不需要 * @param int $second url执行超时时间,默认30s * @throws WxPayException */ function postXmlCurl($xml, $url, $second=30, $useCert=false, $sslcert_path='', $sslkey_path='') { $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch,CURLOPT_URL, $url); //设置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); if($useCert == true){ curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验 //设置证书 //使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLCERT, $sslcert_path); curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLKEY, $sslkey_path); } //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); return false; } } /** * 获取当前服务器的IP * @return Ambigous <string, unknown> */ function get_client_ip() { if (isset($_SERVER['REMOTE_ADDR'])) { $cip = $_SERVER['REMOTE_ADDR']; } elseif (getenv("REMOTE_ADDR")) { $cip = getenv("REMOTE_ADDR"); } elseif (getenv("HTTP_CLIENT_IP")) { $cip = getenv("HTTP_CLIENT_IP"); } else { $cip = "127.0.0.1"; } return $cip; } /** * 将数组转成uri字符串 * @param array $paraMap * @param bool $urlencode * @return string */ function formatBizQueryParaMap($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($urlencode) { $v = urlencode($v); } $buff .= strtolower($k) . "=" . $v . "&"; } $reqPar; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff)-1); } return $reqPar; } /** * XML转数组 * @param unknown $xml * @return mixed */ function xmlToArray($xml) { //将XML转为array $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $array_data; } public function chkParam() { //用户网站订单号 if (empty($this->out_trade_no)) { die('out_trade_no error'); } //商品描述 if (empty($this->body)) { die('body error'); } if (empty($this->time_expire)){ die('time_expire error'); } //检测支付金额 if (empty($this->total_fee) || !is_numeric($this->total_fee)) { die('total_fee error'); } //异步通知URL if (empty($this->notify_url)) { die('notify_url error'); } if (!preg_match("#^http:\/\/#i", $this->notify_url)) { $this->notify_url = "http://" . $_SERVER['HTTP_HOST'] . $this->notify_url; } return true; } /** * 生成支付(返回给APP) * @return boolean|mixed */ public function doPay() { //检测构造参数 $this->chkParam(); return $this->createAppPara(); } /** * APP统一下单 */ private function createAppPara() { $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $data["appid"] = $this->config['appid'];//微信开放平台审核通过的应用APPID $data["body"] = $this->body;//商品或支付单简要描述 $data["mch_id"] = $this->config['mch_id'];//商户号 $data["nonce_str"] = $this->getRandChar(32);//随机字符串 $data["notify_url"] = $this->notify_url;//通知地址 $data["out_trade_no"] = $this->out_trade_no;//商户订单号 $data["spbill_create_ip"] = $this->get_client_ip();//终端IP $data["total_fee"] = $this->total_fee;//总金额 $data["time_expire"] = $this->time_expire;//交易结束时间 $data["trade_type"] = "APP";//交易类型 $data["sign"] = $this->getSign($data, $this->config['api_key']);//签名 $xml = $this->arrayToXml($data); $response = $this->postXmlCurl($xml, $url); //将微信返回的结果xml转成数组 $responseArr = $this->xmlToArray($response); if(isset($responseArr["return_code"]) && $responseArr["return_code"]=='SUCCESS'){ return $this->getOrder($responseArr['prepay_id']); } return $responseArr; } /** * 执行第二次签名,才能返回给客户端使用 * @param int $prepayId:预支付交易会话标识 * @return array */ public function getOrder($prepayId) { $data["appid"] = $this->config['appid']; $data["noncestr"] = $this->getRandChar(32); $data["package"] = "Sign=WXPay"; $data["partnerid"] = $this->config['mch_id']; $data["prepayid"] = $prepayId; $data["timestamp"] = time(); $data["sign"] = $this->getSign($data, $this->config['api_key']); $data["packagestr"] = "Sign=WXPay"; return $data; } /** * 异步通知信息验证 * @return boolean|mixed */ public function verifyNotify() { $xml = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : ''; if(!$xml){ return false; } $wx_back = $this->xmlToArray($xml); if(empty($wx_back)){ return false; } $checkSign = $this->getVerifySign($wx_back, $this->config['api_key']); if($checkSign=$wx_back['sign']){ return $wx_back; }else{ return false; } } }
2. 결제 후 통합 주문 인터페이스와 비동기 콜백 인터페이스를 정의하는 컨트롤러를 만듭니다. :
//异步通知接口 public function notifyandroid() { $wxpayandroid = new \Wxpayandroid; //实例化微信支付类 $verify_result = $wxpayandroid->verifyNotify(); if ($verify_result['return_code']=='SUCCESS' && $verify_result['result_code']=='SUCCESS') { //商户订单号 $out_trade_no = $verify_result['out_trade_no']; //交易号 $trade_no = $verify_result['transaction_id']; //交易状态 $trade_status = $verify_result['result_code']; //支付金额 $total_fee = $verify_result['total_fee']/100; //支付过期时间 $pay_date = $verify_result['time_end']; $order = new Order(); $ret = $order->getOrderN2($out_trade_no); //获取订单信息 $total_amount=$ret['money']; if ($total_amount==$total_fee) { // 验证成功 修改数据库的订单状态等 $result['out_trade_no']为订单号 //此处写自己的逻辑代码 } exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'); }else{ exit('<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>'); } } //调用统一下单接口生成预支付订单并把数据返回给APP public function wxpayandroid(Request $request) { $param = $request->param(); //接收值 $tade_no = $param['orderCode']; $order = new Order(); //实例化订单 $ret = $order->getOrderN2($tade_no); //查询订单信息 $total_fee = $ret['money']; //订单总金额 $wxpayandroid = new \Wxpayandroid; //实例化微信支付类 $res = $wxpayandroid->Weixinpayandroid($total_fee,$tade_no); //调用weixinpay方法 }
결제 클래스 파일을 캡슐화하고 구성 매개변수를 결제 클래스 내에서 컨트롤러를 정의하여 두 가지 방법을 생성하면 모바일 앱에서 WeChat 결제가 두 단계로 완료될 수 있습니다.
위 내용은 이 글의 전체 내용입니다. 모든 분들의 학습에 도움이 되었으면 좋겠습니다. 더 많은 관련 내용은 PHP 중국어 홈페이지를 주목해주세요!
관련 권장사항:
php 개인을 위한 WeChat 기업 계정 결제 구현 방법
PHP는 WeChat 공용 플랫폼 기업 계정 확인 인터페이스를 구현합니다.
위 내용은 PHP를 사용하여 APP에서 WeChat 결제 기능을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

JWT는 주로 신분증 인증 및 정보 교환을 위해 당사자간에 정보를 안전하게 전송하는 데 사용되는 JSON을 기반으로 한 개방형 표준입니다. 1. JWT는 헤더, 페이로드 및 서명의 세 부분으로 구성됩니다. 2. JWT의 작업 원칙에는 세 가지 단계가 포함됩니다. JWT 생성, JWT 확인 및 Parsing Payload. 3. PHP에서 인증에 JWT를 사용하면 JWT를 생성하고 확인할 수 있으며 사용자 역할 및 권한 정보가 고급 사용에 포함될 수 있습니다. 4. 일반적인 오류에는 서명 검증 실패, 토큰 만료 및 대형 페이로드가 포함됩니다. 디버깅 기술에는 디버깅 도구 및 로깅 사용이 포함됩니다. 5. 성능 최적화 및 모범 사례에는 적절한 시그니처 알고리즘 사용, 타당성 기간 설정 합리적,

이 튜토리얼은 PHP를 사용하여 XML 문서를 효율적으로 처리하는 방법을 보여줍니다. XML (Extensible Markup Language)은 인간의 가독성과 기계 구문 분석을 위해 설계된 다목적 텍스트 기반 마크 업 언어입니다. 일반적으로 데이터 저장 AN에 사용됩니다

문자열은 문자, 숫자 및 기호를 포함하여 일련의 문자입니다. 이 튜토리얼은 다른 방법을 사용하여 PHP의 주어진 문자열의 모음 수를 계산하는 방법을 배웁니다. 영어의 모음은 A, E, I, O, U이며 대문자 또는 소문자 일 수 있습니다. 모음이란 무엇입니까? 모음은 특정 발음을 나타내는 알파벳 문자입니다. 대문자와 소문자를 포함하여 영어에는 5 개의 모음이 있습니다. a, e, i, o, u 예 1 입력 : String = "Tutorialspoint" 출력 : 6 설명하다 문자열의 "Tutorialspoint"의 모음은 u, o, i, a, o, i입니다. 총 6 개의 위안이 있습니다

정적 바인딩 (정적 : :)는 PHP에서 늦은 정적 바인딩 (LSB)을 구현하여 클래스를 정의하는 대신 정적 컨텍스트에서 호출 클래스를 참조 할 수 있습니다. 1) 구문 분석 프로세스는 런타임에 수행됩니다. 2) 상속 관계에서 통화 클래스를 찾아보십시오. 3) 성능 오버 헤드를 가져올 수 있습니다.

PHP의 마법 방법은 무엇입니까? PHP의 마법 방법은 다음과 같습니다. 1. \ _ \ _ Construct, 객체를 초기화하는 데 사용됩니다. 2. \ _ \ _ 파괴, 자원을 정리하는 데 사용됩니다. 3. \ _ \ _ 호출, 존재하지 않는 메소드 호출을 처리하십시오. 4. \ _ \ _ get, 동적 속성 액세스를 구현하십시오. 5. \ _ \ _ Set, 동적 속성 설정을 구현하십시오. 이러한 방법은 특정 상황에서 자동으로 호출되어 코드 유연성과 효율성을 향상시킵니다.

PHP에서는 예측할 수없는 토큰을 사용하여 CSRF 공격을 효과적으로 방지 할 수 있습니다. 특정 방법은 다음과 같습니다. 1. 형태로 CSRF 토큰을 생성하고 포함시킨다. 2. 요청을 처리 할 때 토큰의 유효성을 확인하십시오.
