實用技術——支付_微信

  • 與微信官方簽署在線協議

  • 導入微信支付需要的SDK相關文件

  • 配置App跳轉的白名單

  • 添加URL Schemes

  • 配置代碼

    1. 在AppDelegate.m中向微信注冊第三方應用
      //向微信終端程序注冊第三方應用
      [WXApi registerApp:wexinAppId];
    2. 確保支付結果回調方法能夠接受到,在AppDelegate.m中添加一下代碼
      - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
      if([url.host isEqualToString:@"pay"]){
      return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
      }else{
      return YES;
      }
      }
      - (BOOL)application:(UIApplication *)application handleOpenURL:(nonnull NSURL *)url
      {
      if([url.host isEqualToString:@"pay"]){
      return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
      }else{
      return YES;
      }
      }
      - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
      if([url.host isEqualToString:@"pay"]){
      return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
      }else{
      return YES;
      }
      }
    • 設置支付信息,調用微信支付
      NSMutableDictionary dict = [result[@"data"] objectAtIndex:0];
      //調起微信支付
      PayReq
      req = [[PayReq alloc] init];
      //由用戶微信號和AppID組成的唯一標識
      req.openID = [dict objectForKey:@"appid"];
      //商家向財付通申請的商家id
      req.partnerId = [dict objectForKey:@"mch_id"];
      //預支付訂單
      req.prepayId = [dict objectForKey:@"prepay_id"];
      //隨機串,防重發
      req.nonceStr = [dict objectForKey:@"nonce_str"];
      //時間戳,防重發
      req.timeStamp = [[dict objectForKey:@"timeStamp"] intValue];
      //商家根據財付通文檔填寫的數據和簽名
      req.package = @"Sign=WXPay";
      //商家根據微信開放平臺文檔對數據做的簽名
      req.sign = [self getWeiXinPaySign:req];
      [WXApi sendReq:req];

    • 處理支付結果
      為了對支付結果可以進行不同的操作處理,可以創建一個單例對象來管理。
      #import <Foundation/Foundation.h>
      #import "WXApi.h"
      @protocol WXApiManagerDelegate <NSObject>
      @optional
      - (void)managerDidRecvPayForSuccessResponse:(PayResp *)response;

      - (void)managerDidRecvPayForFailResponse:(PayResp *)response;
      @end
      
      @interface WXApiManager : NSObject<WXApiDelegate>
      @property (nonatomic, assign) id<WXApiManagerDelegate> delegate;
      + (instancetype)sharedManager;
      @end
      
      #import "WXApiManager.h"
      @implementation WXApiManager
      
      #pragma mark - LifeCycle
      +(instancetype)sharedManager {
        static dispatch_once_t onceToken;
        static WXApiManager *instance;
        dispatch_once(&onceToken, ^{
        instance = [[WXApiManager alloc] init];
        });
      return instance;
      }
      
      - (void)dealloc {
        self.delegate = nil;
        [super dealloc];
      }
      
      #pragma mark - WXApiDelegate
      - (void)onResp:(BaseResp *)resp {
          if([resp isKindOfClass:[PayResp class]]){
              switch (resp.errCode) {
                  case WXSuccess:
                  {
                      if (_delegate && [_delegate respondsToSelector:@selector(managerDidRecvPayForSuccessResponse:)]) {
                      PayResp *payResp = (PayResp *)resp;
                      [_delegate managerDidRecvPayForSuccessResponse:payResp];
              }
          }
              break;
              
          default:
              if (_delegate && [_delegate respondsToSelector:@selector(managerDidRecvPayForFailResponse:)]) {
                  PayResp *payResp = (PayResp *)resp;
                  [_delegate managerDidRecvPayForFailResponse:payResp];
              }
              break;
          }
        }
      }
      @end
      
    • 簽名sign生成方法
      //獲取微信簽名
      -(NSString)getWeiXinPaySign:(PayReq)req
      {
      NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
      [signParams setObject: req.openID forKey:@"appid"];
      [signParams setObject: req.nonceStr forKey:@"noncestr"];
      [signParams setObject: req.package forKey:@"package"];
      [signParams setObject: req.partnerId forKey:@"partnerid"];
      [signParams setObject: [NSString stringWithFormat:@"%u",(unsigned int)req.timeStamp] forKey:@"timestamp"];
      [signParams setObject: req.prepayId forKey:@"prepayid"];
      //生成簽名
      NSString *sign = [self createMd5Sign:signParams];
      return sign;
      }

      //創建package簽名
      -(NSString*) createMd5Sign:(NSMutableDictionary*)dict
      {
          NSMutableString *contentString  =[NSMutableString string];
          NSArray *keys = [dict allKeys];
          //按字母順序排序
          NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
              return [obj1 compare:obj2 options:NSNumericSearch];
          }];
          //拼接字符串
          for (NSString *categoryId in sortedArray) {
              if (![[dict objectForKey:categoryId] isEqualToString:@""] &&
                  ![categoryId isEqualToString:@"sign"] &&
                  ![categoryId isEqualToString:@"key"]){
              
                  [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
                 }
              }
          //添加key字段,商戶密鑰
          [contentString appendFormat:@"key=%@", @"xxxxxxxxxxx"];
          //得到MD5 sign簽名
          NSString *md5Sign =[WXUtil md5:contentString];
          return md5Sign;
        }
      //md5 encode
      +(NSString *) md5:(NSString *)str
      {
          const char *cStr = [str UTF8String];
          unsigned char digest[CC_MD5_DIGEST_LENGTH];
          CC_MD5( cStr, (unsigned int)strlen(cStr), digest );
      
          NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
          //這里的x是小寫則產生的md5也是小寫,是大寫則產生的md5是大寫
          for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
              [output appendFormat:@"%02X", digest[i]];
      
          return output;
      }
      
  • 注意事項:

    1. 簽名Sign一定得進行MD5加密,格式嚴格按照微信官方方式加密。
      prepayId(預支付訂單)失效、過期。
      如果出現上述問題(一般是參數錯誤),就會造成調起微信支付,只出現一個確定按鈕
    • 支付結果無法獲取回調?
      確保第四步的b步驟是否實現
    • 如果APP里面使用了友盟或者ShareSDK做分享,那就不用再導入SDK了,否則會出現一些詭異的問題,
      例如無法調起手機微信客戶端、無法調起微信客戶端web頁面,調起了但是一閃而過。這都基本上都是因為分享的SDK里面已經包括了微信的SDK。所以如果出現詭異的錯誤了看看是不是兩個沖突了。
    • 如果你用了友盟社會化分享來做微信登錄的話,那么你要先用友盟注冊微信,后調用微信SDK注冊
      [UMSocialWechatHandlersetWXAppId:SHappSecret:SH url:SHAREURL];
      [WXApiregisterApp:SHARE_WX withDescription:@"demo"];
    • 微信無法調起
      未安裝微信、未將微信加入白名單
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • iOS支付 iOS支付分為兩類,第三方支付和應用內支付(內購)。 第三方支付包括:支付寶支付、微信支付、銀聯支付、...
    請輸入賬號名閱讀 6,318評論 3 22
  • 官方建議使用服務器簽名來接入微信支付,從安全上考慮,客戶端不應該知道RAS密鑰,也不需要每個客戶端都寫一遍簽名的算...
    wpf_register閱讀 501評論 0 2
  • 01 木子說來世她一定要做一棵安靜的樹,開心時開花,難過時落葉。她就可以再也不用理會塵世間的那些紛紛擾擾了。 木子...
    愛上世界的張大路閱讀 607評論 8 14
  • 清晨五點,就已醒來,昨晚打球身體疲乏,睡眠質量不高,醒來又進行了劇烈的運動,消耗了不少的體力,致使鬧鐘的呼喊我還是...
    江流_ddba閱讀 180評論 0 0