ホームページ  >  記事  >  WeChat アプレット  >  WeChat Payの開発プロセスの詳細な紹介

WeChat Payの開発プロセスの詳細な紹介

高洛峰
高洛峰オリジナル
2017-03-15 17:33:372013ブラウズ

この記事は主に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&notify_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&notify_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",

パッケージは上記のコードに示されているとおりであるため、パラメータを準備してから署名を準備する必要があります。署名プロセスは次のとおりです:

1. キーの辞書順に従ってパラメータを並べ替え、それらを結合します。これらのキーには署名

2が含まれていないことに注意してください。上記の文字列の後に key=paternerKey が続き、文字列全体が

md5 で署名され、この時点で大文字に変換されます。署名を取得します

次に、すべてのパラメータの値を URLencode し、後でそれらを結合します。sign=signValue で、パッケージ文字列を取得します。

ここでの MD5 の作成プロセスは次のとおりです:

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&notify_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

traceid=test_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 を取得します

コードは次のとおりです:

‘‘‘获取预支付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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。