위 챗 결제 의 실현 방법 분석(.NET 버 전)

얼마 전에 웹 페이지 판 위 챗 결 제 를 했 는데 많은 문제 가 발생 했 지만 결국은 해결 되 었 습 니 다.지금 은 여기 서 개발 절차 와 설명 을 기록 하여 다른 사람 에 게 참고 하 겠 습 니 다.
준비 작업
우선 위 챗 페 이 기능 을 먼저 개통 해 야 하 는데,앞서 위 챗 페 이 를 개통 하려 면 3 만 원 의 보증금 이 필요 한데 이 제 는 필요 하지 않 아 이 기능 을 하 게 됐다.
위 챗 결제 개발 을 하려 면 공중 번호 백 스테이지 와 위 챗 사업 자 백 스테이지 에서 관련 설 치 를 해 야 한다.
1.개발 디 렉 터 리 설정
위 챗 결 제 는 공중 번호 백 스테이지(위 챗 결제=개발 설정)에서 결제 권한 수여 디 렉 터 리 를 설정 해 야 합 니 다.여기 서 권한 수여 디 렉 터 리 는 온라인 주소,즉 인터넷 을 통 해 접근 할 수 있 는 주소,위 챗 결제 시스템 은 인터넷 을 통 해 당신 의 주 소 를 방문 할 수 있어 야 합 니 다.
위 챗 권한 수여 디 렉 터 리 는 2 급 또는 3 급 디 렉 터 리 까지 정확 해 야 합 니 다.사례:지불 을 시작 하 는 링크 는?http://www.hxfspace.net/weixin/WeXinPay/WeXinPayChoose  그럼 설 정 된 디 렉 터 리 는http://www.hxfspace.net/weixin/WeXinPay/ 그 속http://www. hxfspace.net 은 도 메 인 이름 weixin 입 니 다.가상 디 렉 터 리 WeXinPay,즉 Controller 와 관련 된 지불 요청 은 모두 WeXinPay 의 action 에 있 습 니 다.                 
 2.OAuth 2.0 웹 페이지 권한 부여 도 메 인 이름 설정
위 챗 결제 시 결제 요청 을 되 돌려 서 인증 코드(code)를 가 져 오기 때문에 인증 도 메 인 이름 을 설정 해 야 합 니 다.물론 이 도 메 인 이름 은 지불 권한 수여 디 렉 터 리 의 도 메 인 이름과 같 아야 합 니 다.이거 설치 하 는 거 잊 지 마 세 요
3.관련 매개 변수 준비
위 챗 결 제 를 호출 하려 면 스 크 립 트 를 통 해 위 챗 결제 시스템 에 결제 요청 을 해 야 합 니 다.매개 변 수 는 위 챗 홈 페이지 결제 플랫폼 을 참조 하 십시오.https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 
그 중에서 package 와 paySign 의 생 성 은 개발 자 키 AppSecret(응용 키),위 챗 상점 번호,위 챗 결제 키 가 필요 합 니 다.이러한 매개 변수의 획득 과 설정 은 이 글 을 볼 수 있 습 니 다https://www.jb51.net/softjc/346871.html
개발 절차
잔말 말고 정리 후의 절 차 를 직접 말 하 라.
1.위 챗 권한 수여 리 셋 을 통 해 권한 수여 코드 획득
2.권한 수여 코드 를 통 해 웹 페이지 권한 수여 accesstoken 과 openid
3.통 일 된 하단 인 터 페 이 스 를 호출 하여 선불 prepayId 획득
4.jsapi 위 챗 결제 요청 파 라 메 터 를 구성 하여 결 제 를 시작 합 니 다.
5.위 챗 결제 리 턴 을 받 아 후속 작업 을 진행한다.
3.구체 적 인 개발(상 코드)
위 챗 결 제 는 온라인 환경 에서 만 진행 할 수 있 고 튜 닝 이 불편 하 며 개발 을 시작 할 때 모든 관건 적 인 위치 에 로 그 를 기록 하 는 것 이 좋 습 니 다.
1.위 챗 권한 수여 리 셋 을 통 해 권한 수여 코드 획득
먼저 결제 주소 와 관련 매개 변 수 를 위 챗 결제 인터페이스 에 전달 하고 위 챗 결제 가 인증 을 받 은 후에 결제 주 소 를 다시 요청 하고 권한 수여 code 를 가 져 옵 니 다.
여기
  

 //        ,    code,        ,        code,     
      if (string.IsNullOrEmpty(Request.QueryString["code"]))
      {
        string redirectUrl = _weChatPaySerivce.GetAuthorizeUrl(account.AppId, account.RedquestUrl,
          "STATE" + "#wechat_redirect", "snsapi_base");
        return Redirect(redirectUrl);
      }
