iOS 위 챗 결제 절차 상세 설명 실현

배경
위 챗 페 이,알 리 페 이 가 세계 에 진출 한 이래 모 바 일 결제 가 뜨 거 워 지고 있다.가상 화 폐 는 실체 화 폐 를 대체 하 는 추세 가 있다.(이 말 은 순 전 히 허튼소리 이 니 상관 하지 마라)결 제 는 app 개발 에서 기본 적 인 기능 이 므 로 파악 할 필요 가 있다.난이도 에서 볼 때 위 챗 결제 든 알 리 페 이 결제 든 모두 매우 간단 하 다.제3자 의 결제 문서 가 매우 상세 하고 그들 내부 의 안전성 도 매우 높 기 때문이다.이러한 지불 전략 을 사용 하 는 우 리 는 절 차 를 파악 하고 정상 적 인 지불 기능 을 실현 하면 된다.왜 이 박문 을 써 야 합 니까?원인 은 두 가지 가 있 습 니 다.첫째,위 챗 결제 절차 에 구덩이 가 있 고,둘째,나중에 잊 어 버 리 면 꺼 내 볼 수 있다.
배치 하 다.
1.위 챗 결 제 는 두 개의 계 정 이 필요 합 니 다.재 페 이와 위 챗 개발 자 는 등록 이 완 료 된 후에 결제 기능 을 개통 해 야 합 니 다.이런 절 차 는 더 말 할 필요 가 없습니다.모든 신청 이 성공 한 후에 우 리 는 우리 의 지불 기능 에 필요 한 키 를 꺼 내야 한다.
appID,app 키(위 챗 에서 보 낸 메 일 에 키 를 만 드 는 방법 이 있 는 링크),상점 번호.
2.Xcode 에 app ID 를 설정 하려 면 화이트 리스트 를 설정 하고 url 에 app ID 를 설정 해 야 합 니 다.잘 모 르 는 동 화 는 바 이 두 를 사용 할 수 있 습 니 다.
지불 하 다.
여기 서부 터 이번 주제 에 들 어가 지불 을 시작 합 니 다.지불 과정 은 네 단계 로 나 뉜 다.
첫걸음  주문 번호 가 져 오기
주문 번 호 를 가 져 오 는 경 로 는 클 라 이언 트 가 스스로 생 성 할 수도 있 고 서버 에 가서 생 성 할 수도 있 지만 보통 서버 에서 생 성 됩 니 다.주문 번 호 를 받 았 다 고 가정 하여 orderno。
두 번 째 단계  통일 주문
이 과정 은 매우 중요 한 단계 이자 구덩이 가 상주 하 는 단계 이다.아래 주문 을 통일 하 는 방법 은 서버 에서 조작 하 는 것 이 고,어떤 것 은 클 라 이언 트 에서 하 는 것 이 며,어느 곳 에서 주문 을 하 든 이해 할 필요 가 있다.다음은 통일 주문 에 필요 한 매개 변수 목록 을 살 펴 보 겠 습 니 다.

/*  ID              app ID*/
@property (nonatomic, copy) NSString *appid;
/*              */
@property (nonatomic, copy) NSString *mch_id;
/*           ,   32 */
@property (nonatomic, copy) NSString *nonce_str;
/*  */
@property (nonatomic, copy) NSString *sign;
/*          -    。*/
@property (nonatomic, copy) NSString *body;
/*     */
@property (nonatomic, copy) NSString *out_trade_no;
/*         ,    */
@property (nonatomic, copy) NSString *total_fee;
/*  IP*/
@property (nonatomic, copy) NSString *spbill_create_ip;
/*    */
@property (nonatomic, copy) NSString *notify_url;
/*    */
@property (nonatomic, copy) NSString *trade_type;
그 중에서 sign 은 다른 모든 매개 변 수 를 key 1=value 1&key 2=value 2...방식 으로 연결 한 다음 암호 화 합 니 다.매개 변수 조합 은 알파벳 에 따라 정렬 됩 니 다.예 를 들 어 매개 변 수 는 appid=@"id",mch 입 니 다.id=@"mch"에서 얻 은 문자열 은 다음 과 같 습 니 다:@"appid=id&mch"id=mch"다음 코드 와 같이 이 문자열 을 암호 화 합 니 다.

