この記事は主にWeChat決済の開発プロセスに関する関連情報を紹介していますので、必要な友人は参考にしてください
私がWeChatオープンプラットフォームで決済を使用していることに注意してください。これはモバイルアプリに関連しており、それとは何の関係もありません。公開アカウント。
WeChat決済の主な操作プロセス
1. ユーザーはアプリを閲覧し、商品を選択し、注文します。
2. サーバーは注文ロジックを処理し、正式な支払いプロセスを開始します。
3. まず、バックエンド サーバーがトークンを取得するためのリクエストを weixin サーバーに開始します。
4. バックグラウンドサーバーはトークンを取得し、他のパラメーターで暗号化し、前払い ID を取得するリクエストを再度送信します
6。アプリは携帯電話の WeChat
controlを呼び出して支払いプロセスを完了します。 7.app はバックエンド サーバーへのコールバック リクエストを開始し、トランザクションが完了したことをサーバーに通知します。
8. weixin サーバーはすべてのプロセスを処理した後、バックエンド サーバーに対して
post リクエストを開始し、トランザクションが完了したことをバックエンド サーバーに正式に通知します
上記のプロセスで注意すべき点がいくつかあります:1. 毎回取得されるトークンは時間に依存しており、デフォルトは 7200 秒で、1 日に最大 200 回取得できるため、
redisに入れてキャッシュ するのが最善です。有効期限が切れたら再度取得します2. アプリによって開始されたコールバックは、デフォルトでは信頼できません。バックエンドは、このトランザクションの結果を確認するために WeChat サーバーへの注文クエリ
を開始するために最善を尽くす必要があります。 。3. Weixin サーバーによってバックグラウンドで開始される notif
y は、トランザクションの完了を確実にするための最後の障壁です。バックグラウンド サーバーは確認後に「成功」を返す必要があります。そうでない場合、weixin サーバーはリクエストの再送信を試みます。このステップは非常に簡単で、取得リクエストを送信するだけです。正しいパラメータを設定するだけです。
‘‘‘从微信服务器获取token‘‘‘ def _getAccessTokenFromWeixin(self): response = requests.get(self.tokenUrl % (self.appId, self.appSecret)) if response.status_code == 200: text = response.text tokenInfo = json.loads(text) try: token = tokenInfo[‘access_token‘] expires_in = tokenInfo[‘expires_in‘] self._writeWeixinTokenLog(token, self.order_no) return token except KeyError: return None #token获取失败 return None #http请求失败
prepayidを取得する
WeChat Payの開発プロセスで最も面倒なことは、prepayidを取得することです。
このステップでは、次のようなパラメーターを組み立てる必要があります:{ "appid":"wxd930ea5d5a258f4f", "traceid":"test_1399514976", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb ", "timestamp":1399514976, "package":"bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF% 95&fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_ no=7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1& total_fee=1&sign=7F77B507B755B3262884291517E380F8", "sign_method":"sha1", "app_signature":"7f77b507b755b3262884291517e380f8" }
パッケージの組み立て
ここでの最初のステップは、パッケージを組み立てることです:
"package":"bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF% 95&fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_ no=7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1& total_fee=1&sign=7F77B507B755B3262884291517E380F8",
md5 で署名され、この時点で大文字に変換されます。署名を取得します
次に、すべてのパラメータの値を URLencode し、後でそれらを結合します。sign=signValue で、パッケージ文字列を取得します。def createMD5Signature(self, signParams): ‘‘‘先排序‘‘‘ sortedParams = sorted(signParams.iteritems(), key=lambda d:d[0]) ‘‘‘拼接‘‘‘ stringSignTemp = "&".join(["%s=%s" % (item[0], item[1]) for item in sortedParams if item[0] != ‘sign‘ and ‘‘ != item[1]]) #加上财付通商户权限密钥 stringSignTemp += ‘&key=%s‘ % (self.partnerKey) #使用MD5进行签名,然后转化为大写 stringSign = hashlib.md5(stringSignTemp).hexdigest().upper() #Upper return stringSign
def getPackage(self, packageParams): ‘‘‘先获取params的sign,然后将params进行urlencode,最后拼接,加上sign‘‘‘ sign = self.createMD5Signature(packageParams) packageParams = sorted(packageParams.iteritems(), key=lambda d:d[0]) stringParams = "&".join(["%s=%s" % (item[0], urllib.quote(str(item[1]))) for item in packageParams]) stringParams += ‘&sign=%s‘ % (sign) return stringParams
パラメータのアセンブルを続けます
パッケージを取得した後、パラメーターを組み立てます:ここで必要なパラメーター:
appid=wxd930ea5d5a258f4f appkey=L8LrMqqeGRxST5reouB0K66CaY A WpqhA Vsq7ggKkxHCOastWksvuX1uvmvQcl xaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K noncestr=e7d161ac8d8a76529d39d9f5b4249ccb package=bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF%95 &fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_no =7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1&tot al_fee=1&sign=7F77B507B755B3262884291517E380F8 timestamp=1399514976
ここには落とし穴があることに注意してください:
上記のパラメーターは署名
に含まれますが、最後のパラメーターは含まれませんappKey を含めてください。署名後は必ず
してください。
1. すべてのパラメータを辞書編集順に並べ替えて連結します 2. sha1 署名を実行し、それを上記の文字列の末尾に結合します
3. ここで appKey を削除してから、記号を追加する必要があることに注意してくださいsha1 署名コードを取得するには次のようにします:
def createSHA1Signature(self, params): ‘‘‘先排序,然后拼接‘‘‘ sortedParams = sorted(params.iteritems(), key=lambda d:d[0]) stringSignTemp = "&".join(["%s=%s" % (item[0], item[1]) for item in sortedParams]) stringSign = hashlib.sha1(stringSignTemp).hexdigest() return stringSign
{ "appid":"wxd930ea5d5a258f4f", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb", "package":"Sign=WXpay"; "partnerid":"1900000109" "prepayid":"1101000000140429eb40476f8896f4c9", "sign":"7ffecb600d7157c5aa49810d2d8f28bc2811827b", "timestamp":"1399514976" }
‘‘‘获取预支付prepayid‘‘‘ def gerPrepayId(self, token, requestParams): ‘‘‘将参数,包括package,进行json化,然后发起post请求‘‘‘ data = json.dumps(requestParams) response = requests.post(self.gateUrl % (token), data=data) if response.status_code == 200: text = response.text text = json.loads(text) errcode = text[‘errcode‘] if errcode == 0: return text[‘prepayid‘] return None
プリペイドID取得する形式は次のようになります: { "prepayid":"1101000000140429eb40476f8896f4c9","errcode":0,"errmsg":"Success"}
再度署名します
ここでは、上記の sha1 署名メソッドを使用して、再度署名し、次のパラメータを取得します:{ "appid":"wxd930ea5d5a258f4f", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb", "package":"Sign=WXpay"; "partnerid":"1900000109" "prepayid":"1101000000140429eb40476f8896f4c9", "sign":"7ffecb600d7157c5aa49810d2d8f28bc2811827b", "timestamp":"1399514976" }
‘‘‘接收app的请求,返回prepayid‘‘‘ class WeixinRequirePrePaidHandler(BasicTemplateHandler): ‘‘‘这个方法在OrdersAddHandler中被调用‘‘‘ @staticmethod def getPrePaidResult(order_no, total_pay, product_name, client_ip): ‘‘‘封装了常用的签名算法‘‘‘ weixinRequestHandler = WeixinRequestHandler(order_no) ‘‘‘收集订单相关信息‘‘‘ addtion = str(random.randint(10, 100)) #产生一个两位的数字,拼接在订单号的后面 out_trade_no = str(order_no) + addtion order_price = float(total_pay) #这里必须允许浮点数,后面转化成分之后转化为int #order_price = 0.01 #测试 remote_addr = client_ip #客户端的IP地址 print remote_addr current_time = int(time.time()) order_create_time = str(current_time) order_deadline = str(current_time + 20*60) ‘‘‘这里的一些参数供下面使用‘‘‘ noncestr = hashlib.md5(str(random.random())).hexdigest() timestamp = str(int(time.time())) pack = ‘Sign=WXPay‘ ‘‘‘获取token‘‘‘ access_token = weixinRequestHandler.getAccessToken() logging.info("get token: %s" % access_token) if access_token: ‘‘‘设置package参数‘‘‘ packageParams = {} packageParams[‘bank_type‘] = ‘WX‘ #支付类型 packageParams[‘body‘] = product_name #商品名称 packageParams[‘fee_type‘] = ‘1‘ #人民币 fen packageParams[‘input_charset‘] = ‘GBK‘ #GBK packageParams[‘notify_url‘] = config[‘notify_url‘] #post异步消息通知 packageParams[‘out_trade_no‘] = str(out_trade_no) #订单号 packageParams[‘partner‘] = config[‘partnerId‘] #商户号 packageParams[‘total_fee‘] = str(int(order_price*100)) #订单金额,单位是分 packageParams[‘spbill_create_ip‘] = remote_addr #IP packageParams[‘time_start‘] = order_create_time #订单生成时间 packageParams[‘time_expire‘] = order_deadline #订单失效时间 ‘‘‘获取package‘‘‘ package = weixinRequestHandler.getPackage(packageParams) ‘‘‘设置支付参数‘‘‘ signParams = {} signParams[‘appid‘] = config[‘appId‘] signParams[‘appkey‘] = config[‘paySignKey‘] #delete signParams[‘noncestr‘] = noncestr signParams[‘package‘] = package signParams[‘timestamp‘] = timestamp signParams[‘traceid‘] = ‘mytraceid_001‘ ‘‘‘生成支付签名‘‘‘ app_signature = weixinRequestHandler.createSHA1Signature(signParams) ‘‘‘增加不参与签名的额外参数‘‘‘ signParams[‘sign_method‘] = ‘sha1‘ signParams[‘app_signature‘] = app_signature ‘‘‘剔除appKey‘‘‘ del signParams[‘appkey‘] ‘‘‘获取prepayid‘‘‘ prepayid = weixinRequestHandler.gerPrepayId(access_token, signParams) if prepayid: ‘‘‘使用拿到的prepayid再次准备签名‘‘‘ pack = ‘sign=WXPay‘ prepayParams = {} prepayParams[‘appid‘] = config[‘appId‘] prepayParams[‘appkey‘] = config[‘paySignKey‘] prepayParams[‘noncestr‘] = noncestr prepayParams[‘package‘] = pack prepayParams[‘partnerid‘] = config[‘partnerId‘] prepayParams[‘prepayid‘] = prepayid prepayParams[‘timestamp‘] = timestamp ‘‘‘生成签名‘‘‘ sign = weixinRequestHandler.createSHA1Signature(prepayParams) ‘‘‘准备输出参数‘‘‘ returnParams = {} returnParams[‘status‘] = 0 returnParams[‘retmsg‘] = ‘success‘ returnParams[‘appid‘] = config[‘appId‘] returnParams[‘noncestr‘] = noncestr returnParams[‘package‘] = pack returnParams[‘prepayid‘] = prepayid returnParams[‘timestamp‘] = timestamp returnParams[‘sign‘] = sign returnParams[‘partnerId‘] = config[‘partnerId‘] returnParams[‘addtion‘] = addtion else: ‘‘‘prepayid获取失败‘‘‘ returnParams = {} returnParams[‘status‘] = -1 returnParams[‘retmsg‘] = ‘prepayid获取失败‘ else: ‘‘‘token获取失败‘‘‘ returnParams = {} returnParams[‘status‘] = -1 returnParams[‘retmsg‘] = ‘token获取失败‘ ‘‘‘生成json格式文本,然后返回给APP‘‘‘ return returnParams
バックグラウンドの非同期通知
WeChat サーバーによって送信される通知非同期通知は、安全 の理由から、必ず行わなければなりません。 do it 拡張子:
拡張コードは次のとおりです:def isTenpaySign(self, params): helper = WeixinRequestHandler() sign = helper.createMD5Signature(params) return params[‘sign‘] == sign
‘‘‘微信服务器向后台发送的异步通知‘‘‘ class WeixinAppNotifyHandler(BasicTemplateHandler): def initialize(self): self.weixinResponseHandler = WeixinResponseHandler() def post(self): ‘‘‘解析参数‘‘‘ params = self.parseQueryString() ‘‘‘验证是否是weixin服务器发回的消息‘‘‘ verifyWeixinSign = self.weixinResponseHandler.isTenpaySign(params) ‘‘‘处理订单‘‘‘ if verifyWeixinSign: ‘‘‘订单逻辑‘‘‘ order_no = str(params[‘out_trade_no‘]) order_no = order_no[0:-2] print ‘%s paied successfully‘ % order_no self.saveWeixinReceipt(params) updateOrdersPaidByWeixin(order_no) #更新订单使用状态 consumeCouponByOrderNo(order_no) #优惠券已经使用 self.write("success") else: self.write("fail") def parseQueryString(self): ‘‘‘获取url中所有的参数‘‘‘ uri = self.request.uri ‘‘‘解析出URI中的query字符串‘‘‘ parseResult = urlparse.urlparse(uri) query = parseResult.query ‘‘‘解析query字符串‘‘‘ params = urlparse.parse_qs(query) for item in params: params[item] = params[item][0].strip() return params
最後に、ユーザーが携帯電話で支払いを完了した時点では、支払いは成功したとみなされません。Weixin サーバーが通知通知によって返された成功を受信した場合にのみ、この時点で携帯電話は最終的にトランザクションを受け取ることができます。公式の WeChat 通知。
上記は WeChat 決済の開発プロセスに関する情報をまとめたものです。今後も関連情報を追加していきます。このサイトをよろしくお願いします。
以上がWeChat Payの開発プロセスの詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。