PHP payment development instance and php payment instance
The PHP payment development process is for your reference. The details are as follows:
1. Development Environment
Thinkphp 3.2.3
: Service number, certified
Development Domain Name: http://test.paywechat.com (custom domain name, Internet inaccessible)
2. Related Files and permissions are required.
Apply for activation for payment
Public platform developer documentation: http://mp.weixin.qq.com/wiki/home/index.html
Payment developer documentation: https://pay.weixin.qq.com/wiki/doc/api/index.html
Payment SDK: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php? Chapter = 11_1
3. Development
Download the php sdk. The file directory is:
Put the Cert and Lib directories of the payment SDK into Thinkphp. The directory is
This section describes the payment authorization directory. First, fill in the payment authorization directory in the payment development configuration,
Then fill in the JS interface security domain.
Finally, set webpage authorization
After completing these settings, you will be half done. Pay attention to the Set Directory and the directory in my thinkphp.
4. Payment Configuration
Enter the relevant configuration correctly.
/*** Configure account information */class WxPayConfig {// ======== [basic information settings] ========== ========================================/// *** TODO: modify the configuration here to the merchant information you have applied for * Public Account information configuration ** APPID: bound to the payment APPID (required, which can be viewed in the account opening email) ** MCHID: merchant ID (required, which can be viewed in the account opening email) ** KEY: Merchant's payment KEY. For details, refer to the account opening email settings (required, which can be set by logging on to the merchant platform) * set the address: https://pay.weixin.qq.com/index.php/account/api_cert ** APPSECRET: Public Account secert (only JSAPI pay when you need to configure, login to the public platform, enter the Developer Center can be set), * Get address: https://mp.weixin.qq.com/advanced/ad Vanced? Action = dev & t = advanced/dev & token = 2005451881 & lang = zh_CN * @ var string */const APPID = ''; const MCHID = ''; const KEY = ''; const APPSECRET = ''; // ======= [certificate path settings] =================================== =============/ *** TODO: set the merchant certificate path * certificate path. Be sure to enter the absolute path (only required for refund and order revocation, you can log on to the merchant platform to download it, * API certificate: required) * @ var path */const SSLCERT_PATH = '.. /cert/apiclient_cert.pem '; Const SSLKEY_PATH = '.. /cert/apiclient_key.pem '; // ======= [curl proxy settings] ================================ ===========/*** TODO: the proxy machine is set here. It is set only when proxy is required. No proxy is required. Set it to 0.0.0.0 and 0 *. This routine uses the http post method through curl. Here the proxy server can be modified, * CURL_PROXY_HOST = 0.0.0.0 and CURL_PROXY_PORT = 0 by default. The proxy is not enabled at this time (if necessary) * @ var unknown_type */const CURL_PROXY_HOST = "0.0.0.0"; // "10.152.18.220 "; const CURL_PROXY_PORT = 0; // 8080; // ========= [report information configuration] ================ =: The report duration is [1 s]. If reporting succeeds or fails, [never throws an exception], * the interface call process is not affected.) After reporting is enabled, the quality of request calls can be easily monitored, it is recommended that at least * enable error reporting. * Report Level: 0. Disable reporting; 1. Report errors only; 2. Full Report * @ var int */const REPORT_LEVENL = 1 ;}
Now paste the Code:
Namespace Wechat \ Controller; use Think \ Controller;/*** parent class Controller, which must inherit * @ file ParentController. class. php * @ author Gary <lizhiyong2204@sina.com> * @ date August 4, 2015 * @ todu */class ParentController extends Controller {protected $ options = array ('Token' => '', // enter your set key 'enablingaeskey' => '', // enter the encryption encodingaeskey 'appid '=> '', // enter the app id 'appsecret' => ''of the Advanced Call function, // enter the key of the Advanced Call function 'debug' => fals E, 'logcallback' => ''); public $ errCode = 40001; public $ errMsg =" no access "; /*** get access_token * @ return mixed | boolean | unknown */public function getToken () {$ cache_token = S ('exp _ wechat_pay_token '); if (! Empty ($ cache_token) {return $ cache_token;} $ url = 'https: // api.weixin.qq.com/cgi-bin/token? Grant_type = client_credential & appid = % s & secret = % s'; $ url = sprintf ($ url, $ this-> options ['appid '], $ this-> options ['appsecret']); $ result = $ this-> http_get ($ url); $ result = json_decode ($ result, true ); if (empty ($ result) {return false;} S ('exp _ wechat_pay_token ', $ result ['Access _ token'], array ('type' => 'file', 'expire '=> 3600); return $ result ['Access _ token'];} /*** send Customer Service Message ** @ param array $ data message structure {"touser ":" OPENID "," msgtype ":" news "," news ":{...}} */public function sendCustomMessage ($ data) {$ token = $ this-> getToken (); if (empty ($ token) return false; $ url = 'https: // api.weixin.qq.com/cgi-bin/message/custom/send? Access_token = % s'; $ url = sprintf ($ url, $ token); $ result = $ this-> http_post ($ url, self: json_encode ($ data )); if ($ result) {$ json = json_decode ($ result, true); if (! $ Json |! Empty ($ json ['errcode']) {$ this-> errcode = $ json ['errcode']; $ this-> errMsg = $ json ['errmsg ']; return false;} return $ json;} return false ;} /*** send template message ** @ param unknown $ data * @ return boolean | unknown */public function sendTemplateMessage ($ data) {$ token = $ this-> getToken (); if (empty ($ token) return false; $ url = "https://api.weixin.qq.com/cgi-bin/message/template/send? Access_token = % s "; $ url = sprintf ($ url, $ token); $ result = $ this-> http_post ($ url, self: json_encode ($ data )); if ($ result) {$ json = json_decode ($ result, true); if (! $ Json |! Empty ($ json ['errcode']) {$ this-> errcode = $ json ['errcode']; $ this-> errMsg = $ json ['errmsg ']; return false;} return $ json;} return false;} public function getFileCache ($ name) {return S ($ name );} /*** the api does not support json structure escaped from Chinese characters * @ param array $ arr */static function json_encode ($ arr) {$ parts = array (); $ is_list = false; // Find out if the given array is a numerical array $ keys = array_keys ($ arr); $ m Ax_length = count ($ arr)-1; if ($ keys [0] === 0) & ($ keys [$ max_length] ===$ max_length )) {// See if the first key is 0 and last key is length-1 $ is_list = true; for ($ I = 0; $ I <count ($ keys ); $ I ++) {// See if each key correspondes to its position if ($ I! = $ Keys [$ I]) {// A key fails at position check. $ is_list = false; // It is an associative array. break ;}}foreach ($ arr as $ key =>$ value) {if (is_array ($ value) {// Custom handling for arrays if ($ is_list) $ parts [] = self: json_encode ($ value);/*: RECURSION: */else $ parts [] = '"'. $ key. '":'. self: json_encode ($ value);/*: RECURSION: */} else {$ str = ''; if (! $ Is_list) $ str = '"'. $ key. '":'; // Custom handling for multiple data types if (! Is_string ($ value) & is_numeric ($ value) & $ value <2000000000) $ str. = $ value; // Numbers elseif ($ value = false) $ str. = 'false'; // The booleans elseif ($ value = true) $ str. = 'true'; else $ str. = '"'. addslashes ($ value ). '"'; // All other things //: TODO: Is there any more datatype we shoshould be in the lookout? (Object ?) $ Parts [] = $ str ;}$ json = implode (',', $ parts); if ($ is_list) return '['. $ json. ']'; // Return numerical JSON return '{'. $ json. '}'; // Return associative JSON}/** + random * generate random string + ------------------------------------------------------------ * @ param int $ length: 0, numbers + uppercase/lowercase letters; 1, numbers; 2, lowercase letters; 3, uppercase letters; 4, Special characters;-1, numbers + uppercase/lowercase letters + special characters + ------------------------------------------------------ * @ return string + functions */static public function randCode ($ length = 5, $ type = 2) {$ arr = array (1 => "0123456789", 2 => "abcdefghijklmnopqrstuvwxyz", 3 => "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 4 => "~ @ # $ % ^ & * () {} [] | "); If ($ type = 0) {array_pop ($ arr); $ string = implode ("", $ arr);} elseif ($ type = "-1") {$ string = implode ("", $ arr );} else {$ string = $ arr [$ type] ;}$ count = strlen ($ string)-1; $ code = ''; for ($ I = 0; $ I <$ length; $ I ++) {$ code. = $ string [rand (0, $ count)];} return $ code;}/*** GET request * @ param string $ url */private function http_get ($ url) {$ oCurl = curl_init (); if (stri Pos ($ url, "https ://")! = FALSE) {curl_setopt ($ oCurl, success, FALSE); curl_setopt ($ oCurl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt ($ oCurl, CURLOPT_SSLVERSION, 1 ); // CURL_SSLVERSION_TLSv1} curl_setopt ($ oCurl, CURLOPT_URL, $ url); curl_setopt ($ oCurl, CURLOPT_RETURNTRANSFER, 1); $ sContent = curl_exec ($ oCurl ); $ aStatus = curl_getinfo ($ oCurl); curl_close ($ oCurl); if (intval ($ aStatus ["http_code"]) == 200) {retu Rn $ sContent;} else {return false ;}} /*** POST Request * @ param string $ url * @ param array $ param * @ param boolean $ post_file whether to upload files * @ return string content */private function http_post ($ url, $ param, $ post_file = false) {$ oCurl = curl_init (); if (stripos ($ url, "https ://")! = FALSE) {curl_setopt ($ oCurl, success, FALSE); curl_setopt ($ oCurl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt ($ oCurl, CURLOPT_SSLVERSION, 1 ); // CURL_SSLVERSION_TLSv1} if (is_string ($ param) | $ post_file) {$ strPOST = $ param;} else {$ aPOST = array (); foreach ($ param as $ key => $ val) {$ aPOST [] = $ key. "= ". urlencode ($ val) ;}$ strPOST = join ("&", $ aPOST);} curl_setopt ($ oCurl, CURLOPT_URL, $ url); curl_setopt ($ oCurl, CURLOPT_RETURNTRANSFER, 1); curl_setopt ($ oCurl, CURLOPT_POST, true); curl_setopt ($ oCurl, CURLOPT_POSTFIELDS, $ strPOST); $ sContent = curl_exec ($ oCurl ); $ aStatus = curl_getinfo ($ oCurl); curl_close ($ oCurl); if (intval ($ aStatus ["http_code"]) = 200) {return $ sContent ;} else {return false ;}}}
Namespace Wechat \ Controller; use Wechat \ Controller \ ParentController;/*** payment test Controller * @ file TestController. class. php * @ author Gary <lizhiyong2204@sina.com> * @ date August 4, 2015 * @ todu */class TestController extends ParentController {private $ _ order_body = 'xxx'; private $ _ order_goods_tag = 'xxx '; public function _ construct () {parent ::__ construct (); require_once ROOT_PATH. "Api/lib/WxPay. api. php "; requ Ire_once ROOT_PATH. "Api/lib/WxPay. jsApiPay. php ";} public function index () {// ①. Obtain the user openid $ tools = new \ JsApiPay (); $ openId = $ tools-> GetOpenid (); // ② unified order $ input = new \ WxPayUnifiedOrder (); // product description $ input-> SetBody ($ this-> _ order_body); // additional data, you can add the data you need. This data will be appended when the callback is asynchronous. $ input-> SetAttach ('xxx'); // Merchant Order Number $ out_trade_no = \ WxPayConfig: MCHID. date ("YmdHis"); $ input-> SetOut_trade_no ($ out_trade_no); // total amount, Total order amount, which can only be an integer, in the unit of $ input-> settotal_hour (1); // transaction start time $ input-> SetTime_start (date ("YmdHis ")); // transaction end time $ input-> SetTime_expire (date ("YmdHis", time () + 600 )); // product tag $ input-> SetGoods_tag ($ this-> _ order_goods_tag); // notification address, receive payment asynchronous notification callback address SITE_URL = http://test.paywechat.com/Charge $ policy_url = SITE_URL. '/index. php/Test/yy.html '; $ input-> setpolicy_url ($ policy_url); // transaction type $ input-> SetTrade_type ("JSAPI"); $ Input-> SetOpenid ($ openId); $ order = \ WxPayApi: unifiedOrder ($ input); $ jsApiParameters = $ tools-> GetJsApiParameters ($ order ); // get the shared shipping address. js function parameter $ editAddress = $ tools-> GetEditAddressParameters (); $ this-> assign ('openid', $ openId ); $ this-> assign ('jsapiparameters ', $ jsApiParameters); $ this-> assign ('editaddress', $ editAddress); $ this-> display ();} /*** asynchronous notification callback Method */public function Y () {require_once ROOT _ PATH. "Api/lib/notify. php "; $ policy = new \ paypolicycallback (); $ policy-> Handle (false); // here, IsSuccess is a custom method, I will post the code for this file for your reference. $ Is_success = $ policy-> IsSuccess (); $ bdata = $ is_success ['data']; // if the payment is successful ($ is_success ['code'] = 1) {$ news = array ('touser' => $ bdata ['openid'], 'msgtype' => 'News ', 'News' => array ('articles' => array ('title' => 'order payment successful ', 'description' => "payment amount: {$ bdata ['total _ timeout']} \ n ". "Order No.: {$ bdata ['transaction _ id']} \ n" 'picurl' => '', 'url' => '')))); // send a payment notification $ this-> sendCustomMessage ($ news );} else {// payment Failed}/** payment success page * unreliable callback */public function ajax_PaySuccess () {// Order No. $ out_trade_no = I ('Post. out_trade_no '); // payment amount $ total_amount = I ('Post. total_fee ');/* related logic processing */}
Paste template HTML
<Html>
Notify. php file code. Here is a new custom method added to the official file.
Require_once ROOT_PATH. "Api/lib/WxPay. api. php "; require_once ROOT_PATH. 'api/lib/WxPay. policy. php '; require_once ROOT_PATH. 'api/lib/log. php'; // initialization log $ logHandler = new \ CLogFileHandler (ROOT_PATH. "/logs /". date ('Y-m-d '). '. log'); $ log = \ log: Init ($ logHandler, 15); class PayNotifyCallBack extends WxPayNotify {protected $ para = array ('code' => 0, 'data' => ''); // query the order public function Queryorder ($ transaction_id) {$ Input = new \ WxPayOrderQuery (); $ input-> SetTransaction_id ($ transaction_id); $ result = \ WxPayApi: orderQuery ($ input); \ Log: DEBUG ("query: ". json_encode ($ result); if (array_key_exists ("return_code", $ result) & array_key_exists ("result_code", $ result) & $ result ["return_code"] = "SUCCESS" & $ result ["result_code"] = "SUCCESS") {return true ;} $ this-> para ['code'] = 0; $ this-> para ['data'] = ''; re Turn false;} // rewrite the callback handler public function yyprocess ($ data, & $ msg) {\ Log: DEBUG ("call back :". json_encode ($ data); $ notfiyOutput = array (); if (! Array_key_exists ("transaction_id", $ data) {$ msg = "incorrect input parameter"; $ this-> para ['code'] = 0; $ this-> para ['data'] = ''; return false;} // query the order and determine the order authenticity if (! $ This-> Queryorder ($ data ["transaction_id"]) {$ msg = "Order query failed"; $ this-> para ['code'] = 0; $ this-> para ['data'] = ''; return false;} $ this-> para ['code'] = 1; $ this-> para ['data'] = $ data; return true;}/*** Method for customizing whether the method for checking whether the callback is successful * @ return multitype: number string */public function IsSuccess () {return $ this-> para ;}}
Basically done here, you can open the http://test.paywechat.com/Charge/index.php/Test/index/ at the end
In my environment, the HTTP server does not rewrite the url, and payment continues to be explored. In some places, there may be problems or deficiencies in writing. I hope you can understand each other and learn from each other.
The above is all about PHP payment development. I hope it will be helpful to everyone's learning, and I hope you can support more help.