- (instancetype)initWithDicInfo:(NSDictionary *)infoDic{

  if (self = [super init]) {

    self.appid = WECHAT_SHARE_APPID;

    self.mch_id = WECHAT_MCH_ID;

    self.nonce_str = [AppMethod getRandomString];

    self.body = @"test";

    self.out_trade_no = [infoDic formateObjectForKey:@"order_no"];

    self.total_fee = [NSString stringWithFormat:@"%@", [infoDic formateObjectForKey:@"amount"]];

    self.spbill_create_ip = [AppMethod deviceIPAdress];

    self.notify_url = [NSString stringWithFormat:@"%@%@", BASE_URL, WECHAT_NOTI_URL];

    self.trade_type = @"APP";

    self.payDic = [NSMutableDictionary dictionary];

    [self.payDic setValue:self.appid forKey:@"appid"];

    [self.payDic setValue:self.mch_id forKey:@"mch_id"];

    [self.payDic setValue:self.nonce_str forKey:@"nonce_str"];

    [self.payDic setValue:self.body forKey:@"body"];

    [self.payDic setValue:self.out_trade_no forKey:@"out_trade_no"];

    [self.payDic setValue:self.total_fee forKey:@"total_fee"];

    [self.payDic setValue:self.spbill_create_ip forKey:@"spbill_create_ip"];

    [self.payDic setValue:self.notify_url forKey:@"notify_url"];

    [self.payDic setValue:self.trade_type forKey:@"trade_type"];

    self.sign = [self partnerSignOrder:self.payDic];

    [self.payDic setValue:self.sign forKey:@"sign"];

  }

  return self;

}
- (NSString *)partnerSignOrder:(NSDictionary*)paramDic{
  NSArray *keyArray = [paramDic allKeys];
  NSMutableArray *sortedKeyArray = [NSMutableArray arrayWithArray:keyArray];
  [sortedKeyArray sortUsingComparator:^NSComparisonResult(NSString* key1, NSString* key2) {
    return [key1 compare:key2];
  }];
  NSMutableString *paramString = [NSMutableString stringWithString:@""];
  //     A=B&X=Y
  for (NSString *key in sortedKeyArray){
    if ([paramDic[key] length] != 0){
      [paramString appendFormat:@"&%@=%@", key, paramDic[key]];
    }
  }
  if ([paramString length] > 1){
    [paramString deleteCharactersInRange:NSMakeRange(0, 1)];  // remove first '&'
  }
  [paramString appendFormat:@"&key=%@", WeChatPARTNER_ID];//app  
  return [[AppMethod signString:paramString] uppercaseString];
}

AppMethod.m
+ (NSString *)signString:(NSString*)origString{
  const char *original_str = [origString UTF8String];
  unsigned char result[32];
  CC_MD5(original_str, (CC_LONG)strlen(original_str), result);//  md5
  NSMutableString *hash = [NSMutableString string];
  for (int i = 0; i < 16; i++){
    [hash appendFormat:@"%02X", result[i]];
  }
  return hash;
}

이렇게 해서 아래 의 매개 변 수 를 통일 시 킬 준비 가 되 었 습 니 다.다음은 위 챗 의 다음 인 터 페 이 스 를 요청 합 니 다https://api.mch.weixin.qq.com/pay/unifiedorder지금 은 구덩이 가 또 왔 습 니 다.위 챗 의 아래 설명 에 따 르 면 위 챗 서버 에 전 달 된 인 자 는 XML 형식의 데이터 여야 합 니 다.만약 당신 이 이런 유형의 자 연 스 럽 게 처리 하기 쉽다 고 전해 준 적 이 있다 면,나 는 대부분의 어린이 신발 이 이런 유형의 데 이 터 를 전해 준 적 이 없다 고 추측 합 니 다.다행히 AF 에서 방법 을 제공 할 수 있 습 니 다.그렇지 않 으 면 울 기 를 기다 리 세 요.코드 계속 보기

+ (void)postWechatPayWithUrl:(NSString *)url
           params:(id)params
         andSuccess:(requestSuccessResult)successBlock
         andFailure:(requestFailureResult)failureBlock{
  NSString *string = [params XMLString];//      XMLDictionary  ,      
  AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
  //      XML       XML,      XML  ,    AF      
  session.responseSerializer = [[AFHTTPResponseSerializer alloc] init];
  [session.requestSerializer setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
  [session.requestSerializer setValue:url forHTTPHeaderField:@"SOAPAction"];
  [session.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error) {
    return string;
  }];
  
  [session POST:url parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
    
  } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
    successBlock(responseObject);
  } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    HPError *hpError = [HPError errorWithCode:error.code desc:error.description];
    failureBlock(hpError);
  }];
}

