Cet article présente principalement en détail le processus de développement du paiement PHP WeChat. Il a une certaine valeur de référence. Les amis intéressés peuvent s'y référer. J'espère qu'il pourra aider tout le monde.
1. Environnement de développement
Thinkphp 3.2.3
WeChat : Compte de service, certifié
Nom de domaine de développement : http://test.paywechat.com (depuis Le nom de domaine défini n'est pas accessible depuis le réseau externe)
2. Les documents et autorisations pertinents sont requis
Le paiement WeChat doit être activé
Documentation du développeur de la plateforme publique WeChat : http:// mp.weixin.qq.com/wiki/home/index.html
Documentation du développeur de paiement WeChat : https://pay.weixin.qq.com/wiki/doc/api/index.html
Adresse de téléchargement du SDK de paiement WeChat : https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
3. Téléchargez WeChat Pour payer la version PHP du SDK, le répertoire de fichiers est comme indiqué ci-dessous :
Mettez le certificat et Lib du SDK de paiement WeChat Thinkphp, le répertoire est
Présentons maintenant le problème du répertoire d'autorisation de paiement WeChat. La première consiste à remplir. le répertoire d'autorisation de paiement dans la configuration de développement des paiements WeChat,
Renseignez ensuite le domaine de sécurité de l'interface js.
Enfin définir l'autorisation Web
Une fois ces paramètres terminés, c'est essentiellement à moitié fait. Faites attention au répertoire défini et au répertoire dans mon thinkphp.
4. Configuration du paiement WeChat
Remplissez correctement la configuration correspondante. .
[php] voir simplecopie
/**
* Configurer les informations du compte
*/
classe WxPayConfig
{
//========[Paramètres des informations de base]=================== = =================
//
/**
* À FAIRE : Modifiez la configuration ici pour demander vos propres informations de marchand
* Informations sur le compte public WeChat configuration
*
* APPID : APPID lié au paiement (doit être configuré, visible dans l'email d'ouverture du compte)
*
*MCHID : Identifiant du commerçant (doit être configuré, peut être consulté dans l'e-mail d'ouverture du compte)
* )
* Adresse de réglage : https://pay.weixin .qq.com/index.php/account/api_cert
*
* APPSECRET : sécert de compte public (requis uniquement pour le paiement JSAPI, connectez-vous à la plateforme publique et entrez dans le centre de développement pour définir),
* Obtenir l'adresse : https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
* @var string
*/
const APPID = '' ; >;
const CLÉ = ''
const APPSECRET = '';
//==== ===【Paramètres du chemin du certificat】=======================================
* TODO : Définir le chemin du certificat marchand
* Chemin du certificat, veuillez noter que le chemin absolu doit être renseigné ( uniquement requis pour les remboursements et les annulations de commandes, vous pouvez vous connecter au téléchargement de la plateforme marchand,
* Adresse de téléchargement du certificat API : https://pay.weixin.qq.com/index.php/account/api_cert, vous devez installer le certificat d'opération marchand avant téléchargement)
* @var path
*/
const SSLCERT_PATH = './cert/apiclient_cert.pem';>'../cert/apiclient_key.pem'
>//========[paramètres du proxy curl]======================== ========= ===
/*** Cette routine utilise la méthode HTTP POST via curl, et le serveur proxy peut être modifié ici,
* Par défaut CURL_PROXY_HOST=0.0.0.0 et CURL_PROXY_PORT=0, le proxy n'est pas activé pour le moment (défini si nécessaire)
* @var inconnu_type
*/
const CURL_PROXY_HOST = "0.0.0.0";// CURL_PROXY_PORT = 0; //8080;
//========【Configuration des informations du rapport】======================= =========== ====
/**
const REPORT_LEVENL = 1;
}Commencez à publier le code maintenant :
>[php] vue simple copie
espace de noms WechatController ;
utiliser ThinkController; >/**
* Le contrôleur de classe parent doit hériter
* @file ParentController.class.php
* @auteur Gary
* @date 4 août 2015
* @todu
*/
classe ParentController étend Contrôleur {
protégé $options = tableau (
'jeton' => 🎜>// Remplissez la clé que vous avez définie
'encodingaeskey''', // Remplissez la clé EncodingAESKey pour le cryptage
'appid''', // Remplir en avancé L'identifiant de l'application de la fonction appelante
'appsecret''', // Remplissez la clé de la fonction d'appel avancée
'debug' => false,
'logcallback' => ''
);
public $errCode = 40001 ;
public $errMsg = "pas d'accès" ;
/**
* 获取access_token
* @return mixte|booléen|inconnu
*/
public fonction getToken(){
$cache_token = S('exp_wechat_pay_token');
si(!vide( $cache_token)){
retour $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, vrai);
si(vide($résultat)){
retour faux ;
}
S('exp_wechat_pay_token',$result['access_token'],array ('type'=>'fichier','expire' =>3600));
retour $result['access_token'];
}
/**
* Envoyer un message au service client
* @param array $data message structure {"touser":"OPENID","msgtype":"news","news":{...}}
*/
public fonction sendCustomMessage($data){
$token = $this->getToken();
si (vide($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));
si ($résultat)
{
$json = json_decode ($result,vrai) ;
si (!$json || !vide($json['errcode'])) {
$this->errCode = $json['errcode' ];
$this->errMsg = $json['errmsg'];
retour faux ;
}
retour $json;
}
retour FAUX;
}
/**
* Envoyer un modèle de message
* @param inconnu $data
* @return boolean|inconnu
*/
public fonction sendTemplateMessage($data){
$token = $this->getToken();
si (vide($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);
si (!$json || !vide($json['errcode'])) {
$this->errCode = $json['errcode' ];
$this->errMsg = $json['errmsg'];
retour faux ;
}
retour $json;
}
retour FAUX;
}
public function getFileCache($name){
return S($name);
}
/**
* L'API WeChat ne prend pas en charge la structure json échappée en chinois
* @param array $arr
*/
statique fonction json_encode($arr) {
$parts = tableau ();
$is_list = false ;
//Découvrez si le tableau donné est un tableau numérique
$keys = array_keys ( $arr );
$max_length = count ( $arr ) - 1 ;
if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) { //Vérifiez si la première clé est 0 et la dernière clé a la longueur - 1
$is_list = true ;
pour($i = 0; $i compte ( $clés ); $i ++) { //Voir si chaque touche correspond à sa position
if ($i != $keys [$i ]) { //Une clé échoue lors de la vérification de position.
$is_list = faux ; //C'est un tableau associatif.
pause ;
}
}
}
foreach ( $arr comme $clé => $valeur ) {
if (is_array ( $value )) { //Gestion personnalisée pour les tableaux
if ($is_list)
$parts [] = self::json_encode ( $value ); /* :RECURSION : */
autre
$parts [] = '"' . $key . '":' . self::json_encode ( $value ); /* :RECURSION : */
} autre {
$str = '';
if (! $is_list)
$str = '"' . $clé . '":';
//Gestion personnalisée pour plusieurs types de données
if (!is_string ( $value ) && is_numeric ( $value ) && $value
$str .= $value ; //Nombres
elseif ( $value === false)
$str .= 'faux'; //Les booléens
elseif ($value === true)
$str . = 'vrai' ;
autre
$str .= '"' . addslashes ( $value ) . '"' ; //Toutes les autres choses
// :À FAIRE : Y a-t-il plus type de données que nous devrions surveiller ? (Objet ?)
$parts [] = $str;
}
}
$json = imploser ( ',', $parts );
if ($is_list)
retour '[' $json ']'> retour
'{'$json . '}' //Retour JSON associatif }
* Générer une chaîne aléatoire
+----------------- --------- -------------------------------
* @param int $length La longueur de la chaîne aléatoire à générer
* @param string $type Type de code aléatoire : 0, chiffres + lettres majuscules et minuscules ; 1, chiffres ; 2, lettres minuscules ; 4, caractères spéciaux ; -1, chiffres + lettres majuscules et minuscules + caractères spéciaux
+---------------------------------- --------------------
* @ chaîne de retour
+----------------------- -----------------------------------
*/
statique public function randCode($length = 5, $ tapez = 2){
$arr = array(1 => "0123456789", 2 => "abcdefghijklmnopqrstuvwxyz", 3 = > "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 4 => "~@#$%^&*(){}[]|");
if ($type == 0) {
array_pop($arr);
$string = implode("", $arr);
} elseif ($type == "-1") {
$string = imploser("", $arr);
} autre {
$string = $arr[$type];
}
$count = strlen($string) - 1 ;
$code = '';
pour ($i = 0; $i $length; $i++) {
$code .= $string[rand(0 , $count)] ;
}
retour $code;
}
/**
* GET 请求
* @param string $url
*/
privé fonction http_get($url){
$oCurl = curl_init();
si(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"])==200){
retour $sContent ;
}autre{
retour faux ;
}
}
/**
*Demande POST
* @param string $url
* @param array $param
* @param boolean $post_file S'il faut télécharger le fichier
* @return string content
*/
privé fonction http_post($url,$param,$post_file=false){
$oCurl = curl_init();
si(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;
} autre {
$aPOST = tableau();
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){
retour $sContent ;
}autre{
retour faux ;
}
}
}
[php] voir simple copie
espace de noms WechatController ;
utiliser WechatControllerParentController ;
/**
* Contrôleur de test de paiement WeChat
* @file TestController.class.php
* @auteur Gary
* @date 4 août 2015
* @todu
*/
classe TestController s'étend ParentController {
privé $_order_body = 'xxx';
privé $_order_goods_tag = 'xxx';
public fonction __construct(){
parent::__construct();
require_once ROOT_PATH."Api/lib/WxPay.Api.php" ;
require_once ROOT_PATH."Api/lib/WxPay.JsApiPay.php" ;
}
public fonction index(){
//①, Obtenir l'identifiant de l'utilisateur
$tools = nouveau JsApiPay(
$openId = $tools->GetOpenid(); > //②, Ordre unifié
$input
=WxPayUnifiedOrder(> $input
->SetBody(-> ;_order_body);
$input->SetAttach('xxx'
//Numéro de commande du marchand
$out_trade_no = WxPayConfig::MCHID.date("YmdHis"); 🎜>
$input->SetOut_trade_no($out_trade_no ; 🎜>
->SetTotal_fee(1);
->SetTime_start(date(
"YmdHis"//Heure de fin de la transaction
$input->SetTime_expire(date("YmdHis ", time() + 600));
//Étiquette du produit
$input->SetGoods_tag($this->_order_goods_tag);
//Adresse de notification, recevoir l'adresse de rappel de notification asynchrone du paiement WeChat SITE_URL=http://test .paywechat.com/Charge
$notify_url = SITE_URL. '/index.php/Test/notify.html'; >->SetNotify_url(
$notify_url); / /Type d'échange
$input->SetTrade_type(
"JSAPI"$openId); ;
$order = WxPayApi::unifiedOrder($input
$jsApiParameters = $tools->GetJsApiParameters( $order);
//Obtenir les paramètres de la fonction js de l'adresse de livraison partagée
$editAddress = $tools ->GetEditAddressParameters();
this->assign(
,$openId); $this->assign(
, $jsApiParameters 'editAddress'); ,$editAddress);
$this->display(); > }
/**
* Méthode de rappel de notification asynchrone
*/
public
notifier (){ require_once
ROOT_PATH.; > PayNotifyCallBack();
$notify- >Handle(false); >
= $notifier ->EstSuccès();
$bdata = $is_success['data'];
//支付成功
if($is_success['code'] == 1 ){
$news = array(
'touser' => $bdata[ 'openid'],
'msgtype' => 'actualités',
'actualités' => tableau (
'articles'=> tableau (
tableau(
'titre' => 'Commande payée avec succès', >'description'
. "Numéro de commande WeChat : {$bdata['transaction_id']}n"
'picurl' => 🎜>,
'url' =>
)
)
);
//Envoyer une notification de paiement WeChat
$this->sendCustomMessage($news > }else
{}
/**
* Page de réussite du paiement
* Rappels peu fiables
*/
fonction ajax_PaySuccess(){
//Numéro de commande
= I('post.out_trade_no'
);//Montant du paiement total_fee = I(
); /*Traitement logique associé*/
html
tête
méta http-equiv="content-type" content="text/html;charset=utf-8" />
méta nom="viewport" contenu="width= largeur de l'appareil, initial-scale=1"/>
< ;titre>微信支付样例-支付titre >
script type= "text/javascript">
//Appelez le paiement de l'API WeChat JS
fonction jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{$jsApiParameters},
fonction(res){
WeixinJSBridge.log( res.err_msg);
//Annuler le paiement
si( res.err_msg == 'get_brand_wcpay_request:cancel'){
//Logique d'événement pour le traitement de l'annulation du paiement
}else if(res.err_msg == "get_brand_wcpay_request: ok"){
/*Utilisez la méthode ci-dessus pour déterminer le retour frontal. L'équipe WeChat rappelle solennellement :
res. .err_msg sera utilisé lorsque l'utilisateur paie. Retourne ok après succès, mais cela ne garantit pas qu'il est absolument fiable
Ici, vous pouvez utiliser Ajax pour soumettre l'arrière-plan et traite certains journaux, tels que ajax_PaySuccess dans la méthode du contrôleur de test
*/
);
}
fonction callpay()
{
si (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}else if (document.attachEvent){
document.attachEvent(' WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}autre{
jsApiCall();
}
}
//获取共享地址
fonction editAddress()
{
WeixinJSBridge.invoke(
'editAddress',
{$editAddress},
fonction(res){
var value1 = res.proviceFirstStageName;
var value2 = res.addressCitySecondStageName;
var value3 = res.addressCountiesThirdStageName;
var value4 = res.addressDetailInfo;
var tel = res.telNumber;
alerte(valeur1 + valeur2 + valeur3 + valeur4 + ":" + tel);
}
);
}
window.onload = fonction(){
if (typeof WeixinJSBridge == "undefined"){
if( document. addEventListener ){
document.addEventListener('WeixinJSBridgeReady', editAddress, false);
}else if (document.attachEvent){
document.attachEvent(' WeixinJSBridgeReady', modifierAdresse);
document.attachEvent('onWeixinJSBridgeReady', editAddress);
}
}autre{
modifierAdresse();
}
} ;
script>
tête >
corps >
br/>
police couleur= "#9ACD32">b>Le montant du paiement pour cette commande est de span style="couleur:#f00;font-size:50px " >1 pointspan>argent b>font>br/>br/>
p aligner= "centre">
bouton style="width:210px; height:50px; border-radius : 15px;background-color:#FE6714; border : onclick="callpay()" >立即支付bouton> p
corps>
html>
Code du fichier notify.php, voici une méthode personnalisée nouvellement ajoutée dans le fichier officiel.
[php] vue simple copie
require_onceROOT_PATH."Api/lib/WxPay.Api.php"; >require_once
ROOT_PATH.require_once
ROOT_PATH.>;
//初始化日志
$logHandler= nouveau CLogFileHandler(ROOT_PATH." /logs/".date('Y-m-d'). '.log');
$log = Log::Init($logHandler, 15 );
classe PayNotifyCallBack étend WxPayNotify
{
protégé $para = array ('code'=>0,'data'=>'' );
//查询订单
public function Queryorder($transaction_id)
{
$input = nouveau 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"] == " SUCCÈS"
&& $result["result_code "] == "SUCCÈS")
{
retour vrai ;
}
$this->para['code'] = 0;
$this->para['données'] = '';
retour faux; 🎜>
//Réécrire la fonction du gestionnaire de rappel
public fonction NotifyProcess($data, &$msg)
"appel retour : " .json_encode($data));
$notfiyOutput = tableau();
if(!array_key_exists("transaction_id", $data)){
$msg = "Les paramètres d'entrée sont incorrects"
$this->para['code'] = 0;
$this->para['données'] = '';
retour faux; 🎜>
//Interroger la commande pour déterminer si la commande est authentique Sexe
if(!$this->Queryorder($ données["transaction_id"])){
$msg = "Échec de la requête de commande"
$this->para['code'] = 0;
$this->para['data'] = ''
retour faux; > }
$this
'code'] = 1
$this->para['data'] = $données; 🎜>
/**
* Méthode personnalisée pour détecter si le rappel sur WeChat réussit
* @return multitype:chaîne numérique
*/
fonction IsSuccess(){
retourner $this->para
}C'est fondamentalement terminé, vous pouvez ouvrir http://test.paywechat sur WeChat com/Charge/index.php/Test/index/Related. recommandations :
Explication détaillée de l'implémentation nodejs de l'exemple de fonction de paiement WeChat
Thinkphp intègre la fonction de paiement WeChat
Comment ajouter cette fonction de paiement WeChat au site Web du PC
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!