まず: JSAPI有料 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1
使用シナリオ:JSAPI商人の決済手段マイクロチャネルインターフェイスコールJSAPIの支払プロバイダを介して、代金回収を完了するために、マイクロチャネルモジュールを呼び出す支払いシナリオ
例A:例B次の行:いいえ公共シーンC:PCサイトシーン
A: B: C:
JSAPIの支払い命令
<?phpの 名前空間のApp \のHttp \コントローラ\ APIを。 App \アピ\ヘルパー\ MoveNumberを使用します。 使用のApp \のHttp \コントローラ\コントローラ。 使用のApp \のHttp \ミドルウェア\ ApiLog。 App \モデル\ MShopOrdersを使用します。 照らし\のHttp \要求を使用します。 照らし\サポート\ファサード\ DBを使用します。 照らし\サポート\ファサード\バリデータを使用します。 EasyWeChat \ファクトリーを使用します。 / ** *订单 * * / クラスNotifyControllerはコントローラ{延び MoveNumberを使用します。 / ** *支付回调 * * / パブリック関数のnotify_wx() { writeLogs([]、 '已进入到微信回调'、 '通知'); //写入日志记录 $ notify_data =のfile_get_contents( "PHP://入力"); notify_data =の$ this - $> from_xml($ notify_data); writeLogs($ notify_data、 'コールバックの戻りデータ'、 '通知'); //書き込みログレコード (!$ notify_data){IF ($「、notify_data writeLogsは受信されません情報''通知'); //書き込みログ・レコード $ notify_data = $ GLOBALS [' HTTP_RAW_POST_DATAれる] :? ''; } //テスト確認する $ return_data =の$ this - > query_weixin_sign($)notify_dataを、 IF( !$ return_data){ writeLogs($ notify_data、 '通知'、 '失敗したテストを確認してください'); //書き込みログ・レコードは '失敗'エコー; ダイ; } writeLogs($ notify_data、 ' -によってスタンプ'、 ')通知' ; //書き込みログレコード IF($ [ 'RETURN_CODE'] == 'SUCCESS' && $ notify_data notify_data [ 'RESULT_CODE'] == 'SUCCESS'){ $ ORDER_ID = $ notify_data [ 'out_trade_no']。 $ check_data = MShopOrders ::ここで、([ 'order_sn' => $ ORDER_ID]) - >最初の()。 IF($ check_data [ 'ステータス'] == 0){ //事务开启 DB ::のbeginTransaction(); {試みる //更改订单状态 $結果= MShopOrders ::ここで、([ 'order_sn' => $ ORDER_ID]) - >更新([ 'ステータス' => 1])。 (!$結果){もし DB :: ROLLBACK(); move_order_id =の$ this - $> make_phone_order($ ORDER_ID); IF($ move_order_id == -1){ DB :: ROLLBACK(); スロー新しい新\ LogicException(201、 '注文番号が失敗したキャンプを作成した'); } //特許更新正常キャンプ注文 $ :: WHERE MShopOrders RES =([ 'order_sn' => $ ORDER_ID]) - >更新([ 'order_operator' => $ move_order_id]); IF(!RES $){ DB :: ROLLBACK(); スロー新しい新\ LogicException( '在圏更新番号順に失敗しました'、202); } DB ::(コミット); エコー'成功'。 ; キャッチ}(\例外$ E){ writeLogs($、notify_data "コールバックの支払いの更新が失敗し、失敗コード:" $ E->にgetCode。 () " 失敗したメッセージ:" .. $ E->のgetMessage()、「通知'); //書き込みログが記録 DBを:: ROLLBACK(); エコー'失敗「; ダイ; } } エコー"成功"; ダイ; } } / ** *署名を生成-このメソッドをオーバーライドする * @param配列$コンフィギュレーション・オブジェクト・データ * * @returnフロート * / パブリック関数query_weixin_sign($データ) { $ CONFIG = wxconfig( "wechat.payment.default")。 //署名ステップ1:辞書式ソートパラメータを押します ksort($データ); ; = $ $ checkSignデータ[ 'ログイン'] の設定を解除($データ[ 'ログイン']); $文字列=の$ this - > to_url_params($データ); //署名ステップ2:文字列KEY追加 $文字列$ = "&キー=" $ wxconfig [ 'キー']; ... //署名ステップ3:MD5暗号化またはSHA256 HMAC IF(strlenを($ checkSign)<= 32){ //署名未満である場合32に等しい、検証するために使用されているMD5 $ MD5 =文字列(文字列$); }他{ //チェックがSHA256ある $文字列= hash_hmac( "SHA256"、文字列$、$ wxconfig [ 'キー']); } / /署名ステップ4:すべての文字を大文字に $結果= strtoupper($文字列) 。 writeLogs([ '記号' => $結果、 'checksign' => $ checkSign]、 ' コールバックデータ署名検証'、 '通知'); //書き込みログレコード / ** * urlパラメータは、書式設定パラメータにフォーマット * @param配列$件のデータパラメータ {($ == $ checkSignを引き起こす)場合は trueを返します。 }他{ falseを返します。 } } パブリック関数from_xml($ XMLを) { するif($ xmlの!){ エコー"XML数据异常!"。 } //将XML转为アレイ禁止引用外部XML实体 libxml_disable_entity_loader(TRUE)。 $データ= json_decode(json_encode(simplexml_load_string($ xmlの'のSimpleXMLElement'、LIBXML_NOCDATA))、真の); $データを返します。 } * * @return文字列 * / プライベート関数to_url_params($ DATAS) { $バフ= ""; {foreachの($ K => $ Vとして$件のデータ) の場合($ K!= "記号" && V $!= "" &&!IS_ARRAY($ V)){ $バフ。= $ K。"="。$ V。"&"; } } $バフ=( "&"、$バフ)をトリム。 $バフを返します。 } }
まず、シナリオと記述の使用
使用シナリオ:商人はH5モールサイト、メッセージまたはあなたがマイクロ手紙の中でページを開き、二次元コードのスキャンを介してユーザを持っているが、あなたは下の単一の購入の支払いを完了するために、マイクロチャネルの流れを呼び出すことができます。
説明:グラフィックユーザーがメッセージを開くか、2次元コード、内蔵のブラウザマイクロチャネルでのお支払い開いているページをスキャンします。
手紙、通話マイクロチャネル支払いモジュールが提供するマイクロビジネスのWebフロントエンドを使用することによりJSAPI 2。このように、ビジネスのページで購入プロセスのための発注書が必要とされています。
第二に、仕事の準備
何の設定を含むマイクロチャネルの公共プラットフォームサービスの構成で事前に有料の公共のニーズ、支払い承認のディレクトリを、支払ったディレクトリをテストし、ホワイトリストには、設定されていないJSポートセキュリティドメインをし、承認コールバック・ページのドメインを設定します。
1.公共マイクロチャネル支払い前に、我々は公共の番号を申請する必要があり、および機能は、マイクロチャネルの賃金を要求します。
2.支払認証ディレクトリ:
場所:マイクロチャンネル有料 - >開発設定 - 公衆の>数
1)公共の支払いを使用しているすべての数字は、支払い要求リンクアドレスを開始し、ディレクトリの権限の下で支払われなければなら。
2)3許可されたディレクトリをテストするために設定したディレクトリ、およびドメイン名に設定公式支払い承認は、ICPにより提出しなければならない。今まで==「アップ(2017年11月15日)支払認証ディレクトリの設定はに移動されました
マーチャントプラットフォーム - >製品の展示 - >開発構成(ポータル:?HTTPS:= 7_3 //pay.weixin.qq.com/wiki/doc/api/jsapi.php章)、そして同時に5まで設定することができますディレクトリ
ディレクトリの例:
|||||||| なし認証ディレクトリの場合やない、電話は、マイクロチャネルJSAPIエラーを呼び出すとき:
3)ヘッダHTTPまたはHTTPSを含むこと、および第二級または第三級ディレクトリに精製されなければならない、「/」左端スラッシュ。
支払いを開始するビジネスでのページアドレスは、それ以外の場合は、単一のインターフェイスを呼び出すとき、「現在のページのURLが登録されていない」プロンプトが表示されます、ディレクトリの権限の下でなければなりません。
ここで再び2点を追加するために、長いったらしいです:
// WWW×××.COM /デモ:1)などの公式SDKのデモのルートディレクトリにダウンロードし、デモ/例/ jaspi.phpは、authorizeカタログとしてのフレームワークを使用し、せずにHTTPを参照してください。 /例/
2)ThinkPHP、名前の試験項目、ディレクトリ構造、テスト/アプリケーション/ホーム/コントローラ/ WxpayController.class.php、許可されたディレクトリは、HTTPを参照することができるフレームワークを使用した場合、:// WWW×××.COM /を。 index.phpを/ホーム/ Wxpay /
3. セキュリティドメインインターフェースJS:
場所:マイクロチャンネル有料 - >公共号[設定] - > [機能設定] - > [JSインターフェイスセキュリティドメイン
説明:JSポートセキュリティドメインを設定した後、国民はJSの数の開発者は、このドメイン内のオープンインタフェースを微信呼び出すことができます。
注意事項:
1) 可填写三个域名,要求是一级或一级以上域名(例:qq.com,或者 www.qq.com ),需使用字母、数字及“-”的组合,不支持IP地址及端口号;
2) 填写的域名须通过ICP备案的验证;
3)一个自然月内最多可修改并保存三次。
4.授权回调页面域名:(用来jsapi支付的必须)
位置:微信支付——>接口权限——>网页授权获取用户基本信息
用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。
注意事项:
1) 回调页面域名需使用字母、数字及“-”的组合,不支持IP地址及端口号。填写的域名需与实际回调URL中的域名相同;
2) 填写的域名须通过ICP备案的验证。
获取用户授权时redirect_uri对应的URL必须在此域名下,否则回调的地址会无法打开。
三、开发步骤
说明:整个微信公众号支付的流程如下:
【1】用户点击公众号内微信商城打开H5的支付页面
【2】H5页面通过JS调用微信支付接口
【3】微信服务器通过判断输入的JSON数据,返回给客户端相应的成功或失败信息
官方demo结构如下:
1.JSAPI支付——H5网页端调起支付接口
1)用户同意授权,获取code
请求链接:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#we-chat_redirect
2)如果有code,直接就通过code能获取用户openid
如果没有code,通过createOauthUrlForCode方法,传入必要参数,获取code
3)如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。
若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数
redirect_uri?state=STATE
4)code说明以及scope的两种方式说明
【1】code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
这里获取到code 和 state(订单号) 后, 对订单进行验证,用户余额也进行验证,如果条件都满足则才能进行下面的流程。
【2】scope的两种方式说明:
微信提供了两种授权方式:snsapi_base和snsapi_userinfo。
snsapi_base:不弹出授权页面,直接跳转,只能获取用户openid;
snsapi_userinfo:弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息。
想要获取code,需要构造如下地址:
2. 通过code换取网页授权access_token (这里也获取到了openid)
1)请求链接:https://api.weixin.qq.com/sns/oauth2/access_token
?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
2)获取openid:openid是微信支付jsapi支付接口必须的参数
【1】如果网页授权的作用域为snsapi_base(静默授权),则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。
【2】如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。
3)getOpenid方法中调用createOauthUrlForOpenid方法获取openid
3. 调用统一支付接口获取预付款id (这里有个小技巧:你如果直接把表单提交到这里,那就傻逼了。 你的服务器会和微信服务器交互2次,等拿到openid,你提交的数据早就被刷掉了,你可以把它放在session或者缓存里面,然后重定向到下面这个页面,等拿到openid后再从session里面拿数据。)
官方文档说明:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
1) 设置必传参数,按照签名参数产生签名, 此时参与签名字段有 : appid, mch_id , nonce_str, openid, body , out_trade_no, total_fee, notify_url , trade_type
2) 将必传参数转成xml,createXml方法。
3) 使用xml,请求统一支付接口 https://api.mch.weixin.qq.com/pay/unifiedorder
4) 得到xml格式的返回值结果
5) 将结果转成数组,获取预支付id
4. 使用jsapi调起支付
1. 通过getParameters方法设置必传参数,接口输入数据为json
2. 根据官方demo中jsapi.php 调起支付,得到支付结果
注:使用以上方式判断前端返回,res.err_msg 将在用户支付成功后返回 ok,但不保证它绝对可靠。
四、可能遇到的问题
1. 返回参数是xml,而不是直接输出success ,这个与微信app支付有区别。
2. 参与签名字段要保证一致,保证前后签名一样。
3. 由于存在重新发送后台通知的情况,因此同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。比如在支付成功后写入了支付日志,那么第二次回调前前判断是否已经有了支付日志,如果有,直接退出不作处理就好了。
4 . 当用户有余额,先用余额支付,剩下的才是微信 , 支付成功时,回调扣去余额
5. 如果同一笔订单号修改多次价格进行支付,第二次支付时,会出现生成预支付订单失败,主要原因是同一笔订单支付时,支付金额不能一样,或者给到第三方的订单号不一样,所以解决方法就是订单号+标志位(比如Z或A)+ 时间戳生成给到的第三方的支付号即可。