위 와 같은 절차 에 따라 여기까지 정상적으로 주문 할 수 있 습 니 다.만약 위 챗 서버 가 당신 에 게 돌아 온 데이터 에"result"가 있다 면.code" = SUCCESS; "return_code"=SUCCESS,주문 성공 을 설명 합 니 다.이 절차 도 여기 서 끝 납 니 다.
세 번 째 단계  위 챗 클 라 이언 트 를 조정 하고 지불 을 완료 합 니 다.
만약 에 두 번 째 단계 가 정상적으로 주문 을 한다 면 위 챗 은 당신 에 게 선불 ID 를 되 돌려 줄 것 입 니 다.이 ID 는 마지막 결제 에서 매우 중요 합 니 다.아래 의 코드 는 비교적 통일 되 고 모두 가 이렇게 씁 니 다.

HPWechatProduct *product = [[HPWechatProduct alloc] initWithDic:result];
PayReq *req       = [[PayReq alloc] init];
req.partnerId      = product.partnerid;
req.prepayId       = product.prepayid;
req.nonceStr       = product.noncestr;
req.timeStamp      = [product.timestamp intValue];
req.package       = product.package;
req.sign         = product.sign;
BOOL flag = [WXApi sendReq:req];

HPWechatProduct.m
- (instancetype)initWithDic:(NSDictionary *)dic{
  if (self = [super init]) {
    self.appid = WECHAT_SHARE_APPID;
    self.partnerid = mah_id;
    self.prepayid = [dic formateObjectForKey:@"prepay_id"];
    self.package = @"Sign=WXPay";
    self.noncestr = [AppMethod getRandomString];
    self.timestamp = [self getTime];
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    [dic setValue:self.appid forKey:@"appid"];
    [dic setValue:self.partnerid forKey:@"partnerid"];
    [dic setValue:self.prepayid forKey:@"prepayid"];
    [dic setValue:self.package forKey:@"package"];
    [dic setValue:self.noncestr forKey:@"noncestr"];
    [dic setValue:self.timestamp forKey:@"timestamp"];
    self.sign = [self partnerSignOrder:dic];
  }
  return self;
}
- (NSString *)partnerSignOrder:(NSDictionary*)paramDic{
  NSArray *keyArray = [paramDic allKeys];
  NSMutableArray *sortedKeyArray = [NSMutableArray arrayWithArray:keyArray];
  [sortedKeyArray sortUsingComparator:^NSComparisonResult(NSString* key1, NSString* key2) {
    return [key1 compare:key2];
  }];
  NSMutableString *paramString = [NSMutableString stringWithString:@""];
  //     A=B&X=Y
  for (NSString *key in sortedKeyArray){
    if ([paramDic[key] length] != 0){
      [paramString appendFormat:@"&%@=%@", key, paramDic[key]];
    }
  }
  if ([paramString length] > 1){
    [paramString deleteCharactersInRange:NSMakeRange(0, 1)];  // remove first '&'
  }
  [paramString appendFormat:@"&key=%@", WeChatPARTNER_ID];
  return [[AppMethod signString:paramString] uppercaseString];
}

- (NSString *)getTime{
  NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
  return [NSString stringWithFormat:@"%ld", (long)interval];
}


AppMethod.m
+ (NSString *)getRandomString
{
  NSString *str = [NSString stringWithFormat:@"%s",genRandomString(32)];
  return str;
}

만약 이 단계 에 이 르 렀 고 위 챗 에 달 려 가 지불 을 완성 했다 면 위 챗 은 지불 이 성공 했다 는 것 을 알려 줄 것 이다.하지만 정말 성 공 했 군요.네 번 째 단 계 를 계속 보 세 요.
네 번 째 단계  서버 에 가서 지불 성공 여 부 를 조회 하 세 요.
설령 위 챗 이 당신 에 게 지불 이 성공 했다 고 알려 준다 하 더 라 도 당신 은 믿 을 수 없습니다.돈 이 진정 으로 당신들 의 계좌 에 들 어가 야만 지불 이 성공 한 것 입 니 다.언제든지 위 챗 의 리 셋 값 으로 결제 성공 여 부 를 판단 할 수 없습니다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기