PHP Micro-credit payment development

Source: Internet
Author: User
Tags call back http post openid sprintf
1. Development environment
thinkphp 3.2.3
: Service number, certified
Development Domain Name: http://test.paywechat.com (custom domain name, external network unreachable)

2. Need relevant documents and permissions
Payment required for opening
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 Download Address: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

3. Development
Download the SDK to pay the PHP version, the file directory is:


Put the Cert and LIB directories of the payment SDK into the thinkphp directory for

Now introduce the payment authorization directory problem, the first is to pay the development configuration inside the payment authorization directory filled in,

Then fill in the JS interface security domain.

Finally set up page authorization

These settings finish, basically half done, note the set of directories and my thinkphp inside the directory.

4. Payment Configuration

Fill in the relevant configuration correctly.

/** * Configure account information */class wxpayconfig{//======= "Basic information Settings" =====================================///** * TODO: Modify the configuration here for your own Merchant Information Requested * Public number configuration * * APPID: Binding payment of the APPID (must be configured, the account can be viewed in the opening mail) * * Mchid: Merchant Number (must be configured, can be viewed in the account opening mail) * * Key: Merchant payment key, refer to the Account opening mail settings (must be configured, login to the merchant platform itself Settings) * Set Address: Https://pay.weixin.qq.com/index.php/account/api_cert * * Appsecret: Public account Secert (only need to be configured for JSAPI payment, login to public platform, Enter the developer center to set up), * get address: https://mp.weixin.qq.com/advanced/advanced?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 * Certification path, note that absolute path should be filled out (only refunds, cancellation of orders, you can log on to the merchant platform to download, * API certificate Download Address: Https://pay.weixin.qq.com/index.php/account/api_cert, need to install merchant operation Certificate before downloading) * @var path */Const SSLCERT_PATH = '.    ./cert/apiclient_cert.pem '; Const Sslkey_path = '..    /cert/apiclient_key.pem '; ======= "Curl proxy settings" ===================================/** * TODO: Set up agent machine here, only need agent'sWhen set, no proxy required, set to 0.0.0.0 and 0 * This routine uses the HTTP POST method via curl, where you can modify the proxy server, * default curl_proxy_host=0.0.0.0 and curl_proxy_port=    0, do not open the agent at this time (if necessary to set) * @var Unknown_type */Const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220";    Const CURL_PROXY_PORT = 0;//8080; ======= "Escalation information Configuration" ===================================/** * TODO: Interface call escalation level, default tight error escalation (note: escalation time is "1s", escalation regardless of success or failure "never throw exception", * Does not affect the interface invocation process), after you turn on escalation, it is convenient to monitor the quality of request calls, at least * turn on error escalation. * Escalation level, 0. Close the escalation; 1. Error escalation only; 2. Full escalation * @var int */CONST REPORT_LEVENL = 1;}

Now start to post the code:

Namespace Wechat\controller;use think\controller;/** * Parent class controller, need to inherit * @file ParentController.class.php * @author Gary
 
  
 * @date August 4, 2015 * @todu */class Parentcontroller extends Controller {protected $options = Array (' Tok En ' = = ',//fill in your Set key ' Encodingaeskey ' + ',//fill in the encryption with the Encodingaeskey ' appid ' and ' = ',//fill in Write advanced call feature app ID ' appsecret ' + ' + ',//fill in the Advanced Call Function key ' debug ' = False, ' Logcallback ' =& Gt          ''    );       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 Sendcus        Tommessage ($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);        /** * API does not support Chinese-escaped JSON structure * @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);        $max _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! = $key                    s [$i]) {//a key fails at position check. $is _list = false;                    It's an associative array.                Break }}}} foreach ($arr as $key = = $value) {if (Is_array ($value)) {//custom hand Ling 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 and things//: Todo:is There any more datatype we should is in the lookout for?                (Object?)            $parts [] = $STR;        }} $json = Implode (', ', $parts); if ($is _list) return ' ['. $json. ']'; Return numerical JSON return ' {'. $json. '}'; Return Associative JSON}/** +----------------------------------------------------------* Generate random string +------------- ---------------------------------------------* @param int $length The random string length to be generated * @param string $type random code type: 0, digit + case letter; 1, Numbers; 2, lowercase letters, 3, uppercase letters, 4, special characters;-1, digits + uppercase and lowercase letters + special characters +----------------------------------------------------------* @return string +----------------------------------------------------------*/ static public Function Randcode ($length = 5, $type = 2) {$arr = array (1 = "0123456789", 2 = "abcdefghijklmn        Opqrstuvwxyz ", 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 (Stripos ($url, "https://")!==false) {curl_setopt ($oCurl, Curlopt_ssl_verifypeer, 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"]) {return $sContent; ==200)        }else{return false; }}/** * POST request * @param string $url * @param array $param * @param boolean $post _file File upload * @return string con        Tent */Private Function Http_post ($url, $param, $post _file=false) {$oCurl = Curl_init ();            if (Stripos ($url, "https://")!==false) {curl_setopt ($oCurl, Curlopt_ssl_verifypeer, 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"]) {return $sContent; ==200)        }else{return false; }    }}
 
Namespace Wechat\controller;use wechat\controller\parentcontroller;/** * Pay Test Controller * @file TestController.class.php * @  Author Gary
 
  
 * @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 "; Require_once Root_path. "    Api/lib/wxpay.jsapipay.php ";        Public Function Index () {//①, get 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, back to the asynchronous callback will append this data $input->setattach (' xxx ');        Merchant Order number $out _trade_no = \wxpayconfig::mchid.date ("Ymdhis");        $input->setout_trade_no ($out _trade_no);        The total amount, the total order amount, can only be an integer, the unit is divided $input->settotal_fee (1);        Transaction start time $input->settime_start (date ("Ymdhis")); Trade End Time $input->settime_expire (date ("Ymdhis")+ 600));        Commodity Mark $input->setgoods_tag ($this->_order_goods_tag); The notification address, which receives the asynchronous notification callback address Site_url=http://test.paywechat.com/charge $notify _url = site_url. '        /index.php/test/notify.html ';        $input->setnotify_url ($notify _url);        Transaction type $input->settrade_type ("JSAPI");        $input->setopenid ($openId);        $order = \wxpayapi::unifiedorder ($input);        $jsApiParameters = $tools->getjsapiparameters ($order);        Get the shared receipt 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 notify () {require_once Root_path.        Api/lib/notify.php ";        $notify = new \paynotifycallback ();        $notify->handle (FALSE);        Here issuccess is my custom method, I will post the code of this file, for reference. $is _success = $Notify->issuccess ();           $bdata = $is _success[' data '); Payment succeeds if ($is _success[' code '] = = 1) {$news = array (' touser ' = = $bdata [' OpenID '], ' msgtype ' = ' news ', ' news ' = = Array (' Articles ' + = Array (' title ' = =                                            ' Order payment success ', ' description ' = ' + ' Payment amount: {$bdata [' total_fee ']}\n '. "Order Number: {$bdata [' transaction_id ']}\n" ' picurl ' = "                            , ' url ' = = ')            )                    )            );                    Send payment Notice $this->sendcustommessage ($news); }else{//payment Failed}}/** * Payment success Page * Unreliable callback */publIC function ajax_paysuccess () {//order number $out _trade_no = I (' post.out_trade_no ');        Payment amount $total _fee = I (' Post.total_fee '); /* Related logic processing */}
 

Paste the template HTML

    
 
      
 
       Payment Example-payment        
The amount paid for the order is 1 cents .

Pay Now

notify.php file code, here is a new custom method added in the official file.

Require_once Root_path. " Api/lib/wxpay.api.php "; require_once root_path. ' api/lib/wxpay.notify.php '; require_once ROOT_PATH. ' Api/lib/log.php ';//Initialize log $loghandler= new \clogfilehandler (Root_path. ") /logs/". Date (' y-m-d '). Log '), $log = \log::init ($logHandler), class Paynotifycallback extends Wxpaynotify {protected $para = array (' Code ' =&    gt;0, ' data ' = ');        Query order Public Function Queryorder ($transaction _id) {$input = new \wxpayorderquery ();        $input->settransaction_id ($transaction _id);        $result = \wxpayapi::orderquery ($input); \log::D ebug ("query:".)        Json_encode ($result)); if (array_key_exists ("Return_code", $result) && array_key_exists ("Result_code", $result) &amp            ;& $result ["return_code"] = = "SUCCESS" && $result ["result_code"] = = "SUCCESS") {        return true;        } $this->para[' code ' = 0;        $this->para[' data '] = ';    return false; }//Override callback Handler PuBlic function Notifyprocess ($data, & $msg) {\log::D ebug ("Call Back:".        Json_encode ($data));        $notfiyOutput = Array ();            if (!array_key_exists ("transaction_id", $data)) {$msg = "input parameter is incorrect";            $this->para[' code ' = 0;            $this->para[' data '] = ';        return false;            }//Inquiry order, judge 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; }/** * Custom method detection End Callback Successful method * @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
My environment, HTTP server does not rewrite URL, pay to continue to explore, some places may write problems or shortcomings, hope everyone understanding, learn from each other.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.