
ドキュメント:https://pay.weixin.qq.com/wiki/doc/api/index.html
SDK:[https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1
](https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1)JSAPI
決済は、WeChat内のブラウザで開くことでWeChat Payを起動できます。効果は以下の図の通りです。

{$competition\['username'\]}
JavaScript:
// 投票 var offset = {$activity[‘offset’]}; $(’#tips’).html(‘正在给{$competition[‘code’]}号赠送{$prices[0]}钻=’+({$prices[0]}*offset)+‘票’); $(’#vote’).click(function(){ $.post(’/index/index/detailed.html?cid={$cid}&aid={$aid}’,{ formhash :’{FORMHASH}’, submit:‘1’, type:1, openid:’{$_G[‘member’][‘openid’]}’ },function(res){ alert(res.msg); if (res.code == 0) { $(’.box-1 span’).text(res.data.all); $(’.box-2 span’).text(res.data.rank); $(’.box-3 span’).text(res.data.up + ‘票’); } }); }) /* jQuery对象级别プラグイン拡張 */ $.fn.extend({ /* 単選框 */ hlRadio:function () { var radioEl=$(this); radioEl.click(function () { var price = 0; price = $(‘input:radio:checked’).val(); $(’#price’).val(’’); $(’#tips’).html(‘正在给{$competition[‘code’]}号赠送’+price+‘钻=’+(price*offset)+‘票’); radioEl.siblings(“div”).removeClass(“active”); $(this).siblings(“div”).addClass(“active”); }); }, }); $(“input[name=‘price’]”).hlRadio(); $(’#price’).bind(‘input propertychange’, function(){ var price = 0; price = $(’#price’).val(); $(’#tips’).html(‘正在给{$competition[‘code’]}号赠送’+price+‘钻=’+(price*offset)+‘票’); })
CSS部分
.ul_box { margin:0 auto; padding:0; list-style:none; width: 344px; } .ul_box>li { padding:10px 10px 0 10px; overflow:hidden; border-bottom:#e5e5e5 solid 1px; } .ul_box>li:last-child { border-bottom:none; } .ul_box>li>div { float:left; } .ul_box>li>div:nth-child(1) { width:100px; } .ul_box>li>div:nth-child(2) { width:480px; overflow:hidden; } .label_box>label { display:block; float:left; margin:0 10px 10px 0; position:relative; overflow:hidden; } .label_box>label>input { position:absolute; top:0; left:-20px; } .label_box>label>div { width:100px; text-align:center; border:#dddddd solid 1px; height:40px; line-height:40px; color:#666666; user-select:none; overflow:hidden; position:relative; height: 75px; } .label_box>label>div.active{ border:#d51917 solid 1px; background-color: #fff9f8; color:#d51917; } .label_box>label>div.active:after { content:’’; display:block; width:20px; height:20px; background-color:#d51917; transform:skewY(-45deg); position:absolute; bottom:-10px; right:0; z-index:1; } .label_box>label>div.active:before { content:’’; display:block; width:3px; height:8px; border-right:#ffffff solid 2px; border-bottom:#ffffff solid 2px; transform:rotate(35deg); position:absolute; bottom:2px; right:4px; z-index:2; } .input{ height: 75px!important; border: 1px solid #DDD!important; position: initial!important; width: 100px!important; text-align: center!important; padding: 5px!important; font-size: 19px!important; } .am-modal-bd{ border-bottom: none; margin-top: 20px; } .am-modal-bd img{ width: 50px; border-radius: 50px; } .am-icon-diamond{ font-size: 20px; display: block; text-align: center; margin-bottom: -7px; }
WeChat Payを起動します。ここのjsコードはWeChatモバイルブラウザでのみ有効です。
//调用微信JS api 支付 function jsApiCall(appId,timeStamp,nonceStr,package,signType,paySign) { WeixinJSBridge.invoke( ‘getBrandWCPayRequest’,{ “appId”:appId, //公众号名称,由商户传入 “timeStamp”:timeStamp, //时间戳,自1970年以来的秒数 “nonceStr”:nonceStr, //随机串 “package”:package, “signType”:signType, //微信签名方式: “paySign”:paySign //微信签名 }, function(res){ if(res.err_msg == “get_brand_wcpay_request:ok” ){ WeixinJSBridge.log(res.err_msg); alert(‘投票成功’); // window.history.go(-1); var url = ‘/index/index/detailed.html?cid={$cid}&aid={$aid}’; window.location.href=url; // location.reload(); return false; } alert(‘投票失敗’); } ); } // 支付 function callpay() { var price = ‘’; if ($(’#price’).val()) { price = $(’#price’).val(); }else if($(‘input:radio:checked’).val()){ price = $(‘input:radio:checked’).val(); }else{ alert(‘購入数量を入力してください’); } if (Number(price) <= 0) { alert(‘0より大きい正の数を入力してください’); $(’#price’).val(’’); return false } $.post(’/index/index/weixin.html?cid={$cid}&aid={$aid}’,{ formhash :’{FORMHASH}’, submit:‘1’, type:1, pay:1, price: price, openid:’{$_G[‘member’][‘openid’]}’ },function(res){ if (res.code ==0) { jsApiCall( res.data.appId, res.data.timeStamp, res.data.nonceStr, res.data.package, res.data.signType, res.data.paySign, ); }else{ alert(res.msg); } }); // if (typeof WeixinJSBridge == “undefined”){ // if( document.addEventListener ){ // document.addEventListener(‘WeixinJSBridgeReady’, jsApiCall, false); // }else if (document.attachEvent){ // document.attachEvent(‘WeixinJSBridgeReady’, jsApiCall); // document.attachEvent(‘onWeixinJSBridgeReady’, jsApiCall); // } // }else{ // } }
インターフェースはMeizi UIに基づいており、効果は以下の図の通りです。

//①、ユーザーのopenidを取得 $tools = new JsApiPay(); $openid = $tools->Getopenid(); //既に持っている場合は直接代入可能 //②、統合注文 $input = new WxPayUnifiedOrder(); $input->SetBody(“ダイヤモンドチケットを購入”); $input->SetAttach(json_encode([ //追加パラメータ ‘order’ => $order_id, ‘cid’ => $cid, ‘uid’ => $_G[‘uid’], ‘aid’ => $aid, ‘md5’ => $md5 ])); $input->SetOut_trade_no(WxPayConfig::MCHID.date(“YmdHis”)); $input->SetTotal_fee($price); //価格、単位は分、「元は*100を忘れずに」 $input->SetTime_start(date(“YmdHis”)); $input->SetTime_expire(date(“YmdHis”, time() + 600)); $input->SetGoods_tag(“test”); $input->SetNotify_url(WX_NOTIFY_URL); $input->SetTrade_type(“JSAPI”); $input->Setopenid($openid); $order = WxPayApi::unifiedOrder($input); $jsApiParameters = $tools->GetJsApiParameters($order); //ローカルオーダーを保存 DB::insert(‘vote_order’, [ ‘order’ => $order_id, ’time’ => time(), ‘price’ => intval($_GET[‘price’]), ‘uid’ => $_G[‘uid’], ‘openid’ => $openid, ‘ip’ => $ip ]); Json([‘code’ => 0, ‘msg’ => ‘成功’,‘data’ => json_decode($jsApiParameters,true)]); //共有配送先住所js関数パラメータを取得 // $editAddress = $tools->GetEditAddressParameters(); // debug($jsApiParameters); //③、支払い成功コールバック通知で成功後の処理を行う。notify.phpを参照 /** * 注意: * 1、コールバックアドレスにアクセスできない場合、コールバック通知は失敗します。注文を照会して支払いが成功したか確認できます。 * 2、jsapi支払い時にはユーザーのopenidを入力する必要があります。WxPay.JsApiPay.phpにopenid取得フローがあります(ドキュメントはWeChat公式プラットフォームの「ウェブページ認証インターフェース」を参照できます。 * 参照:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html) */
SetReturn\_code("FAIL"); $this->SetReturn\_msg($msg); $this->ReplyNotify(false); return; } else { //このブランチはNotifyCallBackメソッドへの成功コールバックで、処理完了後のフローです。 $attach = json\_decode($msg\['attach'\], true); // file\_put\_contents('aaaa.txt',print\_r($attach,true)); $cid = $attach\['cid'\]; $aid = $attach\['aid'\]; $uid = $attach\['uid'\]; $order = $attach\['order'\]; $md5 = $attach\['md5'\]; $vote\_order = DB::fetch\_first("SELECT \* FROM " . DB::table('vote\_order') . " WHERE \`order\`='{$order}' and status = 0"); if (!$vote\_order) { $this->SetReturn\_code("SUCCESS"); $this->SetReturn\_msg("OK"); } $sign\_md5 = md5($vote\_order\['openid'\] . $vote\_order\['order'\] . $vote\_order\['uid'\] ); if ($sign\_md5 == $md5) { // すべての活動情報 $activity = DB::fetch\_first("SELECT \* FROM " . DB::table('vote\_activity') . " WHERE aid={$aid} "); $ip = $vote\_order\['ip'\]; $jewel\_vote = $vote\_order\['price'\] \* $activity\['offset'\]; // 投票 DB::query("UPDATE \`pre\_vote\_competition\` SET \`jewel\`=jewel+{$vote\_order\['price'\]},jewel\_vote=jewel\_vote+{$jewel\_vote} WHERE (\`cid\`='{$cid}')"); // 投票記録を追加 DB::insert('vote\_record',\[ 'time' => TIMESTAMP, 'openid' => $vote\_order\['openid'\], 'type' => 1, 'aid' => $aid, 'cid' => $cid, 'ip' => $ip, 'price' => $vote\_order\['price'\], 'jewel\_vote' => $jewel\_vote, 'uid' => $uid, 'order' => $vote\_order\['order'\] \]); // 注文ステータスを更新 DB::query("UPDATE \`pre\_vote\_order\` SET \`status\` = 1 WHERE \`order\`={$order}"); // 活動の総収益を更新 DB::query("UPDATE \`pre\_vote\_activity\` SET \`profit\`=profit+{$vote\_order\['price'\]} WHERE \`aid\`={$aid}"); } $this->SetReturn\_code("SUCCESS"); $this->SetReturn\_msg("OK"); } $this->ReplyNotify($needSign); } /\*\* \* \* コールバックメソッドエントリ、サブクラスはこのメソッドをオーバーライドできます。 \* 注意: \* 1、WeChatコールバックのタイムアウトは2秒です。ユーザーは非同期処理フローを使用し、成功を確認したらすぐにWeChatサーバーに返信することをお勧めします。 \* 2、WeChatサーバーは、呼び出しが失敗した場合、または非確認パッケージを受信した場合、再試行を開始します。コールバックが再入可能であることを確認する必要があります。 \* @param array $data コールバックで解析されたパラメータ \* @param string $msg コールバック処理が失敗した場合、エラーメッセージをこのメソッドに出力できます。 \* @return true コールバック処理が完了し、これ以上コールバックする必要がない場合、false コールバック処理が未完了で、引き続きコールバックする必要がある場合 \*/ public function NotifyProcess($data, &$msg) { //TODO ユーザーがこのクラスを継承した後、このメソッドをオーバーライドする必要があります。成功した場合はtrue、失敗した場合はfalseを返します。 return true; } /\*\* \* \* notifyコールバックメソッド、このメソッドでは出力するパラメータに値を割り当てる必要があります。オーバーライドできません。 \* @param array $data \* @return true コールバック処理が完了し、これ以上コールバックする必要がない場合、false コールバック処理が未完了で、引き続きコールバックする必要がある場合 \*/ final public function NotifyCallBack($data) { $msg = "OK"; $result = $this->NotifyProcess($data, $msg); if ($result == true) { $this->SetReturn\_code("SUCCESS"); $this->SetReturn\_msg("OK"); } else { $this->SetReturn\_code("FAIL"); $this->SetReturn\_msg($msg); } return $result; } /\*\* \* \* 通知に返信 \* @param bool $needSign 署名出力が必要かどうか \*/ final private function ReplyNotify($needSign = true) { //署名が必要な場合 if ($needSign == true && $this->GetReturn\_code($return\_code) == "SUCCESS") { $this->SetSign(); } WxpayApi::replyNotify($this->ToXml()); } } コールバッククラスの呼び出し Handle(false); 注意:WeChat PayはバックエンドでWeChat Pay認証ディレクトリを設定する必要があります。APPIDなどのパラメータはWeChat Payバックエンドで取得できます。 WeChat公式アカウント情報設定 APPID:支払いと紐付けられたAPPID(必須設定、開設メールで確認可能) MCHID:加盟店番号(必須設定、開設メールで確認可能) KEY:加盟店支払いキー、開設メールの設定を参照(必須設定、加盟店プラットフォームにログインして自分で設定) 設定アドレス:[https://pay.weixin.qq.com/index.php/account/api\_cert](https://pay.weixin.qq.com/index.php/account/api_cert) APPSECRET:公式アカウントのsecert(JSAPI決済の場合のみ設定が必要、公式プラットフォームにログインし、開発者センターで設定可能) 取得アドレス:[https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh\_CN](https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN) 