위 챗 웹 페이지 연결 권한 부여 Url 방법

public string GetAuthorizeUrl(string appId, string redirectUrl, string state, string scope)
    {
      string url = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state={3}",
          appId, HttpUtility.UrlEncode(redirectUrl), scope, state);
      /*        ,         ,       ,    redirectUrl  。
       *         ,       redirect_uri/?code=CODE&state=STATE。   code    access_token(      access_token   )
       *        ,         code  ,    state  redirect_uri?state=STATE
       */
      AppLog.Write("     url:", AppLog.LogMessageType.Debug); 
      return url;
    }
2.권한 수여 코드 를 통 해 웹 페이지 권한 수여 accesstoken 과 openid
첫 번 째 단계 에서 권한 수여 코드 를 가 져 온 후,웹 페이지 권한 수여 요청 url 을 조합 하여 access 를 가 져 옵 니 다.token 과 openid

 public Tuple<string, string> GetOpenidAndAccessTokenFromCode(string appId, string code, string appSecret)
    {
      Tuple<string, string> tuple = null;
      try
      {
        string url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", appId, appSecret, code);
        string result = WeChatPayHelper.Get(url);
        AppLog.Write("    -  openid access_token   Url:" + url + "result:" + result, AppLog.LogMessageType.Debug);
        if (!string.IsNullOrEmpty(result))
        {
          var jd=Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(result);
          tuple = new Tuple<string, string>(jd["openid"],jd["access_token"]);
          AppLog.Write("    -  openid access_token  ", AppLog.LogMessageType.Debug);
        }
      }
      catch (Exception ex)
      {
        AppLog.Write("    :  openid access_tokenu  ", AppLog.LogMessageType.Debug,ex);
      }
      return tuple;
    }
3.통 일 된 하단 인 터 페 이 스 를 호출 하여 선불 prepayId 획득
 여기 RequestHandler 는 인터넷 상에 서 다른 사람 이 봉 인 된 dll 로 서명 생 성 및 검증 요청 을 봉 인 했 습 니 다.dll 은 이 홈 페이지 에서 다운로드 할 수 있 습 니 다.http://weixin.senparc.com/

//        
      RequestHandler packageReqHandler = new RequestHandler(null);
      //   
      packageReqHandler.Init();
      //   
      string timeStamp = TenPayUtil.GetTimestamp();
      //     
      string nonceStr = TenPayUtil.GetNoncestr();
      //  package       prepayId   Id
      packageReqHandler.SetParameter("appid", account.AppId);     //    ID
      packageReqHandler.SetParameter("mch_id", account.PartnertId);     //   
      packageReqHandler.SetParameter("nonce_str", nonceStr);          //     
      packageReqHandler.SetParameter("body", account.Body);
      packageReqHandler.SetParameter("out_trade_no", account.OrderSerialId);    //     
      packageReqHandler.SetParameter("total_fee", account.TotalAmount);          //    ,     (money * 100).ToString()
      packageReqHandler.SetParameter("spbill_create_ip", account.RequestIp);  //     ip,       IP
      packageReqHandler.SetParameter("notify_url", account.NotifyUrl);      //        URL
      packageReqHandler.SetParameter("trade_type", "JSAPI");            //    
      packageReqHandler.SetParameter("openid", account.OpenId);            //   openId
      string sign = packageReqHandler.CreateMd5Sign("key", account.PaySignKey);
      packageReqHandler.SetParameter("sign", sign);            //  
      string prepayId = string.Empty;
      try
      {
        string data = packageReqHandler.ParseXML();
        var result = TenPayV3.Unifiedorder(data);
        MailHelp.SendMail("        ,    :--"+result+"    :"+data);
        var res = XDocument.Parse(result);
        prepayId = res.Element("xml").Element("prepay_id").Value;
        AppLog.Write("             prepayId  ", AppLog.LogMessageType.Debug);
      }
      catch (Exception ex)
      {
        AppLog.Write("   openid access_tokenu  ", AppLog.LogMessageType.Debug, ex);
        MailHelp.SendMail("             prepayid  :", ex);
        return null;
      }
4.jsapi 위 챗 결제 요청 파 라 메 터 를 구성 하여 결 제 를 시작 합 니 다.
저 는 먼저 위 챗 결제 에 필요 한 인 자 를 조립 한 다음 에 js 스 크 립 트 를 만 듭 니 다.    

//  JsAPI    
      RequestHandler paySignReqHandler = new RequestHandler(null);
      paySignReqHandler.SetParameter("appId", account.AppId);
      paySignReqHandler.SetParameter("timeStamp", timeStamp);
      paySignReqHandler.SetParameter("nonceStr", nonceStr);
      paySignReqHandler.SetParameter("package", string.Format("prepay_id={0}", prepayId));
      paySignReqHandler.SetParameter("signType", "MD5");
      string paySign = paySignReqHandler.CreateMd5Sign("key", account.PaySignKey);
      WeChatJsPayRequestModel resultModel = new WeChatJsPayRequestModel
      {
        AppId = account.AppId,
        NonceStr = nonceStr,
        TimeStamp = timeStamp,
        Package = string.Format("prepay_id={0}", prepayId),
        PaySign = paySign,
        SignType = "MD5"
      };
호출 스 크 립 트 만 들 기

private string CreateWeixinJs(WeChatJsPayRequestModel model)
    {
      string js = @"<script type='text/javascript'>
                callpay();
                function jsApiCall(){
                 WeixinJSBridge.invoke(
                  'getBrandWCPayRequest', {
                    requestParam
                  },
                  function (res) {
                    if(res.err_msg == 'get_brand_wcpay_request:ok' ){
                        window.location.href = 'successUrl';
                    }else{
                        window.location.href = 'failUrl';
                    }
                  }
                 ); 
                }
               function callpay()
                {
                  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{
                    jsApiCall();
                  }
                }
            </script>";
      string requestParam = string.Format(@"'appId': '{0}','timeStamp': '{1}','nonceStr': '{2}','package': '{3}','signType': '{4}','paySign': '{5}'",
        model.AppId, model.TimeStamp, model.NonceStr, model.Package, model.SignType, model.PaySign);
      js = js.Replace("requestParam", requestParam)
        .Replace("successUrl", model.JumpUrl + "&result=1")
        .Replace("failUrl", model.JumpUrl + "&result=0");
      AppLog.Write("         ", AppLog.LogMessageType.Debug);
      return js;
    }
 5.위 챗 결제 리 턴 을 받 아 후속 작업 을 진행한다.
리 셋 할 때 먼저 서명 이 정확 한 지 검증 하고 안전성 을 확보 해 야 한다.서명 검증 을 통과 한 후에 후속 작업,주문 상태,알림 등 을 해 야 한다. 

ResponseHandler resHandler = new ResponseHandler(System.Web.HttpContext.Current);
      bool isSuccess = _weChatPaySerivce.ProcessNotify(resHandler);
      if (isSuccess)
      {
        string result = @"<xml>
                  <return_code><![CDATA[SUCCESS]]></return_code>
                  <return_msg><![CDATA[    ]]></return_msg>
                 </xml>";
        HttpContext.Response.Write(result);
        HttpContext.Response.End();
      }
      return new EmptyResult();
여기 서 주의해 야 할 것 은 바로 위 챗 결제 가 리 셋 될 때 위 챗 이 8 번 알려 주 는 것 입 니 다.이 숫자 인 것 같 습 니 다.그래서 처음 통 지 를 받 은 후에 요청 을 받 은 상 태 를 xml 형식 으로 위 챗 결제 인터페이스 에 응답 해 야 합 니 다.물론 당신 이 이 조작 을 하지 않 아 도 됩 니 다.다시 조정 할 때 매번 이 주문 이 이미 조정 에 성 공 했 는 지 판단 하고,조정 에 성공 하면 처리 하지 않 으 면 됩 니 다.
 원본 링크:http://www.cnblogs.com/minesnil-forfaith/p/4976006.html
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기